Modules and packages, 5 of 6
Using packages
Depend on a package from a folder or from the registry, pin its version in fb.lock, and update it.
What you’ll build
A program, planner, that uses a library package, geometry, for its shapes and units. First
the library is a folder beside the program’s code, then it comes from the registry with
fb add, and fb.lock records the exact version the program builds with.
A package from a folder
A dependency goes in [dependencies], under the name code imports it by. path names its
folder, from the folder project.toml is in. Here geometry is a library in a folder inside the
program’s, with a shapes/ folder of its own.
[project]
name = "planner"
version = "0.1.0"
[dependencies]
geometry = { path = "geometry" }[project]
name = "geometry"
version = "1.2.0"
type = "library"Import std.core
Public Const CM_PER_INCH = 2.54
Public Function ToInches(cm: Float): Float => cm / CM_PER_INCHImport std.core
Public Struct Rect
Public Field Width: Float
Public Field Height: Float
Public Method Area(): Float => Width * Height
End StructImport std.core
Import geometry
Import geometry.shapes
Local desk = Rect(120, 60)
Print("{desk.Area()} square cm")
Print("{ToInches(desk.Width)} inches wide")7200 square cm 47.244095 inches wide
Import geometry brings in the modules directly in the package’s folder, here units.fb, and
Import geometry.shapes the ones in its shapes/ folder. Only a package that lists geometry
in its [dependencies] can import it. The program’s own files can’t import the library’s by
path either: a folder with a project.toml of its own is another package, reached only by its
name.
A dependency is a library. Listing a package that has a main file, an executable, is an error that says so.
A package from the registry
A package published to the registry is added by its name, here in a new package:
fb add geometry Adding geometry v1.2.0
Added geometry v1.2.0 to dependenciesfb add finds the newest version, adds it to [dependencies] as a version range, and leaves the
rest of project.toml as it was:
[dependencies]
geometry = "1.2.0""1.2.0" is a range: 1.2.0 or any later version below 2.0.0, which semantic versioning says is
compatible. Below 1.0, the second number counts as the major one, so "0.4" means 0.4.0 up to
0.5.0, and below 0.1, the third does, so "0.0.3" means exactly 0.0.3. A few other forms:
| Range | Means |
|---|---|
"1.2" | 1.2.0 up to, but not including, 2.0.0 |
"~1.2.3" | 1.2.3 up to 1.3.0 |
"=1.2.3" | exactly 1.2.3 |
">=1.2, <1.5" | 1.2.0 up to 1.5.0 |
fb add geometry@1.1 adds a range of your own, and the code doesn’t change: Import geometry
works the same whichever way the package arrives.
fb.lock
A program is built with one exact version of each registry package it uses, its dependencies’
own dependencies included. For each, fb picks the newest version that every range on it allows,
skipping versions that were yanked, and writes the versions to fb.lock beside project.toml,
with each archive’s SHA-256. Packages from folders aren’t in it. An entry looks like this, beside
the index it came from, which is left out here:
[[package]]
name = "geometry"
version = "1.2.0"
checksum = "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
dependencies = []Commit fb.lock with the program, so every machine builds the same versions.
A build reads fb.lock and changes it only when project.toml asks for what it doesn’t have: a
new dependency, a range its locked version is outside, or another registry. Then fb picks again,
keeping every locked version it can. A download whose hash isn’t the one
fb.lock recorded is an error, and nothing of it is used.
When two packages ask for ranges no one version meets, fb says which ranges conflict, and who asks for each.
Updating
Here geometry 1.1.0 was the newest when the program was locked, and 1.2.0 is out now:
fb update geometry
fb updateUpdating geometry v1.1.0 -> v1.2.0
fb update picks the newest versions that the ranges allow, for every package, and
fb update geometry changes only geometry and what it has to. Downloaded packages are kept in a
cache in your home folder, so a build that has everything it needs works offline.
What you learned
[dependencies]lists a program’s packages, by a folder’spathor by a version range.fb add nameadds the newest version from the registry, as a range.Import nameimports a dependency’s modules by its name, wherever it came from.- fb.lock pins the exact version of every registry package, and belongs in version control.
fb updatemoves to newer versions within the ranges.
The rules are in the language reference.
Report an issue with this page or with FutureBlitz on GitHub.