Renaming Cargo "target"

So you're saying there are actually three different concepts here, right?

  1. A "platform" target: a triple you can compile for (--target)
  2. An "artifact" target: the output of a build (/target)
  3. A "unit" target: a compilation unit (lib, bins, examples, etc; --all-targets)

I seem to remember that Cargo also uses the "unit" wording in some of its internals. Would it maybe make sense to rename (3) to unit while renaming (2) to artifact? I guess at the rustc level there might be overlap with codegen units, but --all-units seems like a potentially better alternative then --all-artifacts especially when used with cargo check (which doesn't actually produce artifacts).

4 Likes

Maybe its my bias for how Cargo already uses "unit" but its ingrained in me that "unit" is the same as "node" or "crate" which can represent anything in the build graph, not just the root (or leaves, depending on your perspective).

1 Like

Bug :100: for renaming this -- I only fairly recently discovered this terminology match and did indeed find it quite confusing.

In terms of candidate names, I think I like "product". cargo check --all-products would check that all products can be produced (without actually producing them), while cargo build --all-products would actually produce them -- I think that makes sense, despite the fact that "product" refers more to the output of the build process than its input.

6 Likes

I kinda like product better than artifact myself, as well. "product" feels like it is both a more common word and one that better fits things like tests for which there is a useful result but it isn't an artifact.

Thoughts, @epage?

My personal bias is that when I see "product" and "products", I have an internal negative reaction as I feel like business speak is being used.

Also, when i first read cargo build --all-products, I read into it the same problem as --all-artifacts when it comes to tests.

3 Likes

Fair enough.

Surely business speak also involves "target" and "feature"? I don't think that should stop us from using these terms.

6 Likes

FWIW, I at least haven't had much issue with “target” as a term. This may be because I conceptualize the cargo “target” as including the compilation “target,” and that the concept of “target” is entirely one of configuration input. E.g. a cargo command would say “Cargo (cargo), build (build) the binary foo (--bin foo) from package bar (--package bar) for x86_64 Windows (--target x86_64-pc-windows-msvc).” The --all-targets flag isn't actually all the targets, and that's because while wanting to process every one of the cargo “target”s is common, processing each and every compilation “target” — or even just the ones I have installed — is an essentially never use case.

I don't see the selection of libs/bins/tests/examples as really having an existing name at all, because I see the selected “target” as including the triple, even if it's inferred and Cargo can only build one triple at a time.

Also FWIW, the Cargo Book’s commands reference documents --target specifying to build “for the given architecture” (specified as a triple).

1 Like

An alternative suggestion: what about using "triple" to refer to "target triples", and "target" for "build targets"?

clang notably actually uses this in their docs to specify a 5-tuple of terms, and:

  • I think anyone specifying --triple=x86_64-unknown-linux-gnu will be able to understand where that term comes from
  • if you don't know what --triple means, it's a reasonably unambiguous term to search for (or ask an LLM coding assistant about)
  • using "triple" for "target triple" and "target" for "build output" will, relative to using "artifact" for "build output", I think result in far less existing documentation becoming outdated, i.e. people finding documentation about "targets" that actually references "artifacts" and getting confused

Some prior art, with links:

Ecosystem/Language Equivalent term for target triple Link
android native triple Usa l'NDK con altri sistemi di compilazione  |  Android NDK  |  Android Developers
autoconf target triplet, specified in either --build, --host, or --target Specifying Target Triplets (Autoconf)
Bazel --platform Reglas de plataformas y cadenas de herramientas  |  Bazel
Buck (unnamed) BUCK and cross compiling on different platforms · Issue #1647 · facebook/buck · GitHub
CMake CMAKE_SYSTEM (and CMAKE_SYSTEM_NAME, CMAKE_HOST_SYSTEM, etc) Cross Compiling With CMake — Mastering CMake
clang The triple has the general format <arch><sub>-<vendor>-<sys>-<env> Cross-compilation using Clang — Clang 20.0.0git documentation
Go CXX_FOR_TARGET, CXX_FOR_${GOOS}_${GOARCH} cgo command - cmd/cgo - Go Packages
Java (GraalVM) --target GraalVM
Ruby (rake-compiler) ext.cross_platform = ['x86-mingw32', 'x64-mingw32'] GitHub - rake-compiler/rake-compiler: Provide a standard and simplified way to build and package Ruby C and Java extensions using Rake as glue.

I think ideally we would use "platform" instead of "target" for what rustc cares about. But that ship has probably sailed. Note that we're about to ship Add `--print host-tuple` to print host target tuple by Noratrieb · Pull Request #125579 · rust-lang/rust · GitHub which explicitly moves away from "triple" terminology (because it sucks).

4 Likes

As mentioned in the recent summary, the main concern we have for renaming "platform" target is that has a lot larger of a migration cost (--target, [target], etc) while every place we use "build" target, we already have motivation for renaming.

Ah, "host tuple" definitely feels like a better term than "triple", or "target tuple" for that matter, although unfortunately not nearly as search-friendly (i.e. I expect to get much better search results for "target triple" than "target tuple").

Thanks for the missing context re the migration cost - I hadn't realized y'all had been talking about this for months already (which makes sense). This just surfaced in an email for me, and while catching up on the thread it was unclear to me why the discussion was so one-sided around "what new term do we use for 'build output'", so I figured a suggestion on the other side was welcome.


Incidentally, in the other list of comparison terminology, to flesh out the list:

  • Bazel refers to "build targets" much like make/autoconf do; however, when chaining one build rule's outputs into another, you simply refer to them as the outputs of an intermediate action (docs) - this is a consequence of that Bazel (and I believe Buck by extension) is explicitly designed to teach the user to think about a graph of build targets.
  • poetry (python) calls libraries "packages" and binaries/executables "scripts" (link)
  • Gradle also describes the build system as a graph of "tasks", and then there is an "output directory" that tasks may write to

"outputs" would be a fine term if not for the fact that it includes things like tests and benchmarks for which you don't get a specific output file.

For meaning 2, perhaps we should mull over general terms that might refer to what gets delivered onto a dock in a harbor or at a port. The word "freight" might work, but maybe it misses the mark by just a little bit.

... or how about the name "payload" as a metaphor for what is delivered that is the most valuable, as are passengers and cargo?

"payload" and "freight" still imply a thing being handled, which doesn't work well for "test" and "bench" and similar.

One suggestion I haven't seen yet is --all-tasks (only found it in one of the lists from other languages, but not as a suggestion). It works for cargo build and cargo check, it can also include benchmarks and tests (which is what we want) and you can already decide what this includes in the Cargo.toml ([[bin]], [[test]], [[bench]], ...) [1], thus allowing you to specify a list of tasks that should be done.

  • --lib build/check the library task (as specified in Cargo.toml or automatic if not specified)
  • --bins build/check all binary tasks
  • --bin X build/check a single binary (task).

The only thing missing from that config (in my opinion) is the ability to specify the list of features cargo should automatically add (only required-features exists, which lets cargo fail if you don't pass them explicitly) and a list of target triples those should be executed on, ideally allowing any combination. Having that would allow a single cargo check --all-tasks (no target tripple) to check multiple targets for some binaries. And calling it task would still make sense.

Just as an example of my last point (not required for calling this --all-tasks):

[[bin]]
name = "frobnicator"
required-features = ["frobnicate"]
default-features = ["frobnicate", "extra"]

[[bin]]
name = "frobnicator-win"
required-features = ["frobnicate"]
default-features = ["frobnicate", "extra"]
targets = ["x86_64-pc-windows-msvc"]

# Unfortunately this doesn't work well with `[lib]`,
# as there can only be one.

  1. The Manifest Format - The Cargo Book ↩︎

1 Like

"task" is also used by tools for project-specific tools that plugin into the build tool which there has been interest for for Cargo.

Is that an argument for or against using "task"? (Or just a neutral statement?)

If we use it here, we need to consider the impact for a "cargo task" feature.