summaryrefslogtreecommitdiffstats
path: root/src/bootstrap/native.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap/native.rs')
-rw-r--r--src/bootstrap/native.rs116
1 files changed, 74 insertions, 42 deletions
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index fc3bfaf1b..2f856c276 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -16,7 +16,9 @@ use std::io;
use std::path::{Path, PathBuf};
use std::process::Command;
+use crate::bolt::{instrument_with_bolt_inplace, optimize_library_with_bolt_inplace};
use crate::builder::{Builder, RunConfig, ShouldRun, Step};
+use crate::channel;
use crate::config::TargetSelection;
use crate::util::get_clang_cl_resource_dir;
use crate::util::{self, exe, output, program_out_of_date, t, up_to_date};
@@ -115,24 +117,29 @@ pub fn prebuilt_llvm_config(
}
/// This retrieves the LLVM sha we *want* to use, according to git history.
-pub(crate) fn detect_llvm_sha(config: &crate::config::Config) -> String {
- let mut rev_list = config.git();
- rev_list.args(&[
- PathBuf::from("rev-list"),
- format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(),
- "-n1".into(),
- "--first-parent".into(),
- "HEAD".into(),
- "--".into(),
- config.src.join("src/llvm-project"),
- config.src.join("src/bootstrap/download-ci-llvm-stamp"),
- // the LLVM shared object file is named `LLVM-12-rust-{version}-nightly`
- config.src.join("src/version"),
- ]);
- let llvm_sha = output(&mut rev_list);
- let llvm_sha = llvm_sha.trim();
-
- if llvm_sha == "" {
+pub(crate) fn detect_llvm_sha(config: &crate::config::Config, is_git: bool) -> String {
+ let llvm_sha = if is_git {
+ let mut rev_list = config.git();
+ rev_list.args(&[
+ PathBuf::from("rev-list"),
+ format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(),
+ "-n1".into(),
+ "--first-parent".into(),
+ "HEAD".into(),
+ "--".into(),
+ config.src.join("src/llvm-project"),
+ config.src.join("src/bootstrap/download-ci-llvm-stamp"),
+ // the LLVM shared object file is named `LLVM-12-rust-{version}-nightly`
+ config.src.join("src/version"),
+ ]);
+ output(&mut rev_list).trim().to_owned()
+ } else if let Some(info) = channel::read_commit_info_file(&config.src) {
+ info.sha.trim().to_owned()
+ } else {
+ "".to_owned()
+ };
+
+ if &llvm_sha == "" {
eprintln!("error: could not find commit hash for downloading LLVM");
eprintln!("help: maybe your repository history is too shallow?");
eprintln!("help: consider disabling `download-ci-llvm`");
@@ -140,7 +147,7 @@ pub(crate) fn detect_llvm_sha(config: &crate::config::Config) -> String {
panic!();
}
- llvm_sha.to_owned()
+ llvm_sha
}
/// Returns whether the CI-found LLVM is currently usable.
@@ -194,7 +201,9 @@ pub(crate) fn is_ci_llvm_available(config: &crate::config::Config, asserts: bool
}
if crate::util::CiEnv::is_ci() {
- let llvm_sha = detect_llvm_sha(config);
+ // We assume we have access to git, so it's okay to unconditionally pass
+ // `true` here.
+ let llvm_sha = detect_llvm_sha(config, true);
let head_sha = output(config.git().arg("rev-parse").arg("HEAD"));
let head_sha = head_sha.trim();
if llvm_sha == head_sha {
@@ -215,7 +224,7 @@ pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) {
}
let llvm_root = config.ci_llvm_root();
let llvm_stamp = llvm_root.join(".llvm-stamp");
- let llvm_sha = detect_llvm_sha(&config);
+ let llvm_sha = detect_llvm_sha(&config, builder.rust_info.is_managed_git_subrepository());
let key = format!("{}{}", llvm_sha, config.llvm_assertions);
if program_out_of_date(&llvm_stamp, &key) && !config.dry_run {
download_ci_llvm(builder, &llvm_sha);
@@ -260,8 +269,8 @@ fn download_ci_llvm(builder: &Builder<'_>, llvm_sha: &str) {
} else {
&builder.config.stage0_metadata.config.artifacts_server
};
- let version = builder.config.artifact_version_part(llvm_sha);
- let filename = format!("rust-dev-{}-{}.tar.xz", version, builder.build.build.triple);
+ let channel = builder.config.artifact_channel(builder, llvm_sha);
+ let filename = format!("rust-dev-{}-{}.tar.xz", channel, builder.build.build.triple);
let tarball = rustc_cache.join(&filename);
if !tarball.exists() {
let help_on_error = "error: failed to download llvm from ci
@@ -395,6 +404,12 @@ impl Step for Llvm {
if let Some(path) = builder.config.llvm_profile_use.as_ref() {
cfg.define("LLVM_PROFDATA_FILE", &path);
}
+ if builder.config.llvm_bolt_profile_generate
+ || builder.config.llvm_bolt_profile_use.is_some()
+ {
+ // Relocations are required for BOLT to work.
+ ldflags.push_all("-Wl,-q");
+ }
// Disable zstd to avoid a dependency on libzstd.so.
cfg.define("LLVM_ENABLE_ZSTD", "OFF");
@@ -423,12 +438,7 @@ impl Step for Llvm {
// which saves both memory during parallel links and overall disk space
// for the tools. We don't do this on every platform as it doesn't work
// equally well everywhere.
- //
- // If we're not linking rustc to a dynamic LLVM, though, then don't link
- // tools to it.
- let llvm_link_shared =
- builder.llvm_link_tools_dynamically(target) && builder.llvm_link_shared();
- if llvm_link_shared {
+ if builder.llvm_link_shared() {
cfg.define("LLVM_LINK_LLVM_DYLIB", "ON");
}
@@ -494,18 +504,18 @@ impl Step for Llvm {
// https://llvm.org/docs/HowToCrossCompileLLVM.html
if target != builder.config.build {
- builder.ensure(Llvm { target: builder.config.build });
- // FIXME: if the llvm root for the build triple is overridden then we
- // should use llvm-tblgen from there, also should verify that it
- // actually exists most of the time in normal installs of LLVM.
- let host_bin = builder.llvm_out(builder.config.build).join("bin");
- cfg.define("LLVM_TABLEGEN", host_bin.join("llvm-tblgen").with_extension(EXE_EXTENSION));
- // LLVM_NM is required for cross compiling using MSVC
- cfg.define("LLVM_NM", host_bin.join("llvm-nm").with_extension(EXE_EXTENSION));
- cfg.define(
- "LLVM_CONFIG_PATH",
- host_bin.join("llvm-config").with_extension(EXE_EXTENSION),
- );
+ let llvm_config = builder.ensure(Llvm { target: builder.config.build });
+ if !builder.config.dry_run {
+ let llvm_bindir = output(Command::new(&llvm_config).arg("--bindir"));
+ let host_bin = Path::new(llvm_bindir.trim());
+ cfg.define(
+ "LLVM_TABLEGEN",
+ host_bin.join("llvm-tblgen").with_extension(EXE_EXTENSION),
+ );
+ // LLVM_NM is required for cross compiling using MSVC
+ cfg.define("LLVM_NM", host_bin.join("llvm-nm").with_extension(EXE_EXTENSION));
+ }
+ cfg.define("LLVM_CONFIG_PATH", llvm_config);
if builder.config.llvm_clang {
let build_bin = builder.llvm_out(builder.config.build).join("build").join("bin");
let clang_tblgen = build_bin.join("clang-tblgen").with_extension(EXE_EXTENSION);
@@ -553,7 +563,7 @@ impl Step for Llvm {
// libLLVM.dylib will be built. However, llvm-config will still look
// for a versioned path like libLLVM-14.dylib. Manually create a symbolic
// link to make llvm-config happy.
- if llvm_link_shared && target.contains("apple-darwin") {
+ if builder.llvm_link_shared() && target.contains("apple-darwin") {
let mut cmd = Command::new(&build_llvm_config);
let version = output(cmd.arg("--version"));
let major = version.split('.').next().unwrap();
@@ -568,12 +578,34 @@ impl Step for Llvm {
}
}
+ // After LLVM is built, we modify (instrument or optimize) the libLLVM.so library file
+ // in place. This is fine, because currently we do not support incrementally rebuilding
+ // LLVM after a configuration change, so to rebuild it the build files have to be removed,
+ // which will also remove these modified files.
+ if builder.config.llvm_bolt_profile_generate {
+ instrument_with_bolt_inplace(&get_built_llvm_lib_path(&build_llvm_config));
+ }
+ if let Some(path) = &builder.config.llvm_bolt_profile_use {
+ optimize_library_with_bolt_inplace(
+ &get_built_llvm_lib_path(&build_llvm_config),
+ &Path::new(path),
+ );
+ }
+
t!(stamp.write());
build_llvm_config
}
}
+/// Returns path to a built LLVM library (libLLVM.so).
+/// Assumes that we have built LLVM into a single library file.
+fn get_built_llvm_lib_path(llvm_config_path: &Path) -> PathBuf {
+ let mut cmd = Command::new(llvm_config_path);
+ cmd.arg("--libfiles");
+ PathBuf::from(output(&mut cmd).trim())
+}
+
fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
if !builder.config.llvm_version_check {
return;