@@ -237,26 +237,38 @@ pub const LibCInstallation = struct {
237237
238238 fn findNativeIncludeDirPosix (self : * LibCInstallation , args : FindNativeOptions ) FindError ! void {
239239 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+
240256 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 (&.{
244263 "-E" ,
245264 "-Wp,-v" ,
246265 "-xc" ,
247266 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+ });
256268
257269 const exec_res = std .ChildProcess .exec (.{
258270 .allocator = allocator ,
259- .argv = & argv ,
271+ .argv = argv . items ,
260272 .max_output_bytes = 1024 * 1024 ,
261273 .env_map = & env_map ,
262274 // 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 {
267279 }) catch | err | switch (err ) {
268280 error .OutOfMemory = > return error .OutOfMemory ,
269281 else = > {
270- printVerboseInvocation (& argv , null , args .verbose , null );
282+ printVerboseInvocation (argv . items , null , args .verbose , null );
271283 return error .UnableToSpawnCCompiler ;
272284 },
273285 };
@@ -277,11 +289,11 @@ pub const LibCInstallation = struct {
277289 }
278290 switch (exec_res .term ) {
279291 .Exited = > | code | if (code != 0 ) {
280- printVerboseInvocation (& argv , null , args .verbose , exec_res .stderr );
292+ printVerboseInvocation (argv . items , null , args .verbose , exec_res .stderr );
281293 return error .CCompilerExitCode ;
282294 },
283295 else = > {
284- printVerboseInvocation (& argv , null , args .verbose , exec_res .stderr );
296+ printVerboseInvocation (argv . items , null , args .verbose , exec_res .stderr );
285297 return error .CCompilerCrashed ;
286298 },
287299 }
@@ -540,8 +552,6 @@ pub const LibCInstallation = struct {
540552 }
541553};
542554
543- const default_cc_exe = if (is_windows ) "cc.exe" else "cc" ;
544-
545555pub const CCPrintFileNameOptions = struct {
546556 allocator : * Allocator ,
547557 search_basename : []const u8 ,
@@ -553,22 +563,33 @@ pub const CCPrintFileNameOptions = struct {
553563fn ccPrintFileName (args : CCPrintFileNameOptions ) ! [:0 ]u8 {
554564 const allocator = args .allocator ;
555565
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.
561567 var env_map = try std .process .getEnvMap (allocator );
562568 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+ };
563580
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 );
568589
569590 const exec_res = std .ChildProcess .exec (.{
570591 .allocator = allocator ,
571- .argv = & argv ,
592+ .argv = argv . items ,
572593 .max_output_bytes = 1024 * 1024 ,
573594 .env_map = & env_map ,
574595 // 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 {
586607 }
587608 switch (exec_res .term ) {
588609 .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 );
590611 return error .CCompilerExitCode ;
591612 },
592613 else = > {
593- printVerboseInvocation (& argv , args .search_basename , args .verbose , exec_res .stderr );
614+ printVerboseInvocation (argv . items , args .search_basename , args .verbose , exec_res .stderr );
594615 return error .CCompilerCrashed ;
595616 },
596617 }
@@ -659,3 +680,23 @@ fn fillSearch(search_buf: *[2]Search, sdk: *ZigWindowsSDK) []Search {
659680 }
660681 return search_buf [0.. search_end ];
661682}
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