diff --git a/src/cli/clean.rs b/src/cli/clean.rs index 66b73ee..aea2f5f 100644 --- a/src/cli/clean.rs +++ b/src/cli/clean.rs @@ -125,17 +125,27 @@ fn parse_clean_flags(args: &[String]) -> Result { fn clean_from_root(root: &Path, flags: &CleanFlags) -> Result<(), String> { let config = Config::open("./dcr.toml").map_err(|err| err.to_string())?; - let target = flags - .target - .clone() - .or_else(|| { - config - .get("build.target") - .and_then(|v| v.as_str()) - .map(|s| s.trim().to_string()) - .filter(|s| !s.is_empty()) - }) - .or_else(|| Some(default_target_triple())); + let target = flags.target.clone().or_else(|| { + config + .get("build.target") + .and_then(|v| v.as_str()) + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) + }); + let target = match target { + Some(t) => Some(crate::utils::build::normalize_target_os(&t).to_string()), + None if cfg!(target_os = "linux") + || cfg!(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly" + )) => + { + Some(default_target_triple()) + } + None => None, + }; if flags.all && let Some(workspace) = parse_workspace( diff --git a/src/core/build/common.rs b/src/core/build/common.rs index a035ae6..4e5bce5 100644 --- a/src/core/build/common.rs +++ b/src/core/build/common.rs @@ -898,6 +898,9 @@ mod tests { #[test] fn needs_rebuild_header_modified() { + use std::fs::{File, FileTimes}; + use std::time::{Duration, SystemTime}; + let dir = temp_dir("rebuild_header"); let src = dir.join("test.c"); let header = dir.join("test.h"); @@ -906,9 +909,33 @@ mod tests { fs::write(&src, "int main() {}").unwrap(); fs::write(&header, "#define A 1").unwrap(); - std::thread::sleep(std::time::Duration::from_millis(1100)); fs::write(&obj, "").unwrap(); + let past = SystemTime::now() - Duration::from_secs(30); + let now = SystemTime::now(); + let future = now + Duration::from_secs(30); + + let past_t = FileTimes::new().set_modified(past); + File::options() + .write(true) + .open(&src) + .unwrap() + .set_times(past_t) + .unwrap(); + File::options() + .write(true) + .open(&header) + .unwrap() + .set_times(past_t) + .unwrap(); + let now_t = FileTimes::new().set_modified(now); + File::options() + .write(true) + .open(&obj) + .unwrap() + .set_times(now_t) + .unwrap(); + let d_content = format!( "{}: {} {}", obj.to_string_lossy(), @@ -922,8 +949,13 @@ mod tests { "should be fresh" ); - std::thread::sleep(std::time::Duration::from_millis(1100)); - fs::write(&header, "#define A 2").unwrap(); + let future_t = FileTimes::new().set_modified(future); + File::options() + .write(true) + .open(&header) + .unwrap() + .set_times(future_t) + .unwrap(); assert!( needs_rebuild(&src.to_string_lossy(), &obj.to_string_lossy()), diff --git a/tests/cli_build.rs b/tests/cli_build.rs index 7e8b190..28e1eef 100644 --- a/tests/cli_build.rs +++ b/tests/cli_build.rs @@ -89,14 +89,17 @@ fn build_run_clean_flags_normal_project() { let out = run_dcr_env(&["clean", "--release"], &dir, &envs); assert!(out.status.success(), "dcr clean --release should succeed"); - let target_dir = "target/x86_64-unknown-linux-gnu".to_string(); + let release_dir = host_profile_dir(&dir, "release"); + let debug_dir = host_profile_dir(&dir, "debug"); assert!( - !dir.join(&target_dir).join("release").exists(), - "target/x86_64-unknown-linux-gnu/release should be removed" + !release_dir.exists(), + "release profile dir should be removed: {}", + release_dir.display() ); assert!( - dir.join(&target_dir).join("debug").is_dir(), - "target/x86_64-unknown-linux-gnu/debug should remain" + debug_dir.is_dir(), + "debug profile dir should remain: {}", + debug_dir.display() ); let out = run_dcr_env(&["clean"], &dir, &envs); @@ -225,15 +228,12 @@ roots = ["src"] assert!(out.status.success(), "flat-bin nasm build should succeed"); let candidates = [ + host_profile_dir(&dir, "debug").join("boot.bin"), dir.join("target/debug/boot.bin"), - dir.join("target").join(format!( - "{}-unknown-linux-gnu/debug/boot.bin", - std::env::consts::ARCH - )), ]; assert!( candidates.iter().any(|p| p.is_file()), - "expected boot.bin under target/…/debug, candidates: {candidates:?}" + "expected boot.bin under host profile dir, candidates: {candidates:?}" ); } diff --git a/tests/cli_errors.rs b/tests/cli_errors.rs index 2a761d9..4267214 100644 --- a/tests/cli_errors.rs +++ b/tests/cli_errors.rs @@ -74,6 +74,32 @@ fn available_compiler() -> Option<&'static str> { None } +fn host_profile_dir(project_root: &Path, profile: &str) -> PathBuf { + let target = project_root.join("target"); + if cfg!(target_os = "linux") { + let arch = std::env::consts::ARCH; + let env = if cfg!(target_env = "musl") { + "musl" + } else { + "gnu" + }; + target + .join(format!("{arch}-unknown-linux-{env}")) + .join(profile) + } else if cfg!(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly" + )) { + let arch = std::env::consts::ARCH; + let os = std::env::consts::OS; + target.join(format!("{arch}-unknown-{os}")).join(profile) + } else { + target.join(profile) + } +} + // --- Tests --- #[test] @@ -223,25 +249,24 @@ fn clean_specific_profile() { let out = run_dcr(&["init"], &dir); assert!(out.status.success(), "init should succeed"); - // Create target/x86_64-unknown-linux-gnu/debug and release dirs - let target_base = "target/x86_64-unknown-linux-gnu"; - std::fs::create_dir_all(dir.join(target_base).join("debug")).expect("create debug"); - std::fs::write(dir.join(target_base).join("debug").join("dummy.o"), "x").expect("write"); - std::fs::create_dir_all(dir.join(target_base).join("release")).expect("create release"); - std::fs::write(dir.join(target_base).join("release").join("dummy.o"), "x").expect("write"); + let debug_dir = host_profile_dir(&dir, "debug"); + let release_dir = host_profile_dir(&dir, "release"); + std::fs::create_dir_all(&debug_dir).expect("create debug"); + std::fs::write(debug_dir.join("dummy.o"), "x").expect("write"); + std::fs::create_dir_all(&release_dir).expect("create release"); + std::fs::write(release_dir.join("dummy.o"), "x").expect("write"); - // Clean only release let out = run_dcr(&["clean", "--release"], &dir); assert!(out.status.success(), "clean --release should succeed"); assert!( - !dir.join(target_base).join("release").exists(), - "target/x86_64-unknown-linux-gnu/release should be removed" + !release_dir.exists(), + "release profile dir should be removed: {}", + release_dir.display() ); assert!( - dir.join("target/x86_64-unknown-linux-gnu") - .join("debug") - .is_dir(), - "target/x86_64-unknown-linux-gnu/debug should remain" + debug_dir.is_dir(), + "debug profile dir should remain: {}", + debug_dir.display() ); } diff --git a/tests/cli_workspace.rs b/tests/cli_workspace.rs index 6059bcc..e748e71 100644 --- a/tests/cli_workspace.rs +++ b/tests/cli_workspace.rs @@ -56,14 +56,17 @@ fn workspace_build_and_clean_all() { "clean --all should not spam missing member target/: {combined}" ); - let target_dir = "target/x86_64-unknown-linux-gnu"; + let release_dir = host_profile_dir(&root, "release"); + let debug_dir = host_profile_dir(&root, "debug"); assert!( - !root.join(target_dir).join("release").exists(), - "root target/x86_64-unknown-linux-gnu/release should be removed" + !release_dir.exists(), + "root release profile dir should be removed: {}", + release_dir.display() ); assert!( - root.join(target_dir).join("debug").exists(), - "root target/x86_64-unknown-linux-gnu/debug should remain" + debug_dir.exists(), + "root debug profile dir should remain: {}", + debug_dir.display() ); let out = run_dcr_env(&["clean", "--all"], &root, &envs); diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 3019fc1..00fdfda 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -92,10 +92,33 @@ pub fn parse_project_name(toml: &str) -> String { } #[allow(dead_code)] -pub fn default_artifact_path(project_root: &Path, project_name: &str) -> PathBuf { - project_root - .join("target") - .join("x86_64-unknown-linux-gnu") - .join("debug") - .join(project_name) +pub fn host_profile_dir(project_root: &Path, profile: &str) -> PathBuf { + let target = project_root.join("target"); + if cfg!(target_os = "linux") { + let arch = std::env::consts::ARCH; + let env = if cfg!(target_env = "musl") { + "musl" + } else { + "gnu" + }; + target + .join(format!("{arch}-unknown-linux-{env}")) + .join(profile) + } else if cfg!(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly" + )) { + let arch = std::env::consts::ARCH; + let os = std::env::consts::OS; + target.join(format!("{arch}-unknown-{os}")).join(profile) + } else { + target.join(profile) + } +} + +#[allow(dead_code)] +pub fn default_artifact_path(project_root: &Path, project_name: &str) -> PathBuf { + host_profile_dir(project_root, "debug").join(project_name) }