@@ -237,26 +237,38 @@ pub const LibCInstallation = struct {
237
237
238
238
fn findNativeIncludeDirPosix (self : * LibCInstallation , args : FindNativeOptions ) FindError ! void {
239
239
const allocator = args .allocator ;
240
+
241
+ // Detect infinite loops.
242
+ var env_map = try std .process .getEnvMap (allocator );
243
+ defer env_map .deinit ();
244
+ const skip_cc_env_var = if (env_map .get (inf_loop_env_key )) | phase | blk : {
245
+ if (std .mem .eql (u8 , phase , "1" )) {
246
+ try env_map .put (inf_loop_env_key , "2" );
247
+ break :blk true ;
248
+ } else {
249
+ return error .ZigIsTheCCompiler ;
250
+ }
251
+ } else blk : {
252
+ try env_map .put (inf_loop_env_key , "1" );
253
+ break :blk false ;
254
+ };
255
+
240
256
const dev_null = if (is_windows ) "nul" else "/dev/null" ;
241
- const cc_exe = std .os .getenvZ ("CC" ) orelse default_cc_exe ;
242
- const argv = [_ ][]const u8 {
243
- cc_exe ,
257
+
258
+ var argv = std .ArrayList ([]const u8 ).init (allocator );
259
+ defer argv .deinit ();
260
+
261
+ try appendCcExe (& argv , skip_cc_env_var );
262
+ try argv .appendSlice (&.{
244
263
"-E" ,
245
264
"-Wp,-v" ,
246
265
"-xc" ,
247
266
dev_null ,
248
- };
249
- var env_map = try std .process .getEnvMap (allocator );
250
- defer env_map .deinit ();
251
-
252
- // Detect infinite loops.
253
- const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS" ;
254
- if (env_map .get (inf_loop_env_key ) != null ) return error .ZigIsTheCCompiler ;
255
- try env_map .put (inf_loop_env_key , "1" );
267
+ });
256
268
257
269
const exec_res = std .ChildProcess .exec (.{
258
270
.allocator = allocator ,
259
- .argv = & argv ,
271
+ .argv = argv . items ,
260
272
.max_output_bytes = 1024 * 1024 ,
261
273
.env_map = & env_map ,
262
274
// Some C compilers, such as Clang, are known to rely on argv[0] to find the path
@@ -267,7 +279,7 @@ pub const LibCInstallation = struct {
267
279
}) catch | err | switch (err ) {
268
280
error .OutOfMemory = > return error .OutOfMemory ,
269
281
else = > {
270
- printVerboseInvocation (& argv , null , args .verbose , null );
282
+ printVerboseInvocation (argv . items , null , args .verbose , null );
271
283
return error .UnableToSpawnCCompiler ;
272
284
},
273
285
};
@@ -277,11 +289,11 @@ pub const LibCInstallation = struct {
277
289
}
278
290
switch (exec_res .term ) {
279
291
.Exited = > | code | if (code != 0 ) {
280
- printVerboseInvocation (& argv , null , args .verbose , exec_res .stderr );
292
+ printVerboseInvocation (argv . items , null , args .verbose , exec_res .stderr );
281
293
return error .CCompilerExitCode ;
282
294
},
283
295
else = > {
284
- printVerboseInvocation (& argv , null , args .verbose , exec_res .stderr );
296
+ printVerboseInvocation (argv . items , null , args .verbose , exec_res .stderr );
285
297
return error .CCompilerCrashed ;
286
298
},
287
299
}
@@ -540,8 +552,6 @@ pub const LibCInstallation = struct {
540
552
}
541
553
};
542
554
543
- const default_cc_exe = if (is_windows ) "cc.exe" else "cc" ;
544
-
545
555
pub const CCPrintFileNameOptions = struct {
546
556
allocator : * Allocator ,
547
557
search_basename : []const u8 ,
@@ -553,22 +563,33 @@ pub const CCPrintFileNameOptions = struct {
553
563
fn ccPrintFileName (args : CCPrintFileNameOptions ) ! [:0 ]u8 {
554
564
const allocator = args .allocator ;
555
565
556
- const cc_exe = std .os .getenvZ ("CC" ) orelse default_cc_exe ;
557
- const arg1 = try std .fmt .allocPrint (allocator , "-print-file-name={s}" , .{args .search_basename });
558
- defer allocator .free (arg1 );
559
- const argv = [_ ][]const u8 { cc_exe , arg1 };
560
-
566
+ // Detect infinite loops.
561
567
var env_map = try std .process .getEnvMap (allocator );
562
568
defer env_map .deinit ();
569
+ const skip_cc_env_var = if (env_map .get (inf_loop_env_key )) | phase | blk : {
570
+ if (std .mem .eql (u8 , phase , "1" )) {
571
+ try env_map .put (inf_loop_env_key , "2" );
572
+ break :blk true ;
573
+ } else {
574
+ return error .ZigIsTheCCompiler ;
575
+ }
576
+ } else blk : {
577
+ try env_map .put (inf_loop_env_key , "1" );
578
+ break :blk false ;
579
+ };
563
580
564
- // Detect infinite loops.
565
- const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS" ;
566
- if (env_map .get (inf_loop_env_key ) != null ) return error .ZigIsTheCCompiler ;
567
- try env_map .put (inf_loop_env_key , "1" );
581
+ var argv = std .ArrayList ([]const u8 ).init (allocator );
582
+ defer argv .deinit ();
583
+
584
+ const arg1 = try std .fmt .allocPrint (allocator , "-print-file-name={s}" , .{args .search_basename });
585
+ defer allocator .free (arg1 );
586
+
587
+ try appendCcExe (& argv , skip_cc_env_var );
588
+ try argv .append (arg1 );
568
589
569
590
const exec_res = std .ChildProcess .exec (.{
570
591
.allocator = allocator ,
571
- .argv = & argv ,
592
+ .argv = argv . items ,
572
593
.max_output_bytes = 1024 * 1024 ,
573
594
.env_map = & env_map ,
574
595
// Some C compilers, such as Clang, are known to rely on argv[0] to find the path
@@ -586,11 +607,11 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
586
607
}
587
608
switch (exec_res .term ) {
588
609
.Exited = > | code | if (code != 0 ) {
589
- printVerboseInvocation (& argv , args .search_basename , args .verbose , exec_res .stderr );
610
+ printVerboseInvocation (argv . items , args .search_basename , args .verbose , exec_res .stderr );
590
611
return error .CCompilerExitCode ;
591
612
},
592
613
else = > {
593
- printVerboseInvocation (& argv , args .search_basename , args .verbose , exec_res .stderr );
614
+ printVerboseInvocation (argv . items , args .search_basename , args .verbose , exec_res .stderr );
594
615
return error .CCompilerCrashed ;
595
616
},
596
617
}
@@ -659,3 +680,23 @@ fn fillSearch(search_buf: *[2]Search, sdk: *ZigWindowsSDK) []Search {
659
680
}
660
681
return search_buf [0.. search_end ];
661
682
}
683
+
684
+ const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS" ;
685
+
686
+ fn appendCcExe (args : * std .ArrayList ([]const u8 ), skip_cc_env_var : bool ) ! void {
687
+ const default_cc_exe = if (is_windows ) "cc.exe" else "cc" ;
688
+ try args .ensureUnusedCapacity (1 );
689
+ if (skip_cc_env_var ) {
690
+ args .appendAssumeCapacity (default_cc_exe );
691
+ return ;
692
+ }
693
+ const cc_env_var = std .os .getenvZ ("CC" ) orelse {
694
+ args .appendAssumeCapacity (default_cc_exe );
695
+ return ;
696
+ };
697
+ // Respect space-separated flags to the C compiler.
698
+ var it = std .mem .tokenize (cc_env_var , " " );
699
+ while (it .next ()) | arg | {
700
+ try args .append (arg );
701
+ }
702
+ }
0 commit comments