add native libc detection patch

this fixes an issue where setting CC to `zig cc` could cause a recursive call and cause failures during linkage.
This commit is contained in:
Jan200101 2021-07-19 22:38:11 +02:00
commit c4504e64ad
No known key found for this signature in database
GPG key ID: 5B71B1D78B882E05
2 changed files with 199 additions and 1 deletions

View file

@ -0,0 +1,192 @@
From 7c6f80f74395e546382c0400ef6db50c1b3e6439 Mon Sep 17 00:00:00 2001
From: Andrew Kelley <andrew@ziglang.org>
Date: Tue, 8 Jun 2021 12:48:48 -0700
Subject: [PATCH] native libc detection: respect spaces in CC env var
Zig has detection for when it is accidentally being called recursively
when trying to find the native libc installation. However it was not
working, resulting in a cryptic failure, because zig tried to execute
a command which had spaces in it rather than tokenizing it.
This improves the user experience of `zig cc` for systems that Zig
does not support cross-compiling for.
Closes #8960
Signed-off-by: Jan200101 <sentrycraft123@gmail.com>
---
src/libc_installation.zig | 99 +++++++++++++++++++++++++++------------
1 file changed, 70 insertions(+), 29 deletions(-)
diff --git a/src/libc_installation.zig b/src/libc_installation.zig
index 2286b2c85..783f76b9b 100644
--- a/src/libc_installation.zig
+++ b/src/libc_installation.zig
@@ -237,26 +237,38 @@ pub const LibCInstallation = struct {
fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void {
const allocator = args.allocator;
+
+ // Detect infinite loops.
+ var env_map = try std.process.getEnvMap(allocator);
+ defer env_map.deinit();
+ const skip_cc_env_var = if (env_map.get(inf_loop_env_key)) |phase| blk: {
+ if (std.mem.eql(u8, phase, "1")) {
+ try env_map.put(inf_loop_env_key, "2");
+ break :blk true;
+ } else {
+ return error.ZigIsTheCCompiler;
+ }
+ } else blk: {
+ try env_map.put(inf_loop_env_key, "1");
+ break :blk false;
+ };
+
const dev_null = if (is_windows) "nul" else "/dev/null";
- const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
- const argv = [_][]const u8{
- cc_exe,
+
+ var argv = std.ArrayList([]const u8).init(allocator);
+ defer argv.deinit();
+
+ try appendCcExe(&argv, skip_cc_env_var);
+ try argv.appendSlice(&.{
"-E",
"-Wp,-v",
"-xc",
dev_null,
- };
- var env_map = try std.process.getEnvMap(allocator);
- defer env_map.deinit();
-
- // Detect infinite loops.
- const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS";
- if (env_map.get(inf_loop_env_key) != null) return error.ZigIsTheCCompiler;
- try env_map.put(inf_loop_env_key, "1");
+ });
const exec_res = std.ChildProcess.exec(.{
.allocator = allocator,
- .argv = &argv,
+ .argv = argv.items,
.max_output_bytes = 1024 * 1024,
.env_map = &env_map,
// 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 {
}) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
else => {
- printVerboseInvocation(&argv, null, args.verbose, null);
+ printVerboseInvocation(argv.items, null, args.verbose, null);
return error.UnableToSpawnCCompiler;
},
};
@@ -277,11 +289,11 @@ pub const LibCInstallation = struct {
}
switch (exec_res.term) {
.Exited => |code| if (code != 0) {
- printVerboseInvocation(&argv, null, args.verbose, exec_res.stderr);
+ printVerboseInvocation(argv.items, null, args.verbose, exec_res.stderr);
return error.CCompilerExitCode;
},
else => {
- printVerboseInvocation(&argv, null, args.verbose, exec_res.stderr);
+ printVerboseInvocation(argv.items, null, args.verbose, exec_res.stderr);
return error.CCompilerCrashed;
},
}
@@ -540,8 +552,6 @@ pub const LibCInstallation = struct {
}
};
-const default_cc_exe = if (is_windows) "cc.exe" else "cc";
-
pub const CCPrintFileNameOptions = struct {
allocator: *Allocator,
search_basename: []const u8,
@@ -553,22 +563,33 @@ pub const CCPrintFileNameOptions = struct {
fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
const allocator = args.allocator;
- const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
- const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={s}", .{args.search_basename});
- defer allocator.free(arg1);
- const argv = [_][]const u8{ cc_exe, arg1 };
-
+ // Detect infinite loops.
var env_map = try std.process.getEnvMap(allocator);
defer env_map.deinit();
+ const skip_cc_env_var = if (env_map.get(inf_loop_env_key)) |phase| blk: {
+ if (std.mem.eql(u8, phase, "1")) {
+ try env_map.put(inf_loop_env_key, "2");
+ break :blk true;
+ } else {
+ return error.ZigIsTheCCompiler;
+ }
+ } else blk: {
+ try env_map.put(inf_loop_env_key, "1");
+ break :blk false;
+ };
- // Detect infinite loops.
- const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS";
- if (env_map.get(inf_loop_env_key) != null) return error.ZigIsTheCCompiler;
- try env_map.put(inf_loop_env_key, "1");
+ var argv = std.ArrayList([]const u8).init(allocator);
+ defer argv.deinit();
+
+ const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={s}", .{args.search_basename});
+ defer allocator.free(arg1);
+
+ try appendCcExe(&argv, skip_cc_env_var);
+ try argv.append(arg1);
const exec_res = std.ChildProcess.exec(.{
.allocator = allocator,
- .argv = &argv,
+ .argv = argv.items,
.max_output_bytes = 1024 * 1024,
.env_map = &env_map,
// 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 {
}
switch (exec_res.term) {
.Exited => |code| if (code != 0) {
- printVerboseInvocation(&argv, args.search_basename, args.verbose, exec_res.stderr);
+ printVerboseInvocation(argv.items, args.search_basename, args.verbose, exec_res.stderr);
return error.CCompilerExitCode;
},
else => {
- printVerboseInvocation(&argv, args.search_basename, args.verbose, exec_res.stderr);
+ printVerboseInvocation(argv.items, args.search_basename, args.verbose, exec_res.stderr);
return error.CCompilerCrashed;
},
}
@@ -659,3 +680,23 @@ fn fillSearch(search_buf: *[2]Search, sdk: *ZigWindowsSDK) []Search {
}
return search_buf[0..search_end];
}
+
+const inf_loop_env_key = "ZIG_IS_DETECTING_LIBC_PATHS";
+
+fn appendCcExe(args: *std.ArrayList([]const u8), skip_cc_env_var: bool) !void {
+ const default_cc_exe = if (is_windows) "cc.exe" else "cc";
+ try args.ensureUnusedCapacity(1);
+ if (skip_cc_env_var) {
+ args.appendAssumeCapacity(default_cc_exe);
+ return;
+ }
+ const cc_env_var = std.os.getenvZ("CC") orelse {
+ args.appendAssumeCapacity(default_cc_exe);
+ return;
+ };
+ // Respect space-separated flags to the C compiler.
+ var it = std.mem.tokenize(cc_env_var, " ");
+ while (it.next()) |arg| {
+ try args.append(arg);
+ }
+}
--
2.31.1

View file

@ -7,7 +7,7 @@
Name: zig
Version: 0.8.0
Release: 5%{?dist}
Release: 6%{?dist}
Summary: Programming language for maintaining robust, optimal, and reusable software
License: MIT and NCSA and LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ and GPLv2+ with exceptions and BSD and Inner-Net and ISC and Public Domain and GFDL and ZPLv2.1
@ -18,6 +18,9 @@ Source1: macros.%{name}
# https://github.com/ziglang/zig/pull/9020
Patch0: 0001-specify-the-output-lib-exe-and-include-paths-with-fl.patch
Patch1: 0002-zig-build-rename-lib-dir-include-dir-exe-dir.patch
# https://github.com/ziglang/zig/commit/d128ec39df4c0a701523d7d7161df3808a6939d2
# prevents zig from recursively calling itself
Patch2: 0003-native-libc-detection-respect-spaces-in-CC-env-var.patch
BuildRequires: gcc
BuildRequires: gcc-c++
@ -141,6 +144,9 @@ sed -i -e "s|@@ZIG_VERSION@@|%{version}|" %{buildroot}%{_rpmconfigdir}/macros.d
%{_rpmconfigdir}/macros.d/macros.%{name}
%changelog
* Mon Jul 19 2021 Jan Drögehoff <sentrycraft123@gmail.com> - 0.8.0-6
- add native libc detection patch
* Sun Jul 04 2021 Jan Drögehoff <sentrycraft123@gmail.com> - 0.8.0-5
- correct newline in macro that caused DESTDIR to be ignored