-
Notifications
You must be signed in to change notification settings - Fork 526
Add prefer_clang_cl_over_msvc #1516
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ pub struct Test { | |
pub td: TempDir, | ||
pub gcc: PathBuf, | ||
pub msvc: bool, | ||
pub msvc_autodetect: bool, | ||
} | ||
|
||
pub struct Execution { | ||
|
@@ -53,6 +54,7 @@ impl Test { | |
td, | ||
gcc, | ||
msvc: false, | ||
msvc_autodetect: false, | ||
} | ||
} | ||
|
||
|
@@ -69,6 +71,14 @@ impl Test { | |
t | ||
} | ||
|
||
// For msvc_autodetect, don't explicitly set the compiler - let the build system discover it | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lines 115-118 explicitly set the compiler to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could add a |
||
pub fn msvc_autodetect() -> Test { | ||
let mut t = Test::new(); | ||
t.shim("cl").shim("clang-cl.exe").shim("lib.exe"); | ||
t.msvc_autodetect = true; | ||
t | ||
} | ||
|
||
pub fn clang() -> Test { | ||
let t = Test::new(); | ||
t.shim("clang").shim("clang++").shim("ar"); | ||
|
@@ -87,7 +97,7 @@ impl Test { | |
|
||
pub fn gcc(&self) -> cc::Build { | ||
let mut cfg = cc::Build::new(); | ||
let target = if self.msvc { | ||
let target = if self.msvc || self.msvc_autodetect { | ||
"x86_64-pc-windows-msvc" | ||
} else if cfg!(target_os = "macos") { | ||
"x86_64-apple-darwin" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -851,3 +851,97 @@ fn clang_android() { | |
test.cmd(0).must_not_have("--target=arm-linux-androideabi"); | ||
} | ||
} | ||
|
||
#[test] | ||
#[cfg(windows)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be better to put them in a |
||
fn msvc_prefer_clang_cl_over_msvc_disabled_by_default() { | ||
reset_env(); | ||
|
||
let test = Test::msvc_autodetect(); | ||
|
||
// When prefer_clang_cl_over_msvc is not called (default false), should use MSVC | ||
let compiler = test | ||
.gcc() | ||
.try_get_compiler() | ||
.expect("Failed to get compiler"); | ||
|
||
// By default, should be using MSVC (cl.exe) and NOT clang-cl | ||
assert!(compiler.is_like_msvc(), "Should use MSVC by default"); | ||
assert!( | ||
!compiler.is_like_clang_cl(), | ||
"Should not use clang-cl by default" | ||
); | ||
} | ||
|
||
#[test] | ||
#[cfg(windows)] | ||
fn msvc_prefer_clang_cl_over_msvc_enabled() { | ||
reset_env(); | ||
|
||
let test = Test::msvc_autodetect(); | ||
|
||
let compiler = test | ||
.gcc() | ||
// When prefer_clang_cl_over_msvc is true, should use clang-cl.exe | ||
.prefer_clang_cl_over_msvc(true) | ||
.try_get_compiler() | ||
.expect("Failed to get compiler"); | ||
|
||
assert!( | ||
compiler.is_like_clang_cl(), | ||
"clang-cl.exe should be identified as clang-cl-like, got {:?}", | ||
compiler | ||
); | ||
assert!( | ||
compiler.is_like_msvc(), | ||
"clang-cl should still be MSVC-like" | ||
); | ||
} | ||
|
||
#[test] | ||
#[cfg(windows)] | ||
fn msvc_prefer_clang_cl_over_msvc_respects_explicit_cc_env() { | ||
reset_env(); | ||
|
||
let test = Test::msvc_autodetect(); | ||
let compiler = test | ||
.gcc() | ||
// We can't set the CC=cl.exe environment variable directly in the test as it's removed | ||
// in mod.rs, so we simulate it by setting the compiler directly | ||
Comment on lines
+909
to
+910
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We have a hidden There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the suggestion. I just tried using that as follows: let compiler = test
.gcc()
// If the user has set CC to cl.exe, we should respect that
.__set_env("CC", "cl.exe")
.prefer_clang_cl_over_msvc(true)
.try_get_compiler()
.expect("Failed to get compiler"); However, it's not being picked up because I'm curious if you're aware of any alternatives though! I also tried There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could update the diff --git a/src/lib.rs b/src/lib.rs
index 8a74141..24a7bbb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3795,7 +3795,11 @@ impl Build {
self.cargo_output
.print_metadata(&format_args!("cargo:rerun-if-env-changed={v}"));
}
- let r = env::var_os(v).map(Arc::from);
+ let r = self.env.iter().find(|(k, _)| k.as_ref() == v).cloned().map(|(_, v)| v);
+ let r = match r {
+ Some(ref val) if !val.is_empty() => Some(val.clone()),
+ _ => env::var_os(v).map(Arc::from),
+ };
self.cargo_output.print_metadata(&format_args!(
"{} = {}",
v, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks pretty good except for the empty checking and unnecessary cloning. let r = self.env
.iter()
.find(|(k, value)| k.as_ref() == v)
.map(|(_, value)| value.clone())
.or_else(|| env::var_os(v).map(Arc::from)); |
||
.compiler("cl.exe") | ||
NobodyXu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
.prefer_clang_cl_over_msvc(true) | ||
.try_get_compiler() | ||
.expect("Failed to get compiler"); | ||
|
||
// The preference should not override explicit compiler setting | ||
assert!(compiler.is_like_msvc(), "Should still be MSVC-like"); | ||
assert!( | ||
!compiler.is_like_clang_cl(), | ||
"Should NOT use clang-cl when CC is explicitly set to cl.exe, got {:?}", | ||
compiler | ||
); | ||
} | ||
|
||
#[test] | ||
#[cfg(windows)] | ||
fn msvc_prefer_clang_cl_over_msvc_cpp_mode() { | ||
reset_env(); | ||
|
||
let test = Test::msvc_autodetect(); | ||
let compiler = test | ||
.gcc() | ||
.cpp(true) | ||
.prefer_clang_cl_over_msvc(true) | ||
.try_get_compiler() | ||
.expect("Failed to get compiler"); | ||
|
||
// Verify clang-cl.exe works correctly in C++ mode | ||
assert!( | ||
compiler.is_like_clang_cl(), | ||
"clang-cl.exe should be identified as clang-cl-like in C++ mode" | ||
); | ||
assert!( | ||
compiler.is_like_msvc(), | ||
"clang-cl should still be MSVC-like in C++ mode" | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed this bit in my other PR #1506.
MSVC_FAMILY
basically setsToolFamily::Msvc { clang_cl: false }
, which isn't accurate when looking forclang-cl.exe
.Question:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
clang_cl
should only set to true for clang-clFor
clang
, I think it'd count as family clang instead of msvc?