2019-11-01 13:50:12 -04:00
|
|
|
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
2019-10-31 12:03:44 -04:00
|
|
|
use cargo_gn;
|
|
|
|
use std::env;
|
|
|
|
use std::path::Path;
|
2019-11-29 21:58:29 -05:00
|
|
|
use std::path::PathBuf;
|
2019-12-13 20:17:45 -05:00
|
|
|
use std::process::exit;
|
2019-10-31 12:03:44 -04:00
|
|
|
use std::process::Command;
|
|
|
|
use which::which;
|
2019-10-15 21:31:05 -04:00
|
|
|
|
|
|
|
fn main() {
|
2019-12-22 10:22:44 -05:00
|
|
|
// Detect if trybuild tests are being compiled.
|
|
|
|
let is_trybuild = env::var_os("DENO_TRYBUILD").is_some();
|
|
|
|
|
2020-01-05 13:52:23 -05:00
|
|
|
// Don't build V8 if "cargo doc" is being run. This is to support docs.rs.
|
2019-12-22 10:22:44 -05:00
|
|
|
let is_cargo_doc = env::var_os("RUSTDOCFLAGS").is_some();
|
|
|
|
|
2020-01-05 13:52:23 -05:00
|
|
|
// Don't build V8 if the rust language server (RLS) is running.
|
|
|
|
let is_rls = env::var_os("CARGO")
|
|
|
|
.map(PathBuf::from)
|
|
|
|
.as_ref()
|
|
|
|
.and_then(|p| p.file_stem())
|
|
|
|
.and_then(|f| f.to_str())
|
|
|
|
.map(|s| s.starts_with("rls"))
|
|
|
|
.unwrap_or(false);
|
|
|
|
|
|
|
|
if !(is_trybuild || is_cargo_doc | is_rls) {
|
2019-12-22 10:22:44 -05:00
|
|
|
build_v8()
|
|
|
|
}
|
2020-01-05 13:52:23 -05:00
|
|
|
if !(is_cargo_doc || is_rls) {
|
2019-12-22 10:22:44 -05:00
|
|
|
print_link_flags()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_v8() {
|
2019-11-29 21:58:29 -05:00
|
|
|
env::set_var("DEPOT_TOOLS_WIN_TOOLCHAIN", "0");
|
2019-11-02 14:51:37 -04:00
|
|
|
|
2019-11-29 21:58:29 -05:00
|
|
|
// cargo publish doesn't like pyc files.
|
|
|
|
env::set_var("PYTHONDONTWRITEBYTECODE", "1");
|
|
|
|
|
|
|
|
// git submodule update --init --recursive
|
|
|
|
let libcxx_src = PathBuf::from("buildtools/third_party/libc++/trunk/src");
|
|
|
|
if !libcxx_src.is_dir() {
|
|
|
|
eprintln!(
|
|
|
|
"missing source code. Run 'git submodule update --init --recursive'"
|
|
|
|
);
|
2019-12-13 20:17:45 -05:00
|
|
|
exit(1);
|
2019-11-29 21:58:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if need_gn_ninja_download() {
|
|
|
|
download_gn_ninja_binaries();
|
2019-10-31 12:03:44 -04:00
|
|
|
}
|
|
|
|
|
2019-11-01 17:28:09 -04:00
|
|
|
// On windows, rustc cannot link with a V8 debug build.
|
|
|
|
let mut gn_args = if cargo_gn::is_debug() && !cfg!(target_os = "windows") {
|
2019-10-31 12:03:44 -04:00
|
|
|
vec!["is_debug=true".to_string()]
|
|
|
|
} else {
|
|
|
|
vec!["is_debug=false".to_string()]
|
|
|
|
};
|
|
|
|
|
2019-12-26 09:43:39 -05:00
|
|
|
if let Some(clang_base_path) = find_compatible_system_clang() {
|
|
|
|
println!("clang_base_path {}", clang_base_path.display());
|
|
|
|
gn_args.push(format!("clang_base_path={:?}", clang_base_path));
|
|
|
|
// TODO: Dedupe this with the one from cc_wrapper()
|
|
|
|
gn_args.push("treat_warnings_as_errors=false".to_string());
|
|
|
|
// we can't use chromiums clang plugins with a system clang
|
|
|
|
gn_args.push("clang_use_chrome_plugins=false".to_string());
|
|
|
|
} else {
|
|
|
|
let clang_base_path = clang_download();
|
|
|
|
gn_args.push(format!("clang_base_path={:?}", clang_base_path));
|
|
|
|
}
|
2019-11-29 21:58:29 -05:00
|
|
|
|
2019-10-31 12:03:44 -04:00
|
|
|
if let Some(p) = env::var_os("SCCACHE") {
|
|
|
|
cc_wrapper(&mut gn_args, &Path::new(&p));
|
|
|
|
} else if let Ok(p) = which("sccache") {
|
|
|
|
cc_wrapper(&mut gn_args, &p);
|
|
|
|
} else {
|
|
|
|
println!("cargo:warning=Not using sccache");
|
|
|
|
}
|
2019-10-18 15:36:58 -04:00
|
|
|
|
2019-12-26 09:43:39 -05:00
|
|
|
if let Ok(args) = env::var("GN_ARGS") {
|
|
|
|
for arg in args.split_whitespace() {
|
|
|
|
gn_args.push(arg.to_string());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-19 17:48:50 -05:00
|
|
|
let gn_root = env::var("CARGO_MANIFEST_DIR").unwrap();
|
2019-11-01 00:10:00 -04:00
|
|
|
|
|
|
|
let gn_out = cargo_gn::maybe_gen(&gn_root, gn_args);
|
2019-10-31 12:03:44 -04:00
|
|
|
assert!(gn_out.exists());
|
|
|
|
assert!(gn_out.join("args.gn").exists());
|
2020-01-04 18:00:22 -05:00
|
|
|
cargo_gn::build("rusty_v8", None);
|
2019-10-15 21:31:05 -04:00
|
|
|
}
|
2019-10-31 12:03:44 -04:00
|
|
|
|
2019-11-29 21:58:29 -05:00
|
|
|
fn platform() -> &'static str {
|
|
|
|
#[cfg(target_os = "windows")]
|
|
|
|
{
|
|
|
|
"win"
|
|
|
|
}
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
{
|
|
|
|
"linux64"
|
|
|
|
}
|
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
{
|
|
|
|
"mac"
|
2019-11-02 14:51:37 -04:00
|
|
|
}
|
2019-10-31 12:03:44 -04:00
|
|
|
}
|
|
|
|
|
2019-11-29 21:58:29 -05:00
|
|
|
fn download_gn_ninja_binaries() {
|
2019-11-01 00:10:00 -04:00
|
|
|
let root = env::current_dir().unwrap();
|
2019-11-29 21:58:29 -05:00
|
|
|
let out_dir = root.join(env::var_os("OUT_DIR").unwrap());
|
|
|
|
let d = out_dir.join("gn_ninja_binaries").join(platform());
|
|
|
|
let gn = d.join("gn");
|
|
|
|
let ninja = d.join("ninja");
|
|
|
|
#[cfg(windows)]
|
|
|
|
let gn = gn.with_extension("exe");
|
|
|
|
#[cfg(windows)]
|
|
|
|
let ninja = ninja.with_extension("exe");
|
2019-10-31 12:03:44 -04:00
|
|
|
|
2019-12-05 17:03:33 -05:00
|
|
|
if !gn.exists() || !ninja.exists() {
|
|
|
|
let status = Command::new("python")
|
|
|
|
.arg("./tools/gn_ninja_binaries.py")
|
|
|
|
.arg("--dir")
|
|
|
|
.arg(&out_dir)
|
|
|
|
.status()
|
|
|
|
.expect("gn_ninja_binaries.py download failed");
|
|
|
|
assert!(status.success());
|
|
|
|
}
|
|
|
|
assert!(gn.exists());
|
|
|
|
assert!(ninja.exists());
|
2019-11-29 21:58:29 -05:00
|
|
|
env::set_var("GN", gn);
|
|
|
|
env::set_var("NINJA", ninja);
|
|
|
|
}
|
|
|
|
|
2019-12-22 10:22:44 -05:00
|
|
|
fn print_link_flags() {
|
|
|
|
println!("cargo:rustc-link-lib=static=rusty_v8");
|
|
|
|
|
|
|
|
if cfg!(target_os = "windows") {
|
|
|
|
println!("cargo:rustc-link-lib=dylib=winmm");
|
|
|
|
println!("cargo:rustc-link-lib=dylib=dbghelp");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-29 21:58:29 -05:00
|
|
|
fn need_gn_ninja_download() -> bool {
|
|
|
|
!((which("ninja").is_ok() || env::var_os("NINJA").is_some())
|
|
|
|
&& env::var_os("GN").is_some())
|
|
|
|
}
|
|
|
|
|
2019-12-26 09:43:39 -05:00
|
|
|
// Chromiums gn arg clang_base_path is currently compatible with:
|
|
|
|
// * Apples clang and clang from homebrew's llvm@x packages
|
|
|
|
// * the official binaries from releases.llvm.org
|
|
|
|
// * unversioned (Linux) packages of clang (if recent enough)
|
|
|
|
// but unfortunately it doesn't work with version-suffixed packages commonly
|
|
|
|
// found in Linux packet managers
|
|
|
|
fn is_compatible_clang_version(clang_path: &Path) -> bool {
|
|
|
|
if let Ok(o) = Command::new(clang_path).arg("--version").output() {
|
2019-12-27 10:54:26 -05:00
|
|
|
let _output = String::from_utf8(o.stdout).unwrap();
|
|
|
|
// TODO check version output to make sure it's supported.
|
|
|
|
const _MIN_APPLE_CLANG_VER: f32 = 11.0;
|
|
|
|
const _MIN_LLVM_CLANG_VER: f32 = 8.0;
|
|
|
|
return true;
|
2019-12-26 09:43:39 -05:00
|
|
|
}
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
|
|
|
fn find_compatible_system_clang() -> Option<PathBuf> {
|
|
|
|
if let Ok(p) = env::var("CLANG_BASE_PATH") {
|
|
|
|
let base_path = Path::new(&p);
|
|
|
|
let clang_path = base_path.join("bin").join("clang");
|
|
|
|
if is_compatible_clang_version(&clang_path) {
|
|
|
|
return Some(base_path.to_path_buf());
|
|
|
|
}
|
|
|
|
}
|
2019-11-29 21:58:29 -05:00
|
|
|
|
2019-12-26 09:43:39 -05:00
|
|
|
println!("using Chromiums clang");
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
// Download chromium's clang into OUT_DIR because Cargo will not allow us to
|
|
|
|
// modify the source directory.
|
|
|
|
fn clang_download() -> PathBuf {
|
2019-11-29 21:58:29 -05:00
|
|
|
let root = env::current_dir().unwrap();
|
2020-01-16 14:20:57 -05:00
|
|
|
// target/debug//build/rusty_v8-d9e5a424d4f96994/out/
|
2019-11-29 21:58:29 -05:00
|
|
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
2020-01-16 14:20:57 -05:00
|
|
|
let clang_base_path = root
|
|
|
|
.join(out_dir)
|
|
|
|
.parent()
|
|
|
|
.unwrap()
|
|
|
|
.parent()
|
|
|
|
.unwrap()
|
|
|
|
.parent()
|
|
|
|
.unwrap()
|
|
|
|
.join("clang");
|
2019-11-29 21:58:29 -05:00
|
|
|
println!("clang_base_path {}", clang_base_path.display());
|
|
|
|
let status = Command::new("python")
|
|
|
|
.arg("./tools/clang/scripts/update.py")
|
2019-12-04 10:44:54 -05:00
|
|
|
.arg("--output-dir")
|
2019-11-29 21:58:29 -05:00
|
|
|
.arg(&clang_base_path)
|
2019-11-01 13:50:12 -04:00
|
|
|
.status()
|
2019-11-29 21:58:29 -05:00
|
|
|
.expect("clang download failed");
|
2019-10-31 12:03:44 -04:00
|
|
|
assert!(status.success());
|
2019-11-29 21:58:29 -05:00
|
|
|
assert!(clang_base_path.exists());
|
|
|
|
clang_base_path
|
2019-10-31 12:03:44 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
fn cc_wrapper(gn_args: &mut Vec<String>, sccache_path: &Path) {
|
|
|
|
gn_args.push(format!("cc_wrapper={:?}", sccache_path));
|
|
|
|
// Disable treat_warnings_as_errors until this sccache bug is fixed:
|
|
|
|
// https://github.com/mozilla/sccache/issues/264
|
|
|
|
if cfg!(target_os = "windows") {
|
|
|
|
gn_args.push("treat_warnings_as_errors=false".to_string());
|
|
|
|
}
|
|
|
|
}
|