Skip to content

Build GCC on CI #136921

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 6 commits into from
Feb 26, 2025
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
3 changes: 2 additions & 1 deletion license-metadata.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"directories": [],
"files": [
"analyzer-decls.h",
"malloc-macro.h"
"malloc-macro.h",
"sarif-path-role.h"
],
"license": {
"copyright": [
Expand Down
9 changes: 9 additions & 0 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::{env, fs, str};

use serde_derive::Deserialize;

use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
use crate::core::build_steps::tool::SourceType;
use crate::core::build_steps::{dist, llvm};
use crate::core::builder;
Expand Down Expand Up @@ -1500,6 +1501,14 @@ impl Step for CodegenBackend {
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
rustc_cargo_env(builder, &mut cargo, target, compiler.stage);

// Ideally, we'd have a separate step for the individual codegen backends,
// like we have in tests (test::CodegenGCC) but that would require a lot of restructuring.
// If the logic gets more complicated, it should probably be done.
if backend == "gcc" {
let gcc = builder.ensure(Gcc { target });
add_cg_gcc_cargo_flags(&mut cargo, &gcc);
}

let tmp_stamp = BuildStamp::new(&out_dir).with_prefix("tmp");

let _guard = builder.msg_build(compiler, format_args!("codegen backend {backend}"), target);
Expand Down
51 changes: 37 additions & 14 deletions src/bootstrap/src/core/build_steps/gcc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
//! ensure that they're always in place if needed.

use std::fs;
use std::path::PathBuf;
use std::path::{Path, PathBuf};
use std::sync::OnceLock;

use build_helper::ci::CiEnv;

use crate::Kind;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::core::builder::{Builder, Cargo, RunConfig, ShouldRun, Step};
use crate::core::config::TargetSelection;
use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash};
use crate::utils::exec::command;
Expand All @@ -29,7 +29,8 @@ pub struct Meta {
}

pub enum GccBuildStatus {
AlreadyBuilt,
/// libgccjit is already built at this path
AlreadyBuilt(PathBuf),
ShouldBuild(Meta),
}

Expand All @@ -41,9 +42,6 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc
// Initialize the gcc submodule if not initialized already.
builder.config.update_submodule("src/gcc");

// FIXME (GuillaumeGomez): To be done once gccjit has been built in the CI.
// builder.config.maybe_download_ci_gcc();

let root = builder.src.join("src/gcc");
let out_dir = builder.gcc_out(target).join("build");
let install_dir = builder.gcc_out(target).join("install");
Expand All @@ -70,19 +68,37 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc
stamp.path().display()
));
}
return GccBuildStatus::AlreadyBuilt;
let path = libgccjit_built_path(&install_dir);
if path.is_file() {
Copy link
Member

Choose a reason for hiding this comment

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

Why not using exists?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I usually prefer explicitly marking that it should be a file, but no strong opinion on this.

Copy link
Member

Choose a reason for hiding this comment

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

I am okay with it. It just seemed weird to me.

return GccBuildStatus::AlreadyBuilt(path);
} else {
builder.info(&format!(
"GCC stamp is up-to-date, but the libgccjit.so file was not found at `{}`",
path.display(),
));
}
}

GccBuildStatus::ShouldBuild(Meta { stamp, out_dir, install_dir, root })
}

