| ... | @@ -237,26 +237,38 @@ pub const LibCInstallation = struct { | ... | @@ -237,26 +237,38 @@ pub const LibCInstallation = struct { |
| 237 | | 237 | |
| 238 | fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { | 238 | fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void { |
| 239 | const allocator = args.allocator; | 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 | const dev_null = if (is_windows) "nul" else "/dev/null"; | 256 | const dev_null = if (is_windows) "nul" else "/dev/null"; |
| 241 | const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; | 257 | |
| 242 | const argv = [_][]const u8{ | 258 | var argv = std.ArrayList([]const u8).init(allocator); |
| 243 | cc_exe, | 259 | defer argv.deinit(); |
| | 260 | |
| | 261 | try appendCcExe(&argv, skip_cc_env_var); |
| | 262 | try argv.appendSlice(&.{ |
| 244 | "-E", | 263 | "-E", |
| 245 | "-Wp,-v", | 264 | "-Wp,-v", |
| 246 | "-xc", | 265 | "-xc", |
| 247 | dev_null, | 266 | dev_null, |
| 248 | }; | 267 | }); |
| 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"); | | |
| 256 | | 268 | |
| 257 | const exec_res = std.ChildProcess.exec(.{ | 269 | const exec_res = std.ChildProcess.exec(.{ |
| 258 | .allocator = allocator, | 270 | .allocator = allocator, |
| 259 | .argv = &argv, | 271 | .argv = argv.items, |
| 260 | .max_output_bytes = 1024 * 1024, | 272 | .max_output_bytes = 1024 * 1024, |
| 261 | .env_map = &env_map, | 273 | .env_map = &env_map, |
| 262 | // Some C compilers, such as Clang, are known to rely on argv[0] to find the path | 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,7 +279,7 @@ pub const LibCInstallation = struct { |
| 267 | }) catch |err| switch (err) { | 279 | }) catch |err| switch (err) { |
| 268 | error.OutOfMemory => return error.OutOfMemory, | 280 | error.OutOfMemory => return error.OutOfMemory, |
| 269 | else => { | 281 | else => { |
| 270 | printVerboseInvocation(&argv, null, args.verbose, null); | 282 | printVerboseInvocation(argv.items, null, args.verbose, null); |
| 271 | return error.UnableToSpawnCCompiler; | 283 | return error.UnableToSpawnCCompiler; |
| 272 | }, | 284 | }, |
| 273 | }; | 285 | }; |
| ... | @@ -277,11 +289,11 @@ pub const LibCInstallation = struct { | ... | @@ -277,11 +289,11 @@ pub const LibCInstallation = struct { |
| 277 | } | 289 | } |
| 278 | switch (exec_res.term) { | 290 | switch (exec_res.term) { |
| 279 | .Exited => |code| if (code != 0) { | 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 | return error.CCompilerExitCode; | 293 | return error.CCompilerExitCode; |
| 282 | }, | 294 | }, |
| 283 | else => { | 295 | else => { |
| 284 | printVerboseInvocation(&argv, null, args.verbose, exec_res.stderr); | 296 | printVerboseInvocation(argv.items, null, args.verbose, exec_res.stderr); |
| 285 | return error.CCompilerCrashed; | 297 | return error.CCompilerCrashed; |
| 286 | }, | 298 | }, |
| 287 | } | 299 | } |
| ... | @@ -540,8 +552,6 @@ pub const LibCInstallation = struct { | ... | @@ -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 | pub const CCPrintFileNameOptions = struct { | 555 | pub const CCPrintFileNameOptions = struct { |
| 546 | allocator: *Allocator, | 556 | allocator: *Allocator, |
| 547 | search_basename: []const u8, | 557 | search_basename: []const u8, |
| ... | @@ -553,22 +563,33 @@ pub const CCPrintFileNameOptions = struct { | ... | @@ -553,22 +563,33 @@ pub const CCPrintFileNameOptions = struct { |
| 553 | fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { | 563 | fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { |
| 554 | const allocator = args.allocator; | 564 | const allocator = args.allocator; |
| 555 | | 565 | |
| 556 | const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; | 566 | // Detect infinite loops. |
| 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 | | | |
| 561 | var env_map = try std.process.getEnvMap(allocator); | 567 | var env_map = try std.process.getEnvMap(allocator); |
| 562 | defer env_map.deinit(); | 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. | 581 | var argv = std.ArrayList([]const u8).init(allocator); |
| 565 | const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS"; | 582 | defer argv.deinit(); |
| 566 | if (env_map.get(inf_loop_env_key) != null) return error.ZigIsTheCCompiler; | 583 | |
| 567 | try env_map.put(inf_loop_env_key, "1"); | 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 | const exec_res = std.ChildProcess.exec(.{ | 590 | const exec_res = std.ChildProcess.exec(.{ |
| 570 | .allocator = allocator, | 591 | .allocator = allocator, |
| 571 | .argv = &argv, | 592 | .argv = argv.items, |
| 572 | .max_output_bytes = 1024 * 1024, | 593 | .max_output_bytes = 1024 * 1024, |
| 573 | .env_map = &env_map, | 594 | .env_map = &env_map, |
| 574 | // Some C compilers, such as Clang, are known to rely on argv[0] to find the path | 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,11 +607,11 @@ fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { |
| 586 | } | 607 | } |
| 587 | switch (exec_res.term) { | 608 | switch (exec_res.term) { |
| 588 | .Exited => |code| if (code != 0) { | 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 | return error.CCompilerExitCode; | 611 | return error.CCompilerExitCode; |
| 591 | }, | 612 | }, |
| 592 | else => { | 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 | return error.CCompilerCrashed; | 615 | return error.CCompilerCrashed; |
| 595 | }, | 616 | }, |
| 596 | } | 617 | } |
| ... | @@ -659,3 +680,23 @@ fn fillSearch(search_buf: *[2]Search, sdk: *ZigWindowsSDK) []Search { | ... | @@ -659,3 +680,23 @@ fn fillSearch(search_buf: *[2]Search, sdk: *ZigWindowsSDK) []Search { |
| 659 | } | 680 | } |
| 660 | return search_buf[0..search_end]; | 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 | } |