Workspace
A project often grows into several packages that you work on together: a program, plus the libraries it is built from. You could keep them in unrelated folders and connect them with path dependencies, as Dependency did. A workspace goes one step further: it puts them in one tree under a single root manifest, so one command can check, build or lint all of them at once.
A root manifest with [Workspace]
The Rux.toml at the root of this lesson has no [Package] section. It has [Workspace] instead:
[Manifest]
Version = 1
MinRux = "0.4.0"
[Workspace]
Packages = [
"App",
"Temperature",
]
Packages lists every member by its folder. The list is explicit: there are no wildcards, and every member must sit inside the root, so adding a package to the project means adding a line here. A manifest has either [Package] or [Workspace], never both — a workspace is not a package. It has no source of its own, declares no dependencies and has nothing to run.
Workspace/
├── Rux.toml [Workspace], listing the two members
├── App/
│ ├── Rux.toml Type = "Executable"
│ └── Src/Main.rux
└── Temperature/
├── Rux.toml Type = "SourceLibrary"
└── Src/Temperature.rux
Members are ordinary packages
Each member has its own manifest and is written exactly as a lone package would be. Being listed changes nothing about it — and in particular, membership does not create dependencies. The program still names the library in its own App/Rux.toml:
Temperature = { Path = "../Temperature" }
Then App/Src/Main.rux imports it like any other package:
import Io::PrintLine;
import Temperature::ToFahrenheit;
So a workspace answers "which packages make up this project?", while each member's [Dependencies] still answers "which packages does this one use?":
flowchart LR
root(["Workspace/Rux.toml<br/>[Workspace]"]) -. "member" .-> app["App<br/>Executable"]
root -. "member" .-> temp["Temperature<br/>SourceLibrary"]
app -- "Path = ../Temperature" --> temp
app --> exe["App.exe"]Commands at the root and in a member
At the root, rux works on every member in turn:
| Where you are | Command | What happens |
|---|---|---|
| root | rux check | checks both members: Checked 2 packages |
| root | rux build | builds App; the source library has nothing to build |
| root | rux lint | lints every member |
| root | rux run | refused — the workspace has nothing to run |
| root | rux --manifest App/Rux.toml run | runs the program without changing folder |
App/ | rux run | builds and runs the program, as for any package |
--manifest is a global option: it tells any rux command which Rux.toml to use instead of the one in the current folder.
The program
The whole lesson is one package in the Examples repository. Its comments explain every step.
// The library member of the workspace. It is an ordinary package with its own manifest; being
// listed in the workspace changes nothing about how it is written.
pub func ToFahrenheit(celsius: float64) -> float64 {
return celsius * 9.0 / 5.0 + 32.0;
}
Run it
cd Examples/Packages/Workspace/App
rux run
-40.0 C = -40.0 F
0.0 C = 32.0 F
21.5 C = 70.7 F
100.0 C = 212.0 F
From the root, rux check, rux build and rux lint work on every member. rux run there stops, because the workspace "has nothing to run", and suggests rux --manifest App/Rux.toml run, which runs the program without changing directory.
Common mistakes
rux run at the root stops with error: manifest '…\Workspace\Rux.toml' is a workspace and has nothing to run, and the help line suggests rux --manifest App/Rux.toml run. Run that, or change into App/ first.Remove the
Temperature line from App/Rux.toml and the import fails, even though both packages are members: error: package 'Temperature' is not listed in [Dependencies]. Each member declares what it uses.Packages = ["*"] is not a pattern. rux takes it as a folder name and reports error: workspace member '*' has no Rux.toml. List every member by name."../Dependency" in the list fails with error: '[Workspace].Packages item' cannot contain a '..' component. A workspace owns its members, so they live inside it. A package elsewhere can still be a path dependency.Try it yourself
- From the workspace root, run
rux check, thenrux --manifest App/Rux.toml run. - Delete
"Temperature",from the root manifest and runrux checkat the root again. How many packages are checked now — and doesAppstill build? - Add a third member: a source library called
Kelvinwith apubfunctionToKelvin(celsius: float64) -> float64. List it in the workspace, depend on it fromApp, and print each reading in kelvin too.
Learn more
- Workspaces in the package manifest reference
- Global options —
--manifestand the other options every command accepts rux checkandrux buildin the CLI reference- Source library — the kind of package
Temperatureis