| author | |
| committer | |
| log | 1554dd9697b77b4fe4a309247982c3e29048f124 |
| tree | f1ed649ac17a98dfb49067e04ea0c169cb34a725 |
| parent | 5c97aff627394439089267132a6c86f5e6162f92 |
| signature | Commit is signed but in an unrecognized format. |
* add a --system-linker-hack command line parameter to work around
poor LLD macho code. See #1535
* build.zig correctly handles static as well as dynamic dependencies
when building the self hosted compiler.
- no more unnecessary libxml2 dependency
- a static build on macos produces a completely static self-hosted
compiler for macos (except for libSystem as intended).6 files changed, 122 insertions(+), 41 deletions(-)
build.zig+84-38| ... | @@ -121,12 +121,23 @@ pub fn build(b: *Builder) !void { | ... | @@ -121,12 +121,23 @@ pub fn build(b: *Builder) !void { |
| 121 | test_step.dependOn(docs_step); | 121 | test_step.dependOn(docs_step); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | fn dependOnLib(lib_exe_obj: var, dep: LibraryDep) void { | 124 | fn dependOnLib(b: *Builder, lib_exe_obj: var, dep: LibraryDep) void { |
| 125 | for (dep.libdirs.toSliceConst()) |lib_dir| { | 125 | for (dep.libdirs.toSliceConst()) |lib_dir| { |
| 126 | lib_exe_obj.addLibPath(lib_dir); | 126 | lib_exe_obj.addLibPath(lib_dir); |
| 127 | } | 127 | } |
| 128 | const lib_dir = os.path.join(b.allocator, dep.prefix, "lib") catch unreachable; | ||
| 128 | for (dep.system_libs.toSliceConst()) |lib| { | 129 | for (dep.system_libs.toSliceConst()) |lib| { |
| 129 | lib_exe_obj.linkSystemLibrary(lib); | 130 | const static_bare_name = if (mem.eql(u8, lib, "curses")) |
| 131 | ([]const u8)("libncurses.a") | ||
| 132 | else | ||
| 133 | b.fmt("lib{}.a", lib); | ||
| 134 | const static_lib_name = os.path.join(b.allocator, lib_dir, static_bare_name) catch unreachable; | ||
| 135 | const have_static = fileExists(static_lib_name) catch unreachable; | ||
| 136 | if (have_static) { | ||
| 137 | lib_exe_obj.addObjectFile(static_lib_name); | ||
| 138 | } else { | ||
| 139 | lib_exe_obj.linkSystemLibrary(lib); | ||
| 140 | } | ||
| 130 | } | 141 | } |
| 131 | for (dep.libs.toSliceConst()) |lib| { | 142 | for (dep.libs.toSliceConst()) |lib| { |
| 132 | lib_exe_obj.addObjectFile(lib); | 143 | lib_exe_obj.addObjectFile(lib); |
| ... | @@ -136,12 +147,23 @@ fn dependOnLib(lib_exe_obj: var, dep: LibraryDep) void { | ... | @@ -136,12 +147,23 @@ fn dependOnLib(lib_exe_obj: var, dep: LibraryDep) void { |
| 136 | } | 147 | } |
| 137 | } | 148 | } |
| 138 | 149 | ||
| 150 | fn fileExists(filename: []const u8) !bool { | ||
| 151 | os.File.access(filename) catch |err| switch (err) { | ||
| 152 | error.PermissionDenied, | ||
| 153 | error.FileNotFound, | ||
| 154 | => return false, | ||
| 155 | else => return err, | ||
| 156 | }; | ||
| 157 | return true; | ||
| 158 | } | ||
| 159 | |||
| 139 | fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void { | 160 | fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void { |
| 140 | const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib"; | 161 | const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib"; |
| 141 | lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable); | 162 | lib_exe_obj.addObjectFile(os.path.join(b.allocator, cmake_binary_dir, "zig_cpp", b.fmt("{}{}{}", lib_prefix, lib_name, lib_exe_obj.target.libFileExt())) catch unreachable); |
| 142 | } | 163 | } |
| 143 | 164 | ||
| 144 | const LibraryDep = struct.{ | 165 | const LibraryDep = struct.{ |
| 166 | prefix: []const u8, | ||
| 145 | libdirs: ArrayList([]const u8), | 167 | libdirs: ArrayList([]const u8), |
| 146 | libs: ArrayList([]const u8), | 168 | libs: ArrayList([]const u8), |
| 147 | system_libs: ArrayList([]const u8), | 169 | system_libs: ArrayList([]const u8), |
| ... | @@ -149,21 +171,25 @@ const LibraryDep = struct.{ | ... | @@ -149,21 +171,25 @@ const LibraryDep = struct.{ |
| 149 | }; | 171 | }; |
| 150 | 172 | ||
| 151 | fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { | 173 | fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep { |
| 152 | const libs_output = try b.exec([][]const u8.{ | 174 | const shared_mode = try b.exec([][]const u8.{ llvm_config_exe, "--shared-mode" }); |
| 153 | llvm_config_exe, | 175 | const is_static = mem.startsWith(u8, shared_mode, "static"); |
| 154 | "--libs", | 176 | const libs_output = if (is_static) |
| 155 | "--system-libs", | 177 | try b.exec([][]const u8.{ |
| 156 | }); | 178 | llvm_config_exe, |
| 157 | const includes_output = try b.exec([][]const u8.{ | 179 | "--libfiles", |
| 158 | llvm_config_exe, | 180 | "--system-libs", |
| 159 | "--includedir", | 181 | }) |
| 160 | }); | 182 | else |
| 161 | const libdir_output = try b.exec([][]const u8.{ | 183 | try b.exec([][]const u8.{ |
| 162 | llvm_config_exe, | 184 | llvm_config_exe, |
| 163 | "--libdir", | 185 | "--libs", |
| 164 | }); | 186 | }); |
| 187 | const includes_output = try b.exec([][]const u8.{ llvm_config_exe, "--includedir" }); | ||
| 188 | const libdir_output = try b.exec([][]const u8.{ llvm_config_exe, "--libdir" }); | ||
| 189 | const prefix_output = try b.exec([][]const u8.{ llvm_config_exe, "--prefix" }); | ||
| 165 | 190 | ||
| 166 | var result = LibraryDep.{ | 191 | var result = LibraryDep.{ |
| 192 | .prefix = mem.split(prefix_output, " \r\n").next().?, | ||
| 167 | .libs = ArrayList([]const u8).init(b.allocator), | 193 | .libs = ArrayList([]const u8).init(b.allocator), |
| 168 | .system_libs = ArrayList([]const u8).init(b.allocator), | 194 | .system_libs = ArrayList([]const u8).init(b.allocator), |
| 169 | .includes = ArrayList([]const u8).init(b.allocator), | 195 | .includes = ArrayList([]const u8).init(b.allocator), |
| ... | @@ -244,10 +270,6 @@ fn nextValue(index: *usize, build_info: []const u8) []const u8 { | ... | @@ -244,10 +270,6 @@ fn nextValue(index: *usize, build_info: []const u8) []const u8 { |
| 244 | } | 270 | } |
| 245 | 271 | ||
| 246 | fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { | 272 | fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { |
| 247 | // This is for finding /lib/libz.a on alpine linux. | ||
| 248 | // TODO turn this into -Dextra-lib-path=/lib option | ||
| 249 | exe.addLibPath("/lib"); | ||
| 250 | |||
| 251 | exe.setNoRoSegment(ctx.no_rosegment); | 273 | exe.setNoRoSegment(ctx.no_rosegment); |
| 252 | 274 | ||
| 253 | exe.addIncludeDir("src"); | 275 | exe.addIncludeDir("src"); |
| ... | @@ -265,39 +287,63 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { | ... | @@ -265,39 +287,63 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { |
| 265 | addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_coff"); | 287 | addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_coff"); |
| 266 | addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_lib"); | 288 | addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_lib"); |
| 267 | } | 289 | } |
| 268 | dependOnLib(exe, ctx.llvm); | 290 | dependOnLib(b, exe, ctx.llvm); |
| 269 | 291 | ||
| 270 | if (exe.target.getOs() == builtin.Os.linux) { | 292 | if (exe.target.getOs() == builtin.Os.linux) { |
| 271 | const libstdcxx_path_padded = try b.exec([][]const u8.{ | 293 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", |
| 272 | ctx.cxx_compiler, | 294 | \\Unable to determine path to libstdc++.a |
| 273 | "-print-file-name=libstdc++.a", | 295 | \\On Fedora, install libstdc++-static and try again. |
| 274 | }); | 296 | \\ |
| 275 | const libstdcxx_path = mem.split(libstdcxx_path_padded, "\r\n").next().?; | 297 | ); |
| 276 | if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) { | ||
| 277 | warn( | ||
| 278 | \\Unable to determine path to libstdc++.a | ||
| 279 | \\On Fedora, install libstdc++-static and try again. | ||
| 280 | \\ | ||
| 281 | ); | ||
| 282 | return error.RequiredLibraryNotFound; | ||
| 283 | } | ||
| 284 | exe.addObjectFile(libstdcxx_path); | ||
| 285 | 298 | ||
| 286 | exe.linkSystemLibrary("pthread"); | 299 | exe.linkSystemLibrary("pthread"); |
| 287 | } else if (exe.target.isDarwin()) { | 300 | } else if (exe.target.isDarwin()) { |
| 288 | exe.linkSystemLibrary("c++"); | 301 | if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "")) { |
| 302 | // Compiler is GCC. | ||
| 303 | try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null); | ||
| 304 | exe.linkSystemLibrary("pthread"); | ||
| 305 | // TODO LLD cannot perform this link. | ||
| 306 | // See https://github.com/ziglang/zig/issues/1535 | ||
| 307 | exe.enableSystemLinkerHack(); | ||
| 308 | } else |err| switch (err) { | ||
| 309 | error.RequiredLibraryNotFound => { | ||
| 310 | // System compiler, not gcc. | ||
| 311 | exe.linkSystemLibrary("c++"); | ||
| 312 | }, | ||
| 313 | else => return err, | ||
| 314 | } | ||
| 289 | } | 315 | } |
| 290 | 316 | ||
| 291 | if (ctx.dia_guids_lib.len != 0) { | 317 | if (ctx.dia_guids_lib.len != 0) { |
| 292 | exe.addObjectFile(ctx.dia_guids_lib); | 318 | exe.addObjectFile(ctx.dia_guids_lib); |
| 293 | } | 319 | } |
| 294 | 320 | ||
| 295 | if (exe.target.getOs() != builtin.Os.windows) { | ||
| 296 | exe.linkSystemLibrary("xml2"); | ||
| 297 | } | ||
| 298 | exe.linkSystemLibrary("c"); | 321 | exe.linkSystemLibrary("c"); |
| 299 | } | 322 | } |
| 300 | 323 | ||
| 324 | fn addCxxKnownPath( | ||
| 325 | b: *Builder, | ||
| 326 | ctx: Context, | ||
| 327 | exe: var, | ||
| 328 | objname: []const u8, | ||
| 329 | errtxt: ?[]const u8, | ||
| 330 | ) !void { | ||
| 331 | const path_padded = try b.exec([][]const u8.{ | ||
| 332 | ctx.cxx_compiler, | ||
| 333 | b.fmt("-print-file-name={}", objname), | ||
| 334 | }); | ||
| 335 | const path_unpadded = mem.split(path_padded, "\r\n").next().?; | ||
| 336 | if (mem.eql(u8, path_unpadded, objname)) { | ||
| 337 | if (errtxt) |msg| { | ||
| 338 | warn("{}", msg); | ||
| 339 | } else { | ||
| 340 | warn("Unable to determine path to {}\n", objname); | ||
| 341 | } | ||
| 342 | return error.RequiredLibraryNotFound; | ||
| 343 | } | ||
| 344 | exe.addObjectFile(path_unpadded); | ||
| 345 | } | ||
| 346 | |||
| 301 | const Context = struct.{ | 347 | const Context = struct.{ |
| 302 | cmake_binary_dir: []const u8, | 348 | cmake_binary_dir: []const u8, |
| 303 | cxx_compiler: []const u8, | 349 | cxx_compiler: []const u8, |
src/all_types.hpp+1| ... | @@ -1731,6 +1731,7 @@ struct CodeGen { | ... | @@ -1731,6 +1731,7 @@ struct CodeGen { |
| 1731 | bool generate_error_name_table; | 1731 | bool generate_error_name_table; |
| 1732 | bool enable_cache; | 1732 | bool enable_cache; |
| 1733 | bool enable_time_report; | 1733 | bool enable_time_report; |
| 1734 | bool system_linker_hack; | ||
| 1734 | 1735 | ||
| 1735 | //////////////////////////// Participates in Input Parameter Cache Hash | 1736 | //////////////////////////// Participates in Input Parameter Cache Hash |
| 1736 | ZigList<LinkLib *> link_libs_list; | 1737 | ZigList<LinkLib *> link_libs_list; |
src/link.cpp+13-2| ... | @@ -778,7 +778,8 @@ static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) { | ... | @@ -778,7 +778,8 @@ static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) { |
| 778 | static void construct_linker_job_macho(LinkJob *lj) { | 778 | static void construct_linker_job_macho(LinkJob *lj) { |
| 779 | CodeGen *g = lj->codegen; | 779 | CodeGen *g = lj->codegen; |
| 780 | 780 | ||
| 781 | lj->args.append("-error-limit=0"); | 781 | // LLD MACH-O has no error limit option. |
| 782 | //lj->args.append("-error-limit=0"); | ||
| 782 | lj->args.append("-demangle"); | 783 | lj->args.append("-demangle"); |
| 783 | 784 | ||
| 784 | if (g->linker_rdynamic) { | 785 | if (g->linker_rdynamic) { |
| ... | @@ -1007,7 +1008,17 @@ void codegen_link(CodeGen *g) { | ... | @@ -1007,7 +1008,17 @@ void codegen_link(CodeGen *g) { |
| 1007 | Buf diag = BUF_INIT; | 1008 | Buf diag = BUF_INIT; |
| 1008 | 1009 | ||
| 1009 | codegen_add_time_event(g, "LLVM Link"); | 1010 | codegen_add_time_event(g, "LLVM Link"); |
| 1010 | if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) { | 1011 | if (g->system_linker_hack && g->zig_target.os == OsMacOSX) { |
| 1012 | Termination term; | ||
| 1013 | ZigList<const char *> args = {}; | ||
| 1014 | for (size_t i = 1; i < lj.args.length; i += 1) { | ||
| 1015 | args.append(lj.args.at(i)); | ||
| 1016 | } | ||
| 1017 | os_spawn_process("ld", args, &term); | ||
| 1018 | if (term.how != TerminationIdClean || term.code != 0) { | ||
| 1019 | exit(1); | ||
| 1020 | } | ||
| 1021 | } else if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) { | ||
| 1011 | fprintf(stderr, "%s\n", buf_ptr(&diag)); | 1022 | fprintf(stderr, "%s\n", buf_ptr(&diag)); |
| 1012 | exit(1); | 1023 | exit(1); |
| 1013 | } | 1024 | } |
src/main.cpp+4| ... | @@ -394,6 +394,7 @@ int main(int argc, char **argv) { | ... | @@ -394,6 +394,7 @@ int main(int argc, char **argv) { |
| 394 | ZigList<const char *> test_exec_args = {0}; | 394 | ZigList<const char *> test_exec_args = {0}; |
| 395 | int runtime_args_start = -1; | 395 | int runtime_args_start = -1; |
| 396 | bool no_rosegment_workaround = false; | 396 | bool no_rosegment_workaround = false; |
| 397 | bool system_linker_hack = false; | ||
| 397 | 398 | ||
| 398 | if (argc >= 2 && strcmp(argv[1], "build") == 0) { | 399 | if (argc >= 2 && strcmp(argv[1], "build") == 0) { |
| 399 | Buf zig_exe_path_buf = BUF_INIT; | 400 | Buf zig_exe_path_buf = BUF_INIT; |
| ... | @@ -560,6 +561,8 @@ int main(int argc, char **argv) { | ... | @@ -560,6 +561,8 @@ int main(int argc, char **argv) { |
| 560 | timing_info = true; | 561 | timing_info = true; |
| 561 | } else if (strcmp(arg, "--disable-pic") == 0) { | 562 | } else if (strcmp(arg, "--disable-pic") == 0) { |
| 562 | disable_pic = true; | 563 | disable_pic = true; |
| 564 | } else if (strcmp(arg, "--system-linker-hack") == 0) { | ||
| 565 | system_linker_hack = true; | ||
| 563 | } else if (strcmp(arg, "--test-cmd-bin") == 0) { | 566 | } else if (strcmp(arg, "--test-cmd-bin") == 0) { |
| 564 | test_exec_args.append(nullptr); | 567 | test_exec_args.append(nullptr); |
| 565 | } else if (arg[1] == 'L' && arg[2] != 0) { | 568 | } else if (arg[1] == 'L' && arg[2] != 0) { |
| ... | @@ -893,6 +896,7 @@ int main(int argc, char **argv) { | ... | @@ -893,6 +896,7 @@ int main(int argc, char **argv) { |
| 893 | g->verbose_llvm_ir = verbose_llvm_ir; | 896 | g->verbose_llvm_ir = verbose_llvm_ir; |
| 894 | g->verbose_cimport = verbose_cimport; | 897 | g->verbose_cimport = verbose_cimport; |
| 895 | codegen_set_errmsg_color(g, color); | 898 | codegen_set_errmsg_color(g, color); |
| 899 | g->system_linker_hack = system_linker_hack; | ||
| 896 | 900 | ||
| 897 | for (size_t i = 0; i < lib_dirs.length; i += 1) { | 901 | for (size_t i = 0; i < lib_dirs.length; i += 1) { |
| 898 | codegen_add_lib_dir(g, lib_dirs.at(i)); | 902 | codegen_add_lib_dir(g, lib_dirs.at(i)); |
src/os.cpp+1-1| ... | @@ -103,7 +103,7 @@ static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, | ... | @@ -103,7 +103,7 @@ static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, |
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | pid_t pid; | 105 | pid_t pid; |
| 106 | int rc = posix_spawn(&pid, exe, nullptr, nullptr, const_cast<char *const*>(argv), environ); | 106 | int rc = posix_spawnp(&pid, exe, nullptr, nullptr, const_cast<char *const*>(argv), environ); |
| 107 | if (rc != 0) { | 107 | if (rc != 0) { |
| 108 | zig_panic("posix_spawn failed: %s", strerror(rc)); | 108 | zig_panic("posix_spawn failed: %s", strerror(rc)); |
| 109 | } | 109 | } |
std/build.zig+19| ... | @@ -836,6 +836,7 @@ pub const LibExeObjStep = struct.{ | ... | @@ -836,6 +836,7 @@ pub const LibExeObjStep = struct.{ |
| 836 | assembly_files: ArrayList([]const u8), | 836 | assembly_files: ArrayList([]const u8), |
| 837 | packages: ArrayList(Pkg), | 837 | packages: ArrayList(Pkg), |
| 838 | build_options_contents: std.Buffer, | 838 | build_options_contents: std.Buffer, |
| 839 | system_linker_hack: bool, | ||
| 839 | 840 | ||
| 840 | // C only stuff | 841 | // C only stuff |
| 841 | source_files: ArrayList([]const u8), | 842 | source_files: ArrayList([]const u8), |
| ... | @@ -930,6 +931,7 @@ pub const LibExeObjStep = struct.{ | ... | @@ -930,6 +931,7 @@ pub const LibExeObjStep = struct.{ |
| 930 | .disable_libc = true, | 931 | .disable_libc = true, |
| 931 | .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable, | 932 | .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable, |
| 932 | .c_std = Builder.CStd.C99, | 933 | .c_std = Builder.CStd.C99, |
| 934 | .system_linker_hack = false, | ||
| 933 | }; | 935 | }; |
| 934 | self.computeOutFileNames(); | 936 | self.computeOutFileNames(); |
| 935 | return self; | 937 | return self; |
| ... | @@ -965,6 +967,7 @@ pub const LibExeObjStep = struct.{ | ... | @@ -965,6 +967,7 @@ pub const LibExeObjStep = struct.{ |
| 965 | .is_zig = false, | 967 | .is_zig = false, |
| 966 | .linker_script = null, | 968 | .linker_script = null, |
| 967 | .c_std = Builder.CStd.C99, | 969 | .c_std = Builder.CStd.C99, |
| 970 | .system_linker_hack = false, | ||
| 968 | 971 | ||
| 969 | .root_src = undefined, | 972 | .root_src = undefined, |
| 970 | .verbose_link = false, | 973 | .verbose_link = false, |
| ... | @@ -1162,6 +1165,10 @@ pub const LibExeObjStep = struct.{ | ... | @@ -1162,6 +1165,10 @@ pub const LibExeObjStep = struct.{ |
| 1162 | self.disable_libc = disable; | 1165 | self.disable_libc = disable; |
| 1163 | } | 1166 | } |
| 1164 | 1167 | ||
| 1168 | pub fn enableSystemLinkerHack(self: *LibExeObjStep) void { | ||
| 1169 | self.system_linker_hack = true; | ||
| 1170 | } | ||
| 1171 | |||
| 1165 | fn make(step: *Step) !void { | 1172 | fn make(step: *Step) !void { |
| 1166 | const self = @fieldParentPtr(LibExeObjStep, "step", step); | 1173 | const self = @fieldParentPtr(LibExeObjStep, "step", step); |
| 1167 | return if (self.is_zig) self.makeZig() else self.makeC(); | 1174 | return if (self.is_zig) self.makeZig() else self.makeC(); |
| ... | @@ -1338,6 +1345,9 @@ pub const LibExeObjStep = struct.{ | ... | @@ -1338,6 +1345,9 @@ pub const LibExeObjStep = struct.{ |
| 1338 | if (self.no_rosegment) { | 1345 | if (self.no_rosegment) { |
| 1339 | try zig_args.append("--no-rosegment"); | 1346 | try zig_args.append("--no-rosegment"); |
| 1340 | } | 1347 | } |
| 1348 | if (self.system_linker_hack) { | ||
| 1349 | try zig_args.append("--system-linker-hack"); | ||
| 1350 | } | ||
| 1341 | 1351 | ||
| 1342 | try builder.spawnChild(zig_args.toSliceConst()); | 1352 | try builder.spawnChild(zig_args.toSliceConst()); |
| 1343 | 1353 | ||
| ... | @@ -1646,6 +1656,7 @@ pub const TestStep = struct.{ | ... | @@ -1646,6 +1656,7 @@ pub const TestStep = struct.{ |
| 1646 | object_files: ArrayList([]const u8), | 1656 | object_files: ArrayList([]const u8), |
| 1647 | no_rosegment: bool, | 1657 | no_rosegment: bool, |
| 1648 | output_path: ?[]const u8, | 1658 | output_path: ?[]const u8, |
| 1659 | system_linker_hack: bool, | ||
| 1649 | 1660 | ||
| 1650 | pub fn init(builder: *Builder, root_src: []const u8) TestStep { | 1661 | pub fn init(builder: *Builder, root_src: []const u8) TestStep { |
| 1651 | const step_name = builder.fmt("test {}", root_src); | 1662 | const step_name = builder.fmt("test {}", root_src); |
| ... | @@ -1665,6 +1676,7 @@ pub const TestStep = struct.{ | ... | @@ -1665,6 +1676,7 @@ pub const TestStep = struct.{ |
| 1665 | .object_files = ArrayList([]const u8).init(builder.allocator), | 1676 | .object_files = ArrayList([]const u8).init(builder.allocator), |
| 1666 | .no_rosegment = false, | 1677 | .no_rosegment = false, |
| 1667 | .output_path = null, | 1678 | .output_path = null, |
| 1679 | .system_linker_hack = false, | ||
| 1668 | }; | 1680 | }; |
| 1669 | } | 1681 | } |
| 1670 | 1682 | ||
| ... | @@ -1747,6 +1759,10 @@ pub const TestStep = struct.{ | ... | @@ -1747,6 +1759,10 @@ pub const TestStep = struct.{ |
| 1747 | self.exec_cmd_args = args; | 1759 | self.exec_cmd_args = args; |
| 1748 | } | 1760 | } |
| 1749 | 1761 | ||
| 1762 | pub fn enableSystemLinkerHack(self: *TestStep) void { | ||
| 1763 | self.system_linker_hack = true; | ||
| 1764 | } | ||
| 1765 | |||
| 1750 | fn make(step: *Step) !void { | 1766 | fn make(step: *Step) !void { |
| 1751 | const self = @fieldParentPtr(TestStep, "step", step); | 1767 | const self = @fieldParentPtr(TestStep, "step", step); |
| 1752 | const builder = self.builder; | 1768 | const builder = self.builder; |
| ... | @@ -1851,6 +1867,9 @@ pub const TestStep = struct.{ | ... | @@ -1851,6 +1867,9 @@ pub const TestStep = struct.{ |
| 1851 | if (self.no_rosegment) { | 1867 | if (self.no_rosegment) { |
| 1852 | try zig_args.append("--no-rosegment"); | 1868 | try zig_args.append("--no-rosegment"); |
| 1853 | } | 1869 | } |
| 1870 | if (self.system_linker_hack) { | ||
| 1871 | try zig_args.append("--system-linker-hack"); | ||
| 1872 | } | ||
| 1854 | 1873 | ||
| 1855 | try builder.spawnChild(zig_args.toSliceConst()); | 1874 | try builder.spawnChild(zig_args.toSliceConst()); |
| 1856 | } | 1875 | } |