| ... | @@ -35,6 +35,7 @@ const usage = | ... | @@ -35,6 +35,7 @@ const usage = |
| 35 | \\ | 35 | \\ |
| 36 | \\Commands: | 36 | \\Commands: |
| 37 | \\ | 37 | \\ |
| | 38 | \\ build Build project from build.zig |
| 38 | \\ build-exe Create executable from source or object files | 39 | \\ build-exe Create executable from source or object files |
| 39 | \\ build-lib Create library from source or object files | 40 | \\ build-lib Create library from source or object files |
| 40 | \\ build-obj Create object from source or assembly | 41 | \\ build-obj Create object from source or assembly |
| ... | @@ -42,6 +43,8 @@ const usage = | ... | @@ -42,6 +43,8 @@ const usage = |
| 42 | \\ c++ Use Zig as a drop-in C++ compiler | 43 | \\ c++ Use Zig as a drop-in C++ compiler |
| 43 | \\ env Print lib path, std path, compiler id and version | 44 | \\ env Print lib path, std path, compiler id and version |
| 44 | \\ fmt Parse file and render in canonical zig format | 45 | \\ fmt Parse file and render in canonical zig format |
| | 46 | \\ init-exe Initialize a `zig build` application in the cwd |
| | 47 | \\ init-lib Initialize a `zig build` library in the cwd |
| 45 | \\ libc Display native libc paths file or validate one | 48 | \\ libc Display native libc paths file or validate one |
| 46 | \\ run Create executable and run immediately | 49 | \\ run Create executable and run immediately |
| 47 | \\ translate-c Convert C code to Zig code | 50 | \\ translate-c Convert C code to Zig code |
| ... | @@ -136,6 +139,8 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v | ... | @@ -136,6 +139,8 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v |
| 136 | mem.eql(u8, cmd, "-cc1") or mem.eql(u8, cmd, "-cc1as")) | 139 | mem.eql(u8, cmd, "-cc1") or mem.eql(u8, cmd, "-cc1as")) |
| 137 | { | 140 | { |
| 138 | return punt_to_clang(arena, args); | 141 | return punt_to_clang(arena, args); |
| | 142 | } else if (mem.eql(u8, cmd, "build")) { |
| | 143 | return cmdBuild(gpa, arena, cmd_args); |
| 139 | } else if (mem.eql(u8, cmd, "fmt")) { | 144 | } else if (mem.eql(u8, cmd, "fmt")) { |
| 140 | return cmdFmt(gpa, cmd_args); | 145 | return cmdFmt(gpa, cmd_args); |
| 141 | } else if (mem.eql(u8, cmd, "libc")) { | 146 | } else if (mem.eql(u8, cmd, "libc")) { |
| ... | @@ -172,18 +177,18 @@ const usage_build_generic = | ... | @@ -172,18 +177,18 @@ const usage_build_generic = |
| 172 | \\Supported file types: | 177 | \\Supported file types: |
| 173 | \\ .zig Zig source code | 178 | \\ .zig Zig source code |
| 174 | \\ .zir Zig Intermediate Representation code | 179 | \\ .zir Zig Intermediate Representation code |
| 175 | \\ (planned) .o ELF object file | 180 | \\ .o ELF object file |
| 176 | \\ (planned) .o MACH-O (macOS) object file | 181 | \\ .o MACH-O (macOS) object file |
| 177 | \\ (planned) .obj COFF (Windows) object file | 182 | \\ .obj COFF (Windows) object file |
| 178 | \\ (planned) .lib COFF (Windows) static library | 183 | \\ .lib COFF (Windows) static library |
| 179 | \\ (planned) .a ELF static library | 184 | \\ .a ELF static library |
| 180 | \\ (planned) .so ELF shared object (dynamic link) | 185 | \\ .so ELF shared object (dynamic link) |
| 181 | \\ (planned) .dll Windows Dynamic Link Library | 186 | \\ .dll Windows Dynamic Link Library |
| 182 | \\ (planned) .dylib MACH-O (macOS) dynamic library | 187 | \\ .dylib MACH-O (macOS) dynamic library |
| 183 | \\ (planned) .s Target-specific assembly source code | 188 | \\ .s Target-specific assembly source code |
| 184 | \\ (planned) .S Assembly with C preprocessor (requires LLVM extensions) | 189 | \\ .S Assembly with C preprocessor (requires LLVM extensions) |
| 185 | \\ (planned) .c C source code (requires LLVM extensions) | 190 | \\ .c C source code (requires LLVM extensions) |
| 186 | \\ (planned) .cpp C++ source code (requires LLVM extensions) | 191 | \\ .cpp C++ source code (requires LLVM extensions) |
| 187 | \\ Other C++ extensions: .C .cc .cxx | 192 | \\ Other C++ extensions: .C .cc .cxx |
| 188 | \\ | 193 | \\ |
| 189 | \\General Options: | 194 | \\General Options: |
| ... | @@ -195,6 +200,8 @@ const usage_build_generic = | ... | @@ -195,6 +200,8 @@ const usage_build_generic = |
| 195 | \\ --show-builtin Output the source of @import("builtin") then exit | 200 | \\ --show-builtin Output the source of @import("builtin") then exit |
| 196 | \\ --cache-dir [path] Override the local cache directory | 201 | \\ --cache-dir [path] Override the local cache directory |
| 197 | \\ --global-cache-dir [path] Override the global cache directory | 202 | \\ --global-cache-dir [path] Override the global cache directory |
| | 203 | \\ --override-lib-dir [path] Override path to Zig installation lib directory |
| | 204 | \\ --enable-cache Output to cache directory; print path to stdout |
| 198 | \\ | 205 | \\ |
| 199 | \\Compile Options: | 206 | \\Compile Options: |
| 200 | \\ -target [name] <arch><sub>-<os>-<abi> see the targets command | 207 | \\ -target [name] <arch><sub>-<os>-<abi> see the targets command |
| ... | @@ -357,6 +364,7 @@ pub fn buildOutputType( | ... | @@ -357,6 +364,7 @@ pub fn buildOutputType( |
| 357 | var test_name_prefix: ?[]const u8 = null; | 364 | var test_name_prefix: ?[]const u8 = null; |
| 358 | var override_local_cache_dir: ?[]const u8 = null; | 365 | var override_local_cache_dir: ?[]const u8 = null; |
| 359 | var override_global_cache_dir: ?[]const u8 = null; | 366 | var override_global_cache_dir: ?[]const u8 = null; |
| | 367 | var override_lib_dir: ?[]const u8 = null; |
| 360 | | 368 | |
| 361 | var system_libs = std.ArrayList([]const u8).init(gpa); | 369 | var system_libs = std.ArrayList([]const u8).init(gpa); |
| 362 | defer system_libs.deinit(); | 370 | defer system_libs.deinit(); |
| ... | @@ -412,7 +420,7 @@ pub fn buildOutputType( | ... | @@ -412,7 +420,7 @@ pub fn buildOutputType( |
| 412 | if (mem.startsWith(u8, arg, "-")) { | 420 | if (mem.startsWith(u8, arg, "-")) { |
| 413 | if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { | 421 | if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { |
| 414 | try io.getStdOut().writeAll(usage_build_generic); | 422 | try io.getStdOut().writeAll(usage_build_generic); |
| 415 | process.exit(0); | 423 | return process.cleanExit(); |
| 416 | } else if (mem.eql(u8, arg, "--")) { | 424 | } else if (mem.eql(u8, arg, "--")) { |
| 417 | if (arg_mode == .run) { | 425 | if (arg_mode == .run) { |
| 418 | runtime_args_start = i + 1; | 426 | runtime_args_start = i + 1; |
| ... | @@ -547,6 +555,12 @@ pub fn buildOutputType( | ... | @@ -547,6 +555,12 @@ pub fn buildOutputType( |
| 547 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); | 555 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); |
| 548 | i += 1; | 556 | i += 1; |
| 549 | override_global_cache_dir = args[i]; | 557 | override_global_cache_dir = args[i]; |
| | 558 | } else if (mem.eql(u8, arg, "--override-lib-dir")) { |
| | 559 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); |
| | 560 | i += 1; |
| | 561 | override_lib_dir = args[i]; |
| | 562 | } else if (mem.eql(u8, arg, "--enable-cache")) { |
| | 563 | enable_cache = true; |
| 550 | } else if (mem.eql(u8, arg, "--test-cmd-bin")) { | 564 | } else if (mem.eql(u8, arg, "--test-cmd-bin")) { |
| 551 | try test_exec_args.append(null); | 565 | try test_exec_args.append(null); |
| 552 | } else if (mem.eql(u8, arg, "--test-evented-io")) { | 566 | } else if (mem.eql(u8, arg, "--test-evented-io")) { |
| ... | @@ -1102,12 +1116,22 @@ pub fn buildOutputType( | ... | @@ -1102,12 +1116,22 @@ pub fn buildOutputType( |
| 1102 | var cleanup_emit_bin_dir: ?fs.Dir = null; | 1116 | var cleanup_emit_bin_dir: ?fs.Dir = null; |
| 1103 | defer if (cleanup_emit_bin_dir) |*dir| dir.close(); | 1117 | defer if (cleanup_emit_bin_dir) |*dir| dir.close(); |
| 1104 | | 1118 | |
| | 1119 | const have_enable_cache = enable_cache orelse false; |
| | 1120 | |
| 1105 | const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) { | 1121 | const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) { |
| 1106 | .no => null, | 1122 | .no => null, |
| 1107 | .yes_default_path => Compilation.EmitLoc{ | 1123 | .yes_default_path => Compilation.EmitLoc{ |
| 1108 | .directory = switch (arg_mode) { | 1124 | .directory = blk: { |
| 1109 | .run, .zig_test => null, | 1125 | switch (arg_mode) { |
| 1110 | else => .{ .path = null, .handle = fs.cwd() }, | 1126 | .run, .zig_test => break :blk null, |
| | 1127 | else => { |
| | 1128 | if (have_enable_cache) { |
| | 1129 | break :blk null; |
| | 1130 | } else { |
| | 1131 | break :blk .{ .path = null, .handle = fs.cwd() }; |
| | 1132 | } |
| | 1133 | }, |
| | 1134 | } |
| 1111 | }, | 1135 | }, |
| 1112 | .basename = try std.zig.binNameAlloc( | 1136 | .basename = try std.zig.binNameAlloc( |
| 1113 | arena, | 1137 | arena, |
| ... | @@ -1120,6 +1144,12 @@ pub fn buildOutputType( | ... | @@ -1120,6 +1144,12 @@ pub fn buildOutputType( |
| 1120 | }, | 1144 | }, |
| 1121 | .yes => |full_path| b: { | 1145 | .yes => |full_path| b: { |
| 1122 | const basename = fs.path.basename(full_path); | 1146 | const basename = fs.path.basename(full_path); |
| | 1147 | if (have_enable_cache) { |
| | 1148 | break :b Compilation.EmitLoc{ |
| | 1149 | .basename = basename, |
| | 1150 | .directory = null, |
| | 1151 | }; |
| | 1152 | } |
| 1123 | if (fs.path.dirname(full_path)) |dirname| { | 1153 | if (fs.path.dirname(full_path)) |dirname| { |
| 1124 | const handle = try fs.cwd().openDir(dirname, .{}); | 1154 | const handle = try fs.cwd().openDir(dirname, .{}); |
| 1125 | cleanup_emit_bin_dir = handle; | 1155 | cleanup_emit_bin_dir = handle; |
| ... | @@ -1192,9 +1222,15 @@ pub fn buildOutputType( | ... | @@ -1192,9 +1222,15 @@ pub fn buildOutputType( |
| 1192 | } else null; | 1222 | } else null; |
| 1193 | | 1223 | |
| 1194 | const self_exe_path = try fs.selfExePathAlloc(arena); | 1224 | const self_exe_path = try fs.selfExePathAlloc(arena); |
| 1195 | var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { | 1225 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| |
| 1196 | fatal("unable to find zig installation directory: {}\n", .{@errorName(err)}); | 1226 | .{ |
| 1197 | }; | 1227 | .path = lib_dir, |
| | 1228 | .handle = try fs.cwd().openDir(lib_dir, .{}), |
| | 1229 | } |
| | 1230 | else |
| | 1231 | introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { |
| | 1232 | fatal("unable to find zig installation directory: {}", .{@errorName(err)}); |
| | 1233 | }; |
| 1198 | defer zig_lib_directory.handle.close(); | 1234 | defer zig_lib_directory.handle.close(); |
| 1199 | | 1235 | |
| 1200 | const random_seed = blk: { | 1236 | const random_seed = blk: { |
| ... | @@ -1337,7 +1373,20 @@ pub fn buildOutputType( | ... | @@ -1337,7 +1373,20 @@ pub fn buildOutputType( |
| 1337 | return cmdTranslateC(comp, arena); | 1373 | return cmdTranslateC(comp, arena); |
| 1338 | } | 1374 | } |
| 1339 | | 1375 | |
| 1340 | try updateModule(gpa, comp, zir_out_path); | 1376 | const hook: AfterUpdateHook = blk: { |
| | 1377 | if (!have_enable_cache) |
| | 1378 | break :blk .none; |
| | 1379 | |
| | 1380 | switch (emit_bin) { |
| | 1381 | .no => break :blk .none, |
| | 1382 | .yes_default_path => break :blk .{ |
| | 1383 | .print = comp.bin_file.options.directory.path orelse ".", |
| | 1384 | }, |
| | 1385 | .yes => |full_path| break :blk .{ .update = full_path }, |
| | 1386 | } |
| | 1387 | }; |
| | 1388 | |
| | 1389 | try updateModule(gpa, comp, zir_out_path, hook); |
| 1341 | | 1390 | |
| 1342 | if (build_options.have_llvm and only_pp_or_asm) { | 1391 | if (build_options.have_llvm and only_pp_or_asm) { |
| 1343 | // this may include dumping the output to stdout | 1392 | // this may include dumping the output to stdout |
| ... | @@ -1389,7 +1438,7 @@ pub fn buildOutputType( | ... | @@ -1389,7 +1438,7 @@ pub fn buildOutputType( |
| 1389 | else => process.exit(1), | 1438 | else => process.exit(1), |
| 1390 | } | 1439 | } |
| 1391 | if (!watch) | 1440 | if (!watch) |
| 1392 | process.exit(0); | 1441 | return process.cleanExit(); |
| 1393 | }, | 1442 | }, |
| 1394 | else => {}, | 1443 | else => {}, |
| 1395 | } | 1444 | } |
| ... | @@ -1413,7 +1462,7 @@ pub fn buildOutputType( | ... | @@ -1413,7 +1462,7 @@ pub fn buildOutputType( |
| 1413 | if (output_mode == .Exe) { | 1462 | if (output_mode == .Exe) { |
| 1414 | try comp.makeBinFileWritable(); | 1463 | try comp.makeBinFileWritable(); |
| 1415 | } | 1464 | } |
| 1416 | try updateModule(gpa, comp, zir_out_path); | 1465 | try updateModule(gpa, comp, zir_out_path, hook); |
| 1417 | } else if (mem.eql(u8, actual_line, "exit")) { | 1466 | } else if (mem.eql(u8, actual_line, "exit")) { |
| 1418 | break; | 1467 | break; |
| 1419 | } else if (mem.eql(u8, actual_line, "help")) { | 1468 | } else if (mem.eql(u8, actual_line, "help")) { |
| ... | @@ -1427,7 +1476,13 @@ pub fn buildOutputType( | ... | @@ -1427,7 +1476,13 @@ pub fn buildOutputType( |
| 1427 | } | 1476 | } |
| 1428 | } | 1477 | } |
| 1429 | | 1478 | |
| 1430 | fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8) !void { | 1479 | const AfterUpdateHook = union(enum) { |
| | 1480 | none, |
| | 1481 | print: []const u8, |
| | 1482 | update: []const u8, |
| | 1483 | }; |
| | 1484 | |
| | 1485 | fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8, hook: AfterUpdateHook) !void { |
| 1431 | try comp.update(); | 1486 | try comp.update(); |
| 1432 | | 1487 | |
| 1433 | var errors = try comp.getAllErrorsAlloc(); | 1488 | var errors = try comp.getAllErrorsAlloc(); |
| ... | @@ -1437,6 +1492,15 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8) | ... | @@ -1437,6 +1492,15 @@ fn updateModule(gpa: *Allocator, comp: *Compilation, zir_out_path: ?[]const u8) |
| 1437 | for (errors.list) |full_err_msg| { | 1492 | for (errors.list) |full_err_msg| { |
| 1438 | full_err_msg.renderToStdErr(); | 1493 | full_err_msg.renderToStdErr(); |
| 1439 | } | 1494 | } |
| | 1495 | } else switch (hook) { |
| | 1496 | .none => {}, |
| | 1497 | .print => |bin_path| try io.getStdOut().writer().print("{s}\n", .{bin_path}), |
| | 1498 | .update => |full_path| _ = try comp.bin_file.options.directory.handle.updateFile( |
| | 1499 | comp.bin_file.options.sub_path, |
| | 1500 | fs.cwd(), |
| | 1501 | full_path, |
| | 1502 | .{}, |
| | 1503 | ), |
| 1440 | } | 1504 | } |
| 1441 | | 1505 | |
| 1442 | if (zir_out_path) |zop| { | 1506 | if (zir_out_path) |zop| { |
| ... | @@ -1535,7 +1599,7 @@ pub fn cmdLibC(gpa: *Allocator, args: []const []const u8) !void { | ... | @@ -1535,7 +1599,7 @@ pub fn cmdLibC(gpa: *Allocator, args: []const []const u8) !void { |
| 1535 | if (mem.eql(u8, arg, "--help")) { | 1599 | if (mem.eql(u8, arg, "--help")) { |
| 1536 | const stdout = io.getStdOut().writer(); | 1600 | const stdout = io.getStdOut().writer(); |
| 1537 | try stdout.writeAll(usage_libc); | 1601 | try stdout.writeAll(usage_libc); |
| 1538 | process.exit(0); | 1602 | return process.cleanExit(); |
| 1539 | } else { | 1603 | } else { |
| 1540 | fatal("unrecognized parameter: '{}'", .{arg}); | 1604 | fatal("unrecognized parameter: '{}'", .{arg}); |
| 1541 | } | 1605 | } |
| ... | @@ -1592,7 +1656,7 @@ pub fn cmdInit( | ... | @@ -1592,7 +1656,7 @@ pub fn cmdInit( |
| 1592 | if (mem.startsWith(u8, arg, "-")) { | 1656 | if (mem.startsWith(u8, arg, "-")) { |
| 1593 | if (mem.eql(u8, arg, "--help")) { | 1657 | if (mem.eql(u8, arg, "--help")) { |
| 1594 | try io.getStdOut().writeAll(usage_init); | 1658 | try io.getStdOut().writeAll(usage_init); |
| 1595 | process.exit(0); | 1659 | return process.cleanExit(); |
| 1596 | } else { | 1660 | } else { |
| 1597 | fatal("unrecognized parameter: '{}'", .{arg}); | 1661 | fatal("unrecognized parameter: '{}'", .{arg}); |
| 1598 | } | 1662 | } |
| ... | @@ -1657,6 +1721,248 @@ pub fn cmdInit( | ... | @@ -1657,6 +1721,248 @@ pub fn cmdInit( |
| 1657 | } | 1721 | } |
| 1658 | } | 1722 | } |
| 1659 | | 1723 | |
| | 1724 | pub const usage_build = |
| | 1725 | \\Usage: zig build [steps] [options] |
| | 1726 | \\ |
| | 1727 | \\ Build a project from build.zig. |
| | 1728 | \\ |
| | 1729 | \\Options: |
| | 1730 | \\ --help Print this help and exit |
| | 1731 | \\ |
| | 1732 | \\ |
| | 1733 | ; |
| | 1734 | |
| | 1735 | pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !void { |
| | 1736 | // We want to release all the locks before executing the child process, so we make a nice |
| | 1737 | // big block here to ensure the cleanup gets run when we extract out our argv. |
| | 1738 | const lock_and_argv = lock_and_argv: { |
| | 1739 | const self_exe_path = try fs.selfExePathAlloc(arena); |
| | 1740 | |
| | 1741 | var build_file: ?[]const u8 = null; |
| | 1742 | var override_lib_dir: ?[]const u8 = null; |
| | 1743 | var override_global_cache_dir: ?[]const u8 = null; |
| | 1744 | var override_local_cache_dir: ?[]const u8 = null; |
| | 1745 | var child_argv = std.ArrayList([]const u8).init(arena); |
| | 1746 | |
| | 1747 | const argv_index_exe = child_argv.items.len; |
| | 1748 | _ = try child_argv.addOne(); |
| | 1749 | |
| | 1750 | try child_argv.append(self_exe_path); |
| | 1751 | |
| | 1752 | const argv_index_build_file = child_argv.items.len; |
| | 1753 | _ = try child_argv.addOne(); |
| | 1754 | |
| | 1755 | const argv_index_cache_dir = child_argv.items.len; |
| | 1756 | _ = try child_argv.addOne(); |
| | 1757 | |
| | 1758 | { |
| | 1759 | var i: usize = 0; |
| | 1760 | while (i < args.len) : (i += 1) { |
| | 1761 | const arg = args[i]; |
| | 1762 | if (mem.startsWith(u8, arg, "-")) { |
| | 1763 | if (mem.eql(u8, arg, "--build-file")) { |
| | 1764 | if (i + 1 >= args.len) fatal("expected argument after '{}'", .{arg}); |
| | 1765 | i += 1; |
| | 1766 | build_file = args[i]; |
| | 1767 | continue; |
| | 1768 | } else if (mem.eql(u8, arg, "--override-lib-dir")) { |
| | 1769 | if (i + 1 >= args.len) fatal("expected argument after '{}'", .{arg}); |
| | 1770 | i += 1; |
| | 1771 | override_lib_dir = args[i]; |
| | 1772 | try child_argv.appendSlice(&[_][]const u8{ arg, args[i] }); |
| | 1773 | continue; |
| | 1774 | } else if (mem.eql(u8, arg, "--cache-dir")) { |
| | 1775 | if (i + 1 >= args.len) fatal("expected argument after '{}'", .{arg}); |
| | 1776 | i += 1; |
| | 1777 | override_local_cache_dir = args[i]; |
| | 1778 | try child_argv.appendSlice(&[_][]const u8{ arg, args[i] }); |
| | 1779 | continue; |
| | 1780 | } else if (mem.eql(u8, arg, "--global-cache-dir")) { |
| | 1781 | if (i + 1 >= args.len) fatal("expected argument after '{}'", .{arg}); |
| | 1782 | i += 1; |
| | 1783 | override_global_cache_dir = args[i]; |
| | 1784 | try child_argv.appendSlice(&[_][]const u8{ arg, args[i] }); |
| | 1785 | continue; |
| | 1786 | } |
| | 1787 | } |
| | 1788 | try child_argv.append(arg); |
| | 1789 | } |
| | 1790 | } |
| | 1791 | |
| | 1792 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| |
| | 1793 | .{ |
| | 1794 | .path = lib_dir, |
| | 1795 | .handle = try fs.cwd().openDir(lib_dir, .{}), |
| | 1796 | } |
| | 1797 | else |
| | 1798 | introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { |
| | 1799 | fatal("unable to find zig installation directory: {}", .{@errorName(err)}); |
| | 1800 | }; |
| | 1801 | defer zig_lib_directory.handle.close(); |
| | 1802 | |
| | 1803 | const std_special = "std" ++ fs.path.sep_str ++ "special"; |
| | 1804 | const special_dir_path = try zig_lib_directory.join(arena, &[_][]const u8{std_special}); |
| | 1805 | |
| | 1806 | var root_pkg: Package = .{ |
| | 1807 | .root_src_directory = .{ |
| | 1808 | .path = special_dir_path, |
| | 1809 | .handle = try zig_lib_directory.handle.openDir(std_special, .{}), |
| | 1810 | }, |
| | 1811 | .root_src_path = "build_runner.zig", |
| | 1812 | }; |
| | 1813 | defer root_pkg.root_src_directory.handle.close(); |
| | 1814 | |
| | 1815 | var cleanup_build_dir: ?fs.Dir = null; |
| | 1816 | defer if (cleanup_build_dir) |*dir| dir.close(); |
| | 1817 | |
| | 1818 | const cwd_path = try process.getCwdAlloc(arena); |
| | 1819 | const build_zig_basename = if (build_file) |bf| fs.path.basename(bf) else "build.zig"; |
| | 1820 | const build_directory: Compilation.Directory = blk: { |
| | 1821 | if (build_file) |bf| { |
| | 1822 | if (fs.path.dirname(bf)) |dirname| { |
| | 1823 | const dir = try fs.cwd().openDir(dirname, .{}); |
| | 1824 | cleanup_build_dir = dir; |
| | 1825 | break :blk .{ .path = dirname, .handle = dir }; |
| | 1826 | } |
| | 1827 | |
| | 1828 | break :blk .{ .path = null, .handle = fs.cwd() }; |
| | 1829 | } |
| | 1830 | // Search up parent directories until we find build.zig. |
| | 1831 | var dirname: []const u8 = cwd_path; |
| | 1832 | while (true) { |
| | 1833 | const joined_path = try fs.path.join(arena, &[_][]const u8{ dirname, build_zig_basename }); |
| | 1834 | if (fs.cwd().access(joined_path, .{})) |_| { |
| | 1835 | const dir = try fs.cwd().openDir(dirname, .{}); |
| | 1836 | break :blk .{ .path = dirname, .handle = dir }; |
| | 1837 | } else |err| switch (err) { |
| | 1838 | error.FileNotFound => { |
| | 1839 | dirname = fs.path.dirname(dirname) orelse { |
| | 1840 | std.log.info("{}", .{ |
| | 1841 | \\Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`, |
| | 1842 | \\or see `zig --help` for more options. |
| | 1843 | }); |
| | 1844 | fatal("No 'build.zig' file found, in the current directory or any parent directories.", .{}); |
| | 1845 | }; |
| | 1846 | continue; |
| | 1847 | }, |
| | 1848 | else => |e| return e, |
| | 1849 | } |
| | 1850 | } |
| | 1851 | }; |
| | 1852 | child_argv.items[argv_index_build_file] = build_directory.path orelse cwd_path; |
| | 1853 | |
| | 1854 | var build_pkg: Package = .{ |
| | 1855 | .root_src_directory = build_directory, |
| | 1856 | .root_src_path = build_zig_basename, |
| | 1857 | }; |
| | 1858 | try root_pkg.table.put(arena, "@build", &build_pkg); |
| | 1859 | |
| | 1860 | var global_cache_directory: Compilation.Directory = l: { |
| | 1861 | const p = override_global_cache_dir orelse try introspect.resolveGlobalCacheDir(arena); |
| | 1862 | break :l .{ |
| | 1863 | .handle = try fs.cwd().makeOpenPath(p, .{}), |
| | 1864 | .path = p, |
| | 1865 | }; |
| | 1866 | }; |
| | 1867 | defer global_cache_directory.handle.close(); |
| | 1868 | |
| | 1869 | var local_cache_directory: Compilation.Directory = l: { |
| | 1870 | if (override_local_cache_dir) |local_cache_dir_path| { |
| | 1871 | break :l .{ |
| | 1872 | .handle = try fs.cwd().makeOpenPath(local_cache_dir_path, .{}), |
| | 1873 | .path = local_cache_dir_path, |
| | 1874 | }; |
| | 1875 | } |
| | 1876 | const cache_dir_path = try build_directory.join(arena, &[_][]const u8{"zig-cache"}); |
| | 1877 | break :l .{ |
| | 1878 | .handle = try build_directory.handle.makeOpenPath("zig-cache", .{}), |
| | 1879 | .path = cache_dir_path, |
| | 1880 | }; |
| | 1881 | }; |
| | 1882 | defer local_cache_directory.handle.close(); |
| | 1883 | |
| | 1884 | child_argv.items[argv_index_cache_dir] = local_cache_directory.path orelse cwd_path; |
| | 1885 | |
| | 1886 | gimmeMoreOfThoseSweetSweetFileDescriptors(); |
| | 1887 | |
| | 1888 | const cross_target: std.zig.CrossTarget = .{}; |
| | 1889 | const target_info = try detectNativeTargetInfo(gpa, cross_target); |
| | 1890 | |
| | 1891 | const exe_basename = try std.zig.binNameAlloc(arena, "build", target_info.target, .Exe, null, null); |
| | 1892 | const emit_bin: Compilation.EmitLoc = .{ |
| | 1893 | .directory = null, // Use the local zig-cache. |
| | 1894 | .basename = exe_basename, |
| | 1895 | }; |
| | 1896 | const random_seed = blk: { |
| | 1897 | var random_seed: u64 = undefined; |
| | 1898 | try std.crypto.randomBytes(mem.asBytes(&random_seed)); |
| | 1899 | break :blk random_seed; |
| | 1900 | }; |
| | 1901 | var default_prng = std.rand.DefaultPrng.init(random_seed); |
| | 1902 | const comp = Compilation.create(gpa, .{ |
| | 1903 | .zig_lib_directory = zig_lib_directory, |
| | 1904 | .local_cache_directory = local_cache_directory, |
| | 1905 | .global_cache_directory = global_cache_directory, |
| | 1906 | .root_name = "build", |
| | 1907 | .target = target_info.target, |
| | 1908 | .is_native_os = cross_target.isNativeOs(), |
| | 1909 | .dynamic_linker = target_info.dynamic_linker.get(), |
| | 1910 | .output_mode = .Exe, |
| | 1911 | .root_pkg = &root_pkg, |
| | 1912 | .emit_bin = emit_bin, |
| | 1913 | .emit_h = null, |
| | 1914 | .optimize_mode = .Debug, |
| | 1915 | .self_exe_path = self_exe_path, |
| | 1916 | .rand = &default_prng.random, |
| | 1917 | }) catch |err| { |
| | 1918 | fatal("unable to create compilation: {}", .{@errorName(err)}); |
| | 1919 | }; |
| | 1920 | defer comp.destroy(); |
| | 1921 | |
| | 1922 | try updateModule(gpa, comp, null, .none); |
| | 1923 | |
| | 1924 | child_argv.items[argv_index_exe] = try comp.bin_file.options.directory.join(arena, &[_][]const u8{exe_basename}); |
| | 1925 | |
| | 1926 | break :lock_and_argv .{ |
| | 1927 | .child_argv = child_argv.items, |
| | 1928 | .lock = comp.bin_file.toOwnedLock(), |
| | 1929 | }; |
| | 1930 | }; |
| | 1931 | const child_argv = lock_and_argv.child_argv; |
| | 1932 | var lock = lock_and_argv.lock; |
| | 1933 | defer lock.release(); |
| | 1934 | |
| | 1935 | const child = try std.ChildProcess.init(child_argv, gpa); |
| | 1936 | defer child.deinit(); |
| | 1937 | |
| | 1938 | child.stdin_behavior = .Inherit; |
| | 1939 | child.stdout_behavior = .Inherit; |
| | 1940 | child.stderr_behavior = .Inherit; |
| | 1941 | |
| | 1942 | var cmd = std.ArrayList(u8).init(arena); |
| | 1943 | |
| | 1944 | const term = try child.spawnAndWait(); |
| | 1945 | switch (term) { |
| | 1946 | .Exited => |code| { |
| | 1947 | if (code == 0) return process.cleanExit(); |
| | 1948 | try cmd.writer().print("failed with exit code {}:\n", .{code}); |
| | 1949 | }, |
| | 1950 | else => { |
| | 1951 | try cmd.appendSlice("crashed:\n"); |
| | 1952 | }, |
| | 1953 | } |
| | 1954 | |
| | 1955 | try cmd.append('\n'); |
| | 1956 | for (child_argv[0 .. child_argv.len - 1]) |arg| { |
| | 1957 | try cmd.appendSlice(arg); |
| | 1958 | try cmd.append(' '); |
| | 1959 | } |
| | 1960 | try cmd.appendSlice(child_argv[child_argv.len - 1]); |
| | 1961 | |
| | 1962 | if (true) // Working around erroneous stage1 compile error: unreachable code on child.deinit() |
| | 1963 | fatal("The following build command {}", .{cmd.items}); |
| | 1964 | } |
| | 1965 | |
| 1660 | pub const usage_fmt = | 1966 | pub const usage_fmt = |
| 1661 | \\Usage: zig fmt [file]... | 1967 | \\Usage: zig fmt [file]... |
| 1662 | \\ | 1968 | \\ |
| ... | @@ -1699,7 +2005,7 @@ pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void { | ... | @@ -1699,7 +2005,7 @@ pub fn cmdFmt(gpa: *Allocator, args: []const []const u8) !void { |
| 1699 | if (mem.eql(u8, arg, "--help")) { | 2005 | if (mem.eql(u8, arg, "--help")) { |
| 1700 | const stdout = io.getStdOut().outStream(); | 2006 | const stdout = io.getStdOut().outStream(); |
| 1701 | try stdout.writeAll(usage_fmt); | 2007 | try stdout.writeAll(usage_fmt); |
| 1702 | process.exit(0); | 2008 | return process.cleanExit(); |
| 1703 | } else if (mem.eql(u8, arg, "--color")) { | 2009 | } else if (mem.eql(u8, arg, "--color")) { |
| 1704 | if (i + 1 >= args.len) { | 2010 | if (i + 1 >= args.len) { |
| 1705 | fatal("expected [auto|on|off] after --color", .{}); | 2011 | fatal("expected [auto|on|off] after --color", .{}); |