| ... | ... | @@ -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 | } |