Skip to content

Commit d1c0a9d

Browse files
committed
Auto merge of #9030 - Ekleog:target-setting, r=alexcrichton
Expose build.target .cargo/config setting as packages.target in Cargo.toml Hey! I'm trying to do my first cargo contribution by implementing per-crate target settings as per [the irlo thread](https://internals.rust-lang.org/t/proposal-move-some-cargo-config-settings-to-cargo-toml/13336) ; and I think I have a draft that looks good-ish (the root units returned by `generate_targets` have the right kinds set). Closes #7004 **_Edit: the below problem description is now solved in the latest version of this PR, please ignore_** But for some reason running on a test project now blocks on `Blocking waiting for file lock on build directory` and I have literally no idea how my changes could trigger this… would anyone have an idea of how the changes could lead to infinitely blocking there? (I already tried cargo clean just in case and it didn't appear to help) FWIW, the output that looks hopeful to me is, on my testbed workspace: ``` Root units [out of generate_targets] are [...]: - package ‘smtp-client’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘smtp-server’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘yuubind-config’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘smtp-message-fuzz’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘yuubind-rpc’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘yuubind-config-example’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘smtp-message-fuzz’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘yuubind-config-example’ with kind ‘Target(CompileTarget { name: "wasm32-unknown-unknown" })’ - package ‘smtp-queue’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘smtp-message-fuzz’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘smtp-message’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘smtp-server-fuzz’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘yuubind-config’ with kind ‘Target(CompileTarget { name: "wasm32-unknown-unknown" })’ - package ‘yuubind’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ - package ‘smtp-queue-fs’ with kind ‘Target(CompileTarget { name: "x86_64-unknown-linux-gnu" })’ ``` (where both `yuubind-config` and `yuubind-config-example` are being configured to be `wasm32-unknown-unknown` and the other ones stay as host). Interestingly enough, if I remove the `target` setting from `yuubind-config` (and leave it on `yuubind-config-example`) then it does no longer block on waiting for file lock on build directory, even though it does not actually compile with `wasm32-unknown-unknown`. And it does appear to correctly build yuubind-config-example as wasm32. My investigation shows that it appears to happen iff there is a package with `package.target` being set that has dependencies. This most likely is a bug in my code (eg. I build only the root units and not the whole unit graph maybe?), and am going to keep investigating it as such, but maybe someone would already know how dependency resolution could interact with build lock acquisition and give me hints? Anyway, thank you all for all you do cargo!
2 parents a3ff382 + fcd7617 commit d1c0a9d

File tree

18 files changed

+393
-36
lines changed

18 files changed

+393
-36
lines changed

crates/cargo-test-support/build.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fn main() {
2+
println!(
3+
"cargo:rustc-env=NATIVE_ARCH={}",
4+
std::env::var("TARGET").unwrap()
5+
);
6+
}

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,23 @@ rustup does not appear to be installed. Make sure that the appropriate
179179
panic!("{}", message);
180180
}
181181

182+
/// The arch triple of the test-running host.
183+
pub fn native() -> &'static str {
184+
env!("NATIVE_ARCH")
185+
}
186+
187+
pub fn native_arch() -> &'static str {
188+
match native()
189+
.split("-")
190+
.next()
191+
.expect("Target triple has unexpected format")
192+
{
193+
"x86_64" => "x86_64",
194+
"i686" => "x86",
195+
_ => panic!("This test should be gated on cross_compile::disabled."),
196+
}
197+
}
198+
182199
/// The alternate target-triple to build with.
183200
///
184201
/// Only use this function on tests that check `cross_compile::disabled`.
@@ -204,6 +221,15 @@ pub fn alternate_arch() -> &'static str {
204221
}
205222
}
206223

