authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-10-14 02:05:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-10-14 02:05:56-07:00
log0f4386875fd8c3e809307481320d02d7654bc13a
tree5d2f04a979b2301e1c8c767aa89d2bd5df4bcc2c
parent68b31c59a6fd64607d501ab1f397b846e41930e1

stage2: support ZIG_LIBC env var and detect self as system C compiler


1 files changed, 37 insertions(+), 1 deletions(-)

src/main.zig+37-1
...@@ -120,6 +120,39 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v...@@ -120,6 +120,39 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
120 fatal("expected command argument", .{});120 fatal("expected command argument", .{});
121 }121 }
122122
123 if (std.Target.current.os.tag != .windows and
124 std.os.getenvZ("ZIG_IS_DETECTING_LIBC_PATHS") != null)
125 {
126 // In this case we have accidentally invoked ourselves as "the system C compiler"
127 // to figure out where libc is installed. This is essentially infinite recursion
128 // via child process execution due to the CC environment variable pointing to Zig.
129 // Here we ignore the CC environment variable and exec `cc` as a child process.
130 // However it's possible Zig is installed as *that* C compiler as well, which is
131 // why we have this additional environment variable here to check.
132 var env_map = try std.process.getEnvMap(arena);
133
134 const inf_loop_env_key = "ZIG_IS_TRYING_TO_NOT_CALL_ITSELF";
135 if (env_map.get(inf_loop_env_key) != null) {
136 fatal("The compilation links against libc, but Zig is unable to provide a libc " ++
137 "for this operating system, and no --libc " ++
138 "parameter was provided, so Zig attempted to invoke the system C compiler " ++
139 "in order to determine where libc is installed. However the system C " ++
140 "compiler is `zig cc`, so no libc installation was found.", .{});
141 }
142 try env_map.set(inf_loop_env_key, "1");
143
144 // Some programs such as CMake will strip the `cc` and subsequent args from the
145 // CC environment variable. We detect and support this scenario here because of
146 // the ZIG_IS_DETECTING_LIBC_PATHS environment variable.
147 if (mem.eql(u8, args[1], "cc")) {
148 return std.os.execvpe(arena, args[1..], &env_map);
149 } else {
150 const modified_args = try arena.dupe([]const u8, args);
151 modified_args[0] = "cc";
152 return std.os.execvpe(arena, modified_args, &env_map);
153 }
154 }
155
123 const cmd = args[1];156 const cmd = args[1];
124 const cmd_args = args[2..];157 const cmd_args = args[2..];
125 if (mem.eql(u8, cmd, "build-exe")) {158 if (mem.eql(u8, cmd, "build-exe")) {
...@@ -444,7 +477,10 @@ fn buildOutputType(...@@ -444,7 +477,10 @@ fn buildOutputType(
444 var link_eh_frame_hdr = false;477 var link_eh_frame_hdr = false;
445 var link_emit_relocs = false;478 var link_emit_relocs = false;
446 var each_lib_rpath: ?bool = null;479 var each_lib_rpath: ?bool = null;
447 var libc_paths_file: ?[]const u8 = null;480 var libc_paths_file: ?[]const u8 = std.process.getEnvVarOwned(arena, "ZIG_LIBC") catch |err| switch (err) {
481 error.EnvironmentVariableNotFound => null,
482 else => |e| return e,
483 };
448 var machine_code_model: std.builtin.CodeModel = .default;484 var machine_code_model: std.builtin.CodeModel = .default;
449 var runtime_args_start: ?usize = null;485 var runtime_args_start: ?usize = null;
450 var test_filter: ?[]const u8 = null;486 var test_filter: ?[]const u8 = null;