Skip to content
Draft
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
1 change: 1 addition & 0 deletions bootstrap.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@
# modifications to the `src/gcc` submodule.
# Currently, this is only supported for the `x86_64-unknown-linux-gnu` target.
#gcc.download-ci-gcc = false
#libgccjit-libs-dir = "/path/to/libgccjit-libs-dir"

# =============================================================================
# General build configuration options
Expand Down
4 changes: 3 additions & 1 deletion src/bootstrap/src/core/build_steps/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2857,7 +2857,9 @@ impl Step for Gcc {
fn run(self, builder: &Builder<'_>) -> Self::Output {
let tarball = Tarball::new(builder, "gcc", &self.target.triple);
let output = builder.ensure(super::gcc::Gcc { target: self.target });
tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
if let Some(ref path) = output.libgccjit {
tarball.add_file(path, "lib", FileType::NativeLibrary);
}
tarball.generate()
}

Expand Down
75 changes: 60 additions & 15 deletions src/bootstrap/src/core/build_steps/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ pub struct Gcc {

#[derive(Clone)]
pub struct GccOutput {
pub libgccjit: PathBuf,
/// Path to a built or downloaded libgccjit.
/// Is None when setting libgccjit-libs-dir.
/// FIXME: it seems wrong to make this an Option.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Kobzol: What are your thoughts about this?

/// Perhaps it should be a Vec so that we can install all libs from libgccjit-libs-dir?
pub libgccjit: Option<PathBuf>,
}

impl GccOutput {
Expand All @@ -36,18 +40,50 @@ impl GccOutput {
return;
}

let target_filename = self.libgccjit.file_name().unwrap().to_str().unwrap().to_string();
if let Some(ref path) = self.libgccjit {
let target_filename = path.file_name().unwrap().to_str().unwrap().to_string();

// If we build libgccjit ourselves, then `self.libgccjit` can actually be a symlink.
// In that case, we have to resolve it first, otherwise we'd create a symlink to a symlink,
// which wouldn't work.
let actual_libgccjit_path = t!(
self.libgccjit.canonicalize(),
format!("Cannot find libgccjit at {}", self.libgccjit.display())
);
// If we build libgccjit ourselves, then `self.libgccjit` can actually be a symlink.
// In that case, we have to resolve it first, otherwise we'd create a symlink to a symlink,
// which wouldn't work.
let actual_libgccjit_path =
t!(path.canonicalize(), format!("Cannot find libgccjit at {}", path.display()));

let dst = directory.join(&target_filename);
builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);
}

let dst = directory.join(target_filename);
builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);
if let Some(ref path) = builder.config.libgccjit_libs_dir {
let host_target = builder.config.host_target.triple;

let source = path.join(host_target);
let dst = directory;

let targets = builder
.config
.targets
.iter()
.map(|target| target.triple)
.chain(std::iter::once(host_target));

let target_filename = "libgccjit.so.0";
for target in targets {
let source = source.join(target).join(target_filename);
// To support symlinks in libgccjit-libs-dir, we have to resolve it first,
// otherwise we'd create a symlink to a symlink, which wouldn't work.
let actual_libgccjit_path = t!(
source.canonicalize(),
format!("Cannot find libgccjit at {}", source.display())
);
let target_dir = dst.join(target);
t!(
std::fs::create_dir_all(&target_dir),
format!("Cannot create target dir {} for libgccjit", target_dir.display())
);
let dst = target_dir.join(target_filename);
builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary);
}
}
}
}

Expand All @@ -70,7 +106,8 @@ impl Step for Gcc {

// If GCC has already been built, we avoid building it again.
let metadata = match get_gcc_build_status(builder, target) {
GccBuildStatus::AlreadyBuilt(path) => return GccOutput { libgccjit: path },
GccBuildStatus::AlreadyBuilt(path) => return GccOutput { libgccjit: Some(path) },
GccBuildStatus::InLibsDir => return GccOutput { libgccjit: None },
GccBuildStatus::ShouldBuild(m) => m,
};

Expand All @@ -80,14 +117,14 @@ impl Step for Gcc {

let libgccjit_path = libgccjit_built_path(&metadata.install_dir);
if builder.config.dry_run() {
return GccOutput { libgccjit: libgccjit_path };
return GccOutput { libgccjit: Some(libgccjit_path) };
}

build_gcc(&metadata, builder, target);

t!(metadata.stamp.write());

GccOutput { libgccjit: libgccjit_path }
GccOutput { libgccjit: Some(libgccjit_path) }
}
}

