fix(loader): allow parallel compilation on windows

This commit is contained in:
Amaan Qureshi 2025-09-21 16:56:45 -04:00 committed by Amaan Qureshi
parent 24c8feba3e
commit 92efd26380
3 changed files with 24 additions and 12 deletions

View file

@ -74,10 +74,7 @@ jobs:
run: |
printf 'EMSCRIPTEN_VERSION=%s\n' "$(<crates/loader/emscripten-version)" >> $GITHUB_ENV
if [[ '${{ matrix.platform }}' =~ ^windows ]]; then
# Prevent race condition (see #2041)
printf 'RUST_TEST_THREADS=1\n' >> $GITHUB_ENV
elif [[ '${{ matrix.cross }}' == true ]]; then
if [[ '${{ matrix.cross }}' == true ]]; then
for target in armv7-unknown-linux-gnueabihf i686-unknown-linux-gnu powerpc64-unknown-linux-gnu; do
camel_target=${target//-/_}; target_cc=${target/-unknown/}
printf 'CC_%s=%s\n' "$camel_target" "${target_cc/v7/}-gcc"

View file

@ -904,12 +904,27 @@ impl Loader {
let output_path = config.output_path.as_ref().unwrap();
if compiler.is_like_msvc() {
let temp_dir = if compiler.is_like_msvc() {
let out = format!("-out:{}", output_path.to_str().unwrap());
command.arg(if self.debug_build { "-LDd" } else { "-LD" });
command.arg("-utf-8");
// Windows creates intermediate files when compiling (.exp, .lib, .obj), which causes
// issues when multiple processes are compiling in the same directory. This creates a
// temporary directory for those files to go into, which is deleted after compilation.
let temp_dir = output_path.parent().unwrap().join(format!(
"tmp_{}_{:?}",
std::process::id(),
std::thread::current().id()
));
std::fs::create_dir_all(&temp_dir).unwrap();
command.arg(format!("/Fo{}\\", temp_dir.display()));
command.args(cc_config.get_files());
command.arg("-link").arg(out);
command.arg(format!("/IMPLIB:{}.lib", temp_dir.join("temp").display()));
Some(temp_dir)
} else {
command.arg("-Werror=implicit-function-declaration");
if cfg!(any(target_os = "macos", target_os = "ios")) {
@ -921,12 +936,18 @@ impl Loader {
}
command.args(cc_config.get_files());
command.arg("-o").arg(output_path);
}
None
};
let output = command.output().with_context(|| {
format!("Failed to execute the C compiler with the following command:\n{command:?}")
})?;
if let Some(temp_dir) = temp_dir {
let _ = fs::remove_dir_all(temp_dir);
}
FileExt::unlock(lock_file)?;
fs::remove_file(lock_path)?;

View file

@ -73,9 +73,6 @@ pub fn run(args: &Test) -> Result<()> {
.arg("--no-run")
.arg("--message-format=json");
#[cfg(target_os = "windows")]
cargo_cmd.arg("--").arg("--test-threads=1");
let cargo_cmd = cargo_cmd.stdout(Stdio::piped()).spawn()?;
let jq_cmd = Command::new("jq")
@ -103,9 +100,6 @@ pub fn run(args: &Test) -> Result<()> {
}
cargo_cmd.args(&args.args);
#[cfg(target_os = "windows")]
cargo_cmd.arg("--").arg("--test-threads=1");
if args.nocapture {
#[cfg(not(target_os = "windows"))]
cargo_cmd.arg("--");