Implement interrupt handling for long-running commands and archive extraction
- Added an `interrupts` module to manage Ctrl-C signals and propagate them to child processes. - Refactored archive extraction functions to check for interrupts and handle them gracefully. - Introduced `copy_interruptibly` function to allow for interruptible copying of data. - Updated various source files to utilize the new interrupt handling functions, ensuring that commands and archive extractions can be interrupted by the user. - Added tests to verify the interrupt functionality during copying and tar extraction. - Introduced a new Meson option for generating HTML CLI documentation. - Enhanced the `PackageSpec` struct to support additional Rust LTO flags.
This commit is contained in:
+21
-20
@@ -128,8 +128,7 @@ pub fn build(
|
||||
configure_cmd.arg(expanded);
|
||||
}
|
||||
|
||||
let status = configure_cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut configure_cmd)
|
||||
.with_context(|| format!("Failed to run configure in {}", build_dir.display()))?;
|
||||
|
||||
if !status.success() {
|
||||
@@ -164,7 +163,7 @@ pub fn build(
|
||||
|
||||
crate::builder::prepare_tool_command(&mut make_cmd, &env_vars);
|
||||
|
||||
let status = make_cmd.status().with_context(|| {
|
||||
let status = crate::interrupts::command_status(&mut make_cmd).with_context(|| {
|
||||
format!("Failed to run {} in {}", make_exec, make_dir.display())
|
||||
})?;
|
||||
|
||||
@@ -216,14 +215,15 @@ pub fn build(
|
||||
crate::builder::prepare_tool_command(&mut test_cmd, &env_vars);
|
||||
|
||||
let test_targets_display = test_targets.join(" ");
|
||||
let status = test_cmd.status().with_context(|| {
|
||||
format!(
|
||||
"Failed to run {} {} in {}",
|
||||
make_exec,
|
||||
test_targets_display,
|
||||
test_dir.display()
|
||||
)
|
||||
})?;
|
||||
let status =
|
||||
crate::interrupts::command_status(&mut test_cmd).with_context(|| {
|
||||
format!(
|
||||
"Failed to run {} {} in {}",
|
||||
make_exec,
|
||||
test_targets_display,
|
||||
test_dir.display()
|
||||
)
|
||||
})?;
|
||||
if !status.success() {
|
||||
anyhow::bail!(
|
||||
"{} {} failed with status: {} (dir: {})",
|
||||
@@ -344,15 +344,16 @@ pub fn build(
|
||||
));
|
||||
crate::builder::prepare_tool_command(&mut install_cmd, &install_env);
|
||||
|
||||
let status = install_cmd.status().with_context(|| {
|
||||
format!(
|
||||
"Failed to run {} {} for {} in {}",
|
||||
make_exec,
|
||||
install_targets.join(" "),
|
||||
spec.package.name,
|
||||
install_dir.display()
|
||||
)
|
||||
})?;
|
||||
let status =
|
||||
crate::interrupts::command_status(&mut install_cmd).with_context(|| {
|
||||
format!(
|
||||
"Failed to run {} {} for {} in {}",
|
||||
make_exec,
|
||||
install_targets.join(" "),
|
||||
spec.package.name,
|
||||
install_dir.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
if !status.success() {
|
||||
anyhow::bail!(
|
||||
|
||||
+117
-13
@@ -63,6 +63,9 @@ pub fn build(
|
||||
for arg in cmake_install_dir_args(flags) {
|
||||
cmake_cmd.arg(arg);
|
||||
}
|
||||
for arg in cmake_lib32_target_args(flags, cross) {
|
||||
cmake_cmd.arg(arg);
|
||||
}
|
||||
|
||||
// Add toolchain file for cross-compilation
|
||||
if let Some(ref tf) = toolchain_file {
|
||||
@@ -90,7 +93,8 @@ pub fn build(
|
||||
|
||||
crate::builder::prepare_tool_command(&mut cmake_cmd, &env_vars);
|
||||
|
||||
let status = cmake_cmd.status().context("Failed to run cmake")?;
|
||||
let status =
|
||||
crate::interrupts::command_status(&mut cmake_cmd).context("Failed to run cmake")?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("cmake configure failed");
|
||||
}
|
||||
@@ -117,8 +121,7 @@ pub fn build(
|
||||
|
||||
crate::builder::prepare_tool_command(&mut build_cmd, &env_vars);
|
||||
|
||||
let status = build_cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut build_cmd)
|
||||
.with_context(|| format!("Failed to run cmake build for {}", spec.package.name))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("cmake build failed");
|
||||
@@ -139,12 +142,13 @@ pub fn build(
|
||||
}
|
||||
crate::builder::prepare_tool_command(&mut test_cmd, &env_vars);
|
||||
|
||||
let status = test_cmd.status().with_context(|| {
|
||||
format!(
|
||||
"Failed to run cmake build target(s) '{}' for {}",
|
||||
joined, spec.package.name
|
||||
)
|
||||
})?;
|
||||
let status =
|
||||
crate::interrupts::command_status(&mut test_cmd).with_context(|| {
|
||||
format!(
|
||||
"Failed to run cmake build target(s) '{}' for {}",
|
||||
joined, spec.package.name
|
||||
)
|
||||
})?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("cmake test target(s) '{}' failed", joined);
|
||||
}
|
||||
@@ -157,8 +161,7 @@ pub fn build(
|
||||
test_cmd.arg("--output-on-failure");
|
||||
crate::builder::prepare_tool_command(&mut test_cmd, &env_vars);
|
||||
|
||||
let status = test_cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut test_cmd)
|
||||
.with_context(|| format!("Failed to run ctest for {}", spec.package.name))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("ctest failed");
|
||||
@@ -203,8 +206,7 @@ pub fn build(
|
||||
));
|
||||
crate::builder::prepare_tool_command(&mut install_cmd, &install_env);
|
||||
|
||||
let status = install_cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut install_cmd)
|
||||
.with_context(|| format!("Failed to run cmake install for {}", spec.package.name))?;
|
||||
if !status.success() {
|
||||
if !install_targets.is_empty() {
|
||||
@@ -378,6 +380,55 @@ fn cmake_install_dir_args(flags: &crate::package::BuildFlags) -> Vec<String> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn cmake_lib32_target_args(
|
||||
flags: &crate::package::BuildFlags,
|
||||
cross: Option<&CrossConfig>,
|
||||
) -> Vec<String> {
|
||||
if !flags.lib32_variant {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let target = match lib32_target_triple(flags, cross) {
|
||||
Some(target) => target,
|
||||
None => return Vec::new(),
|
||||
};
|
||||
let arch = crate::cross::target_arch_from_triple(&target);
|
||||
let defaults = [
|
||||
("CMAKE_SYSTEM_PROCESSOR", arch.to_string()),
|
||||
("CMAKE_C_COMPILER_TARGET", target.clone()),
|
||||
("CMAKE_CXX_COMPILER_TARGET", target.clone()),
|
||||
("CMAKE_ASM_COMPILER_TARGET", target),
|
||||
];
|
||||
|
||||
defaults
|
||||
.into_iter()
|
||||
.filter(|(variable, _)| cmake_cache_entry_value(&flags.configure, variable).is_none())
|
||||
.map(|(variable, value)| format!("-D{variable}={value}"))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn lib32_target_triple(
|
||||
flags: &crate::package::BuildFlags,
|
||||
cross: Option<&CrossConfig>,
|
||||
) -> Option<String> {
|
||||
let host = if let Some(cc_cfg) = cross {
|
||||
Some(cc_cfg.host_triple().to_string())
|
||||
} else if !flags.chost.trim().is_empty() {
|
||||
Some(flags.chost.trim().to_string())
|
||||
} else {
|
||||
let detected = CrossConfig::build_triple();
|
||||
if let Err(err) = &detected {
|
||||
crate::log_warn!(
|
||||
"Failed to detect native build triple for lib32 CMake target flags: {}",
|
||||
err
|
||||
);
|
||||
}
|
||||
detected.ok()
|
||||
};
|
||||
|
||||
host.map(|host| crate::cross::lib32_target_triple(&host))
|
||||
}
|
||||
|
||||
fn cmake_install_dir_value(prefix: &str, value: &str) -> String {
|
||||
let trimmed_prefix = prefix.trim();
|
||||
let trimmed_value = value.trim();
|
||||
@@ -610,6 +661,59 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cmake_lib32_target_args_include_compiler_target_defaults() {
|
||||
let flags = BuildFlags {
|
||||
lib32_variant: true,
|
||||
chost: "x86_64-sfg-linux-gnu".into(),
|
||||
..BuildFlags::default()
|
||||
};
|
||||
|
||||
let args = cmake_lib32_target_args(&flags, None);
|
||||
assert!(args.iter().any(|a| a == "-DCMAKE_SYSTEM_PROCESSOR=i686"));
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_C_COMPILER_TARGET=i686-sfg-linux-gnu")
|
||||
);
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_CXX_COMPILER_TARGET=i686-sfg-linux-gnu")
|
||||
);
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_ASM_COMPILER_TARGET=i686-sfg-linux-gnu")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cmake_lib32_target_args_respect_explicit_overrides() {
|
||||
let flags = BuildFlags {
|
||||
lib32_variant: true,
|
||||
chost: "x86_64-sfg-linux-gnu".into(),
|
||||
configure: vec![
|
||||
"-DCMAKE_C_COMPILER_TARGET=i686-custom-linux-gnu".into(),
|
||||
"-DCMAKE_SYSTEM_PROCESSOR=i686".into(),
|
||||
],
|
||||
..BuildFlags::default()
|
||||
};
|
||||
|
||||
let args = cmake_lib32_target_args(&flags, None);
|
||||
assert!(
|
||||
!args
|
||||
.iter()
|
||||
.any(|a| a.starts_with("-DCMAKE_C_COMPILER_TARGET="))
|
||||
);
|
||||
assert!(
|
||||
!args
|
||||
.iter()
|
||||
.any(|a| a.starts_with("-DCMAKE_SYSTEM_PROCESSOR="))
|
||||
);
|
||||
assert!(
|
||||
args.iter()
|
||||
.any(|a| a == "-DCMAKE_CXX_COMPILER_TARGET=i686-sfg-linux-gnu")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cmake_install_dir_args_respect_explicit_user_overrides() {
|
||||
let flags = BuildFlags {
|
||||
|
||||
@@ -131,7 +131,7 @@ pub fn build(
|
||||
crate::builder::prepare_tool_command(&mut cmd, &env_vars);
|
||||
|
||||
// Run the command and include the OS error on spawn failures for clearer diagnostics
|
||||
let status = cmd.status().map_err(|e| {
|
||||
let status = crate::interrupts::command_status(&mut cmd).map_err(|e| {
|
||||
anyhow::anyhow!(
|
||||
"Failed to run build script {}: {}",
|
||||
build_script.display(),
|
||||
|
||||
@@ -48,8 +48,7 @@ pub fn build(
|
||||
cmd.current_dir(src_dir);
|
||||
crate::builder::prepare_tool_command(&mut cmd, &env_vars);
|
||||
|
||||
let status = cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut cmd)
|
||||
.with_context(|| format!("Failed to run build command: {}", cmd_str))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("Build command failed: {}", cmd_str);
|
||||
@@ -89,8 +88,7 @@ pub fn build(
|
||||
));
|
||||
crate::builder::prepare_tool_command(&mut cmd, &install_env);
|
||||
|
||||
let status = cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut cmd)
|
||||
.with_context(|| format!("Failed to run install command: {}", cmd_str))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("Install command failed: {}", cmd_str);
|
||||
|
||||
+154
-8
@@ -29,9 +29,12 @@ pub fn build(
|
||||
// Environment variables
|
||||
let env_vars = crate::builder::standard_build_env(spec, cross, true, export_compiler_flags);
|
||||
|
||||
// Generate cross file if cross-compiling
|
||||
// Generate cross file if cross-compiling, or when the lib32 variant needs
|
||||
// Meson to treat the build as x86 instead of the native x86_64 host.
|
||||
let cross_file = if let Some(cc_cfg) = cross {
|
||||
Some(cc_cfg.generate_meson_cross_file(&build_dir)?)
|
||||
} else if flags.lib32_variant {
|
||||
Some(generate_lib32_meson_cross_file(flags, &build_dir)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -56,7 +59,8 @@ pub fn build(
|
||||
|
||||
crate::builder::prepare_tool_command(&mut meson_cmd, &env_vars);
|
||||
|
||||
let status = meson_cmd.status().context("Failed to run meson setup")?;
|
||||
let status = crate::interrupts::command_status(&mut meson_cmd)
|
||||
.context("Failed to run meson setup")?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("meson setup failed");
|
||||
}
|
||||
@@ -76,8 +80,7 @@ pub fn build(
|
||||
|
||||
crate::builder::prepare_tool_command(&mut ninja_cmd, &env_vars);
|
||||
|
||||
let status = ninja_cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut ninja_cmd)
|
||||
.with_context(|| format!("Failed to run ninja for {}", spec.package.name))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("ninja build failed");
|
||||
@@ -105,8 +108,7 @@ pub fn build(
|
||||
|
||||
crate::builder::prepare_tool_command(&mut test_cmd, &env_vars);
|
||||
|
||||
let status = test_cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut test_cmd)
|
||||
.with_context(|| format!("Failed to run meson test for {}", spec.package.name))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("meson test failed");
|
||||
@@ -141,8 +143,7 @@ pub fn build(
|
||||
));
|
||||
crate::builder::prepare_tool_command(&mut install_cmd, &install_env);
|
||||
|
||||
let status = install_cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut install_cmd)
|
||||
.with_context(|| format!("Failed to run meson install for {}", spec.package.name))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("meson install failed");
|
||||
@@ -258,6 +259,109 @@ fn meson_setup_args(
|
||||
args
|
||||
}
|
||||
|
||||
fn generate_lib32_meson_cross_file(
|
||||
flags: &crate::package::BuildFlags,
|
||||
build_dir: &Path,
|
||||
) -> Result<PathBuf> {
|
||||
let target = lib32_target_triple(flags);
|
||||
let arch = crate::cross::target_arch_from_triple(&target);
|
||||
let cpu_family = crate::cross::cpu_family_for_arch(arch);
|
||||
let c = meson_binary_value(
|
||||
&compiler_command_with_lib32_target(&flags.cc, &target),
|
||||
"C compiler",
|
||||
)?;
|
||||
let cpp = meson_binary_value(
|
||||
&compiler_command_with_lib32_target(&flags.cxx, &target),
|
||||
"C++ compiler",
|
||||
)?;
|
||||
let ar = meson_binary_value(&command_words(&flags.ar), "archiver")?;
|
||||
|
||||
let mut content = format!(
|
||||
"# Meson cross file for lib32 builds\n# Generated by depot for target: {target}\n\n[binaries]\nc = {c}\ncpp = {cpp}\nar = {ar}\n"
|
||||
);
|
||||
if !flags.ld.trim().is_empty() {
|
||||
let ld = meson_binary_value(&command_words(&flags.ld), "linker")?;
|
||||
content.push_str(&format!("ld = {ld}\n"));
|
||||
}
|
||||
content.push_str(&format!(
|
||||
"\n[host_machine]\nsystem = 'linux'\ncpu_family = '{cpu_family}'\ncpu = '{arch}'\nendian = 'little'\n"
|
||||
));
|
||||
|
||||
fs::create_dir_all(build_dir)?;
|
||||
let cross_path = build_dir.join("lib32-cross-file.ini");
|
||||
fs::write(&cross_path, content)
|
||||
.with_context(|| format!("Failed to write {}", cross_path.display()))?;
|
||||
Ok(cross_path)
|
||||
}
|
||||
|
||||
fn lib32_target_triple(flags: &crate::package::BuildFlags) -> String {
|
||||
let host = if !flags.chost.trim().is_empty() {
|
||||
flags.chost.trim().to_string()
|
||||
} else {
|
||||
match CrossConfig::build_triple() {
|
||||
Ok(triple) => triple,
|
||||
Err(err) => {
|
||||
crate::log_warn!(
|
||||
"Failed to detect native build triple for lib32 Meson target file: {}",
|
||||
err
|
||||
);
|
||||
"x86_64-unknown-linux-gnu".to_string()
|
||||
}
|
||||
}
|
||||
};
|
||||
crate::cross::lib32_target_triple(&host)
|
||||
}
|
||||
|
||||
fn compiler_command_with_lib32_target(command: &str, target: &str) -> Vec<String> {
|
||||
let mut parts = command_words(command);
|
||||
if compiler_command_supports_target(&parts) && !compiler_command_has_target(&parts) {
|
||||
parts.push(format!("--target={target}"));
|
||||
}
|
||||
parts
|
||||
}
|
||||
|
||||
fn command_words(command: &str) -> Vec<String> {
|
||||
command
|
||||
.split_whitespace()
|
||||
.filter(|part| !part.is_empty())
|
||||
.map(ToString::to_string)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn compiler_command_supports_target(parts: &[String]) -> bool {
|
||||
parts.first().is_some_and(|tool| {
|
||||
Path::new(tool)
|
||||
.file_name()
|
||||
.and_then(|name| name.to_str())
|
||||
.is_some_and(|name| name.contains("clang"))
|
||||
})
|
||||
}
|
||||
|
||||
fn compiler_command_has_target(parts: &[String]) -> bool {
|
||||
parts.iter().any(|part| {
|
||||
part == "--target"
|
||||
|| part == "-target"
|
||||
|| part.starts_with("--target=")
|
||||
|| part.starts_with("-target=")
|
||||
})
|
||||
}
|
||||
|
||||
fn meson_binary_value(parts: &[String], label: &str) -> Result<String> {
|
||||
if parts.is_empty() {
|
||||
anyhow::bail!("Missing {} command for lib32 Meson cross file", label);
|
||||
}
|
||||
|
||||
let rendered = parts
|
||||
.iter()
|
||||
.map(|part| format!("'{}'", part.replace('\\', "\\\\").replace('\'', "\\'")))
|
||||
.collect::<Vec<_>>();
|
||||
if rendered.len() == 1 {
|
||||
Ok(rendered[0].clone())
|
||||
} else {
|
||||
Ok(format!("[{}]", rendered.join(", ")))
|
||||
}
|
||||
}
|
||||
|
||||
/// Expand environment variables in a string (e.g., $DEPOT_SYSROOT)
|
||||
fn expand_env_vars(input: &str) -> String {
|
||||
let mut result = input.to_string();
|
||||
@@ -439,6 +543,48 @@ mod tests {
|
||||
assert!(!args.iter().any(|a| a == "-Dcpp_ld=ld.lld"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compiler_command_with_lib32_target_adds_clang_target() {
|
||||
let parts = compiler_command_with_lib32_target("clang -m32", "i686-sfg-linux-gnu");
|
||||
assert_eq!(
|
||||
parts,
|
||||
vec![
|
||||
"clang".to_string(),
|
||||
"-m32".to_string(),
|
||||
"--target=i686-sfg-linux-gnu".to_string()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compiler_command_with_lib32_target_skips_non_clang_compilers() {
|
||||
let parts = compiler_command_with_lib32_target("gcc -m32", "i686-sfg-linux-gnu");
|
||||
assert_eq!(parts, vec!["gcc".to_string(), "-m32".to_string()]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_lib32_meson_cross_file_sets_x86_host_machine() -> Result<()> {
|
||||
let tmp = tempdir()?;
|
||||
let flags = BuildFlags {
|
||||
lib32_variant: true,
|
||||
chost: "x86_64-sfg-linux-gnu".to_string(),
|
||||
cc: "clang -m32".to_string(),
|
||||
cxx: "clang++ -m32".to_string(),
|
||||
ar: "llvm-ar".to_string(),
|
||||
ld: "ld.lld".to_string(),
|
||||
..BuildFlags::default()
|
||||
};
|
||||
|
||||
let path = generate_lib32_meson_cross_file(&flags, tmp.path())?;
|
||||
let content = fs::read_to_string(path)?;
|
||||
assert!(content.contains("Generated by depot for target: i686-sfg-linux-gnu"));
|
||||
assert!(content.contains("c = ['clang', '-m32', '--target=i686-sfg-linux-gnu']"));
|
||||
assert!(content.contains("cpp = ['clang++', '-m32', '--target=i686-sfg-linux-gnu']"));
|
||||
assert!(content.contains("cpu_family = 'x86'"));
|
||||
assert!(content.contains("cpu = 'i686'"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_resolve_build_dir_uses_flag() {
|
||||
let flags = BuildFlags {
|
||||
|
||||
+40
-2
@@ -194,12 +194,21 @@ fn compiler_flag_sets(
|
||||
(cflags, cxxflags, ldflags, ltoflags)
|
||||
}
|
||||
|
||||
fn rust_ltoflags(flags: &crate::package::BuildFlags) -> Vec<String> {
|
||||
sanitize_flag_list(flags.rustltoflags.clone(), "build.flags.rustltoflags")
|
||||
}
|
||||
|
||||
pub(crate) fn effective_rustflags(flags: &crate::package::BuildFlags) -> Vec<String> {
|
||||
replaced_flags(
|
||||
let mut rustflags = replaced_flags(
|
||||
&flags.rustflags,
|
||||
&flags.replace_rustflags,
|
||||
"build.flags.rustflags",
|
||||
)
|
||||
);
|
||||
let rust_ltoflags = rust_ltoflags(flags);
|
||||
if flags.use_lto && !rust_ltoflags.is_empty() {
|
||||
rustflags.extend(rust_ltoflags);
|
||||
}
|
||||
rustflags
|
||||
}
|
||||
|
||||
pub fn standard_build_env(
|
||||
@@ -224,6 +233,10 @@ pub fn standard_build_env(
|
||||
if !ltoflags.is_empty() {
|
||||
set_env_var(&mut env_vars, "LTOFLAGS", ltoflags.join(" "));
|
||||
}
|
||||
let rust_ltoflags = rust_ltoflags(flags);
|
||||
if !rust_ltoflags.is_empty() {
|
||||
set_env_var(&mut env_vars, "RUSTLTOFLAGS", rust_ltoflags.join(" "));
|
||||
}
|
||||
|
||||
let ldflags = if !ldflags.is_empty() || !flags.libc.is_empty() {
|
||||
if flags.libc.is_empty() {
|
||||
@@ -717,6 +730,7 @@ mod tests {
|
||||
let mut spec = mk_spec(vec!["-O2"], vec!["-Wl,--as-needed"]);
|
||||
spec.build.flags.cxxflags = vec!["-O2".into()];
|
||||
spec.build.flags.ltoflags = vec!["-flto=auto".into()];
|
||||
spec.build.flags.rustltoflags = vec!["-Clinker-plugin-lto".into()];
|
||||
spec.build.flags.use_lto = false;
|
||||
|
||||
let env = standard_build_env(&spec, None, true, true);
|
||||
@@ -738,6 +752,12 @@ mod tests {
|
||||
.any(|(k, v)| k == "LTOFLAGS" && v == "-flto=auto"),
|
||||
"expected LTOFLAGS variable to be exported even when use_lto is false"
|
||||
);
|
||||
assert!(
|
||||
env.iter()
|
||||
.any(|(k, v)| k == "RUSTLTOFLAGS" && v == "-Clinker-plugin-lto"),
|
||||
"expected RUSTLTOFLAGS variable to be exported even when use_lto is false"
|
||||
);
|
||||
assert_eq!(effective_rustflags(&spec.build.flags), Vec::<String>::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -778,6 +798,24 @@ mod tests {
|
||||
assert_eq!(effective_rustflags(&flags), vec!["-C", "opt-level=2"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_effective_rustflags_appends_rustltoflags_when_enabled() {
|
||||
let mut flags = BuildFlags::default();
|
||||
flags.rustflags = vec!["-C".into(), "opt-level=3".into()];
|
||||
flags.rustltoflags = vec!["-Clinker-plugin-lto".into(), "-Cembed-bitcode=yes".into()];
|
||||
flags.use_lto = true;
|
||||
|
||||
assert_eq!(
|
||||
effective_rustflags(&flags),
|
||||
vec![
|
||||
"-C",
|
||||
"opt-level=3",
|
||||
"-Clinker-plugin-lto",
|
||||
"-Cembed-bitcode=yes"
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standard_build_env_passthrough_does_not_override_default_vars() {
|
||||
let mut spec = mk_spec(Vec::new(), Vec::new());
|
||||
|
||||
+2
-2
@@ -267,7 +267,7 @@ fn resolve_perl_configure_script(spec: &PackageSpec, actual_src: &Path) -> PathB
|
||||
}
|
||||
|
||||
fn command_status_with_sh_fallback(cmd: &mut Command) -> std::io::Result<std::process::ExitStatus> {
|
||||
match cmd.status() {
|
||||
match crate::interrupts::command_status(cmd) {
|
||||
Ok(status) => Ok(status),
|
||||
Err(err) if err.kind() == std::io::ErrorKind::PermissionDenied => {
|
||||
let Some(script) = resolved_script_path(cmd) else {
|
||||
@@ -296,7 +296,7 @@ fn command_status_with_sh_fallback(cmd: &mut Command) -> std::io::Result<std::pr
|
||||
}
|
||||
}
|
||||
}
|
||||
fallback.status()
|
||||
crate::interrupts::command_status(&mut fallback)
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
|
||||
@@ -273,8 +273,7 @@ fn build_wheel_setup_py(
|
||||
.arg(dist_dir);
|
||||
crate::builder::prepare_tool_command(&mut cmd, &env_vars.to_vec());
|
||||
|
||||
let status = cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut cmd)
|
||||
.with_context(|| format!("Failed to run setup.py in {}", src_dir.display()))?;
|
||||
if !status.success() {
|
||||
bail!("setup.py bdist_wheel failed with status {}", status);
|
||||
@@ -315,25 +314,23 @@ fn build_wheel_pep517(
|
||||
);
|
||||
crate::builder::prepare_command(&mut cmd, &build_env);
|
||||
|
||||
let output = cmd.output().with_context(|| {
|
||||
let status = crate::interrupts::command_status(&mut cmd).with_context(|| {
|
||||
format!(
|
||||
"Failed to run python3 for PEP 517 build in {}",
|
||||
src_dir.display()
|
||||
)
|
||||
})?;
|
||||
if !output.status.success() {
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
if !status.success() {
|
||||
let requires = if cfg.requires.is_empty() {
|
||||
"(none declared)".to_string()
|
||||
} else {
|
||||
cfg.requires.join(", ")
|
||||
};
|
||||
bail!(
|
||||
"PEP 517 wheel build failed with status {}. Backend: {}. Declared build requirements: {}. stderr: {}",
|
||||
output.status,
|
||||
"PEP 517 wheel build failed with status {}. Backend: {}. Declared build requirements: {}",
|
||||
status,
|
||||
cfg.backend,
|
||||
requires,
|
||||
stderr.trim()
|
||||
requires
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -102,8 +102,7 @@ pub fn build(
|
||||
// Set environment
|
||||
crate::builder::prepare_tool_command(&mut cargo_cmd, &env_vars);
|
||||
|
||||
let status = cargo_cmd
|
||||
.status()
|
||||
let status = crate::interrupts::command_status(&mut cargo_cmd)
|
||||
.with_context(|| format!("Failed to run cargo build for {}", spec.package.name))?;
|
||||
if !status.success() {
|
||||
anyhow::bail!("cargo build failed");
|
||||
|
||||
Reference in New Issue
Block a user