lib.systems: rust: Make rustcTargetSpec the primary entrypoint (#446668)

This commit is contained in:
Alyssa Ross 2026-03-07 08:22:44 +00:00 committed by GitHub
commit bd0c7ad05a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 98 additions and 89 deletions

View file

@ -254,7 +254,7 @@ By default, it takes the `stdenv.hostPlatform.config` and replaces components
where they are known to differ. But there are ways to customize the argument: where they are known to differ. But there are ways to customize the argument:
- To choose a different target by name, define - To choose a different target by name, define
`stdenv.hostPlatform.rust.rustcTarget` as that name (a string), and that `stdenv.hostPlatform.rust.rustcTargetSpec` as that name (a string), and that
name will be used instead. name will be used instead.
For example: For example:
@ -262,7 +262,7 @@ where they are known to differ. But there are ways to customize the argument:
```nix ```nix
import <nixpkgs> { import <nixpkgs> {
crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // { crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // {
rust.rustcTarget = "thumbv7em-none-eabi"; rust.rustcTargetSpec = "thumbv7em-none-eabi";
}; };
} }
``` ```
@ -274,22 +274,24 @@ where they are known to differ. But there are ways to customize the argument:
``` ```
- To pass a completely custom target, define - To pass a completely custom target, define
`stdenv.hostPlatform.rust.rustcTarget` with its name, and `stdenv.hostPlatform.rust.rustcTargetSpec` with the path to the custom
`stdenv.hostPlatform.rust.platform` with the value. The value will be target specification JSON file.
serialized to JSON in a file called
`${stdenv.hostPlatform.rust.rustcTarget}.json`, and the path of that file Note that some tools like Cargo and some crates like `cc` make use of the
will be used instead. file name of the target JSON. Therefore, do not use
`./path/to/target-spec.json` directly, because it will be renamed by Nix.
Instead, place it a directory and use `"${./path/to/dir}/target-spec.json"`.
The directory should contain only this one file, to avoid unrelated changes
causing unnecessary rebuilds.
For example: For example:
```nix ```nix
import <nixpkgs> { import <nixpkgs> {
crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // { crossSystem = {
rust.rustcTarget = "thumb-crazy"; config = "mips64el-unknown-linux-gnuabi64";
rust.platform = { # gcc = ...; # Config for C compiler omitted
foo = ""; rust.rustcTargetSpec = "${./rust}/mips64el_mips3-unknown-linux-gnuabi64.json";
bar = "";
};
}; };
} }
``` ```
@ -297,12 +299,9 @@ where they are known to differ. But there are ways to customize the argument:
will result in: will result in:
```shell ```shell
--target /nix/store/asdfasdfsadf-thumb-crazy.json # contains {"foo":"","bar":""} --target /nix/store/...-rust/mips64el_mips3-unknown-linux-gnuabi64.json
``` ```
Note that currently custom targets aren't compiled with `std`, so `cargo test`
will fail. This can be ignored by adding `doCheck = false;` to your derivation.
### Running package tests {#running-package-tests} ### Running package tests {#running-package-tests}
When using `buildRustPackage`, the `checkPhase` is enabled by default and runs When using `buildRustPackage`, the `checkPhase` is enabled by default and runs

View file

@ -417,12 +417,20 @@ let
// args // args
// { // {
rust = rust // { rust = rust // {
platform =
rust.platform or (
if lib.hasSuffix ".json" (rust.rustcTargetSpec or "") then
lib.importJSON rust.rustcTargetSpec
else
{ }
)
# Once args.rustc.platform.target-family is deprecated and # Once args.rustc.platform.target-family is deprecated and
# removed, there will no longer be any need to modify any # removed, there will no longer be any need to modify any
# values from args.rust.platform, so we can drop all the # values from args.rust.platform, so we can drop all the
# "args ? rust" etc. checks, and merge args.rust.platform in # "args ? rust" etc. checks, and merge args.rust.platform in
# /after/. # /after/.
platform = rust.platform or { } // { // {
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch # https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch
arch = arch =
if rust ? platform then if rust ? platform then
@ -474,9 +482,10 @@ let
.${vendor.name} or vendor.name; .${vendor.name} or vendor.name;
}; };
# The name of the rust target, even if it is custom. Adjustments are # The name of the rust target if it is standard, or the json file
# because rust has slightly different naming conventions than we do. # containing the custom target spec. Adjustments are because rust has
rustcTarget = # slightly different naming conventions than we do.
rustcTargetSpec =
let let
inherit (final.parsed) cpu kernel abi; inherit (final.parsed) cpu kernel abi;
cpu_ = cpu_ =
@ -497,28 +506,29 @@ let
"gnu" "gnu"
else else
abi.name; abi.name;
in
# TODO: deprecate args.rustc in favour of args.rust after 23.05 is EOL. inferred =
args.rust.rustcTarget or args.rustc.config or ( if final.isWasi then
# Rust uses `wasm32-wasip?` rather than `wasm32-unknown-wasi`. # Rust uses `wasm32-wasip?` rather than `wasm32-unknown-wasi`.
# We cannot know which subversion does the user want, and # We cannot know which subversion does the user want, and
# currently use WASI 0.1 as default for compatibility. Custom # currently use WASI 0.1 as default for compatibility. Custom
# users can set `rust.rustcTarget` to override it. # users can set `rust.rustcTargetSpec` to override it.
if final.isWasi then
"${cpu_}-wasip1" "${cpu_}-wasip1"
else else
"${cpu_}-${vendor_}-${kernel.name}${optionalString (abi.name != "unknown") "-${abi_}"}" "${cpu_}-${vendor_}-${kernel.name}${optionalString (abi.name != "unknown") "-${abi_}"}";
in
# TODO: deprecate args.rustc in favour of args.rust after 23.05 is EOL.
args.rust.rustcTargetSpec or args.rustc.config or (
if rust ? platform then
# TODO: This breaks cc-rs and thus std support, so maybe remove support?
builtins.toFile (rust.rustcTarget or inferred + ".json") (toJSON rust.platform)
else
args.rust.rustcTarget or inferred
); );
# The name of the rust target if it is standard, or the json file # Do not use rustcTarget. Use rustcTargetSpec or cargoShortTarget.
# containing the custom target spec. # TODO: Remove all in-tree usages, and deprecate
rustcTargetSpec = rustcTarget = rust.rustcTarget or final.rust.cargoShortTarget;
rust.rustcTargetSpec or (
if rust ? platform then
builtins.toFile (final.rust.rustcTarget + ".json") (toJSON rust.platform)
else
final.rust.rustcTarget
);
# The name of the rust target if it is standard, or the # The name of the rust target if it is standard, or the
# basename of the file containing the custom target spec, # basename of the file containing the custom target spec,