Skip to content

Commit 6332003

Browse files
Add support for downloading libgccjit.so file to prevent requiring to build it yourself
1 parent e936289 commit 6332003

File tree

8 files changed

+132
-12
lines changed

8 files changed

+132
-12
lines changed

compiler/rustc_codegen_gcc/build_system/src/config.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -444,15 +444,17 @@ impl ConfigInfo {
444444
"build_sysroot/sysroot/lib/rustlib/{}/lib",
445445
self.target_triple,
446446
));
447-
let ld_library_path = format!(
448-
"{target}:{sysroot}:{gcc_path}",
449-
target = self.cargo_target_dir,
450-
sysroot = sysroot.display(),
451-
gcc_path = self.gcc_path,
452-
);
453-
env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone());
454-
env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone());
455-
env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path);
447+
if !use_system_gcc {
448+
let ld_library_path = format!(
449+
"{target}:{sysroot}:{gcc_path}",
450+
target = self.cargo_target_dir,
451+
sysroot = sysroot.display(),
452+
gcc_path = self.gcc_path,
453+
);
454+
env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone());
455+
env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone());
456+
env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path);
457+
}
456458

457459
// NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
458460
// To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.

config.example.toml

+7
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,13 @@
155155
# Custom CMake defines to set when building LLVM.
156156
#build-config = {}
157157

158+
# =============================================================================
159+
# General configuration options for the GCC backend
160+
# =============================================================================
161+
[gcc]
162+
# Change to `true` if you want to use the version used in Rust CI.
163+
# download-gccjit = false
164+
158165
# =============================================================================
159166
# General build configuration options
160167
# =============================================================================

src/bootstrap/src/core/build_steps/compile.rs

+5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use std::str;
2020
use serde_derive::Deserialize;
2121

