ADR 0002: every crate has a package name and a library name
Status Accepted
Audience Anyone who opens `models/Cargo.toml` and wonders why
the package is `nihilurk-models` and the library is
`models`, or who is about to rename one of them.
Supersedes --
Related ../how-to/publish-to-crates-io.md
Every crate in this workspace has two names, and they are different on purpose.
directory models/
package name nihilurk-models what crates.io and `cargo -p` see
library name models what `use models::*;` sees
Context
The directory and the library name are the short ones the code was written with. Publishing to crates.io forced the package name to change.
crates.io gives out names on a first-come basis. engine, models and strings were all taken by other people before nihilurk existed, so a crate published under those names would be refused. particle-core was free, but it was marked publish = false, and the crates above it cannot go out unless it does.
That last point forces the issue. engine depends on models and strings by path. crates.io does not accept a path dependency: it needs a version that resolves in its own index. So publishing the game means publishing the whole chain, and each link in it needs a name nobody else holds.
Decision
Rename the packages. Keep the directories and the library names.
- Every crate that ships is
nihilurkornihilurk-<thing>.engine/tests/workspace.rsfails if a new one is not. - The binary’s package takes the bare name
nihilurk, which is free. The binary was already callednihilurk, socargo install nihilurkinstalls the thing it says. - A package name and a library name are separate settings in Cargo, so two lines keep the library names:
`[lib] name = "models"` in the crate itself, so its own
integration tests keep compiling.
`models = { package = "nihilurk-models", ... }`
in the crate that depends on it, so
the dependency is still called
`models` in the code.
compat/is alreadynihilurk-compatand ispublish = false. It is a test rig that builds the game for other machines, and it depends on ratatui, which the shipped binary may not. Nothing installs it, so it has no name to defend.
Rejected:
- Renaming the library too. The library name defaults to the package name with hyphens turned into underscores, so renaming the package alone would have made it
nihilurk_modelsand broken everyuse models::line in the game, the tests and the docs. Renaming the library means touching every file that mentions it, a diff a hundred times the size for a gain the player never sees. - One crate. Fold
models,stringsandparticle-coreinto onenihilurkcrate as modules and publish once. Two reasons against:particle-coreisno_stdwith no dependencies so anyone can build it for a machine with no OS and get the arithmetic the game runs, and folded in it would sit besidebevy_ecsand the save-file code, and that would end. Andmodelsis the crate the documentation is written around: almost every page undertutorial/,how-to/andreference/names a file in it, so moving it is a rewrite of the docs, not a release task.
Consequences
Accepted costs:
- A reader has to know both names.
cargo -ptakes the package name, so it iscargo test -p nihilurk-modelsandcargo run -p nihilurk, while the code saysmodels. This ADR is the page that explains it.
Benefits realised:
- The game, its tests and its docs kept every
use models::line. cargo install nihilurkinstalls the game.particle-corestays small,no_stdand dependency-free.
When to revisit
Reopen this decision if any of these becomes true:
- crates.io stops being a target. With nothing published, the package names can go back to the short ones.
- A short name is released to us. If
modelsorengineever becomes available, the rename is a different trade. - The docs stop being written around
models. Then folding crates costs less than it does now.
See also
../how-to/publish-to-crates-io.md the release recipe
cross-platform-testing.md why particle-core stays separate
../../engine/tests/workspace.rs the tests that hold the names in place