/// Returns the path to a libgccjit.so file in the install directory of GCC.
fn libgccjit_built_path(install_dir: &Path) -> PathBuf {
install_dir.join("lib/libgccjit.so")
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Gcc {
pub target: TargetSelection,
}

#[derive(Clone)]
pub struct GccOutput {
pub libgccjit: PathBuf,
}

impl Step for Gcc {
type Output = bool;
type Output = GccOutput;

const ONLY_HOSTS: bool = true;

Expand All @@ -94,14 +110,14 @@ impl Step for Gcc {
run.builder.ensure(Gcc { target: run.target });
}

/// Compile GCC for `target`.
fn run(self, builder: &Builder<'_>) -> bool {
/// Compile GCC (specifically `libgccjit`) for `target`.
fn run(self, builder: &Builder<'_>) -> Self::Output {
let target = self.target;

// If GCC has already been built, we avoid building it again.
let Meta { stamp, out_dir, install_dir, root } = match prebuilt_gcc_config(builder, target)
{
GccBuildStatus::AlreadyBuilt => return true,
GccBuildStatus::AlreadyBuilt(path) => return GccOutput { libgccjit: path },
GccBuildStatus::ShouldBuild(m) => m,
};

Expand All @@ -110,8 +126,9 @@ impl Step for Gcc {
let _time = helpers::timeit(builder);
t!(fs::create_dir_all(&out_dir));

let libgccjit_path = libgccjit_built_path(&install_dir);
if builder.config.dry_run() {
return true;
return GccOutput { libgccjit: libgccjit_path };
Comment on lines +129 to +131
Copy link
Member

Choose a reason for hiding this comment

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

You can make libgccjit_built_path to return GccOutput directly. Or, maybe return PathBuf from this step instead of the wrapper type GccOutput?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't like when Steps return just PathBuf, it's not obvious what does the path represent. In the future the struct might contain other attributes, the path to the libgccjit file isn't exactly the same as the built output of thw GCC step.

}

// GCC creates files (e.g. symlinks to the downloaded dependencies)
Expand Down Expand Up @@ -173,11 +190,17 @@ impl Step for Gcc {

let lib_alias = install_dir.join("lib/libgccjit.so.0");
if !lib_alias.exists() {
t!(builder.symlink_file(install_dir.join("lib/libgccjit.so"), lib_alias,));
t!(builder.symlink_file(&libgccjit_path, lib_alias));
}

t!(stamp.write());

true
GccOutput { libgccjit: libgccjit_path }
}
}

/// 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()));
}
7 changes: 6 additions & 1 deletion src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use clap_complete::shells;

use crate::core::build_steps::compile::run_cargo;
use crate::core::build_steps::doc::DocumentationFormat;
use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
use crate::core::build_steps::llvm::get_llvm_version;
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
use crate::core::build_steps::tool::{self, SourceType, Tool};
Expand Down Expand Up @@ -3520,6 +3521,8 @@ impl Step for CodegenGCC {
let compiler = self.compiler;
let target = self.target;

let gcc = builder.ensure(Gcc { target });

builder.ensure(
compile::Std::new(compiler, target)
.extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]),
Expand All @@ -3546,6 +3549,7 @@ impl Step for CodegenGCC {
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
add_cg_gcc_cargo_flags(&mut cargo, &gcc);

// Avoid incremental cache issues when changing rustc
cargo.env("CARGO_BUILD_INCREMENTAL", "false");
Expand Down Expand Up @@ -3578,9 +3582,10 @@ impl Step for CodegenGCC {
.env("CG_RUSTFLAGS", "-Alinker-messages")
.arg("--")
.arg("test")
.arg("--use-system-gcc")
.arg("--use-backend")
.arg("gcc")
.arg("--gcc-path")
.arg(gcc.libgccjit.parent().unwrap())
.arg("--out-dir")
.arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_gcc"))
.arg("--release")
Expand Down
4 changes: 1 addition & 3 deletions src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ FROM ubuntu:24.04
ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get update && apt-get install -y --no-install-recommends \
bzip2 \
Copy link
Member

Choose a reason for hiding this comment

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

Q: Why is it required only in this image but not in others?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently we build and test GCC only on this one job, in PR builds, unless I missed something.

g++ \
gcc-multilib \
make \
Expand Down Expand Up @@ -55,9 +56,6 @@ ENV RUST_CONFIGURE_ARGS \
--set rust.thin-lto-import-instr-limit=10

COPY scripts/shared.sh /scripts/
COPY scripts/build-gccjit.sh /scripts/

RUN /scripts/build-gccjit.sh /scripts

ARG SCRIPT_ARG

Expand Down
3 changes: 0 additions & 3 deletions src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ ENV RUST_CONFIGURE_ARGS \
--set rust.thin-lto-import-instr-limit=10

COPY scripts/shared.sh /scripts/
COPY scripts/build-gccjit.sh /scripts/

RUN /scripts/build-gccjit.sh /scripts

ARG SCRIPT_ARG

Expand Down
3 changes: 0 additions & 3 deletions src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,6 @@ ENV HOST_TARGET x86_64-unknown-linux-gnu
#ENV FORCE_CI_RUSTC 1

COPY scripts/shared.sh /scripts/
COPY scripts/build-gccjit.sh /scripts/

RUN /scripts/build-gccjit.sh /scripts

# For now, we need to use `--unsafe-perm=true` to go around an issue when npm tries
# to create a new folder. For reference:
Expand Down
37 changes: 0 additions & 37 deletions src/ci/docker/scripts/build-gccjit.sh

This file was deleted.

2 changes: 1 addition & 1 deletion src/gcc
Submodule gcc updated 19134 files
Loading