Skip to content

Commit

Permalink
bootstrap: Add build scripts for crates
Browse files Browse the repository at this point in the history
This commits adds build scripts to the necessary Rust crates for all the native
dependencies. This is currently a duplication of the support found in mk/rt.mk
and is my best effort at representing the logic twice, but there may be some
unfortunate-and-inevitable divergence.

As a summary:

* alloc_jemalloc - build script to compile jemallocal
* flate - build script to compile miniz.c
* rustc_llvm - build script to run llvm-config and learn about how to link it.
  Note that this crucially (and will not ever) compile LLVM as that would take
  far too long.
* rustdoc - build script to compile hoedown
* std - script to determine lots of libraries/linkages as well as compile
  libbacktrace
  • Loading branch information
alexcrichton committed Feb 11, 2016
1 parent 2581b14 commit 4da4970
Show file tree
Hide file tree
Showing 5 changed files with 387 additions and 0 deletions.
104 changes: 104 additions & 0 deletions src/liballoc_jemalloc/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate build_helper;
extern crate gcc;

use std::env;
use std::path::PathBuf;
use std::process::Command;
use build_helper::run;

fn main() {
let target = env::var("TARGET").unwrap();
let host = env::var("HOST").unwrap();
let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let src_dir = env::current_dir().unwrap();

if let Some(jemalloc) = env::var_os("JEMALLOC_OVERRIDE") {
let jemalloc = PathBuf::from(jemalloc);
println!("cargo:rustc-link-search=native={}",
jemalloc.parent().unwrap().display());
let stem = jemalloc.file_stem().unwrap().to_str().unwrap();
let name = jemalloc.file_name().unwrap().to_str().unwrap();
let kind = if name.ends_with(".a") {"static"} else {"dylib"};
println!("cargo:rustc-link-lib={}={}", kind, &stem[3..]);
return
}

let compiler = gcc::Config::new().get_compiler();
let ar = build_helper::cc2ar(compiler.path(), &target);
let cflags = compiler.args().iter().map(|s| s.to_str().unwrap())
.collect::<Vec<_>>().join(" ");

let mut cmd = Command::new("sh");
cmd.arg(src_dir.join("../jemalloc/configure").to_str().unwrap()
.replace("C:\\", "/c/")
.replace("\\", "/"))
.current_dir(&build_dir)
.env("CC", compiler.path())
.env("EXTRA_CFLAGS", cflags)
.env("AR", &ar)
.env("RANLIB", format!("{} s", ar.display()));

if target.contains("windows-gnu") {
// A bit of history here, this used to be --enable-lazy-lock added in
// #14006 which was filed with jemalloc in jemalloc/jemalloc#83 which
// was also reported to MinGW:
//
// http://sourceforge.net/p/mingw-w64/bugs/395/
//
// When updating jemalloc to 4.0, however, it was found that binaries
// would exit with the status code STATUS_RESOURCE_NOT_OWNED indicating
// that a thread was unlocking a mutex it never locked. Disabling this
// "lazy lock" option seems to fix the issue, but it was enabled by
// default for MinGW targets in 13473c7 for jemalloc.
//
// As a result of all that, force disabling lazy lock on Windows, and
// after reading some code it at least *appears* that the initialization
// of mutexes is otherwise ok in jemalloc, so shouldn't cause problems
// hopefully...
//
// tl;dr: make windows behave like other platforms by disabling lazy
// locking, but requires passing an option due to a historical
// default with jemalloc.
cmd.arg("--disable-lazy-lock");
} else if target.contains("ios") || target.contains("android") {
cmd.arg("--disable-tls");
}

if cfg!(feature = "debug-jemalloc") {
cmd.arg("--enable-debug");
}

// Turn off broken quarantine (see jemalloc/jemalloc#161)
cmd.arg("--disable-fill");
cmd.arg("--with-jemalloc-prefix=je_");
cmd.arg(format!("--host={}", build_helper::gnu_target(&target)));
cmd.arg(format!("--build={}", build_helper::gnu_target(&host)));

run(&mut cmd);
run(Command::new("make")
.current_dir(&build_dir)
.arg("build_lib_static")
.arg("-j").arg(env::var("NUM_JOBS").unwrap()));

if target.contains("windows") {
println!("cargo:rustc-link-lib=static=jemalloc");
} else {
println!("cargo:rustc-link-lib=static=jemalloc_pic");
}
println!("cargo:rustc-link-search=native={}/lib", build_dir.display());
if target.contains("android") {
println!("cargo:rustc-link-lib=gcc");
} else if !target.contains("windows") {
println!("cargo:rustc-link-lib=pthread");
}
}
17 changes: 17 additions & 0 deletions src/libflate/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate gcc;

