fix a round of regressions in this branch

* Don't try to generate C header files yet since it will only cause a
   crash saying the feature is unimplemented.
 * Rename the CLI options for release modes to use the `-O` prefix to
   match C compiler precedent. Options are now `-ODebug`,
   `-OReleaseFast`, `-OReleaseSafe`, `-OReleaseSmall`. The optimization
   mode matches the enum tags of std.builtin.Mode. It is planned to, at
   some point, rename std.builtin.Mode to std.builtin.OptimizationMode
   and modify the tags to be lower case to match the style convention.
   - Update build.zig code to support this new CLI.
 * update std.zig.binNameAlloc to support an optional Version and update
   the implementation to correctly deal with dynamic library version
   suffixes.
This commit is contained in:
Andrew Kelley 2020-09-24 23:50:15 -07:00
parent 7964341c76
commit 30dfdfdbd0
7 changed files with 107 additions and 77 deletions

View File

@ -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");

View File

@ -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",
};

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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,

View File

@ -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,