Expand All @@ -101,6 +138,7 @@ pub struct Meta {
pub enum GccBuildStatus {
/// libgccjit is already built at this path
AlreadyBuilt(PathBuf),
InLibsDir,
ShouldBuild(Meta),
}

Expand Down Expand Up @@ -165,6 +203,11 @@ fn try_download_gcc(_builder: &Builder<'_>, _target: TargetSelection) -> Option<
/// It's used to avoid busting caches during x.py check -- if we've already built
/// GCC, it's fine for us to not try to avoid doing so.
pub fn get_gcc_build_status(builder: &Builder<'_>, target: TargetSelection) -> GccBuildStatus {
if matches!(builder.config.gcc_ci_mode, crate::core::config::GccCiMode::CopyFromLibsDir) {
// FIXME: check if this is OK.
return GccBuildStatus::InLibsDir;
}

if let Some(path) = try_download_gcc(builder, target) {
return GccBuildStatus::AlreadyBuilt(path);
}
Expand Down Expand Up @@ -288,7 +331,9 @@ fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) {
/// Configures a Cargo invocation so that it can build the GCC codegen backend.
pub fn add_cg_gcc_cargo_flags(cargo: &mut Cargo, gcc: &GccOutput) {
// Add the path to libgccjit.so to the linker search paths.
cargo.rustflag(&format!("-L{}", gcc.libgccjit.parent().unwrap().to_str().unwrap()));
if let Some(ref path) = gcc.libgccjit {
cargo.rustflag(&format!("-L{}", path.parent().unwrap().to_str().unwrap()));
}
}

/// The absolute path to the downloaded GCC artifacts.
Expand Down
6 changes: 4 additions & 2 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3938,13 +3938,15 @@ impl Step for CodegenGCC {
.arg("test")
.arg("--use-backend")
.arg("gcc")
.arg("--gcc-path")
.arg(gcc.libgccjit.parent().unwrap())
.arg("--out-dir")
.arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc"))
.arg("--release")
.arg("--mini-tests")
.arg("--std-tests");

if let Some(ref path) = gcc.libgccjit {
cargo.arg("--gcc-path").arg(path.parent().unwrap());
}
cargo.args(builder.config.test_args());

cargo.into_cmd().run(builder);
Expand Down
12 changes: 8 additions & 4 deletions src/bootstrap/src/core/config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ pub struct Config {

// gcc codegen options
pub gcc_ci_mode: GccCiMode,
pub libgccjit_libs_dir: Option<PathBuf>,

// rust codegen options
pub rust_optimize: RustOptimize,
Expand Down Expand Up @@ -620,7 +621,8 @@ impl Config {
vendor: dist_vendor,
} = toml.dist.unwrap_or_default();

let Gcc { download_ci_gcc: gcc_download_ci_gcc } = toml.gcc.unwrap_or_default();
let Gcc { download_ci_gcc: gcc_download_ci_gcc, libgccjit_libs_dir } =
toml.gcc.unwrap_or_default();

if rust_bootstrap_override_lld.is_some() && rust_bootstrap_override_lld_legacy.is_some() {
panic!(
Expand Down Expand Up @@ -1218,12 +1220,13 @@ impl Config {
Warnings::Default => rust_deny_warnings.unwrap_or(true),
};

let gcc_ci_mode = match gcc_download_ci_gcc {
Some(value) => match value {
let gcc_ci_mode = match (&libgccjit_libs_dir, gcc_download_ci_gcc) {
(Some(_), _) => GccCiMode::CopyFromLibsDir,
(None, Some(value)) => match value {
true => GccCiMode::DownloadFromCi,
false => GccCiMode::BuildLocally,
},
None => GccCiMode::default(),
(None, None) => GccCiMode::default(),
};

let targets = flags_target
Expand Down Expand Up @@ -1346,6 +1349,7 @@ impl Config {
keep_stage: flags_keep_stage,
keep_stage_std: flags_keep_stage_std,
libdir: install_libdir.map(PathBuf::from),
libgccjit_libs_dir,
library_docs_private_items: build_library_docs_private_items.unwrap_or(false),
lld_enabled,
lldb: build_lldb.map(PathBuf::from),
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/src/core/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ pub enum GccCiMode {
/// If it is not available on CI, it will be built locally instead.
#[default]
DownloadFromCi,
CopyFromLibsDir,
}

pub fn threads_from_config(v: u32) -> u32 {
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/src/core/config/toml/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ define_config! {
#[derive(Default)]
struct Gcc {
download_ci_gcc: Option<bool> = "download-ci-gcc",
libgccjit_libs_dir: Option<PathBuf> = "libgccjit-libs-dir",
}
}
Loading