diff --git a/src/cli/build.rs b/src/cli/build.rs index 5bf8223..ed39098 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -23,9 +23,9 @@ use crate::core::config::Config; use crate::core::deps::{register, resolve_deps}; use crate::core::workspace::parse_workspace; use crate::utils::build::{ - get_bool_with_profile, get_config_opt, get_config_str, get_language_with_profile, - normalize_target_os, parse_version_info, profile_table, resolve_compiler, - resolve_pkg_config_flags, resolve_tool, + default_target_triple, get_bool_with_profile, get_config_opt, get_config_str, + get_language_with_profile, normalize_target_os, parse_version_info, prepend_clang_target_flag, + profile_table, resolve_compiler, resolve_pkg_config_flags, resolve_tool, }; use crate::utils::fs::{check_dir, find_project_root, with_dir}; use crate::utils::log::error; @@ -100,27 +100,7 @@ pub fn build(args: &[String]) -> i32 { } } if flags.target.is_none() { - let default_target = if cfg!(target_os = "linux") { - format!("{}-unknown-linux-gnu", std::env::consts::ARCH) - } else if cfg!(target_os = "macos") { - "x86_64-apple-darwin".to_string() - } else if cfg!(target_os = "windows") { - "x86_64-pc-windows-msvc".to_string() - } else if cfg!(any( - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly" - )) { - format!( - "{}-unknown-{}", - std::env::consts::ARCH, - std::env::consts::OS - ) - } else { - "unknown".to_string() - }; - flags.target = Some(default_target); + flags.target = Some(default_target_triple()); } if flags.clean { let mut clean_args = Vec::new(); @@ -718,19 +698,13 @@ fn build_project_at( tc_cxx.as_deref(), tc_as.as_deref(), ); - if let Some(t) = build_target - && !t.trim().is_empty() - && resolved_compiler.to_lowercase().contains("clang") - { - let target_flag = format!("--target={}", t.trim()); - if !build_cflags - .iter() - .any(|f| f == &target_flag || f.starts_with("--target=")) - { - build_cflags.insert(0, target_flag); - } - } let resolved_linker = resolve_tool("DCR_LD", tc_ld.as_deref()); + prepend_clang_target_flag(&mut build_cflags, build_target, &resolved_compiler); + prepend_clang_target_flag( + &mut build_ldflags, + build_target, + resolved_linker.as_deref().unwrap_or(&resolved_compiler), + ); let resolved_archiver = resolve_tool("DCR_AR", tc_ar.as_deref()); let out_dir_config = get_build_string_with_profile(&config, "out_dir", profile); diff --git a/src/cli/clean.rs b/src/cli/clean.rs index 931b1ed..151f6bb 100644 --- a/src/cli/clean.rs +++ b/src/cli/clean.rs @@ -18,7 +18,7 @@ use crate::config::flags; use crate::core::config::Config; use crate::core::workspace::parse_workspace; -use crate::utils::build::parse_version_info; +use crate::utils::build::{default_target_triple, parse_version_info}; use crate::utils::fs::{check_dir, find_project_root, with_dir}; use crate::utils::log::{error, warn}; use crate::utils::text::{BOLD_CYAN, BOLD_GREEN, colored, printc}; @@ -136,28 +136,7 @@ fn clean_from_root(root: &Path, flags: &CleanFlags) -> Result<(), String> { .map(|s| s.trim().to_string()) .filter(|s| !s.is_empty()) }) - .or_else(|| { - Some(if cfg!(target_os = "linux") { - format!("{}-unknown-linux-gnu", std::env::consts::ARCH) - } else if cfg!(target_os = "macos") { - "x86_64-apple-darwin".to_string() - } else if cfg!(target_os = "windows") { - "x86_64-pc-windows-msvc".to_string() - } else if cfg!(any( - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly" - )) { - format!( - "{}-unknown-{}", - std::env::consts::ARCH, - std::env::consts::OS - ) - } else { - "unknown".to_string() - }) - }); + .or_else(|| Some(default_target_triple())); if flags.all && let Some(workspace) = parse_workspace( diff --git a/src/cli/run.rs b/src/cli/run.rs index 70c2218..942e0c1 100644 --- a/src/cli/run.rs +++ b/src/cli/run.rs @@ -19,7 +19,7 @@ use crate::cli::build::build; use crate::cli::flags::parse_build_run_flags; use crate::core::config::Config; use crate::core::runner::run_binary; -use crate::utils::build::{normalize_target_os, parse_version_info}; +use crate::utils::build::{default_target_triple, normalize_target_os, parse_version_info}; use crate::utils::fs::find_project_root; use crate::utils::fs::with_dir; use crate::utils::log::error; @@ -178,27 +178,7 @@ fn run_project( // If no target specified, use default host target for target-specific config let mut target = flags.target.clone(); if target.is_none() { - let default_target = if cfg!(target_os = "linux") { - format!("{}-unknown-linux-gnu", std::env::consts::ARCH) - } else if cfg!(target_os = "macos") { - "x86_64-apple-darwin".to_string() - } else if cfg!(target_os = "windows") { - "x86_64-pc-windows-msvc".to_string() - } else if cfg!(any( - target_os = "freebsd", - target_os = "openbsd", - target_os = "netbsd", - target_os = "dragonfly" - )) { - format!( - "{}-unknown-{}", - std::env::consts::ARCH, - std::env::consts::OS - ) - } else { - "unknown".to_string() - }; - target = Some(default_target); + target = Some(default_target_triple()); } let build_kind = config diff --git a/src/utils/build.rs b/src/utils/build.rs index 6f21ed4..b480f51 100644 --- a/src/utils/build.rs +++ b/src/utils/build.rs @@ -72,6 +72,46 @@ pub fn normalize_target_os(target: &str) -> &str { } } +pub fn default_target_triple() -> String { + if cfg!(target_os = "linux") { + format!("{}-unknown-linux-gnu", std::env::consts::ARCH) + } else if cfg!(target_os = "macos") { + format!("{}-apple-darwin", std::env::consts::ARCH) + } else if cfg!(target_os = "windows") { + format!("{}-pc-windows-msvc", std::env::consts::ARCH) + } else if cfg!(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly" + )) { + format!( + "{}-unknown-{}", + std::env::consts::ARCH, + std::env::consts::OS + ) + } else { + "unknown".to_string() + } +} + +pub fn prepend_clang_target_flag(flags: &mut Vec, target: Option<&str>, tool: &str) { + let Some(target) = target.map(str::trim).filter(|t| !t.is_empty()) else { + return; + }; + if !tool.to_lowercase().contains("clang") { + return; + } + + let target_flag = format!("--target={target}"); + if !flags + .iter() + .any(|f| f == &target_flag || f.starts_with("--target=")) + { + flags.insert(0, target_flag); + } +} + pub fn get_config_str(config: &Config, key: &str) -> String { config .get(key) @@ -380,6 +420,61 @@ mod tests { assert_eq!(normalize_target_os("unknown"), "unknown"); } + #[test] + fn default_target_triple_uses_host_arch() { + let target = default_target_triple(); + if cfg!(target_os = "linux") { + assert_eq!( + target, + format!("{}-unknown-linux-gnu", std::env::consts::ARCH) + ); + } else if cfg!(target_os = "macos") { + assert_eq!(target, format!("{}-apple-darwin", std::env::consts::ARCH)); + } else if cfg!(target_os = "windows") { + assert_eq!( + target, + format!("{}-pc-windows-msvc", std::env::consts::ARCH) + ); + } else if cfg!(any( + target_os = "freebsd", + target_os = "openbsd", + target_os = "netbsd", + target_os = "dragonfly" + )) { + assert_eq!( + target, + format!( + "{}-unknown-{}", + std::env::consts::ARCH, + std::env::consts::OS + ) + ); + } else { + assert_eq!(target, "unknown"); + } + } + + #[test] + fn prepend_clang_target_flag_adds_once_for_clang() { + let mut flags = vec!["-O2".to_string()]; + prepend_clang_target_flag(&mut flags, Some("aarch64-apple-darwin"), "clang"); + prepend_clang_target_flag(&mut flags, Some("aarch64-apple-darwin"), "clang"); + assert_eq!( + flags, + vec![ + "--target=aarch64-apple-darwin".to_string(), + "-O2".to_string() + ] + ); + } + + #[test] + fn prepend_clang_target_flag_ignores_non_clang_tools() { + let mut flags = vec!["-O2".to_string()]; + prepend_clang_target_flag(&mut flags, Some("aarch64-apple-darwin"), "gcc"); + assert_eq!(flags, vec!["-O2".to_string()]); + } + #[test] fn parse_version_parts() { let info = parse_version_info("1.2.3-beta");