Skip to content

Support configuring the set of codegen backends to build per host triple #120348

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,11 @@
# target triples containing `-none`, `nvptx`, `switch`, or `-uefi`.
#no-std = <platform-specific> (bool)

# This is an array of the codegen backends that will be compiled a rustc
# compiled for this target, overriding the global rust.codegen-backends option.
# See that option for more info.
#codegen-backends = rust.codegen-backends (array)

# =============================================================================
# Distribution options
#
Expand Down
16 changes: 8 additions & 8 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,7 @@ impl Step for Rustc {
pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection, stage: u32) {
cargo
.arg("--features")
.arg(builder.rustc_features(builder.kind))
.arg(builder.rustc_features(builder.kind, target))
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc/Cargo.toml"));

Expand Down Expand Up @@ -1060,7 +1060,7 @@ pub fn rustc_cargo_env(
cargo.env("CFG_OMIT_GIT_HASH", "1");
}

if let Some(backend) = builder.config.default_codegen_backend() {
if let Some(backend) = builder.config.default_codegen_backend(target) {
cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend);
}

Expand Down Expand Up @@ -1101,7 +1101,7 @@ pub fn rustc_cargo_env(
// build. If we are in a check build we still go ahead here presuming we've
// detected that LLVM is already built and good to go which helps prevent
// busting caches (e.g. like #71152).
if builder.config.llvm_enabled() {
if builder.config.llvm_enabled(target) {
let building_is_expensive =
crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target).is_err();
// `top_stage == stage` might be false for `check --stage 1`, if we are building the stage 1 compiler
Expand Down Expand Up @@ -1250,7 +1250,7 @@ pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
if path.path.to_str().unwrap().contains(&CODEGEN_BACKEND_PREFIX) {
let mut needs_codegen_backend_config = true;
for &backend in &run.builder.config.rust_codegen_backends {
for &backend in run.builder.config.codegen_backends(run.target) {
if path
.path
.to_str()
Expand Down Expand Up @@ -1287,7 +1287,7 @@ impl Step for CodegenBackend {
return;
}

for &backend in &run.builder.config.rust_codegen_backends {
for &backend in run.builder.config.codegen_backends(run.target) {
if backend == "llvm" {
continue; // Already built as part of rustc
}
Expand Down Expand Up @@ -1387,7 +1387,7 @@ fn copy_codegen_backends_to_sysroot(
return;
}

for backend in builder.config.rust_codegen_backends.iter() {
for backend in builder.config.codegen_backends(target) {
if backend == "llvm" {
continue; // Already built as part of rustc
}
Expand Down Expand Up @@ -1694,7 +1694,7 @@ impl Step for Assemble {
// to not fail while linking the artifacts.
build_compiler.stage = actual_stage;

for &backend in builder.config.rust_codegen_backends.iter() {
for &backend in builder.config.codegen_backends(target_compiler.host) {
if backend == "llvm" {
continue; // Already built as part of rustc
}
Expand Down Expand Up @@ -1779,7 +1779,7 @@ impl Step for Assemble {
}
}

if builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
if builder.config.llvm_enabled(target_compiler.host) {
let llvm::LlvmResult { llvm_config, .. } =
builder.ensure(llvm::Llvm { target: target_compiler.host });
if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
Expand Down
4 changes: 2 additions & 2 deletions src/bootstrap/src/core/build_steps/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1278,7 +1278,7 @@ impl Step for CodegenBackend {
}

fn make_run(run: RunConfig<'_>) {
for &backend in &run.builder.config.rust_codegen_backends {
for &backend in run.builder.config.codegen_backends(run.target) {
if backend == "llvm" {
continue; // Already built as part of rustc
}
Expand All @@ -1302,7 +1302,7 @@ impl Step for CodegenBackend {
return None;
}

if !builder.config.rust_codegen_backends.contains(&self.backend) {
if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend) {
return None;
}

Expand Down
7 changes: 4 additions & 3 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1841,7 +1841,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the

let mut llvm_components_passed = false;
let mut copts_passed = false;
if builder.config.llvm_enabled() {
if builder.config.llvm_enabled(compiler.host) {
let llvm::LlvmResult { llvm_config, .. } =
builder.ensure(llvm::Llvm { target: builder.config.build });
if !builder.config.dry_run() {
Expand Down Expand Up @@ -3155,7 +3155,8 @@ impl Step for CodegenCranelift {
return;
}

if !builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("cranelift")) {
if !builder.config.codegen_backends(run.target).contains(&INTERNER.intern_str("cranelift"))
{
builder.info("cranelift not in rust.codegen-backends. skipping");
return;
}
Expand Down Expand Up @@ -3277,7 +3278,7 @@ impl Step for CodegenGCC {
return;
}

if !builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("gcc")) {
if !builder.config.codegen_backends(run.target).contains(&INTERNER.intern_str("gcc")) {
builder.info("gcc not in rust.codegen-backends. skipping");
return;
}
Expand Down
5 changes: 3 additions & 2 deletions src/bootstrap/src/core/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1230,7 +1230,7 @@ impl<'a> Builder<'a> {
/// Note that this returns `None` if LLVM is disabled, or if we're in a
/// check build or dry-run, where there's no need to build all of LLVM.
fn llvm_config(&self, target: TargetSelection) -> Option<PathBuf> {
if self.config.llvm_enabled() && self.kind != Kind::Check && !self.config.dry_run() {
if self.config.llvm_enabled(target) && self.kind != Kind::Check && !self.config.dry_run() {
let llvm::LlvmResult { llvm_config, .. } = self.ensure(llvm::Llvm { target });
if llvm_config.is_file() {
return Some(llvm_config);
Expand Down Expand Up @@ -2113,7 +2113,8 @@ impl<'a> Builder<'a> {
};

if let Some(limit) = limit {
if stage == 0 || self.config.default_codegen_backend().unwrap_or_default() == "llvm"
if stage == 0
|| self.config.default_codegen_backend(target).unwrap_or_default() == "llvm"
{
rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}"));
}
Expand Down
35 changes: 31 additions & 4 deletions src/bootstrap/src/core/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,7 @@ pub struct Target {
pub wasi_root: Option<PathBuf>,
pub qemu_rootfs: Option<PathBuf>,
pub no_std: bool,
pub codegen_backends: Option<Vec<Interned<String>>>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a change info for this field? Similar to

ChangeInfo {
change_id: 117435,
severity: ChangeSeverity::Info,
summary: "New option `rust.parallel-compiler` added to config.toml.",
},

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

impl Target {
Expand Down Expand Up @@ -1139,6 +1140,7 @@ define_config! {
wasi_root: Option<String> = "wasi-root",
qemu_rootfs: Option<String> = "qemu-rootfs",
no_std: Option<bool> = "no-std",
codegen_backends: Option<Vec<String>> = "codegen-backends",
}
}

Expand Down Expand Up @@ -1845,6 +1847,24 @@ impl Config {
target.profiler = cfg.profiler;
target.rpath = cfg.rpath;

if let Some(ref backends) = cfg.codegen_backends {
let available_backends = vec!["llvm", "cranelift", "gcc"];

target.codegen_backends = Some(backends.iter().map(|s| {
if let Some(backend) = s.strip_prefix(CODEGEN_BACKEND_PREFIX) {
if available_backends.contains(&backend) {
panic!("Invalid value '{s}' for 'target.{triple}.codegen-backends'. Instead, please use '{backend}'.");
} else {
println!("HELP: '{s}' for 'target.{triple}.codegen-backends' might fail. \
Codegen backends are mostly defined without the '{CODEGEN_BACKEND_PREFIX}' prefix. \
In this case, it would be referred to as '{backend}'.");
}
}

INTERNER.intern_str(s)
}).collect());
}

config.target_config.insert(TargetSelection::from_user(&triple), target);
}
}
Expand Down Expand Up @@ -2227,8 +2247,8 @@ impl Config {
self.target_config.get(&target).map(|t| t.rpath).flatten().unwrap_or(self.rust_rpath)
}

pub fn llvm_enabled(&self) -> bool {
self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
self.codegen_backends(target).contains(&INTERNER.intern_str("llvm"))
}

pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {
Expand All @@ -2247,8 +2267,15 @@ impl Config {
self.submodules.unwrap_or(rust_info.is_managed_git_subrepository())
}

pub fn default_codegen_backend(&self) -> Option<Interned<String>> {
self.rust_codegen_backends.get(0).cloned()
pub fn codegen_backends(&self, target: TargetSelection) -> &[Interned<String>] {
self.target_config
.get(&target)
.and_then(|cfg| cfg.codegen_backends.as_deref())
.unwrap_or(&self.rust_codegen_backends)
}

pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<Interned<String>> {
self.codegen_backends(target).get(0).cloned()
}

pub fn git_config(&self) -> GitConfig<'_> {
Expand Down
32 changes: 17 additions & 15 deletions src/bootstrap/src/core/sanity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ use std::path::PathBuf;
use std::process::Command;

use crate::core::config::Target;
use crate::utils::cache::INTERNER;
use crate::utils::helpers::output;
use crate::Build;

Expand Down Expand Up @@ -88,19 +87,19 @@ pub fn check(build: &mut Build) {
}

// We need cmake, but only if we're actually building LLVM or sanitizers.
let building_llvm = build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm"))
&& build
.hosts
.iter()
.map(|host| {
build
let building_llvm = build
.hosts
.iter()
.map(|host| {
build.config.llvm_enabled(*host)
&& build
.config
.target_config
.get(host)
.map(|config| config.llvm_config.is_none())
.unwrap_or(true)
})
.any(|build_llvm_ourselves| build_llvm_ourselves);
})
.any(|build_llvm_ourselves| build_llvm_ourselves);

let need_cmake = building_llvm || build.config.any_sanitizers_to_build();
if need_cmake && cmd_finder.maybe_have("cmake").is_none() {
Expand Down Expand Up @@ -190,13 +189,16 @@ than building it.
if !build.config.dry_run() {
cmd_finder.must_have(build.cxx(*host).unwrap());
}
}

if build.config.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) {
// Externally configured LLVM requires FileCheck to exist
let filecheck = build.llvm_filecheck(build.build);
if !filecheck.starts_with(&build.out) && !filecheck.exists() && build.config.codegen_tests {
panic!("FileCheck executable {filecheck:?} does not exist");
if build.config.llvm_enabled(*host) {
// Externally configured LLVM requires FileCheck to exist
let filecheck = build.llvm_filecheck(build.build);
if !filecheck.starts_with(&build.out)
&& !filecheck.exists()
&& build.config.codegen_tests
{
panic!("FileCheck executable {filecheck:?} does not exist");
}
}
}

Expand Down
7 changes: 4 additions & 3 deletions src/bootstrap/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -734,12 +734,12 @@ impl Build {
}

/// Gets the space-separated set of activated features for the compiler.
fn rustc_features(&self, kind: Kind) -> String {
fn rustc_features(&self, kind: Kind, target: TargetSelection) -> String {
let mut features = vec![];
if self.config.jemalloc {
features.push("jemalloc");
}
if self.config.llvm_enabled() || kind == Kind::Check {
if self.config.llvm_enabled(target) || kind == Kind::Check {
features.push("llvm");
}
// keep in sync with `bootstrap/compile.rs:rustc_cargo_env`
Expand Down Expand Up @@ -1560,7 +1560,8 @@ impl Build {
|| target
.map(|t| self.config.profiler_enabled(t))
.unwrap_or_else(|| self.config.any_profiler_enabled()))
&& (dep != "rustc_codegen_llvm" || self.config.llvm_enabled())
&& (dep != "rustc_codegen_llvm"
|| self.config.hosts.iter().any(|host| self.config.llvm_enabled(*host)))
{
list.push(*dep);
}
Expand Down
5 changes: 5 additions & 0 deletions src/bootstrap/src/utils/change_tracker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Warning,
summary: "A new `optimized-compiler-builtins` option has been introduced. Whether to build llvm's `compiler-rt` from source is no longer implicitly controlled by git state. See the PR for more details.",
},
ChangeInfo {
change_id: 120348,
severity: ChangeSeverity::Info,
summary: "New option `target.<triple>.codegen-backends` added to config.toml.",
},
];