fn main() {
gcc::Config::new()
.file("../rt/miniz.c")
.compile("libminiz.a");
}
130 changes: 130 additions & 0 deletions src/librustc_llvm/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate gcc;
extern crate build_helper;

use std::process::Command;
use std::env;
use std::path::PathBuf;

use build_helper::output;

fn main() {
let target = env::var("TARGET").unwrap();
let llvm_config = env::var_os("LLVM_CONFIG").map(PathBuf::from)
.unwrap_or_else(|| {
match env::var_os("CARGO_TARGET_DIR").map(PathBuf::from) {
Some(dir) => {
let to_test = dir.parent().unwrap().parent().unwrap()
.join(&target).join("llvm/bin/llvm-config");
if Command::new(&to_test).output().is_ok() {
return to_test
}
}
None => {}
}
PathBuf::from("llvm-config")
});

println!("cargo:rerun-if-changed={}", llvm_config.display());

let optional_components = ["x86", "arm", "aarch64", "mips", "powerpc",
"pnacl"];

// FIXME: surely we don't need all these components, right? Stuff like mcjit
// or interpreter the compiler itself never uses.
let required_components = &["ipo", "bitreader", "bitwriter", "linker",
"asmparser", "mcjit", "interpreter",
"instrumentation"];

let components = output(Command::new(&llvm_config).arg("--components"));
let mut components = components.split_whitespace().collect::<Vec<_>>();
components.retain(|c| {
optional_components.contains(c) || required_components.contains(c)
});

for component in required_components {
if !components.contains(component) {
panic!("require llvm component {} but wasn't found", component);
}
}

for component in components.iter() {
println!("cargo:rustc-cfg=llvm_component=\"{}\"", component);
}

// Link in our own LLVM shims, compiled with the same flags as LLVM
let mut cmd = Command::new(&llvm_config);
cmd.arg("--cxxflags");
let cxxflags = output(&mut cmd);
let mut cfg = gcc::Config::new();
for flag in cxxflags.split_whitespace() {
cfg.flag(flag);
}
cfg.file("../rustllvm/ExecutionEngineWrapper.cpp")
.file("../rustllvm/PassWrapper.cpp")
.file("../rustllvm/RustWrapper.cpp")
.file("../rustllvm/ArchiveWrapper.cpp")
.cpp(true)
.cpp_link_stdlib(None) // we handle this below
.compile("librustllvm.a");

// Link in all LLVM libraries
let mut cmd = Command::new(&llvm_config);
cmd.arg("--libs").arg("--system-libs").args(&components[..]);
for lib in output(&mut cmd).split_whitespace() {
let name = if lib.starts_with("-l") {
&lib[2..]
} else if lib.starts_with("-") {
&lib[1..]
} else {
continue
};

// Don't need or want this library, but LLVM's CMake build system
// doesn't provide a way to disable it, so filter it here even though we
// may or may not have built it. We don't reference anything from this
// library and it otherwise may just pull in extra dependencies on
// libedit which we don't want
if name == "LLVMLineEditor" {
continue
}

let kind = if name.starts_with("LLVM") {"static"} else {"dylib"};
println!("cargo:rustc-link-lib={}={}", kind, name);
}

// LLVM ldflags
let mut cmd = Command::new(&llvm_config);
cmd.arg("--ldflags");
for lib in output(&mut cmd).split_whitespace() {
if lib.starts_with("-l") {
println!("cargo:rustc-link-lib={}", &lib[2..]);
} else if lib.starts_with("-L") {
println!("cargo:rustc-link-search=native={}", &lib[2..]);
}
}

// C++ runtime library
if !target.contains("msvc") {
if let Some(s) = env::var_os("LLVM_STATIC_STDCPP") {
assert!(!cxxflags.contains("stdlib=libc++"));
let path = PathBuf::from(s);
println!("cargo:rustc-link-search=native={}",
path.parent().unwrap().display());
println!("cargo:rustc-link-lib=static=stdc++");
} else if cxxflags.contains("stdlib=libc++") {
println!("cargo:rustc-link-lib=c++");
} else {
println!("cargo:rustc-link-lib=stdc++");
}
}
}
26 changes: 26 additions & 0 deletions src/librustdoc/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate gcc;

