diff --git a/BRANCH_TODO b/BRANCH_TODO index 026efaddce..c84dc397bb 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,3 +1,5 @@ + * skip LLD caching when bin directory is not in the cache (so we don't put `id.txt` into the cwd) + (maybe make it an explicit option and have main.zig disable it) * `zig build` * repair @cImport * make sure zig cc works @@ -12,7 +14,8 @@ * -fno-emit-asm (default) do not output .s (assembly code)\n" * -femit-llvm-ir produce a .ll file with LLVM IR\n" * -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n" - * --cache-dir [path] override the local cache directory\n" + * --cache-dir [path] override the local cache directory + * --global-cache-dir [path] override the global cache directory * implement proper parsing of LLD stderr/stdout and exposing compile errors * implement proper parsing of clang stderr/stdout and exposing compile errors * support rpaths in ELF linker code @@ -27,8 +30,6 @@ * support cross compiling stage2 with `zig build` * --main-pkg-path * audit the CLI options for stage2 - * `zig init-lib` - * `zig init-exe` * restore error messages for stage2_add_link_lib * audit the base cache hash * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process. @@ -56,10 +57,6 @@ * libc_installation.zig: make it look for msvc only if msvc abi is chosen * switch the default C ABI for windows to be mingw-w64 * change glibc log errors to normal exposed compile errors - * update Package to use Compilation.Directory in create() - - skip LLD caching when bin directory is not in the cache (so we don't put `id.txt` into the cwd) - (maybe make it an explicit option and have main.zig disable it) - - make it possible for Package to not openDir and reference already existing resources. * improve Directory.join to only use 1 allocation in a clean way. * tracy builds with lc++ * some kind of "zig identifier escape" function rather than unconditionally using @"" syntax diff --git a/src/main.zig b/src/main.zig index c35586e925..3faa8b62a1 100644 --- a/src/main.zig +++ b/src/main.zig @@ -140,6 +140,10 @@ pub fn mainArgs(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v return cmdFmt(gpa, cmd_args); } else if (mem.eql(u8, cmd, "libc")) { return cmdLibC(gpa, cmd_args); + } else if (mem.eql(u8, cmd, "init-exe")) { + return cmdInit(gpa, arena, cmd_args, .Exe); + } else if (mem.eql(u8, cmd, "init-lib")) { + return cmdInit(gpa, arena, cmd_args, .Lib); } else if (mem.eql(u8, cmd, "targets")) { const info = try detectNativeTargetInfo(arena, .{}); const stdout = io.getStdOut().outStream(); @@ -1520,6 +1524,97 @@ pub fn cmdLibC(gpa: *Allocator, args: []const []const u8) !void { } } +pub const usage_init = + \\Usage: zig init-exe + \\ zig init-lib + \\ + \\ Initializes a `zig build` project in the current working + \\ directory. + \\ + \\Options: + \\ --help Print this help and exit + \\ + \\ +; + +pub fn cmdInit( + gpa: *Allocator, + arena: *Allocator, + args: []const []const u8, + output_mode: std.builtin.OutputMode, +) !void { + { + var i: usize = 0; + while (i < args.len) : (i += 1) { + const arg = args[i]; + if (mem.startsWith(u8, arg, "-")) { + if (mem.eql(u8, arg, "--help")) { + try io.getStdOut().writeAll(usage_init); + process.exit(0); + } else { + fatal("unrecognized parameter: '{}'", .{arg}); + } + } else { + fatal("unexpected extra parameter: '{}'", .{arg}); + } + } + } + const self_exe_path = try fs.selfExePathAlloc(arena); + var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { + fatal("unable to find zig installation directory: {}\n", .{@errorName(err)}); + }; + defer zig_lib_directory.handle.close(); + + const s = fs.path.sep_str; + const template_sub_path = switch (output_mode) { + .Obj => unreachable, + .Lib => "std" ++ s ++ "special" ++ s ++ "init-lib", + .Exe => "std" ++ s ++ "special" ++ s ++ "init-exe", + }; + var template_dir = try zig_lib_directory.handle.openDir(template_sub_path, .{}); + defer template_dir.close(); + + const cwd_path = try process.getCwdAlloc(arena); + const cwd_basename = fs.path.basename(cwd_path); + + const max_bytes = 10 * 1024 * 1024; + const build_zig_contents = template_dir.readFileAlloc(arena, "build.zig", max_bytes) catch |err| { + fatal("unable to read template file 'build.zig': {}", .{@errorName(err)}); + }; + var modified_build_zig_contents = std.ArrayList(u8).init(arena); + try modified_build_zig_contents.ensureCapacity(build_zig_contents.len); + for (build_zig_contents) |c| { + if (c == '$') { + try modified_build_zig_contents.appendSlice(cwd_basename); + } else { + try modified_build_zig_contents.append(c); + } + } + const main_zig_contents = template_dir.readFileAlloc(arena, "src" ++ s ++ "main.zig", max_bytes) catch |err| { + fatal("unable to read template file 'main.zig': {}", .{@errorName(err)}); + }; + if (fs.cwd().access("build.zig", .{})) |_| { + fatal("existing build.zig file would be overwritten", .{}); + } else |err| switch (err) { + error.FileNotFound => {}, + else => fatal("unable to test existence of build.zig: {}\n", .{@errorName(err)}), + } + var src_dir = try fs.cwd().makeOpenPath("src", .{}); + defer src_dir.close(); + + try src_dir.writeFile("main.zig", main_zig_contents); + try fs.cwd().writeFile("build.zig", modified_build_zig_contents.items); + + std.log.info("Created build.zig", .{}); + std.log.info("Created src" ++ s ++ "main.zig", .{}); + + switch (output_mode) { + .Lib => std.log.info("Next, try `zig build --help` or `zig build test`", .{}), + .Exe => std.log.info("Next, try `zig build --help` or `zig build run`", .{}), + .Obj => unreachable, + } +} + pub const usage_fmt = \\Usage: zig fmt [file]... \\