add safe release build mode

closes #288
This commit is contained in:
Andrew Kelley 2017-05-02 17:34:21 -04:00
parent 7c236f6dd8
commit 24a9a42966
11 changed files with 151 additions and 89 deletions

View File

@ -1297,6 +1297,12 @@ struct TimeEvent {
const char *name;
};
enum BuildMode {
BuildModeDebug,
BuildModeFastRelease,
BuildModeSafeRelease,
};
struct CodeGen {
LLVMModuleRef module;
ZigList<ErrorMsg*> 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;

View File

@ -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<CodeGen>(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),

View File

@ -14,10 +14,9 @@
#include <stdio.h>
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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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