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:
- 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.
For example:
@ -262,7 +262,7 @@ where they are known to differ. But there are ways to customize the argument:
```nix
import <nixpkgs> {
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
`stdenv.hostPlatform.rust.rustcTarget` with its name, and
`stdenv.hostPlatform.rust.platform` with the value. The value will be
serialized to JSON in a file called
`${stdenv.hostPlatform.rust.rustcTarget}.json`, and the path of that file
will be used instead.
`stdenv.hostPlatform.rust.rustcTargetSpec` with the path to the custom
target specification JSON file.
Note that some tools like Cargo and some crates like `cc` make use of the
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:
```nix
import <nixpkgs> {
crossSystem = (import <nixpkgs/lib>).systems.examples.armhf-embedded // {
rust.rustcTarget = "thumb-crazy";
rust.platform = {
foo = "";
bar = "";
};
crossSystem = {
config = "mips64el-unknown-linux-gnuabi64";
# gcc = ...; # Config for C compiler omitted
rust.rustcTargetSpec = "${./rust}/mips64el_mips3-unknown-linux-gnuabi64.json";
};
}
```
@ -297,12 +299,9 @@ where they are known to differ. But there are ways to customize the argument:
will result in:
```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}
When using `buildRustPackage`, the `checkPhase` is enabled by default and runs

View file

@ -417,66 +417,75 @@ let
// args
// {
rust = rust // {
# Once args.rustc.platform.target-family is deprecated and
# removed, there will no longer be any need to modify any
# values from args.rust.platform, so we can drop all the
# "args ? rust" etc. checks, and merge args.rust.platform in
# /after/.
platform = rust.platform or { } // {
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch
arch =
if rust ? platform then
rust.platform.arch
else if final.isAarch32 then
"arm"
else if final.isMips64 then
"mips64" # never add "el" suffix
else if final.isPower64 then
"powerpc64" # never add "le" suffix
platform =
rust.platform or (
if lib.hasSuffix ".json" (rust.rustcTargetSpec or "") then
lib.importJSON rust.rustcTargetSpec
else
final.parsed.cpu.name;
{ }
)
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_os
os =
if rust ? platform then
rust.platform.os or "none"
else if final.isDarwin then
"macos"
else if final.isWasm && !final.isWasi then
"unknown" # Needed for {wasm32,wasm64}-unknown-unknown.
else
final.parsed.kernel.name;
# Once args.rustc.platform.target-family is deprecated and
# removed, there will no longer be any need to modify any
# values from args.rust.platform, so we can drop all the
# "args ? rust" etc. checks, and merge args.rust.platform in
# /after/.
// {
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_arch
arch =
if rust ? platform then
rust.platform.arch
else if final.isAarch32 then
"arm"
else if final.isMips64 then
"mips64" # never add "el" suffix
else if final.isPower64 then
"powerpc64" # never add "le" suffix
else
final.parsed.cpu.name;
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_family
target-family =
if args ? rust.platform.target-family then
args.rust.platform.target-family
else if args ? rustc.platform.target-family then
(
# Since https://github.com/rust-lang/rust/pull/84072
# `target-family` is a list instead of single value.
let
f = args.rustc.platform.target-family;
in
if isList f then f else [ f ]
)
else
optional final.isUnix "unix" ++ optional final.isWindows "windows" ++ optional final.isWasm "wasm";
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_os
os =
if rust ? platform then
rust.platform.os or "none"
else if final.isDarwin then
"macos"
else if final.isWasm && !final.isWasi then
"unknown" # Needed for {wasm32,wasm64}-unknown-unknown.
else
final.parsed.kernel.name;
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_vendor
vendor =
let
inherit (final.parsed) vendor;
in
rust.platform.vendor or {
"w64" = "pc";
}
.${vendor.name} or vendor.name;
};
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_family
target-family =
if args ? rust.platform.target-family then
args.rust.platform.target-family
else if args ? rustc.platform.target-family then
(
# Since https://github.com/rust-lang/rust/pull/84072
# `target-family` is a list instead of single value.
let
f = args.rustc.platform.target-family;
in
if isList f then f else [ f ]
)
else
optional final.isUnix "unix" ++ optional final.isWindows "windows" ++ optional final.isWasm "wasm";
# The name of the rust target, even if it is custom. Adjustments are
# because rust has slightly different naming conventions than we do.
rustcTarget =
# https://doc.rust-lang.org/reference/conditional-compilation.html#target_vendor
vendor =
let
inherit (final.parsed) vendor;
in
rust.platform.vendor or {
"w64" = "pc";
}
.${vendor.name} or vendor.name;
};
# The name of the rust target if it is standard, or the json file
# containing the custom target spec. Adjustments are because rust has
# slightly different naming conventions than we do.
rustcTargetSpec =
let
inherit (final.parsed) cpu kernel abi;
cpu_ =
@ -497,28 +506,29 @@ let
"gnu"
else
abi.name;
inferred =
if final.isWasi then
# Rust uses `wasm32-wasip?` rather than `wasm32-unknown-wasi`.
# We cannot know which subversion does the user want, and
# currently use WASI 0.1 as default for compatibility. Custom
# users can set `rust.rustcTargetSpec` to override it.
"${cpu_}-wasip1"
else
"${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.rustcTarget or args.rustc.config or (
# Rust uses `wasm32-wasip?` rather than `wasm32-unknown-wasi`.
# We cannot know which subversion does the user want, and
# currently use WASI 0.1 as default for compatibility. Custom
# users can set `rust.rustcTarget` to override it.
if final.isWasi then
"${cpu_}-wasip1"
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
"${cpu_}-${vendor_}-${kernel.name}${optionalString (abi.name != "unknown") "-${abi_}"}"
args.rust.rustcTarget or inferred
);
# The name of the rust target if it is standard, or the json file
# containing the custom target spec.
rustcTargetSpec =
rust.rustcTargetSpec or (
if rust ? platform then
builtins.toFile (final.rust.rustcTarget + ".json") (toJSON rust.platform)
else
final.rust.rustcTarget
);
# Do not use rustcTarget. Use rustcTargetSpec or cargoShortTarget.
# TODO: Remove all in-tree usages, and deprecate
rustcTarget = rust.rustcTarget or final.rust.cargoShortTarget;
# The name of the rust target if it is standard, or the
# basename of the file containing the custom target spec,