Skip to content

Commit e87ec1a

Browse files
authored
Accessing each build script's OUT_DIR and in the correct order (#15776)
Hi Everyone! This PR is aimed to have some improvements over #15704 ### What does this PR try to resolve? Now, multiple build scripts are built correctly. But there are some underlying issues, that this PR is targeting. - Preserving the order of the build scripts: Earlier the build scripts were sorted by default, but now, the order will be preserved. ### How to test and review this PR? There is a feature gate `multiple-build-scripts` that can be passed via `cargo-features` in `Cargo.toml`. So, you have to add ```toml cargo-features = ["multiple-build-scripts"] ``` Preferably on the top of the `Cargo.toml` and use nightly toolchain to use the feature
2 parents d507fbe + aca513a commit e87ec1a

File tree

2 files changed

+103
-3
lines changed

2 files changed

+103
-3
lines changed

src/cargo/core/compiler/unit_dependencies.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ use crate::core::dependency::{Artifact, ArtifactKind, ArtifactTarget, DepKind};
3030
use crate::core::profiles::{Profile, Profiles, UnitFor};
3131
use crate::core::resolver::Resolve;
3232
use crate::core::resolver::features::{FeaturesFor, ResolvedFeatures};
33-
use crate::core::{Dependency, Package, PackageId, PackageSet, Target, TargetKind, Workspace};
33+
use crate::core::{
34+
Dependency, Feature, Package, PackageId, PackageSet, Target, TargetKind, Workspace,
35+
};
3436
use crate::ops::resolve_all_features;
3537
use crate::util::GlobalContext;
3638
use crate::util::interning::InternedString;
@@ -142,8 +144,27 @@ pub fn build_unit_dependencies<'a, 'gctx>(
142144
// which affect the determinism of the build itself. As a result be sure
143145
// that dependency lists are always sorted to ensure we've always got a
144146
// deterministic output.
145-
for list in state.unit_dependencies.values_mut() {
146-
list.sort();
147+
for (unit, list) in &mut state.unit_dependencies {
148+
let is_multiple_build_scripts_enabled = unit
149+
.pkg
150+
.manifest()
151+
.unstable_features()
152+
.require(Feature::multiple_build_scripts())
153+
.is_ok();
154+
155+
if is_multiple_build_scripts_enabled {
156+
list.sort_by_key(|unit_dep| {
157+
if unit_dep.unit.target.is_custom_build() {
158+
// We do not sort build scripts to preserve the user-defined order.
159+
// In terms of determinism, we are assuming nothing interferes with order from when the user set it in `Cargo.toml` to here
160+
(0, None)
161+
} else {
162+
(1, Some(unit_dep.clone()))
163+
}
164+
});
165+
} else {
166+
list.sort();
167+
}
147168
}
148169
trace!("ALL UNIT DEPENDENCIES {:#?}", state.unit_dependencies);
149170

tests/testsuite/build_scripts_multiple.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,85 @@ Hello, from Build Script 2!
608608
.run();
609609
}
610610

611+
#[cargo_test]
612+
fn build_script_with_conflicts_reverse_sorted() {
613+
// In this, multiple scripts create file with same name in their respective OUT_DIR.
614+
// It is different from above because `package.build` is not sorted in this.
615+
616+
let p = project()
617+
.file(
618+
"Cargo.toml",
619+
r#"
620+
cargo-features = ["multiple-build-scripts"]
621+
622+
[package]
623+
name = "foo"
624+
version = "0.1.0"
625+
edition = "2024"
626+
627+
build = ["build2.rs", "build1.rs"]
628+
"#,
629+
)
630+
// OUT_DIR is set to the lexicographically largest build script's OUT_DIR by default
631+
.file(
632+
"src/main.rs",
633+
r#"
634+
include!(concat!(env!("OUT_DIR"), "/foo.rs"));
635+
fn main() {
636+
println!("{}", message());
637+
}
638+
"#,
639+
)
640+
.file(
641+
"build1.rs",
642+
r#"
643+
use std::env;
644+
use std::fs;
645+
use std::path::Path;
646+
647+
fn main() {
648+
let out_dir = env::var_os("OUT_DIR").unwrap();
649+
let dest_path = Path::new(&out_dir).join("foo.rs");
650+
fs::write(
651+
&dest_path,
652+
"pub fn message() -> &'static str {
653+
\"Hello, from Build Script 1!\"
654+
}
655+
"
656+
).unwrap();
657+
}"#,
658+
)
659+
.file(
660+
"build2.rs",
661+
r#"
662+
use std::env;
663+
use std::fs;
664+
use std::path::Path;
665+
666+
fn main() {
667+
let out_dir = env::var_os("OUT_DIR").unwrap();
668+
let dest_path = Path::new(&out_dir).join("foo.rs");
669+
fs::write(
670+
&dest_path,
671+
"pub fn message() -> &'static str {
672+
\"Hello, from Build Script 2!\"
673+
}
674+
"
675+
).unwrap();
676+
}"#,
677+
)
678+
.build();
679+
680+
p.cargo("run -v")
681+
.masquerade_as_nightly_cargo(&["multiple-build-scripts"])
682+
.with_status(0)
683+
.with_stdout_data(str![[r#"
684+
Hello, from Build Script 1!
685+
686+
"#]])
687+
.run();
688+
}
689+
611690
#[cargo_test]
612691
fn rerun_untracks_other_files() {
613692
let p = project()

0 commit comments

Comments
 (0)