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