99//! ensure that they're always in place if needed.
1010
1111use std:: fs;
12- use std:: path:: PathBuf ;
12+ use std:: path:: { Path , PathBuf } ;
1313use std:: sync:: OnceLock ;
1414
1515use build_helper:: ci:: CiEnv ;
1616
1717use crate :: Kind ;
18- use crate :: core:: builder:: { Builder , RunConfig , ShouldRun , Step } ;
18+ use crate :: core:: builder:: { Builder , Cargo , RunConfig , ShouldRun , Step } ;
1919use crate :: core:: config:: TargetSelection ;
2020use crate :: utils:: build_stamp:: { BuildStamp , generate_smart_stamp_hash} ;
2121use crate :: utils:: exec:: command;
@@ -29,7 +29,8 @@ pub struct Meta {
2929}
3030
3131pub enum GccBuildStatus {
32- AlreadyBuilt ,
32+ /// libgccjit is already built at this path
33+ AlreadyBuilt ( PathBuf ) ,
3334 ShouldBuild ( Meta ) ,
3435}
3536
@@ -41,9 +42,6 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc
4142 // Initialize the gcc submodule if not initialized already.
4243 builder. config . update_submodule ( "src/gcc" ) ;
4344
44- // FIXME (GuillaumeGomez): To be done once gccjit has been built in the CI.
45- // builder.config.maybe_download_ci_gcc();
46-
4745 let root = builder. src . join ( "src/gcc" ) ;
4846 let out_dir = builder. gcc_out ( target) . join ( "build" ) ;
4947 let install_dir = builder. gcc_out ( target) . join ( "install" ) ;
@@ -70,19 +68,37 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc
7068 stamp. path( ) . display( )
7169 ) ) ;
7270 }
73- return GccBuildStatus :: AlreadyBuilt ;
71+ let path = libgccjit_built_path ( & install_dir) ;
72+ if path. is_file ( ) {
73+ return GccBuildStatus :: AlreadyBuilt ( path) ;
74+ } else {
75+ builder. info ( & format ! (
76+ "GCC stamp is up-to-date, but the libgccjit.so file was not found at `{}`" ,
77+ path. display( ) ,
78+ ) ) ;
79+ }
7480 }
7581
7682 GccBuildStatus :: ShouldBuild ( Meta { stamp, out_dir, install_dir, root } )
7783}
7884
85+ /// Returns the path to a libgccjit.so file in the install directory of GCC.
86+ fn libgccjit_built_path ( install_dir : & Path ) -> PathBuf {
87+ install_dir. join ( "lib/libgccjit.so" )
88+ }
89+
7990#[ derive( Debug , Clone , Hash , PartialEq , Eq ) ]
8091pub struct Gcc {
8192 pub target : TargetSelection ,
8293}
8394
95+ #[ derive( Clone ) ]
96+ pub struct GccOutput {
97+ pub libgccjit : PathBuf ,
98+ }
99+
84100impl Step for Gcc {
85- type Output = bool ;
101+ type Output = GccOutput ;
86102
87103 const ONLY_HOSTS : bool = true ;
88104
@@ -94,14 +110,14 @@ impl Step for Gcc {
94110 run. builder . ensure ( Gcc { target : run. target } ) ;
95111 }
96112
97- /// Compile GCC for `target`.
98- fn run ( self , builder : & Builder < ' _ > ) -> bool {
113+ /// Compile GCC (specifically `libgccjit`) for `target`.
114+ fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
99115 let target = self . target ;
100116
101117 // If GCC has already been built, we avoid building it again.
102118 let Meta { stamp, out_dir, install_dir, root } = match prebuilt_gcc_config ( builder, target)
103119 {
104- GccBuildStatus :: AlreadyBuilt => return true ,
120+ GccBuildStatus :: AlreadyBuilt ( path ) => return GccOutput { libgccjit : path } ,
105121 GccBuildStatus :: ShouldBuild ( m) => m,
106122 } ;
107123
@@ -110,8 +126,9 @@ impl Step for Gcc {
110126 let _time = helpers:: timeit ( builder) ;
111127 t ! ( fs:: create_dir_all( & out_dir) ) ;
112128
129+ let libgccjit_path = libgccjit_built_path ( & install_dir) ;
113130 if builder. config . dry_run ( ) {
114- return true ;
131+ return GccOutput { libgccjit : libgccjit_path } ;
115132 }
116133
117134 // GCC creates files (e.g. symlinks to the downloaded dependencies)
@@ -173,11 +190,17 @@ impl Step for Gcc {
173190
174191 let lib_alias = install_dir. join ( "lib/libgccjit.so.0" ) ;
175192 if !lib_alias. exists ( ) {
176- t ! ( builder. symlink_file( install_dir . join ( "lib/libgccjit.so" ) , lib_alias, ) ) ;
193+ t ! ( builder. symlink_file( & libgccjit_path , lib_alias) ) ;
177194 }
178195
179196 t ! ( stamp. write( ) ) ;
180197
181- true
198+ GccOutput { libgccjit : libgccjit_path }
182199 }
183200}
201+
202+ /// Configures a Cargo invocation so that it can build the GCC codegen backend.
203+ pub fn add_cg_gcc_cargo_flags ( cargo : & mut Cargo , gcc : & GccOutput ) {
204+ // Add the path to libgccjit.so to the linker search paths.
205+ cargo. rustflag ( & format ! ( "-L{}" , gcc. libgccjit. parent( ) . unwrap( ) . display( ) ) ) ;
206+ }
0 commit comments