authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-24 23:50:15-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-24 23:50:15-07:00
log30dfdfdbd09570f97420413015eb8a1517382961
tree6e4e3f43eaa0f870629a9f969907e3adee8d1bfa
parent7964341c76fab985b06a5022b88ceb261305ffaf

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.

7 files changed, 107 insertions(+), 77 deletions(-)

lib/std/build.zig+2-6
......@@ -1692,8 +1692,6 @@ pub const LibExeObjStep = struct {
16921692 self.main_pkg_path = dir_path;
16931693 }
16941694
1695 pub const setDisableGenH = @compileError("deprecated; set the emit_h field directly");
1696
16971695 pub fn setLibCFile(self: *LibExeObjStep, libc_file: ?[]const u8) void {
16981696 self.libc_file = libc_file;
16991697 }
......@@ -2067,10 +2065,8 @@ pub const LibExeObjStep = struct {
20672065 }
20682066
20692067 switch (self.build_mode) {
2070 .Debug => {},
2071 .ReleaseSafe => zig_args.append("--release-safe") catch unreachable,
2072 .ReleaseFast => zig_args.append("--release-fast") catch unreachable,
2073 .ReleaseSmall => zig_args.append("--release-small") catch unreachable,
2068 .Debug => {}, // Skip since it's the default.
2069 else => zig_args.append(builder.fmt("-O{s}", .{@tagName(self.build_mode)})) catch unreachable,
20742070 }
20752071
20762072 try zig_args.append("--cache-dir");
lib/std/zig.zig+30-17
......@@ -64,17 +64,21 @@ pub fn lineDelta(source: []const u8, start: usize, end: usize) isize {
6464 return line;
6565}
6666
67/// Returns the standard file system basename of a binary generated by the Zig compiler.
68pub fn binNameAlloc(
69 allocator: *std.mem.Allocator,
67pub const BinNameOptions = struct {
7068 root_name: []const u8,
7169 target: std.Target,
7270 output_mode: std.builtin.OutputMode,
73 link_mode: ?std.builtin.LinkMode,
74 object_format: ?std.Target.ObjectFormat,
75) error{OutOfMemory}![]u8 {
76 switch (object_format orelse target.getObjectFormat()) {
77 .coff, .pe => switch (output_mode) {
71 link_mode: ?std.builtin.LinkMode = null,
72 object_format: ?std.Target.ObjectFormat = null,
73 version: ?std.builtin.Version = null,
74};
75
76/// Returns the standard file system basename of a binary generated by the Zig compiler.
77pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) error{OutOfMemory}![]u8 {
78 const root_name = options.root_name;
79 const target = options.target;
80 switch (options.object_format orelse target.getObjectFormat()) {
81 .coff, .pe => switch (options.output_mode) {
7882 .Exe => {
7983 const suffix = switch (target.os.tag) {
8084 .uefi => ".efi",
......@@ -83,7 +87,7 @@ pub fn binNameAlloc(
8387 return std.fmt.allocPrint(allocator, "{}{}", .{ root_name, suffix });
8488 },
8589 .Lib => {
86 const suffix = switch (link_mode orelse .Static) {
90 const suffix = switch (options.link_mode orelse .Static) {
8791 .Static => ".lib",
8892 .Dynamic => ".dll",
8993 };
......@@ -91,21 +95,30 @@ pub fn binNameAlloc(
9195 },
9296 .Obj => return std.fmt.allocPrint(allocator, "{}.obj", .{root_name}),
9397 },
94 .elf => switch (output_mode) {
98 .elf => switch (options.output_mode) {
9599 .Exe => return allocator.dupe(u8, root_name),
96100 .Lib => {
97 const suffix = switch (link_mode orelse .Static) {
98 .Static => ".a",
99 .Dynamic => ".so",
100 };
101 return std.fmt.allocPrint(allocator, "{}{}{}", .{ target.libPrefix(), root_name, suffix });
101 switch (options.link_mode orelse .Static) {
102 .Static => return std.fmt.allocPrint(allocator, "{}{}.a", .{
103 target.libPrefix(), root_name,
104 }),
105 .Dynamic => {
106 if (options.version) |ver| {
107 return std.fmt.allocPrint(allocator, "{}{}.so.{}.{}.{}", .{
108 target.libPrefix(), root_name, ver.major, ver.minor, ver.patch,
109 });
110 } else {
111 return std.fmt.allocPrint(allocator, "{}{}.so", .{ target.libPrefix(), root_name });
112 }
113 },
114 }
102115 },
103116 .Obj => return std.fmt.allocPrint(allocator, "{}.o", .{root_name}),
104117 },
105 .macho => switch (output_mode) {
118 .macho => switch (options.output_mode) {
106119 .Exe => return allocator.dupe(u8, root_name),
107120 .Lib => {
108 const suffix = switch (link_mode orelse .Static) {
121 const suffix = switch (options.link_mode orelse .Static) {
109122 .Static => ".a",
110123 .Dynamic => ".dylib",
111124 };
src/Compilation.zig+5-1
......@@ -2562,7 +2562,11 @@ pub fn build_crt_file(
25622562 defer tracy.end();
25632563
25642564 const target = comp.getTarget();
2565 const basename = try std.zig.binNameAlloc(comp.gpa, root_name, target, output_mode, null, null);
2565 const basename = try std.zig.binNameAlloc(comp.gpa, .{
2566 .root_name = root_name,
2567 .target = target,
2568 .output_mode = output_mode,
2569 });
25662570 errdefer comp.gpa.free(basename);
25672571
25682572 // TODO: This is extracted into a local variable to work around a stage1 miscompilation.
src/libcxx.zig+12-2
......@@ -88,7 +88,12 @@ pub fn buildLibCXX(comp: *Compilation) !void {
8888 const output_mode = .Lib;
8989 const link_mode = .Static;
9090 const target = comp.getTarget();
91 const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null);
91 const basename = try std.zig.binNameAlloc(arena, .{
92 .root_name = root_name,
93 .target = target,
94 .output_mode = output_mode,
95 .link_mode = link_mode,
96 });
9297
9398 const emit_bin = Compilation.EmitLoc{
9499 .directory = null, // Put it in the cache directory.
......@@ -205,7 +210,12 @@ pub fn buildLibCXXABI(comp: *Compilation) !void {
205210 const output_mode = .Lib;
206211 const link_mode = .Static;
207212 const target = comp.getTarget();
208 const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null);
213 const basename = try std.zig.binNameAlloc(arena, .{
214 .root_name = root_name,
215 .target = target,
216 .output_mode = output_mode,
217 .link_mode = link_mode,
218 });
209219
210220 const emit_bin = Compilation.EmitLoc{
211221 .directory = null, // Put it in the cache directory.
src/libunwind.zig+6-4
......@@ -23,13 +23,16 @@ pub fn buildStaticLib(comp: *Compilation) !void {
2323 const output_mode = .Lib;
2424 const link_mode = .Static;
2525 const target = comp.getTarget();
26 const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null);
27
26 const basename = try std.zig.binNameAlloc(arena, .{
27 .root_name = root_name,
28 .target = target,
29 .output_mode = output_mode,
30 .link_mode = link_mode,
31 });
2832 const emit_bin = Compilation.EmitLoc{
2933 .directory = null, // Put it in the cache directory.
3034 .basename = basename,
3135 };
32
3336 const unwind_src_list = [_][]const u8{
3437 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "libunwind.cpp",
3538 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-EHABI.cpp",
......@@ -40,7 +43,6 @@ pub fn buildStaticLib(comp: *Compilation) !void {
4043 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S",
4144 "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S",
4245 };
43
4446 var c_source_files: [unwind_src_list.len]Compilation.CSourceFile = undefined;
4547 for (unwind_src_list) |unwind_src, i| {
4648 var cflags = std.ArrayList([]const u8).init(arena);
src/main.zig+46-46
......@@ -210,11 +210,10 @@ const usage_build_generic =
210210 \\ small|kernel|
211211 \\ medium|large]
212212 \\ --name [name] Override root name (not a file path)
213 \\ --mode [mode] Set the build mode
214 \\ Debug (default) optimizations off, safety on
215 \\ ReleaseFast Optimizations on, safety off
216 \\ ReleaseSafe Optimizations on, safety on
217 \\ ReleaseSmall Optimize for small binary, safety off
213 \\ -ODebug (default) optimizations off, safety on
214 \\ -OReleaseFast Optimizations on, safety off
215 \\ -OReleaseSafe Optimizations on, safety on
216 \\ -OReleaseSmall Optimize for small binary, safety off
218217 \\ --pkg-begin [name] [path] Make pkg available to import and push current pkg
219218 \\ --pkg-end Pop current pkg
220219 \\ --main-pkg-path Set the directory of the root package
......@@ -307,7 +306,7 @@ pub fn buildOutputType(
307306 },
308307) !void {
309308 var color: Color = .Auto;
310 var build_mode: std.builtin.Mode = .Debug;
309 var optimize_mode: std.builtin.Mode = .Debug;
311310 var provided_name: ?[]const u8 = null;
312311 var link_mode: ?std.builtin.LinkMode = null;
313312 var dll_export_fns: ?bool = null;
......@@ -416,20 +415,23 @@ pub fn buildOutputType(
416415
417416 switch (arg_mode) {
418417 .build, .translate_c, .zig_test, .run => {
418 var optimize_mode_string: ?[]const u8 = null;
419419 output_mode = switch (arg_mode) {
420420 .build => |m| m,
421421 .translate_c => .Obj,
422422 .zig_test, .run => .Exe,
423423 else => unreachable,
424424 };
425 switch (arg_mode) {
426 .build => switch (output_mode) {
427 .Exe => emit_h = .no,
428 .Obj, .Lib => emit_h = .yes_default_path,
429 },
430 .translate_c, .zig_test, .run => emit_h = .no,
431 else => unreachable,
432 }
425 // TODO finish self-hosted and add support for emitting C header files
426 emit_h = .no;
427 //switch (arg_mode) {
428 // .build => switch (output_mode) {
429 // .Exe => emit_h = .no,
430 // .Obj, .Lib => emit_h = .yes_default_path,
431 // },
432 // .translate_c, .zig_test, .run => emit_h = .no,
433 // else => unreachable,
434 //}
433435 const args = all_args[2..];
434436 var i: usize = 0;
435437 while (i < args.len) : (i += 1) {
......@@ -498,23 +500,10 @@ pub fn buildOutputType(
498500 } else {
499501 fatal("expected [auto|on|off] after --color, found '{}'", .{next_arg});
500502 }
501 } else if (mem.eql(u8, arg, "--mode")) {
502 if (i + 1 >= args.len) {
503 fatal("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode", .{});
504 }
503 } else if (mem.eql(u8, arg, "-O")) {
504 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
505505 i += 1;
506 const next_arg = args[i];
507 if (mem.eql(u8, next_arg, "Debug")) {
508 build_mode = .Debug;
509 } else if (mem.eql(u8, next_arg, "ReleaseSafe")) {
510 build_mode = .ReleaseSafe;
511 } else if (mem.eql(u8, next_arg, "ReleaseFast")) {
512 build_mode = .ReleaseFast;
513 } else if (mem.eql(u8, next_arg, "ReleaseSmall")) {
514 build_mode = .ReleaseSmall;
515 } else {
516 fatal("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode, found '{}'", .{next_arg});
517 }
506 optimize_mode_string = args[i];
518507 } else if (mem.eql(u8, arg, "--stack")) {
519508 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
520509 i += 1;
......@@ -583,6 +572,8 @@ pub fn buildOutputType(
583572 target_mcpu = arg["-mcpu=".len..];
584573 } else if (mem.startsWith(u8, arg, "-mcmodel=")) {
585574 machine_code_model = parseCodeModel(arg["-mcmodel=".len..]);
575 } else if (mem.startsWith(u8, arg, "-O")) {
576 optimize_mode_string = arg["-O".len..];
586577 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
587578 if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg});
588579 i += 1;
......@@ -749,6 +740,10 @@ pub fn buildOutputType(
749740 },
750741 }
751742 }
743 if (optimize_mode_string) |s| {
744 optimize_mode = std.meta.stringToEnum(std.builtin.Mode, s) orelse
745 fatal("unrecognized optimization mode: '{}'", .{s});
746 }
752747 },
753748 .cc, .cpp => {
754749 emit_h = .no;
......@@ -826,16 +821,16 @@ pub fn buildOutputType(
826821 .optimize => {
827822 // Alright, what release mode do they want?
828823 if (mem.eql(u8, it.only_arg, "Os")) {
829 build_mode = .ReleaseSmall;
824 optimize_mode = .ReleaseSmall;
830825 } else if (mem.eql(u8, it.only_arg, "O2") or
831826 mem.eql(u8, it.only_arg, "O3") or
832827 mem.eql(u8, it.only_arg, "O4"))
833828 {
834 build_mode = .ReleaseFast;
829 optimize_mode = .ReleaseFast;
835830 } else if (mem.eql(u8, it.only_arg, "Og") or
836831 mem.eql(u8, it.only_arg, "O0"))
837832 {
838 build_mode = .Debug;
833 optimize_mode = .Debug;
839834 } else {
840835 try clang_argv.appendSlice(it.other_args);
841836 }
......@@ -999,8 +994,8 @@ pub fn buildOutputType(
999994 }
1000995
1001996 if (want_sanitize_c) |wsc| {
1002 if (wsc and build_mode == .ReleaseFast) {
1003 build_mode = .ReleaseSafe;
997 if (wsc and optimize_mode == .ReleaseFast) {
998 optimize_mode = .ReleaseSafe;
1004999 }
10051000 }
10061001
......@@ -1177,6 +1172,7 @@ pub fn buildOutputType(
11771172 defer if (cleanup_emit_bin_dir) |*dir| dir.close();
11781173
11791174 const have_enable_cache = enable_cache orelse false;
1175 const optional_version = if (have_version) version else null;
11801176
11811177 const emit_bin_loc: ?Compilation.EmitLoc = switch (emit_bin) {
11821178 .no => null,
......@@ -1193,14 +1189,14 @@ pub fn buildOutputType(
11931189 },
11941190 }
11951191 },
1196 .basename = try std.zig.binNameAlloc(
1197 arena,
1198 root_name,
1199 target_info.target,
1200 output_mode,
1201 link_mode,
1202 object_format,
1203 ),
1192 .basename = try std.zig.binNameAlloc(arena, .{
1193 .root_name = root_name,
1194 .target = target_info.target,
1195 .output_mode = output_mode,
1196 .link_mode = link_mode,
1197 .object_format = object_format,
1198 .version = optional_version,
1199 }),
12041200 },
12051201 .yes => |full_path| b: {
12061202 const basename = fs.path.basename(full_path);
......@@ -1374,7 +1370,7 @@ pub fn buildOutputType(
13741370 .link_mode = link_mode,
13751371 .dll_export_fns = dll_export_fns,
13761372 .object_format = object_format,
1377 .optimize_mode = build_mode,
1373 .optimize_mode = optimize_mode,
13781374 .keep_source_files_loaded = zir_out_path != null,
13791375 .clang_argv = clang_argv.items,
13801376 .lld_argv = lld_argv.items,
......@@ -1411,7 +1407,7 @@ pub fn buildOutputType(
14111407 .self_exe_path = self_exe_path,
14121408 .rand = &default_prng.random,
14131409 .clang_passthrough_mode = arg_mode != .build,
1414 .version = if (have_version) version else null,
1410 .version = optional_version,
14151411 .libc_installation = if (libc_installation) |*lci| lci else null,
14161412 .verbose_cc = verbose_cc,
14171413 .verbose_link = verbose_link,
......@@ -1977,7 +1973,11 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
19771973 const cross_target: std.zig.CrossTarget = .{};
19781974 const target_info = try detectNativeTargetInfo(gpa, cross_target);
19791975
1980 const exe_basename = try std.zig.binNameAlloc(arena, "build", target_info.target, .Exe, null, null);
1976 const exe_basename = try std.zig.binNameAlloc(arena, .{
1977 .root_name = "build",
1978 .target = target_info.target,
1979 .output_mode = .Exe,
1980 });
19811981 const emit_bin: Compilation.EmitLoc = .{
19821982 .directory = null, // Use the local zig-cache.
19831983 .basename = exe_basename,
src/test.zig+6-1
......@@ -469,7 +469,12 @@ pub const TestContext = struct {
469469 };
470470
471471 const ofmt: ?std.builtin.ObjectFormat = if (case.cbe) .c else null;
472 const bin_name = try std.zig.binNameAlloc(arena, "test_case", target, case.output_mode, null, ofmt);
472 const bin_name = try std.zig.binNameAlloc(arena, .{
473 .root_name = "test_case",
474 .target = target,
475 .output_mode = case.output_mode,
476 .object_format = ofmt,
477 });
473478
474479 const emit_directory: Compilation.Directory = .{
475480 .path = bogus_path,