Skip to content

Commit 0b115f5

Browse files
committed
-Zfeatures=host_dep: Support decoupling proc-macro features.
1 parent 5a1862c commit 0b115f5

File tree

10 files changed

+339
-112
lines changed

10 files changed

+339
-112
lines changed

crates/cargo-test-support/src/registry.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ pub struct Package {
144144
local: bool,
145145
alternative: bool,
146146
invalid_json: bool,
147+
proc_macro: bool,
147148
}
148149

149150
#[derive(Clone)]
@@ -242,6 +243,7 @@ impl Package {
242243
local: false,
243244
alternative: false,
244245
invalid_json: false,
246+
proc_macro: false,
245247
}
246248
}
247249

@@ -345,6 +347,12 @@ impl Package {
345347
self
346348
}
347349

350+
/// Specifies whether or not this is a proc macro.
351+
pub fn proc_macro(&mut self, proc_macro: bool) -> &mut Package {
352+
self.proc_macro = proc_macro;
353+
self
354+
}
355+
348356
/// Adds an entry in the `[features]` section.
349357
pub fn feature(&mut self, name: &str, deps: &[&str]) -> &mut Package {
350358
let deps = deps.iter().map(|s| s.to_string()).collect();
@@ -413,6 +421,7 @@ impl Package {
413421
"cksum": cksum,
414422
"features": self.features,
415423
"yanked": self.yanked,
424+
"pm": self.proc_macro,
416425
})
417426
.to_string();
418427

@@ -498,6 +507,9 @@ impl Package {
498507
manifest.push_str(&format!("registry-index = \"{}\"", alt_registry_url()));
499508
}
500509
}
510+
if self.proc_macro {
511+
manifest.push_str("[lib]\nproc-macro = true\n");
512+
}
501513

502514
let dst = self.archive_dst();
503515
t!(fs::create_dir_all(dst.parent().unwrap()));

