diff --git a/lib/std/build.zig b/lib/std/build.zig index 2c7a0da53a..3538629144 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1692,8 +1692,6 @@ pub const LibExeObjStep = struct { self.main_pkg_path = dir_path; } - pub const setDisableGenH = @compileError("deprecated; set the emit_h field directly"); - pub fn setLibCFile(self: *LibExeObjStep, libc_file: ?[]const u8) void { self.libc_file = libc_file; } @@ -2067,10 +2065,8 @@ pub const LibExeObjStep = struct { } switch (self.build_mode) { - .Debug => {}, - .ReleaseSafe => zig_args.append("--release-safe") catch unreachable, - .ReleaseFast => zig_args.append("--release-fast") catch unreachable, - .ReleaseSmall => zig_args.append("--release-small") catch unreachable, + .Debug => {}, // Skip since it's the default. + else => zig_args.append(builder.fmt("-O{s}", .{@tagName(self.build_mode)})) catch unreachable, } try zig_args.append("--cache-dir"); diff --git a/lib/std/zig.zig b/lib/std/zig.zig index b6dfada6cc..fc173ecda9 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -64,17 +64,21 @@ pub fn lineDelta(source: []const u8, start: usize, end: usize) isize { return line; } -/// Returns the standard file system basename of a binary generated by the Zig compiler. -pub fn binNameAlloc( - allocator: *std.mem.Allocator, +pub const BinNameOptions = struct { root_name: []const u8, target: std.Target, output_mode: std.builtin.OutputMode, - link_mode: ?std.builtin.LinkMode, - object_format: ?std.Target.ObjectFormat, -) error{OutOfMemory}![]u8 { - switch (object_format orelse target.getObjectFormat()) { - .coff, .pe => switch (output_mode) { + link_mode: ?std.builtin.LinkMode = null, + object_format: ?std.Target.ObjectFormat = null, + version: ?std.builtin.Version = null, +}; + +/// Returns the standard file system basename of a binary generated by the Zig compiler. +pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 { + const root_name = options.root_name; + const target = options.target; + switch (options.object_format orelse target.getObjectFormat()) { + .coff, .pe => switch (options.output_mode) { .Exe => { const suffix = switch (target.os.tag) { .uefi => ".efi", @@ -83,7 +87,7 @@ pub fn binNameAlloc( return std.fmt.allocPrint(allocator, "{}{}", .{ root_name, suffix }); }, .Lib => { - const suffix = switch (link_mode orelse .Static) { + const suffix = switch (options.link_mode orelse .Static) { .Static => ".lib", .Dynamic => ".dll", }; @@ -91,21 +95,30 @@ pub fn binNameAlloc( }, .Obj => return std.fmt.allocPrint(allocator, "{}.obj", .{root_name}), }, - .elf => switch (output_mode) { + .elf => switch (options.output_mode) { .Exe => return allocator.dupe(u8, root_name), .Lib => { - const suffix = switch (link_mode orelse .Static) { - .Static => ".a", - .Dynamic => ".so", - }; - return std.fmt.allocPrint(allocator, "{}{}{}", .{ target.libPrefix(), root_name, suffix }); + switch (options.link_mode orelse .Static) { + .Static => return std.fmt.allocPrint(allocator, "{}{}.a", .{ + target.libPrefix(), root_name, + }), + .Dynamic => { + if (options.version) |ver| { + return std.fmt.allocPrint(allocator, "{}{}.so.{}.{}.{}", .{ + target.libPrefix(), root_name, ver.major, ver.minor, ver.patch, + }); + } else { + return std.fmt.allocPrint(allocator, "{}{}.so", .{ target.libPrefix(), root_name }); + } + }, + } }, .Obj => return std.fmt.allocPrint(allocator, "{}.o", .{root_name}), }, - .macho => switch (output_mode) { + .macho => switch (options.output_mode) { .Exe => return allocator.dupe(u8, root_name), .Lib => { - const suffix = switch (link_mode orelse .Static) { + const suffix = switch (options.link_mode orelse .Static) { .Static => ".a", .Dynamic => ".dylib", }; diff --git a/src/Compilation.zig b/src/Compilation.zig index 03da22d80c..bdd11abc20 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2562,7 +2562,11 @@ pub fn build_crt_file( defer tracy.end(); const target = comp.getTarget(); - const basename = try std.zig.binNameAlloc(comp.gpa, root_name, target, output_mode, null, null); + const basename = try std.zig.binNameAlloc(comp.gpa, .{ + .root_name = root_name, + .target = target, + .output_mode = output_mode, + }); errdefer comp.gpa.free(basename); // TODO: This is extracted into a local variable to work around a stage1 miscompilation. diff --git a/src/libcxx.zig b/src/libcxx.zig index 4fbca42875..16c9581f82 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -88,7 +88,12 @@ pub fn buildLibCXX(comp: *Compilation) !void { const output_mode = .Lib; const link_mode = .Static; const target = comp.getTarget(); - const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null); + const basename = try std.zig.binNameAlloc(arena, .{ + .root_name = root_name, + .target = target, + .output_mode = output_mode, + .link_mode = link_mode, + }); const emit_bin = Compilation.EmitLoc{ .directory = null, // Put it in the cache directory. @@ -205,7 +210,12 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { const output_mode = .Lib; const link_mode = .Static; const target = comp.getTarget(); - const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null); + const basename = try std.zig.binNameAlloc(arena, .{ + .root_name = root_name, + .target = target, + .output_mode = output_mode, + .link_mode = link_mode, + }); const emit_bin = Compilation.EmitLoc{ .directory = null, // Put it in the cache directory. diff --git a/src/libunwind.zig b/src/libunwind.zig index 28445b7284..cbe632ba94 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -23,13 +23,16 @@ pub fn buildStaticLib(comp: *Compilation) !void { const output_mode = .Lib; const link_mode = .Static; const target = comp.getTarget(); - const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null); - + const basename = try std.zig.binNameAlloc(arena, .{ + .root_name = root_name, + .target = target, + .output_mode = output_mode, + .link_mode = link_mode, + }); const emit_bin = Compilation.EmitLoc{ .directory = null, // Put it in the cache directory. .basename = basename, }; - const unwind_src_list = [_][]const u8{ "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "libunwind.cpp", "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-EHABI.cpp", @@ -40,7 +43,6 @@ pub fn buildStaticLib(comp: *Compilation) !void { "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S", "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S", }; - var c_source_files: [unwind_src_list.len]Compilation.CSourceFile = undefined; for (unwind_src_list) |unwind_src, i| { var cflags = std.ArrayList([]const u8).init(arena); diff --git a/src/main.zig b/src/main.zig index be2c55f828..fe4c27ced6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -210,11 +210,10 @@ const usage_build_generic = \\ small|kernel| \\ medium|large] \\ --name [name] Override root name (not a file path) - \\ --mode [mode] Set the build mode - \\ Debug (default) optimizations off, safety on - \\ ReleaseFast Optimizations on, safety off - \\ ReleaseSafe Optimizations on, safety on - \\ ReleaseSmall Optimize for small binary, safety off + \\ -ODebug (default) optimizations off, safety on + \\ -OReleaseFast Optimizations on, safety off + \\ -OReleaseSafe Optimizations on, safety on + \\ -OReleaseSmall Optimize for small binary, safety off \\ --pkg-begin [name] [path] Make pkg available to import and push current pkg \\ --pkg-end Pop current pkg \\ --main-pkg-path Set the directory of the root package @@ -307,7 +306,7 @@ pub fn buildOutputType( }, ) !void { var color: Color = .Auto; - var build_mode: std.builtin.Mode = .Debug; + var optimize_mode: std.builtin.Mode = .Debug; var provided_name: ?[]const u8 = null; var link_mode: ?std.builtin.LinkMode = null; var dll_export_fns: ?bool = null; @@ -416,20 +415,23 @@ pub fn buildOutputType( switch (arg_mode) { .build, .translate_c, .zig_test, .run => { + var optimize_mode_string: ?[]const u8 = null; output_mode = switch (arg_mode) { .build => |m| m, .translate_c => .Obj, .zig_test, .run => .Exe, else => unreachable, }; - switch (arg_mode) { - .build => switch (output_mode) { - .Exe => emit_h = .no, - .Obj, .Lib => emit_h = .yes_default_path, - }, - .translate_c, .zig_test, .run => emit_h = .no, - else => unreachable, - } + // TODO finish self-hosted and add support for emitting C header files + emit_h = .no; + //switch (arg_mode) { + // .build => switch (output_mode) { + // .Exe => emit_h = .no, + // .Obj, .Lib => emit_h = .yes_default_path, + // }, + // .translate_c, .zig_test, .run => emit_h = .no, + // else => unreachable, + //} const args = all_args[2..]; var i: usize = 0; while (i < args.len) : (i += 1) { @@ -498,23 +500,10 @@ pub fn buildOutputType( } else { fatal("expected [auto|on|off] after --color, found '{}'", .{next_arg}); } - } else if (mem.eql(u8, arg, "--mode")) { - if (i + 1 >= args.len) { - fatal("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode", .{}); - } + } else if (mem.eql(u8, arg, "-O")) { + if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); i += 1; - const next_arg = args[i]; - if (mem.eql(u8, next_arg, "Debug")) { - build_mode = .Debug; - } else if (mem.eql(u8, next_arg, "ReleaseSafe")) { - build_mode = .ReleaseSafe; - } else if (mem.eql(u8, next_arg, "ReleaseFast")) { - build_mode = .ReleaseFast; - } else if (mem.eql(u8, next_arg, "ReleaseSmall")) { - build_mode = .ReleaseSmall; - } else { - fatal("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode, found '{}'", .{next_arg}); - } + optimize_mode_string = args[i]; } else if (mem.eql(u8, arg, "--stack")) { if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); i += 1; @@ -583,6 +572,8 @@ pub fn buildOutputType( target_mcpu = arg["-mcpu=".len..]; } else if (mem.startsWith(u8, arg, "-mcmodel=")) { machine_code_model = parseCodeModel(arg["-mcmodel=".len..]); + } else if (mem.startsWith(u8, arg, "-O")) { + optimize_mode_string = arg["-O".len..]; } else if (mem.eql(u8, arg, "--dynamic-linker")) { if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); i += 1; @@ -749,6 +740,10 @@ pub fn buildOutputType( }, } } + if (optimize_mode_string) |s| { + optimize_mode = std.meta.stringToEnum(std.builtin.Mode, s) orelse + fatal("unrecognized optimization mode: '{}'", .{s}); + } }, .cc, .cpp => { emit_h = .no; @@ -826,16 +821,16 @@ pub fn buildOutputType( .optimize => { // Alright, what release mode do they want? if (mem.eql(u8, it.only_arg, "Os")) { - build_mode = .ReleaseSmall; + optimize_mode = .ReleaseSmall; } else if (mem.eql(u8, it.only_arg, "O2") or mem.eql(u8, it.only_arg, "O3") or mem.eql(u8, it.only_arg, "O4")) { - build_mode = .ReleaseFast; + optimize_mode = .ReleaseFast; } else if (mem.eql(u8, it.only_arg, "Og") or mem.eql(u8, it.only_arg, "O0")) { - build_mode = .Debug; + optimize_mode = .Debug; } else { try clang_argv.appendSlice(it.other_args); } @@ -999,8 +994,8 @@ pub fn buildOutputType( } if (want_sanitize_c) |wsc| { - if (wsc and build_mode == .ReleaseFast) { - build_mode = .ReleaseSafe; + if (wsc and optimize_mode == .ReleaseFast) { + optimize_mode = .ReleaseSafe; } } @@ -1177,6 +1172,7 @@ pub fn buildOutputType( defer if (cleanup_emit_bin_dir) |*dir| dir.close(); const have_enable_cache = enable_cache orelse false; + const optional_version = if (have_version) version else null; const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) { .no => null, @@ -1193,14 +1189,14 @@ pub fn buildOutputType( }, } }, - .basename = try std.zig.binNameAlloc( - arena, - root_name, - target_info.target, - output_mode, - link_mode, - object_format, - ), + .basename = try std.zig.binNameAlloc(arena, .{ + .root_name = root_name, + .target = target_info.target, + .output_mode = output_mode, + .link_mode = link_mode, + .object_format = object_format, + .version = optional_version, + }), }, .yes => |full_path| b: { const basename = fs.path.basename(full_path); @@ -1374,7 +1370,7 @@ pub fn buildOutputType( .link_mode = link_mode, .dll_export_fns = dll_export_fns, .object_format = object_format, - .optimize_mode = build_mode, + .optimize_mode = optimize_mode, .keep_source_files_loaded = zir_out_path != null, .clang_argv = clang_argv.items, .lld_argv = lld_argv.items, @@ -1411,7 +1407,7 @@ pub fn buildOutputType( .self_exe_path = self_exe_path, .rand = &default_prng.random, .clang_passthrough_mode = arg_mode != .build, - .version = if (have_version) version else null, + .version = optional_version, .libc_installation = if (libc_installation) |*lci| lci else null, .verbose_cc = verbose_cc, .verbose_link = verbose_link, @@ -1977,7 +1973,11 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v const cross_target: std.zig.CrossTarget = .{}; const target_info = try detectNativeTargetInfo(gpa, cross_target); - const exe_basename = try std.zig.binNameAlloc(arena, "build", target_info.target, .Exe, null, null); + const exe_basename = try std.zig.binNameAlloc(arena, .{ + .root_name = "build", + .target = target_info.target, + .output_mode = .Exe, + }); const emit_bin: Compilation.EmitLoc = .{ .directory = null, // Use the local zig-cache. .basename = exe_basename, diff --git a/src/test.zig b/src/test.zig index 558fe3e95d..8ad11efa9c 100644 --- a/src/test.zig +++ b/src/test.zig @@ -469,7 +469,12 @@ pub const TestContext = struct { }; const ofmt: ?std.builtin.ObjectFormat = if (case.cbe) .c else null; - const bin_name = try std.zig.binNameAlloc(arena, "test_case", target, case.output_mode, null, ofmt); + const bin_name = try std.zig.binNameAlloc(arena, .{ + .root_name = "test_case", + .target = target, + .output_mode = case.output_mode, + .object_format = ofmt, + }); const emit_directory: Compilation.Directory = .{ .path = bogus_path,