@@ -312,6 +312,7 @@ pub struct Build {
312
312
emit_rerun_if_env_changed : bool ,
313
313
cached_compiler_family : Arc < RwLock < HashMap < Box < Path > , ToolFamily > > > ,
314
314
shell_escaped_flags : Option < bool > ,
315
+ inherit_rustflags : bool ,
315
316
}
316
317
317
318
/// Represents the types of errors that may occur while using cc-rs.
@@ -437,6 +438,7 @@ impl Build {
437
438
emit_rerun_if_env_changed : true ,
438
439
cached_compiler_family : Arc :: default ( ) ,
439
440
shell_escaped_flags : None ,
441
+ inherit_rustflags : true ,
440
442
}
441
443
}
442
444
@@ -664,6 +666,7 @@ impl Build {
664
666
. debug ( false )
665
667
. cpp ( self . cpp )
666
668
. cuda ( self . cuda )
669
+ . inherit_rustflags ( false )
667
670
. emit_rerun_if_env_changed ( self . emit_rerun_if_env_changed ) ;
668
671
if let Some ( target) = & self . target {
669
672
cfg. target ( target) ;
@@ -1313,6 +1316,15 @@ impl Build {
1313
1316
self
1314
1317
}
1315
1318
1319
+ /// Configure whether cc should automatically inherit compatible flags passed to rustc
1320
+ /// from `CARGO_ENCODED_RUSTFLAGS`.
1321
+ ///
1322
+ /// This option defaults to `true`.
1323
+ pub fn inherit_rustflags ( & mut self , inherit_rustflags : bool ) -> & mut Build {
1324
+ self . inherit_rustflags = inherit_rustflags;
1325
+ self
1326
+ }
1327
+
1316
1328
#[ doc( hidden) ]
1317
1329
pub fn __set_env < A , B > ( & mut self , a : A , b : B ) -> & mut Build
1318
1330
where
@@ -1904,6 +1916,11 @@ impl Build {
1904
1916
cmd. args . push ( ( * * flag) . into ( ) ) ;
1905
1917
}
1906
1918
1919
+ // Add cc flags inherited from matching rustc flags
1920
+ if self . inherit_rustflags {
1921
+ self . add_inherited_rustflags ( & mut cmd, & target) ?;
1922
+ }
1923
+
1907
1924
for flag in self . flags_supported . iter ( ) {
1908
1925
if self
1909
1926
. is_flag_supported_inner ( flag, & cmd. path , & target)
@@ -2439,6 +2456,38 @@ impl Build {
2439
2456
Ok ( ( ) )
2440
2457
}
2441
2458
2459
+ fn add_inherited_rustflags ( & self , cmd : & mut Tool , target : & Target ) -> Result < ( ) , Error > {
2460
+ let env_os = match self . getenv ( "CARGO_ENCODED_RUSTFLAGS" ) {
2461
+ Some ( env) => env,
2462
+ // No encoded RUSTFLAGS -> nothing to do
2463
+ None => return Ok ( ( ) ) ,
2464
+ } ;
2465
+
2466
+ let mut cc_flags: Vec < OsString > = env_os
2467
+ . to_string_lossy ( )
2468
+ . split ( "\u{1f} " )
2469
+ // Strip prefixes from rustc flags
2470
+ . flat_map ( |flag| {
2471
+ if flag == "-Z" || flag == "-C" {
2472
+ None
2473
+ } else if flag. starts_with ( "-Z" ) || flag. starts_with ( "-C" ) {
2474
+ Some ( & flag[ 2 ..] )
2475
+ } else {
2476
+ Some ( flag)
2477
+ }
2478
+ } )
2479
+ . flat_map ( |flag| rustc_to_cc_flag ( flag, cmd. family ) )
2480
+ // Filter out flags not supported by the currently used CC
2481
+ . filter ( |flag| {
2482
+ self . is_flag_supported_inner ( flag, & cmd. path , & target)
2483
+ . unwrap_or ( false )
2484
+ } )
2485
+ . collect ( ) ;
2486
+
2487
+ cmd. args . append ( & mut cc_flags) ;
2488
+ Ok ( ( ) )
2489
+ }
2490
+
2442
2491
fn has_flags ( & self ) -> bool {
2443
2492
let flags_env_var_name = if self . cpp { "CXXFLAGS" } else { "CFLAGS" } ;
2444
2493
let flags_env_var_value = self . getenv_with_target_prefixes ( flags_env_var_name) ;
@@ -4221,6 +4270,161 @@ fn map_darwin_target_from_rust_to_compiler_architecture(target: &Target) -> &str
4221
4270
}
4222
4271
}
4223
4272
4273
+ // Rust and clang/cc don't agree on what equivalent flags should look like either.
4274
+ fn rustc_to_cc_flag ( flag : & str , family : ToolFamily ) -> Option < OsString > {
4275
+ match family {
4276
+ ToolFamily :: Clang { .. } | ToolFamily :: Gnu => match flag {
4277
+ _ if flag. starts_with ( "branch-protection" ) => {
4278
+ Some ( format ! ( "-m{}" , flag. replace( "," , "+" ) ) . into ( ) )
4279
+ }
4280
+ _ if flag. starts_with ( "code-model" ) => {
4281
+ Some ( flag. replace ( "code-model" , "-mcmodel" ) . into ( ) )
4282
+ }
4283
+ _ if flag. starts_with ( "no-vectorize-loops" ) => Some ( "-fno-vectorize" . into ( ) ) ,
4284
+ _ if flag. starts_with ( "no-vectorize-slp" ) => Some ( "-fno-slp-vectorize" . into ( ) ) ,
4285
+ _ if flag. starts_with ( "profile-generate" ) => Some ( format ! ( "-f{flag}" ) . into ( ) ) ,
4286
+ _ if flag. starts_with ( "profile-use" ) => Some ( format ! ( "-f{flag}" ) . into ( ) ) ,
4287
+ _ if flag. starts_with ( "control-flow-guard" ) => {
4288
+ if let Some ( ( _, rustc_val) ) = flag. split_once ( "=" ) {
4289
+ let cc_val = match rustc_val {
4290
+ "y" | "yes" | "on" | "true" | "checks" => "cf" ,
4291
+ "nochecks" => "cf-nochecks" ,
4292
+ "n" | "no" | "off" | "false" => "none" ,
4293
+ _ => return None ,
4294
+ } ;
4295
+ Some ( format ! ( "-mguard={cc_val}" ) . into ( ) )
4296
+ } else {
4297
+ None
4298
+ }
4299
+ }
4300
+ _ if flag. starts_with ( "embed-bitcode" ) => {
4301
+ if let Some ( ( _, rustc_val) ) = flag. split_once ( "=" ) {
4302
+ let cc_val = match rustc_val {
4303
+ "y" | "yes" | "on" | "true" => "all" ,
4304
+ "n" | "no" | "off" | "false" => "off" ,
4305
+ _ => return None ,
4306
+ } ;
4307
+ Some ( format ! ( "-fembed-bitcode={cc_val}" ) . into ( ) )
4308
+ } else {
4309
+ None
4310
+ }
4311
+ }
4312
+ _ if flag. starts_with ( "force-frame-pointers" ) => {
4313
+ let force_frame_pointers = if let Some ( ( _, rustc_val) ) = flag. split_once ( "=" ) {
4314
+ match rustc_val {
4315
+ "y" | "yes" | "on" | "true" => true ,
4316
+ "n" | "no" | "off" | "false" => false ,
4317
+ _ => return None ,
4318
+ }
4319
+ } else {
4320
+ true
4321
+ } ;
4322
+ let cc_flag = if force_frame_pointers {
4323
+ "-fno-omit-frame-pointer"
4324
+ } else {
4325
+ "-fomit-frame-pointer"
4326
+ } ;
4327
+ Some ( cc_flag. into ( ) )
4328
+ }
4329
+ _ if flag. starts_with ( "link-dead-code" ) => match flag. split_once ( "=" ) {
4330
+ Some ( ( _, "n" | "no" | "off" | "false" ) ) => Some ( "-dead_strip" . into ( ) ) ,
4331
+ _ => None ,
4332
+ } ,
4333
+ _ if flag. starts_with ( "lto" ) => {
4334
+ let lto_mode = if let Some ( ( _, rustc_val) ) = flag. split_once ( "=" ) {
4335
+ match rustc_val {
4336
+ "y" | "yes" | "on" | "true" | "fat" => "full" ,
4337
+ "thin" => "thin" ,
4338
+ _ => return None ,
4339
+ }
4340
+ } else {
4341
+ "full"
4342
+ } ;
4343
+
4344
+ Some ( format ! ( "-flto={lto_mode}" ) . into ( ) )
4345
+ }
4346
+ _ if flag. starts_with ( "no-redzone" ) => {
4347
+ let no_redzone = if let Some ( ( _, rustc_val) ) = flag. split_once ( "=" ) {
4348
+ match rustc_val {
4349
+ "y" | "yes" | "on" | "true" => true ,
4350
+ "n" | "no" | "off" | "false" => false ,
4351
+ _ => return None ,
4352
+ }
4353
+ } else {
4354
+ true
4355
+ } ;
4356
+
4357
+ let cc_flag = if no_redzone {
4358
+ "-mno-red-zone"
4359
+ } else {
4360
+ "-mred-zone"
4361
+ } ;
4362
+ Some ( cc_flag. into ( ) )
4363
+ }
4364
+ _ if flag. starts_with ( "relocation-model" ) => {
4365
+ if let Some ( ( _, rustc_val) ) = flag. split_once ( "=" ) {
4366
+ let cc_flag = match rustc_val {
4367
+ "pic" => "-fPIC" ,
4368
+ "pie" => "-fPIE" ,
4369
+ "dynamic-no-pic" => "-mdynamic-no-pic" ,
4370
+ _ => return None ,
4371
+ } ;
4372
+ Some ( cc_flag. into ( ) )
4373
+ } else {
4374
+ None
4375
+ }
4376
+ }
4377
+ _ if flag. starts_with ( "soft-float" ) => {
4378
+ let soft_float = if let Some ( ( _, rustc_val) ) = flag. split_once ( "=" ) {
4379
+ match rustc_val {
4380
+ "y" | "yes" | "on" | "true" => true ,
4381
+ "n" | "no" | "off" | "false" => false ,
4382
+ _ => return None ,
4383
+ }
4384
+ } else {
4385
+ true
4386
+ } ;
4387
+
4388
+ let cc_flag = if soft_float {
4389
+ "-msoft-float"
4390
+ } else {
4391
+ "-mno-soft-float"
4392
+ } ;
4393
+ Some ( cc_flag. into ( ) )
4394
+ }
4395
+ _ => None ,
4396
+ } ,
4397
+ ToolFamily :: Msvc { .. } => match flag {
4398
+ _ if flag. starts_with ( "control-flow-guard" ) => {
4399
+ if let Some ( ( _, rustc_val) ) = flag. split_once ( "=" ) {
4400
+ let cc_val = match rustc_val {
4401
+ "y" | "yes" | "on" | "true" | "checks" => "cf" ,
4402
+ "n" | "no" | "off" | "false" => "cf-" ,
4403
+ _ => return None ,
4404
+ } ;
4405
+ Some ( format ! ( "/guard:{cc_val}" ) . into ( ) )
4406
+ } else {
4407
+ None
4408
+ }
4409
+ }
4410
+ _ if flag. starts_with ( "force-frame-pointers" ) => {
4411
+ let force_frame_pointers = if let Some ( ( _, rustc_val) ) = flag. split_once ( "=" ) {
4412
+ match rustc_val {
4413
+ "y" | "yes" | "on" | "true" => true ,
4414
+ "n" | "no" | "off" | "false" => false ,
4415
+ _ => return None ,
4416
+ }
4417
+ } else {
4418
+ true
4419
+ } ;
4420
+ let cc_flag = if force_frame_pointers { "/Oy-" } else { "/Oy" } ;
4421
+ Some ( cc_flag. into ( ) )
4422
+ }
4423
+ _ => None ,
4424
+ } ,
4425
+ }
4426
+ }
4427
+
4224
4428
#[ derive( Clone , Copy , PartialEq ) ]
4225
4429
enum AsmFileExt {
4226
4430
/// `.asm` files. On MSVC targets, we assume these should be passed to MASM
0 commit comments