crates/resolver-tests/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ pub fn resolve_with_config_raw(
176176
&BTreeMap::<String, Vec<String>>::new(),
177177
None::<&String>,
178178
false,
179+
false,
179180
)
180181
.unwrap();
181182
let opts = ResolveOpts::everything();
@@ -577,6 +578,7 @@ pub fn pkg_dep<T: ToPkgId>(name: T, dep: Vec<Dependency>) -> Summary {
577578
&BTreeMap::<String, Vec<String>>::new(),
578579
link,
579580
false,
581+
false,
580582
)
581583
.unwrap()
582584
}
@@ -605,6 +607,7 @@ pub fn pkg_loc(name: &str, loc: &str) -> Summary {
605607
&BTreeMap::<String, Vec<String>>::new(),
606608
link,
607609
false,
610+
false,
608611
)
609612
.unwrap()
610613
}
@@ -619,6 +622,7 @@ pub fn remove_dep(sum: &Summary, ind: usize) -> Summary {
619622
&BTreeMap::<String, Vec<String>>::new(),
620623
sum.links().map(|a| a.as_str()),
621624
sum.namespaced_features(),
625+
sum.proc_macro(),
622626
)
623627
.unwrap()
624628
}

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,11 @@ fn deps_of_roots<'a, 'cfg>(roots: &[Unit<'a>], mut state: &mut State<'a, 'cfg>)
178178
} else if unit.target.is_custom_build() {
179179
// This normally doesn't happen, except `clean` aggressively
180180
// generates all units.
181-
UnitFor::new_build(false)
181+
UnitFor::new_host(false)
182+
} else if unit.target.proc_macro() {
183+
UnitFor::new_host(true)
182184
} else if unit.target.for_host() {
183-
// Proc macro / plugin should never have panic set.
185+
// Plugin should never have panic set.
184186
UnitFor::new_compiler()
185187
} else {
186188
UnitFor::new_normal()
@@ -297,7 +299,7 @@ fn compute_deps<'a, 'cfg>(
297299
let dep_unit_for = unit_for
298300
.with_for_host(lib.for_host())
299301
// If it is a custom build script, then it *only* has build dependencies.
300-
.with_build_dep(unit.target.is_custom_build());
302+
.with_host_features(unit.target.is_custom_build() || lib.proc_macro());
301303

302304
if bcx.config.cli_unstable().dual_proc_macros && lib.proc_macro() && !unit.kind.is_host() {
303305
let unit_dep = new_unit_dep(state, unit, pkg, lib, dep_unit_for, unit.kind, mode)?;
@@ -388,9 +390,10 @@ fn compute_deps_custom_build<'a, 'cfg>(
388390
return Ok(Vec::new());
389391
}
390392
}
391-
// All dependencies of this unit should use profiles for custom
392-
// builds.
393-
let script_unit_for = UnitFor::new_build(unit_for.is_for_build_dep());
393+
// All dependencies of this unit should use profiles for custom builds.
394+
// If this is a build script of a proc macro, make sure it uses host
395+
// features.
396+
let script_unit_for = UnitFor::new_host(unit_for.is_for_host_features());
394397
// When not overridden, then the dependencies to run a build script are:
395398
//
396399
// 1. Compiling the build script itself.
@@ -445,7 +448,9 @@ fn compute_deps_doc<'a, 'cfg>(
445448
// Rustdoc only needs rmeta files for regular dependencies.
446449
// However, for plugins/proc macros, deps should be built like normal.
447450
let mode = check_or_build_mode(unit.mode, lib);
448-
let dep_unit_for = UnitFor::new_normal().with_for_host(lib.for_host());
451+
let dep_unit_for = UnitFor::new_normal()
452+
.with_for_host(lib.for_host())
453+
.with_host_features(lib.proc_macro());
449454
let lib_unit_dep = new_unit_dep(
450455
state,
451456
unit,
@@ -528,32 +533,32 @@ fn dep_build_script<'a>(
528533
.bcx
529534
.profiles
530535
.get_profile_run_custom_build(&unit.profile);
531-
// UnitFor::new_build is used because we want the `host` flag set
536+
// UnitFor::new_host is used because we want the `host` flag set
532537
// for all of our build dependencies (so they all get
533538
// build-override profiles), including compiling the build.rs
534539
// script itself.
535540
//
536-
// If `is_for_build_dep` here is `false`, that means we are a
541+
// If `is_for_host_features` here is `false`, that means we are a
537542
// build.rs script for a normal dependency and we want to set the
538543
// CARGO_FEATURE_* environment variables to the features as a
539544
// normal dep.
540545
//
541-
// If `is_for_build_dep` here is `true`, that means that this
542-
// package is being used as a build dependency, and so we only
543-
// want to set CARGO_FEATURE_* variables for the build-dependency
546+
// If `is_for_host_features` here is `true`, that means that this
547+
// package is being used as a build dependency or proc-macro, and
548+
// so we only want to set CARGO_FEATURE_* variables for the host
544549
// side of the graph.
545550
//
546551
// Keep in mind that the RunCustomBuild unit and the Compile
547552
// build.rs unit use the same features. This is because some
548553
// people use `cfg!` and `#[cfg]` expressions to check for enabled
549554
// features instead of just checking `CARGO_FEATURE_*` at runtime.
550-
// In the case with `-Zfeatures=build_dep`, and a shared
555+
// In the case with `-Zfeatures=host_dep`, and a shared
551556
// dependency has different features enabled for normal vs. build,
552557
// then the build.rs script will get compiled twice. I believe it
553558
// is not feasible to only build it once because it would break a
554559
// large number of scripts (they would think they have the wrong
555560
// set of features enabled).
556-
let script_unit_for = UnitFor::new_build(unit_for.is_for_build_dep());
561+
let script_unit_for = UnitFor::new_host(unit_for.is_for_host_features());
557562
new_unit_dep_with_profile(
558563
state,
559564
unit,

src/cargo/core/profiles.rs

Lines changed: 45 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ pub struct UnitFor {
768768
/// any of its dependencies. This enables `build-override` profiles for
769769
/// these targets.
770770
///
771-
/// An invariant is that if `build_dep` is true, `host` must be true.
771+
/// An invariant is that if `host_features` is true, `host` must be true.
772772
///
773773
/// Note that this is `true` for `RunCustomBuild` units, even though that
774774
/// unit should *not* use build-override profiles. This is a bit of a
@@ -779,16 +779,16 @@ pub struct UnitFor {
779779
/// sticky (and forced to `true` for all further dependencies) — which is
780780
/// the whole point of `UnitFor`.
781781
host: bool,
782-
/// A target for a build dependency (or any of its dependencies). This is
783-
/// used for computing features of build dependencies independently of
784-
/// other dependency kinds.
782+
/// A target for a build dependency or proc-macro (or any of its
783+
/// dependencies). This is used for computing features of build
784+
/// dependencies and proc-macros independently of other dependency kinds.
785785
///
786786
/// The subtle difference between this and `host` is that the build script
787787
/// for a non-host package sets this to `false` because it wants the
788788
/// features of the non-host package (whereas `host` is true because the
789-
/// build script is being built for the host). `build_dep` becomes `true`
790-
/// for build-dependencies, or any of their dependencies. For example, with
791-
/// this dependency tree:
789+
/// build script is being built for the host). `host_features` becomes
790+
/// `true` for build-dependencies or proc-macros, or any of their
791+
/// dependencies. For example, with this dependency tree:
792792
///
793793
/// ```text
794794
/// foo
@@ -799,17 +799,18 @@ pub struct UnitFor {
799799
/// └── shared_dep build.rs
800800
/// ```
801801
///
802-
/// In this example, `foo build.rs` is HOST=true, BUILD_DEP=false. This is
803-
/// so that `foo build.rs` gets the profile settings for build scripts
804-
/// (HOST=true) and features of foo (BUILD_DEP=false) because build scripts
805-
/// need to know which features their package is being built with.
802+
/// In this example, `foo build.rs` is HOST=true, HOST_FEATURES=false.
803+
/// This is so that `foo build.rs` gets the profile settings for build
804+
/// scripts (HOST=true) and features of foo (HOST_FEATURES=false) because
805+
/// build scripts need to know which features their package is being built
806+
/// with.
806807
///
807808
/// But in the case of `shared_dep`, when built as a build dependency,
808809
/// both flags are true (it only wants the build-dependency features).
809810
/// When `shared_dep` is built as a normal dependency, then `shared_dep
810-
/// build.rs` is HOST=true, BUILD_DEP=false for the same reasons that
811+
/// build.rs` is HOST=true, HOST_FEATURES=false for the same reasons that
811812
/// foo's build script is set that way.
812-
build_dep: bool,
813+
host_features: bool,
813814
/// How Cargo processes the `panic` setting or profiles. This is done to
814815
/// handle test/benches inheriting from dev/release, as well as forcing
815816
/// `for_host` units to always unwind.
@@ -837,32 +838,35 @@ impl UnitFor {
837838
pub fn new_normal() -> UnitFor {
838839
UnitFor {
839840
host: false,
840-
build_dep: false,
841+
host_features: false,
841842
panic_setting: PanicSetting::ReadProfile,
842843
}
843844
}
844845

845-
/// A unit for a custom build script or its dependencies.
846+
/// A unit for a custom build script or proc-macro or its dependencies.
846847
///
847-
/// The `build_dep` parameter is whether or not this is for a build
848-
/// dependency. Build scripts for non-host units should use `false`
849-
/// because they want to use the features of the package they are running
850-
/// for.
851-
pub fn new_build(build_dep: bool) -> UnitFor {
848+
/// The `host_features` parameter is whether or not this is for a build
849+
/// dependency or proc-macro (something that requires being built "on the
850+
/// host"). Build scripts for non-host units should use `false` because
851+
/// they want to use the features of the package they are running for.
852+
pub fn new_host(host_features: bool) -> UnitFor {
852853
UnitFor {
853854
host: true,
854-
build_dep,
855+
host_features,
855856
// Force build scripts to always use `panic=unwind` for now to
856857
// maximally share dependencies with procedural macros.
857858
panic_setting: PanicSetting::AlwaysUnwind,
858859
}
859860
}
860861

861-
/// A unit for a proc macro or compiler plugin or their dependencies.
862+
/// A unit for a compiler plugin or their dependencies.
862863
pub fn new_compiler() -> UnitFor {
863864
UnitFor {
864865
host: false,
865-
build_dep: false,
866+
// The feature resolver doesn't know which dependencies are
867+
// plugins, so for now plugins don't split features. Since plugins
868+
// are mostly deprecated, just leave this as false.
869+
host_features: false,
866870
// Force plugins to use `panic=abort` so panics in the compiler do
867871
// not abort the process but instead end with a reasonable error
868872
// message that involves catching the panic in the compiler.
@@ -879,7 +883,7 @@ impl UnitFor {
879883
pub fn new_test(config: &Config) -> UnitFor {
880884
UnitFor {
881885
host: false,
882-
build_dep: false,
886+
host_features: false,
883887
// We're testing out an unstable feature (`-Zpanic-abort-tests`)
884888
// which inherits the panic setting from the dev/release profile
885889
// (basically avoid recompiles) but historical defaults required
@@ -902,7 +906,7 @@ impl UnitFor {
902906
pub fn with_for_host(self, for_host: bool) -> UnitFor {
903907
UnitFor {
904908
host: self.host || for_host,
905-
build_dep: self.build_dep,
909+
host_features: self.host_features,
906910
panic_setting: if for_host {
907911
PanicSetting::AlwaysUnwind
908912
} else {
@@ -911,15 +915,16 @@ impl UnitFor {
911915
}
912916
}
913917

914-
/// Returns a new copy updating it for a build dependency.
918+
/// Returns a new copy updating it whether or not it should use features
919+
/// for build dependencies and proc-macros.
915920
///
916921
/// This is part of the machinery responsible for handling feature
917922
/// decoupling for build dependencies in the new feature resolver.
918-
pub fn with_build_dep(mut self, build_dep: bool) -> UnitFor {
919-
if build_dep {
923+
pub fn with_host_features(mut self, host_features: bool) -> UnitFor {
924+
if host_features {
920925
assert!(self.host);
921926
}
922-
self.build_dep = self.build_dep || build_dep;
927+
self.host_features = self.host_features || host_features;
923928
self
924929
}
925930

@@ -929,8 +934,8 @@ impl UnitFor {
929934
self.host
930935
}
931936

932-
pub fn is_for_build_dep(&self) -> bool {
933-
self.build_dep
937+
pub fn is_for_host_features(&self) -> bool {
938+
self.host_features
934939
}
935940

936941
/// Returns how `panic` settings should be handled for this profile
@@ -943,43 +948,43 @@ impl UnitFor {
943948
static ALL: &[UnitFor] = &[
944949
UnitFor {
945950
host: false,
946-
build_dep: false,
951+
host_features: false,
947952
panic_setting: PanicSetting::ReadProfile,
948953
},
949954
UnitFor {
950955
host: true,
951-
build_dep: false,
956+
host_features: false,
952957
panic_setting: PanicSetting::AlwaysUnwind,
953958
},
954959
UnitFor {
955960
host: false,
956-
build_dep: false,
961+
host_features: false,
957962
panic_setting: PanicSetting::AlwaysUnwind,
958963
},
959964
UnitFor {
960965
host: false,
961-
build_dep: false,
966+
host_features: false,
962967
panic_setting: PanicSetting::Inherit,
963968
},
964-
// build_dep=true must always have host=true
969+
// host_features=true must always have host=true
965970
// `Inherit` is not used in build dependencies.
966971
UnitFor {
967972
host: true,
968-
build_dep: true,
973+
host_features: true,
969974
panic_setting: PanicSetting::ReadProfile,
970975
},
971976
UnitFor {
972977
host: true,
973-
build_dep: true,
978+
host_features: true,
974979
panic_setting: PanicSetting::AlwaysUnwind,
975980
},
976981
];
977982
ALL
978983
}
979984

980985
pub(crate) fn map_to_features_for(&self) -> FeaturesFor {
981-
if self.is_for_build_dep() {
982-
FeaturesFor::BuildDep
986+
if self.is_for_host_features() {
987+
FeaturesFor::HostDep
983988
} else {
984989
FeaturesFor::NormalOrDev
985990
}

0 commit comments

Comments
 (0)