| author | |
| committer | |
| log | 574e31f0a046aa6e6fad73fff2cbbb3617fe1bae |
| tree | b83f2dfec8821055929b82b18c87ea6b4e8da78a |
| parent | 8fba0a6ae862993afa2aeca774347adc399b3605 |
* introduce std.atomic.Int
* add src-self-hosted/test.zig which is tested by the main test suite
- it fully utilizes the multithreaded async/await event loop so the
tests should Go Fast
* `stage2/bin/zig build-obj test.zig` is able to spit out an error if 2 exported
functions collide
* ability for `zig test` to accept `--object` and `--assembly`
arguments
* std.build: TestStep supports addLibPath and addObjectFile11 files changed, 432 insertions(+), 107 deletions(-)
CMakeLists.txt+1| ... | @@ -431,6 +431,7 @@ set(ZIG_CPP_SOURCES | ... | @@ -431,6 +431,7 @@ set(ZIG_CPP_SOURCES |
| 431 | set(ZIG_STD_FILES | 431 | set(ZIG_STD_FILES |
| 432 | "array_list.zig" | 432 | "array_list.zig" |
| 433 | "atomic/index.zig" | 433 | "atomic/index.zig" |
| 434 | "atomic/int.zig" | ||
| 434 | "atomic/queue_mpmc.zig" | 435 | "atomic/queue_mpmc.zig" |
| 435 | "atomic/queue_mpsc.zig" | 436 | "atomic/queue_mpsc.zig" |
| 436 | "atomic/stack.zig" | 437 | "atomic/stack.zig" |
build.zig+89-63| ... | @@ -35,70 +35,27 @@ pub fn build(b: *Builder) !void { | ... | @@ -35,70 +35,27 @@ pub fn build(b: *Builder) !void { |
| 35 | "BUILD_INFO", | 35 | "BUILD_INFO", |
| 36 | }); | 36 | }); |
| 37 | var index: usize = 0; | 37 | var index: usize = 0; |
| 38 | const cmake_binary_dir = nextValue(&index, build_info); | 38 | var ctx = Context{ |
| 39 | const cxx_compiler = nextValue(&index, build_info); | 39 | .cmake_binary_dir = nextValue(&index, build_info), |
| 40 | const llvm_config_exe = nextValue(&index, build_info); | 40 | .cxx_compiler = nextValue(&index, build_info), |
| 41 | const lld_include_dir = nextValue(&index, build_info); | 41 | .llvm_config_exe = nextValue(&index, build_info), |
| 42 | const lld_libraries = nextValue(&index, build_info); | 42 | .lld_include_dir = nextValue(&index, build_info), |
| 43 | const std_files = nextValue(&index, build_info); | 43 | .lld_libraries = nextValue(&index, build_info), |
| 44 | const c_header_files = nextValue(&index, build_info); | 44 | .std_files = nextValue(&index, build_info), |
| 45 | const dia_guids_lib = nextValue(&index, build_info); | 45 | .c_header_files = nextValue(&index, build_info), |
| 46 | .dia_guids_lib = nextValue(&index, build_info), | ||
| 47 | .llvm = undefined, | ||
| 48 | }; | ||
| 49 | ctx.llvm = try findLLVM(b, ctx.llvm_config_exe); | ||
| 46 | 50 | ||
| 47 | const llvm = findLLVM(b, llvm_config_exe) catch unreachable; | 51 | var test_stage2 = b.addTest("src-self-hosted/test.zig"); |
| 52 | test_stage2.setBuildMode(builtin.Mode.Debug); | ||
| 48 | 53 | ||
| 49 | var exe = b.addExecutable("zig", "src-self-hosted/main.zig"); | 54 | var exe = b.addExecutable("zig", "src-self-hosted/main.zig"); |
| 50 | exe.setBuildMode(mode); | 55 | exe.setBuildMode(mode); |
| 51 | 56 | ||
| 52 | // This is for finding /lib/libz.a on alpine linux. | 57 | try configureStage2(b, test_stage2, ctx); |
| 53 | // TODO turn this into -Dextra-lib-path=/lib option | 58 | try configureStage2(b, exe, ctx); |
| 54 | exe.addLibPath("/lib"); | ||
| 55 | |||
| 56 | exe.addIncludeDir("src"); | ||
| 57 | exe.addIncludeDir(cmake_binary_dir); | ||
| 58 | addCppLib(b, exe, cmake_binary_dir, "zig_cpp"); | ||
| 59 | if (lld_include_dir.len != 0) { | ||
| 60 | exe.addIncludeDir(lld_include_dir); | ||
| 61 | var it = mem.split(lld_libraries, ";"); | ||
| 62 | while (it.next()) |lib| { | ||
| 63 | exe.addObjectFile(lib); | ||
| 64 | } | ||
| 65 | } else { | ||
| 66 | addCppLib(b, exe, cmake_binary_dir, "embedded_lld_wasm"); | ||
| 67 | addCppLib(b, exe, cmake_binary_dir, "embedded_lld_elf"); | ||
| 68 | addCppLib(b, exe, cmake_binary_dir, "embedded_lld_coff"); | ||
| 69 | addCppLib(b, exe, cmake_binary_dir, "embedded_lld_lib"); | ||
| 70 | } | ||
| 71 | dependOnLib(exe, llvm); | ||
| 72 | |||
| 73 | if (exe.target.getOs() == builtin.Os.linux) { | ||
| 74 | const libstdcxx_path_padded = try b.exec([][]const u8{ | ||
| 75 | cxx_compiler, | ||
| 76 | "-print-file-name=libstdc++.a", | ||
| 77 | }); | ||
| 78 | const libstdcxx_path = mem.split(libstdcxx_path_padded, "\r\n").next().?; | ||
| 79 | if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) { | ||
| 80 | warn( | ||
| 81 | \\Unable to determine path to libstdc++.a | ||
| 82 | \\On Fedora, install libstdc++-static and try again. | ||
| 83 | \\ | ||
| 84 | ); | ||
| 85 | return error.RequiredLibraryNotFound; | ||
| 86 | } | ||
| 87 | exe.addObjectFile(libstdcxx_path); | ||
| 88 | |||
| 89 | exe.linkSystemLibrary("pthread"); | ||
| 90 | } else if (exe.target.isDarwin()) { | ||
| 91 | exe.linkSystemLibrary("c++"); | ||
| 92 | } | ||
| 93 | |||
| 94 | if (dia_guids_lib.len != 0) { | ||
| 95 | exe.addObjectFile(dia_guids_lib); | ||
| 96 | } | ||
| 97 | |||
| 98 | if (exe.target.getOs() != builtin.Os.windows) { | ||
| 99 | exe.linkSystemLibrary("xml2"); | ||
| 100 | } | ||
| 101 | exe.linkSystemLibrary("c"); | ||
| 102 | 59 | ||
| 103 | b.default_step.dependOn(&exe.step); | 60 | b.default_step.dependOn(&exe.step); |
| 104 | 61 | ||
| ... | @@ -110,12 +67,16 @@ pub fn build(b: *Builder) !void { | ... | @@ -110,12 +67,16 @@ pub fn build(b: *Builder) !void { |
| 110 | exe.setVerboseLink(verbose_link_exe); | 67 | exe.setVerboseLink(verbose_link_exe); |
| 111 | 68 | ||
| 112 | b.installArtifact(exe); | 69 | b.installArtifact(exe); |
| 113 | installStdLib(b, std_files); | 70 | installStdLib(b, ctx.std_files); |
| 114 | installCHeaders(b, c_header_files); | 71 | installCHeaders(b, ctx.c_header_files); |
| 115 | 72 | ||
| 116 | const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter"); | 73 | const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter"); |
| 117 | const with_lldb = b.option(bool, "with-lldb", "Run tests in LLDB to get a backtrace if one fails") orelse false; | 74 | const with_lldb = b.option(bool, "with-lldb", "Run tests in LLDB to get a backtrace if one fails") orelse false; |
| 118 | 75 | ||
| 76 | const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests"); | ||
| 77 | test_stage2_step.dependOn(&test_stage2.step); | ||
| 78 | test_step.dependOn(test_stage2_step); | ||
| 79 | |||
| 119 | test_step.dependOn(docs_step); | 80 | test_step.dependOn(docs_step); |
| 120 | 81 | ||
| 121 | test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", with_lldb)); | 82 | test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", with_lldb)); |
| ... | @@ -133,7 +94,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -133,7 +94,7 @@ pub fn build(b: *Builder) !void { |
| 133 | test_step.dependOn(tests.addGenHTests(b, test_filter)); | 94 | test_step.dependOn(tests.addGenHTests(b, test_filter)); |
| 134 | } | 95 | } |
| 135 | 96 | ||
| 136 | fn dependOnLib(lib_exe_obj: *std.build.LibExeObjStep, dep: *const LibraryDep) void { | 97 | fn dependOnLib(lib_exe_obj: var, dep: *const LibraryDep) void { |
| 137 | for (dep.libdirs.toSliceConst()) |lib_dir| { | 98 | for (dep.libdirs.toSliceConst()) |lib_dir| { |
| 138 | lib_exe_obj.addLibPath(lib_dir); | 99 | lib_exe_obj.addLibPath(lib_dir); |
| 139 | } | 100 | } |
| ... | @@ -148,7 +109,7 @@ fn dependOnLib(lib_exe_obj: *std.build.LibExeObjStep, dep: *const LibraryDep) vo | ... | @@ -148,7 +109,7 @@ fn dependOnLib(lib_exe_obj: *std.build.LibExeObjStep, dep: *const LibraryDep) vo |
| 148 | } | 109 | } |
| 149 | } | 110 | } |
| 150 | 111 | ||
| 151 | fn addCppLib(b: *Builder, lib_exe_obj: *std.build.LibExeObjStep, cmake_binary_dir: []const u8, lib_name: []const u8) void { | 112 | fn addCppLib(b: *Builder, lib_exe_obj: var, cmake_binary_dir: []const u8, lib_name: []const u8) void { |
| 152 | const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib"; | 113 | const lib_prefix = if (lib_exe_obj.target.isWindows()) "" else "lib"; |
| 153 | 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); | 114 | 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); |
| 154 | } | 115 | } |
| ... | @@ -254,3 +215,68 @@ fn nextValue(index: *usize, build_info: []const u8) []const u8 { | ... | @@ -254,3 +215,68 @@ fn nextValue(index: *usize, build_info: []const u8) []const u8 { |
| 254 | } | 215 | } |
| 255 | } | 216 | } |
| 256 | } | 217 | } |
| 218 | |||
| 219 | fn configureStage2(b: *Builder, exe: var, ctx: Context) !void { | ||
| 220 | // This is for finding /lib/libz.a on alpine linux. | ||
| 221 | // TODO turn this into -Dextra-lib-path=/lib option | ||
| 222 | exe.addLibPath("/lib"); | ||
| 223 | |||
| 224 | exe.addIncludeDir("src"); | ||
| 225 | exe.addIncludeDir(ctx.cmake_binary_dir); | ||
| 226 | addCppLib(b, exe, ctx.cmake_binary_dir, "zig_cpp"); | ||
| 227 | if (ctx.lld_include_dir.len != 0) { | ||
| 228 | exe.addIncludeDir(ctx.lld_include_dir); | ||
| 229 | var it = mem.split(ctx.lld_libraries, ";"); | ||
| 230 | while (it.next()) |lib| { | ||
| 231 | exe.addObjectFile(lib); | ||
| 232 | } | ||
| 233 | } else { | ||
| 234 | addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_wasm"); | ||
| 235 | addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_elf"); | ||
| 236 | addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_coff"); | ||
| 237 | addCppLib(b, exe, ctx.cmake_binary_dir, "embedded_lld_lib"); | ||
| 238 | } | ||
| 239 | dependOnLib(exe, ctx.llvm); | ||
| 240 | |||
| 241 | if (exe.target.getOs() == builtin.Os.linux) { | ||
| 242 | const libstdcxx_path_padded = try b.exec([][]const u8{ | ||
| 243 | ctx.cxx_compiler, | ||
| 244 | "-print-file-name=libstdc++.a", | ||
| 245 | }); | ||
| 246 | const libstdcxx_path = mem.split(libstdcxx_path_padded, "\r\n").next().?; | ||
| 247 | if (mem.eql(u8, libstdcxx_path, "libstdc++.a")) { | ||
| 248 | warn( | ||
| 249 | \\Unable to determine path to libstdc++.a | ||
| 250 | \\On Fedora, install libstdc++-static and try again. | ||
| 251 | \\ | ||
| 252 | ); | ||
| 253 | return error.RequiredLibraryNotFound; | ||
| 254 | } | ||
| 255 | exe.addObjectFile(libstdcxx_path); | ||
| 256 | |||
| 257 | exe.linkSystemLibrary("pthread"); | ||
| 258 | } else if (exe.target.isDarwin()) { | ||
| 259 | exe.linkSystemLibrary("c++"); | ||
| 260 | } | ||
| 261 | |||
| 262 | if (ctx.dia_guids_lib.len != 0) { | ||
| 263 | exe.addObjectFile(ctx.dia_guids_lib); | ||
| 264 | } | ||
| 265 | |||
| 266 | if (exe.target.getOs() != builtin.Os.windows) { | ||
| 267 | exe.linkSystemLibrary("xml2"); | ||
| 268 | } | ||
| 269 | exe.linkSystemLibrary("c"); | ||
| 270 | } | ||
| 271 | |||
| 272 | const Context = struct { | ||
| 273 | cmake_binary_dir: []const u8, | ||
| 274 | cxx_compiler: []const u8, | ||
| 275 | llvm_config_exe: []const u8, | ||
| 276 | lld_include_dir: []const u8, | ||
| 277 | lld_libraries: []const u8, | ||
| 278 | std_files: []const u8, | ||
| 279 | c_header_files: []const u8, | ||
| 280 | dia_guids_lib: []const u8, | ||
| 281 | llvm: LibraryDep, | ||
| 282 | }; |
src-self-hosted/errmsg.zig+12-6| ... | @@ -11,11 +11,15 @@ pub const Color = enum { | ... | @@ -11,11 +11,15 @@ pub const Color = enum { |
| 11 | On, | 11 | On, |
| 12 | }; | 12 | }; |
| 13 | 13 | ||
| 14 | pub const Span = struct { | ||
| 15 | first: ast.TokenIndex, | ||
| 16 | last: ast.TokenIndex, | ||
| 17 | }; | ||
| 18 | |||
| 14 | pub const Msg = struct { | 19 | pub const Msg = struct { |
| 15 | path: []const u8, | 20 | path: []const u8, |
| 16 | text: []u8, | 21 | text: []u8, |
| 17 | first_token: TokenIndex, | 22 | span: Span, |
| 18 | last_token: TokenIndex, | ||
| 19 | tree: *ast.Tree, | 23 | tree: *ast.Tree, |
| 20 | }; | 24 | }; |
| 21 | 25 | ||
| ... | @@ -39,8 +43,10 @@ pub fn createFromParseError( | ... | @@ -39,8 +43,10 @@ pub fn createFromParseError( |
| 39 | .tree = tree, | 43 | .tree = tree, |
| 40 | .path = path, | 44 | .path = path, |
| 41 | .text = text_buf.toOwnedSlice(), | 45 | .text = text_buf.toOwnedSlice(), |
| 42 | .first_token = loc_token, | 46 | .span = Span{ |
| 43 | .last_token = loc_token, | 47 | .first = loc_token, |
| 48 | .last = loc_token, | ||
| 49 | }, | ||
| 44 | }); | 50 | }); |
| 45 | errdefer allocator.destroy(msg); | 51 | errdefer allocator.destroy(msg); |
| 46 | 52 | ||
| ... | @@ -48,8 +54,8 @@ pub fn createFromParseError( | ... | @@ -48,8 +54,8 @@ pub fn createFromParseError( |
| 48 | } | 54 | } |
| 49 | 55 | ||
| 50 | pub fn printToStream(stream: var, msg: *const Msg, color_on: bool) !void { | 56 | pub fn printToStream(stream: var, msg: *const Msg, color_on: bool) !void { |
| 51 | const first_token = msg.tree.tokens.at(msg.first_token); | 57 | const first_token = msg.tree.tokens.at(msg.span.first); |
| 52 | const last_token = msg.tree.tokens.at(msg.last_token); | 58 | const last_token = msg.tree.tokens.at(msg.span.last); |
| 53 | const start_loc = msg.tree.tokenLocationPtr(0, first_token); | 59 | const start_loc = msg.tree.tokenLocationPtr(0, first_token); |
| 54 | const end_loc = msg.tree.tokenLocationPtr(first_token.end, last_token); | 60 | const end_loc = msg.tree.tokenLocationPtr(first_token.end, last_token); |
| 55 | if (!color_on) { | 61 | if (!color_on) { |
src-self-hosted/introspect.zig+5| ... | @@ -53,3 +53,8 @@ pub fn resolveZigLibDir(allocator: *mem.Allocator) ![]u8 { | ... | @@ -53,3 +53,8 @@ pub fn resolveZigLibDir(allocator: *mem.Allocator) ![]u8 { |
| 53 | return error.ZigLibDirNotFound; | 53 | return error.ZigLibDirNotFound; |
| 54 | }; | 54 | }; |
| 55 | } | 55 | } |
| 56 | |||
| 57 | /// Caller must free result | ||
| 58 | pub fn resolveZigCacheDir(allocator: *mem.Allocator) ![]u8 { | ||
| 59 | return std.mem.dupe(allocator, u8, "zig-cache"); | ||
| 60 | } |
src-self-hosted/main.zig+18-18| ... | @@ -481,29 +481,29 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo | ... | @@ -481,29 +481,29 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Mo |
| 481 | module.link_out_file = flags.single("out-file"); | 481 | module.link_out_file = flags.single("out-file"); |
| 482 | 482 | ||
| 483 | try module.build(); | 483 | try module.build(); |
| 484 | const process_build_events_handle = try async<loop.allocator> processBuildEvents(module, true); | 484 | const process_build_events_handle = try async<loop.allocator> processBuildEvents(module, color); |
| 485 | defer cancel process_build_events_handle; | 485 | defer cancel process_build_events_handle; |
| 486 | loop.run(); | 486 | loop.run(); |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | async fn processBuildEvents(module: *Module, watch: bool) void { | 489 | async fn processBuildEvents(module: *Module, color: errmsg.Color) void { |
| 490 | while (watch) { | 490 | // TODO directly awaiting async should guarantee memory allocation elision |
| 491 | // TODO directly awaiting async should guarantee memory allocation elision | 491 | const build_event = await (async module.events.get() catch unreachable); |
| 492 | const build_event = await (async module.events.get() catch unreachable); | ||
| 493 | 492 | ||
| 494 | switch (build_event) { | 493 | switch (build_event) { |
| 495 | Module.Event.Ok => { | 494 | Module.Event.Ok => { |
| 496 | std.debug.warn("Build succeeded\n"); | 495 | std.debug.warn("Build succeeded\n"); |
| 497 | return; | 496 | return; |
| 498 | }, | 497 | }, |
| 499 | Module.Event.Error => |err| { | 498 | Module.Event.Error => |err| { |
| 500 | std.debug.warn("build failed: {}\n", @errorName(err)); | 499 | std.debug.warn("build failed: {}\n", @errorName(err)); |
| 501 | @panic("TODO error return trace"); | 500 | @panic("TODO error return trace"); |
| 502 | }, | 501 | }, |
| 503 | Module.Event.Fail => |errs| { | 502 | Module.Event.Fail => |msgs| { |
| 504 | @panic("TODO print compile error messages"); | 503 | for (msgs) |msg| { |
| 505 | }, | 504 | errmsg.printToFile(&stderr_file, msg, color) catch os.exit(1); |
| 506 | } | 505 | } |
| 506 | }, | ||
| 507 | } | 507 | } |
| 508 | } | 508 | } |
| 509 | 509 |
src-self-hosted/module.zig+81-17| ... | @@ -89,12 +89,9 @@ pub const Module = struct { | ... | @@ -89,12 +89,9 @@ pub const Module = struct { |
| 89 | /// the build is complete. | 89 | /// the build is complete. |
| 90 | build_group: event.Group(BuildError!void), | 90 | build_group: event.Group(BuildError!void), |
| 91 | 91 | ||
| 92 | const BuildErrorsList = std.SegmentedList(BuildErrorDesc, 1); | 92 | compile_errors: event.Locked(CompileErrList), |
| 93 | 93 | ||
| 94 | pub const BuildErrorDesc = struct { | 94 | const CompileErrList = std.ArrayList(*errmsg.Msg); |
| 95 | code: BuildError, | ||
| 96 | text: []const u8, | ||
| 97 | }; | ||
| 98 | 95 | ||
| 99 | // TODO handle some of these earlier and report them in a way other than error codes | 96 | // TODO handle some of these earlier and report them in a way other than error codes |
| 100 | pub const BuildError = error{ | 97 | pub const BuildError = error{ |
| ... | @@ -131,11 +128,12 @@ pub const Module = struct { | ... | @@ -131,11 +128,12 @@ pub const Module = struct { |
| 131 | NoStdHandles, | 128 | NoStdHandles, |
| 132 | Overflow, | 129 | Overflow, |
| 133 | NotSupported, | 130 | NotSupported, |
| 131 | BufferTooSmall, | ||
| 134 | }; | 132 | }; |
| 135 | 133 | ||
| 136 | pub const Event = union(enum) { | 134 | pub const Event = union(enum) { |
| 137 | Ok, | 135 | Ok, |
| 138 | Fail: []errmsg.Msg, | 136 | Fail: []*errmsg.Msg, |
| 139 | Error: BuildError, | 137 | Error: BuildError, |
| 140 | }; | 138 | }; |
| 141 | 139 | ||
| ... | @@ -249,6 +247,7 @@ pub const Module = struct { | ... | @@ -249,6 +247,7 @@ pub const Module = struct { |
| 249 | .link_out_file = null, | 247 | .link_out_file = null, |
| 250 | .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)), | 248 | .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)), |
| 251 | .build_group = event.Group(BuildError!void).init(loop), | 249 | .build_group = event.Group(BuildError!void).init(loop), |
| 250 | .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)), | ||
| 252 | }); | 251 | }); |
| 253 | } | 252 | } |
| 254 | 253 | ||
| ... | @@ -288,7 +287,17 @@ pub const Module = struct { | ... | @@ -288,7 +287,17 @@ pub const Module = struct { |
| 288 | await (async self.events.put(Event{ .Error = err }) catch unreachable); | 287 | await (async self.events.put(Event{ .Error = err }) catch unreachable); |
| 289 | return; | 288 | return; |
| 290 | }; | 289 | }; |
| 291 | await (async self.events.put(Event.Ok) catch unreachable); | 290 | const compile_errors = blk: { |
| 291 | const held = await (async self.compile_errors.acquire() catch unreachable); | ||
| 292 | defer held.release(); | ||
| 293 | break :blk held.value.toOwnedSlice(); | ||
| 294 | }; | ||
| 295 | |||
| 296 | if (compile_errors.len == 0) { | ||
| 297 | await (async self.events.put(Event.Ok) catch unreachable); | ||
| 298 | } else { | ||
| 299 | await (async self.events.put(Event{ .Fail = compile_errors }) catch unreachable); | ||
| 300 | } | ||
| 292 | // for now we stop after 1 | 301 | // for now we stop after 1 |
| 293 | return; | 302 | return; |
| 294 | } | 303 | } |
| ... | @@ -310,10 +319,13 @@ pub const Module = struct { | ... | @@ -310,10 +319,13 @@ pub const Module = struct { |
| 310 | }; | 319 | }; |
| 311 | errdefer self.a().free(source_code); | 320 | errdefer self.a().free(source_code); |
| 312 | 321 | ||
| 313 | var parsed_file = ParsedFile{ | 322 | const parsed_file = try self.a().create(ParsedFile{ |
| 314 | .tree = try std.zig.parse(self.a(), source_code), | 323 | .tree = undefined, |
| 315 | .realpath = root_src_real_path, | 324 | .realpath = root_src_real_path, |
| 316 | }; | 325 | }); |
| 326 | errdefer self.a().destroy(parsed_file); | ||
| 327 | |||
| 328 | parsed_file.tree = try std.zig.parse(self.a(), source_code); | ||
| 317 | errdefer parsed_file.tree.deinit(); | 329 | errdefer parsed_file.tree.deinit(); |
| 318 | 330 | ||
| 319 | const tree = &parsed_file.tree; | 331 | const tree = &parsed_file.tree; |
| ... | @@ -337,7 +349,7 @@ pub const Module = struct { | ... | @@ -337,7 +349,7 @@ pub const Module = struct { |
| 337 | const name = if (fn_proto.name_token) |name_token| tree.tokenSlice(name_token) else { | 349 | const name = if (fn_proto.name_token) |name_token| tree.tokenSlice(name_token) else { |
| 338 | @panic("TODO add compile error"); | 350 | @panic("TODO add compile error"); |
| 339 | //try self.addCompileError( | 351 | //try self.addCompileError( |
| 340 | // &parsed_file, | 352 | // parsed_file, |
| 341 | // fn_proto.fn_token, | 353 | // fn_proto.fn_token, |
| 342 | // fn_proto.fn_token + 1, | 354 | // fn_proto.fn_token + 1, |
| 343 | // "missing function name", | 355 | // "missing function name", |
| ... | @@ -357,7 +369,7 @@ pub const Module = struct { | ... | @@ -357,7 +369,7 @@ pub const Module = struct { |
| 357 | }); | 369 | }); |
| 358 | errdefer self.a().destroy(fn_decl); | 370 | errdefer self.a().destroy(fn_decl); |
| 359 | 371 | ||
| 360 | try decl_group.call(addTopLevelDecl, self, tree, &fn_decl.base); | 372 | try decl_group.call(addTopLevelDecl, self, parsed_file, &fn_decl.base); |
| 361 | }, | 373 | }, |
| 362 | ast.Node.Id.TestDecl => @panic("TODO"), | 374 | ast.Node.Id.TestDecl => @panic("TODO"), |
| 363 | else => unreachable, | 375 | else => unreachable, |
| ... | @@ -367,20 +379,56 @@ pub const Module = struct { | ... | @@ -367,20 +379,56 @@ pub const Module = struct { |
| 367 | try await (async self.build_group.wait() catch unreachable); | 379 | try await (async self.build_group.wait() catch unreachable); |
| 368 | } | 380 | } |
| 369 | 381 | ||
| 370 | async fn addTopLevelDecl(self: *Module, tree: *ast.Tree, decl: *Decl) !void { | 382 | async fn addTopLevelDecl(self: *Module, parsed_file: *ParsedFile, decl: *Decl) !void { |
| 371 | const is_export = decl.isExported(tree); | 383 | const is_export = decl.isExported(&parsed_file.tree); |
| 372 | 384 | ||
| 373 | if (is_export) { | 385 | if (is_export) { |
| 374 | try self.build_group.call(verifyUniqueSymbol, self, decl); | 386 | try self.build_group.call(verifyUniqueSymbol, self, parsed_file, decl); |
| 375 | } | 387 | } |
| 376 | } | 388 | } |
| 377 | 389 | ||
| 378 | async fn verifyUniqueSymbol(self: *Module, decl: *Decl) !void { | 390 | fn addCompileError(self: *Module, parsed_file: *ParsedFile, span: errmsg.Span, comptime fmt: []const u8, args: ...) !void { |
| 391 | const text = try std.fmt.allocPrint(self.loop.allocator, fmt, args); | ||
| 392 | errdefer self.loop.allocator.free(text); | ||
| 393 | |||
| 394 | try self.build_group.call(addCompileErrorAsync, self, parsed_file, span.first, span.last, text); | ||
| 395 | } | ||
| 396 | |||
| 397 | async fn addCompileErrorAsync( | ||
| 398 | self: *Module, | ||
| 399 | parsed_file: *ParsedFile, | ||
| 400 | first_token: ast.TokenIndex, | ||
| 401 | last_token: ast.TokenIndex, | ||
| 402 | text: []u8, | ||
| 403 | ) !void { | ||
| 404 | const msg = try self.loop.allocator.create(errmsg.Msg{ | ||
| 405 | .path = parsed_file.realpath, | ||
| 406 | .text = text, | ||
| 407 | .span = errmsg.Span{ | ||
| 408 | .first = first_token, | ||
| 409 | .last = last_token, | ||
| 410 | }, | ||
| 411 | .tree = &parsed_file.tree, | ||
| 412 | }); | ||
| 413 | errdefer self.loop.allocator.destroy(msg); | ||
| 414 | |||
| 415 | const compile_errors = await (async self.compile_errors.acquire() catch unreachable); | ||
| 416 | defer compile_errors.release(); | ||
| 417 | |||
| 418 | try compile_errors.value.append(msg); | ||
| 419 | } | ||
| 420 | |||
| 421 | async fn verifyUniqueSymbol(self: *Module, parsed_file: *ParsedFile, decl: *Decl) !void { | ||
| 379 | const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable); | 422 | const exported_symbol_names = await (async self.exported_symbol_names.acquire() catch unreachable); |
| 380 | defer exported_symbol_names.release(); | 423 | defer exported_symbol_names.release(); |
| 381 | 424 | ||
| 382 | if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| { | 425 | if (try exported_symbol_names.value.put(decl.name, decl)) |other_decl| { |
| 383 | @panic("TODO report compile error"); | 426 | try self.addCompileError( |
| 427 | parsed_file, | ||
| 428 | decl.getSpan(), | ||
| 429 | "exported symbol collision: '{}'", | ||
| 430 | decl.name, | ||
| 431 | ); | ||
| 384 | } | 432 | } |
| 385 | } | 433 | } |
| 386 | 434 | ||
| ... | @@ -503,6 +551,22 @@ pub const Decl = struct { | ... | @@ -503,6 +551,22 @@ pub const Decl = struct { |
| 503 | } | 551 | } |
| 504 | } | 552 | } |
| 505 | 553 | ||
| 554 | pub fn getSpan(base: *const Decl) errmsg.Span { | ||
| 555 | switch (base.id) { | ||
| 556 | Id.Fn => { | ||
| 557 | const fn_decl = @fieldParentPtr(Fn, "base", base); | ||
| 558 | const fn_proto = fn_decl.fn_proto; | ||
| 559 | const start = fn_proto.fn_token; | ||
| 560 | const end = fn_proto.name_token orelse start; | ||
| 561 | return errmsg.Span{ | ||
| 562 | .first = start, | ||
| 563 | .last = end + 1, | ||
| 564 | }; | ||
| 565 | }, | ||
| 566 | else => @panic("TODO"), | ||
| 567 | } | ||
| 568 | } | ||
| 569 | |||
| 506 | pub const Resolution = enum { | 570 | pub const Resolution = enum { |
| 507 | Unresolved, | 571 | Unresolved, |
| 508 | InProgress, | 572 | InProgress, |
src-self-hosted/test.zig created+176| ... | @@ -0,0 +1,176 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const mem = std.mem; | ||
| 3 | const builtin = @import("builtin"); | ||
| 4 | const Target = @import("target.zig").Target; | ||
| 5 | const Module = @import("module.zig").Module; | ||
| 6 | const introspect = @import("introspect.zig"); | ||
| 7 | const assertOrPanic = std.debug.assertOrPanic; | ||
| 8 | const errmsg = @import("errmsg.zig"); | ||
| 9 | |||
| 10 | test "compile errors" { | ||
| 11 | var ctx: TestContext = undefined; | ||
| 12 | try ctx.init(); | ||
| 13 | defer ctx.deinit(); | ||
| 14 | |||
| 15 | try ctx.testCompileError( | ||
| 16 | \\export fn entry() void {} | ||
| 17 | \\export fn entry() void {} | ||
| 18 | , file1, 2, 8, "exported symbol collision: 'entry'"); | ||
| 19 | |||
| 20 | try ctx.run(); | ||
| 21 | } | ||
| 22 | |||
| 23 | const file1 = "1.zig"; | ||
| 24 | |||
| 25 | const TestContext = struct { | ||
| 26 | loop: std.event.Loop, | ||
| 27 | zig_lib_dir: []u8, | ||
| 28 | direct_allocator: std.heap.DirectAllocator, | ||
| 29 | arena: std.heap.ArenaAllocator, | ||
| 30 | zig_cache_dir: []u8, | ||
| 31 | file_index: std.atomic.Int(usize), | ||
| 32 | group: std.event.Group(error!void), | ||
| 33 | any_err: error!void, | ||
| 34 | |||
| 35 | const tmp_dir_name = "stage2_test_tmp"; | ||
| 36 | |||
| 37 | fn init(self: *TestContext) !void { | ||
| 38 | self.* = TestContext{ | ||
| 39 | .any_err = {}, | ||
| 40 | .direct_allocator = undefined, | ||
| 41 | .arena = undefined, | ||
| 42 | .loop = undefined, | ||
| 43 | .zig_lib_dir = undefined, | ||
| 44 | .zig_cache_dir = undefined, | ||
| 45 | .group = undefined, | ||
| 46 | .file_index = std.atomic.Int(usize).init(0), | ||
| 47 | }; | ||
| 48 | |||
| 49 | self.direct_allocator = std.heap.DirectAllocator.init(); | ||
| 50 | errdefer self.direct_allocator.deinit(); | ||
| 51 | |||
| 52 | self.arena = std.heap.ArenaAllocator.init(&self.direct_allocator.allocator); | ||
| 53 | errdefer self.arena.deinit(); | ||
| 54 | |||
| 55 | // TODO faster allocator for coroutines that is thread-safe/lock-free | ||
| 56 | try self.loop.initMultiThreaded(&self.direct_allocator.allocator); | ||
| 57 | errdefer self.loop.deinit(); | ||
| 58 | |||
| 59 | self.group = std.event.Group(error!void).init(&self.loop); | ||
| 60 | errdefer self.group.cancelAll(); | ||
| 61 | |||
| 62 | self.zig_lib_dir = try introspect.resolveZigLibDir(&self.arena.allocator); | ||
| 63 | errdefer self.arena.allocator.free(self.zig_lib_dir); | ||
| 64 | |||
| 65 | self.zig_cache_dir = try introspect.resolveZigCacheDir(&self.arena.allocator); | ||
| 66 | errdefer self.arena.allocator.free(self.zig_cache_dir); | ||
| 67 | |||
| 68 | try std.os.makePath(&self.arena.allocator, tmp_dir_name); | ||
| 69 | errdefer std.os.deleteTree(&self.arena.allocator, tmp_dir_name) catch {}; | ||
| 70 | } | ||
| 71 | |||
| 72 | fn deinit(self: *TestContext) void { | ||
| 73 | std.os.deleteTree(&self.arena.allocator, tmp_dir_name) catch {}; | ||
| 74 | self.arena.allocator.free(self.zig_cache_dir); | ||
| 75 | self.arena.allocator.free(self.zig_lib_dir); | ||
| 76 | self.loop.deinit(); | ||
| 77 | self.arena.deinit(); | ||
| 78 | self.direct_allocator.deinit(); | ||
| 79 | } | ||
| 80 | |||
| 81 | fn run(self: *TestContext) !void { | ||
| 82 | const handle = try self.loop.call(waitForGroup, self); | ||
| 83 | defer cancel handle; | ||
| 84 | self.loop.run(); | ||
| 85 | return self.any_err; | ||
| 86 | } | ||
| 87 | |||
| 88 | async fn waitForGroup(self: *TestContext) void { | ||
| 89 | self.any_err = await (async self.group.wait() catch unreachable); | ||
| 90 | } | ||
| 91 | |||
| 92 | fn testCompileError( | ||
| 93 | self: *TestContext, | ||
| 94 | source: []const u8, | ||
| 95 | path: []const u8, | ||
| 96 | line: usize, | ||
| 97 | column: usize, | ||
| 98 | msg: []const u8, | ||
| 99 | ) !void { | ||
| 100 | var file_index_buf: [20]u8 = undefined; | ||
| 101 | const file_index = try std.fmt.bufPrint(file_index_buf[0..], "{}", self.file_index.next()); | ||
| 102 | const file1_path = try std.os.path.join(&self.arena.allocator, tmp_dir_name, file_index, file1); | ||
| 103 | |||
| 104 | if (std.os.path.dirname(file1_path)) |dirname| { | ||
| 105 | try std.os.makePath(&self.arena.allocator, dirname); | ||
| 106 | } | ||
| 107 | |||
| 108 | // TODO async I/O | ||
| 109 | try std.io.writeFile(&self.arena.allocator, file1_path, source); | ||
| 110 | |||
| 111 | var module = try Module.create( | ||
| 112 | &self.loop, | ||
| 113 | "test", | ||
| 114 | file1_path, | ||
| 115 | Target.Native, | ||
| 116 | Module.Kind.Obj, | ||
| 117 | builtin.Mode.Debug, | ||
| 118 | self.zig_lib_dir, | ||
| 119 | self.zig_cache_dir, | ||
| 120 | ); | ||
| 121 | errdefer module.destroy(); | ||
| 122 | |||
| 123 | try module.build(); | ||
| 124 | |||
| 125 | try self.group.call(getModuleEvent, module, source, path, line, column, msg); | ||
| 126 | } | ||
| 127 | |||
| 128 | async fn getModuleEvent( | ||
| 129 | module: *Module, | ||
| 130 | source: []const u8, | ||
| 131 | path: []const u8, | ||
| 132 | line: usize, | ||
| 133 | column: usize, | ||
| 134 | text: []const u8, | ||
| 135 | ) !void { | ||
| 136 | defer module.destroy(); | ||
| 137 | const build_event = await (async module.events.get() catch unreachable); | ||
| 138 | |||
| 139 | switch (build_event) { | ||
| 140 | Module.Event.Ok => { | ||
| 141 | @panic("build incorrectly succeeded"); | ||
| 142 | }, | ||
| 143 | Module.Event.Error => |err| { | ||
| 144 | @panic("build incorrectly failed"); | ||
| 145 | }, | ||
| 146 | Module.Event.Fail => |msgs| { | ||
| 147 | assertOrPanic(msgs.len != 0); | ||
| 148 | for (msgs) |msg| { | ||
| 149 | if (mem.endsWith(u8, msg.path, path) and mem.eql(u8, msg.text, text)) { | ||
| 150 | const first_token = msg.tree.tokens.at(msg.span.first); | ||
| 151 | const last_token = msg.tree.tokens.at(msg.span.first); | ||
| 152 | const start_loc = msg.tree.tokenLocationPtr(0, first_token); | ||
| 153 | if (start_loc.line + 1 == line and start_loc.column + 1 == column) { | ||
| 154 | return; | ||
| 155 | } | ||
| 156 | } | ||
| 157 | } | ||
| 158 | std.debug.warn( | ||
| 159 | "\n=====source:=======\n{}\n====expected:========\n{}:{}:{}: error: {}\n", | ||
| 160 | source, | ||
| 161 | path, | ||
| 162 | line, | ||
| 163 | column, | ||
| 164 | text, | ||
| 165 | ); | ||
| 166 | std.debug.warn("\n====found:========\n"); | ||
| 167 | var stderr = try std.io.getStdErr(); | ||
| 168 | for (msgs) |msg| { | ||
| 169 | try errmsg.printToFile(&stderr, msg, errmsg.Color.Auto); | ||
| 170 | } | ||
| 171 | std.debug.warn("============\n"); | ||
| 172 | return error.TestFailed; | ||
| 173 | }, | ||
| 174 | } | ||
| 175 | } | ||
| 176 | }; | ||
src/main.cpp+7-3| ... | @@ -891,15 +891,19 @@ int main(int argc, char **argv) { | ... | @@ -891,15 +891,19 @@ int main(int argc, char **argv) { |
| 891 | 891 | ||
| 892 | add_package(g, cur_pkg, g->root_package); | 892 | add_package(g, cur_pkg, g->root_package); |
| 893 | 893 | ||
| 894 | if (cmd == CmdBuild || cmd == CmdRun) { | 894 | if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) { |
| 895 | codegen_set_emit_file_type(g, emit_file_type); | ||
| 896 | |||
| 897 | for (size_t i = 0; i < objects.length; i += 1) { | 895 | for (size_t i = 0; i < objects.length; i += 1) { |
| 898 | codegen_add_object(g, buf_create_from_str(objects.at(i))); | 896 | codegen_add_object(g, buf_create_from_str(objects.at(i))); |
| 899 | } | 897 | } |
| 900 | for (size_t i = 0; i < asm_files.length; i += 1) { | 898 | for (size_t i = 0; i < asm_files.length; i += 1) { |
| 901 | codegen_add_assembly(g, buf_create_from_str(asm_files.at(i))); | 899 | codegen_add_assembly(g, buf_create_from_str(asm_files.at(i))); |
| 902 | } | 900 | } |
| 901 | } | ||
| 902 | |||
| 903 | |||
| 904 | if (cmd == CmdBuild || cmd == CmdRun) { | ||
| 905 | codegen_set_emit_file_type(g, emit_file_type); | ||
| 906 | |||
| 903 | codegen_build(g); | 907 | codegen_build(g); |
| 904 | codegen_link(g, out_file); | 908 | codegen_link(g, out_file); |
| 905 | if (timing_info) | 909 | if (timing_info) |
std/atomic/index.zig+2| ... | @@ -1,9 +1,11 @@ | ... | @@ -1,9 +1,11 @@ |
| 1 | pub const Stack = @import("stack.zig").Stack; | 1 | pub const Stack = @import("stack.zig").Stack; |
| 2 | pub const QueueMpsc = @import("queue_mpsc.zig").QueueMpsc; | 2 | pub const QueueMpsc = @import("queue_mpsc.zig").QueueMpsc; |
| 3 | pub const QueueMpmc = @import("queue_mpmc.zig").QueueMpmc; | 3 | pub const QueueMpmc = @import("queue_mpmc.zig").QueueMpmc; |
| 4 | pub const Int = @import("int.zig").Int; | ||
| 4 | 5 | ||
| 5 | test "std.atomic" { | 6 | test "std.atomic" { |
| 6 | _ = @import("stack.zig"); | 7 | _ = @import("stack.zig"); |
| 7 | _ = @import("queue_mpsc.zig"); | 8 | _ = @import("queue_mpsc.zig"); |
| 8 | _ = @import("queue_mpmc.zig"); | 9 | _ = @import("queue_mpmc.zig"); |
| 10 | _ = @import("int.zig"); | ||
| 9 | } | 11 | } |
std/atomic/int.zig created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const AtomicOrder = builtin.AtomicOrder; | ||
| 3 | |||
| 4 | /// Thread-safe, lock-free integer | ||
| 5 | pub fn Int(comptime T: type) type { | ||
| 6 | return struct { | ||
| 7 | value: T, | ||
| 8 | |||
| 9 | pub const Self = this; | ||
| 10 | |||
| 11 | pub fn init(init_val: T) Self { | ||
| 12 | return Self{ .value = init_val }; | ||
| 13 | } | ||
| 14 | |||
| 15 | pub fn next(self: *Self) T { | ||
| 16 | return @atomicRmw(T, &self.value, builtin.AtomicRmwOp.Add, 1, AtomicOrder.SeqCst); | ||
| 17 | } | ||
| 18 | }; | ||
| 19 | } | ||
std/build.zig+22| ... | @@ -1596,6 +1596,8 @@ pub const TestStep = struct { | ... | @@ -1596,6 +1596,8 @@ pub const TestStep = struct { |
| 1596 | target: Target, | 1596 | target: Target, |
| 1597 | exec_cmd_args: ?[]const ?[]const u8, | 1597 | exec_cmd_args: ?[]const ?[]const u8, |
| 1598 | include_dirs: ArrayList([]const u8), | 1598 | include_dirs: ArrayList([]const u8), |
| 1599 | lib_paths: ArrayList([]const u8), | ||
| 1600 | object_files: ArrayList([]const u8), | ||
| 1599 | 1601 | ||
| 1600 | pub fn init(builder: *Builder, root_src: []const u8) TestStep { | 1602 | pub fn init(builder: *Builder, root_src: []const u8) TestStep { |
| 1601 | const step_name = builder.fmt("test {}", root_src); | 1603 | const step_name = builder.fmt("test {}", root_src); |
| ... | @@ -1611,9 +1613,15 @@ pub const TestStep = struct { | ... | @@ -1611,9 +1613,15 @@ pub const TestStep = struct { |
| 1611 | .target = Target{ .Native = {} }, | 1613 | .target = Target{ .Native = {} }, |
| 1612 | .exec_cmd_args = null, | 1614 | .exec_cmd_args = null, |
| 1613 | .include_dirs = ArrayList([]const u8).init(builder.allocator), | 1615 | .include_dirs = ArrayList([]const u8).init(builder.allocator), |
| 1616 | .lib_paths = ArrayList([]const u8).init(builder.allocator), | ||
| 1617 | .object_files = ArrayList([]const u8).init(builder.allocator), | ||
| 1614 | }; | 1618 | }; |
| 1615 | } | 1619 | } |
| 1616 | 1620 | ||
| 1621 | pub fn addLibPath(self: *TestStep, path: []const u8) void { | ||
| 1622 | self.lib_paths.append(path) catch unreachable; | ||
| 1623 | } | ||
| 1624 | |||
| 1617 | pub fn setVerbose(self: *TestStep, value: bool) void { | 1625 | pub fn setVerbose(self: *TestStep, value: bool) void { |
| 1618 | self.verbose = value; | 1626 | self.verbose = value; |
| 1619 | } | 1627 | } |
| ... | @@ -1638,6 +1646,10 @@ pub const TestStep = struct { | ... | @@ -1638,6 +1646,10 @@ pub const TestStep = struct { |
| 1638 | self.filter = text; | 1646 | self.filter = text; |
| 1639 | } | 1647 | } |
| 1640 | 1648 | ||
| 1649 | pub fn addObjectFile(self: *TestStep, path: []const u8) void { | ||
| 1650 | self.object_files.append(path) catch unreachable; | ||
| 1651 | } | ||
| 1652 | |||
| 1641 | pub fn setTarget(self: *TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { | 1653 | pub fn setTarget(self: *TestStep, target_arch: builtin.Arch, target_os: builtin.Os, target_environ: builtin.Environ) void { |
| 1642 | self.target = Target{ | 1654 | self.target = Target{ |
| 1643 | .Cross = CrossTarget{ | 1655 | .Cross = CrossTarget{ |
| ... | @@ -1699,6 +1711,11 @@ pub const TestStep = struct { | ... | @@ -1699,6 +1711,11 @@ pub const TestStep = struct { |
| 1699 | try zig_args.append(self.name_prefix); | 1711 | try zig_args.append(self.name_prefix); |
| 1700 | } | 1712 | } |
| 1701 | 1713 | ||
| 1714 | for (self.object_files.toSliceConst()) |object_file| { | ||
| 1715 | try zig_args.append("--object"); | ||
| 1716 | try zig_args.append(builder.pathFromRoot(object_file)); | ||
| 1717 | } | ||
| 1718 | |||
| 1702 | { | 1719 | { |
| 1703 | var it = self.link_libs.iterator(); | 1720 | var it = self.link_libs.iterator(); |
| 1704 | while (true) { | 1721 | while (true) { |
| ... | @@ -1734,6 +1751,11 @@ pub const TestStep = struct { | ... | @@ -1734,6 +1751,11 @@ pub const TestStep = struct { |
| 1734 | try zig_args.append(rpath); | 1751 | try zig_args.append(rpath); |
| 1735 | } | 1752 | } |
| 1736 | 1753 | ||
| 1754 | for (self.lib_paths.toSliceConst()) |lib_path| { | ||
| 1755 | try zig_args.append("--library-path"); | ||
| 1756 | try zig_args.append(lib_path); | ||
| 1757 | } | ||
| 1758 | |||
| 1737 | for (builder.lib_paths.toSliceConst()) |lib_path| { | 1759 | for (builder.lib_paths.toSliceConst()) |lib_path| { |
| 1738 | try zig_args.append("--library-path"); | 1760 | try zig_args.append("--library-path"); |
| 1739 | try zig_args.append(lib_path); | 1761 | try zig_args.append(lib_path); |