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