Skip to content

Commit fa6f805

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

File tree

7 files changed

+113
-14
lines changed

7 files changed

+113
-14
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/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -3503,6 +3503,7 @@ impl Step for CodegenGCC {
35033503
// Avoid incremental cache issues when changing rustc
35043504
cargo.env("CARGO_BUILD_INCREMENTAL", "false");
35053505
cargo.rustflag("-Cpanic=abort");
3506+
cargo.add_rustc_lib_path(builder);
35063507

35073508
cargo
35083509
};

src/bootstrap/src/core/builder.rs

+8-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ use crate::core::config::flags::{Color, Subcommand};
2121
use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection};
2222
use crate::prepare_behaviour_dump_dir;
2323
use crate::utils::cache::Cache;
24-
use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, linker_args};
25-
use crate::utils::helpers::{check_cfg_arg, libdir, linker_flags, output, t, LldThreads};
24+
use crate::utils::helpers::{
25+
self, add_dylib_path, add_link_lib_path, check_cfg_arg, detect_gccjit_sha, exe, libdir,
26+
linker_args, linker_flags, output, t, LldThreads,
27+
};
2628
use crate::EXTRA_CHECK_CFGS;
2729
use crate::{Build, CLang, Crate, DocTests, GitRepo, Mode};
2830

@@ -1196,6 +1198,10 @@ impl<'a> Builder<'a> {
11961198
let ci_llvm_lib = self.out.join(&*compiler.host.triple).join("ci-llvm").join("lib");
11971199
dylib_dirs.push(ci_llvm_lib);
11981200
}
1201+
if self.config.gcc_download_gccjit {
1202+
let libgccjit_path = self.config.libgccjit_folder(&detect_gccjit_sha());
1203+
dylib_dirs.push(libgccjit_path);
1204+
}
11991205

12001206
dylib_dirs
12011207
}

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>,
@@ -592,6 +594,7 @@ pub(crate) struct TomlConfig {
592594
build: Option<Build>,
593595
install: Option<Install>,
594596
llvm: Option<Llvm>,
597+
gcc: Option<Gcc>,
595598
rust: Option<Rust>,
596599
target: Option<HashMap<String, TomlTarget>>,
597600
dist: Option<Dist>,
@@ -626,7 +629,7 @@ trait Merge {
626629
impl Merge for TomlConfig {
627630
fn merge(
628631
&mut self,
629-
TomlConfig { build, install, llvm, rust, dist, target, profile: _, change_id }: Self,
632+
TomlConfig { build, install, llvm, rust, dist, target, profile: _, change_id, gcc }: Self,
630633
replace: ReplaceOpt,
631634
) {
632635
fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
@@ -644,6 +647,7 @@ impl Merge for TomlConfig {
644647
do_merge(&mut self.llvm, llvm, replace);
645648
do_merge(&mut self.rust, rust, replace);
646649
do_merge(&mut self.dist, dist, replace);
650+
do_merge(&mut self.gcc, gcc, replace);
647651
assert!(target.is_none(), "merging target-specific config is not currently supported");
648652
}
649653
}
@@ -899,6 +903,13 @@ define_config! {
899903
}
900904
}
901905

906+
define_config! {
907+
/// TOML representation of how the GCC backend is configured.
908+
struct Gcc {
909+
download_gccjit: Option<bool> = "download-gccjit",
910+
}
911+
}
912+
902913
#[derive(Clone, Debug, Deserialize)]
903914
#[serde(untagged)]
904915
pub enum StringOrBool {
@@ -1724,6 +1735,14 @@ impl Config {
17241735
ci_channel.clone_into(&mut config.channel);
17251736
}
17261737

1738+
if let Some(gcc) = toml.gcc {
1739+
let Gcc { download_gccjit } = gcc;
1740+
config.gcc_download_gccjit = download_gccjit.unwrap_or(false);
1741+
}
1742+
if config.gcc_enabled(config.build) {
1743+
config.maybe_download_gccjit();
1744+
}
1745+
17271746
if let Some(llvm) = toml.llvm {
17281747
let Llvm {
17291748
optimize: optimize_toml,
@@ -2329,6 +2348,18 @@ impl Config {
23292348
self.codegen_backends(target).contains(&"llvm".to_owned())
23302349
}
23312350

2351+
pub fn gcc_enabled(&self, target: TargetSelection) -> bool {
2352+
self.codegen_backends(target).contains(&"gcc".to_owned())
2353+
}
2354+
2355+
pub fn libgccjit_folder(&self, gcc_sha: &str) -> PathBuf {
2356+
assert!(self.gcc_download_gccjit);
2357+
let cache_prefix = format!("libgccjit-{gcc_sha}");
2358+
let cache_dst =
2359+
self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache"));
2360+
cache_dst.join(cache_prefix)
2361+
}
2362+
23322363
pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {
23332364
self.target_config
23342365
.get(&target)

src/bootstrap/src/core/download.rs

+35-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use build_helper::ci::CiEnv;
1212
use build_helper::stage0_parser::VersionMetadata;
1313
use xz2::bufread::XzDecoder;
1414

15-
use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date};
15+
use crate::core::config::RustfmtMetadata;
16+
use crate::utils::helpers::{check_run, detect_gccjit_sha, exe, move_file, program_out_of_date};
1617
use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode};
1718
use crate::{t, Config};
1819

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

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

src/bootstrap/src/utils/helpers.rs

+19
Original file line numberDiff line numberDiff line change
@@ -598,3 +598,22 @@ pub fn check_cfg_arg(name: &str, values: Option<&[&str]>) -> String {
598598
};
599599
format!("--check-cfg=cfg({name}{next})")
600600
}
601+
602+
/// This retrieves the gccjit sha we use.
603+
pub fn detect_gccjit_sha() -> String {
604+
// FIXME: This is absolutely ugly. Please find another way to do that.
605+
let content = include_str!("../../../ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh");
606+
if let Some(commit) = content
607+
.lines()
608+
.filter_map(|line| line.strip_prefix("GIT_COMMIT=\""))
609+
.filter_map(|commit| commit.strip_suffix('"'))
610+
.next()
611+
{
612+
if !commit.is_empty() {
613+
return commit.to_string();
614+
}
615+
}
616+
617+
eprintln!("error: could not find commit hash for downloading libgccjit");
618+
panic!();
619+
}

0 commit comments

Comments
 (0)