buildRustCrate: add extraRustcOptsForProcMacro

Proc-macro crates are host dylibs that rustc dlopen()s. Instrumentation
flags passed via extraRustcOpts (e.g. -Zsanitizer=address,
-Cinstrument-coverage) leave unresolved runtime symbols in those dylibs
and break the build. Cargo avoids this by not applying RUSTFLAGS to host
artifacts; buildRustCrate already has extraRustcOptsForBuildRs for build
scripts, so add the analogous knob for proc-macros.

Defaults to null, which falls back to extraRustcOpts so existing callers
are unchanged. Set to [] to opt proc-macros out when applying
sanitizer/coverage flags tree-wide via crateOverrides.
This commit is contained in:
Bernardo Meurer
2026-04-22 23:47:34 -04:00
committed by Jörg Thalheim
parent 162f04bf3d
commit 127a52082d
3 changed files with 59 additions and 3 deletions

View File

@@ -871,6 +871,15 @@ general. A number of other parameters can be overridden:
(hello { }).override { extraRustcOpts = "-Z debuginfo=2"; }
```
- Extra arguments passed to `rustc` when the crate is a proc-macro,
replacing `extraRustcOpts`. Useful to keep instrumentation flags
(sanitizers, coverage) off host dylibs. Defaults to `null`, which
inherits `extraRustcOpts`:
```nix
(myProcMacro { }).override { extraRustcOptsForProcMacro = [ ]; }
```
- The lint level cap passed to `rustc`. Defaults to `null`, which
auto-resolves to `"allow"` (silences all lints) when `lints` is
empty, or `"forbid"` (no cap) when `lints` is set. Because `rustc`

View File

@@ -255,6 +255,12 @@ lib.makeOverridable
# Example: [ "-Z debuginfo=2" ]
# Default: []
extraRustcOptsForBuildRs,
# Extra rustc options for proc-macro crates, replacing
# `extraRustcOpts`. Lets callers keep instrumentation flags
# (sanitizers, coverage) off host dylibs, mirroring Cargo's
# behaviour of not applying RUSTFLAGS to host artifacts.
# Default: null (inherit `extraRustcOpts`)
extraRustcOptsForProcMacro,
# The lint level cap passed to rustc via `--cap-lints`.
# See <https://doc.rust-lang.org/rustc/lints/levels.html#capping-lints>.
#
@@ -352,7 +358,21 @@ lib.makeOverridable
buildInputs_ = buildInputs;
extraRustcOpts_ = extraRustcOpts;
extraRustcOptsForBuildRs_ = extraRustcOptsForBuildRs;
extraRustcOptsForProcMacro_ = extraRustcOptsForProcMacro;
buildTests_ = buildTests;
procMacro = lib.attrByPath [ "procMacro" ] false crate;
# For proc-macros, prefer the *ForProcMacro variant at each level
# (crate attr, override arg) and fall back to extraRustcOpts.
crateExtraRustcOpts =
if procMacro && crate ? extraRustcOptsForProcMacro then
crate.extraRustcOptsForProcMacro
else
crate.extraRustcOpts or [ ];
overrideExtraRustcOpts =
if procMacro && extraRustcOptsForProcMacro_ != null then
extraRustcOptsForProcMacro_
else
extraRustcOpts_;
resolvedLints = crate.lints or lints;
lintFlags = lintsToRustcFlags resolvedLints;
resolvedCapLints =
@@ -474,7 +494,7 @@ lib.makeOverridable
crateRustVersion = crate.rust-version or "";
crateVersion = crate.version;
crateType =
if lib.attrByPath [ "procMacro" ] false crate then
if procMacro then
[ "proc-macro" ]
else if lib.attrByPath [ "plugin" ] false crate then
[ "dylib" ]
@@ -485,8 +505,8 @@ lib.makeOverridable
edition = crate.edition or null;
codegenUnits = if crate ? codegenUnits then crate.codegenUnits else defaultCodegenUnits;
extraRustcOpts =
lib.optionals (crate ? extraRustcOpts) crate.extraRustcOpts
++ extraRustcOpts_
crateExtraRustcOpts
++ overrideExtraRustcOpts
++ lintFlags
++ (lib.optional (edition != null) "--edition ${edition}");
extraRustcOptsForBuildRs =
@@ -586,6 +606,7 @@ lib.makeOverridable
verbose = crate_.verbose or true;
extraRustcOpts = [ ];
extraRustcOptsForBuildRs = [ ];
extraRustcOptsForProcMacro = null;
capLints = null;
lints = { };
features = [ ];

View File

@@ -836,6 +836,32 @@ rec {
];
};
};
# Default (null) inherits extraRustcOpts for proc-macros.
procMacroExtraOptsInherit = {
procMacro = true;
edition = "2018";
extraRustcOpts = [ "--cfg=target_only" ];
src = mkFile "src/lib.rs" ''
#[cfg(not(target_only))]
compile_error!("extraRustcOpts not inherited by proc-macro");
use proc_macro as _;
'';
};
# When set, extraRustcOptsForProcMacro replaces extraRustcOpts
# for proc-macro crates.
procMacroExtraOptsOverride = {
procMacro = true;
edition = "2018";
extraRustcOpts = [ "--cfg=target_only" ];
extraRustcOptsForProcMacro = [ "--cfg=host_only" ];
src = mkFile "src/lib.rs" ''
#[cfg(target_only)]
compile_error!("extraRustcOpts leaked into proc-macro");
#[cfg(not(host_only))]
compile_error!("extraRustcOptsForProcMacro not applied");
use proc_macro as _;
'';
};
# The `lints` attr mirrors Cargo.toml's `[lints]` table and is
# translated to rustc `-A`/`-W`/`-D`/`-F` flags. Lower-priority
# entries are emitted first so that higher-priority specific lints