Skip to content
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

chore: Fixed incorrect use of cfg! macro and update build.rs to support arm target #1458

Merged
merged 9 commits into from
May 12, 2024
139 changes: 71 additions & 68 deletions build.rs
Expand Up @@ -137,20 +137,23 @@ fn build_v8(is_asan: bool) {
if need_gn_ninja_download() {
download_ninja_gn_binaries();
}

// `#[cfg(...)]` attributes don't work as expected from build.rs -- they refer to the configuration
// of the host system which the build.rs script will be running on. In short, `cfg!(target_<os/arch>)`
// is actually the host os/arch instead of target os/arch while cross compiling. Instead, Environment variables
// are the officially approach to get the target os/arch in build.rs.
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a few lines here with a note explaining why cfg! isn't appropriate for future contributors to this file? The commentary from the PR description will work.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a few lines here with a note explaining why cfg! isn't appropriate for future contributors to this file? The commentary from the PR description will work.

Of course! Actually #[cfg(...)] attributes don't work as expected from build.rs -- they refer to the configuration of the host system which the build.rs script will be running on. In short, cfg!(target_<os/arch>) is actually the host os/arch instead of target os/arch while cross compiling. Instead, Environment viariables is the officially approach to get the target os/arch in build.rs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe some parts of the original code that use the cfg!(target_<os/arch>) macro are used to obtain the host <os/arch>, but I think using this ambiguous syntax is not conducive to long-term maintenance. It's highly recommended to use the HOST environment variable to get the host triplet or use cfg!(target_<os/arch>) with explicit annotation

mmastrac marked this conversation as resolved.
Show resolved Hide resolved
let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
// On windows, rustc cannot link with a V8 debug build.
let mut gn_args = if is_debug() && !cfg!(target_os = "windows") {
let mut gn_args = if is_debug() && target_os != "windows" {
// Note: When building for Android aarch64-qemu, use release instead of debug.
vec!["is_debug=true".to_string()]
} else {
vec!["is_debug=false".to_string()]
};

if is_asan {
gn_args.push("is_asan=true".to_string());
}

if cfg!(not(feature = "use_custom_libcxx")) {
if env::var("CARGO_FEATURE_USE_CUSTOM_LIBCXX").is_err() {
gn_args.push("use_custom_libcxx=false".to_string());
}

Expand All @@ -172,7 +175,7 @@ fn build_v8(is_asan: bool) {
let clang_base_path = clang_download();
gn_args.push(format!("clang_base_path={:?}", clang_base_path));

if cfg!(target_os = "android") && cfg!(target_arch = "aarch64") {
if target_os == "android" && target_arch == "aarch64" {
gn_args.push("treat_warnings_as_errors=false".to_string());
}
}
Expand All @@ -194,45 +197,43 @@ fn build_v8(is_asan: bool) {
gn_args.push(arg.to_string());
}
}
// cross-compilation setup
if target_arch == "aarch64" {
gn_args.push(r#"target_cpu="arm64""#.to_string());
gn_args.push("use_sysroot=true".to_string());
maybe_install_sysroot("arm64");
maybe_install_sysroot("amd64");
}
if target_arch == "arm" {
gn_args.push(r#"target_cpu="arm""#.to_string());
gn_args.push(r#"v8_target_cpu="arm""#.to_string());
gn_args.push("use_sysroot=true".to_string());
maybe_install_sysroot("i386");
maybe_install_sysroot("arm");
}

let target_triple = env::var("TARGET").unwrap();
// check if the target triple describes a non-native environment
if target_triple != env::var("HOST").unwrap() {
// cross-compilation setup
if target_triple == "aarch64-unknown-linux-gnu"
|| target_triple == "aarch64-linux-android"
{
gn_args.push(r#"target_cpu="arm64""#.to_string());
gn_args.push("use_sysroot=true".to_string());
maybe_install_sysroot("arm64");
maybe_install_sysroot("amd64");
if target_triple != env::var("HOST").unwrap() && target_os == "android" {
let arch = if target_arch == "x86_64" {
"x64"
} else if target_arch == "aarch64" {
"arm64"
} else {
"unknown"
};
if target_arch == "x86_64" {
maybe_install_sysroot("amd64");
}
gn_args.push(format!(r#"v8_target_cpu="{}""#, arch).to_string());
gn_args.push(format!(r#"target_cpu="{}""#, arch).to_string());
gn_args.push(r#"target_os="android""#.to_string());
gn_args.push("treat_warnings_as_errors=false".to_string());
gn_args.push("use_sysroot=true".to_string());

let t_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let t_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();

if t_os == "android" {
let arch = if t_arch == "x86_64" {
"x64"
} else if t_arch == "aarch64" {
"arm64"
} else {
"unknown"
};

if t_arch == "x86_64" {
maybe_install_sysroot("amd64");
}

gn_args.push(format!(r#"v8_target_cpu="{}""#, arch).to_string());
gn_args.push(format!(r#"target_cpu="{}""#, arch).to_string());
gn_args.push(r#"target_os="android""#.to_string());
gn_args.push("treat_warnings_as_errors=false".to_string());
gn_args.push("use_sysroot=true".to_string());

// NDK 23 and above removes libgcc entirely.
// https://github.com/rust-lang/rust/pull/85806
if !Path::new("./third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++").exists() {
// NDK 23 and above removes libgcc entirely.
// https://github.com/rust-lang/rust/pull/85806
if !Path::new("./third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++").exists() {
assert!(Command::new("curl")
.arg("-L")
.arg("-o").arg("./third_party/android-ndk-r26c-linux.zip")
Expand All @@ -253,21 +254,18 @@ fn build_v8(is_asan: bool) {
fs::rename("./third_party/android-ndk-r26c", "./third_party/android_ndk").unwrap();
fs::remove_file("./third_party/android-ndk-r26c-linux.zip").unwrap();
}

static CHROMIUM_URI: &str = "https://chromium.googlesource.com";

maybe_clone_repo(
"./third_party/android_platform",
&format!(
"{}/chromium/src/third_party/android_platform.git",
CHROMIUM_URI
),
);
maybe_clone_repo(
"./third_party/catapult",
&format!("{}/catapult.git", CHROMIUM_URI),
);
};
static CHROMIUM_URI: &str = "https://chromium.googlesource.com";
maybe_clone_repo(
"./third_party/android_platform",
&format!(
"{}/chromium/src/third_party/android_platform.git",
CHROMIUM_URI
),
);
maybe_clone_repo(
"./third_party/catapult",
&format!("{}/catapult.git", CHROMIUM_URI),
);
}

if target_triple.starts_with("i686-") {
Expand Down Expand Up @@ -321,7 +319,7 @@ fn maybe_install_sysroot(arch: &str) {
}
}

fn platform() -> String {
fn host_platform() -> String {
let os = if cfg!(target_os = "linux") {
"linux"
} else if cfg!(target_os = "macos") {
Expand All @@ -336,18 +334,19 @@ fn platform() -> String {
"amd64"
} else if cfg!(target_arch = "aarch64") {
"arm64"
} else if cfg!(target_arch = "arm") {
"arm"
} else {
"unknown"
};

format!("{os}-{arch}")
}

fn download_ninja_gn_binaries() {
let target_dir = build_dir();
let bin_dir = target_dir
.join("ninja_gn_binaries-20221218")
.join(platform());
.join(host_platform());
let gn = bin_dir.join("gn");
let ninja = bin_dir.join("ninja");
#[cfg(windows)]
Expand Down Expand Up @@ -379,9 +378,9 @@ fn static_lib_url() -> String {
env::var("RUSTY_V8_MIRROR").unwrap_or_else(|_| default_base.into());
let version = env::var("CARGO_PKG_VERSION").unwrap();
let target = env::var("TARGET").unwrap();

let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
// Note: we always use the release build on windows.
if cfg!(target_os = "windows") {
if target_os == "windows" {
return format!("{}/v{}/rusty_v8_release_{}.lib.gz", base, version, target);
}
// Use v8 in release mode unless $V8_FORCE_DEBUG=true
Expand All @@ -403,9 +402,11 @@ fn env_bool(key: &str) -> bool {
}

fn static_lib_name() -> &'static str {
match cfg!(target_os = "windows") {
true => "rusty_v8.lib",
false => "librusty_v8.a",
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "windows" {
"rusty_v8.lib"
} else {
"librusty_v8.a"
}
}

Expand Down Expand Up @@ -616,8 +617,8 @@ fn copy_archive(url: &str, filename: &Path) {

fn print_link_flags() {
println!("cargo:rustc-link-lib=static=rusty_v8");

let should_dyn_link_libcxx = cfg!(not(feature = "use_custom_libcxx"))
let should_dyn_link_libcxx = env::var("CARGO_FEATURE_USE_CUSTOM_LIBCXX")
.is_err()
|| env::var("GN_ARGS").map_or(false, |gn_args| {
gn_args
.split_whitespace()
Expand Down Expand Up @@ -646,16 +647,18 @@ fn print_link_flags() {
}
}
}
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();

if cfg!(target_os = "windows") {
if target_os == "windows" {
println!("cargo:rustc-link-lib=dylib=winmm");
println!("cargo:rustc-link-lib=dylib=dbghelp");
}

if cfg!(target_env = "msvc") {
if target_env == "msvc" {
// On Windows, including libcpmt[d]/msvcprt[d] explicitly links the C++
// standard library, which libc++ needs for exception_ptr internals.
if cfg!(target_feature = "crt-static") {
if env::var("CARGO_FEATURE_CRT_STATIC").is_ok() {
println!("cargo:rustc-link-lib=libcpmt");
} else {
println!("cargo:rustc-link-lib=dylib=msvcprt");
Expand Down
9 changes: 9 additions & 0 deletions rust-toolchain.toml
@@ -1,3 +1,12 @@
[toolchain]
channel = "1.77.2"
components = ["rustfmt", "clippy"]
targets = [
"x86_64-apple-darwin",
"aarch64-apple-darwin",
"x86_64-unknown-linux-gnu",
"aarch64-unknown-linux-gnu",
"x86_64-pc-windows-msvc",
"aarch64-linux-android",
"x86_64-linux-android",
]