authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-16 12:46:39-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-18 16:52:43-07:00
logcaddbbc315e834241c6ae7e22434b574c589e5fc
treefe412c607e0e4a21a8f43da130335ace3c4fe304
parent10132126972604c4636b148df27ab7fe9e50136b

build: avoid compiling self-hosted twice

build.zig: add a 'compile' step to compile the self-hosted compiler without installing it. Compilation: set cache mode to whole when using the LLVM backend and --enable-cache is passed. This makes `zig build` act the same as it does with stage1. Upside is that a second invocation of `zig build` on an unmodified source tree will avoid redoing the compilation again. Downside is that it will proliferate more garbage in the project-local cache (same as stage1). This can eventually be fixed when Zig's incremental compilation is more robust; we can go back to having LLVM use CacheMode.incremental and rely on it detecting no changes and avoiding doing the flush() step.

5 files changed, 20 insertions(+), 10 deletions(-)

CMakeLists.txt+2-2
...@@ -1045,7 +1045,7 @@ elseif(MINGW)...@@ -1045,7 +1045,7 @@ elseif(MINGW)
1045 target_link_libraries(zig2 ntdll)1045 target_link_libraries(zig2 ntdll)
1046endif()1046endif()
10471047
1048set(ZIG_BUILD_ARGS "build"1048set(ZIG_BUILD_ARGS
1049 --zig-lib-dir "${CMAKE_SOURCE_DIR}/lib"1049 --zig-lib-dir "${CMAKE_SOURCE_DIR}/lib"
1050 "-Dconfig_h=${ZIG_CONFIG_H_OUT}"1050 "-Dconfig_h=${ZIG_CONFIG_H_OUT}"
1051 "-Denable-llvm"1051 "-Denable-llvm"
...@@ -1060,7 +1060,7 @@ set(ZIG_BUILD_ARGS "build"...@@ -1060,7 +1060,7 @@ set(ZIG_BUILD_ARGS "build"
1060)1060)
10611061
1062add_custom_target(stage3 ALL1062add_custom_target(stage3 ALL
1063 COMMAND zig2 ${ZIG_BUILD_ARGS}1063 COMMAND zig2 build compile ${ZIG_BUILD_ARGS}
1064 DEPENDS zig21064 DEPENDS zig2
1065 COMMENT STATUS "Building stage3"1065 COMMENT STATUS "Building stage3"
1066 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"1066 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
build.zig+4
...@@ -142,6 +142,10 @@ pub fn build(b: *Builder) !void {...@@ -142,6 +142,10 @@ pub fn build(b: *Builder) !void {
142 };142 };
143143
144 const exe = b.addExecutable("zig", main_file);144 const exe = b.addExecutable("zig", main_file);
145
146 const compile_step = b.step("compile", "Build the self-hosted compiler");
147 compile_step.dependOn(&exe.step);
148
145 exe.stack_size = stack_size;149 exe.stack_size = stack_size;
146 exe.strip = strip;150 exe.strip = strip;
147 exe.sanitize_thread = sanitize_thread;151 exe.sanitize_thread = sanitize_thread;
cmake/install.cmake+5-2
...@@ -1,5 +1,8 @@...@@ -1,5 +1,8 @@
1set(ZIG_INSTALL_ARGS ${ZIG_BUILD_ARGS} --prefix "${CMAKE_INSTALL_PREFIX}")1set(ZIG_INSTALL_ARGS build ${ZIG_BUILD_ARGS} --prefix "${CMAKE_INSTALL_PREFIX}")
2execute_process(COMMAND "${ZIG_EXECUTABLE}" ${ZIG_INSTALL_ARGS} WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE _result)2execute_process(
3 COMMAND "${ZIG_EXECUTABLE}" ${ZIG_INSTALL_ARGS}
4 WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
5 RESULT_VARIABLE _result)
36
4if(_result)7if(_result)
5 message("::")8 message("::")
src/Compilation.zig+8-5
...@@ -1109,11 +1109,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1109,11 +1109,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
11091109
1110 const use_stage1 = options.use_stage1 orelse false;1110 const use_stage1 = options.use_stage1 orelse false;
11111111
1112 const cache_mode = if (use_stage1 and !options.disable_lld_caching)
1113 CacheMode.whole
1114 else
1115 options.cache_mode;
1116
1117 // Make a decision on whether to use LLVM or our own backend.1112 // Make a decision on whether to use LLVM or our own backend.
1118 const use_llvm = build_options.have_llvm and blk: {1113 const use_llvm = build_options.have_llvm and blk: {
1119 if (options.use_llvm) |explicit|1114 if (options.use_llvm) |explicit|
...@@ -1154,6 +1149,14 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1154,6 +1149,14 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1154 }1149 }
1155 }1150 }
11561151
1152 // TODO: once we support incremental compilation for the LLVM backend via
1153 // saving the LLVM module into a bitcode file and restoring it, along with
1154 // compiler state, the second clause here can be removed so that incremental
1155 // cache mode is used for LLVM backend too. We need some fuzz testing before
1156 // that can be enabled.
1157 const cache_mode = if ((use_stage1 and !options.disable_lld_caching) or
1158 (use_llvm and !options.disable_lld_caching)) CacheMode.whole else options.cache_mode;
1159
1157 const tsan = options.want_tsan orelse false;1160 const tsan = options.want_tsan orelse false;
1158 // TSAN is implemented in C++ so it requires linking libc++.1161 // TSAN is implemented in C++ so it requires linking libc++.
1159 const link_libcpp = options.link_libcpp or tsan;1162 const link_libcpp = options.link_libcpp or tsan;
src/link/Elf.zig+1-1
...@@ -1282,7 +1282,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1282,7 +1282,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1282 // linked are in the hash that namespaces the directory we are outputting to. Therefore,1282 // linked are in the hash that namespaces the directory we are outputting to. Therefore,
1283 // we must hash those now, and the resulting digest will form the "id" of the linking1283 // we must hash those now, and the resulting digest will form the "id" of the linking
1284 // job we are about to perform.1284 // job we are about to perform.
1285 // After a successful link, we store the id in the metadata of a symlink named "id.txt" in1285 // After a successful link, we store the id in the metadata of a symlink named "lld.id" in
1286 // the artifact directory. So, now, we check if this symlink exists, and if it matches1286 // the artifact directory. So, now, we check if this symlink exists, and if it matches
1287 // our digest. If so, we can skip linking. Otherwise, we proceed with invoking LLD.1287 // our digest. If so, we can skip linking. Otherwise, we proceed with invoking LLD.
1288 const id_symlink_basename = "lld.id";1288 const id_symlink_basename = "lld.id";