From 6ab9268a9024fe8e9076f07cb207107d2cad0876 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 24 Dec 2020 14:11:58 -0700 Subject: [PATCH] stage2: re-use compiler runtime libs across opt modes and strip flag Previously Zig would need to recompile runtime libs if you changed the values of --strip or -O. Now, unless the `debug_compiler_runtime_libs` flag is set (which is currently not exposed to the CLI), Zig will always choose ReleaseFast or ReleaseSmall for compiler runtime libraries. When the main application chooses ReleaseFast or ReleaseSmall, that value is propagated to compiler runtime libraries. Otherwise a decision is made based on the target, which is currently ReleaseSmall for freestanding WebAssembly and ReleaseFast for everything else. Ultimately the purpose of this commit is to have Debug and ReleaseSafe builds of applications still get optimized builds of, e.g. libcxx and libunwind, as well as to spend less time unnecessarily rebuilding compiler runtime libraries. --- src/Compilation.zig | 42 ++++++++++++++++++++++++++++++------------ src/glibc.zig | 12 ++---------- src/libcxx.zig | 13 ++++--------- src/libtsan.zig | 16 ++-------------- src/libunwind.zig | 4 ++-- src/mingw.zig | 9 --------- src/musl.zig | 4 ++-- src/target.zig | 8 ++++++++ 8 files changed, 50 insertions(+), 58 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index 010ac96b6f5b5ef411a25882812bd00c6e629e4f..885ecbb95c7aa06bd59da0d4953e04c8051c6977 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -131,6 +131,7 @@ mutex: std.Mutex = .{}, test_filter: ?[]const u8, test_name_prefix: ?[]const u8, test_evented_io: bool, +debug_compiler_runtime_libs: bool, emit_asm: ?EmitLoc, emit_llvm_ir: ?EmitLoc, @@ -429,6 +430,7 @@ pub const InitOptions = struct { verbose_llvm_cpu_features: bool = false, is_test: bool = false, test_evented_io: bool = false, + debug_compiler_runtime_libs: bool = false, /// Normally when you create a `Compilation`, Zig will automatically build /// and link in required dependencies, such as compiler-rt and libc. When /// building such dependencies themselves, this flag must be set to avoid @@ -1025,6 +1027,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .test_filter = options.test_filter, .test_name_prefix = options.test_name_prefix, .test_evented_io = options.test_evented_io, + .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs, .work_queue_wait_group = undefined, }; break :comp comp; @@ -2891,14 +2894,6 @@ fn buildOutputFromZig( .directory = null, // Put it in the cache directory. .basename = bin_basename, }; - const optimize_mode: std.builtin.Mode = blk: { - if (comp.bin_file.options.is_test) - break :blk comp.bin_file.options.optimize_mode; - switch (comp.bin_file.options.optimize_mode) { - .Debug, .ReleaseFast, .ReleaseSafe => break :blk .ReleaseFast, - .ReleaseSmall => break :blk .ReleaseSmall, - } - }; const sub_compilation = try Compilation.create(comp.gpa, .{ .global_cache_directory = comp.global_cache_directory, .local_cache_directory = comp.global_cache_directory, @@ -2910,7 +2905,7 @@ fn buildOutputFromZig( .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, - .optimize_mode = optimize_mode, + .optimize_mode = comp.compilerRtOptMode(), .link_mode = .Static, .function_sections = true, .want_sanitize_c = false, @@ -2920,7 +2915,7 @@ fn buildOutputFromZig( .want_pic = comp.bin_file.options.pic, .want_pie = comp.bin_file.options.pie, .emit_h = null, - .strip = comp.bin_file.options.strip, + .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, .self_exe_path = comp.self_exe_path, @@ -3289,7 +3284,7 @@ pub fn build_crt_file( .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, - .optimize_mode = comp.bin_file.options.optimize_mode, + .optimize_mode = comp.compilerRtOptMode(), .want_sanitize_c = false, .want_stack_check = false, .want_valgrind = false, @@ -3297,7 +3292,7 @@ pub fn build_crt_file( .want_pic = comp.bin_file.options.pic, .want_pie = comp.bin_file.options.pie, .emit_h = null, - .strip = comp.bin_file.options.strip, + .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, .self_exe_path = comp.self_exe_path, @@ -3344,3 +3339,26 @@ pub fn stage1AddLinkLib(comp: *Compilation, lib_name: []const u8) !void { }); } } + +/// This decides the optimization mode for all zig-provided libraries, including +/// compiler-rt, libcxx, libc, libunwind, etc. +pub fn compilerRtOptMode(comp: Compilation) std.builtin.Mode { + if (comp.debug_compiler_runtime_libs) { + return comp.bin_file.options.optimize_mode; + } + switch (comp.bin_file.options.optimize_mode) { + .Debug, .ReleaseSafe => return target_util.defaultCompilerRtOptimizeMode(comp.getTarget()), + .ReleaseFast => return .ReleaseFast, + .ReleaseSmall => return .ReleaseSmall, + } +} + +/// This decides whether to strip debug info for all zig-provided libraries, including +/// compiler-rt, libcxx, libc, libunwind, etc. +pub fn compilerRtStrip(comp: Compilation) bool { + if (comp.debug_compiler_runtime_libs) { + return comp.bin_file.options.strip; + } else { + return true; + } +} diff --git a/src/glibc.zig b/src/glibc.zig index 2e42cef519b092bf163001461a25ec80fb853625..0c2787272057cc9bfd5ae37837be5ed99e15d90c 100644 --- a/src/glibc.zig +++ b/src/glibc.zig @@ -271,7 +271,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { try lib_path(comp, arena, lib_libc_glibc ++ "include" ++ path.sep_str ++ "libc-symbols.h"), "-DTOP_NAMESPACE=glibc", "-DASSEMBLER", - "-g", "-Wa,--noexecstack", }); return comp.build_crt_file("crti", .Obj, &[1]Compilation.CSourceFile{ @@ -291,7 +290,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { try lib_path(comp, arena, lib_libc_glibc ++ "include" ++ path.sep_str ++ "libc-symbols.h"), "-DTOP_NAMESPACE=glibc", "-DASSEMBLER", - "-g", "-Wa,--noexecstack", }); return comp.build_crt_file("crtn", .Obj, &[1]Compilation.CSourceFile{ @@ -317,7 +315,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { "-DSHARED", "-DTOP_NAMESPACE=glibc", "-DASSEMBLER", - "-g", "-Wa,--noexecstack", }); break :blk .{ @@ -337,7 +334,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { "-DMODULE_NAME=libc", "-DTOP_NAMESPACE=glibc", "-DASSEMBLER", - "-g", "-Wa,--noexecstack", }); break :blk .{ @@ -372,8 +368,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { try args.appendSlice(&[_][]const u8{ "-std=gnu11", "-fgnu89-inline", - "-g", - "-O2", "-fmerge-all-constants", "-fno-stack-protector", "-fmath-errno", @@ -409,8 +403,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { try args.appendSlice(&[_][]const u8{ "-std=gnu11", "-fgnu89-inline", - "-g", - "-O2", "-fmerge-all-constants", "-fno-stack-protector", "-fmath-errno", @@ -939,13 +931,13 @@ fn buildSharedLib( .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, - .optimize_mode = comp.bin_file.options.optimize_mode, + .optimize_mode = comp.compilerRtOptMode(), .want_sanitize_c = false, .want_stack_check = false, .want_valgrind = false, .want_tsan = false, .emit_h = null, - .strip = comp.bin_file.options.strip, + .strip = comp.compilerRtStrip(), .is_native_os = false, .is_native_abi = false, .self_exe_path = comp.self_exe_path, diff --git a/src/libcxx.zig b/src/libcxx.zig index 47bf93dee3709671bd514960d58dcded2333637d..e79a0106e902763ff52a60c835098d115ea6c6a5 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -138,7 +138,6 @@ pub fn buildLibCXX(comp: *Compilation) !void { try cflags.append("-I"); try cflags.append(cxxabi_include_path); - try cflags.append("-O3"); if (target_util.supports_fpic(target)) { try cflags.append("-fPIC"); } @@ -164,7 +163,7 @@ pub fn buildLibCXX(comp: *Compilation) !void { .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, - .optimize_mode = comp.bin_file.options.optimize_mode, + .optimize_mode = comp.compilerRtOptMode(), .link_mode = link_mode, .want_sanitize_c = false, .want_stack_check = false, @@ -173,7 +172,7 @@ pub fn buildLibCXX(comp: *Compilation) !void { .want_pic = comp.bin_file.options.pic, .want_pie = comp.bin_file.options.pie, .emit_h = null, - .strip = comp.bin_file.options.strip, + .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, .self_exe_path = comp.self_exe_path, @@ -256,16 +255,12 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { try cflags.append("-I"); try cflags.append(cxx_include_path); - try cflags.append("-O3"); - try cflags.append("-DNDEBUG"); if (target_util.supports_fpic(target)) { try cflags.append("-fPIC"); } try cflags.append("-nostdinc++"); try cflags.append("-fstrict-aliasing"); try cflags.append("-funwind-tables"); - try cflags.append("-D_DEBUG"); - try cflags.append("-UNDEBUG"); try cflags.append("-std=c++11"); c_source_files[i] = .{ @@ -285,7 +280,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, - .optimize_mode = comp.bin_file.options.optimize_mode, + .optimize_mode = comp.compilerRtOptMode(), .link_mode = link_mode, .want_sanitize_c = false, .want_stack_check = false, @@ -294,7 +289,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { .want_pic = comp.bin_file.options.pic, .want_pie = comp.bin_file.options.pie, .emit_h = null, - .strip = comp.bin_file.options.strip, + .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, .self_exe_path = comp.self_exe_path, diff --git a/src/libtsan.zig b/src/libtsan.zig index ecf15693e159f87b9afa501e09d569bdec6406d1..d126d7313ab1e400dd3aba40cf89ba6e32007883 100644 --- a/src/libtsan.zig +++ b/src/libtsan.zig @@ -43,8 +43,6 @@ pub fn buildTsan(comp: *Compilation) !void { try cflags.append("-I"); try cflags.append(tsan_include_path); - try cflags.append("-O3"); - try cflags.append("-DNDEBUG"); try cflags.append("-nostdinc++"); try cflags.append("-fvisibility-inlines-hidden"); try cflags.append("-std=c++14"); @@ -67,8 +65,6 @@ pub fn buildTsan(comp: *Compilation) !void { try cflags.append("-I"); try cflags.append(tsan_include_path); - try cflags.append("-O3"); - try cflags.append("-DNDEBUG"); try cflags.append("-nostdinc++"); try cflags.append("-fvisibility-inlines-hidden"); try cflags.append("-std=c++14"); @@ -110,8 +106,6 @@ pub fn buildTsan(comp: *Compilation) !void { try cflags.append("-I"); try cflags.append(sanitizer_common_include_path); - try cflags.append("-O3"); - try cflags.append("-DNDEBUG"); try cflags.append("-nostdinc++"); try cflags.append("-fvisibility-inlines-hidden"); try cflags.append("-std=c++14"); @@ -136,8 +130,6 @@ pub fn buildTsan(comp: *Compilation) !void { try cflags.append("-I"); try cflags.append(sanitizer_common_include_path); - try cflags.append("-O3"); - try cflags.append("-DNDEBUG"); try cflags.append("-nostdinc++"); try cflags.append("-fvisibility-inlines-hidden"); try cflags.append("-std=c++14"); @@ -158,8 +150,6 @@ pub fn buildTsan(comp: *Compilation) !void { try cflags.append("-I"); try cflags.append(tsan_include_path); - try cflags.append("-O3"); - try cflags.append("-DNDEBUG"); try cflags.append("-nostdinc++"); try cflags.append("-fvisibility-inlines-hidden"); try cflags.append("-std=c++14"); @@ -188,8 +178,6 @@ pub fn buildTsan(comp: *Compilation) !void { try cflags.append("-I"); try cflags.append(tsan_include_path); - try cflags.append("-O3"); - try cflags.append("-DNDEBUG"); try cflags.append("-nostdinc++"); try cflags.append("-fvisibility-inlines-hidden"); try cflags.append("-std=c++14"); @@ -218,7 +206,7 @@ pub fn buildTsan(comp: *Compilation) !void { .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, - .optimize_mode = comp.bin_file.options.optimize_mode, + .optimize_mode = comp.compilerRtOptMode(), .link_mode = link_mode, .want_sanitize_c = false, .want_stack_check = false, @@ -227,7 +215,7 @@ pub fn buildTsan(comp: *Compilation) !void { .want_pic = true, .want_pie = true, .emit_h = null, - .strip = comp.bin_file.options.strip, + .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, .self_exe_path = comp.self_exe_path, diff --git a/src/libunwind.zig b/src/libunwind.zig index 057663a44b9c11c62c8ffba584b3ce364b25c66e..7710b1aa770b17ce1c74fbb4e532efa2bf9a4afd 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -104,7 +104,7 @@ pub fn buildStaticLib(comp: *Compilation) !void { .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, - .optimize_mode = comp.bin_file.options.optimize_mode, + .optimize_mode = comp.compilerRtOptMode(), .link_mode = link_mode, .want_sanitize_c = false, .want_stack_check = false, @@ -113,7 +113,7 @@ pub fn buildStaticLib(comp: *Compilation) !void { .want_pic = comp.bin_file.options.pic, .want_pie = comp.bin_file.options.pie, .emit_h = null, - .strip = comp.bin_file.options.strip, + .strip = comp.compilerRtStrip(), .is_native_os = comp.bin_file.options.is_native_os, .is_native_abi = comp.bin_file.options.is_native_abi, .self_exe_path = comp.self_exe_path, diff --git a/src/mingw.zig b/src/mingw.zig index 8c819627ba6603f7ccc23a41767c8a7ac1fb1202..a9e275434f31882bf9bd17d61759ab7e43d0e1e9 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -91,8 +91,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { "-D_CRTBLD", "-D_WIN32_WINNT=0x0f00", "-D__MSVCRT_VERSION__=0x700", - "-g", - "-O2", }); c_source_files[i] = .{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ @@ -119,9 +117,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { "-isystem", try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "any-windows-any" }), - - "-g", - "-O2", }); var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena); @@ -167,8 +162,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { "-D_CRTBLD", "-D_WIN32_WINNT=0x0f00", "-D__MSVCRT_VERSION__=0x700", - "-g", - "-O2", "-isystem", try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "any-windows-any" }), @@ -233,8 +226,6 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { "-D_CRTBLD", "-D_WIN32_WINNT=0x0f00", "-D__MSVCRT_VERSION__=0x700", - "-g", - "-O2", "-isystem", try comp.zig_lib_directory.join(arena, &[_][]const u8{ diff --git a/src/musl.zig b/src/musl.zig index 6680eabb03e30e61cdc944f2abda3f3c226e56dc..f67fe90addafff68358f14f04589d090525fcc7b 100644 --- a/src/musl.zig +++ b/src/musl.zig @@ -203,13 +203,13 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { .thread_pool = comp.thread_pool, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = Compilation.EmitLoc{ .directory = null, .basename = "libc.so" }, - .optimize_mode = comp.bin_file.options.optimize_mode, + .optimize_mode = comp.compilerRtOptMode(), .want_sanitize_c = false, .want_stack_check = false, .want_valgrind = false, .want_tsan = false, .emit_h = null, - .strip = comp.bin_file.options.strip, + .strip = comp.compilerRtStrip(), .is_native_os = false, .is_native_abi = false, .self_exe_path = comp.self_exe_path, diff --git a/src/target.zig b/src/target.zig index 9749675a898759c72a6beb15db6a3c19d7e8d9a9..b3c83c76d8f507f12e4e1e1d77c79e84f759fd2f 100644 --- a/src/target.zig +++ b/src/target.zig @@ -344,3 +344,11 @@ pub fn is_libcpp_lib_name(target: std.Target, name: []const u8) bool { pub fn hasDebugInfo(target: std.Target) bool { return !target.cpu.arch.isWasm(); } + +pub fn defaultCompilerRtOptimizeMode(target: std.Target) std.builtin.Mode { + if (target.cpu.arch.isWasm() and target.os.tag == .freestanding) { + return .ReleaseSmall; + } else { + return .ReleaseFast; + } +} -- 2.54.0