2222
use crate::core::build_steps::dist;
23+
use crate::core::build_steps::gcc::set_gccjit_library_path;
2324
use crate::core::build_steps::llvm;
2425
use crate::core::build_steps::tool::SourceType;
2526
use crate::core::builder;
@@ -1365,6 +1366,10 @@ impl Step for CodegenBackend {
13651366
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
13661367
rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
13671368

1369+
if backend == "gcc" {
1370+
set_gccjit_library_path(&builder.config, &mut cargo);
1371+
}
1372+
13681373
let tmp_stamp = out_dir.join(".tmp.stamp");
13691374

13701375
let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//! Retrieves information related to GCC backend.
2+
3+
use crate::builder::Cargo;
4+
5+
/// This retrieves the gccjit sha we use.
6+
pub(crate) fn detect_gccjit_sha() -> String {
7+
// FIXME: This is absolutely ugly. Please find another way to do that.
8+
let content =
9+
include_str!("../../../../ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh");
10+
if let Some(commit) = content
11+
.lines()
12+
.filter_map(|line| line.strip_prefix("GIT_COMMIT=\""))
13+
.filter_map(|commit| commit.strip_suffix("\""))
14+
.next()
15+
{
16+
if !commit.is_empty() {
17+
return commit.to_string();
18+
}
19+
}
20+
21+
eprintln!("error: could not find commit hash for downloading libgccjit");
22+
panic!();
23+
}
24+
25+
pub fn set_gccjit_library_path(config: &crate::Config, cargo: &mut Cargo) {
26+
if config.gcc_download_gccjit {
27+
let libgccjit_path = config.libgccjit_folder(&detect_gccjit_sha());
28+
let mut library_path = std::env::var("LD_LIBRARY_PATH").unwrap_or_default();
29+
if !library_path.is_empty() {
30+
library_path.push(':');
31+
}
32+
library_path.push_str(&libgccjit_path.display().to_string());
33+
cargo.env("LD_LIBRARY_PATH", &library_path);
34+
cargo.env("LIBRARY_PATH", library_path);
35+
}
36+
}

src/bootstrap/src/core/build_steps/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub(crate) mod compile;
55
pub(crate) mod dist;
66
pub(crate) mod doc;
77
pub(crate) mod format;
8+
pub(crate) mod gcc;
89
pub(crate) mod install;
910
pub(crate) mod llvm;
1011
pub(crate) mod run;

src/bootstrap/src/core/build_steps/test.rs

+3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use clap_complete::shells;
1616
use crate::core::build_steps::compile;
1717
use crate::core::build_steps::dist;
1818
use crate::core::build_steps::doc::DocumentationFormat;
19+
use crate::core::build_steps::gcc::set_gccjit_library_path;
1920
use crate::core::build_steps::llvm;
2021
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
2122
use crate::core::build_steps::tool::{self, SourceType, Tool};
@@ -3512,6 +3513,8 @@ impl Step for CodegenGCC {
35123513

35133514
let mut cargo = build_cargo();
35143515

3516+
set_gccjit_library_path(&builder.config, &mut cargo);
3517+
35153518
cargo
35163519
.arg("--")
35173520
.arg("test")

src/bootstrap/src/core/config/config.rs

+32-1
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,8 @@ pub struct Config {
250250
pub llvm_ldflags: Option<String>,
251251
pub llvm_use_libcxx: bool,
252252

253+
pub gcc_download_gccjit: bool,
254+
253255
// rust codegen options
254256
pub rust_optimize: RustOptimize,
255257
pub rust_codegen_units: Option<u32>,
@@ -617,6 +619,7 @@ pub(crate) struct TomlConfig {
617619
build: Option<Build>,
618620
install: Option<Install>,
619621
llvm: Option<Llvm>,
622+
gcc: Option<Gcc>,
620623
rust: Option<Rust>,
621624
target: Option<HashMap<String, TomlTarget>>,
622625
dist: Option<Dist>,
@@ -651,7 +654,7 @@ trait Merge {
651654
impl Merge for TomlConfig {
652655
fn merge(
653656
&mut self,
654-
TomlConfig { build, install, llvm, rust, dist, target, profile: _, change_id }: Self,
657+
TomlConfig { build, install, llvm, rust, dist, target, profile: _, change_id, gcc }: Self,
655658
replace: ReplaceOpt,
656659
) {
657660
fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
@@ -669,6 +672,7 @@ impl Merge for TomlConfig {
669672
do_merge(&mut self.llvm, llvm, replace);
670673
do_merge(&mut self.rust, rust, replace);
671674
do_merge(&mut self.dist, dist, replace);
675+
do_merge(&mut self.gcc, gcc, replace);
672676
assert!(target.is_none(), "merging target-specific config is not currently supported");
673677
}
674678
}
@@ -923,6 +927,13 @@ define_config! {
923927
}
924928
}
925929

930+
define_config! {
931+
/// TOML representation of how the GCC backend is configured.
932+
struct Gcc {
933+
download_gccjit: Option<bool> = "download-gccjit",
934+
}
935+
}
936+
926937
#[derive(Clone, Debug, Deserialize)]
927938
#[serde(untagged)]
928939
pub enum StringOrBool {
@@ -1749,6 +1760,14 @@ impl Config {
17491760
config.omit_git_hash = omit_git_hash.unwrap_or(default);
17501761
config.rust_info = GitInfo::new(config.omit_git_hash, &config.src);
17511762

1763+
if let Some(gcc) = toml.gcc {
1764+
let Gcc { download_gccjit } = gcc;
1765+
config.gcc_download_gccjit = download_gccjit.unwrap_or(false);
1766+
}
1767+
if config.gcc_enabled(config.build) {
1768+
config.maybe_download_gccjit();
1769+
}
1770+
17521771
if let Some(llvm) = toml.llvm {
17531772
let Llvm {
17541773
optimize: optimize_toml,
@@ -2315,6 +2334,18 @@ impl Config {
23152334
self.codegen_backends(target).contains(&"llvm".to_owned())
23162335
}
23172336

2337+
pub fn gcc_enabled(&self, target: TargetSelection) -> bool {
2338+
self.codegen_backends(target).contains(&"gcc".to_owned())
2339+
}
2340+
2341+
pub fn libgccjit_folder(&self, gcc_sha: &str) -> PathBuf {
2342+
assert!(self.gcc_download_gccjit);
2343+
let cache_prefix = format!("libgccjit-{gcc_sha}");
2344+
let cache_dst =
2345+
self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache"));
2346+
cache_dst.join(cache_prefix)
2347+
}
2348+
23182349
pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {
23192350
self.target_config
23202351
.get(&target)

src/bootstrap/src/core/download.rs

+37-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ use xz2::bufread::XzDecoder;
1313

1414
use crate::core::config::RustfmtMetadata;
1515
use crate::utils::helpers::{check_run, exe, program_out_of_date};
16-
use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode};
16+
use crate::{
17+
core::build_steps::gcc::detect_gccjit_sha, core::build_steps::llvm::detect_llvm_sha,
18+
utils::helpers::hex_encode,
19+
};
1720
use crate::{t, Config};
1821

1922
static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock<bool> = OnceLock::new();
@@ -229,7 +232,7 @@ impl Config {
229232
tempfile.to_str().unwrap(),
230233
"--retry",
231234
"3",
232-
"-SRf",
235+
"-SRfL",
233236
]);
234237
// Don't print progress in CI; the \r wrapping looks bad and downloads don't take long enough for progress to be useful.
235238
if CiEnv::is_ci() {
@@ -742,6 +745,38 @@ download-rustc = false
742745
let llvm_root = self.ci_llvm_root();
743746
self.unpack(&tarball, &llvm_root, "rust-dev");
744747
}
748+
749+
pub(crate) fn maybe_download_gccjit(&self) {
750+
if !self.gcc_download_gccjit {
751+
return;
752+
}
753+
self.download_gccjit(&detect_gccjit_sha());
754+
}
755+
756+
fn download_gccjit(&self, gcc_sha: &str) {
757+
let help_on_error = "ERROR: failed to download libgccjit
758+
759+
HELP: There could be two reasons behind this:
760+
1) The host triple is not supported for `download-gccjit`.
761+
2) Old builds get deleted after a certain time.
762+
";
763+
if !self.build.triple.contains("linux") || !self.build.triple.contains("x86_64") {
764+
eprintln!("{help_on_error}");
765+
return;
766+
}
767+
let rustc_cache = self.libgccjit_folder(gcc_sha);
768+
if !rustc_cache.exists() {
769+
t!(fs::create_dir_all(&rustc_cache));
770+
}
771+
772+
let lib_path = rustc_cache.join("libgccjit.so.0");
773+
if !lib_path.exists() {
774+
let url = format!(
775+
"https://github.com/rust-lang/gcc/releases/download/master-{gcc_sha}/libgccjit.so",
776+
);
777+
self.download_file(&url, &lib_path, help_on_error);
778+
}
779+
}
745780
}
746781

747782
fn path_is_dylib(path: &Path) -> bool {

0 commit comments

Comments
 (0)