Dependency
Almost every program in this course has started with import Io::PrintLine;, and that import only works because the manifest lists Io as a dependency. This lesson looks at that list properly. There are two kinds of dependency — packages from the registry, and packages in a folder on your own disk — and this program uses both.
The [Dependencies] section
The lesson's Rux.toml ends with three lines:
[Dependencies]
Io = { Namespace = "Rux", Version = "*" }
Math = { Namespace = "Rux", Version = "*" }
Units = { Path = "Units" }
The key on the left of each line is the import name: the first segment of every import that reaches into that package. Io = … is what makes import Io::PrintLine; mean something. The inline table on the right says where the package comes from, and its shape decides which kind of dependency it is.
Registry dependencies
A registry dependency names a namespace and a version requirement. Io and Math are standard packages, published under the Rux namespace. They ship with the compiler, so they are already in the package cache on your machine; for any other registry package, rux install downloads a matching version into that cache once, and builds read it from there without going online again.
The requirement says which versions are acceptable:
| Requirement | Accepts |
|---|---|
* | any version — whichever is installed |
^0.1.0 | 0.1.x, but not 0.2.0 |
>=1.2.0, <2.0.0 | a range spelt out |
rux list shows what each line resolved to — here Resolved Rux/Io @ * to 0.1.0, the same for Math, and Path Units at 'Units'.
In Rux 0.4.0,
rux add Rux/Io does not work for the standard packages. Write their line into Rux.toml yourself, as every lesson in this course does: Io = { Namespace = "Rux", Version = "*" }.Path dependencies
A path dependency names a folder holding a Rux.toml, relative to this manifest. Here it is Units/, right beside Src/:
pub const KilometresPerMile: float64 = 1.609344;
pub func ToMiles(kilometres: float64) -> float64 {
return kilometres / KilometresPerMile;
}
Its source is compiled with the program, so an edit to Units/Src/Units.rux shows up on the next build, and nothing needs installing. The price is that a package with a path dependency cannot be published: the path means nothing on anyone else's machine.
Both kinds look the same in the code
Once declared, nothing in the source says where a package came from:
import Io::PrintLine;
import Math::{ Hypot, Round };
import Units::ToMiles;
flowchart LR
reg[("registry")] -- "rux install<br/>(once)" --> cache[("package cache<br/>Io, Math")]
cache -- "Namespace + Version" --> prog["Dependency<br/>Src/Main.rux"]
folder["Units/<br/>beside Src/"] -- "Path" --> prog
prog --> exe["Dependency.exe"]Hypot(3.0, 4.0) from Math is the length of the long side of a right triangle — five kilometres for three east and four north — and ToMiles from Units converts it. Round(… * 100.0) / 100.0 keeps two decimal places.
The program
The whole lesson is one package in the Examples repository. Its comments explain every step.
// A package names what it needs in the `[Dependencies]` section of its `Rux.toml`. Each line's key
// is the import name, the first segment of every `import` that reaches into that package. This
// program uses both kinds of dependency there are:
//
// Io = { Namespace = "Rux", Version = "*" }
// Math = { Namespace = "Rux", Version = "*" }
// Units = { Path = "Units" }
//
// A registry dependency names a namespace and a version requirement. `rux install` downloads a
// matching version into the package cache on this machine, and builds then read it from there,
// without going online again. `*` accepts any version; `^0.1.0` would accept 0.1.x but not 0.2.0,
// and `>=1.2.0, <2.0.0` spells a range out.
//
// A path dependency names a directory holding a `Rux.toml`, relative to this manifest. The source
// there is compiled with this program, edits to it are seen on the next build, and nothing needs
// installing. A package with a path dependency cannot be published, because the path means
// nothing on anyone else's machine.
//
// Once declared, the two kinds look the same in the code.
import Io::PrintLine;
import Math::{ Hypot, Round };
import Units::ToMiles;
func Main() -> int {
// Three kilometres east, then four north: how far from the start, as the crow flies?
let kilometres = Hypot(3.0, 4.0);
let miles = Round(ToMiles(kilometres) * 100.0) / 100.0;
PrintLine("straight line {} km", kilometres);
PrintLine("which is {} miles", miles);
return 0;
}
Run it
cd Examples/Packages/Dependency
rux run
straight line 5.0 km
which is 3.11 miles
Common mistakes
Delete the
Math line and the build stops before any code is checked: error: package 'Math' is not listed in [Dependencies], with the note "the import requires a package dependency with the same import name". Every import name needs its line.With
Path = "Unit", rux reports error: could not open the manifest for the missing folder, then error: cannot load dependency package 'Units'. The path is relative to the manifest that declares it, not to the folder you run rux from.Math = { Namespace = "Rux" } fails with error: registry dependency 'Math' must declare 'Version'. Write Version = "*" if any version will do.A dependency is one kind or the other.
Units = { Path = "Units", Version = "*" } fails with error: path dependency 'Units' cannot also declare 'Namespace' or 'Version'.With
Version = "^9.0.0" for Math, the build fails with error: no installed version of 'Rux/Math' satisfies '^9.0.0', and a note lists the versions that are installed. Loosen the requirement, or install a version that matches.Try it yourself
- Change the requirement for
Mathto^0.1.0and runrux list. Does anything change in the build? - Add a
ToKilometresfunction toUnitsand use it to convert the roundedmilesback. Why is the answer not exactly 5.0? - The import name does not have to match the package's own name. Rename the line to
Distance = { Path = "Units", Package = "Units" }and change the import to match.
Learn more
- Dependencies — requirement syntax, the package cache and target-specific dependencies
rux installandrux listin the CLI reference- Math — the standard package this program borrows
HypotandRoundfrom - Workspace — several packages, with path dependencies between them, kept in one tree