fn main() {
let mut cfg = gcc::Config::new();
cfg.file("../rt/hoedown/src/autolink.c")
.file("../rt/hoedown/src/buffer.c")
.file("../rt/hoedown/src/document.c")
.file("../rt/hoedown/src/escape.c")
.file("../rt/hoedown/src/html.c")
.file("../rt/hoedown/src/html_blocks.c")
.file("../rt/hoedown/src/html_smartypants.c")
.file("../rt/hoedown/src/stack.c")
.file("../rt/hoedown/src/version.c")
.include("../rt/hoedown/src")
.compile("libhoedown.a");
}
110 changes: 110 additions & 0 deletions src/libstd/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern crate gcc;
extern crate build_helper;

use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::Command;

use build_helper::run;

fn main() {
let target = env::var("TARGET").unwrap();
let host = env::var("HOST").unwrap();
if !target.contains("apple") && !target.contains("msvc") {
build_libbacktrace(&host, &target);
}

if target.contains("unknown-linux") {
if target.contains("musl") {
println!("cargo:rustc-link-lib=static=unwind");
} else {
println!("cargo:rustc-link-lib=dl");
println!("cargo:rustc-link-lib=rt");
println!("cargo:rustc-link-lib=pthread");
println!("cargo:rustc-link-lib=gcc_s");
}
} else if target.contains("android") {
println!("cargo:rustc-link-lib=dl");
println!("cargo:rustc-link-lib=log");
println!("cargo:rustc-link-lib=gcc");
} else if target.contains("freebsd") {
println!("cargo:rustc-link-lib=execinfo");
println!("cargo:rustc-link-lib=pthread");
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("dragonfly") || target.contains("bitrig") ||
target.contains("netbsd") || target.contains("openbsd") {
println!("cargo:rustc-link-lib=pthread");

if target.contains("rumprun") {
println!("cargo:rustc-link-lib=unwind");
} else if target.contains("netbsd") || target.contains("openbsd") {
println!("cargo:rustc-link-lib=gcc");
} else if target.contains("bitrig") {
println!("cargo:rustc-link-lib=c++abi");
} else if target.contains("dragonfly") {
println!("cargo:rustc-link-lib=gcc_pic");
}
} else if target.contains("apple-darwin") {
println!("cargo:rustc-link-lib=System");
} else if target.contains("apple-ios") {
println!("cargo:rustc-link-lib=System");
println!("cargo:rustc-link-lib=objc");
println!("cargo:rustc-link-lib=framework=Security");
println!("cargo:rustc-link-lib=framework=Foundation");
} else if target.contains("windows") {
if target.contains("windows-gnu") {
println!("cargo:rustc-link-lib=gcc_eh");
}
println!("cargo:rustc-link-lib=advapi32");
println!("cargo:rustc-link-lib=ws2_32");
println!("cargo:rustc-link-lib=userenv");
println!("cargo:rustc-link-lib=shell32");
}
}

fn build_libbacktrace(host: &str, target: &str) {
let src_dir = env::current_dir().unwrap().join("../libbacktrace");
let build_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());

println!("cargo:rustc-link-lib=static=backtrace");
println!("cargo:rustc-link-search=native={}/.libs", build_dir.display());

if fs::metadata(&build_dir.join(".libs/libbacktrace.a")).is_ok() {
return
}

let compiler = gcc::Config::new().get_compiler();
let ar = build_helper::cc2ar(compiler.path(), target);
let cflags = compiler.args().iter().map(|s| s.to_str().unwrap())
.collect::<Vec<_>>().join(" ");
run(Command::new("sh")
.current_dir(&build_dir)
.arg(src_dir.join("configure").to_str().unwrap()
.replace("C:\\", "/c/")
.replace("\\", "/"))
.arg("--with-pic")
.arg("--disable-multilib")
.arg("--disable-shared")
.arg("--disable-host-shared")
.arg(format!("--host={}", build_helper::gnu_target(target)))
.arg(format!("--build={}", build_helper::gnu_target(host)))
.env("CC", compiler.path())
.env("AR", &ar)
.env("RANLIB", format!("{} s", ar.display()))
.env("CFLAGS", cflags));
run(Command::new("make")
.current_dir(&build_dir)
.arg(format!("INCDIR={}", src_dir.display()))
.arg("-j").arg(env::var("NUM_JOBS").unwrap()));
}

0 comments on commit 4da4970

Please sign in to comment.