| author | |
| committer | |
| log | 94b9bcd034960f0467ca789217064b17f2ca7a49 |
| tree | fb9bc675814214ad303f41bce4c8b3ca75f2c3c8 |
| parent | d7f8368da86241f47e97257e737b6fb14bf5f773 |
Fixes #115955 files changed, 94 insertions(+), 1 deletions(-)
lib/std/build.zig+26-1| ... | ... | @@ -3009,6 +3009,7 @@ pub const LibExeObjStep = struct { |
| 3009 | 3009 | // Windows has an argument length limit of 32,766 characters, macOS 262,144 and Linux |
| 3010 | 3010 | // 2,097,152. If our args exceed 30 KiB, we instead write them to a "response file" and |
| 3011 | 3011 | // pass that to zig, e.g. via 'zig build-lib @args.rsp' |
| 3012 | // See @file syntax here: https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html | |
| 3012 | 3013 | var args_length: usize = 0; |
| 3013 | 3014 | for (zig_args.items) |arg| { |
| 3014 | 3015 | args_length += arg.len + 1; // +1 to account for null terminator |
| ... | ... | @@ -3020,9 +3021,33 @@ pub const LibExeObjStep = struct { |
| 3020 | 3021 | ); |
| 3021 | 3022 | try std.fs.cwd().makePath(args_dir); |
| 3022 | 3023 | |
| 3024 | var args_arena = std.heap.ArenaAllocator.init(builder.allocator); | |
| 3025 | defer args_arena.deinit(); | |
| 3026 | ||
| 3027 | const args_to_escape = zig_args.items[2..]; | |
| 3028 | var escaped_args = try ArrayList([]const u8).initCapacity(args_arena.allocator(), args_to_escape.len); | |
| 3029 | ||
| 3030 | arg_blk: for (args_to_escape) |arg| { | |
| 3031 | for (arg) |c, arg_idx| { | |
| 3032 | if (c == '\\' or c == '"') { | |
| 3033 | // Slow path for arguments that need to be escaped. We'll need to allocate and copy | |
| 3034 | var escaped = try ArrayList(u8).initCapacity(args_arena.allocator(), arg.len + 1); | |
| 3035 | const writer = escaped.writer(); | |
| 3036 | writer.writeAll(arg[0..arg_idx]) catch unreachable; | |
| 3037 | for (arg[arg_idx..]) |to_escape| { | |
| 3038 | if (to_escape == '\\' or to_escape == '"') try writer.writeByte('\\'); | |
| 3039 | try writer.writeByte(to_escape); | |
| 3040 | } | |
| 3041 | escaped_args.appendAssumeCapacity(escaped.items); | |
| 3042 | continue :arg_blk; | |
| 3043 | } | |
| 3044 | } | |
| 3045 | escaped_args.appendAssumeCapacity(arg); // no escaping needed so just use original argument | |
| 3046 | } | |
| 3047 | ||
| 3023 | 3048 | // Write the args to zig-cache/args/<SHA256 hash of args> to avoid conflicts with |
| 3024 | 3049 | // other zig build commands running in parallel. |
| 3025 | const partially_quoted = try std.mem.join(builder.allocator, "\" \"", zig_args.items[2..]); | |
| 3050 | const partially_quoted = try std.mem.join(builder.allocator, "\" \"", escaped_args.items); | |
| 3026 | 3051 | const args = try std.mem.concat(builder.allocator, u8, &[_][]const u8{ "\"", partially_quoted, "\"" }); |
| 3027 | 3052 | |
| 3028 | 3053 | var args_hash: [Sha256.digest_length]u8 = undefined; |
test/standalone.zig+1| ... | ... | @@ -49,6 +49,7 @@ pub fn addCases(cases: *tests.StandaloneContext) void { |
| 49 | 49 | cases.addBuildFile("test/standalone/issue_7030/build.zig", .{}); |
| 50 | 50 | cases.addBuildFile("test/standalone/install_raw_hex/build.zig", .{}); |
| 51 | 51 | cases.addBuildFile("test/standalone/issue_9812/build.zig", .{}); |
| 52 | cases.addBuildFile("test/standalone/issue_11595/build.zig", .{}); | |
| 52 | 53 | if (builtin.os.tag != .wasi) { |
| 53 | 54 | cases.addBuildFile("test/standalone/load_dynamic_library/build.zig", .{}); |
| 54 | 55 | } |
test/standalone/issue_11595/build.zig created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const Builder = std.build.Builder; | |
| 4 | const CrossTarget = std.zig.CrossTarget; | |
| 5 | ||
| 6 | // TODO integrate this with the std.build executor API | |
| 7 | fn isRunnableTarget(t: CrossTarget) bool { | |
| 8 | if (t.isNative()) return true; | |
| 9 | ||
| 10 | return (t.getOsTag() == builtin.os.tag and | |
| 11 | t.getCpuArch() == builtin.cpu.arch); | |
| 12 | } | |
| 13 | ||
| 14 | pub fn build(b: *Builder) void { | |
| 15 | const mode = b.standardReleaseOptions(); | |
| 16 | const target = b.standardTargetOptions(.{}); | |
| 17 | ||
| 18 | const exe = b.addExecutable("zigtest", "main.zig"); | |
| 19 | exe.setBuildMode(mode); | |
| 20 | exe.install(); | |
| 21 | ||
| 22 | const c_sources = [_][]const u8{ | |
| 23 | "test.c", | |
| 24 | }; | |
| 25 | ||
| 26 | exe.addCSourceFiles(&c_sources, &.{}); | |
| 27 | exe.linkLibC(); | |
| 28 | ||
| 29 | var i: i32 = 0; | |
| 30 | while (i < 1000) : (i += 1) { | |
| 31 | exe.defineCMacro("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"); | |
| 32 | } | |
| 33 | ||
| 34 | exe.defineCMacro("FOO", "42"); | |
| 35 | exe.defineCMacro("BAR", "\"BAR\""); | |
| 36 | exe.defineCMacro("BAZ", | |
| 37 | \\"\"BAZ\"" | |
| 38 | ); | |
| 39 | exe.defineCMacro("QUX", "\"Q\" \"UX\""); | |
| 40 | exe.defineCMacro("QUUX", "\"QU\\\"UX\""); | |
| 41 | ||
| 42 | exe.setTarget(target); | |
| 43 | b.default_step.dependOn(&exe.step); | |
| 44 | ||
| 45 | const test_step = b.step("test", "Test the program"); | |
| 46 | if (isRunnableTarget(target)) { | |
| 47 | const run_cmd = exe.run(); | |
| 48 | test_step.dependOn(&run_cmd.step); | |
| 49 | } else { | |
| 50 | test_step.dependOn(&exe.step); | |
| 51 | } | |
| 52 | } |
test/standalone/issue_11595/main.zig created+5| ... | ... | @@ -0,0 +1,5 @@ |
| 1 | extern fn check() c_int; | |
| 2 | ||
| 3 | pub fn main() u8 { | |
| 4 | return @intCast(u8, check()); | |
| 5 | } |
test/standalone/issue_11595/test.c created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | #include <string.h> | |
| 2 | ||
| 3 | int check(void) { | |
| 4 | if (FOO != 42) return 1; | |
| 5 | if (strcmp(BAR, "BAR")) return 2; | |
| 6 | if (strcmp(BAZ, "\"BAZ\"")) return 3; | |
| 7 | if (strcmp(QUX, "QUX")) return 4; | |
| 8 | if (strcmp(QUUX, "QU\"UX")) return 5; | |
| 9 | return 0; | |
| 10 | } |