-
Notifications
You must be signed in to change notification settings - Fork 507
Implement autodetection for default compiler from NDK #495
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
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 |
---|---|---|
|
@@ -1370,6 +1370,15 @@ impl Build { | |
cmd.push_opt_unless_duplicate(format!("-O{}", opt_level).into()); | ||
} | ||
|
||
if cmd.family == ToolFamily::Clang && target.contains("android") { | ||
// For compatibility with code that doesn't use pre-defined `__ANDROID__` macro. | ||
// If compiler used via ndk-build or cmake (officially supported build methods) | ||
// this macros is defined. | ||
// See https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/build/cmake/android.toolchain.cmake#456 | ||
// https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/build/core/build-binary.mk#141 | ||
cmd.push_opt_unless_duplicate("-DANDROID".into()); | ||
} | ||
|
||
if !target.contains("-ios") { | ||
cmd.push_cc_arg("-ffunction-sections".into()); | ||
cmd.push_cc_arg("-fdata-sections".into()); | ||
|
@@ -1406,7 +1415,11 @@ impl Build { | |
// Target flags | ||
match cmd.family { | ||
ToolFamily::Clang => { | ||
cmd.args.push(format!("--target={}", target).into()); | ||
if !(target.contains("android") | ||
&& android_clang_compiler_uses_target_arg_internally(&cmd.path)) | ||
{ | ||
cmd.args.push(format!("--target={}", target).into()); | ||
} | ||
} | ||
ToolFamily::Msvc { clang_cl } => { | ||
// This is an undocumented flag from MSVC but helps with making | ||
|
@@ -1974,29 +1987,7 @@ impl Build { | |
format!("{}.exe", gnu) | ||
} | ||
} else if target.contains("android") { | ||
let target = target | ||
.replace("armv7neon", "arm") | ||
.replace("armv7", "arm") | ||
.replace("thumbv7neon", "arm") | ||
.replace("thumbv7", "arm"); | ||
let gnu_compiler = format!("{}-{}", target, gnu); | ||
let clang_compiler = format!("{}-{}", target, clang); | ||
// On Windows, the Android clang compiler is provided as a `.cmd` file instead | ||
// of a `.exe` file. `std::process::Command` won't run `.cmd` files unless the | ||
// `.cmd` is explicitly appended to the command name, so we do that here. | ||
let clang_compiler_cmd = format!("{}-{}.cmd", target, clang); | ||
|
||
// Check if gnu compiler is present | ||
// if not, use clang | ||
if Command::new(&gnu_compiler).output().is_ok() { | ||
gnu_compiler | ||
} else if host.contains("windows") | ||
&& Command::new(&clang_compiler_cmd).output().is_ok() | ||
{ | ||
clang_compiler_cmd | ||
} else { | ||
clang_compiler | ||
} | ||
autodetect_android_compiler(&target, &host, gnu, clang) | ||
} else if target.contains("cloudabi") { | ||
format!("{}-{}", target, traditional) | ||
} else if target == "wasm32-wasi" | ||
|
@@ -2722,3 +2713,75 @@ fn command_add_output_file( | |
cmd.arg("-o").arg(&dst); | ||
} | ||
} | ||
|
||
// Use by default minimum available API level | ||
// See note about naming here | ||
// https://android.googlesource.com/platform/ndk/+/refs/heads/ndk-release-r21/docs/BuildSystemMaintainers.md#Clang | ||
static NEW_STANDALONE_ANDROID_COMPILERS: [&str; 4] = [ | ||
"aarch64-linux-android21-clang", | ||
"armv7a-linux-androideabi16-clang", | ||
"i686-linux-android16-clang", | ||
"x86_64-linux-android21-clang", | ||
Dushistov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
]; | ||
|
||
// New "standalone" C/C++ cross-compiler executables from recent Android NDK | ||
// are just shell scripts that call main clang binary (from Android NDK) with | ||
// proper `--target` argument. | ||
// | ||
// For example, armv7a-linux-androideabi16-clang passes | ||
// `--target=armv7a-linux-androideabi16` to clang. | ||
// So to construct proper command line check if | ||
// `--target` argument would be passed or not to clang | ||
fn android_clang_compiler_uses_target_arg_internally(clang_path: &Path) -> bool { | ||
NEW_STANDALONE_ANDROID_COMPILERS.iter().any(|x| { | ||
let x: &OsStr = x.as_ref(); | ||
x == clang_path.as_os_str() | ||
}) | ||
} | ||
|
||
fn autodetect_android_compiler(target: &str, host: &str, gnu: &str, clang: &str) -> String { | ||
let new_clang_key = match target { | ||
"aarch64-linux-android" => Some("aarch64"), | ||
"armv7-linux-androideabi" => Some("armv7a"), | ||
"i686-linux-android" => Some("i686"), | ||
"x86_64-linux-android" => Some("x86_64"), | ||
_ => None, | ||
}; | ||
|
||
let new_clang = new_clang_key | ||
.map(|key| { | ||
NEW_STANDALONE_ANDROID_COMPILERS | ||
.iter() | ||
.find(|x| x.starts_with(key)) | ||
}) | ||
.unwrap_or(None); | ||
|
||
if let Some(new_clang) = new_clang { | ||
if Command::new(new_clang).output().is_ok() { | ||
return (*new_clang).into(); | ||
} | ||
} | ||
|
||
let target = target | ||
.replace("armv7neon", "arm") | ||
.replace("armv7", "arm") | ||
.replace("thumbv7neon", "arm") | ||
.replace("thumbv7", "arm"); | ||
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. FWIW this normalization isn't used when trying to find a new compiler, could this be refactored a bit such that these rustc targets would still find the armv7a android compiler? 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. I intentionally did not touch this code. Tier 1,2 platforms have only linux+android support. So it is hard test for Windows and MacOS, but code bellow works with windows, so I avoid changing anything that I can not test. Plus I don't think that this is refactoring is possible. IMHO new target naming that include android API level was introduced recently, so if somebody do not want update Android NDK and uses old 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. My point is that the 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.
@alexcrichton, not sure that I understand you. 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. Ah ok I think I was misreading a bit. In any case we can always tweak this later! |
||
let gnu_compiler = format!("{}-{}", target, gnu); | ||
let clang_compiler = format!("{}-{}", target, clang); | ||
|
||
// On Windows, the Android clang compiler is provided as a `.cmd` file instead | ||
// of a `.exe` file. `std::process::Command` won't run `.cmd` files unless the | ||
// `.cmd` is explicitly appended to the command name, so we do that here. | ||
let clang_compiler_cmd = format!("{}-{}.cmd", target, clang); | ||
|
||
// Check if gnu compiler is present | ||
// if not, use clang | ||
if Command::new(&gnu_compiler).output().is_ok() { | ||
gnu_compiler | ||
} else if host.contains("windows") && Command::new(&clang_compiler_cmd).output().is_ok() { | ||
clang_compiler_cmd | ||
} else { | ||
clang_compiler | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.