@@ -20,14 +20,16 @@ use rustc_span::edit_distance::find_best_match_for_name;
20
20
use rustc_span:: edition:: Edition ;
21
21
use rustc_span:: source_map:: FileLoader ;
22
22
use rustc_span:: symbol:: { sym, Symbol } ;
23
+ use rustc_target:: spec:: Target ;
23
24
use session:: { CompilerIO , EarlyErrorHandler } ;
24
- use std:: env;
25
25
use std:: env:: consts:: { DLL_PREFIX , DLL_SUFFIX } ;
26
26
use std:: mem;
27
+ use std:: ops:: Deref ;
27
28
use std:: path:: { Path , PathBuf } ;
28
29
use std:: sync:: atomic:: { AtomicBool , Ordering } ;
29
30
use std:: sync:: OnceLock ;
30
31
use std:: thread;
32
+ use std:: { env, iter} ;
31
33
32
34
/// Function pointer type that constructs a new CodegenBackend.
33
35
pub type MakeBackendFn = fn ( ) -> Box < dyn CodegenBackend > ;
@@ -79,24 +81,41 @@ pub fn create_session(
79
81
} ;
80
82
81
83
let ( codegen_backend, target_cfg) = match make_codegen_backend {
82
- Some ( make_codegen_backend) => {
83
- let backend = make_codegen_backend ( & sopts) ;
84
+ None => {
85
+ // Build a target without override, so that it can override the backend if needed
86
+ let target = config:: build_target_config ( handler, & sopts, None , & sysroot) ;
87
+
88
+ let backend = get_codegen_backend (
89
+ handler,
90
+ & sysroot,
91
+ sopts. unstable_opts . codegen_backend . as_deref ( ) ,
92
+ & target,
93
+ ) ;
84
94
85
95
// target_override is documented to be called before init(), so this is okay
86
96
let target_override = backend. target_override ( & sopts) ;
87
97
98
+ // Assert that we don't use target's override of the backend and
99
+ // backend's override of the target at the same time
100
+ if sopts. unstable_opts . codegen_backend . is_none ( )
101
+ && target. default_codegen_backend . is_some ( )
102
+ && target_override. is_some ( )
103
+ {
104
+ rustc_middle:: bug!(
105
+ "Codegen backend requested target override even though the target requested the backend"
106
+ ) ;
107
+ }
108
+
109
+ // Re-build target with the (potential) override
88
110
let target = config:: build_target_config ( handler, & sopts, target_override, & sysroot) ;
89
111
90
112
( backend, target)
91
113
}
92
- None => {
93
- let _target = config:: build_target_config ( handler, & sopts, None , & sysroot) ;
114
+ Some ( make_codegen_backend) => {
115
+ // N.B. `make_codegen_backend` takes precedence over `target.default_codegen_backend`,
116
+ // which is ignored in this case.
94
117
95
- let backend = get_codegen_backend (
96
- handler,
97
- & sopts. maybe_sysroot ,
98
- sopts. unstable_opts . codegen_backend . as_deref ( ) ,
99
- ) ;
118
+ let backend = make_codegen_backend ( & sopts) ;
100
119
101
120
// target_override is documented to be called before init(), so this is okay
102
121
let target_override = backend. target_override ( & sopts) ;
@@ -295,21 +314,25 @@ fn load_backend_from_dylib(handler: &EarlyErrorHandler, path: &Path) -> MakeBack
295
314
/// A name of `None` indicates that the default backend should be used.
296
315
pub fn get_codegen_backend (
297
316
handler : & EarlyErrorHandler ,
298
- maybe_sysroot : & Option < PathBuf > ,
317
+ sysroot : & Path ,
299
318
backend_name : Option < & str > ,
319
+ target : & Target ,
300
320
) -> Box < dyn CodegenBackend > {
301
321
static LOAD : OnceLock < unsafe fn ( ) -> Box < dyn CodegenBackend > > = OnceLock :: new ( ) ;
302
322
303
323
let load = LOAD . get_or_init ( || {
304
- let default_codegen_backend = option_env ! ( "CFG_DEFAULT_CODEGEN_BACKEND" ) . unwrap_or ( "llvm" ) ;
324
+ let backend = backend_name
325
+ . or ( target. default_codegen_backend . as_deref ( ) )
326
+ . or ( option_env ! ( "CFG_DEFAULT_CODEGEN_BACKEND" ) )
327
+ . unwrap_or ( "llvm" ) ;
305
328
306
- match backend_name . unwrap_or ( default_codegen_backend ) {
329
+ match backend {
307
330
filename if filename. contains ( '.' ) => {
308
331
load_backend_from_dylib ( handler, filename. as_ref ( ) )
309
332
}
310
333
#[ cfg( feature = "llvm" ) ]
311
334
"llvm" => rustc_codegen_llvm:: LlvmCodegenBackend :: new,
312
- backend_name => get_codegen_sysroot ( handler, maybe_sysroot , backend_name) ,
335
+ backend_name => get_codegen_sysroot ( handler, sysroot , backend_name) ,
313
336
}
314
337
} ) ;
315
338
@@ -343,7 +366,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
343
366
344
367
fn get_codegen_sysroot (
345
368
handler : & EarlyErrorHandler ,
346
- maybe_sysroot : & Option < PathBuf > ,
369
+ sysroot : & Path ,
347
370
backend_name : & str ,
348
371
) -> MakeBackendFn {
349
372
// For now we only allow this function to be called once as it'll dlopen a
@@ -360,9 +383,8 @@ fn get_codegen_sysroot(
360
383
let target = session:: config:: host_triple ( ) ;
361
384
let sysroot_candidates = sysroot_candidates ( ) ;
362
385
363
- let sysroot = maybe_sysroot
364
- . iter ( )
365
- . chain ( sysroot_candidates. iter ( ) )
386
+ let sysroot = iter:: once ( sysroot)
387
+ . chain ( sysroot_candidates. iter ( ) . map ( <_ >:: deref) )
366
388
. map ( |sysroot| {
367
389
filesearch:: make_target_lib_path ( sysroot, target) . with_file_name ( "codegen-backends" )
368
390
} )
0 commit comments