Skip to content

Commit 70e1b77

Browse files
committed
build system: implement --release[=mode]
This allows a `zig build` command to specify intention to create a release build, regardless of what per-project options exist. It also allows the command to specify a "preferred optimization mode", which is chosen if the project itself does not choose one (in other words, the project gets first choice). If neither the build command nor the project specify a preferred release mode, an error occurs.
1 parent 826f5e3 commit 70e1b77

File tree

2 files changed

+45
-8
lines changed

2 files changed

+45
-8
lines changed

lib/build_runner.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ pub fn main() !void {
131131
} else if (mem.startsWith(u8, arg, "-fno-sys=")) {
132132
const name = arg["-fno-sys=".len..];
133133
graph.system_library_options.put(arena, name, .user_disabled) catch @panic("OOM");
134+
} else if (mem.eql(u8, arg, "--release")) {
135+
builder.release_mode = .any;
136+
} else if (mem.startsWith(u8, arg, "--release=")) {
137+
const text = arg["--release=".len..];
138+
builder.release_mode = std.meta.stringToEnum(std.Build.ReleaseMode, text) orelse {
139+
fatalWithHint("expected [off|any|fast|safe|small] in '{s}', found '{s}'", .{
140+
arg, text,
141+
});
142+
};
134143
} else if (mem.eql(u8, arg, "--host-target")) {
135144
graph.host_query_options.arch_os_abi = nextArgOrFatal(args, &arg_idx);
136145
} else if (mem.eql(u8, arg, "--host-cpu")) {
@@ -1049,6 +1058,9 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
10491058
\\ --prefix-exe-dir [path] Where to put installed executables
10501059
\\ --prefix-include-dir [path] Where to put installed C header files
10511060
\\
1061+
\\ --release[=mode] Request release mode, optionally specifying a
1062+
\\ preferred optimization mode: fast, safe, small
1063+
\\
10521064
\\ --sysroot [path] Set the system root directory (usually /)
10531065
\\ --search-prefix [path] Add a path to look for binaries, libraries, headers
10541066
\\ --libc [file] Provide a file which specifies libc paths

lib/std/Build.zig

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ initialized_deps: *InitializedDepMap,
9696
/// A mapping from dependency names to package hashes.
9797
available_deps: AvailableDeps,
9898

99+
release_mode: ReleaseMode,
100+
101+
pub const ReleaseMode = enum {
102+
off,
103+
any,
104+
fast,
105+
safe,
106+
small,
107+
};
108+
99109
/// Shared state among all Build instances.
100110
/// Settings that are here rather than in Build are not configurable per-package.
101111
pub const Graph = struct {
@@ -295,6 +305,7 @@ pub fn create(
295305
.named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(arena),
296306
.initialized_deps = initialized_deps,
297307
.available_deps = available_deps,
308+
.release_mode = .off,
298309
};
299310
try self.top_level_steps.put(arena, self.install_tls.step.name, &self.install_tls);
300311
try self.top_level_steps.put(arena, self.uninstall_tls.step.name, &self.uninstall_tls);
@@ -386,6 +397,7 @@ fn createChildOnly(
386397
.named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator),
387398
.initialized_deps = parent.initialized_deps,
388399
.available_deps = pkg_deps,
400+
.release_mode = parent.release_mode,
389401
};
390402
try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls);
391403
try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls);
@@ -1230,20 +1242,33 @@ pub const StandardOptimizeOptionOptions = struct {
12301242
preferred_optimize_mode: ?std.builtin.OptimizeMode = null,
12311243
};
12321244

1233-
pub fn standardOptimizeOption(self: *Build, options: StandardOptimizeOptionOptions) std.builtin.OptimizeMode {
1245+
pub fn standardOptimizeOption(b: *Build, options: StandardOptimizeOptionOptions) std.builtin.OptimizeMode {
12341246
if (options.preferred_optimize_mode) |mode| {
1235-
if (self.option(bool, "release", "optimize for end users") orelse false) {
1247+
if (b.option(bool, "release", "optimize for end users") orelse (b.release_mode != .off)) {
12361248
return mode;
12371249
} else {
12381250
return .Debug;
12391251
}
1240-
} else {
1241-
return self.option(
1242-
std.builtin.OptimizeMode,
1243-
"optimize",
1244-
"Prioritize performance, safety, or binary size (-O flag)",
1245-
) orelse .Debug;
12461252
}
1253+
1254+
if (b.option(
1255+
std.builtin.OptimizeMode,
1256+
"optimize",
1257+
"Prioritize performance, safety, or binary size (-O flag)",
1258+
)) |mode| {
1259+
return mode;
1260+
}
1261+
1262+
return switch (b.release_mode) {
1263+
.off => .Debug,
1264+
.any => {
1265+
std.debug.print("the project does not declare a preferred optimization mode. choose: --release=fast, --release=safe, or --release=small\n", .{});
1266+
process.exit(1);
1267+
},
1268+
.fast => .ReleaseFast,
1269+
.safe => .ReleaseSafe,
1270+
.small => .ReleaseSmall,
1271+
};
12471272
}
12481273

12491274
pub const StandardTargetOptionsArgs = struct {

0 commit comments

Comments
 (0)