diff options
Diffstat (limited to 'src/bootstrap/src/utils/cc_detect.rs')
| -rw-r--r-- | src/bootstrap/src/utils/cc_detect.rs | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs index 4aec554b432..1e84a7deff1 100644 --- a/src/bootstrap/src/utils/cc_detect.rs +++ b/src/bootstrap/src/utils/cc_detect.rs @@ -29,11 +29,9 @@ use crate::core::config::TargetSelection; use crate::utils::exec::{BootstrapCommand, command}; use crate::{Build, CLang, GitRepo}; -// The `cc` crate doesn't provide a way to obtain a path to the detected archiver, -// so use some simplified logic here. First we respect the environment variable `AR`, then -// try to infer the archiver path from the C compiler path. -// In the future this logic should be replaced by calling into the `cc` crate. -fn cc2ar(cc: &Path, target: TargetSelection) -> Option<PathBuf> { +/// Finds archiver tool for the given target if possible. +/// FIXME(onur-ozkan): This logic should be replaced by calling into the `cc` crate. +fn cc2ar(cc: &Path, target: TargetSelection, default_ar: PathBuf) -> Option<PathBuf> { if let Some(ar) = env::var_os(format!("AR_{}", target.triple.replace('-', "_"))) { Some(PathBuf::from(ar)) } else if let Some(ar) = env::var_os("AR") { @@ -57,19 +55,11 @@ fn cc2ar(cc: &Path, target: TargetSelection) -> Option<PathBuf> { } else if target.contains("android") || target.contains("-wasi") { Some(cc.parent().unwrap().join(PathBuf::from("llvm-ar"))) } else { - let parent = cc.parent().unwrap(); - let file = cc.file_name().unwrap().to_str().unwrap(); - for suffix in &["gcc", "cc", "clang"] { - if let Some(idx) = file.rfind(suffix) { - let mut file = file[..idx].to_owned(); - file.push_str("ar"); - return Some(parent.join(&file)); - } - } - Some(parent.join(file)) + Some(default_ar) } } +/// Creates and configures a new [`cc::Build`] instance for the given target. fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build { let mut cfg = cc::Build::new(); cfg.cargo_metadata(false) @@ -96,6 +86,12 @@ fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build { cfg } +/// Probes for C and C++ compilers and configures the corresponding entries in the [`Build`] +/// structure. +/// +/// This function determines which targets need a C compiler (and, if needed, a C++ compiler) +/// by combining the primary build target, host targets, and any additional targets. For +/// each target, it calls [`find_target`] to configure the necessary compiler tools. pub fn find(build: &Build) { let targets: HashSet<_> = match build.config.cmd { // We don't need to check cross targets for these commands. @@ -124,6 +120,11 @@ pub fn find(build: &Build) { } } +/// Probes and configures the C and C++ compilers for a single target. +/// +/// This function uses both user-specified configuration (from `config.toml`) and auto-detection +/// logic to determine the correct C/C++ compilers for the target. It also determines the appropriate +/// archiver (`ar`) and sets up additional compilation flags (both handled and unhandled). pub fn find_target(build: &Build, target: TargetSelection) { let mut cfg = new_cc_build(build, target); let config = build.config.target_config.get(&target); @@ -138,11 +139,12 @@ pub fn find_target(build: &Build, target: TargetSelection) { let ar = if let ar @ Some(..) = config.and_then(|c| c.ar.clone()) { ar } else { - cc2ar(compiler.path(), target) + cc2ar(compiler.path(), target, PathBuf::from(cfg.get_archiver().get_program())) }; build.cc.borrow_mut().insert(target, compiler.clone()); - let cflags = build.cflags(target, GitRepo::Rustc, CLang::C); + let mut cflags = build.cc_handled_clags(target, CLang::C); + cflags.extend(build.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::C)); // If we use llvm-libunwind, we will need a C++ compiler as well for all targets // We'll need one anyways if the target triple is also a host triple @@ -168,7 +170,8 @@ pub fn find_target(build: &Build, target: TargetSelection) { build.verbose(|| println!("CC_{} = {:?}", target.triple, build.cc(target))); build.verbose(|| println!("CFLAGS_{} = {cflags:?}", target.triple)); if let Ok(cxx) = build.cxx(target) { - let cxxflags = build.cflags(target, GitRepo::Rustc, CLang::Cxx); + let mut cxxflags = build.cc_handled_clags(target, CLang::Cxx); + cxxflags.extend(build.cc_unhandled_cflags(target, GitRepo::Rustc, CLang::Cxx)); build.verbose(|| println!("CXX_{} = {cxx:?}", target.triple)); build.verbose(|| println!("CXXFLAGS_{} = {cxxflags:?}", target.triple)); } @@ -182,6 +185,8 @@ pub fn find_target(build: &Build, target: TargetSelection) { } } +/// Determines the default compiler for a given target and language when not explicitly +/// configured in `config.toml`. fn default_compiler( cfg: &mut cc::Build, compiler: Language, @@ -258,6 +263,12 @@ fn default_compiler( } } +/// Constructs the path to the Android NDK compiler for the given target triple and language. +/// +/// This helper function transform the target triple by converting certain architecture names +/// (for example, translating "arm" to "arm7a"), appends the minimum API level (hardcoded as "21" +/// for NDK r26d), and then constructs the full path based on the provided NDK directory and host +/// platform. pub(crate) fn ndk_compiler(compiler: Language, triple: &str, ndk: &Path) -> PathBuf { let mut triple_iter = triple.split('-'); let triple_translated = if let Some(arch) = triple_iter.next() { @@ -287,7 +298,11 @@ pub(crate) fn ndk_compiler(compiler: Language, triple: &str, ndk: &Path) -> Path ndk.join("toolchains").join("llvm").join("prebuilt").join(host_tag).join("bin").join(compiler) } -/// The target programming language for a native compiler. +/// Representing the target programming language for a native compiler. +/// +/// This enum is used to indicate whether a particular compiler is intended for C or C++. +/// It also provides helper methods for obtaining the standard executable names for GCC and +/// clang-based compilers. #[derive(PartialEq)] pub(crate) enum Language { /// The compiler is targeting C. @@ -297,7 +312,7 @@ pub(crate) enum Language { } impl Language { - /// Obtains the name of a compiler in the GCC collection. + /// Returns the executable name for a GCC compiler corresponding to this language. fn gcc(self) -> &'static str { match self { Language::C => "gcc", @@ -305,7 +320,7 @@ impl Language { } } - /// Obtains the name of a compiler in the clang suite. + /// Returns the executable name for a clang-based compiler corresponding to this language. fn clang(self) -> &'static str { match self { Language::C => "clang", @@ -313,3 +328,6 @@ impl Language { } } } + +#[cfg(test)] +mod tests; |