224+
/// A target-triple that is neither the host nor the target.
225+
///
226+
/// Rustc may not work with it and it's alright, apart from being a
227+
/// valid target triple it is supposed to be used only as a
228+
/// placeholder for targets that should not be considered.
229+
pub fn unused() -> &'static str {
230+
"wasm32-unknown-unknown"
231+
}
232+
207233
/// Whether or not the host can run cross-compiled executables.
208234
pub fn can_run_on_host() -> bool {
209235
if disabled() {

src/cargo/core/compiler/build_context/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ pub struct BuildContext<'a, 'cfg> {
3939
pub packages: PackageSet<'cfg>,
4040

4141
/// Information about rustc and the target platform.
42-
pub target_data: RustcTargetData,
42+
pub target_data: RustcTargetData<'cfg>,
4343

4444
/// The root units of `unit_graph` (units requested on the command-line).
4545
pub roots: Vec<Unit>,
@@ -58,7 +58,7 @@ impl<'a, 'cfg> BuildContext<'a, 'cfg> {
5858
build_config: &'a BuildConfig,
5959
profiles: Profiles,
6060
extra_compiler_args: HashMap<Unit, Vec<String>>,
61-
target_data: RustcTargetData,
61+
target_data: RustcTargetData<'cfg>,
6262
roots: Vec<Unit>,
6363
unit_graph: UnitGraph,
6464
) -> CargoResult<BuildContext<'a, 'cfg>> {

src/cargo/core/compiler/build_context/target_info.rs

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -655,9 +655,14 @@ fn env_args(
655655
}
656656

657657
/// Collection of information about `rustc` and the host and target.
658-
pub struct RustcTargetData {
658+
pub struct RustcTargetData<'cfg> {
659659
/// Information about `rustc` itself.
660660
pub rustc: Rustc,
661+
662+
/// Config
663+
config: &'cfg Config,
664+
requested_kinds: Vec<CompileKind>,
665+
661666
/// Build information for the "host", which is information about when
662667
/// `rustc` is invoked without a `--target` flag. This is used for
663668
/// procedural macros, build scripts, etc.
@@ -670,27 +675,17 @@ pub struct RustcTargetData {
670675
target_info: HashMap<CompileTarget, TargetInfo>,
671676
}
672677

673-
impl RustcTargetData {
678+
impl<'cfg> RustcTargetData<'cfg> {
674679
pub fn new(
675-
ws: &Workspace<'_>,
680+
ws: &Workspace<'cfg>,
676681
requested_kinds: &[CompileKind],
677-
) -> CargoResult<RustcTargetData> {
682+
) -> CargoResult<RustcTargetData<'cfg>> {
678683
let config = ws.config();
679684
let rustc = config.load_global_rustc(Some(ws))?;
680685
let host_config = config.target_cfg_triple(&rustc.host)?;
681686
let host_info = TargetInfo::new(config, requested_kinds, &rustc, CompileKind::Host)?;
682687
let mut target_config = HashMap::new();
683688
let mut target_info = HashMap::new();
684-
for kind in requested_kinds {
685-
if let CompileKind::Target(target) = *kind {
686-
let tcfg = config.target_cfg_triple(target.short_name())?;
687-
target_config.insert(target, tcfg);
688-
target_info.insert(
689-
target,
690-
TargetInfo::new(config, requested_kinds, &rustc, *kind)?,
691-
);
692-
}
693-
}
694689

695690
// This is a hack. The unit_dependency graph builder "pretends" that
696691
// `CompileKind::Host` is `CompileKind::Target(host)` if the
@@ -703,13 +698,49 @@ impl RustcTargetData {
703698
target_config.insert(ct, host_config.clone());
704699
}
705700

706-
Ok(RustcTargetData {
701+
let mut res = RustcTargetData {
707702
rustc,
703+
config,
704+
requested_kinds: requested_kinds.into(),
708705
host_config,
709706
host_info,
710707
target_config,
711708
target_info,
712-
})
709+
};
710+
711+
// Get all kinds we currently know about.
712+
//
713+
// For now, targets can only ever come from the root workspace
714+
// units as artifact dependencies are not a thing yet, so this
715+
// correctly represents all the kinds that can happen. When we
716+
// have artifact dependencies or other ways for targets to
717+
// appear at places that are not the root units, we may have
718+
// to revisit this.
719+
let all_kinds = requested_kinds
720+
.iter()
721+
.copied()
722+
.chain(ws.members().flat_map(|p| {
723+
p.manifest()
724+
.default_kind()
725+
.into_iter()
726+
.chain(p.manifest().forced_kind())
727+
}));
728+
for kind in all_kinds {
729+
if let CompileKind::Target(target) = kind {
730+
if !res.target_config.contains_key(&target) {
731+
res.target_config
732+
.insert(target, res.config.target_cfg_triple(target.short_name())?);
733+
}
734+
if !res.target_info.contains_key(&target) {
735+
res.target_info.insert(
736+
target,
737+
TargetInfo::new(res.config, &res.requested_kinds, &res.rustc, kind)?,
738+
);
739+
}
740+
}
741+
}
742+
743+
Ok(res)
713744
}
714745

715746
/// Returns a "short" name for the given kind, suitable for keying off

src/cargo/core/compiler/compilation.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,10 @@ impl<'cfg> Compilation<'cfg> {
127127
sysroot_target_libdir: bcx
128128
.all_kinds
129129
.iter()
130-
.map(|kind| {
130+
.map(|&kind| {
131131
(
132-
*kind,
133-
bcx.target_data.info(*kind).sysroot_target_libdir.clone(),
132+
kind,
133+
bcx.target_data.info(kind).sysroot_target_libdir.clone(),
134134
)
135135
})
136136
.collect(),

src/cargo/core/compiler/standard_lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn parse_unstable_flag(value: Option<&str>) -> Vec<String> {
3333
/// Resolve the standard library dependencies.
3434
pub fn resolve_std<'cfg>(
3535
ws: &Workspace<'cfg>,
36-
target_data: &RustcTargetData,
36+
target_data: &RustcTargetData<'cfg>,
3737
requested_targets: &[CompileKind],
3838
crates: &[String],
3939
) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> {
@@ -185,7 +185,7 @@ pub fn generate_std_roots(
185185
Ok(ret)
186186
}
187187

188-
fn detect_sysroot_src_path(target_data: &RustcTargetData) -> CargoResult<PathBuf> {
188+
fn detect_sysroot_src_path(target_data: &RustcTargetData<'_>) -> CargoResult<PathBuf> {
189189
if let Some(s) = env::var_os("__CARGO_TESTS_ONLY_SRC_ROOT") {
190190
return Ok(s.into());
191191
}

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ struct State<'a, 'cfg> {
4444
/// library.
4545
is_std: bool,
4646
global_mode: CompileMode,
47-
target_data: &'a RustcTargetData,
47+
target_data: &'a RustcTargetData<'cfg>,
4848
profiles: &'a Profiles,
4949
interner: &'a UnitInterner,
5050

@@ -63,7 +63,7 @@ pub fn build_unit_dependencies<'a, 'cfg>(
6363
roots: &[Unit],
6464
std_roots: &HashMap<CompileKind, Vec<Unit>>,
6565
global_mode: CompileMode,
66-
target_data: &'a RustcTargetData,
66+
target_data: &'a RustcTargetData<'cfg>,
6767
profiles: &'a Profiles,
6868
interner: &'a UnitInterner,
6969
) -> CargoResult<UnitGraph> {

src/cargo/core/features.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,9 @@ features! {
390390

391391
// Support for 2021 edition.
392392
(unstable, edition2021, "", "reference/unstable.html#edition-2021"),
393+
394+
// Allow to specify per-package targets (compile kinds)
395+
(unstable, per_package_target, "", "reference/unstable.html#per-package-target"),
393396
}
394397

395398
const PUBLISH_LOCKFILE_REMOVED: &str = "The publish-lockfile key in Cargo.toml \

src/cargo/core/manifest.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use serde::ser;
1111
use serde::Serialize;
1212
use url::Url;
1313

14-
use crate::core::compiler::CrateType;
14+
use crate::core::compiler::{CompileKind, CrateType};
1515
use crate::core::resolver::ResolveBehavior;
1616
use crate::core::{Dependency, PackageId, PackageIdSpec, SourceId, Summary};
1717
use crate::core::{Edition, Feature, Features, WorkspaceConfig};
@@ -32,6 +32,8 @@ pub enum EitherManifest {
3232
pub struct Manifest {
3333
summary: Summary,
3434
targets: Vec<Target>,
35+
default_kind: Option<CompileKind>,
36+
forced_kind: Option<CompileKind>,
3537
links: Option<String>,
3638
warnings: Warnings,
3739
exclude: Vec<String>,
@@ -366,6 +368,8 @@ compact_debug! {
366368
impl Manifest {
367369
pub fn new(
368370
summary: Summary,
371+
default_kind: Option<CompileKind>,
372+
forced_kind: Option<CompileKind>,
369373
targets: Vec<Target>,
370374
exclude: Vec<String>,
371375
include: Vec<String>,
@@ -388,6 +392,8 @@ impl Manifest {
388392
) -> Manifest {
389393
Manifest {
390394
summary,
395+
default_kind,
396+
forced_kind,
391397
targets,
392398
warnings: Warnings::new(),
393399
exclude,
@@ -414,6 +420,12 @@ impl Manifest {
414420
pub fn dependencies(&self) -> &[Dependency] {
415421
self.summary.dependencies()
416422
}
423+
pub fn default_kind(&self) -> Option<CompileKind> {
424+
self.default_kind
425+
}
426+
pub fn forced_kind(&self) -> Option<CompileKind> {
427+
self.forced_kind
428+
}
417429
pub fn exclude(&self) -> &[String] {
418430
&self.exclude
419431
}
@@ -503,6 +515,15 @@ impl Manifest {
503515
})?;
504516
}
505517

518+
if self.default_kind.is_some() || self.forced_kind.is_some() {
519+
self.unstable_features
520+
.require(Feature::per_package_target())
521+
.with_context(|| {
522+
"the `package.default-target` and `package.forced-target` \
523+
manifest keys are unstable and may not work properly"
524+
})?;
525+
}
526+
506527
Ok(())
507528
}
508529

src/cargo/core/package.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ impl<'cfg> PackageSet<'cfg> {
500500
root_ids: &[PackageId],
501501
has_dev_units: HasDevUnits,
502502
requested_kinds: &[CompileKind],
503-
target_data: &RustcTargetData,
503+
target_data: &RustcTargetData<'cfg>,
504504
force_all_targets: ForceAllTargets,
505505
) -> CargoResult<()> {
506506
fn collect_used_deps(
@@ -509,7 +509,7 @@ impl<'cfg> PackageSet<'cfg> {
509509
pkg_id: PackageId,
510510
has_dev_units: HasDevUnits,
511511
requested_kinds: &[CompileKind],
512-
target_data: &RustcTargetData,
512+
target_data: &RustcTargetData<'_>,
513513
force_all_targets: ForceAllTargets,
514514
) -> CargoResult<()> {
515515
if !used.insert(pkg_id) {

src/cargo/core/resolver/features.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ pub struct FeatureDifferences {
414414

415415
pub struct FeatureResolver<'a, 'cfg> {
416416
ws: &'a Workspace<'cfg>,
417-
target_data: &'a RustcTargetData,
417+
target_data: &'a RustcTargetData<'cfg>,
418418
/// The platforms to build for, requested by the user.
419419
requested_targets: &'a [CompileKind],
420420
resolve: &'a Resolve,
@@ -452,7 +452,7 @@ impl<'a, 'cfg> FeatureResolver<'a, 'cfg> {
452452
/// with the result.
453453
pub fn resolve(
454454
ws: &Workspace<'cfg>,
455-
target_data: &RustcTargetData,
455+
target_data: &RustcTargetData<'cfg>,
456456
resolve: &Resolve,
457457
package_set: &'a PackageSet<'cfg>,
458458
cli_features: &CliFeatures,

src/cargo/ops/cargo_compile.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,11 +467,17 @@ pub fn create_bcx<'a, 'cfg>(
467467
})
468468
.collect();
469469

470+
// Passing `build_config.requested_kinds` instead of
471+
// `explicit_host_kinds` here so that `generate_targets` can do
472+
// its own special handling of `CompileKind::Host`. It will
473+
// internally replace the host kind by the `explicit_host_kind`
474+
// before setting as a unit.
470475
let mut units = generate_targets(
471476
ws,
472477
&to_builds,
473478
filter,
474-
&explicit_host_kinds,
479+
&build_config.requested_kinds,
480+
explicit_host_kind,
475481
build_config.mode,
476482
&resolve,
477483
&workspace_resolve,
@@ -842,6 +848,7 @@ fn generate_targets(
842848
packages: &[&Package],
843849
filter: &CompileFilter,
844850
requested_kinds: &[CompileKind],
851+
explicit_host_kind: CompileKind,
845852
mode: CompileMode,
846853
resolve: &Resolve,
847854
workspace_resolve: &Option<Resolve>,
@@ -915,7 +922,27 @@ fn generate_targets(
915922
let features_for = FeaturesFor::from_for_host(target.proc_macro());
916923
let features = resolved_features.activated_features(pkg.package_id(), features_for);
917924

918-
for kind in requested_kinds {
925+
// If `--target` has not been specified, then the unit
926+
// graph is built almost like if `--target $HOST` was
927+
// specified. See `rebuild_unit_graph_shared` for more on
928+
// why this is done. However, if the package has its own
929+
// `package.target` key, then this gets used instead of
930+
// `$HOST`
931+
let explicit_kinds = if let Some(k) = pkg.manifest().forced_kind() {
932+
vec![k]
933+
} else {
934+
requested_kinds
935+
.iter()
936+
.map(|kind| match kind {
937+
CompileKind::Host => {
938+
pkg.manifest().default_kind().unwrap_or(explicit_host_kind)
939+
}
940+
CompileKind::Target(t) => CompileKind::Target(*t),
941+
})
942+
.collect()
943+
};
944+
945+
for kind in explicit_kinds.iter() {
919946
let profile = profiles.get_profile(
920947
pkg.package_id(),
921948
ws.is_member(pkg),

src/cargo/ops/cargo_output_metadata.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ fn build_resolve_graph_r(
171171
pkg_id: PackageId,
172172
resolve: &Resolve,
173173
package_map: &BTreeMap<PackageId, Package>,
174-
target_data: &RustcTargetData,
174+
target_data: &RustcTargetData<'_>,
175175
requested_kinds: &[CompileKind],
176176
) {
177177
if node_map.contains_key(&pkg_id) {

src/cargo/ops/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ pub fn resolve_ws<'a>(ws: &Workspace<'a>) -> CargoResult<(PackageSet<'a>, Resolv
7979
/// members. In this case, `opts.all_features` must be `true`.
8080
pub fn resolve_ws_with_opts<'cfg>(
8181
ws: &Workspace<'cfg>,
82-
target_data: &RustcTargetData,
82+
target_data: &RustcTargetData<'cfg>,
8383
requested_targets: &[CompileKind],
8484
cli_features: &CliFeatures,
8585
specs: &[PackageIdSpec],

0 commit comments

Comments
 (0)