diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 25d186b6a9..f6a4cab6cf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,6 +62,11 @@ jobs: variant: release cargo: cargo + - os: ${{ github.repository == 'denoland/rusty_v8' && 'ubuntu-24.04-xl' || 'ubuntu-24.04' }} + target: x86_64-unknown-linux-musl + variant: release + cargo: cargo + - os: ${{ github.repository == 'denoland/rusty_v8' && 'windows-2022-xxl' || 'windows-2022' }} target: x86_64-pc-windows-msvc variant: release # Note: we do not support windows debug builds. @@ -108,6 +113,10 @@ jobs: run: | sudo apt-get install -y glib2.0 + - name: Install cross compilation toolchain (musl) + if: endsWith(matrix.config.target, '-musl') + run: rustup target add ${{ matrix.config.target }} + - name: Install cross compilation toolchain if: matrix.config.target == 'aarch64-unknown-linux-gnu' run: | diff --git a/.gitmodules b/.gitmodules index 44ef796ab5..2ce5eadc4c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -37,3 +37,6 @@ [submodule "third_party/fast_float/src"] path = third_party/fast_float/src url = https://chromium.googlesource.com/external/github.com/fastfloat/fast_float.git +[submodule "musl-cross-make"] + path = musl-cross-make + url = https://github.com/richfelker/musl-cross-make.git diff --git a/build.rs b/build.rs index 4aead47749..8107d2acda 100644 --- a/build.rs +++ b/build.rs @@ -190,9 +190,20 @@ fn build_v8(is_asan: bool) { } else { vec!["is_debug=false".to_string()] }; + if is_asan { gn_args.push("is_asan=true".to_string()); } + + if std::env::var("CARGO_CFG_TARGET_ENV").map_or(false, |e| e == "musl") { + build_musl_cross_make(); + + gn_args.push("use_custom_libcxx=true".to_string()); + gn_args.push("is_clang=false".to_string()); + gn_args.push("treat_warnings_as_errors=false".to_string()); + gn_args.push("line_tables_only=false".to_string()); + } + if env::var("CARGO_FEATURE_USE_CUSTOM_LIBCXX").is_err() { gn_args.push("use_custom_libcxx=false".to_string()); } @@ -220,6 +231,50 @@ fn build_v8(is_asan: bool) { } } + if std::env::var("CARGO_CFG_TARGET_ENV").map_or(false, |e| e == "musl") { + let toolchain = build_musl_cross_make(); + + let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); + let manifest_dir = Path::new(&manifest_dir).join("toolchain"); + let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap(); + + gn_args.push("use_custom_libcxx=false".to_string()); + gn_args.push("is_clang=false".to_string()); + gn_args.push("treat_warnings_as_errors=false".to_string()); + gn_args.push("line_tables_only=false".to_string()); + gn_args.push("use_gold=false".to_string()); + gn_args.push("use_sysroot=false".to_string()); + gn_args.push("use_lld=false".to_string()); + gn_args.push("v8_static_library=true".to_string()); + gn_args.push("clang_use_chrome_plugins=false".to_string()); + // execinfo. is not available in musl + gn_args.push("is_debug=false".to_string()); + gn_args.push(format!( + "custom_toolchain=\"{}:{}\"", + manifest_dir.display(), + arch + )); + + let target = std::env::var("TARGET").unwrap(); + env::set_var("TOOLCHAIN", toolchain.join("bin").display().to_string()); + env::set_var( + format!("CC_{}", target.replace('-', "_")), + format!( + "{}/bin/{}-cc", + toolchain.display(), + target.replace("-unknown-", "-") + ), + ); + env::set_var( + format!("CARGO_TARGET_{}_LINKER", target.replace('-', "_")), + format!( + "{}/bin/{}-gcc", + toolchain.display(), + target.replace("-unknown-", "-") + ), + ); + } + if let Some(p) = env::var_os("SCCACHE") { cc_wrapper(&mut gn_args, Path::new(&p)); } else if let Ok(p) = which("sccache") { @@ -406,6 +461,33 @@ fn static_lib_name(suffix: &str) -> String { } } +fn build_musl_cross_make() -> PathBuf { + let toolchain_dir = build_dir().join("musl-cross-make"); + if toolchain_dir.exists() { + println!("musl-cross-make toolchain already exists, skipping build"); + return toolchain_dir; + } + + std::fs::copy("config.mak", "musl-cross-make/config.mak").unwrap(); + Command::new("make") + .arg("-C") + .arg("musl-cross-make") + .arg("TARGET=x86_64-linux-musl") + .status() + .unwrap(); + + Command::new("make") + .arg("-C") + .arg("musl-cross-make") + .arg("TARGET=x86_64-linux-musl") + .arg("install") + .arg(format!("OUTPUT={}", toolchain_dir.display())) + .status() + .unwrap(); + + toolchain_dir +} + fn static_lib_url() -> String { if let Ok(custom_archive) = env::var("RUSTY_V8_ARCHIVE") { return custom_archive; diff --git a/config.mak b/config.mak new file mode 100644 index 0000000000..b89eb31891 --- /dev/null +++ b/config.mak @@ -0,0 +1,7 @@ +MUSL_VER = 1.2.4 +GCC_VER = 11.2.0 + +GCC_CONFIG += --enable-default-pie + +DL_CMD = curl -C - -L -s -o +SHA1_CMD = shasum -a 1 -c diff --git a/musl-cross-make b/musl-cross-make new file mode 160000 index 0000000000..fd6be58297 --- /dev/null +++ b/musl-cross-make @@ -0,0 +1 @@ +Subproject commit fd6be58297ee21fcba89216ccd0d4aca1e3f1c5c diff --git a/toolchain/BUILD.gn b/toolchain/BUILD.gn new file mode 100644 index 0000000000..ee440669d5 --- /dev/null +++ b/toolchain/BUILD.gn @@ -0,0 +1,54 @@ +import("//build/config/sysroot.gni") +import("//build/toolchain/gcc_toolchain.gni") + +template("cross_toolchain") { + gcc_toolchain(target_name) { + assert(defined(invoker.toolprefix), "missing toolprefix") + + toolchain = getenv("TOOLCHAIN") + toolprefix = "${toolchain}/${invoker.toolprefix}" + + cc = "${toolprefix}-gcc" + cxx = "${toolprefix}-g++" + ld = cxx + + ar = "${toolprefix}-ar" + readelf = "${toolprefix}-readelf" + nm = "${toolprefix}-nm" + + extra_ldflags = "-static" + + toolchain_args = { + forward_variables_from(invoker.toolchain_args, "*") + use_remoteexec = false + is_clang = false + } + } +} + +cross_toolchain("aarch64") { + toolprefix = "aarch64-linux-musl" + + toolchain_args = { + current_cpu = "arm64" + current_os = "linux" + } +} + +cross_toolchain("armv7") { + toolprefix = "armv7-linux-musleabihf" + + toolchain_args = { + current_cpu = "arm" + current_os = "linux" + } +} + +cross_toolchain("x86_64") { + toolprefix = "x86_64-linux-musl" + + toolchain_args = { + current_cpu = "x64" + current_os = "linux" + } +}