From 24a9a42966dc9c0654314ad99866699208776025 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 May 2017 17:34:21 -0400 Subject: [PATCH] add safe release build mode closes #288 --- src/all_types.hpp | 8 ++- src/codegen.cpp | 46 +++++++----- src/codegen.hpp | 3 +- src/ir.cpp | 1 - src/link.cpp | 4 +- src/main.cpp | 16 +++-- std/build.zig | 104 ++++++++++++++++++---------- std/hash_map.zig | 2 +- std/special/build_file_template.zig | 14 +++- std/special/builtin.zig | 2 +- test/tests.zig | 40 ++++++----- 11 files changed, 151 insertions(+), 89 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 99ad25a3dd..6be77d19f0 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1297,6 +1297,12 @@ struct TimeEvent { const char *name; }; +enum BuildMode { + BuildModeDebug, + BuildModeFastRelease, + BuildModeSafeRelease, +}; + struct CodeGen { LLVMModuleRef module; ZigList errors; @@ -1392,7 +1398,7 @@ struct CodeGen { Buf *dynamic_linker; Buf *ar_path; Buf triple_str; - bool is_release_build; + BuildMode build_mode; bool is_test_build; uint32_t target_os_index; uint32_t target_arch_index; diff --git a/src/codegen.cpp b/src/codegen.cpp index 7a2c95d1b0..4d7398c7b5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -55,11 +55,12 @@ static PackageTableEntry *new_package(const char *root_src_dir, const char *root return entry; } -CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type) { +CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode) { CodeGen *g = allocate(1); codegen_add_time_event(g, "Initialize"); + g->build_mode = build_mode; g->out_type = out_type; g->import_table.init(32); g->builtin_fn_table.init(32); @@ -72,7 +73,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out g->memoized_fn_eval_table.init(16); g->exported_symbol_names.init(8); g->external_prototypes.init(8); - g->is_release_build = false; g->is_test_build = false; g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); @@ -154,10 +154,6 @@ void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) { g->clang_argv_len = len; } -void codegen_set_is_release(CodeGen *g, bool is_release_build) { - g->is_release_build = is_release_build; -} - void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt) { g->omit_zigrt = omit_zigrt; } @@ -393,7 +389,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { } if (fn_table_entry->body_node != nullptr) { - bool want_fn_safety = !g->is_release_build && !fn_table_entry->def_scope->safety_off; + bool want_fn_safety = g->build_mode != BuildModeFastRelease && !fn_table_entry->def_scope->safety_off; if (want_fn_safety) { if (g->link_libc) { addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong"); @@ -407,7 +403,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value); } addLLVMFnAttr(fn_table_entry->llvm_value, "nounwind"); - if (!g->is_release_build && fn_table_entry->fn_inline != FnInlineAlways) { + if (g->build_mode == BuildModeDebug && fn_table_entry->fn_inline != FnInlineAlways) { ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true"); ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim-non-leaf", nullptr); } @@ -440,7 +436,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { unsigned scope_line = line_number; bool is_definition = fn_table_entry->body_node != nullptr; unsigned flags = 0; - bool is_optimized = g->is_release_build; + bool is_optimized = g->build_mode != BuildModeDebug; bool is_internal_linkage = (fn_table_entry->linkage == GlobalLinkageIdInternal); ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder, get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "", @@ -555,7 +551,7 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntr } static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) { - if (g->is_release_build) + if (g->build_mode == BuildModeFastRelease) return false; // TODO memoize @@ -725,7 +721,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMSetLinkage(fn_val, LLVMInternalLinkage); LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv); addLLVMFnAttr(fn_val, "nounwind"); - if (!g->is_release_build) { + if (g->build_mode == BuildModeDebug) { ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr); } @@ -1697,7 +1693,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable, if (!type_has_bits(var->value->type)) return nullptr; - if (var->ref_count == 0 && g->is_release_build) + if (var->ref_count == 0 && g->build_mode != BuildModeDebug) return nullptr; IrInstruction *init_value = decl_var_instruction->init_value; @@ -3926,7 +3922,7 @@ static void do_code_gen(CodeGen *g) { os_path_join(g->cache_dir, o_basename, output_path); ensure_cache_dir(g); if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), - LLVMObjectFile, &err_msg, !g->is_release_build)) + LLVMObjectFile, &err_msg, g->build_mode == BuildModeDebug)) { zig_panic("unable to write object file: %s", err_msg); } @@ -4320,6 +4316,15 @@ static const char *bool_to_str(bool b) { return b ? "true" : "false"; } +static const char *build_mode_to_str(BuildMode build_mode) { + switch (build_mode) { + case BuildModeDebug: return "Mode.Debug"; + case BuildModeSafeRelease: return "Mode.ReleaseSafe"; + case BuildModeFastRelease: return "Mode.ReleaseFast"; + } + zig_unreachable(); +} + static void define_builtin_compile_vars(CodeGen *g) { if (g->std_package == nullptr) return; @@ -4428,13 +4433,21 @@ static void define_builtin_compile_vars(CodeGen *g) { " SeqCst,\n" "};\n\n"); } + { + buf_appendf(contents, + "pub const Mode = enum {\n" + " Debug,\n" + " ReleaseSafe,\n" + " ReleaseFast,\n" + "};\n\n"); + } buf_appendf(contents, "pub const is_big_endian = %s;\n", bool_to_str(g->is_big_endian)); - buf_appendf(contents, "pub const is_release = %s;\n", bool_to_str(g->is_release_build)); buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build)); buf_appendf(contents, "pub const os = Os.%s;\n", cur_os); buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch); buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ); buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt); + buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode)); { buf_appendf(contents, "pub const link_libs = [][]const u8 {\n"); @@ -4484,8 +4497,8 @@ static void init(CodeGen *g) { zig_panic("unable to create target based on: %s", buf_ptr(&g->triple_str)); } - - LLVMCodeGenOptLevel opt_level = g->is_release_build ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone; + bool is_optimized = g->build_mode != BuildModeDebug; + LLVMCodeGenOptLevel opt_level = is_optimized ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone; LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC; @@ -4518,7 +4531,6 @@ static void init(CodeGen *g) { Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING); - bool is_optimized = g->is_release_build; const char *flags = ""; unsigned runtime_version = 0; ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name), diff --git a/src/codegen.hpp b/src/codegen.hpp index 013a28dd0f..cbe9fcfce1 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -14,10 +14,9 @@ #include -CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type); +CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode); void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); -void codegen_set_is_release(CodeGen *codegen, bool is_release); void codegen_set_is_test(CodeGen *codegen, bool is_test); void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); diff --git a/src/ir.cpp b/src/ir.cpp index ebe5ada52e..7f12c4dfa4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -4649,7 +4649,6 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod if (init_value == irb->codegen->invalid_instruction) return init_value; - IrInstruction *result = ir_build_var_decl(irb, scope, node, var, type_instruction, init_value); var->decl_instruction = result; return result; diff --git a/src/link.cpp b/src/link.cpp index 5e1d2cce3a..09bea8a999 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -37,7 +37,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) { os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path); ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; - CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj); + CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode); child_gen->link_libc = parent_gen->link_libc; child_gen->link_libs.resize(parent_gen->link_libs.length); @@ -50,8 +50,6 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) { codegen_set_cache_dir(child_gen, parent_gen->cache_dir); - codegen_set_is_release(child_gen, parent_gen->is_release_build); - codegen_set_strip(child_gen, parent_gen->strip_debug_symbols); codegen_set_is_static(child_gen, parent_gen->is_static); diff --git a/src/main.cpp b/src/main.cpp index ef09be4775..ae0f747d1e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,7 +38,8 @@ static int usage(const char *arg0) { " --output-h [file] override generated header file path\n" " --pkg-begin [name] [path] make package available to import and push current pkg\n" " --pkg-end pop current pkg\n" - " --release build with optimizations on and debug protection off\n" + " --release-fast build with optimizations on and safety off\n" + " --release-safe build with optimizations on and safety on\n" " --static output will be statically linked\n" " --strip exclude debug symbols\n" " --target-arch [name] specify target architecture\n" @@ -161,7 +162,6 @@ int main(int argc, char **argv) { const char *in_file = nullptr; const char *out_file = nullptr; const char *out_file_h = nullptr; - bool is_release_build = false; bool strip = false; bool is_static = false; OutType out_type = OutTypeUnknown; @@ -201,6 +201,7 @@ int main(int argc, char **argv) { bool timing_info = false; const char *cache_dir = nullptr; CliPkg *cur_pkg = allocate(1); + BuildMode build_mode = BuildModeDebug; if (argc >= 2 && strcmp(argv[1], "build") == 0) { const char *zig_exe_path = arg0; @@ -237,7 +238,7 @@ int main(int argc, char **argv) { } } - CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe); + CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug); codegen_set_out_name(g, buf_create_from_str("build")); codegen_set_verbose(g, verbose); @@ -319,8 +320,10 @@ int main(int argc, char **argv) { char *arg = argv[i]; if (arg[0] == '-') { - if (strcmp(arg, "--release") == 0) { - is_release_build = true; + if (strcmp(arg, "--release-fast") == 0) { + build_mode = BuildModeFastRelease; + } else if (strcmp(arg, "--release-safe") == 0) { + build_mode = BuildModeSafeRelease; } else if (strcmp(arg, "--strip") == 0) { strip = true; } else if (strcmp(arg, "--static") == 0) { @@ -569,10 +572,9 @@ int main(int argc, char **argv) { buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir), full_cache_dir); - CodeGen *g = codegen_create(zig_root_source_file, target, out_type); + CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode); codegen_set_out_name(g, buf_out_name); codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); - codegen_set_is_release(g, is_release_build); codegen_set_is_test(g, cmd == CmdTest); codegen_set_linker_script(g, linker_script); codegen_set_cache_dir(g, full_cache_dir); diff --git a/std/build.zig b/std/build.zig index 939b4e8d57..4001aa4259 100644 --- a/std/build.zig +++ b/std/build.zig @@ -405,6 +405,23 @@ pub const Builder = struct { return &step_info.step; } + pub fn standardReleaseOptions(self: &Builder) -> builtin.Mode { + const release_safe = self.option(bool, "release-safe", "optimizations on and safety on") ?? false; + const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") ?? false; + + if (release_safe and !release_fast) { + return builtin.Mode.ReleaseSafe; + } else if (release_fast and !release_safe) { + return builtin.Mode.ReleaseFast; + } else if (!release_fast and !release_safe) { + return builtin.Mode.Debug; + } else { + %%io.stderr.printf("Both -Drelease-safe and -Drelease-fast specified"); + self.markInvalidUserInput(); + return builtin.Mode.Debug; + } + } + pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool { test (%%self.user_input_options.put(name, UserInputOption { .name = name, @@ -667,7 +684,7 @@ pub const LibExeObjStep = struct { linker_script: ?[]const u8, link_libs: BufSet, verbose: bool, - release: bool, + build_mode: builtin.Mode, static: bool, output_path: ?[]const u8, output_h_path: ?[]const u8, @@ -724,7 +741,7 @@ pub const LibExeObjStep = struct { var self = LibExeObjStep { .builder = builder, .verbose = false, - .release = false, + .build_mode = builtin.Mode.Debug, .static = static, .kind = kind, .root_src = root_src, @@ -794,8 +811,8 @@ pub const LibExeObjStep = struct { self.verbose = value; } - pub fn setRelease(self: &LibExeObjStep, value: bool) { - self.release = value; + pub fn setBuildMode(self: &LibExeObjStep, mode: builtin.Mode) { + self.build_mode = mode; } pub fn setOutputPath(self: &LibExeObjStep, value: []const u8) { @@ -886,8 +903,10 @@ pub const LibExeObjStep = struct { %%zig_args.append("--verbose"); } - if (self.release) { - %%zig_args.append("--release"); + switch (self.build_mode) { + builtin.Mode.Debug => {}, + builtin.Mode.ReleaseSafe => %%zig_args.append("--release-safe"), + builtin.Mode.ReleaseFast => %%zig_args.append("--release-fast"), } %%zig_args.append("--cache-dir"); @@ -980,7 +999,7 @@ pub const TestStep = struct { step: Step, builder: &Builder, root_src: []const u8, - release: bool, + build_mode: builtin.Mode, verbose: bool, link_libs: BufSet, name_prefix: []const u8, @@ -992,7 +1011,7 @@ pub const TestStep = struct { .step = Step.init(step_name, builder.allocator, make), .builder = builder, .root_src = root_src, - .release = false, + .build_mode = builtin.Mode.Debug, .verbose = false, .name_prefix = "", .filter = null, @@ -1004,8 +1023,8 @@ pub const TestStep = struct { self.verbose = value; } - pub fn setRelease(self: &TestStep, value: bool) { - self.release = value; + pub fn setBuildMode(self: &TestStep, mode: builtin.Mode) { + self.build_mode = mode; } pub fn linkSystemLibrary(self: &TestStep, name: []const u8) { @@ -1034,8 +1053,10 @@ pub const TestStep = struct { %%zig_args.append("--verbose"); } - if (self.release) { - %%zig_args.append("--release"); + switch (self.build_mode) { + builtin.Mode.Debug => {}, + builtin.Mode.ReleaseSafe => %%zig_args.append("--release-safe"), + builtin.Mode.ReleaseFast => %%zig_args.append("--release-fast"), } test (self.filter) |filter| { @@ -1095,6 +1116,8 @@ pub const CLibExeObjStep = struct { name_only_filename: []const u8, object_src: []const u8, kind: Kind, + build_mode: builtin.Mode, + strip: bool, const Kind = enum { Exe, @@ -1147,6 +1170,8 @@ pub const CLibExeObjStep = struct { .major_only_filename = undefined, .name_only_filename = undefined, .object_src = undefined, + .build_mode = builtin.Mode.Debug, + .strip = false, }; clib.computeOutFileNames(); return clib; @@ -1233,13 +1258,8 @@ pub const CLibExeObjStep = struct { %%self.include_dirs.append(path); } - pub fn addCompileFlagsForRelease(self: &CLibExeObjStep, release: bool) { - if (release) { - %%self.cflags.append("-g"); - %%self.cflags.append("-O2"); - } else { - %%self.cflags.append("-g"); - } + pub fn setBuildMode(self: &CLibExeObjStep, build_mode: builtin.Mode) { + self.build_mode = build_mode; } pub fn addCompileFlags(self: &CLibExeObjStep, flags: []const []const u8) { @@ -1248,6 +1268,34 @@ pub const CLibExeObjStep = struct { } } + fn appendCompileFlags(self: &CLibExeObjStep, args: &List([]const u8)) { + if (!self.strip) { + %%args.append("-g"); + } + switch (self.build_mode) { + builtin.Mode.Debug => {}, + builtin.Mode.ReleaseSafe => { + %%args.append("-O2"); + %%args.append("-D_FORTIFY_SOURCE=2"); + %%args.append("-fstack-protector-strong"); + %%args.append("--param"); + %%args.append("ssp-buffer-size=4"); + }, + builtin.Mode.ReleaseFast => { + %%args.append("-O2"); + }, + } + + for (self.include_dirs.toSliceConst()) |dir| { + %%args.append("-I"); + %%args.append(self.builder.pathFromRoot(dir)); + } + + for (self.cflags.toSliceConst()) |cflag| { + %%args.append(cflag); + } + } + fn make(step: &Step) -> %void { const self = @fieldParentPtr(CLibExeObjStep, "step", step); const cc = os.getEnv("CC") ?? "cc"; @@ -1265,14 +1313,7 @@ pub const CLibExeObjStep = struct { %%cc_args.append("-o"); %%cc_args.append(output_path); - for (self.cflags.toSliceConst()) |cflag| { - %%cc_args.append(cflag); - } - - for (self.include_dirs.toSliceConst()) |dir| { - %%cc_args.append("-I"); - %%cc_args.append(builder.pathFromRoot(dir)); - } + self.appendCompileFlags(&cc_args); %return builder.spawnChild(cc, cc_args.toSliceConst()); }, @@ -1295,14 +1336,7 @@ pub const CLibExeObjStep = struct { %%cc_args.append("-o"); %%cc_args.append(cache_o_file); - for (self.cflags.toSliceConst()) |cflag| { - %%cc_args.append(cflag); - } - - for (self.include_dirs.toSliceConst()) |dir| { - %%cc_args.append("-I"); - %%cc_args.append(builder.pathFromRoot(dir)); - } + self.appendCompileFlags(&cc_args); %return builder.spawnChild(cc, cc_args.toSliceConst()); diff --git a/std/hash_map.zig b/std/hash_map.zig index 7bec4b9df5..67b8fb1206 100644 --- a/std/hash_map.zig +++ b/std/hash_map.zig @@ -5,7 +5,7 @@ const mem = @import("mem.zig"); const Allocator = mem.Allocator; const builtin = @import("builtin"); -const want_modification_safety = !builtin.is_release; +const want_modification_safety = builtin.mode != builtin.Mode.ReleaseFast; const debug_u32 = if (want_modification_safety) u32 else void; pub fn HashMap(comptime K: type, comptime V: type, diff --git a/std/special/build_file_template.zig b/std/special/build_file_template.zig index dfb2efeec4..02872945a6 100644 --- a/std/special/build_file_template.zig +++ b/std/special/build_file_template.zig @@ -1,10 +1,20 @@ const Builder = @import("std").build.Builder; +const Mode = @import("builtin").Mode; pub fn build(b: &Builder) { - const release = b.option(bool, "release", "optimizations on and safety off") ?? false; + const release_safe = b.option(bool, "--release-safe", "optimizations on and safety on") ?? false; + const release_fast = b.option(bool, "--release-fast", "optimizations on and safety off") ?? false; + + const build_mode = if (release_safe) { + Mode.ReleaseSafe + } else if (release_fast) { + Mode.ReleaseFast + } else { + Mode.Debug + }; const exe = b.addExecutable("YOUR_NAME_HERE", "src/main.zig"); - exe.setRelease(release); + exe.setBuildMode(build_mode); b.default_step.dependOn(&exe.step); } diff --git a/std/special/builtin.zig b/std/special/builtin.zig index 271b3936cd..38100329e3 100644 --- a/std/special/builtin.zig +++ b/std/special/builtin.zig @@ -32,7 +32,7 @@ export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) { } export fn __stack_chk_fail() { - if (builtin.is_release) { + if (builtin.mode == builtin.Mode.ReleaseFast) { @setGlobalLinkage(__stack_chk_fail, builtin.GlobalLinkage.Internal); unreachable; } diff --git a/test/tests.zig b/test/tests.zig index fa5aea10eb..ac442e8f61 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -9,6 +9,7 @@ const io = std.io; const mem = std.mem; const fmt = std.fmt; const List = std.list.List; +const Mode = @import("builtin").Mode; const compare_output = @import("compare_output.zig"); const build_examples = @import("build_examples.zig"); @@ -107,14 +108,13 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons name:[] const u8, desc: []const u8) -> &build.Step { const step = b.step(b.fmt("test-{}", name), desc); - for ([]bool{false, true}) |release| { + for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| { for ([]bool{false, true}) |link_libc| { const these_tests = b.addTest(root_src); - these_tests.setNamePrefix(b.fmt("{}-{}-{} ", name, - if (release) "release" else "debug", + these_tests.setNamePrefix(b.fmt("{}-{}-{} ", name, @enumTagName(mode), if (link_libc) "c" else "bare")); these_tests.setFilter(test_filter); - these_tests.setRelease(release); + these_tests.setBuildMode(mode); if (link_libc) { these_tests.linkSystemLibrary("c"); } @@ -372,9 +372,9 @@ pub const CompareOutputContext = struct { self.step.dependOn(&run_and_cmp_output.step); }, Special.None => { - for ([]bool{false, true}) |release| { + for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| { const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})", - "compare-output", case.name, if (release) "release" else "debug"); + "compare-output", case.name, @enumTagName(mode)); test (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; @@ -382,7 +382,7 @@ pub const CompareOutputContext = struct { const exe = b.addExecutable("test", root_src); exe.setOutputPath(exe_path); - exe.setRelease(release); + exe.setBuildMode(mode); if (case.link_libc) { exe.linkSystemLibrary("c"); } @@ -465,10 +465,10 @@ pub const CompileErrorContext = struct { name: []const u8, test_index: usize, case: &const TestCase, - release: bool, + build_mode: Mode, pub fn create(context: &CompileErrorContext, name: []const u8, - case: &const TestCase, release: bool) -> &CompileCmpOutputStep + case: &const TestCase, build_mode: Mode) -> &CompileCmpOutputStep { const allocator = context.b.allocator; const ptr = %%allocator.create(CompileCmpOutputStep); @@ -478,7 +478,7 @@ pub const CompileErrorContext = struct { .name = name, .test_index = context.test_index, .case = case, - .release = release, + .build_mode = build_mode, }; context.test_index += 1; return ptr; @@ -501,8 +501,10 @@ pub const CompileErrorContext = struct { %%zig_args.append("--output"); %%zig_args.append(b.pathFromRoot(obj_path)); - if (self.release) { - %%zig_args.append("--release"); + switch (self.build_mode) { + Mode.Debug => {}, + Mode.ReleaseSafe => %%zig_args.append("--release-safe"), + Mode.ReleaseFast => %%zig_args.append("--release-fast"), } %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name); @@ -620,15 +622,15 @@ pub const CompileErrorContext = struct { pub fn addCase(self: &CompileErrorContext, case: &const TestCase) { const b = self.b; - for ([]bool{false, true}) |release| { + for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| { const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})", - case.name, if (release) "release" else "debug"); + case.name, @enumTagName(mode)); test (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } - const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, release); + const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode); self.step.dependOn(&compile_and_cmp_errors.step); for (case.sources.toSliceConst()) |src_file| { @@ -657,7 +659,7 @@ pub const BuildExamplesContext = struct { pub fn addBuildFile(self: &BuildExamplesContext, build_file: []const u8) { const b = self.b; - const annotated_case_name = b.fmt("build {} (debug)", build_file); + const annotated_case_name = b.fmt("build {} (Debug)", build_file); test (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) return; @@ -686,16 +688,16 @@ pub const BuildExamplesContext = struct { pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) { const b = self.b; - for ([]bool{false, true}) |release| { + for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| { const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})", - root_src, if (release) "release" else "debug"); + root_src, @enumTagName(mode)); test (self.test_filter) |filter| { if (mem.indexOf(u8, annotated_case_name, filter) == null) continue; } const exe = b.addExecutable("test", root_src); - exe.setRelease(release); + exe.setBuildMode(mode); if (link_libc) { exe.linkSystemLibrary("c"); }