Merge branch 'master' of github.com:1011X/rust
This commit is contained in:
commit
df283db4c1
103 changed files with 849 additions and 1095 deletions
9
.gitmodules
vendored
9
.gitmodules
vendored
|
|
@ -41,12 +41,15 @@
|
|||
[submodule "src/dlmalloc"]
|
||||
path = src/dlmalloc
|
||||
url = https://github.com/alexcrichton/dlmalloc-rs.git
|
||||
[submodule "src/binaryen"]
|
||||
path = src/binaryen
|
||||
url = https://github.com/alexcrichton/binaryen.git
|
||||
[submodule "src/doc/rust-by-example"]
|
||||
path = src/doc/rust-by-example
|
||||
url = https://github.com/rust-lang/rust-by-example
|
||||
[submodule "src/llvm-emscripten"]
|
||||
path = src/llvm-emscripten
|
||||
url = https://github.com/rust-lang/llvm
|
||||
[submodule "src/stdsimd"]
|
||||
path = src/stdsimd
|
||||
url = https://github.com/rust-lang-nursery/stdsimd
|
||||
[submodule "src/tools/lld"]
|
||||
path = src/tools/lld
|
||||
url = https://github.com/rust-lang/lld.git
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ matrix:
|
|||
# OSX 10.7 and `xcode7` is the latest Xcode able to compile LLVM for 10.7.
|
||||
- env: >
|
||||
RUST_CHECK_TARGET=dist
|
||||
RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-extended --enable-profiler --enable-emscripten"
|
||||
RUST_CONFIGURE_ARGS="--build=i686-apple-darwin --enable-full-tools --enable-profiler"
|
||||
SRC=.
|
||||
DEPLOY=1
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT=1
|
||||
|
|
@ -95,7 +95,7 @@ matrix:
|
|||
|
||||
- env: >
|
||||
RUST_CHECK_TARGET=dist
|
||||
RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-extended --enable-sanitizers --enable-profiler --enable-emscripten"
|
||||
RUST_CONFIGURE_ARGS="--target=aarch64-apple-ios,armv7-apple-ios,armv7s-apple-ios,i386-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler"
|
||||
SRC=.
|
||||
DEPLOY=1
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT=1
|
||||
|
|
|
|||
|
|
@ -129,9 +129,6 @@ CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.
|
|||
python x.py build
|
||||
```
|
||||
|
||||
If you are seeing build failure when compiling `rustc_binaryen`, make sure the path
|
||||
length of the rust folder is not longer than 22 characters.
|
||||
|
||||
#### Specifying an ABI
|
||||
[specifying-an-abi]: #specifying-an-abi
|
||||
|
||||
|
|
|
|||
10
appveyor.yml
10
appveyor.yml
|
|
@ -67,21 +67,19 @@ environment:
|
|||
# 32/64 bit MSVC and GNU deployment
|
||||
- RUST_CONFIGURE_ARGS: >
|
||||
--build=x86_64-pc-windows-msvc
|
||||
--enable-extended
|
||||
--enable-full-tools
|
||||
--enable-profiler
|
||||
--enable-emscripten
|
||||
SCRIPT: python x.py dist
|
||||
DEPLOY: 1
|
||||
- RUST_CONFIGURE_ARGS: >
|
||||
--build=i686-pc-windows-msvc
|
||||
--target=i586-pc-windows-msvc
|
||||
--enable-extended
|
||||
--enable-full-tools
|
||||
--enable-profiler
|
||||
--enable-emscripten
|
||||
SCRIPT: python x.py dist
|
||||
DEPLOY: 1
|
||||
- MSYS_BITS: 32
|
||||
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-extended --enable-emscripten
|
||||
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu --enable-full-tools
|
||||
SCRIPT: python x.py dist
|
||||
MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
|
||||
MINGW_ARCHIVE: i686-6.3.0-release-posix-dwarf-rt_v5-rev2.7z
|
||||
|
|
@ -89,7 +87,7 @@ environment:
|
|||
DEPLOY: 1
|
||||
- MSYS_BITS: 64
|
||||
SCRIPT: python x.py dist
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-extended --enable-emscripten
|
||||
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-gnu --enable-full-tools
|
||||
MINGW_URL: https://s3-us-west-1.amazonaws.com/rust-lang-ci2/rust-ci-mirror
|
||||
MINGW_ARCHIVE: x86_64-6.3.0-release-posix-seh-rt_v5-rev2.7z
|
||||
MINGW_DIR: mingw64
|
||||
|
|
|
|||
|
|
@ -321,11 +321,18 @@
|
|||
# bootstrap)
|
||||
#codegen-backends = ["llvm"]
|
||||
|
||||
# This is the name of the directory in which codegen backends will get installed
|
||||
#codegen-backends-dir = "codegen-backends"
|
||||
|
||||
# Flag indicating whether `libstd` calls an imported function to handle basic IO
|
||||
# when targeting WebAssembly. Enable this to debug tests for the `wasm32-unknown-unknown`
|
||||
# target, as without this option the test output will not be captured.
|
||||
#wasm-syscall = false
|
||||
|
||||
# Indicates whether LLD will be compiled and made available in the sysroot for
|
||||
# rustc to execute.
|
||||
#lld = false
|
||||
|
||||
# =============================================================================
|
||||
# Options for specific targets
|
||||
#
|
||||
|
|
|
|||
10
src/Cargo.lock
generated
10
src/Cargo.lock
generated
|
|
@ -1818,15 +1818,6 @@ dependencies = [
|
|||
"syntax 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_binaryen"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_borrowck"
|
||||
version = "0.0.0"
|
||||
|
|
@ -2107,7 +2098,6 @@ dependencies = [
|
|||
"rustc_allocator 0.0.0",
|
||||
"rustc_apfloat 0.0.0",
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_binaryen 0.0.0",
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 17841e155edf858c8ea7802dd5f5ecbef54b989f
|
||||
|
|
@ -224,7 +224,7 @@ fn main() {
|
|||
// flesh out rpath support more fully in the future.
|
||||
cmd.arg("-Z").arg("osx-rpath-install-name");
|
||||
Some("-Wl,-rpath,@loader_path/../lib")
|
||||
} else if !target.contains("windows") {
|
||||
} else if !target.contains("windows") && !target.contains("wasm32") {
|
||||
Some("-Wl,-rpath,$ORIGIN/../lib")
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -314,7 +314,6 @@ class RustBuild(object):
|
|||
self.build_dir = os.path.join(os.getcwd(), "build")
|
||||
self.clean = False
|
||||
self.config_toml = ''
|
||||
self.printed = False
|
||||
self.rust_root = os.path.abspath(os.path.join(__file__, '../../..'))
|
||||
self.use_locked_deps = ''
|
||||
self.use_vendored_sources = ''
|
||||
|
|
@ -336,7 +335,6 @@ class RustBuild(object):
|
|||
if self.rustc().startswith(self.bin_root()) and \
|
||||
(not os.path.exists(self.rustc()) or
|
||||
self.program_out_of_date(self.rustc_stamp())):
|
||||
self.print_what_bootstrap_means()
|
||||
if os.path.exists(self.bin_root()):
|
||||
shutil.rmtree(self.bin_root())
|
||||
filename = "rust-std-{}-{}.tar.gz".format(
|
||||
|
|
@ -351,10 +349,17 @@ class RustBuild(object):
|
|||
with open(self.rustc_stamp(), 'w') as rust_stamp:
|
||||
rust_stamp.write(self.date)
|
||||
|
||||
# This is required so that we don't mix incompatible MinGW
|
||||
# libraries/binaries that are included in rust-std with
|
||||
# the system MinGW ones.
|
||||
if "pc-windows-gnu" in self.build:
|
||||
filename = "rust-mingw-{}-{}.tar.gz".format(
|
||||
rustc_channel, self.build)
|
||||
self._download_stage0_helper(filename, "rust-mingw")
|
||||
|
||||
if self.cargo().startswith(self.bin_root()) and \
|
||||
(not os.path.exists(self.cargo()) or
|
||||
self.program_out_of_date(self.cargo_stamp())):
|
||||
self.print_what_bootstrap_means()
|
||||
filename = "cargo-{}-{}.tar.gz".format(cargo_channel, self.build)
|
||||
self._download_stage0_helper(filename, "cargo")
|
||||
self.fix_executable("{}/bin/cargo".format(self.bin_root()))
|
||||
|
|
@ -555,23 +560,6 @@ class RustBuild(object):
|
|||
return '.exe'
|
||||
return ''
|
||||
|
||||
def print_what_bootstrap_means(self):
|
||||
"""Prints more information about the build system"""
|
||||
if hasattr(self, 'printed'):
|
||||
return
|
||||
self.printed = True
|
||||
if os.path.exists(self.bootstrap_binary()):
|
||||
return
|
||||
if '--help' not in sys.argv or len(sys.argv) == 1:
|
||||
return
|
||||
|
||||
print('info: the build system for Rust is written in Rust, so this')
|
||||
print(' script is now going to download a stage0 rust compiler')
|
||||
print(' and then compile the build system itself')
|
||||
print('')
|
||||
print('info: in the meantime you can read more about rustbuild at')
|
||||
print(' src/bootstrap/README.md before the download finishes')
|
||||
|
||||
def bootstrap_binary(self):
|
||||
"""Return the path of the boostrap binary
|
||||
|
||||
|
|
@ -585,7 +573,6 @@ class RustBuild(object):
|
|||
|
||||
def build_bootstrap(self):
|
||||
"""Build bootstrap"""
|
||||
self.print_what_bootstrap_means()
|
||||
build_dir = os.path.join(self.build_dir, "bootstrap")
|
||||
if self.clean and os.path.exists(build_dir):
|
||||
shutil.rmtree(build_dir)
|
||||
|
|
@ -654,6 +641,10 @@ class RustBuild(object):
|
|||
continue
|
||||
if self.get_toml('jemalloc'):
|
||||
continue
|
||||
if module.endswith("lld"):
|
||||
config = self.get_toml('lld')
|
||||
if config is None or config == 'false':
|
||||
continue
|
||||
filtered_submodules.append(module)
|
||||
run(["git", "submodule", "update",
|
||||
"--init", "--recursive"] + filtered_submodules,
|
||||
|
|
@ -670,8 +661,16 @@ class RustBuild(object):
|
|||
self._download_url = 'https://dev-static.rust-lang.org'
|
||||
|
||||
|
||||
def bootstrap():
|
||||
def bootstrap(help_triggered):
|
||||
"""Configure, fetch, build and run the initial bootstrap"""
|
||||
|
||||
# If the user is asking for help, let them know that the whole download-and-build
|
||||
# process has to happen before anything is printed out.
|
||||
if help_triggered:
|
||||
print("info: Downloading and building bootstrap before processing --help")
|
||||
print(" command. See src/bootstrap/README.md for help with common")
|
||||
print(" commands.")
|
||||
|
||||
parser = argparse.ArgumentParser(description='Build rust')
|
||||
parser.add_argument('--config')
|
||||
parser.add_argument('--build')
|
||||
|
|
@ -708,7 +707,7 @@ def bootstrap():
|
|||
print(' and so in order to preserve your $HOME this will now')
|
||||
print(' use vendored sources by default. Note that if this')
|
||||
print(' does not work you should run a normal build first')
|
||||
print(' before running a command like `sudo make install`')
|
||||
print(' before running a command like `sudo ./x.py install`')
|
||||
|
||||
if build.use_vendored_sources:
|
||||
if not os.path.exists('.cargo'):
|
||||
|
|
@ -734,7 +733,10 @@ def bootstrap():
|
|||
if 'dev' in data:
|
||||
build.set_dev_environment()
|
||||
|
||||
build.update_submodules()
|
||||
# No help text depends on submodules. This check saves ~1 minute of git commands, even if
|
||||
# all the submodules are present and downloaded!
|
||||
if not help_triggered:
|
||||
build.update_submodules()
|
||||
|
||||
# Fetch/build the bootstrap
|
||||
build.build = args.build or build.build_triple()
|
||||
|
|
@ -760,7 +762,7 @@ def main():
|
|||
help_triggered = (
|
||||
'-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1)
|
||||
try:
|
||||
bootstrap()
|
||||
bootstrap(help_triggered)
|
||||
if not help_triggered:
|
||||
print("Build completed successfully in {}".format(
|
||||
format_build_time(time() - start_time)))
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ impl<'a> Builder<'a> {
|
|||
tool::UnstableBookGen, tool::Tidy, tool::Linkchecker, tool::CargoTest,
|
||||
tool::Compiletest, tool::RemoteTestServer, tool::RemoteTestClient,
|
||||
tool::RustInstaller, tool::Cargo, tool::Rls, tool::Rustdoc, tool::Clippy,
|
||||
native::Llvm, tool::Rustfmt, tool::Miri),
|
||||
native::Llvm, tool::Rustfmt, tool::Miri, native::Lld),
|
||||
Kind::Check => describe!(check::Std, check::Test, check::Rustc),
|
||||
Kind::Test => describe!(test::Tidy, test::Bootstrap, test::Ui, test::RunPass,
|
||||
test::CompileFail, test::ParseFail, test::RunFail, test::RunPassValgrind,
|
||||
|
|
@ -464,7 +464,7 @@ impl<'a> Builder<'a> {
|
|||
|
||||
pub fn sysroot_codegen_backends(&self, compiler: Compiler) -> PathBuf {
|
||||
self.sysroot_libdir(compiler, compiler.host)
|
||||
.with_file_name("codegen-backends")
|
||||
.with_file_name(self.build.config.rust_codegen_backends_dir.clone())
|
||||
}
|
||||
|
||||
/// Returns the compiler's libdir where it stores the dynamic libraries that
|
||||
|
|
@ -688,9 +688,25 @@ impl<'a> Builder<'a> {
|
|||
//
|
||||
// FIXME: the guard against msvc shouldn't need to be here
|
||||
if !target.contains("msvc") {
|
||||
let cc = self.cc(target);
|
||||
cargo.env(format!("CC_{}", target), cc)
|
||||
.env("CC", cc);
|
||||
let ccache = self.config.ccache.as_ref();
|
||||
let ccacheify = |s: &Path| {
|
||||
let ccache = match ccache {
|
||||
Some(ref s) => s,
|
||||
None => return s.display().to_string(),
|
||||
};
|
||||
// FIXME: the cc-rs crate only recognizes the literal strings
|
||||
// `ccache` and `sccache` when doing caching compilations, so we
|
||||
// mirror that here. It should probably be fixed upstream to
|
||||
// accept a new env var or otherwise work with custom ccache
|
||||
// vars.
|
||||
match &ccache[..] {
|
||||
"ccache" | "sccache" => format!("{} {}", ccache, s.display()),
|
||||
_ => s.display().to_string(),
|
||||
}
|
||||
};
|
||||
let cc = ccacheify(&self.cc(target));
|
||||
cargo.env(format!("CC_{}", target), &cc)
|
||||
.env("CC", &cc);
|
||||
|
||||
let cflags = self.cflags(target).join(" ");
|
||||
cargo.env(format!("CFLAGS_{}", target), cflags.clone())
|
||||
|
|
@ -705,8 +721,9 @@ impl<'a> Builder<'a> {
|
|||
}
|
||||
|
||||
if let Ok(cxx) = self.cxx(target) {
|
||||
cargo.env(format!("CXX_{}", target), cxx)
|
||||
.env("CXX", cxx)
|
||||
let cxx = ccacheify(&cxx);
|
||||
cargo.env(format!("CXX_{}", target), &cxx)
|
||||
.env("CXX", &cxx)
|
||||
.env(format!("CXXFLAGS_{}", target), cflags.clone())
|
||||
.env("CXXFLAGS", cflags);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,6 +79,9 @@ pub fn find(build: &mut Build) {
|
|||
let mut cfg = cc::Build::new();
|
||||
cfg.cargo_metadata(false).opt_level(0).warnings(false).debug(false)
|
||||
.target(&target).host(&build.build);
|
||||
if target.contains("msvc") {
|
||||
cfg.static_crt(true);
|
||||
}
|
||||
|
||||
let config = build.config.target_config.get(&target);
|
||||
if let Some(cc) = config.and_then(|c| c.cc.as_ref()) {
|
||||
|
|
|
|||
|
|
@ -514,7 +514,8 @@ fn rustc_cargo_env(build: &Build, cargo: &mut Command) {
|
|||
cargo.env("CFG_RELEASE", build.rust_release())
|
||||
.env("CFG_RELEASE_CHANNEL", &build.config.channel)
|
||||
.env("CFG_VERSION", build.rust_version())
|
||||
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default());
|
||||
.env("CFG_PREFIX", build.config.prefix.clone().unwrap_or_default())
|
||||
.env("CFG_CODEGEN_BACKENDS_DIR", &build.config.rust_codegen_backends_dir);
|
||||
|
||||
let libdir_relative = build.config.libdir_relative().unwrap_or(Path::new("lib"));
|
||||
cargo.env("CFG_LIBDIR_RELATIVE", libdir_relative);
|
||||
|
|
@ -746,6 +747,21 @@ fn copy_codegen_backends_to_sysroot(builder: &Builder,
|
|||
}
|
||||
}
|
||||
|
||||
fn copy_lld_to_sysroot(builder: &Builder,
|
||||
target_compiler: Compiler,
|
||||
lld_install_root: &Path) {
|
||||
let target = target_compiler.host;
|
||||
|
||||
let dst = builder.sysroot_libdir(target_compiler, target)
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join("bin");
|
||||
t!(fs::create_dir_all(&dst));
|
||||
|
||||
let exe = exe("lld", &target);
|
||||
copy(&lld_install_root.join("bin").join(&exe), &dst.join(&exe));
|
||||
}
|
||||
|
||||
/// Cargo's output path for the standard library in a given stage, compiled
|
||||
/// by a particular compiler for the specified target.
|
||||
pub fn libstd_stamp(build: &Build, compiler: Compiler, target: Interned<String>) -> PathBuf {
|
||||
|
|
@ -895,6 +911,14 @@ impl Step for Assemble {
|
|||
}
|
||||
}
|
||||
|
||||
let lld_install = if build.config.lld_enabled && target_compiler.stage > 0 {
|
||||
Some(builder.ensure(native::Lld {
|
||||
target: target_compiler.host,
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let stage = target_compiler.stage;
|
||||
let host = target_compiler.host;
|
||||
println!("Assembling stage{} compiler ({})", stage, host);
|
||||
|
|
@ -914,6 +938,9 @@ impl Step for Assemble {
|
|||
copy_codegen_backends_to_sysroot(builder,
|
||||
build_compiler,
|
||||
target_compiler);
|
||||
if let Some(lld_install) = lld_install {
|
||||
copy_lld_to_sysroot(builder, target_compiler, &lld_install);
|
||||
}
|
||||
|
||||
// Link the compiler binary itself into place
|
||||
let out_dir = build.cargo_out(build_compiler, Mode::Librustc, host);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ pub struct Config {
|
|||
pub llvm_experimental_targets: String,
|
||||
pub llvm_link_jobs: Option<u32>,
|
||||
|
||||
pub lld_enabled: bool,
|
||||
|
||||
// rust codegen options
|
||||
pub rust_optimize: bool,
|
||||
pub rust_codegen_units: Option<u32>,
|
||||
|
|
@ -96,6 +98,7 @@ pub struct Config {
|
|||
pub rust_debuginfo_tests: bool,
|
||||
pub rust_dist_src: bool,
|
||||
pub rust_codegen_backends: Vec<Interned<String>>,
|
||||
pub rust_codegen_backends_dir: String,
|
||||
|
||||
pub build: Interned<String>,
|
||||
pub hosts: Vec<Interned<String>>,
|
||||
|
|
@ -289,7 +292,9 @@ struct Rust {
|
|||
test_miri: Option<bool>,
|
||||
save_toolstates: Option<String>,
|
||||
codegen_backends: Option<Vec<String>>,
|
||||
codegen_backends_dir: Option<String>,
|
||||
wasm_syscall: Option<bool>,
|
||||
lld: Option<bool>,
|
||||
}
|
||||
|
||||
/// TOML representation of how each build target is configured.
|
||||
|
|
@ -330,6 +335,7 @@ impl Config {
|
|||
config.rust_dist_src = true;
|
||||
config.test_miri = false;
|
||||
config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")];
|
||||
config.rust_codegen_backends_dir = "codegen-backends".to_owned();
|
||||
|
||||
config.rustc_error_format = flags.rustc_error_format;
|
||||
config.on_fail = flags.on_fail;
|
||||
|
|
@ -477,6 +483,7 @@ impl Config {
|
|||
set(&mut config.quiet_tests, rust.quiet_tests);
|
||||
set(&mut config.test_miri, rust.test_miri);
|
||||
set(&mut config.wasm_syscall, rust.wasm_syscall);
|
||||
set(&mut config.lld_enabled, rust.lld);
|
||||
config.rustc_parallel_queries = rust.experimental_parallel_queries.unwrap_or(false);
|
||||
config.rustc_default_linker = rust.default_linker.clone();
|
||||
config.musl_root = rust.musl_root.clone().map(PathBuf::from);
|
||||
|
|
@ -488,6 +495,8 @@ impl Config {
|
|||
.collect();
|
||||
}
|
||||
|
||||
set(&mut config.rust_codegen_backends_dir, rust.codegen_backends_dir.clone());
|
||||
|
||||
match rust.codegen_units {
|
||||
Some(0) => config.rust_codegen_units = Some(num_cpus::get() as u32),
|
||||
Some(n) => config.rust_codegen_units = Some(n),
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ o("dist-src", "rust.dist-src", "when building tarballs enables building a source
|
|||
o("cargo-openssl-static", "build.openssl-static", "static openssl in cargo")
|
||||
o("profiler", "build.profiler", "build the profiler runtime")
|
||||
o("emscripten", None, "compile the emscripten backend as well as LLVM")
|
||||
o("full-tools", None, "enable all tools")
|
||||
|
||||
# Optimization and debugging options. These may be overridden by the release
|
||||
# channel, etc.
|
||||
|
|
@ -326,6 +327,10 @@ for key in known_args:
|
|||
set('build.target', value.split(','))
|
||||
elif option.name == 'emscripten':
|
||||
set('rust.codegen-backends', ['llvm', 'emscripten'])
|
||||
elif option.name == 'full-tools':
|
||||
set('rust.codegen-backends', ['llvm', 'emscripten'])
|
||||
set('rust.lld', True)
|
||||
set('build.extended', True)
|
||||
elif option.name == 'option-checking':
|
||||
# this was handled above
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ use build_helper::output;
|
|||
|
||||
use {Build, Compiler, Mode};
|
||||
use channel;
|
||||
use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file};
|
||||
use util::{cp_r, libdir, is_dylib, cp_filtered, copy, replace_in_file, exe};
|
||||
use builder::{Builder, RunConfig, ShouldRun, Step};
|
||||
use compile;
|
||||
use native;
|
||||
|
|
@ -443,6 +443,22 @@ impl Step for Rustc {
|
|||
t!(fs::create_dir_all(&backends_dst));
|
||||
cp_r(&backends_src, &backends_dst);
|
||||
|
||||
// Copy over lld if it's there
|
||||
if builder.config.lld_enabled {
|
||||
let exe = exe("lld", &compiler.host);
|
||||
let src = builder.sysroot_libdir(compiler, host)
|
||||
.parent()
|
||||
.unwrap()
|
||||
.join("bin")
|
||||
.join(&exe);
|
||||
let dst = image.join("lib/rustlib")
|
||||
.join(&*host)
|
||||
.join("bin")
|
||||
.join(&exe);
|
||||
t!(fs::create_dir_all(&dst.parent().unwrap()));
|
||||
copy(&src, &dst);
|
||||
}
|
||||
|
||||
// Man pages
|
||||
t!(fs::create_dir_all(image.join("share/man/man1")));
|
||||
let man_src = build.src.join("src/doc/man");
|
||||
|
|
@ -590,7 +606,10 @@ impl Step for Std {
|
|||
let mut src = builder.sysroot_libdir(compiler, target).to_path_buf();
|
||||
src.pop(); // Remove the trailing /lib folder from the sysroot_libdir
|
||||
cp_filtered(&src, &dst, &|path| {
|
||||
path.file_name().and_then(|s| s.to_str()) != Some("codegen-backends")
|
||||
let name = path.file_name().and_then(|s| s.to_str());
|
||||
name != Some(build.config.rust_codegen_backends_dir.as_str()) &&
|
||||
name != Some("bin")
|
||||
|
||||
});
|
||||
|
||||
let mut cmd = rust_installer(builder);
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ fn invoke_rustdoc(builder: &Builder, compiler: Compiler, target: Interned<String
|
|||
cmd.arg("--html-after-content").arg(&footer)
|
||||
.arg("--html-before-content").arg(&version_info)
|
||||
.arg("--html-in-header").arg(&favicon)
|
||||
.arg("--markdown-no-toc")
|
||||
.arg("--markdown-playground-url")
|
||||
.arg("https://play.rust-lang.org/")
|
||||
.arg("-o").arg(&out)
|
||||
|
|
|
|||
|
|
@ -501,6 +501,10 @@ impl Build {
|
|||
self.out.join(&*target).join("llvm-emscripten")
|
||||
}
|
||||
|
||||
fn lld_out(&self, target: Interned<String>) -> PathBuf {
|
||||
self.out.join(&*target).join("lld")
|
||||
}
|
||||
|
||||
/// Output directory for all documentation for a target
|
||||
fn doc_out(&self, target: Interned<String>) -> PathBuf {
|
||||
self.out.join(&*target).join("doc")
|
||||
|
|
@ -685,7 +689,9 @@ impl Build {
|
|||
.and_then(|c| c.linker.as_ref()) {
|
||||
Some(linker)
|
||||
} else if target != self.config.build &&
|
||||
!target.contains("msvc") && !target.contains("emscripten") {
|
||||
!target.contains("msvc") &&
|
||||
!target.contains("emscripten") &&
|
||||
!target.contains("wasm32") {
|
||||
Some(self.cc(target))
|
||||
} else {
|
||||
None
|
||||
|
|
|
|||
|
|
@ -81,11 +81,11 @@ impl Step for Llvm {
|
|||
|
||||
let (out_dir, llvm_config_ret_dir) = if emscripten {
|
||||
let dir = build.emscripten_llvm_out(target);
|
||||
let config_dir = dir.join("bin");
|
||||
let config_dir = dir.join("build/bin");
|
||||
(dir, config_dir)
|
||||
} else {
|
||||
(build.llvm_out(target),
|
||||
build.llvm_out(build.config.build).join("bin"))
|
||||
build.llvm_out(build.config.build).join("build/bin"))
|
||||
};
|
||||
let done_stamp = out_dir.join("llvm-finished-building");
|
||||
let build_llvm_config = llvm_config_ret_dir
|
||||
|
|
@ -110,9 +110,6 @@ impl Step for Llvm {
|
|||
// http://llvm.org/docs/CMake.html
|
||||
let root = if self.emscripten { "src/llvm-emscripten" } else { "src/llvm" };
|
||||
let mut cfg = cmake::Config::new(build.src.join(root));
|
||||
if build.config.ninja {
|
||||
cfg.generator("Ninja");
|
||||
}
|
||||
|
||||
let profile = match (build.config.llvm_optimize, build.config.llvm_release_debuginfo) {
|
||||
(false, _) => "Debug",
|
||||
|
|
@ -139,9 +136,7 @@ impl Step for Llvm {
|
|||
|
||||
let assertions = if build.config.llvm_assertions {"ON"} else {"OFF"};
|
||||
|
||||
cfg.target(&target)
|
||||
.host(&build.build)
|
||||
.out_dir(&out_dir)
|
||||
cfg.out_dir(&out_dir)
|
||||
.profile(profile)
|
||||
.define("LLVM_ENABLE_ASSERTIONS", assertions)
|
||||
.define("LLVM_TARGETS_TO_BUILD", llvm_targets)
|
||||
|
|
@ -213,67 +208,7 @@ impl Step for Llvm {
|
|||
cfg.define("LLVM_NATIVE_BUILD", build.llvm_out(build.build).join("build"));
|
||||
}
|
||||
|
||||
let sanitize_cc = |cc: &Path| {
|
||||
if target.contains("msvc") {
|
||||
OsString::from(cc.to_str().unwrap().replace("\\", "/"))
|
||||
} else {
|
||||
cc.as_os_str().to_owned()
|
||||
}
|
||||
};
|
||||
|
||||
let configure_compilers = |cfg: &mut cmake::Config| {
|
||||
// MSVC with CMake uses msbuild by default which doesn't respect these
|
||||
// vars that we'd otherwise configure. In that case we just skip this
|
||||
// entirely.
|
||||
if target.contains("msvc") && !build.config.ninja {
|
||||
return
|
||||
}
|
||||
|
||||
let cc = build.cc(target);
|
||||
let cxx = build.cxx(target).unwrap();
|
||||
|
||||
// Handle msvc + ninja + ccache specially (this is what the bots use)
|
||||
if target.contains("msvc") &&
|
||||
build.config.ninja &&
|
||||
build.config.ccache.is_some() {
|
||||
let mut cc = env::current_exe().expect("failed to get cwd");
|
||||
cc.set_file_name("sccache-plus-cl.exe");
|
||||
|
||||
cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc))
|
||||
.define("CMAKE_CXX_COMPILER", sanitize_cc(&cc));
|
||||
cfg.env("SCCACHE_PATH",
|
||||
build.config.ccache.as_ref().unwrap())
|
||||
.env("SCCACHE_TARGET", target);
|
||||
|
||||
// If ccache is configured we inform the build a little differently hwo
|
||||
// to invoke ccache while also invoking our compilers.
|
||||
} else if let Some(ref ccache) = build.config.ccache {
|
||||
cfg.define("CMAKE_C_COMPILER", ccache)
|
||||
.define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc))
|
||||
.define("CMAKE_CXX_COMPILER", ccache)
|
||||
.define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx));
|
||||
} else {
|
||||
cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc))
|
||||
.define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
|
||||
}
|
||||
|
||||
cfg.build_arg("-j").build_arg(build.jobs().to_string());
|
||||
cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" "));
|
||||
cfg.define("CMAKE_CXX_FLAGS", build.cflags(target).join(" "));
|
||||
if let Some(ar) = build.ar(target) {
|
||||
if ar.is_absolute() {
|
||||
// LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it
|
||||
// tries to resolve this path in the LLVM build directory.
|
||||
cfg.define("CMAKE_AR", sanitize_cc(ar));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
configure_compilers(&mut cfg);
|
||||
|
||||
if env::var_os("SCCACHE_ERROR_LOG").is_some() {
|
||||
cfg.env("RUST_LOG", "sccache=warn");
|
||||
}
|
||||
configure_cmake(build, target, &mut cfg, false);
|
||||
|
||||
// FIXME: we don't actually need to build all LLVM tools and all LLVM
|
||||
// libraries here, e.g. we just want a few components and a few
|
||||
|
|
@ -304,6 +239,134 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
|
|||
panic!("\n\nbad LLVM version: {}, need >=3.9\n\n", version)
|
||||
}
|
||||
|
||||
fn configure_cmake(build: &Build,
|
||||
target: Interned<String>,
|
||||
cfg: &mut cmake::Config,
|
||||
building_dist_binaries: bool) {
|
||||
if build.config.ninja {
|
||||
cfg.generator("Ninja");
|
||||
}
|
||||
cfg.target(&target)
|
||||
.host(&build.config.build);
|
||||
|
||||
let sanitize_cc = |cc: &Path| {
|
||||
if target.contains("msvc") {
|
||||
OsString::from(cc.to_str().unwrap().replace("\\", "/"))
|
||||
} else {
|
||||
cc.as_os_str().to_owned()
|
||||
}
|
||||
};
|
||||
|
||||
// MSVC with CMake uses msbuild by default which doesn't respect these
|
||||
// vars that we'd otherwise configure. In that case we just skip this
|
||||
// entirely.
|
||||
if target.contains("msvc") && !build.config.ninja {
|
||||
return
|
||||
}
|
||||
|
||||
let cc = build.cc(target);
|
||||
let cxx = build.cxx(target).unwrap();
|
||||
|
||||
// Handle msvc + ninja + ccache specially (this is what the bots use)
|
||||
if target.contains("msvc") &&
|
||||
build.config.ninja &&
|
||||
build.config.ccache.is_some() {
|
||||
let mut cc = env::current_exe().expect("failed to get cwd");
|
||||
cc.set_file_name("sccache-plus-cl.exe");
|
||||
|
||||
cfg.define("CMAKE_C_COMPILER", sanitize_cc(&cc))
|
||||
.define("CMAKE_CXX_COMPILER", sanitize_cc(&cc));
|
||||
cfg.env("SCCACHE_PATH",
|
||||
build.config.ccache.as_ref().unwrap())
|
||||
.env("SCCACHE_TARGET", target);
|
||||
|
||||
// If ccache is configured we inform the build a little differently hwo
|
||||
// to invoke ccache while also invoking our compilers.
|
||||
} else if let Some(ref ccache) = build.config.ccache {
|
||||
cfg.define("CMAKE_C_COMPILER", ccache)
|
||||
.define("CMAKE_C_COMPILER_ARG1", sanitize_cc(cc))
|
||||
.define("CMAKE_CXX_COMPILER", ccache)
|
||||
.define("CMAKE_CXX_COMPILER_ARG1", sanitize_cc(cxx));
|
||||
} else {
|
||||
cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc))
|
||||
.define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
|
||||
}
|
||||
|
||||
cfg.build_arg("-j").build_arg(build.jobs().to_string());
|
||||
cfg.define("CMAKE_C_FLAGS", build.cflags(target).join(" "));
|
||||
let mut cxxflags = build.cflags(target).join(" ");
|
||||
if building_dist_binaries {
|
||||
if build.config.llvm_static_stdcpp && !target.contains("windows") {
|
||||
cxxflags.push_str(" -static-libstdc++");
|
||||
}
|
||||
}
|
||||
cfg.define("CMAKE_CXX_FLAGS", cxxflags);
|
||||
if let Some(ar) = build.ar(target) {
|
||||
if ar.is_absolute() {
|
||||
// LLVM build breaks if `CMAKE_AR` is a relative path, for some reason it
|
||||
// tries to resolve this path in the LLVM build directory.
|
||||
cfg.define("CMAKE_AR", sanitize_cc(ar));
|
||||
}
|
||||
}
|
||||
|
||||
if env::var_os("SCCACHE_ERROR_LOG").is_some() {
|
||||
cfg.env("RUST_LOG", "sccache=warn");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct Lld {
|
||||
pub target: Interned<String>,
|
||||
}
|
||||
|
||||
impl Step for Lld {
|
||||
type Output = PathBuf;
|
||||
const ONLY_HOSTS: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun) -> ShouldRun {
|
||||
run.path("src/tools/lld")
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig) {
|
||||
run.builder.ensure(Lld { target: run.target });
|
||||
}
|
||||
|
||||
/// Compile LLVM for `target`.
|
||||
fn run(self, builder: &Builder) -> PathBuf {
|
||||
let target = self.target;
|
||||
let build = builder.build;
|
||||
|
||||
let llvm_config = builder.ensure(Llvm {
|
||||
target: self.target,
|
||||
emscripten: false,
|
||||
});
|
||||
|
||||
let out_dir = build.lld_out(target);
|
||||
let done_stamp = out_dir.join("lld-finished-building");
|
||||
if done_stamp.exists() {
|
||||
return out_dir
|
||||
}
|
||||
|
||||
let _folder = build.fold_output(|| "lld");
|
||||
println!("Building LLD for {}", target);
|
||||
let _time = util::timeit();
|
||||
t!(fs::create_dir_all(&out_dir));
|
||||
|
||||
let mut cfg = cmake::Config::new(build.src.join("src/tools/lld"));
|
||||
configure_cmake(build, target, &mut cfg, true);
|
||||
|
||||
cfg.out_dir(&out_dir)
|
||||
.profile("Release")
|
||||
.define("LLVM_CONFIG_PATH", llvm_config)
|
||||
.define("LLVM_INCLUDE_TESTS", "OFF");
|
||||
|
||||
cfg.build();
|
||||
|
||||
t!(File::create(&done_stamp));
|
||||
out_dir
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct TestHelpers {
|
||||
pub target: Interned<String>,
|
||||
|
|
|
|||
|
|
@ -914,7 +914,7 @@ impl Step for Compiletest {
|
|||
}
|
||||
|
||||
if build.config.llvm_enabled {
|
||||
let llvm_config = build.llvm_config(target);
|
||||
let llvm_config = build.llvm_config(build.config.build);
|
||||
let llvm_version = output(Command::new(&llvm_config).arg("--version"));
|
||||
cmd.arg("--llvm-version").arg(llvm_version);
|
||||
if !build.is_rust_llvm(target) {
|
||||
|
|
|
|||
|
|
@ -31,9 +31,7 @@ ENV PATH=$PATH:/android/sdk/platform-tools
|
|||
|
||||
ENV TARGETS=arm-linux-androideabi
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=$TARGETS \
|
||||
--arm-linux-androideabi-ndk=/android/ndk/arm-14
|
||||
ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14
|
||||
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS
|
||||
|
||||
|
|
|
|||
|
|
@ -76,9 +76,7 @@ RUN curl -O http://ftp.nl.debian.org/debian/dists/jessie/main/installer-armhf/cu
|
|||
COPY scripts/sccache.sh /scripts/
|
||||
RUN sh /scripts/sccache.sh
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=arm-unknown-linux-gnueabihf \
|
||||
--qemu-armhf-rootfs=/tmp/rootfs
|
||||
ENV RUST_CONFIGURE_ARGS --qemu-armhf-rootfs=/tmp/rootfs
|
||||
ENV SCRIPT python2.7 ../x.py test --target arm-unknown-linux-gnueabihf
|
||||
|
||||
ENV NO_CHANGE_USER=1
|
||||
|
|
|
|||
|
|
@ -29,6 +29,6 @@ ENV EM_CONFIG=/emsdk-portable/.emscripten
|
|||
|
||||
ENV TARGETS=asmjs-unknown-emscripten
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-emscripten
|
||||
ENV RUST_CONFIGURE_ARGS --enable-emscripten
|
||||
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS
|
||||
|
|
|
|||
|
|
@ -74,7 +74,6 @@ COPY scripts/sccache.sh /scripts/
|
|||
RUN sh /scripts/sccache.sh
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=aarch64-unknown-linux-gnu \
|
||||
--qemu-aarch64-rootfs=/tmp/rootfs
|
||||
ENV SCRIPT python2.7 ../x.py test --target aarch64-unknown-linux-gnu
|
||||
ENV NO_CHANGE_USER=1
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ ENV DEP_Z_ROOT=/android/ndk/arm64-21/sysroot/usr/
|
|||
ENV HOSTS=aarch64-linux-android
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--host=$HOSTS \
|
||||
--target=$HOSTS \
|
||||
--aarch64-linux-android-ndk=/android/ndk/arm64-21 \
|
||||
--disable-rpath \
|
||||
--enable-extended \
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ ENV DEP_Z_ROOT=/android/ndk/arm-14/sysroot/usr/
|
|||
ENV HOSTS=armv7-linux-androideabi
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--host=$HOSTS \
|
||||
--target=$HOSTS \
|
||||
--armv7-linux-androideabi-ndk=/android/ndk/arm \
|
||||
--disable-rpath \
|
||||
--enable-extended \
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@ ENV DEP_Z_ROOT=/android/ndk/x86-14/sysroot/usr/
|
|||
ENV HOSTS=i686-linux-android
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--host=$HOSTS \
|
||||
--target=$HOSTS \
|
||||
--i686-linux-android-ndk=/android/ndk/x86 \
|
||||
--disable-rpath \
|
||||
--enable-extended \
|
||||
|
|
|
|||
|
|
@ -14,8 +14,6 @@ ENV DEP_Z_ROOT=/android/ndk/x86_64-21/sysroot/usr/
|
|||
ENV HOSTS=x86_64-linux-android
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--host=$HOSTS \
|
||||
--target=$HOSTS \
|
||||
--x86_64-linux-android-ndk=/android/ndk/x86_64-21 \
|
||||
--disable-rpath \
|
||||
--enable-extended \
|
||||
|
|
|
|||
|
|
@ -32,5 +32,5 @@ ENV \
|
|||
|
||||
ENV HOSTS=x86_64-unknown-dragonfly
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ RUN sh /scripts/sccache.sh
|
|||
ENV HOST=x86_64-unknown-haiku
|
||||
ENV TARGET=target.$HOST
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOST --target=$HOST --disable-jemalloc \
|
||||
ENV RUST_CONFIGURE_ARGS --disable-jemalloc \
|
||||
--set=$TARGET.cc=x86_64-unknown-haiku-gcc \
|
||||
--set=$TARGET.cxx=x86_64-unknown-haiku-g++ \
|
||||
--set=$TARGET.llvm-config=/bin/llvm-config-haiku
|
||||
ENV SCRIPT python2.7 ../x.py dist
|
||||
ENV SCRIPT python2.7 ../x.py dist --host=$HOST --target=$HOST
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@ ENV \
|
|||
CC_x86_64_unknown_redox=x86_64-unknown-redox-gcc \
|
||||
CXX_x86_64_unknown_redox=x86_64-unknown-redox-g++
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --target=x86_64-unknown-redox --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --target x86_64-unknown-redox
|
||||
|
|
|
|||
|
|
@ -30,6 +30,6 @@ ENV EM_CONFIG=/root/.emscripten
|
|||
|
||||
ENV TARGETS=wasm32-experimental-emscripten
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --target=$TARGETS --experimental-targets=WebAssembly
|
||||
ENV RUST_CONFIGURE_ARGS --experimental-targets=WebAssembly
|
||||
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS
|
||||
|
|
|
|||
|
|
@ -29,7 +29,4 @@ ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.37.13_64bit/binaryen/
|
|||
ENV EM_CONFIG=/emsdk-portable/.emscripten
|
||||
|
||||
ENV TARGETS=wasm32-unknown-emscripten
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --target=$TARGETS
|
||||
|
||||
ENV SCRIPT python2.7 ../x.py test --target $TARGETS
|
||||
|
|
|
|||
|
|
@ -32,5 +32,5 @@ ENV CC_aarch64_unknown_linux_gnu=aarch64-unknown-linux-gnueabi-gcc \
|
|||
|
||||
ENV HOSTS=aarch64-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ ENV TARGETS=$TARGETS,aarch64-linux-android
|
|||
ENV TARGETS=$TARGETS,x86_64-linux-android
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=$TARGETS \
|
||||
--enable-extended \
|
||||
--arm-linux-androideabi-ndk=/android/ndk/arm-14 \
|
||||
--armv7-linux-androideabi-ndk=/android/ndk/arm-14 \
|
||||
|
|
|
|||
|
|
@ -32,5 +32,5 @@ ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \
|
|||
|
||||
ENV HOSTS=arm-unknown-linux-gnueabi
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -32,5 +32,5 @@ ENV CC_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-gcc \
|
|||
|
||||
ENV HOSTS=arm-unknown-linux-gnueabihf
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -32,5 +32,5 @@ ENV CC_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-gcc \
|
|||
|
||||
ENV HOSTS=armv7-unknown-linux-gnueabihf
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ COPY scripts/sccache.sh /scripts/
|
|||
RUN sh /scripts/sccache.sh
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=i686-unknown-linux-musl,i586-unknown-linux-gnu \
|
||||
--musl-root-i586=/musl-i586 \
|
||||
--musl-root-i686=/musl-i686 \
|
||||
--enable-extended
|
||||
|
|
@ -46,8 +45,7 @@ ENV CFLAGS_i586_unknown_linux_gnu=-Wa,-mrelax-relocations=no
|
|||
# https://github.com/alexcrichton/cc-rs/pull/281
|
||||
ENV CFLAGS_i586_unknown_linux_musl="-Wa,-mrelax-relocations=no -Wl,-melf_i386"
|
||||
|
||||
ENV TARGETS=i586-unknown-linux-gnu
|
||||
ENV TARGETS=$TARGETS,i686-unknown-linux-musl
|
||||
ENV TARGETS=i586-unknown-linux-gnu,i686-unknown-linux-musl
|
||||
|
||||
ENV SCRIPT \
|
||||
python2.7 ../x.py test --target $TARGETS && \
|
||||
|
|
|
|||
|
|
@ -29,5 +29,5 @@ ENV \
|
|||
|
||||
ENV HOSTS=i686-unknown-freebsd
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -82,13 +82,10 @@ RUN sh /scripts/sccache.sh
|
|||
ENV HOSTS=i686-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--host=$HOSTS \
|
||||
--enable-extended \
|
||||
--enable-full-tools \
|
||||
--enable-sanitizers \
|
||||
--enable-profiler \
|
||||
--enable-emscripten \
|
||||
--build=i686-unknown-linux-gnu
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
--enable-profiler
|
||||
ENV SCRIPT python2.7 ../x.py dist --build $HOSTS --host $HOSTS --target $HOSTS
|
||||
|
||||
# This is the only builder which will create source tarballs
|
||||
ENV DIST_SRC 1
|
||||
|
|
|
|||
|
|
@ -22,5 +22,5 @@ RUN sh /scripts/sccache.sh
|
|||
|
||||
ENV HOSTS=mips-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -21,5 +21,5 @@ RUN sh /scripts/sccache.sh
|
|||
|
||||
ENV HOSTS=mips64-unknown-linux-gnuabi64
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -22,5 +22,5 @@ RUN sh /scripts/sccache.sh
|
|||
|
||||
ENV HOSTS=mips64el-unknown-linux-gnuabi64
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -21,5 +21,5 @@ RUN sh /scripts/sccache.sh
|
|||
|
||||
ENV HOSTS=mipsel-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ ENV \
|
|||
|
||||
ENV HOSTS=powerpc-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
||||
# FIXME(#36150) this will fail the bootstrap. Probably means something bad is
|
||||
|
|
|
|||
|
|
@ -35,5 +35,5 @@ ENV \
|
|||
|
||||
ENV HOSTS=powerpc64-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -32,5 +32,5 @@ ENV \
|
|||
|
||||
ENV HOSTS=powerpc64le-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -34,5 +34,5 @@ ENV \
|
|||
|
||||
ENV HOSTS=s390x-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ ENV CC_mipsel_unknown_linux_musl=mipsel-openwrt-linux-gcc \
|
|||
CFLAGS_armv5te_unknown_linux_gnueabi="-march=armv5te -marm -mfloat-abi=soft"
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=$TARGETS \
|
||||
--musl-root-arm=/musl-arm \
|
||||
--musl-root-armhf=/musl-armhf \
|
||||
--musl-root-armv7=/musl-armv7 \
|
||||
|
|
|
|||
|
|
@ -55,5 +55,5 @@ ENV TARGETS=$TARGETS,x86_64-sun-solaris
|
|||
ENV TARGETS=$TARGETS,x86_64-unknown-linux-gnux32
|
||||
ENV TARGETS=$TARGETS,x86_64-unknown-cloudabi
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --target=$TARGETS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --target $TARGETS
|
||||
|
|
|
|||
|
|
@ -29,5 +29,5 @@ ENV \
|
|||
|
||||
ENV HOSTS=x86_64-unknown-freebsd
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -82,11 +82,9 @@ RUN sh /scripts/sccache.sh
|
|||
ENV HOSTS=x86_64-unknown-linux-gnu
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--host=$HOSTS \
|
||||
--enable-extended \
|
||||
--enable-full-tools \
|
||||
--enable-sanitizers \
|
||||
--enable-profiler \
|
||||
--enable-emscripten
|
||||
--enable-profiler
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
||||
# This is the only builder which will create source tarballs
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ COPY scripts/sccache.sh /scripts/
|
|||
RUN sh /scripts/sccache.sh
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=x86_64-unknown-linux-musl \
|
||||
--musl-root-x86_64=/musl-x86_64 \
|
||||
--enable-extended
|
||||
|
||||
|
|
|
|||
|
|
@ -33,5 +33,5 @@ ENV \
|
|||
|
||||
ENV HOSTS=x86_64-unknown-netbsd
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS --host=$HOSTS --enable-extended
|
||||
ENV RUST_CONFIGURE_ARGS --enable-extended
|
||||
ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ RUN sh /scripts/sccache.sh
|
|||
ENV TARGETS=wasm32-unknown-unknown
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--target=$TARGETS \
|
||||
--set build.nodejs=/node-v9.2.0-linux-x64/bin/node
|
||||
--set build.nodejs=/node-v9.2.0-linux-x64/bin/node \
|
||||
--set rust.lld
|
||||
|
||||
ENV SCRIPT python2.7 /checkout/x.py test --target $TARGETS \
|
||||
src/test/ui \
|
||||
|
|
|
|||
|
|
@ -67,6 +67,12 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
# We've had problems in the past of shell scripts leaking fds into the sccache
|
||||
# server (#48192) which causes Cargo to erroneously think that a build script
|
||||
# hasn't finished yet. Try to solve that problem by starting a very long-lived
|
||||
# sccache server at the start of the build, but no need to worry if this fails.
|
||||
SCCACHE_IDLE_TIMEOUT=10800 sccache --start-server || true
|
||||
|
||||
travis_fold start configure
|
||||
travis_time_start
|
||||
$SRC/configure $RUST_CONFIGURE_ARGS
|
||||
|
|
|
|||
|
|
@ -107,6 +107,8 @@ imports.env = {
|
|||
exp2f: function(x) { return Math.pow(2, x); },
|
||||
ldexp: function(x, y) { return x * Math.pow(2, y); },
|
||||
ldexpf: function(x, y) { return x * Math.pow(2, y); },
|
||||
log: Math.log,
|
||||
log2: Math.log2,
|
||||
log10: Math.log10,
|
||||
log10f: Math.log10,
|
||||
|
||||
|
|
|
|||
|
|
@ -1527,142 +1527,26 @@ impl<T: Hash> Hash for Vec<T> {
|
|||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> Index<usize> for Vec<T> {
|
||||
type Output = T;
|
||||
impl<T, I> Index<I> for Vec<T>
|
||||
where
|
||||
I: ::core::slice::SliceIndex<[T]>,
|
||||
{
|
||||
type Output = I::Output;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: usize) -> &T {
|
||||
// NB built-in indexing via `&[T]`
|
||||
&(**self)[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> IndexMut<usize> for Vec<T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: usize) -> &mut T {
|
||||
// NB built-in indexing via `&mut [T]`
|
||||
&mut (**self)[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::Index<ops::Range<usize>> for Vec<T> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: ops::Range<usize>) -> &[T] {
|
||||
fn index(&self, index: I) -> &Self::Output {
|
||||
Index::index(&**self, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::Index<ops::RangeTo<usize>> for Vec<T> {
|
||||
type Output = [T];
|
||||
|
||||
impl<T, I> IndexMut<I> for Vec<T>
|
||||
where
|
||||
I: ::core::slice::SliceIndex<[T]>,
|
||||
{
|
||||
#[inline]
|
||||
fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
|
||||
Index::index(&**self, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::Index<ops::RangeFrom<usize>> for Vec<T> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
|
||||
Index::index(&**self, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::Index<ops::RangeFull> for Vec<T> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
fn index(&self, _index: ops::RangeFull) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::Index<ops::RangeInclusive<usize>> for Vec<T> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: ops::RangeInclusive<usize>) -> &[T] {
|
||||
Index::index(&**self, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::Index<ops::RangeToInclusive<usize>> for Vec<T> {
|
||||
type Output = [T];
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: ops::RangeToInclusive<usize>) -> &[T] {
|
||||
Index::index(&**self, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::IndexMut<ops::Range<usize>> for Vec<T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut [T] {
|
||||
IndexMut::index_mut(&mut **self, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::IndexMut<ops::RangeTo<usize>> for Vec<T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut [T] {
|
||||
IndexMut::index_mut(&mut **self, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::IndexMut<ops::RangeFrom<usize>> for Vec<T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut [T] {
|
||||
IndexMut::index_mut(&mut **self, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::IndexMut<ops::RangeFull> for Vec<T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::IndexMut<ops::RangeInclusive<usize>> for Vec<T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut [T] {
|
||||
IndexMut::index_mut(&mut **self, index)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "inclusive_range", reason = "recently added, follows RFC", issue = "28237")]
|
||||
#[rustc_on_unimplemented = "vector indices are of type `usize` or ranges of `usize`"]
|
||||
impl<T> ops::IndexMut<ops::RangeToInclusive<usize>> for Vec<T> {
|
||||
#[inline]
|
||||
fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut [T] {
|
||||
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
||||
IndexMut::index_mut(&mut **self, index)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,16 +68,21 @@
|
|||
#![feature(allow_internal_unstable)]
|
||||
#![feature(asm)]
|
||||
#![feature(associated_type_defaults)]
|
||||
#![feature(attr_literals)]
|
||||
#![feature(cfg_target_feature)]
|
||||
#![feature(cfg_target_has_atomic)]
|
||||
#![feature(concat_idents)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(custom_attribute)]
|
||||
#![feature(doc_spotlight)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(i128_type)]
|
||||
#![feature(inclusive_range_syntax)]
|
||||
#![feature(intrinsics)]
|
||||
#![feature(iterator_flatten)]
|
||||
#![feature(iterator_repeat_with)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(link_llvm_intrinsics)]
|
||||
#![feature(never_type)]
|
||||
#![feature(no_core)]
|
||||
#![feature(on_unimplemented)]
|
||||
|
|
@ -85,15 +90,17 @@
|
|||
#![feature(prelude_import)]
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(rustc_const_unstable)]
|
||||
#![feature(simd_ffi)]
|
||||
#![feature(specialization)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(target_feature)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(untagged_unions)]
|
||||
#![feature(unwind_attributes)]
|
||||
#![feature(doc_spotlight)]
|
||||
#![feature(rustc_const_unstable)]
|
||||
#![feature(iterator_repeat_with)]
|
||||
#![feature(iterator_flatten)]
|
||||
|
||||
#![cfg_attr(stage0, allow(unused_attributes))]
|
||||
|
||||
#[prelude_import]
|
||||
#[allow(unused)]
|
||||
|
|
@ -179,3 +186,21 @@ mod char_private;
|
|||
mod iter_private;
|
||||
mod tuple;
|
||||
mod unit;
|
||||
|
||||
// Pull in the the `coresimd` crate directly into libcore. This is where all the
|
||||
// architecture-specific (and vendor-specific) intrinsics are defined. AKA
|
||||
// things like SIMD and such. Note that the actual source for all this lies in a
|
||||
// different repository, rust-lang-nursery/stdsimd. That's why the setup here is
|
||||
// a bit wonky.
|
||||
#[path = "../stdsimd/coresimd/mod.rs"]
|
||||
#[allow(missing_docs, missing_debug_implementations, dead_code)]
|
||||
#[unstable(feature = "stdsimd", issue = "48556")]
|
||||
#[cfg(not(stage0))] // allow changes to how stdsimd works in stage0
|
||||
mod coresimd;
|
||||
|
||||
#[unstable(feature = "stdsimd", issue = "48556")]
|
||||
#[cfg(not(stage0))]
|
||||
pub use coresimd::simd;
|
||||
#[unstable(feature = "stdsimd", issue = "48556")]
|
||||
#[cfg(not(stage0))]
|
||||
pub use coresimd::arch;
|
||||
|
|
|
|||
|
|
@ -43,14 +43,32 @@ use std::str::FromStr;
|
|||
|
||||
use serialize::json::{Json, ToJson};
|
||||
|
||||
macro_rules! linker_flavor {
|
||||
($(($variant:ident, $string:expr),)+) => {
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
|
||||
RustcEncodable, RustcDecodable)]
|
||||
pub enum LinkerFlavor {
|
||||
$($variant,)+
|
||||
}
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
|
||||
RustcEncodable, RustcDecodable)]
|
||||
pub enum LinkerFlavor {
|
||||
Em,
|
||||
Gcc,
|
||||
Ld,
|
||||
Msvc,
|
||||
Lld(LldFlavor),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash,
|
||||
RustcEncodable, RustcDecodable)]
|
||||
pub enum LldFlavor {
|
||||
Wasm,
|
||||
Ld64,
|
||||
Ld,
|
||||
Link,
|
||||
}
|
||||
|
||||
impl ToJson for LinkerFlavor {
|
||||
fn to_json(&self) -> Json {
|
||||
self.desc().to_json()
|
||||
}
|
||||
}
|
||||
macro_rules! flavor_mappings {
|
||||
($((($($flavor:tt)*), $string:expr),)*) => (
|
||||
impl LinkerFlavor {
|
||||
pub const fn one_of() -> &'static str {
|
||||
concat!("one of: ", $($string, " ",)+)
|
||||
|
|
@ -58,32 +76,30 @@ macro_rules! linker_flavor {
|
|||
|
||||
pub fn from_str(s: &str) -> Option<Self> {
|
||||
Some(match s {
|
||||
$($string => LinkerFlavor::$variant,)+
|
||||
$($string => $($flavor)*,)+
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn desc(&self) -> &str {
|
||||
match *self {
|
||||
$(LinkerFlavor::$variant => $string,)+
|
||||
$($($flavor)* => $string,)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJson for LinkerFlavor {
|
||||
fn to_json(&self) -> Json {
|
||||
self.desc().to_json()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
linker_flavor! {
|
||||
(Em, "em"),
|
||||
(Binaryen, "binaryen"),
|
||||
(Gcc, "gcc"),
|
||||
(Ld, "ld"),
|
||||
(Msvc, "msvc"),
|
||||
|
||||
flavor_mappings! {
|
||||
((LinkerFlavor::Em), "em"),
|
||||
((LinkerFlavor::Gcc), "gcc"),
|
||||
((LinkerFlavor::Ld), "ld"),
|
||||
((LinkerFlavor::Msvc), "msvc"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Wasm)), "wasm-ld"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Ld64)), "ld64.lld"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Ld)), "ld.lld"),
|
||||
((LinkerFlavor::Lld(LldFlavor::Link)), "lld-link"),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
|
|||
let mut base = super::cloudabi_base::opts();
|
||||
base.max_atomic_width = Some(128);
|
||||
base.abi_blacklist = super::arm_base::abi_blacklist();
|
||||
base.linker = "aarch64-unknown-cloudabi-cc".to_string();
|
||||
base.linker = Some("aarch64-unknown-cloudabi-cc".to_string());
|
||||
|
||||
Ok(Target {
|
||||
llvm_target: "aarch64-unknown-cloudabi".to_string(),
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ pub fn target() -> TargetResult {
|
|||
base.max_atomic_width = Some(64);
|
||||
base.features = "+v7,+vfp3,+neon".to_string();
|
||||
base.abi_blacklist = super::arm_base::abi_blacklist();
|
||||
base.linker = "armv7-unknown-cloudabi-eabihf-cc".to_string();
|
||||
base.linker = Some("armv7-unknown-cloudabi-eabihf-cc".to_string());
|
||||
|
||||
Ok(Target {
|
||||
llvm_target: "armv7-unknown-cloudabi-eabihf".to_string(),
|
||||
|
|
|
|||
|
|
@ -12,13 +12,7 @@ use LinkerFlavor;
|
|||
use target::{Target, TargetOptions, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::linux_musl_base::opts();
|
||||
|
||||
// Most of these settings are copied from the armv7_unknown_linux_gnueabihf
|
||||
// target.
|
||||
base.features = "+v7,+vfp3,+neon".to_string();
|
||||
base.cpu = "cortex-a8".to_string();
|
||||
base.max_atomic_width = Some(64);
|
||||
let base = super::linux_musl_base::opts();
|
||||
Ok(Target {
|
||||
// It's important we use "gnueabihf" and not "musleabihf" here. LLVM
|
||||
// uses it to determine the calling convention and float ABI, and LLVM
|
||||
|
|
@ -33,9 +27,15 @@ pub fn target() -> TargetResult {
|
|||
target_env: "musl".to_string(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
linker_flavor: LinkerFlavor::Gcc,
|
||||
|
||||
// Most of these settings are copied from the armv7_unknown_linux_gnueabihf
|
||||
// target.
|
||||
options: TargetOptions {
|
||||
features: "+v7,+vfp3,+d16,+thumb2,-neon".to_string(),
|
||||
cpu: "generic".to_string(),
|
||||
max_atomic_width: Some(64),
|
||||
abi_blacklist: super::arm_base::abi_blacklist(),
|
||||
.. base
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
use LinkerFlavor;
|
||||
use super::{LinkArgs, Target, TargetOptions};
|
||||
use super::emscripten_base::{cmd};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
let mut args = LinkArgs::new();
|
||||
|
|
@ -19,8 +18,6 @@ pub fn target() -> Result<Target, String> {
|
|||
"ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
|
||||
|
||||
let opts = TargetOptions {
|
||||
linker: cmd("emcc"),
|
||||
|
||||
dynamic_linking: false,
|
||||
executables: true,
|
||||
exe_suffix: ".js".to_string(),
|
||||
|
|
|
|||
|
|
@ -1,17 +0,0 @@
|
|||
// Copyright 2014-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.
|
||||
|
||||
pub fn cmd(name: &str) -> String {
|
||||
if cfg!(windows) {
|
||||
format!("{}.bat", name)
|
||||
} else {
|
||||
name.to_string()
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,6 @@ use std::default::Default;
|
|||
|
||||
pub fn opts() -> TargetOptions {
|
||||
TargetOptions {
|
||||
linker: "cc".to_string(),
|
||||
dynamic_linking: true,
|
||||
executables: true,
|
||||
has_rpath: false,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
|
|||
let mut base = super::cloudabi_base::opts();
|
||||
base.cpu = "pentium4".to_string();
|
||||
base.max_atomic_width = Some(64);
|
||||
base.linker = "i686-unknown-cloudabi-cc".to_string();
|
||||
base.linker = Some("i686-unknown-cloudabi-cc".to_string());
|
||||
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m32".to_string());
|
||||
base.stack_probes = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ pub fn opts() -> Result<TargetOptions, String> {
|
|||
has_elf_tls: false,
|
||||
exe_allocation_crate: None,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
linker: "ld".to_string(),
|
||||
pre_link_args,
|
||||
post_link_args,
|
||||
target_family: Some("unix".to_string()),
|
||||
|
|
|
|||
|
|
@ -58,7 +58,6 @@ mod arm_base;
|
|||
mod bitrig_base;
|
||||
mod cloudabi_base;
|
||||
mod dragonfly_base;
|
||||
mod emscripten_base;
|
||||
mod freebsd_base;
|
||||
mod haiku_base;
|
||||
mod linux_base;
|
||||
|
|
@ -279,8 +278,8 @@ pub struct TargetOptions {
|
|||
/// Whether the target is built-in or loaded from a custom target specification.
|
||||
pub is_builtin: bool,
|
||||
|
||||
/// Linker to invoke. Defaults to "cc".
|
||||
pub linker: String,
|
||||
/// Linker to invoke
|
||||
pub linker: Option<String>,
|
||||
|
||||
/// Linker arguments that are unconditionally passed *before* any
|
||||
/// user-defined libraries.
|
||||
|
|
@ -482,7 +481,7 @@ impl Default for TargetOptions {
|
|||
fn default() -> TargetOptions {
|
||||
TargetOptions {
|
||||
is_builtin: false,
|
||||
linker: option_env!("CFG_DEFAULT_LINKER").unwrap_or("cc").to_string(),
|
||||
linker: option_env!("CFG_DEFAULT_LINKER").map(|s| s.to_string()),
|
||||
pre_link_args: LinkArgs::new(),
|
||||
post_link_args: LinkArgs::new(),
|
||||
asm_args: Vec::new(),
|
||||
|
|
@ -732,7 +731,7 @@ impl Target {
|
|||
}
|
||||
|
||||
key!(is_builtin, bool);
|
||||
key!(linker);
|
||||
key!(linker, optional);
|
||||
key!(pre_link_args, link_args);
|
||||
key!(pre_link_objects_exe, list);
|
||||
key!(pre_link_objects_dll, list);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ pub fn target() -> TargetResult {
|
|||
// to gcc to get object files. For this reason we have a hard
|
||||
// dependency on this specific gcc.
|
||||
asm_args: vec!["-mcpu=msp430".to_string()],
|
||||
linker: "msp430-elf-gcc".to_string(),
|
||||
linker: Some("msp430-elf-gcc".to_string()),
|
||||
no_integrated_as: true,
|
||||
|
||||
// There are no atomic instructions available in the MSP430
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ pub fn opts() -> TargetOptions {
|
|||
executables: true,
|
||||
// In 99%+ of cases, we want to use the `arm-none-eabi-gcc` compiler (there aren't many
|
||||
// options around)
|
||||
linker: "arm-none-eabi-gcc".to_string(),
|
||||
linker: Some("arm-none-eabi-gcc".to_string()),
|
||||
// Because these devices have very little resources having an unwinder is too onerous so we
|
||||
// default to "abort" because the "unwind" strategy is very rare.
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
use LinkerFlavor;
|
||||
use super::{LinkArgs, Target, TargetOptions};
|
||||
use super::emscripten_base::{cmd};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
let mut post_link_args = LinkArgs::new();
|
||||
|
|
@ -24,8 +23,6 @@ pub fn target() -> Result<Target, String> {
|
|||
"-g3".to_string()]);
|
||||
|
||||
let opts = TargetOptions {
|
||||
linker: cmd("emcc"),
|
||||
|
||||
dynamic_linking: false,
|
||||
executables: true,
|
||||
// Today emcc emits two files - a .js file to bootstrap and
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@
|
|||
|
||||
use LinkerFlavor;
|
||||
use super::{LinkArgs, Target, TargetOptions};
|
||||
use super::emscripten_base::{cmd};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
let mut post_link_args = LinkArgs::new();
|
||||
|
|
@ -21,8 +20,6 @@ pub fn target() -> Result<Target, String> {
|
|||
"ERROR_ON_UNDEFINED_SYMBOLS=1".to_string()]);
|
||||
|
||||
let opts = TargetOptions {
|
||||
linker: cmd("emcc"),
|
||||
|
||||
dynamic_linking: false,
|
||||
executables: true,
|
||||
// Today emcc emits two files - a .js file to bootstrap and
|
||||
|
|
|
|||
|
|
@ -8,41 +8,20 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// The wasm32-unknown-unknown target is currently a highly experimental version
|
||||
// of a wasm-based target which does *not* use the Emscripten toolchain. Instead
|
||||
// this is a pretty flavorful (aka hacked up) target right now. The definition
|
||||
// and semantics of this target are likely to change and so this shouldn't be
|
||||
// relied on just yet.
|
||||
// The wasm32-unknown-unknown target is currently an experimental version of a
|
||||
// wasm-based target which does *not* use the Emscripten toolchain. Instead
|
||||
// this toolchain is based purely on LLVM's own toolchain, using LLVM's native
|
||||
// WebAssembly backend as well as LLD for a native linker.
|
||||
//
|
||||
// In general everyone is currently waiting on a linker for wasm code. In the
|
||||
// meantime we have no means of actually making use of the traditional separate
|
||||
// compilation model. At a high level this means that assembling Rust programs
|
||||
// into a WebAssembly program looks like:
|
||||
//
|
||||
// 1. All intermediate artifacts are LLVM bytecode. We'll be using LLVM as
|
||||
// a linker later on.
|
||||
// 2. For the final artifact we emit one giant assembly file (WebAssembly
|
||||
// doesn't have an object file format). To do this we force LTO to be turned
|
||||
// on (`requires_lto` below) to ensure all Rust code is in one module. Any
|
||||
// "linked" C library is basically just ignored.
|
||||
// 3. Using LLVM we emit a `foo.s` file (assembly) with some... what I can only
|
||||
// describe as arcane syntax. From there we need to actually change this
|
||||
// into a wasm module. For this step we use the `binaryen` project. This
|
||||
// project is mostly intended as a WebAssembly code generator, but for now
|
||||
// we're just using its LLVM-assembly-to-wasm-module conversion utilities.
|
||||
//
|
||||
// And voila, out comes a web assembly module! There's some various tweaks here
|
||||
// and there, but that's the high level at least. Note that this will be
|
||||
// rethought from the ground up once a linker (lld) is available, so this is all
|
||||
// temporary and should improve in the future.
|
||||
// There's some trickery below on crate types supported and various defaults
|
||||
// (aka panic=abort by default), but otherwise this is in general a relatively
|
||||
// standard target.
|
||||
|
||||
use LinkerFlavor;
|
||||
use {LinkerFlavor, LldFlavor};
|
||||
use super::{Target, TargetOptions, PanicStrategy};
|
||||
|
||||
pub fn target() -> Result<Target, String> {
|
||||
let opts = TargetOptions {
|
||||
linker: "not-used".to_string(),
|
||||
|
||||
// we allow dynamic linking, but only cdylibs. Basically we allow a
|
||||
// final library artifact that exports some symbols (a wasm module) but
|
||||
// we don't allow intermediate `dylib` crate types
|
||||
|
|
@ -58,9 +37,6 @@ pub fn target() -> Result<Target, String> {
|
|||
dll_suffix: ".wasm".to_string(),
|
||||
linker_is_gnu: false,
|
||||
|
||||
// We're storing bitcode for now in all the rlibs
|
||||
obj_is_bitcode: true,
|
||||
|
||||
// A bit of a lie, but "eh"
|
||||
max_atomic_width: Some(32),
|
||||
|
||||
|
|
@ -69,27 +45,17 @@ pub fn target() -> Result<Target, String> {
|
|||
// the future once unwinding is implemented. Don't rely on this.
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
|
||||
// There's no linker yet so we're forced to use LLVM as a linker. This
|
||||
// means that we must always enable LTO for final artifacts.
|
||||
requires_lto: true,
|
||||
|
||||
// Wasm doesn't have atomics yet, so tell LLVM that we're in a single
|
||||
// threaded model which will legalize atomics to normal operations.
|
||||
singlethread: true,
|
||||
|
||||
// Because we're always enabling LTO we can't enable builtin lowering as
|
||||
// otherwise we'll lower the definition of the `memcpy` function to
|
||||
// memcpy itself. Note that this is specifically because we're
|
||||
// performing LTO with compiler-builtins.
|
||||
no_builtins: true,
|
||||
|
||||
// no dynamic linking, no need for default visibility!
|
||||
default_hidden_visibility: true,
|
||||
|
||||
.. Default::default()
|
||||
};
|
||||
Ok(Target {
|
||||
llvm_target: "wasm32-unknown-unknown".to_string(),
|
||||
llvm_target: "wasm32-unknown-unknown-wasm".to_string(),
|
||||
target_endian: "little".to_string(),
|
||||
target_pointer_width: "32".to_string(),
|
||||
target_c_int_width: "32".to_string(),
|
||||
|
|
@ -100,8 +66,7 @@ pub fn target() -> Result<Target, String> {
|
|||
target_vendor: "unknown".to_string(),
|
||||
data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(),
|
||||
arch: "wasm32".to_string(),
|
||||
// A bit of a lie, but it gets the job done
|
||||
linker_flavor: LinkerFlavor::Binaryen,
|
||||
linker_flavor: LinkerFlavor::Lld(LldFlavor::Wasm),
|
||||
options: opts,
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ pub fn opts() -> TargetOptions {
|
|||
TargetOptions {
|
||||
// FIXME(#13846) this should be enabled for windows
|
||||
function_sections: false,
|
||||
linker: "gcc".to_string(),
|
||||
linker: Some("gcc".to_string()),
|
||||
dynamic_linking: true,
|
||||
executables: true,
|
||||
dll_prefix: "".to_string(),
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ pub fn opts() -> TargetOptions {
|
|||
|
||||
TargetOptions {
|
||||
function_sections: true,
|
||||
linker: "link.exe".to_string(),
|
||||
dynamic_linking: true,
|
||||
executables: true,
|
||||
dll_prefix: "".to_string(),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
|
|||
let mut base = super::netbsd_base::opts();
|
||||
base.cpu = "x86-64".to_string();
|
||||
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
|
||||
base.linker = "x86_64-rumprun-netbsd-gcc".to_string();
|
||||
base.linker = Some("x86_64-rumprun-netbsd-gcc".to_string());
|
||||
base.max_atomic_width = Some(64);
|
||||
|
||||
base.dynamic_linking = false;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
|
|||
let mut base = super::cloudabi_base::opts();
|
||||
base.cpu = "x86-64".to_string();
|
||||
base.max_atomic_width = Some(64);
|
||||
base.linker = "x86_64-unknown-cloudabi-cc".to_string();
|
||||
base.linker = Some("x86_64-unknown-cloudabi-cc".to_string());
|
||||
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
|
||||
base.stack_probes = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,160 +0,0 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
// This is a small C API inserted on top of the Binaryen C++ API which we use
|
||||
// from Rust. Once we have a real linker for we'll be able to remove all this,
|
||||
// and otherwise this is just all on a "as we need it" basis for now.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "s2wasm.h"
|
||||
#include "wasm-binary.h"
|
||||
#include "wasm-linker.h"
|
||||
|
||||
using namespace wasm;
|
||||
|
||||
struct BinaryenRustModule {
|
||||
BufferWithRandomAccess buffer;
|
||||
std::string sourceMapJSON;
|
||||
};
|
||||
|
||||
struct BinaryenRustModuleOptions {
|
||||
uint64_t globalBase;
|
||||
bool debug;
|
||||
uint64_t stackAllocation;
|
||||
uint64_t initialMem;
|
||||
uint64_t maxMem;
|
||||
bool importMemory;
|
||||
bool ignoreUnknownSymbols;
|
||||
bool debugInfo;
|
||||
std::string startFunction;
|
||||
std::string sourceMapUrl;
|
||||
|
||||
BinaryenRustModuleOptions() :
|
||||
globalBase(0),
|
||||
debug(false),
|
||||
stackAllocation(0),
|
||||
initialMem(0),
|
||||
maxMem(0),
|
||||
importMemory(false),
|
||||
ignoreUnknownSymbols(false),
|
||||
debugInfo(false),
|
||||
startFunction(""),
|
||||
sourceMapUrl("")
|
||||
{}
|
||||
|
||||
};
|
||||
|
||||
extern "C" BinaryenRustModuleOptions*
|
||||
BinaryenRustModuleOptionsCreate() {
|
||||
return new BinaryenRustModuleOptions;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleOptionsFree(BinaryenRustModuleOptions *options) {
|
||||
delete options;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleOptionsSetDebugInfo(BinaryenRustModuleOptions *options,
|
||||
bool debugInfo) {
|
||||
options->debugInfo = debugInfo;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleOptionsSetStart(BinaryenRustModuleOptions *options,
|
||||
char *start) {
|
||||
options->startFunction = start;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleOptionsSetSourceMapUrl(BinaryenRustModuleOptions *options,
|
||||
char *sourceMapUrl) {
|
||||
options->sourceMapUrl = sourceMapUrl;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleOptionsSetStackAllocation(BinaryenRustModuleOptions *options,
|
||||
uint64_t stack) {
|
||||
options->stackAllocation = stack;
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleOptionsSetImportMemory(BinaryenRustModuleOptions *options,
|
||||
bool import) {
|
||||
options->importMemory = import;
|
||||
}
|
||||
|
||||
extern "C" BinaryenRustModule*
|
||||
BinaryenRustModuleCreate(const BinaryenRustModuleOptions *options,
|
||||
const char *assembly) {
|
||||
Linker linker(
|
||||
options->globalBase,
|
||||
options->stackAllocation,
|
||||
options->initialMem,
|
||||
options->maxMem,
|
||||
options->importMemory,
|
||||
options->ignoreUnknownSymbols,
|
||||
options->startFunction,
|
||||
options->debug);
|
||||
|
||||
S2WasmBuilder mainbuilder(assembly, options->debug);
|
||||
linker.linkObject(mainbuilder);
|
||||
linker.layout();
|
||||
|
||||
auto ret = make_unique<BinaryenRustModule>();
|
||||
{
|
||||
WasmBinaryWriter writer(&linker.getOutput().wasm, ret->buffer, options->debug);
|
||||
writer.setNamesSection(options->debugInfo);
|
||||
|
||||
std::unique_ptr<std::ostringstream> sourceMapStream = nullptr;
|
||||
{
|
||||
sourceMapStream = make_unique<std::ostringstream>();
|
||||
writer.setSourceMap(sourceMapStream.get(), options->sourceMapUrl);
|
||||
}
|
||||
|
||||
// FIXME: support symbol maps?
|
||||
// writer.setSymbolMap(symbolMap);
|
||||
writer.write();
|
||||
|
||||
if (sourceMapStream) {
|
||||
ret->sourceMapJSON = sourceMapStream->str();
|
||||
}
|
||||
}
|
||||
return ret.release();
|
||||
}
|
||||
|
||||
extern "C" const uint8_t*
|
||||
BinaryenRustModulePtr(const BinaryenRustModule *M) {
|
||||
return M->buffer.data();
|
||||
}
|
||||
|
||||
extern "C" size_t
|
||||
BinaryenRustModuleLen(const BinaryenRustModule *M) {
|
||||
return M->buffer.size();
|
||||
}
|
||||
|
||||
extern "C" const char*
|
||||
BinaryenRustModuleSourceMapPtr(const BinaryenRustModule *M) {
|
||||
return M->sourceMapJSON.data();
|
||||
}
|
||||
|
||||
extern "C" size_t
|
||||
BinaryenRustModuleSourceMapLen(const BinaryenRustModule *M) {
|
||||
return M->sourceMapJSON.length();
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
BinaryenRustModuleFree(BinaryenRustModule *M) {
|
||||
delete M;
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
# Wondering what this crate is? Take a look at the `lib.rs`!
|
||||
|
||||
[package]
|
||||
name = "rustc_binaryen"
|
||||
version = "0.0.0"
|
||||
authors = ["The Rust Project Developers"]
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
|
||||
[build-dependencies]
|
||||
cmake = "0.1"
|
||||
cc = "1.0"
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
// Copyright 2017 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 cc;
|
||||
extern crate cmake;
|
||||
|
||||
use std::env;
|
||||
|
||||
use cmake::Config;
|
||||
|
||||
fn main() {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
|
||||
// Bring in `__emutls_get_address` which is apparently needed for now
|
||||
if target.contains("pc-windows-gnu") {
|
||||
println!("cargo:rustc-link-lib=gcc_eh");
|
||||
println!("cargo:rustc-link-lib=pthread");
|
||||
}
|
||||
|
||||
Config::new("../binaryen")
|
||||
.define("BUILD_STATIC_LIB", "ON")
|
||||
.build_target("binaryen")
|
||||
.build();
|
||||
|
||||
// I couldn't figure out how to link just one of these, so link everything.
|
||||
println!("cargo:rustc-link-lib=static=asmjs");
|
||||
println!("cargo:rustc-link-lib=static=binaryen");
|
||||
println!("cargo:rustc-link-lib=static=cfg");
|
||||
println!("cargo:rustc-link-lib=static=emscripten-optimizer");
|
||||
println!("cargo:rustc-link-lib=static=ir");
|
||||
println!("cargo:rustc-link-lib=static=passes");
|
||||
println!("cargo:rustc-link-lib=static=support");
|
||||
println!("cargo:rustc-link-lib=static=wasm");
|
||||
|
||||
let out_dir = env::var("OUT_DIR").unwrap();
|
||||
println!("cargo:rustc-link-search=native={}/build/lib", out_dir);
|
||||
|
||||
// Add in our own little shim along with some extra files that weren't
|
||||
// included in the main build.
|
||||
let mut cfg = cc::Build::new();
|
||||
cfg.file("BinaryenWrapper.cpp")
|
||||
.file("../binaryen/src/wasm-linker.cpp")
|
||||
.file("../binaryen/src/wasm-emscripten.cpp")
|
||||
.include("../binaryen/src")
|
||||
.cpp_link_stdlib(None)
|
||||
.warnings(false)
|
||||
.cpp(true);
|
||||
|
||||
if !target.contains("msvc") {
|
||||
cfg.flag("-std=c++11");
|
||||
}
|
||||
cfg.compile("binaryen_wrapper");
|
||||
}
|
||||
|
|
@ -1,172 +0,0 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
//! Rustc bindings to the binaryen project.
|
||||
//!
|
||||
//! This crate is a small shim around the binaryen project which provides us the
|
||||
//! ability to take LLVM's output and generate a wasm module. Specifically this
|
||||
//! only supports one operation, creating a module from LLVM's assembly format
|
||||
//! and then serializing that module to a wasm module.
|
||||
|
||||
extern crate libc;
|
||||
|
||||
use std::slice;
|
||||
use std::ffi::{CString, CStr};
|
||||
|
||||
/// In-memory representation of a serialized wasm module.
|
||||
pub struct Module {
|
||||
ptr: *mut BinaryenRustModule,
|
||||
}
|
||||
|
||||
impl Module {
|
||||
/// Creates a new wasm module from the LLVM-assembly provided (in a C string
|
||||
/// format).
|
||||
///
|
||||
/// The actual module creation can be tweaked through the various options in
|
||||
/// `ModuleOptions` as well. Any errors are just returned as a bland string.
|
||||
pub fn new(assembly: &CStr, opts: &ModuleOptions) -> Result<Module, String> {
|
||||
unsafe {
|
||||
let ptr = BinaryenRustModuleCreate(opts.ptr, assembly.as_ptr());
|
||||
if ptr.is_null() {
|
||||
Err(format!("failed to create binaryen module"))
|
||||
} else {
|
||||
Ok(Module { ptr })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the data of the serialized wasm module. This is a `foo.wasm`
|
||||
/// file contents.
|
||||
pub fn data(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let ptr = BinaryenRustModulePtr(self.ptr);
|
||||
let len = BinaryenRustModuleLen(self.ptr);
|
||||
slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the data of the source map JSON.
|
||||
pub fn source_map(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let ptr = BinaryenRustModuleSourceMapPtr(self.ptr);
|
||||
let len = BinaryenRustModuleSourceMapLen(self.ptr);
|
||||
slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Module {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
BinaryenRustModuleFree(self.ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModuleOptions {
|
||||
ptr: *mut BinaryenRustModuleOptions,
|
||||
}
|
||||
|
||||
impl ModuleOptions {
|
||||
pub fn new() -> ModuleOptions {
|
||||
unsafe {
|
||||
let ptr = BinaryenRustModuleOptionsCreate();
|
||||
ModuleOptions { ptr }
|
||||
}
|
||||
}
|
||||
|
||||
/// Turns on or off debug info.
|
||||
///
|
||||
/// From what I can tell this just creates a "names" section of the wasm
|
||||
/// module which contains a table of the original function names.
|
||||
pub fn debuginfo(&mut self, debug: bool) -> &mut Self {
|
||||
unsafe {
|
||||
BinaryenRustModuleOptionsSetDebugInfo(self.ptr, debug);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures a `start` function for the module, to be executed when it's
|
||||
/// loaded.
|
||||
pub fn start(&mut self, func: &str) -> &mut Self {
|
||||
let func = CString::new(func).unwrap();
|
||||
unsafe {
|
||||
BinaryenRustModuleOptionsSetStart(self.ptr, func.as_ptr());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures a `sourceMappingURL` custom section value for the module.
|
||||
pub fn source_map_url(&mut self, url: &str) -> &mut Self {
|
||||
let url = CString::new(url).unwrap();
|
||||
unsafe {
|
||||
BinaryenRustModuleOptionsSetSourceMapUrl(self.ptr, url.as_ptr());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures how much stack is initially allocated for the module. 1MB is
|
||||
/// probably good enough for now.
|
||||
pub fn stack(&mut self, amt: u64) -> &mut Self {
|
||||
unsafe {
|
||||
BinaryenRustModuleOptionsSetStackAllocation(self.ptr, amt);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Flags whether the initial memory should be imported or exported. So far
|
||||
/// we export it by default.
|
||||
pub fn import_memory(&mut self, import: bool) -> &mut Self {
|
||||
unsafe {
|
||||
BinaryenRustModuleOptionsSetImportMemory(self.ptr, import);
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ModuleOptions {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
BinaryenRustModuleOptionsFree(self.ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum BinaryenRustModule {}
|
||||
enum BinaryenRustModuleOptions {}
|
||||
|
||||
extern {
|
||||
fn BinaryenRustModuleCreate(opts: *const BinaryenRustModuleOptions,
|
||||
assembly: *const libc::c_char)
|
||||
-> *mut BinaryenRustModule;
|
||||
fn BinaryenRustModulePtr(module: *const BinaryenRustModule) -> *const u8;
|
||||
fn BinaryenRustModuleLen(module: *const BinaryenRustModule) -> usize;
|
||||
fn BinaryenRustModuleSourceMapPtr(module: *const BinaryenRustModule) -> *const u8;
|
||||
fn BinaryenRustModuleSourceMapLen(module: *const BinaryenRustModule) -> usize;
|
||||
fn BinaryenRustModuleFree(module: *mut BinaryenRustModule);
|
||||
|
||||
fn BinaryenRustModuleOptionsCreate()
|
||||
-> *mut BinaryenRustModuleOptions;
|
||||
fn BinaryenRustModuleOptionsSetDebugInfo(module: *mut BinaryenRustModuleOptions,
|
||||
debuginfo: bool);
|
||||
fn BinaryenRustModuleOptionsSetStart(module: *mut BinaryenRustModuleOptions,
|
||||
start: *const libc::c_char);
|
||||
fn BinaryenRustModuleOptionsSetSourceMapUrl(module: *mut BinaryenRustModuleOptions,
|
||||
sourceMapUrl: *const libc::c_char);
|
||||
fn BinaryenRustModuleOptionsSetStackAllocation(
|
||||
module: *mut BinaryenRustModuleOptions,
|
||||
stack: u64,
|
||||
);
|
||||
fn BinaryenRustModuleOptionsSetImportMemory(
|
||||
module: *mut BinaryenRustModuleOptions,
|
||||
import: bool,
|
||||
);
|
||||
fn BinaryenRustModuleOptionsFree(module: *mut BinaryenRustModuleOptions);
|
||||
}
|
||||
|
|
@ -10,16 +10,16 @@
|
|||
|
||||
use bitvec::BitMatrix;
|
||||
use fx::FxHashMap;
|
||||
use sync::Lock;
|
||||
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
|
||||
use stable_hasher::{HashStable, StableHasher, StableHasherResult};
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::mem;
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash + Clone> {
|
||||
pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash> {
|
||||
// List of elements. This is used to map from a T to a usize.
|
||||
elements: Vec<T>,
|
||||
|
||||
|
|
@ -32,14 +32,14 @@ pub struct TransitiveRelation<T: Clone + Debug + Eq + Hash + Clone> {
|
|||
|
||||
// This is a cached transitive closure derived from the edges.
|
||||
// Currently, we build it lazilly and just throw out any existing
|
||||
// copy whenever a new edge is added. (The RefCell is to permit
|
||||
// copy whenever a new edge is added. (The Lock is to permit
|
||||
// the lazy computation.) This is kind of silly, except for the
|
||||
// fact its size is tied to `self.elements.len()`, so I wanted to
|
||||
// wait before building it up to avoid reallocating as new edges
|
||||
// are added with new elements. Perhaps better would be to ask the
|
||||
// user for a batch of edges to minimize this effect, but I
|
||||
// already wrote the code this way. :P -nmatsakis
|
||||
closure: RefCell<Option<BitMatrix>>,
|
||||
closure: Lock<Option<BitMatrix>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
|
||||
|
|
@ -51,13 +51,13 @@ struct Edge {
|
|||
target: Index,
|
||||
}
|
||||
|
||||
impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
|
||||
impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
|
||||
pub fn new() -> TransitiveRelation<T> {
|
||||
TransitiveRelation {
|
||||
elements: vec![],
|
||||
map: FxHashMap(),
|
||||
edges: vec![],
|
||||
closure: RefCell::new(None),
|
||||
closure: Lock::new(None),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +72,7 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
|
|||
fn add_index(&mut self, a: T) -> Index {
|
||||
let &mut TransitiveRelation {
|
||||
ref mut elements,
|
||||
ref closure,
|
||||
ref mut closure,
|
||||
ref mut map,
|
||||
..
|
||||
} = self;
|
||||
|
|
@ -82,7 +82,7 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
|
|||
elements.push(a);
|
||||
|
||||
// if we changed the dimensions, clear the cache
|
||||
*closure.borrow_mut() = None;
|
||||
*closure.get_mut() = None;
|
||||
|
||||
Index(elements.len() - 1)
|
||||
})
|
||||
|
|
@ -122,7 +122,7 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
|
|||
self.edges.push(edge);
|
||||
|
||||
// added an edge, clear the cache
|
||||
*self.closure.borrow_mut() = None;
|
||||
*self.closure.get_mut() = None;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -443,7 +443,7 @@ impl<T> Decodable for TransitiveRelation<T>
|
|||
.enumerate()
|
||||
.map(|(index, elem)| (elem.clone(), Index(index)))
|
||||
.collect();
|
||||
Ok(TransitiveRelation { elements, edges, map, closure: RefCell::new(None) })
|
||||
Ok(TransitiveRelation { elements, edges, map, closure: Lock::new(None) })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -303,7 +303,9 @@ fn get_trans_sysroot(backend_name: &str) -> fn() -> Box<TransCrate> {
|
|||
let sysroot = sysroot_candidates.iter()
|
||||
.map(|sysroot| {
|
||||
let libdir = filesearch::relative_target_lib_path(&sysroot, &target);
|
||||
sysroot.join(libdir).with_file_name("codegen-backends")
|
||||
sysroot.join(libdir)
|
||||
.with_file_name(option_env!("CFG_CODEGEN_BACKENDS_DIR")
|
||||
.unwrap_or("codegen-backends"))
|
||||
})
|
||||
.filter(|f| {
|
||||
info!("codegen backend candidate: {}", f.display());
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ test = false
|
|||
|
||||
[dependencies]
|
||||
bitflags = "1.0"
|
||||
cc = "1.0.1"
|
||||
flate2 = "1.0"
|
||||
jobserver = "0.1.5"
|
||||
libc = "0.2"
|
||||
|
|
@ -21,7 +22,6 @@ rustc-demangle = "0.1.4"
|
|||
rustc_allocator = { path = "../librustc_allocator" }
|
||||
rustc_apfloat = { path = "../librustc_apfloat" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_binaryen = { path = "../librustc_binaryen" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
|
|
@ -35,9 +35,6 @@ syntax = { path = "../libsyntax" }
|
|||
syntax_pos = { path = "../libsyntax_pos" }
|
||||
tempdir = "0.3"
|
||||
|
||||
[target."cfg(windows)".dependencies]
|
||||
cc = "1.0.1"
|
||||
|
||||
[features]
|
||||
# Used to communicate the feature to `rustc_back` in the same manner that the
|
||||
# `rustc` driver script communicate this.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ use std::io;
|
|||
use std::mem;
|
||||
use std::process::{self, Output};
|
||||
|
||||
use rustc_back::LldFlavor;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Command {
|
||||
program: Program,
|
||||
|
|
@ -28,6 +30,7 @@ pub struct Command {
|
|||
enum Program {
|
||||
Normal(OsString),
|
||||
CmdBatScript(OsString),
|
||||
Lld(OsString, LldFlavor)
|
||||
}
|
||||
|
||||
impl Command {
|
||||
|
|
@ -39,6 +42,10 @@ impl Command {
|
|||
Command::_new(Program::CmdBatScript(program.as_ref().to_owned()))
|
||||
}
|
||||
|
||||
pub fn lld<P: AsRef<OsStr>>(program: P, flavor: LldFlavor) -> Command {
|
||||
Command::_new(Program::Lld(program.as_ref().to_owned(), flavor))
|
||||
}
|
||||
|
||||
fn _new(program: Program) -> Command {
|
||||
Command {
|
||||
program,
|
||||
|
|
@ -74,17 +81,6 @@ impl Command {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn envs<I, K, V>(&mut self, envs: I) -> &mut Command
|
||||
where I: IntoIterator<Item=(K, V)>,
|
||||
K: AsRef<OsStr>,
|
||||
V: AsRef<OsStr>
|
||||
{
|
||||
for (key, value) in envs {
|
||||
self._env(key.as_ref(), value.as_ref());
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn _env(&mut self, key: &OsStr, value: &OsStr) {
|
||||
self.env.push((key.to_owned(), value.to_owned()));
|
||||
}
|
||||
|
|
@ -101,6 +97,16 @@ impl Command {
|
|||
c.arg("/c").arg(p);
|
||||
c
|
||||
}
|
||||
Program::Lld(ref p, flavor) => {
|
||||
let mut c = process::Command::new(p);
|
||||
c.arg("-flavor").arg(match flavor {
|
||||
LldFlavor::Wasm => "wasm",
|
||||
LldFlavor::Ld => "gnu",
|
||||
LldFlavor::Link => "link",
|
||||
LldFlavor::Ld64 => "darwin",
|
||||
});
|
||||
c
|
||||
}
|
||||
};
|
||||
ret.args(&self.args);
|
||||
ret.envs(self.env.clone());
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use cc::windows_registry;
|
||||
use super::archive::{ArchiveBuilder, ArchiveConfig};
|
||||
use super::bytecode::RLIB_BYTECODE_EXTENSION;
|
||||
use super::linker::Linker;
|
||||
|
|
@ -15,6 +16,7 @@ use super::command::Command;
|
|||
use super::rpath::RPathConfig;
|
||||
use super::rpath;
|
||||
use metadata::METADATA_FILENAME;
|
||||
use rustc_back::LinkerFlavor;
|
||||
use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType, PrintRequest};
|
||||
use rustc::session::config::{RUST_CGU_EXT, Lto};
|
||||
use rustc::session::filesearch;
|
||||
|
|
@ -27,14 +29,13 @@ use rustc::util::common::time;
|
|||
use rustc::util::fs::fix_windows_verbatim_for_gcc;
|
||||
use rustc::hir::def_id::CrateNum;
|
||||
use tempdir::TempDir;
|
||||
use rustc_back::{PanicStrategy, RelroLevel, LinkerFlavor};
|
||||
use rustc_back::{PanicStrategy, RelroLevel};
|
||||
use context::get_reloc_model;
|
||||
use llvm;
|
||||
|
||||
use std::ascii;
|
||||
use std::char;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::io;
|
||||
|
|
@ -57,9 +58,7 @@ pub use rustc_trans_utils::link::{find_crate_name, filename_for_input, default_o
|
|||
// The third parameter is for env vars, used on windows to set up the
|
||||
// path for MSVC to find its DLLs, and gcc to find its bundled
|
||||
// toolchain
|
||||
pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString)>) {
|
||||
let envs = vec![("PATH".into(), command_path(sess))];
|
||||
|
||||
pub fn get_linker(sess: &Session) -> (PathBuf, Command) {
|
||||
// If our linker looks like a batch script on Windows then to execute this
|
||||
// we'll need to spawn `cmd` explicitly. This is primarily done to handle
|
||||
// emscripten where the linker is `emcc.bat` and needs to be spawned as
|
||||
|
|
@ -74,56 +73,57 @@ pub fn get_linker(sess: &Session) -> (PathBuf, Command, Vec<(OsString, OsString)
|
|||
return Command::bat_script(linker)
|
||||
}
|
||||
}
|
||||
Command::new(linker)
|
||||
match sess.linker_flavor() {
|
||||
LinkerFlavor::Lld(f) => Command::lld(linker, f),
|
||||
_ => Command::new(linker),
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(ref linker) = sess.opts.cg.linker {
|
||||
(linker.clone(), cmd(linker), envs)
|
||||
} else if sess.target.target.options.is_like_msvc {
|
||||
let (cmd, envs) = msvc_link_exe_cmd(sess);
|
||||
(PathBuf::from("link.exe"), cmd, envs)
|
||||
} else {
|
||||
let linker = PathBuf::from(&sess.target.target.options.linker);
|
||||
let cmd = cmd(&linker);
|
||||
(linker, cmd, envs)
|
||||
}
|
||||
}
|
||||
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple, "link.exe");
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn msvc_link_exe_cmd(sess: &Session) -> (Command, Vec<(OsString, OsString)>) {
|
||||
use cc::windows_registry;
|
||||
let linker_path = sess.opts.cg.linker.as_ref().map(|s| &**s)
|
||||
.or(sess.target.target.options.linker.as_ref().map(|s| s.as_ref()))
|
||||
.unwrap_or(match sess.linker_flavor() {
|
||||
LinkerFlavor::Msvc => {
|
||||
msvc_tool.as_ref().map(|t| t.path()).unwrap_or("link.exe".as_ref())
|
||||
}
|
||||
LinkerFlavor::Em if cfg!(windows) => "emcc.bat".as_ref(),
|
||||
LinkerFlavor::Em => "emcc".as_ref(),
|
||||
LinkerFlavor::Gcc => "cc".as_ref(),
|
||||
LinkerFlavor::Ld => "ld".as_ref(),
|
||||
LinkerFlavor::Lld(_) => "lld".as_ref(),
|
||||
});
|
||||
|
||||
let target = &sess.opts.target_triple;
|
||||
let tool = windows_registry::find_tool(target, "link.exe");
|
||||
let mut cmd = cmd(linker_path);
|
||||
|
||||
if let Some(tool) = tool {
|
||||
let mut cmd = Command::new(tool.path());
|
||||
cmd.args(tool.args());
|
||||
for &(ref k, ref v) in tool.env() {
|
||||
cmd.env(k, v);
|
||||
}
|
||||
let envs = tool.env().to_vec();
|
||||
(cmd, envs)
|
||||
} else {
|
||||
debug!("Failed to locate linker.");
|
||||
(Command::new("link.exe"), vec![])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn msvc_link_exe_cmd(_sess: &Session) -> (Command, Vec<(OsString, OsString)>) {
|
||||
(Command::new("link.exe"), vec![])
|
||||
}
|
||||
|
||||
fn command_path(sess: &Session) -> OsString {
|
||||
// The compiler's sysroot often has some bundled tools, so add it to the
|
||||
// PATH for the child.
|
||||
let mut new_path = sess.host_filesearch(PathKind::All)
|
||||
.get_tools_search_paths();
|
||||
if let Some(path) = env::var_os("PATH") {
|
||||
new_path.extend(env::split_paths(&path));
|
||||
let mut msvc_changed_path = false;
|
||||
if sess.target.target.options.is_like_msvc {
|
||||
if let Some(ref tool) = msvc_tool {
|
||||
cmd.args(tool.args());
|
||||
for &(ref k, ref v) in tool.env() {
|
||||
if k == "PATH" {
|
||||
new_path.extend(env::split_paths(v));
|
||||
msvc_changed_path = true;
|
||||
} else {
|
||||
cmd.env(k, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
env::join_paths(new_path).unwrap()
|
||||
|
||||
if !msvc_changed_path {
|
||||
if let Some(path) = env::var_os("PATH") {
|
||||
new_path.extend(env::split_paths(&path));
|
||||
}
|
||||
}
|
||||
cmd.env("PATH", env::join_paths(new_path).unwrap());
|
||||
|
||||
(linker_path.to_path_buf(), cmd)
|
||||
}
|
||||
|
||||
pub fn remove(sess: &Session, path: &Path) {
|
||||
|
|
@ -612,15 +612,8 @@ fn link_natively(sess: &Session,
|
|||
info!("preparing {:?} to {:?}", crate_type, out_filename);
|
||||
let flavor = sess.linker_flavor();
|
||||
|
||||
// The "binaryen linker" is massively special, so skip everything below.
|
||||
if flavor == LinkerFlavor::Binaryen {
|
||||
return link_binaryen(sess, crate_type, out_filename, trans, tmpdir);
|
||||
}
|
||||
|
||||
// The invocations of cc share some flags across platforms
|
||||
let (pname, mut cmd, envs) = get_linker(sess);
|
||||
// This will set PATH on windows
|
||||
cmd.envs(envs);
|
||||
let (pname, mut cmd) = get_linker(sess);
|
||||
|
||||
let root = sess.target_filesearch(PathKind::Native).get_lib_path();
|
||||
if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
|
||||
|
|
@ -1485,33 +1478,6 @@ fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
/// For now "linking with binaryen" is just "move the one module we generated in
|
||||
/// the backend to the final output"
|
||||
///
|
||||
/// That is, all the heavy lifting happens during the `back::write` phase. Here
|
||||
/// we just clean up after that.
|
||||
///
|
||||
/// Note that this is super temporary and "will not survive the night", this is
|
||||
/// guaranteed to get removed as soon as a linker for wasm exists. This should
|
||||
/// not be used for anything other than wasm.
|
||||
fn link_binaryen(sess: &Session,
|
||||
_crate_type: config::CrateType,
|
||||
out_filename: &Path,
|
||||
trans: &CrateTranslation,
|
||||
_tmpdir: &Path) {
|
||||
assert!(trans.allocator_module.is_none());
|
||||
assert_eq!(trans.modules.len(), 1);
|
||||
|
||||
let object = trans.modules[0].object.as_ref().expect("object must exist");
|
||||
let res = fs::hard_link(object, out_filename)
|
||||
.or_else(|_| fs::copy(object, out_filename).map(|_| ()));
|
||||
if let Err(e) = res {
|
||||
sess.fatal(&format!("failed to create `{}`: {}",
|
||||
out_filename.display(),
|
||||
e));
|
||||
}
|
||||
}
|
||||
|
||||
fn is_full_lto_enabled(sess: &Session) -> bool {
|
||||
match sess.lto() {
|
||||
Lto::Yes |
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ use rustc::middle::dependency_format::Linkage;
|
|||
use rustc::session::Session;
|
||||
use rustc::session::config::{self, CrateType, OptLevel, DebugInfoLevel};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_back::LinkerFlavor;
|
||||
use rustc_back::{LinkerFlavor, LldFlavor};
|
||||
use serialize::{json, Encoder};
|
||||
|
||||
/// For all the linkers we support, and information they might
|
||||
|
|
@ -45,6 +45,7 @@ impl LinkerInfo {
|
|||
cmd: Command,
|
||||
sess: &'a Session) -> Box<Linker+'a> {
|
||||
match sess.linker_flavor() {
|
||||
LinkerFlavor::Lld(LldFlavor::Link) |
|
||||
LinkerFlavor::Msvc => {
|
||||
Box::new(MsvcLinker {
|
||||
cmd,
|
||||
|
|
@ -68,6 +69,9 @@ impl LinkerInfo {
|
|||
is_ld: false,
|
||||
}) as Box<Linker>
|
||||
}
|
||||
|
||||
LinkerFlavor::Lld(LldFlavor::Ld) |
|
||||
LinkerFlavor::Lld(LldFlavor::Ld64) |
|
||||
LinkerFlavor::Ld => {
|
||||
Box::new(GccLinker {
|
||||
cmd,
|
||||
|
|
@ -77,8 +81,11 @@ impl LinkerInfo {
|
|||
is_ld: true,
|
||||
}) as Box<Linker>
|
||||
}
|
||||
LinkerFlavor::Binaryen => {
|
||||
panic!("can't instantiate binaryen linker")
|
||||
|
||||
LinkerFlavor::Lld(LldFlavor::Wasm) => {
|
||||
Box::new(WasmLd {
|
||||
cmd,
|
||||
}) as Box<Linker>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -785,3 +792,111 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec<String> {
|
|||
|
||||
symbols
|
||||
}
|
||||
|
||||
pub struct WasmLd {
|
||||
cmd: Command,
|
||||
}
|
||||
|
||||
impl Linker for WasmLd {
|
||||
fn link_dylib(&mut self, lib: &str) {
|
||||
self.cmd.arg("-l").arg(lib);
|
||||
}
|
||||
|
||||
fn link_staticlib(&mut self, lib: &str) {
|
||||
self.cmd.arg("-l").arg(lib);
|
||||
}
|
||||
|
||||
fn link_rlib(&mut self, lib: &Path) {
|
||||
self.cmd.arg(lib);
|
||||
}
|
||||
|
||||
fn include_path(&mut self, path: &Path) {
|
||||
self.cmd.arg("-L").arg(path);
|
||||
}
|
||||
|
||||
fn framework_path(&mut self, _path: &Path) {
|
||||
panic!("frameworks not supported")
|
||||
}
|
||||
|
||||
fn output_filename(&mut self, path: &Path) {
|
||||
self.cmd.arg("-o").arg(path);
|
||||
}
|
||||
|
||||
fn add_object(&mut self, path: &Path) {
|
||||
self.cmd.arg(path);
|
||||
}
|
||||
|
||||
fn position_independent_executable(&mut self) {
|
||||
}
|
||||
|
||||
fn partial_relro(&mut self) {
|
||||
}
|
||||
|
||||
fn full_relro(&mut self) {
|
||||
}
|
||||
|
||||
fn build_static_executable(&mut self) {
|
||||
}
|
||||
|
||||
fn args(&mut self, args: &[String]) {
|
||||
self.cmd.args(args);
|
||||
}
|
||||
|
||||
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
|
||||
self.cmd.arg("-l").arg(lib);
|
||||
}
|
||||
|
||||
fn link_framework(&mut self, _framework: &str) {
|
||||
panic!("frameworks not supported")
|
||||
}
|
||||
|
||||
fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
|
||||
self.cmd.arg("-l").arg(lib);
|
||||
}
|
||||
|
||||
fn link_whole_rlib(&mut self, lib: &Path) {
|
||||
self.cmd.arg(lib);
|
||||
}
|
||||
|
||||
fn gc_sections(&mut self, _keep_metadata: bool) {
|
||||
}
|
||||
|
||||
fn optimize(&mut self) {
|
||||
}
|
||||
|
||||
fn debuginfo(&mut self) {
|
||||
}
|
||||
|
||||
fn no_default_libraries(&mut self) {
|
||||
}
|
||||
|
||||
fn build_dylib(&mut self, _out_filename: &Path) {
|
||||
}
|
||||
|
||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {
|
||||
}
|
||||
|
||||
fn subsystem(&mut self, _subsystem: &str) {
|
||||
}
|
||||
|
||||
fn no_position_independent_executable(&mut self) {
|
||||
}
|
||||
|
||||
fn finalize(&mut self) -> Command {
|
||||
self.cmd.arg("--threads");
|
||||
|
||||
// FIXME we probably shouldn't pass this but instead pass an explicit
|
||||
// whitelist of symbols we'll allow to be undefined. Unfortunately
|
||||
// though we can't handle symbols like `log10` that LLVM injects at a
|
||||
// super late date without actually parsing object files. For now let's
|
||||
// stick to this and hopefully fix it before stabilization happens.
|
||||
self.cmd.arg("--allow-undefined");
|
||||
|
||||
// For now we just never have an entry symbol
|
||||
self.cmd.arg("--no-entry");
|
||||
|
||||
let mut cmd = Command::new("");
|
||||
::std::mem::swap(&mut cmd, &mut self.cmd);
|
||||
cmd
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ use rustc::ty::TyCtxt;
|
|||
use rustc::ty::maps::Providers;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_allocator::ALLOCATOR_METHODS;
|
||||
use rustc_back::LinkerFlavor;
|
||||
use syntax::attr;
|
||||
|
||||
pub type ExportedSymbols = FxHashMap<
|
||||
|
|
@ -156,26 +155,12 @@ pub fn provide_extern(providers: &mut Providers) {
|
|||
let special_runtime_crate =
|
||||
tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum);
|
||||
|
||||
// Dealing with compiler-builtins and wasm right now is super janky.
|
||||
// There's no linker! As a result we need all of the compiler-builtins
|
||||
// exported symbols to make their way through all the way to the end of
|
||||
// compilation. We want to make sure that LLVM doesn't remove them as
|
||||
// well because we may or may not need them in the final output
|
||||
// artifact. For now just force them to always get exported at the C
|
||||
// layer, and we'll worry about gc'ing them later.
|
||||
let compiler_builtins_and_binaryen =
|
||||
tcx.is_compiler_builtins(cnum) &&
|
||||
tcx.sess.linker_flavor() == LinkerFlavor::Binaryen;
|
||||
|
||||
let mut crate_exports: Vec<_> = tcx
|
||||
.exported_symbol_ids(cnum)
|
||||
.iter()
|
||||
.map(|&def_id| {
|
||||
let name = tcx.symbol_name(Instance::mono(tcx, def_id));
|
||||
let export_level = if compiler_builtins_and_binaryen &&
|
||||
tcx.contains_extern_indicator(def_id) {
|
||||
SymbolExportLevel::C
|
||||
} else if special_runtime_crate {
|
||||
let export_level = if special_runtime_crate {
|
||||
// We can probably do better here by just ensuring that
|
||||
// it has hidden visibility rather than public
|
||||
// visibility, as this is primarily here to ensure it's
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ use rustc::session::config::{self, OutputFilenames, OutputType, Passes, SomePass
|
|||
AllPasses, Sanitizer, Lto};
|
||||
use rustc::session::Session;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_back::LinkerFlavor;
|
||||
use time_graph::{self, TimeGraph, Timeline};
|
||||
use llvm;
|
||||
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef};
|
||||
|
|
@ -344,9 +343,7 @@ pub struct CodegenContext {
|
|||
pub tm_factory: Arc<Fn() -> Result<TargetMachineRef, String> + Send + Sync>,
|
||||
pub msvc_imps_needed: bool,
|
||||
pub target_pointer_width: String,
|
||||
binaryen_linker: bool,
|
||||
debuginfo: config::DebugInfoLevel,
|
||||
wasm_import_memory: bool,
|
||||
|
||||
// Number of cgus excluding the allocator/metadata modules
|
||||
pub total_cgus: usize,
|
||||
|
|
@ -639,13 +636,6 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
f(cpm)
|
||||
}
|
||||
|
||||
// If we're going to generate wasm code from the assembly that llvm
|
||||
// generates then we'll be transitively affecting a ton of options below.
|
||||
// This only happens on the wasm target now.
|
||||
let asm2wasm = cgcx.binaryen_linker &&
|
||||
!cgcx.crate_types.contains(&config::CrateTypeRlib) &&
|
||||
mtrans.kind == ModuleKind::Regular;
|
||||
|
||||
// If we don't have the integrated assembler, then we need to emit asm
|
||||
// from LLVM and use `gcc` to create the object file.
|
||||
let asm_to_obj = config.emit_obj && config.no_integrated_as;
|
||||
|
|
@ -654,10 +644,10 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
// just llvm bitcode. In that case write bitcode, and possibly
|
||||
// delete the bitcode if it wasn't requested. Don't generate the
|
||||
// machine code, instead copy the .o file from the .bc
|
||||
let write_bc = config.emit_bc || (config.obj_is_bitcode && !asm2wasm);
|
||||
let rm_bc = !config.emit_bc && config.obj_is_bitcode && !asm2wasm;
|
||||
let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm2wasm && !asm_to_obj;
|
||||
let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode && !asm2wasm;
|
||||
let write_bc = config.emit_bc || config.obj_is_bitcode;
|
||||
let rm_bc = !config.emit_bc && config.obj_is_bitcode;
|
||||
let write_obj = config.emit_obj && !config.obj_is_bitcode && !asm_to_obj;
|
||||
let copy_bc_to_obj = config.emit_obj && config.obj_is_bitcode;
|
||||
|
||||
let bc_out = cgcx.output_filenames.temp_path(OutputType::Bitcode, module_name);
|
||||
let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, module_name);
|
||||
|
|
@ -736,13 +726,13 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
timeline.record("ir");
|
||||
}
|
||||
|
||||
if config.emit_asm || (asm2wasm && config.emit_obj) || asm_to_obj {
|
||||
if config.emit_asm || asm_to_obj {
|
||||
let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
||||
|
||||
// We can't use the same module for asm and binary output, because that triggers
|
||||
// various errors like invalid IR or broken binaries, so we might have to clone the
|
||||
// module to produce the asm output
|
||||
let llmod = if config.emit_obj && !asm2wasm {
|
||||
let llmod = if config.emit_obj {
|
||||
llvm::LLVMCloneModule(llmod)
|
||||
} else {
|
||||
llmod
|
||||
|
|
@ -751,24 +741,13 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
write_output_file(diag_handler, tm, cpm, llmod, &path,
|
||||
llvm::FileType::AssemblyFile)
|
||||
})?;
|
||||
if config.emit_obj && !asm2wasm {
|
||||
if config.emit_obj {
|
||||
llvm::LLVMDisposeModule(llmod);
|
||||
}
|
||||
timeline.record("asm");
|
||||
}
|
||||
|
||||
if asm2wasm && config.emit_obj {
|
||||
let assembly = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
|
||||
let suffix = ".wasm.map"; // FIXME use target suffix
|
||||
let map = cgcx.output_filenames.path(OutputType::Exe)
|
||||
.with_extension(&suffix[1..]);
|
||||
binaryen_assemble(cgcx, diag_handler, &assembly, &obj_out, &map);
|
||||
timeline.record("binaryen");
|
||||
|
||||
if !config.emit_asm {
|
||||
drop(fs::remove_file(&assembly));
|
||||
}
|
||||
} else if write_obj {
|
||||
if write_obj {
|
||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||
write_output_file(diag_handler, tm, cpm, llmod, &obj_out,
|
||||
llvm::FileType::ObjectFile)
|
||||
|
|
@ -808,49 +787,6 @@ unsafe fn codegen(cgcx: &CodegenContext,
|
|||
&cgcx.output_filenames))
|
||||
}
|
||||
|
||||
/// Translates the LLVM-generated `assembly` on the filesystem into a wasm
|
||||
/// module using binaryen, placing the output at `object`.
|
||||
///
|
||||
/// In this case the "object" is actually a full and complete wasm module. We
|
||||
/// won't actually be doing anything else to the output for now. This is all
|
||||
/// pretty janky and will get removed as soon as a linker for wasm exists.
|
||||
fn binaryen_assemble(cgcx: &CodegenContext,
|
||||
handler: &Handler,
|
||||
assembly: &Path,
|
||||
object: &Path,
|
||||
map: &Path) {
|
||||
use rustc_binaryen::{Module, ModuleOptions};
|
||||
|
||||
let input = fs::read(&assembly).and_then(|contents| {
|
||||
Ok(CString::new(contents)?)
|
||||
});
|
||||
let mut options = ModuleOptions::new();
|
||||
if cgcx.debuginfo != config::NoDebugInfo {
|
||||
options.debuginfo(true);
|
||||
let map_file_name = map.file_name().unwrap();
|
||||
options.source_map_url(map_file_name.to_str().unwrap());
|
||||
}
|
||||
|
||||
options.stack(1024 * 1024);
|
||||
options.import_memory(cgcx.wasm_import_memory);
|
||||
let assembled = input.and_then(|input| {
|
||||
Module::new(&input, &options)
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))
|
||||
});
|
||||
let err = assembled.and_then(|binary| {
|
||||
fs::write(&object, binary.data()).and_then(|()| {
|
||||
if cgcx.debuginfo != config::NoDebugInfo {
|
||||
fs::write(map, binary.source_map())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
});
|
||||
if let Err(e) = err {
|
||||
handler.err(&format!("failed to run binaryen assembler: {}", e));
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct CompiledModules {
|
||||
pub modules: Vec<CompiledModule>,
|
||||
pub metadata_module: CompiledModule,
|
||||
|
|
@ -1431,12 +1367,9 @@ fn start_executing_work(tcx: TyCtxt,
|
|||
each_linked_rlib_for_lto.push((cnum, path.to_path_buf()));
|
||||
}));
|
||||
|
||||
let wasm_import_memory =
|
||||
attr::contains_name(&tcx.hir.krate().attrs, "wasm_import_memory");
|
||||
|
||||
let assembler_cmd = if modules_config.no_integrated_as {
|
||||
// HACK: currently we use linker (gcc) as our assembler
|
||||
let (name, mut cmd, _) = get_linker(sess);
|
||||
let (name, mut cmd) = get_linker(sess);
|
||||
cmd.args(&sess.target.target.options.asm_args);
|
||||
Some(Arc::new(AssemblerCommand {
|
||||
name,
|
||||
|
|
@ -1471,9 +1404,7 @@ fn start_executing_work(tcx: TyCtxt,
|
|||
total_cgus,
|
||||
msvc_imps_needed: msvc_imps_needed(tcx),
|
||||
target_pointer_width: tcx.sess.target.target.target_pointer_width.clone(),
|
||||
binaryen_linker: tcx.sess.linker_flavor() == LinkerFlavor::Binaryen,
|
||||
debuginfo: tcx.sess.opts.debuginfo,
|
||||
wasm_import_memory,
|
||||
assembler_cmd,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ extern crate rustc_mir;
|
|||
extern crate rustc_allocator;
|
||||
extern crate rustc_apfloat;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_binaryen;
|
||||
extern crate rustc_const_math;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_demangle;
|
||||
|
|
@ -63,7 +62,6 @@ extern crate rustc_trans_utils;
|
|||
extern crate syntax_pos;
|
||||
extern crate rustc_errors as errors;
|
||||
extern crate serialize;
|
||||
#[cfg(windows)]
|
||||
extern crate cc; // Used to locate MSVC
|
||||
extern crate tempdir;
|
||||
|
||||
|
|
|
|||
172
src/librustdoc/README.md
Normal file
172
src/librustdoc/README.md
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
# The walking tour of rustdoc
|
||||
|
||||
Rustdoc is implemented entirely within the crate `librustdoc`. After partially compiling a crate to
|
||||
get its AST (technically the HIR map) from rustc, librustdoc performs two major steps past that to
|
||||
render a set of documentation:
|
||||
|
||||
* "Clean" the AST into a form that's more suited to creating documentation (and slightly more
|
||||
resistant to churn in the compiler).
|
||||
* Use this cleaned AST to render a crate's documentation, one page at a time.
|
||||
|
||||
Naturally, there's more than just this, and those descriptions simplify out lots of details, but
|
||||
that's the high-level overview.
|
||||
|
||||
(Side note: this is a library crate! The `rustdoc` binary is crated using the project in
|
||||
`src/tools/rustdoc`. Note that literally all that does is call the `main()` that's in this crate's
|
||||
`lib.rs`, though.)
|
||||
|
||||
## Cheat sheet
|
||||
|
||||
* Use `x.py build --stage 1 src/libstd src/tools/rustdoc` to make a useable rustdoc you can run on
|
||||
other projects.
|
||||
* Add `src/libtest` to be able to use `rustdoc --test`.
|
||||
* If you've used `rustup toolchain link local /path/to/build/$TARGET/stage1` previously, then
|
||||
after the previous build command, `cargo +local doc` will Just Work.
|
||||
* Use `x.py doc --stage 1 src/libstd` to use this rustdoc to generate the standard library docs.
|
||||
* The completed docs will be available in `build/$TARGET/doc/std`, though the bundle is meant to
|
||||
be used as though you would copy out the `doc` folder to a web server, since that's where the
|
||||
CSS/JS and landing page are.
|
||||
* Most of the HTML printing code is in `html/format.rs` and `html/render.rs`. It's in a bunch of
|
||||
`fmt::Display` implementations and supplementary functions.
|
||||
* The types that got `Display` impls above are defined in `clean/mod.rs`, right next to the custom
|
||||
`Clean` trait used to process them out of the rustc HIR.
|
||||
* The bits specific to using rustdoc as a test harness are in `test.rs`.
|
||||
* The Markdown renderer is loaded up in `html/markdown.rs`, including functions for extracting
|
||||
doctests from a given block of Markdown.
|
||||
* The tests on rustdoc *output* are located in `src/test/rustdoc`, where they're handled by the test
|
||||
runner of rustbuild and the supplementary script `src/etc/htmldocck.py`.
|
||||
* Tests on search index generation are located in `src/test/rustdoc-js`, as a series of JavaScript
|
||||
files that encode queries on the standard library search index and expected results.
|
||||
|
||||
## From crate to clean
|
||||
|
||||
In `core.rs` are two central items: the `DocContext` struct, and the `run_core` function. The latter
|
||||
is where rustdoc calls out to rustc to compile a crate to the point where rustdoc can take over. The
|
||||
former is a state container used when crawling through a crate to gather its documentation.
|
||||
|
||||
The main process of crate crawling is done in `clean/mod.rs` through several implementations of the
|
||||
`Clean` trait defined within. This is a conversion trait, which defines one method:
|
||||
|
||||
```rust
|
||||
pub trait Clean<T> {
|
||||
fn clean(&self, cx: &DocContext) -> T;
|
||||
}
|
||||
```
|
||||
|
||||
`clean/mod.rs` also defines the types for the "cleaned" AST used later on to render documentation
|
||||
pages. Each usually accompanies an implementation of `Clean` that takes some AST or HIR type from
|
||||
rustc and converts it into the appropriate "cleaned" type. "Big" items like modules or associated
|
||||
items may have some extra processing in its `Clean` implementation, but for the most part these
|
||||
impls are straightforward conversions. The "entry point" to this module is the `impl Clean<Crate>
|
||||
for visit_ast::RustdocVisitor`, which is called by `run_core` above.
|
||||
|
||||
You see, I actually lied a little earlier: There's another AST transformation that happens before
|
||||
the events in `clean/mod.rs`. In `visit_ast.rs` is the type `RustdocVisitor`, which *actually*
|
||||
crawls a `hir::Crate` to get the first intermediate representation, defined in `doctree.rs`. This
|
||||
pass is mainly to get a few intermediate wrappers around the HIR types and to process visibility
|
||||
and inlining. This is where `#[doc(inline)]`, `#[doc(no_inline)]`, and `#[doc(hidden)]` are
|
||||
processed, as well as the logic for whether a `pub use` should get the full page or a "Reexport"
|
||||
line in the module page.
|
||||
|
||||
The other major thing that happens in `clean/mod.rs` is the collection of doc comments and
|
||||
`#[doc=""]` attributes into a separate field of the Attributes struct, present on anything that gets
|
||||
hand-written documentation. This makes it easier to collect this documentation later in the process.
|
||||
|
||||
The primary output of this process is a clean::Crate with a tree of Items which describe the
|
||||
publicly-documentable items in the target crate.
|
||||
|
||||
### Hot potato
|
||||
|
||||
Before moving on to the next major step, a few important "passes" occur over the documentation.
|
||||
These do things like combine the separate "attributes" into a single string and strip leading
|
||||
whitespace to make the document easier on the markdown parser, or drop items that are not public or
|
||||
deliberately hidden with `#[doc(hidden)]`. These are all implemented in the `passes/` directory, one
|
||||
file per pass. By default, all of these passes are run on a crate, but the ones regarding dropping
|
||||
private/hidden items can be bypassed by passing `--document-private-items` to rustdoc.
|
||||
|
||||
(Strictly speaking, you can fine-tune the passes run and even add your own, but [we're trying to
|
||||
deprecate that][44136]. If you need finer-grain control over these passes, please let us know!)
|
||||
|
||||
[44136]: https://github.com/rust-lang/rust/issues/44136
|
||||
|
||||
## From clean to crate
|
||||
|
||||
This is where the "second phase" in rustdoc begins. This phase primarily lives in the `html/`
|
||||
folder, and it all starts with `run()` in `html/render.rs`. This code is responsible for setting up
|
||||
the `Context`, `SharedContext`, and `Cache` which are used during rendering, copying out the static
|
||||
files which live in every rendered set of documentation (things like the fonts, CSS, and JavaScript
|
||||
that live in `html/static/`), creating the search index, and printing out the source code rendering,
|
||||
before beginning the process of rendering all the documentation for the crate.
|
||||
|
||||
Several functions implemented directly on `Context` take the `clean::Crate` and set up some state
|
||||
between rendering items or recursing on a module's child items. From here the "page rendering"
|
||||
begins, via an enormous `write!()` call in `html/layout.rs`. The parts that actually generate HTML
|
||||
from the items and documentation occurs within a series of `std::fmt::Display` implementations and
|
||||
functions that pass around a `&mut std::fmt::Formatter`. The top-level implementation that writes
|
||||
out the page body is the `impl<'a> fmt::Display for Item<'a>` in `html/render.rs`, which switches
|
||||
out to one of several `item_*` functions based on the kind of `Item` being rendered.
|
||||
|
||||
Depending on what kind of rendering code you're looking for, you'll probably find it either in
|
||||
`html/render.rs` for major items like "what sections should I print for a struct page" or
|
||||
`html/format.rs` for smaller component pieces like "how should I print a where clause as part of
|
||||
some other item".
|
||||
|
||||
Whenever rustdoc comes across an item that should print hand-written documentation alongside, it
|
||||
calls out to `html/markdown.rs` which interfaces with the Markdown parser. This is exposed as a
|
||||
series of types that wrap a string of Markdown, and implement `fmt::Display` to emit HTML text. It
|
||||
takes special care to enable certain features like footnotes and tables and add syntax highlighting
|
||||
to Rust code blocks (via `html/highlight.rs`) before running the Markdown parser. There's also a
|
||||
function in here (`find_testable_code`) that specifically scans for Rust code blocks so the
|
||||
test-runner code can find all the doctests in the crate.
|
||||
|
||||
### From soup to nuts
|
||||
|
||||
(alternate title: ["An unbroken thread that stretches from those first `Cell`s to us"][video])
|
||||
|
||||
[video]: https://www.youtube.com/watch?v=hOLAGYmUQV0
|
||||
|
||||
It's important to note that the AST cleaning can ask the compiler for information (crucially,
|
||||
`DocContext` contains a `TyCtxt`), but page rendering cannot. The `clean::Crate` created within
|
||||
`run_core` is passed outside the compiler context before being handed to `html::render::run`. This
|
||||
means that a lot of the "supplementary data" that isn't immediately available inside an item's
|
||||
definition, like which trait is the `Deref` trait used by the language, needs to be collected during
|
||||
cleaning, stored in the `DocContext`, and passed along to the `SharedContext` during HTML rendering.
|
||||
This manifests as a bunch of shared state, context variables, and `RefCell`s.
|
||||
|
||||
Also of note is that some items that come from "asking the compiler" don't go directly into the
|
||||
`DocContext` - for example, when loading items from a foreign crate, rustdoc will ask about trait
|
||||
implementations and generate new `Item`s for the impls based on that information. This goes directly
|
||||
into the returned `Crate` rather than roundabout through the `DocContext`. This way, these
|
||||
implementations can be collected alongside the others, right before rendering the HTML.
|
||||
|
||||
## Other tricks up its sleeve
|
||||
|
||||
All this describes the process for generating HTML documentation from a Rust crate, but there are
|
||||
couple other major modes that rustdoc runs in. It can also be run on a standalone Markdown file, or
|
||||
it can run doctests on Rust code or standalone Markdown files. For the former, it shortcuts straight
|
||||
to `html/markdown.rs`, optionally including a mode which inserts a Table of Contents to the output
|
||||
HTML.
|
||||
|
||||
For the latter, rustdoc runs a similar partial-compilation to get relevant documentation in
|
||||
`test.rs`, but instead of going through the full clean and render process, it runs a much simpler
|
||||
crate walk to grab *just* the hand-written documentation. Combined with the aforementioned
|
||||
"`find_testable_code`" in `html/markdown.rs`, it builds up a collection of tests to run before
|
||||
handing them off to the libtest test runner. One notable location in `test.rs` is the function
|
||||
`make_test`, which is where hand-written doctests get transformed into something that can be
|
||||
executed.
|
||||
|
||||
## Dotting i's and crossing t's
|
||||
|
||||
So that's rustdoc's code in a nutshell, but there's more things in the repo that deal with it. Since
|
||||
we have the full `compiletest` suite at hand, there's a set of tests in `src/test/rustdoc` that make
|
||||
sure the final HTML is what we expect in various situations. These tests also use a supplementary
|
||||
script, `src/etc/htmldocck.py`, that allows it to look through the final HTML using XPath notation
|
||||
to get a precise look at the output. The full description of all the commands available to rustdoc
|
||||
tests is in `htmldocck.py`.
|
||||
|
||||
In addition, there are separate tests for the search index and rustdoc's ability to query it. The
|
||||
files in `src/test/rustdoc-js` each contain a different search query and the expected results,
|
||||
broken out by search tab. These files are processed by a script in `src/tools/rustdoc-js` and the
|
||||
Node.js runtime. These tests don't have as thorough of a writeup, but a broad example that features
|
||||
results in all tabs can be found in `basic.js`. The basic idea is that you match a given `QUERY`
|
||||
with a set of `EXPECTED` results, complete with the full item path of each item.
|
||||
|
|
@ -299,6 +299,7 @@
|
|||
#![feature(rand)]
|
||||
#![feature(raw)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(stdsimd)]
|
||||
#![feature(sip_hash_13)]
|
||||
#![feature(slice_bytes)]
|
||||
#![feature(slice_concat_ext)]
|
||||
|
|
@ -501,6 +502,35 @@ mod memchr;
|
|||
// compiler
|
||||
pub mod rt;
|
||||
|
||||
// Pull in the the `stdsimd` crate directly into libstd. This is the same as
|
||||
// libcore's arch/simd modules where the source of truth here is in a different
|
||||
// repository, but we pull things in here manually to get it into libstd.
|
||||
//
|
||||
// Note that the #[cfg] here is intended to do two things. First it allows us to
|
||||
// change the rustc implementation of intrinsics in stage0 by not compiling simd
|
||||
// intrinsics in stage0. Next it doesn't compile anything in test mode as
|
||||
// stdsimd has tons of its own tests which we don't want to run.
|
||||
#[path = "../stdsimd/stdsimd/mod.rs"]
|
||||
#[allow(missing_debug_implementations, missing_docs, dead_code)]
|
||||
#[unstable(feature = "stdsimd", issue = "48556")]
|
||||
#[cfg(all(not(stage0), not(test)))]
|
||||
mod stdsimd;
|
||||
|
||||
// A "fake" module needed by the `stdsimd` module to compile, not actually
|
||||
// exported though.
|
||||
#[cfg(not(stage0))]
|
||||
mod coresimd {
|
||||
pub use core::arch;
|
||||
pub use core::simd;
|
||||
}
|
||||
|
||||
#[unstable(feature = "stdsimd", issue = "48556")]
|
||||
#[cfg(all(not(stage0), not(test)))]
|
||||
pub use stdsimd::simd;
|
||||
#[unstable(feature = "stdsimd", issue = "48556")]
|
||||
#[cfg(all(not(stage0), not(test)))]
|
||||
pub use stdsimd::arch;
|
||||
|
||||
// Include a number of private modules that exist solely to provide
|
||||
// the rustdoc documentation for primitive types. Using `include!`
|
||||
// because rustdoc only looks for these modules at the crate level.
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ pub use version::UnicodeVersion;
|
|||
/// [`to_lowercase`]: ../../std/primitive.char.html#method.to_lowercase
|
||||
/// [`char`]: ../../std/primitive.char.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ToLowercase(CaseMappingIter);
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -81,7 +81,7 @@ impl FusedIterator for ToLowercase {}
|
|||
/// [`to_uppercase`]: ../../std/primitive.char.html#method.to_uppercase
|
||||
/// [`char`]: ../../std/primitive.char.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ToUppercase(CaseMappingIter);
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
@ -95,7 +95,7 @@ impl Iterator for ToUppercase {
|
|||
#[unstable(feature = "fused", issue = "35602")]
|
||||
impl FusedIterator for ToUppercase {}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
enum CaseMappingIter {
|
||||
Three(char, char, char),
|
||||
Two(char, char),
|
||||
|
|
|
|||
|
|
@ -414,9 +414,6 @@ declare_features! (
|
|||
// Allow trait methods with arbitrary self types
|
||||
(active, arbitrary_self_types, "1.23.0", Some(44874)),
|
||||
|
||||
// #![wasm_import_memory] attribute
|
||||
(active, wasm_import_memory, "1.22.0", None),
|
||||
|
||||
// `crate` in paths
|
||||
(active, crate_in_paths, "1.23.0", Some(45477)),
|
||||
|
||||
|
|
@ -985,11 +982,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
|
|||
never be stable",
|
||||
cfg_fn!(rustc_attrs))),
|
||||
|
||||
("wasm_import_memory", Whitelisted, Gated(Stability::Unstable,
|
||||
"wasm_import_memory",
|
||||
"wasm_import_memory attribute is currently unstable",
|
||||
cfg_fn!(wasm_import_memory))),
|
||||
|
||||
("rustc_args_required_const", Whitelisted, Gated(Stability::Unstable,
|
||||
"rustc_attrs",
|
||||
"never will be stable",
|
||||
|
|
|
|||
1
src/stdsimd
Submodule
1
src/stdsimd
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 678cbd325c84070c9dbe4303969fbd2734c0b4ee
|
||||
|
|
@ -13,10 +13,10 @@ pub fn main() {
|
|||
let s: String = "abcdef".to_string();
|
||||
v[3_usize];
|
||||
v[3];
|
||||
v[3u8]; //~ERROR : std::ops::Index<u8>` is not satisfied
|
||||
v[3i8]; //~ERROR : std::ops::Index<i8>` is not satisfied
|
||||
v[3u32]; //~ERROR : std::ops::Index<u32>` is not satisfied
|
||||
v[3i32]; //~ERROR : std::ops::Index<i32>` is not satisfied
|
||||
v[3u8]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
|
||||
v[3i8]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
|
||||
v[3u32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
|
||||
v[3i32]; //~ERROR : std::slice::SliceIndex<[isize]>` is not satisfied
|
||||
s.as_bytes()[3_usize];
|
||||
s.as_bytes()[3];
|
||||
s.as_bytes()[3u8]; //~ERROR : std::slice::SliceIndex<[u8]>` is not satisfied
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
// ignore-windows
|
||||
// ignore-wasm32-bare no libs to link
|
||||
|
||||
#![feature(link_args)]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
#![wasm_import_memory] //~ ERROR: currently unstable
|
||||
|
||||
fn main() {}
|
||||
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
error[E0658]: wasm_import_memory attribute is currently unstable
|
||||
--> $DIR/feature-gate-wasm_import_memory.rs:11:1
|
||||
|
|
||||
LL | #![wasm_import_memory] //~ ERROR: currently unstable
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: add #![feature(wasm_import_memory)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
If you want more information on this error, try using "rustc --explain E0658"
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue