authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-21 20:29:42-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-22 00:16:27-07:00
log6e4fff6ba62ae3e61a948c98fa8fea7e35732cc0
tree017722866adaf7405fd5a2cc72bc0380334de060
parent1291f4aca46b2929d9ee9b265a2bfe5311e60861

move installation logic to the build script where it belongs

* build.zig: introduce `-Dflat` option which makes the installation match what we want to ship for our download tarballs. This allows deleting a bunch of shell script logic from the CI. - for example it puts the executable directly in prefix/zig rather than prefix/bin/zig and it additionally includes prefix/LICENSE. * build.zig: by default also install std lib documentation to doc/std/ - this can be disabled by `-Dno-autodocs` similar to how there is already `-Dno-langref`. * build.zig: add `std-docs` and `langref` steps which build and install the std lib autodocs and langref to prefix/doc/std and prefix/doc/langref.html, respectively. * std.Build: implement proper handling of `-femit-docs` using the LazyPath system. This is a breaking change. - this is a partial implementation of #16351 * frontend: fixed the handling of Autodocs with regards to caching and putting the artifacts in the proper location to integrate with the build system. - closes #15864 * CI: delete the logic for autodocs since it is now handled by build.zig and is enabled by default. - in the future we should strive to have nearly all the CI shell script logic deleted in favor of `zig build` commands. * CI: pass `-DZIG_NO_LIB=ON`/`-Dno-lib` except for the one command where we want to actually generate the langref and autodocs. Generating the langref takes 14 minutes right now (why?!) so we don't want to do that more times than necessary. * Autodoc: fixed use of a global variable. It works fine as a local variable instead. - note that in the future we will want to make Autodoc run simultaneously using the job system, but for now the principle of YAGNI dictates that we don't have an init()/deinit() API and instead simply call the function that does the things. * Autodoc: only do it when there are no compile errors

16 files changed, 215 insertions(+), 137 deletions(-)

build.zig+43-6
...@@ -24,12 +24,14 @@ pub fn build(b: *std.Build) !void {...@@ -24,12 +24,14 @@ pub fn build(b: *std.Build) !void {
2424
25 const optimize = b.standardOptimizeOption(.{});25 const optimize = b.standardOptimizeOption(.{});
2626
27 const flat = b.option(bool, "flat", "Put files into the installation prefix in a manner suited for upstream distribution rather than a posix file system hierarchy standard") orelse false;
27 const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode");28 const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode");
28 const use_zig_libcxx = b.option(bool, "use-zig-libcxx", "If libc++ is needed, use zig's bundled version, don't try to integrate with the system") orelse false;29 const use_zig_libcxx = b.option(bool, "use-zig-libcxx", "If libc++ is needed, use zig's bundled version, don't try to integrate with the system") orelse false;
2930
30 const test_step = b.step("test", "Run all the tests");31 const test_step = b.step("test", "Run all the tests");
31 const skip_install_lib_files = b.option(bool, "no-lib", "skip copying of lib/ files and langref to installation prefix. Useful for development") orelse false;32 const skip_install_lib_files = b.option(bool, "no-lib", "skip copying of lib/ files and langref to installation prefix. Useful for development") orelse false;
32 const skip_install_langref = b.option(bool, "no-langref", "skip copying of langref to the installation prefix") orelse skip_install_lib_files;33 const skip_install_langref = b.option(bool, "no-langref", "skip copying of langref to the installation prefix") orelse skip_install_lib_files;
34 const skip_install_autodocs = b.option(bool, "no-autodocs", "skip copying of standard library autodocs to the installation prefix") orelse skip_install_lib_files;
33 const no_bin = b.option(bool, "no-bin", "skip emitting compiler binary") orelse false;35 const no_bin = b.option(bool, "no-bin", "skip emitting compiler binary") orelse false;
3436
35 const docgen_exe = b.addExecutable(.{37 const docgen_exe = b.addExecutable(.{
...@@ -52,8 +54,34 @@ pub fn build(b: *std.Build) !void {...@@ -52,8 +54,34 @@ pub fn build(b: *std.Build) !void {
52 b.getInstallStep().dependOn(&install_langref.step);54 b.getInstallStep().dependOn(&install_langref.step);
53 }55 }
5456
55 const docs_step = b.step("docs", "Build documentation");57 const autodoc_test = b.addTest(.{
56 docs_step.dependOn(&docgen_cmd.step);58 .root_source_file = .{ .path = "lib/std/std.zig" },
59 .target = target,
60 });
61 autodoc_test.overrideZigLibDir("lib");
62 autodoc_test.emit_bin = .no_emit; // https://github.com/ziglang/zig/issues/16351
63 const install_std_docs = b.addInstallDirectory(.{
64 .source_dir = autodoc_test.getOutputDocs(),
65 .install_dir = .prefix,
66 .install_subdir = "doc/std",
67 });
68 if (!skip_install_autodocs) {
69 b.getInstallStep().dependOn(&install_std_docs.step);
70 }
71
72 if (flat) {
73 b.installFile("LICENSE", "LICENSE");
74 }
75
76 const langref_step = b.step("langref", "Build and install the language reference");
77 langref_step.dependOn(&install_langref.step);
78
79 const std_docs_step = b.step("std-docs", "Build and install the standard library documentation");
80 std_docs_step.dependOn(&install_std_docs.step);
81
82 const docs_step = b.step("docs", "Build and install documentation");
83 docs_step.dependOn(langref_step);
84 docs_step.dependOn(std_docs_step);
5785
58 const check_case_exe = b.addExecutable(.{86 const check_case_exe = b.addExecutable(.{
59 .name = "check-case",87 .name = "check-case",
...@@ -104,10 +132,10 @@ pub fn build(b: *std.Build) !void {...@@ -104,10 +132,10 @@ pub fn build(b: *std.Build) !void {
104 const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h");132 const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h");
105133
106 if (!skip_install_lib_files) {134 if (!skip_install_lib_files) {
107 b.installDirectory(InstallDirectoryOptions{135 b.installDirectory(.{
108 .source_dir = .{ .path = "lib" },136 .source_dir = .{ .path = "lib" },
109 .install_dir = .lib,137 .install_dir = if (flat) .prefix else .lib,
110 .install_subdir = "zig",138 .install_subdir = if (flat) "lib" else "zig",
111 .exclude_extensions = &[_][]const u8{139 .exclude_extensions = &[_][]const u8{
112 // exclude files from lib/std/compress/testdata140 // exclude files from lib/std/compress/testdata
113 ".gz",141 ".gz",
...@@ -167,6 +195,9 @@ pub fn build(b: *std.Build) !void {...@@ -167,6 +195,9 @@ pub fn build(b: *std.Build) !void {
167 exe.pie = pie;195 exe.pie = pie;
168 exe.sanitize_thread = sanitize_thread;196 exe.sanitize_thread = sanitize_thread;
169 exe.entitlements = entitlements;197 exe.entitlements = entitlements;
198 // TODO -femit-bin/-fno-emit-bin should be inferred by the build system
199 // based on whether or not the exe is run or installed.
200 // https://github.com/ziglang/zig/issues/16351
170 if (no_bin) exe.emit_bin = .no_emit;201 if (no_bin) exe.emit_bin = .no_emit;
171202
172 exe.build_id = b.option(203 exe.build_id = b.option(
...@@ -175,7 +206,13 @@ pub fn build(b: *std.Build) !void {...@@ -175,7 +206,13 @@ pub fn build(b: *std.Build) !void {
175 "Request creation of '.note.gnu.build-id' section",206 "Request creation of '.note.gnu.build-id' section",
176 );207 );
177208
178 b.installArtifact(exe);209 if (!no_bin) {
210 const install_exe = b.addInstallArtifact(exe);
211 if (flat) {
212 install_exe.dest_dir = .prefix;
213 }
214 b.getInstallStep().dependOn(&install_exe.step);
215 }
179216
180 test_step.dependOn(&exe.step);217 test_step.dependOn(&exe.step);
181218
ci/aarch64-linux-debug.sh+9-6
...@@ -40,6 +40,7 @@ cmake .. \...@@ -40,6 +40,7 @@ cmake .. \
40 -DZIG_TARGET_TRIPLE="$TARGET" \40 -DZIG_TARGET_TRIPLE="$TARGET" \
41 -DZIG_TARGET_MCPU="$MCPU" \41 -DZIG_TARGET_MCPU="$MCPU" \
42 -DZIG_STATIC=ON \42 -DZIG_STATIC=ON \
43 -DZIG_NO_LIB=ON \
43 -GNinja44 -GNinja
4445
45# Now cmake will use zig as the C/C++ compiler. We reset the environment variables46# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
...@@ -49,16 +50,18 @@ unset CXX...@@ -49,16 +50,18 @@ unset CXX
4950
50ninja install51ninja install
5152
53# TODO: move this to a build.zig step (check-fmt)
52echo "Looking for non-conforming code formatting..."54echo "Looking for non-conforming code formatting..."
53stage3-debug/bin/zig fmt --check .. \55stage3-debug/bin/zig fmt --check .. \
54 --exclude ../test/cases/ \56 --exclude ../test/cases/ \
55 --exclude ../build-debug57 --exclude ../build-debug
5658
57# simultaneously test building self-hosted without LLVM and with 32-bit arm59# simultaneously test building self-hosted without LLVM and with 32-bit arm
58stage3-debug/bin/zig build -Dtarget=arm-linux-musleabihf60stage3-debug/bin/zig build \
61 -Dtarget=arm-linux-musleabihf \
62 -Dno-lib
5963
60# TODO: add -fqemu back to this line64# TODO: add -fqemu back to this line
61
62stage3-debug/bin/zig build test docs \65stage3-debug/bin/zig build test docs \
63 --maxrss 24696061952 \66 --maxrss 24696061952 \
64 -fwasmtime \67 -fwasmtime \
...@@ -68,10 +71,8 @@ stage3-debug/bin/zig build test docs \...@@ -68,10 +71,8 @@ stage3-debug/bin/zig build test docs \
68 --zig-lib-dir "$(pwd)/../lib"71 --zig-lib-dir "$(pwd)/../lib"
6972
70# Look for HTML errors.73# Look for HTML errors.
71tidy --drop-empty-elements no -qe "stage3-debug/doc/langref.html"74# TODO: move this to a build.zig flag (-Denable-tidy)
7275tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
73# Produce the experimental std lib documentation.
74stage3-debug/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
7576
76# Ensure that updating the wasm binary from this commit will result in a viable build.77# Ensure that updating the wasm binary from this commit will result in a viable build.
77stage3-debug/bin/zig build update-zig178stage3-debug/bin/zig build update-zig1
...@@ -91,6 +92,7 @@ cmake .. \...@@ -91,6 +92,7 @@ cmake .. \
91 -DZIG_TARGET_TRIPLE="$TARGET" \92 -DZIG_TARGET_TRIPLE="$TARGET" \
92 -DZIG_TARGET_MCPU="$MCPU" \93 -DZIG_TARGET_MCPU="$MCPU" \
93 -DZIG_STATIC=ON \94 -DZIG_STATIC=ON \
95 -DZIG_NO_LIB=ON \
94 -GNinja96 -GNinja
9597
96unset CC98unset CC
...@@ -102,6 +104,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test...@@ -102,6 +104,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test
102stage3/bin/zig build -p stage4 \104stage3/bin/zig build -p stage4 \
103 -Dstatic-llvm \105 -Dstatic-llvm \
104 -Dtarget=native-native-musl \106 -Dtarget=native-native-musl \
107 -Dno-lib \
105 --search-prefix "$PREFIX" \108 --search-prefix "$PREFIX" \
106 --zig-lib-dir "$(pwd)/../lib"109 --zig-lib-dir "$(pwd)/../lib"
107stage4/bin/zig test ../test/behavior.zig -I../test110stage4/bin/zig test ../test/behavior.zig -I../test
ci/aarch64-linux-release.sh+9-6
...@@ -40,6 +40,7 @@ cmake .. \...@@ -40,6 +40,7 @@ cmake .. \
40 -DZIG_TARGET_TRIPLE="$TARGET" \40 -DZIG_TARGET_TRIPLE="$TARGET" \
41 -DZIG_TARGET_MCPU="$MCPU" \41 -DZIG_TARGET_MCPU="$MCPU" \
42 -DZIG_STATIC=ON \42 -DZIG_STATIC=ON \
43 -DZIG_NO_LIB=ON \
43 -GNinja44 -GNinja
4445
45# Now cmake will use zig as the C/C++ compiler. We reset the environment variables46# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
...@@ -49,16 +50,18 @@ unset CXX...@@ -49,16 +50,18 @@ unset CXX
4950
50ninja install51ninja install
5152
53# TODO: move this to a build.zig step (check-fmt)
52echo "Looking for non-conforming code formatting..."54echo "Looking for non-conforming code formatting..."
53stage3-release/bin/zig fmt --check .. \55stage3-release/bin/zig fmt --check .. \
54 --exclude ../test/cases/ \56 --exclude ../test/cases/ \
55 --exclude ../build-release57 --exclude ../build-release
5658
57# simultaneously test building self-hosted without LLVM and with 32-bit arm59# simultaneously test building self-hosted without LLVM and with 32-bit arm
58stage3-release/bin/zig build -Dtarget=arm-linux-musleabihf60stage3-release/bin/zig build \
61 -Dtarget=arm-linux-musleabihf \
62 -Dno-lib
5963
60# TODO: add -fqemu back to this line64# TODO: add -fqemu back to this line
61
62stage3-release/bin/zig build test docs \65stage3-release/bin/zig build test docs \
63 --maxrss 24696061952 \66 --maxrss 24696061952 \
64 -fwasmtime \67 -fwasmtime \
...@@ -68,10 +71,8 @@ stage3-release/bin/zig build test docs \...@@ -68,10 +71,8 @@ stage3-release/bin/zig build test docs \
68 --zig-lib-dir "$(pwd)/../lib"71 --zig-lib-dir "$(pwd)/../lib"
6972
70# Look for HTML errors.73# Look for HTML errors.
71tidy --drop-empty-elements no -qe "stage3-release/doc/langref.html"74# TODO: move this to a build.zig flag (-Denable-tidy)
7275tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
73# Produce the experimental std lib documentation.
74stage3-release/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
7576
76# Ensure that updating the wasm binary from this commit will result in a viable build.77# Ensure that updating the wasm binary from this commit will result in a viable build.
77stage3-release/bin/zig build update-zig178stage3-release/bin/zig build update-zig1
...@@ -91,6 +92,7 @@ cmake .. \...@@ -91,6 +92,7 @@ cmake .. \
91 -DZIG_TARGET_TRIPLE="$TARGET" \92 -DZIG_TARGET_TRIPLE="$TARGET" \
92 -DZIG_TARGET_MCPU="$MCPU" \93 -DZIG_TARGET_MCPU="$MCPU" \
93 -DZIG_STATIC=ON \94 -DZIG_STATIC=ON \
95 -DZIG_NO_LIB=ON \
94 -GNinja96 -GNinja
9597
96unset CC98unset CC
...@@ -102,6 +104,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test...@@ -102,6 +104,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test
102stage3/bin/zig build -p stage4 \104stage3/bin/zig build -p stage4 \
103 -Dstatic-llvm \105 -Dstatic-llvm \
104 -Dtarget=native-native-musl \106 -Dtarget=native-native-musl \
107 -Dno-lib \
105 --search-prefix "$PREFIX" \108 --search-prefix "$PREFIX" \
106 --zig-lib-dir "$(pwd)/../lib"109 --zig-lib-dir "$(pwd)/../lib"
107stage4/bin/zig test ../test/behavior.zig -I../test110stage4/bin/zig test ../test/behavior.zig -I../test
ci/aarch64-macos-debug.sh+1-3
...@@ -39,6 +39,7 @@ PATH="$HOME/local/bin:$PATH" cmake .. \...@@ -39,6 +39,7 @@ PATH="$HOME/local/bin:$PATH" cmake .. \
39 -DZIG_TARGET_TRIPLE="$TARGET" \39 -DZIG_TARGET_TRIPLE="$TARGET" \
40 -DZIG_TARGET_MCPU="$MCPU" \40 -DZIG_TARGET_MCPU="$MCPU" \
41 -DZIG_STATIC=ON \41 -DZIG_STATIC=ON \
42 -DZIG_NO_LIB=ON \
42 -GNinja43 -GNinja
4344
44$HOME/local/bin/ninja install45$HOME/local/bin/ninja install
...@@ -49,6 +50,3 @@ stage3-debug/bin/zig build test docs \...@@ -49,6 +50,3 @@ stage3-debug/bin/zig build test docs \
49 -Dstatic-llvm \50 -Dstatic-llvm \
50 -Dskip-non-native \51 -Dskip-non-native \
51 --search-prefix "$PREFIX"52 --search-prefix "$PREFIX"
52
53# Produce the experimental std lib documentation.
54stage3-debug/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
ci/aarch64-macos-release.sh+1-3
...@@ -39,6 +39,7 @@ PATH="$HOME/local/bin:$PATH" cmake .. \...@@ -39,6 +39,7 @@ PATH="$HOME/local/bin:$PATH" cmake .. \
39 -DZIG_TARGET_TRIPLE="$TARGET" \39 -DZIG_TARGET_TRIPLE="$TARGET" \
40 -DZIG_TARGET_MCPU="$MCPU" \40 -DZIG_TARGET_MCPU="$MCPU" \
41 -DZIG_STATIC=ON \41 -DZIG_STATIC=ON \
42 -DZIG_NO_LIB=ON \
42 -GNinja43 -GNinja
4344
44$HOME/local/bin/ninja install45$HOME/local/bin/ninja install
...@@ -50,9 +51,6 @@ stage3-release/bin/zig build test docs \...@@ -50,9 +51,6 @@ stage3-release/bin/zig build test docs \
50 -Dskip-non-native \51 -Dskip-non-native \
51 --search-prefix "$PREFIX"52 --search-prefix "$PREFIX"
5253
53# Produce the experimental std lib documentation.
54stage3-release/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
55
56# Ensure that stage3 and stage4 are byte-for-byte identical.54# Ensure that stage3 and stage4 are byte-for-byte identical.
57stage3-release/bin/zig build \55stage3-release/bin/zig build \
58 --prefix stage4-release \56 --prefix stage4-release \
ci/aarch64-windows.ps1+2-9
...@@ -55,7 +55,8 @@ $Env:ZIG_LOCAL_CACHE_DIR="$(Get-Location)\zig-local-cache"...@@ -55,7 +55,8 @@ $Env:ZIG_LOCAL_CACHE_DIR="$(Get-Location)\zig-local-cache"
55 -DZIG_AR_WORKAROUND=ON `55 -DZIG_AR_WORKAROUND=ON `
56 -DZIG_TARGET_TRIPLE="$TARGET" `56 -DZIG_TARGET_TRIPLE="$TARGET" `
57 -DZIG_TARGET_MCPU="$MCPU" `57 -DZIG_TARGET_MCPU="$MCPU" `
58 -DZIG_STATIC=ON58 -DZIG_STATIC=ON `
59 -DZIG_NO_LIB=ON
59CheckLastExitCode60CheckLastExitCode
6061
61ninja install62ninja install
...@@ -69,11 +70,3 @@ Write-Output "Main test suite..."...@@ -69,11 +70,3 @@ Write-Output "Main test suite..."
69 -Dskip-non-native `70 -Dskip-non-native `
70 -Denable-symlinks-windows71 -Denable-symlinks-windows
71CheckLastExitCode72CheckLastExitCode
72
73Write-Output "Testing Autodocs..."
74& "stage3-release\bin\zig.exe" test "..\lib\std\std.zig" `
75 --zig-lib-dir "$ZIG_LIB_DIR" `
76 -femit-docs `
77 -fno-emit-bin
78CheckLastExitCode
79
ci/x86_64-linux-debug.sh+9-5
...@@ -40,6 +40,7 @@ cmake .. \...@@ -40,6 +40,7 @@ cmake .. \
40 -DZIG_TARGET_TRIPLE="$TARGET" \40 -DZIG_TARGET_TRIPLE="$TARGET" \
41 -DZIG_TARGET_MCPU="$MCPU" \41 -DZIG_TARGET_MCPU="$MCPU" \
42 -DZIG_STATIC=ON \42 -DZIG_STATIC=ON \
43 -DZIG_NO_LIB=ON \
43 -GNinja44 -GNinja
4445
45# Now cmake will use zig as the C/C++ compiler. We reset the environment variables46# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
...@@ -49,13 +50,16 @@ unset CXX...@@ -49,13 +50,16 @@ unset CXX
4950
50ninja install51ninja install
5152
53# TODO: move this to a build.zig step (check-fmt)
52echo "Looking for non-conforming code formatting..."54echo "Looking for non-conforming code formatting..."
53stage3-debug/bin/zig fmt --check .. \55stage3-debug/bin/zig fmt --check .. \
54 --exclude ../test/cases/ \56 --exclude ../test/cases/ \
55 --exclude ../build-debug57 --exclude ../build-debug
5658
57# simultaneously test building self-hosted without LLVM and with 32-bit arm59# simultaneously test building self-hosted without LLVM and with 32-bit arm
58stage3-debug/bin/zig build -Dtarget=arm-linux-musleabihf60stage3-debug/bin/zig build \
61 -Dtarget=arm-linux-musleabihf \
62 -Dno-lib
5963
60stage3-debug/bin/zig build test docs \64stage3-debug/bin/zig build test docs \
61 --maxrss 21000000000 \65 --maxrss 21000000000 \
...@@ -67,10 +71,8 @@ stage3-debug/bin/zig build test docs \...@@ -67,10 +71,8 @@ stage3-debug/bin/zig build test docs \
67 --zig-lib-dir "$(pwd)/../lib"71 --zig-lib-dir "$(pwd)/../lib"
6872
69# Look for HTML errors.73# Look for HTML errors.
70tidy --drop-empty-elements no -qe "stage3-debug/doc/langref.html"74# TODO: move this to a build.zig flag (-Denable-tidy)
7175tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
72# Produce the experimental std lib documentation.
73stage3-debug/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
7476
75# Ensure that updating the wasm binary from this commit will result in a viable build.77# Ensure that updating the wasm binary from this commit will result in a viable build.
76stage3-debug/bin/zig build update-zig178stage3-debug/bin/zig build update-zig1
...@@ -90,6 +92,7 @@ cmake .. \...@@ -90,6 +92,7 @@ cmake .. \
90 -DZIG_TARGET_TRIPLE="$TARGET" \92 -DZIG_TARGET_TRIPLE="$TARGET" \
91 -DZIG_TARGET_MCPU="$MCPU" \93 -DZIG_TARGET_MCPU="$MCPU" \
92 -DZIG_STATIC=ON \94 -DZIG_STATIC=ON \
95 -DZIG_NO_LIB=ON \
93 -GNinja96 -GNinja
9497
95unset CC98unset CC
...@@ -101,6 +104,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test...@@ -101,6 +104,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test
101stage3/bin/zig build -p stage4 \104stage3/bin/zig build -p stage4 \
102 -Dstatic-llvm \105 -Dstatic-llvm \
103 -Dtarget=native-native-musl \106 -Dtarget=native-native-musl \
107 -Dno-lib \
104 --search-prefix "$PREFIX" \108 --search-prefix "$PREFIX" \
105 --zig-lib-dir "$(pwd)/../lib"109 --zig-lib-dir "$(pwd)/../lib"
106stage4/bin/zig test ../test/behavior.zig -I../test110stage4/bin/zig test ../test/behavior.zig -I../test
ci/x86_64-linux-release.sh+9-5
...@@ -40,6 +40,7 @@ cmake .. \...@@ -40,6 +40,7 @@ cmake .. \
40 -DZIG_TARGET_TRIPLE="$TARGET" \40 -DZIG_TARGET_TRIPLE="$TARGET" \
41 -DZIG_TARGET_MCPU="$MCPU" \41 -DZIG_TARGET_MCPU="$MCPU" \
42 -DZIG_STATIC=ON \42 -DZIG_STATIC=ON \
43 -DZIG_NO_LIB=ON \
43 -GNinja44 -GNinja
4445
45# Now cmake will use zig as the C/C++ compiler. We reset the environment variables46# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
...@@ -49,6 +50,7 @@ unset CXX...@@ -49,6 +50,7 @@ unset CXX
4950
50ninja install51ninja install
5152
53# TODO: move this to a build.zig step (check-fmt)
52echo "Looking for non-conforming code formatting..."54echo "Looking for non-conforming code formatting..."
53stage3-release/bin/zig fmt --check .. \55stage3-release/bin/zig fmt --check .. \
54 --exclude ../test/cases/ \56 --exclude ../test/cases/ \
...@@ -56,7 +58,9 @@ stage3-release/bin/zig fmt --check .. \...@@ -56,7 +58,9 @@ stage3-release/bin/zig fmt --check .. \
56 --exclude ../build-release58 --exclude ../build-release
5759
58# simultaneously test building self-hosted without LLVM and with 32-bit arm60# simultaneously test building self-hosted without LLVM and with 32-bit arm
59stage3-release/bin/zig build -Dtarget=arm-linux-musleabihf61stage3-release/bin/zig build \
62 -Dtarget=arm-linux-musleabihf \
63 -Dno-lib
6064
61stage3-release/bin/zig build test docs \65stage3-release/bin/zig build test docs \
62 --maxrss 21000000000 \66 --maxrss 21000000000 \
...@@ -68,10 +72,8 @@ stage3-release/bin/zig build test docs \...@@ -68,10 +72,8 @@ stage3-release/bin/zig build test docs \
68 --zig-lib-dir "$(pwd)/../lib"72 --zig-lib-dir "$(pwd)/../lib"
6973
70# Look for HTML errors.74# Look for HTML errors.
71tidy --drop-empty-elements no -qe "stage3-release/doc/langref.html"75# TODO: move this to a build.zig flag (-Denable-tidy)
7276tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
73# Produce the experimental std lib documentation.
74stage3-release/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
7577
76# Ensure that stage3 and stage4 are byte-for-byte identical.78# Ensure that stage3 and stage4 are byte-for-byte identical.
77stage3-release/bin/zig build \79stage3-release/bin/zig build \
...@@ -107,6 +109,7 @@ cmake .. \...@@ -107,6 +109,7 @@ cmake .. \
107 -DZIG_TARGET_TRIPLE="$TARGET" \109 -DZIG_TARGET_TRIPLE="$TARGET" \
108 -DZIG_TARGET_MCPU="$MCPU" \110 -DZIG_TARGET_MCPU="$MCPU" \
109 -DZIG_STATIC=ON \111 -DZIG_STATIC=ON \
112 -DZIG_NO_LIB=ON \
110 -GNinja113 -GNinja
111114
112unset CC115unset CC
...@@ -118,6 +121,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test...@@ -118,6 +121,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test
118stage3/bin/zig build -p stage4 \121stage3/bin/zig build -p stage4 \
119 -Dstatic-llvm \122 -Dstatic-llvm \
120 -Dtarget=native-native-musl \123 -Dtarget=native-native-musl \
124 -Dno-lib \
121 --search-prefix "$PREFIX" \125 --search-prefix "$PREFIX" \
122 --zig-lib-dir "$(pwd)/../lib"126 --zig-lib-dir "$(pwd)/../lib"
123stage4/bin/zig test ../test/behavior.zig -I../test127stage4/bin/zig test ../test/behavior.zig -I../test
ci/x86_64-macos-release.sh+2-4
...@@ -43,7 +43,8 @@ cmake .. \...@@ -43,7 +43,8 @@ cmake .. \
43 -DCMAKE_CXX_COMPILER="$ZIG;c++;-target;$TARGET;-mcpu=$MCPU" \43 -DCMAKE_CXX_COMPILER="$ZIG;c++;-target;$TARGET;-mcpu=$MCPU" \
44 -DZIG_TARGET_TRIPLE="$TARGET" \44 -DZIG_TARGET_TRIPLE="$TARGET" \
45 -DZIG_TARGET_MCPU="$MCPU" \45 -DZIG_TARGET_MCPU="$MCPU" \
46 -DZIG_STATIC=ON46 -DZIG_STATIC=ON \
47 -DZIG_NO_LIB=ON
4748
48make $JOBS install49make $JOBS install
4950
...@@ -54,9 +55,6 @@ stage3/bin/zig build test docs \...@@ -54,9 +55,6 @@ stage3/bin/zig build test docs \
54 -Dskip-non-native \55 -Dskip-non-native \
55 --search-prefix "$PREFIX"56 --search-prefix "$PREFIX"
5657
57# Produce the experimental std lib documentation.
58stage3/bin/zig test ../lib/std/std.zig -femit-docs -fno-emit-bin --zig-lib-dir ../lib
59
60# Ensure that stage3 and stage4 are byte-for-byte identical.58# Ensure that stage3 and stage4 are byte-for-byte identical.
61stage3/bin/zig build \59stage3/bin/zig build \
62 --prefix stage4 \60 --prefix stage4 \
ci/x86_64-windows-debug.ps1+2-8
...@@ -45,7 +45,8 @@ Set-Location -Path 'build-debug'...@@ -45,7 +45,8 @@ Set-Location -Path 'build-debug'
45 -DCMAKE_CXX_COMPILER="$($ZIG -Replace "\\", "/");c++;-target;$TARGET;-mcpu=$MCPU" `45 -DCMAKE_CXX_COMPILER="$($ZIG -Replace "\\", "/");c++;-target;$TARGET;-mcpu=$MCPU" `
46 -DZIG_TARGET_TRIPLE="$TARGET" `46 -DZIG_TARGET_TRIPLE="$TARGET" `
47 -DZIG_TARGET_MCPU="$MCPU" `47 -DZIG_TARGET_MCPU="$MCPU" `
48 -DZIG_STATIC=ON48 -DZIG_STATIC=ON `
49 -DZIG_NO_LIB=ON
49CheckLastExitCode50CheckLastExitCode
5051
51ninja install52ninja install
...@@ -60,13 +61,6 @@ Write-Output "Main test suite..."...@@ -60,13 +61,6 @@ Write-Output "Main test suite..."
60 -Denable-symlinks-windows61 -Denable-symlinks-windows
61CheckLastExitCode62CheckLastExitCode
6263
63Write-Output "Testing Autodocs..."
64& "stage3-debug\bin\zig.exe" test "..\lib\std\std.zig" `
65 --zig-lib-dir "$ZIG_LIB_DIR" `
66 -femit-docs `
67 -fno-emit-bin
68CheckLastExitCode
69
70Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..."64Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..."
71& "stage3-debug\bin\zig.exe" test `65& "stage3-debug\bin\zig.exe" test `
72 ..\test\behavior.zig `66 ..\test\behavior.zig `
ci/x86_64-windows-release.ps1+2-8
...@@ -45,7 +45,8 @@ Set-Location -Path 'build-release'...@@ -45,7 +45,8 @@ Set-Location -Path 'build-release'
45 -DCMAKE_CXX_COMPILER="$($ZIG -Replace "\\", "/");c++;-target;$TARGET;-mcpu=$MCPU" `45 -DCMAKE_CXX_COMPILER="$($ZIG -Replace "\\", "/");c++;-target;$TARGET;-mcpu=$MCPU" `
46 -DZIG_TARGET_TRIPLE="$TARGET" `46 -DZIG_TARGET_TRIPLE="$TARGET" `
47 -DZIG_TARGET_MCPU="$MCPU" `47 -DZIG_TARGET_MCPU="$MCPU" `
48 -DZIG_STATIC=ON48 -DZIG_STATIC=ON `
49 -DZIG_NO_LIB=ON
49CheckLastExitCode50CheckLastExitCode
5051
51ninja install52ninja install
...@@ -60,13 +61,6 @@ Write-Output "Main test suite..."...@@ -60,13 +61,6 @@ Write-Output "Main test suite..."
60 -Denable-symlinks-windows61 -Denable-symlinks-windows
61CheckLastExitCode62CheckLastExitCode
6263
63Write-Output "Testing Autodocs..."
64& "stage3-release\bin\zig.exe" test "..\lib\std\std.zig" `
65 --zig-lib-dir "$ZIG_LIB_DIR" `
66 -femit-docs `
67 -fno-emit-bin
68CheckLastExitCode
69
70Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..."64Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..."
71& "stage3-release\bin\zig.exe" test `65& "stage3-release\bin\zig.exe" test `
72 ..\test\behavior.zig `66 ..\test\behavior.zig `
lib/std/Build/Step/Compile.zig+17-3
...@@ -49,7 +49,6 @@ verbose_cc: bool,...@@ -49,7 +49,6 @@ verbose_cc: bool,
49emit_analysis: EmitOption = .default,49emit_analysis: EmitOption = .default,
50emit_asm: EmitOption = .default,50emit_asm: EmitOption = .default,
51emit_bin: EmitOption = .default,51emit_bin: EmitOption = .default,
52emit_docs: EmitOption = .default,
53emit_implib: EmitOption = .default,52emit_implib: EmitOption = .default,
54emit_llvm_bc: EmitOption = .default,53emit_llvm_bc: EmitOption = .default,
55emit_llvm_ir: EmitOption = .default,54emit_llvm_ir: EmitOption = .default,
...@@ -217,6 +216,7 @@ output_lib_path_source: GeneratedFile,...@@ -217,6 +216,7 @@ output_lib_path_source: GeneratedFile,
217output_h_path_source: GeneratedFile,216output_h_path_source: GeneratedFile,
218output_pdb_path_source: GeneratedFile,217output_pdb_path_source: GeneratedFile,
219output_dirname_source: GeneratedFile,218output_dirname_source: GeneratedFile,
219generated_docs: ?*GeneratedFile,
220220
221pub const CSourceFiles = struct {221pub const CSourceFiles = struct {
222 files: []const []const u8,222 files: []const []const u8,
...@@ -433,7 +433,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -433,7 +433,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
433 }) catch @panic("OOM");433 }) catch @panic("OOM");
434434
435 const self = owner.allocator.create(Compile) catch @panic("OOM");435 const self = owner.allocator.create(Compile) catch @panic("OOM");
436 self.* = Compile{436 self.* = .{
437 .strip = null,437 .strip = null,
438 .unwind_tables = null,438 .unwind_tables = null,
439 .verbose_link = false,439 .verbose_link = false,
...@@ -486,6 +486,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {...@@ -486,6 +486,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
486 .output_h_path_source = GeneratedFile{ .step = &self.step },486 .output_h_path_source = GeneratedFile{ .step = &self.step },
487 .output_pdb_path_source = GeneratedFile{ .step = &self.step },487 .output_pdb_path_source = GeneratedFile{ .step = &self.step },
488 .output_dirname_source = GeneratedFile{ .step = &self.step },488 .output_dirname_source = GeneratedFile{ .step = &self.step },
489 .generated_docs = null,
489490
490 .target_info = target_info,491 .target_info = target_info,
491492
...@@ -1004,6 +1005,15 @@ pub fn getOutputPdbSource(self: *Compile) FileSource {...@@ -1004,6 +1005,15 @@ pub fn getOutputPdbSource(self: *Compile) FileSource {
1004 return .{ .generated = &self.output_pdb_path_source };1005 return .{ .generated = &self.output_pdb_path_source };
1005}1006}
10061007
1008pub fn getOutputDocs(self: *Compile) FileSource {
1009 assert(self.generated_docs == null); // This function may only be called once.
1010 const arena = self.step.owner.allocator;
1011 const generated_file = arena.create(GeneratedFile) catch @panic("OOM");
1012 generated_file.* = .{ .step = &self.step };
1013 self.generated_docs = generated_file;
1014 return .{ .generated = generated_file };
1015}
1016
1007pub fn addAssemblyFile(self: *Compile, path: []const u8) void {1017pub fn addAssemblyFile(self: *Compile, path: []const u8) void {
1008 const b = self.step.owner;1018 const b = self.step.owner;
1009 self.link_objects.append(.{1019 self.link_objects.append(.{
...@@ -1509,7 +1519,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1509,7 +1519,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1509 if (self.emit_analysis.getArg(b, "emit-analysis")) |arg| try zig_args.append(arg);1519 if (self.emit_analysis.getArg(b, "emit-analysis")) |arg| try zig_args.append(arg);
1510 if (self.emit_asm.getArg(b, "emit-asm")) |arg| try zig_args.append(arg);1520 if (self.emit_asm.getArg(b, "emit-asm")) |arg| try zig_args.append(arg);
1511 if (self.emit_bin.getArg(b, "emit-bin")) |arg| try zig_args.append(arg);1521 if (self.emit_bin.getArg(b, "emit-bin")) |arg| try zig_args.append(arg);
1512 if (self.emit_docs.getArg(b, "emit-docs")) |arg| try zig_args.append(arg);1522 if (self.generated_docs != null) try zig_args.append("-femit-docs");
1513 if (self.emit_implib.getArg(b, "emit-implib")) |arg| try zig_args.append(arg);1523 if (self.emit_implib.getArg(b, "emit-implib")) |arg| try zig_args.append(arg);
1514 if (self.emit_llvm_bc.getArg(b, "emit-llvm-bc")) |arg| try zig_args.append(arg);1524 if (self.emit_llvm_bc.getArg(b, "emit-llvm-bc")) |arg| try zig_args.append(arg);
1515 if (self.emit_llvm_ir.getArg(b, "emit-llvm-ir")) |arg| try zig_args.append(arg);1525 if (self.emit_llvm_ir.getArg(b, "emit-llvm-ir")) |arg| try zig_args.append(arg);
...@@ -2022,6 +2032,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -2022,6 +2032,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
2022 &.{ output_dir, self.out_pdb_filename },2032 &.{ output_dir, self.out_pdb_filename },
2023 );2033 );
2024 }2034 }
2035
2036 if (self.generated_docs) |generated_docs| {
2037 generated_docs.path = b.pathJoin(&.{ output_dir, "docs" });
2038 }
2025 }2039 }
20262040
2027 if (self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic and2041 if (self.kind == .lib and self.linkage != null and self.linkage.? == .dynamic and
src/Autodoc.zig+13-40
...@@ -15,7 +15,6 @@ const log = std.log.scoped(.autodoc);...@@ -15,7 +15,6 @@ const log = std.log.scoped(.autodoc);
15const renderer = @import("autodoc/render_source.zig");15const renderer = @import("autodoc/render_source.zig");
1616
17comp_module: *CompilationModule,17comp_module: *CompilationModule,
18doc_location: Compilation.EmitLoc,
19arena: std.mem.Allocator,18arena: std.mem.Allocator,
2019
21// The goal of autodoc is to fill up these arrays20// The goal of autodoc is to fill up these arrays
...@@ -74,28 +73,23 @@ const Section = struct {...@@ -74,28 +73,23 @@ const Section = struct {
74 };73 };
75};74};
7675
77var arena_allocator: std.heap.ArenaAllocator = undefined;76pub fn generate(cm: *CompilationModule, output_dir: std.fs.Dir) !void {
78pub fn init(m: *CompilationModule, doc_location: Compilation.EmitLoc) Autodoc {77 var arena_allocator = std.heap.ArenaAllocator.init(cm.gpa);
79 arena_allocator = std.heap.ArenaAllocator.init(m.gpa);78 defer arena_allocator.deinit();
80 return .{79 var autodoc: Autodoc = .{
81 .comp_module = m,80 .comp_module = cm,
82 .doc_location = doc_location,
83 .arena = arena_allocator.allocator(),81 .arena = arena_allocator.allocator(),
84 };82 };
85}83 try autodoc.generateZirData(output_dir);
8684
87pub fn deinit(_: *Autodoc) void {85 const lib_dir = cm.comp.zig_lib_directory.handle;
88 arena_allocator.deinit();86 try lib_dir.copyFile("docs/main.js", output_dir, "main.js", .{});
87 try lib_dir.copyFile("docs/ziglexer.js", output_dir, "ziglexer.js", .{});
88 try lib_dir.copyFile("docs/commonmark.js", output_dir, "commonmark.js", .{});
89 try lib_dir.copyFile("docs/index.html", output_dir, "index.html", .{});
89}90}
9091
91/// The entry point of the Autodoc generation process.92fn generateZirData(self: *Autodoc, output_dir: std.fs.Dir) !void {
92pub fn generateZirData(self: *Autodoc) !void {
93 if (self.doc_location.directory) |dir| {
94 if (dir.path) |path| {
95 log.debug("path: {s}", .{path});
96 }
97 }
98
99 const root_src_dir = self.comp_module.main_pkg.root_src_directory;93 const root_src_dir = self.comp_module.main_pkg.root_src_directory;
100 const root_src_path = self.comp_module.main_pkg.root_src_path;94 const root_src_path = self.comp_module.main_pkg.root_src_path;
101 const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path});95 const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path});
...@@ -362,19 +356,6 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -362,19 +356,6 @@ pub fn generateZirData(self: *Autodoc) !void {
362 .guide_sections = self.guide_sections,356 .guide_sections = self.guide_sections,
363 };357 };
364358
365 const base_dir = self.doc_location.directory orelse
366 self.comp_module.zig_cache_artifact_directory;
367
368 base_dir.handle.makeDir(self.doc_location.basename) catch |e| switch (e) {
369 error.PathAlreadyExists => {},
370 else => |err| return err,
371 };
372
373 const output_dir = if (self.doc_location.directory) |d|
374 try d.handle.openDir(self.doc_location.basename, .{})
375 else
376 try self.comp_module.zig_cache_artifact_directory.handle.openDir(self.doc_location.basename, .{});
377
378 {359 {
379 const data_js_f = try output_dir.createFile("data.js", .{});360 const data_js_f = try output_dir.createFile("data.js", .{});
380 defer data_js_f.close();361 defer data_js_f.close();
...@@ -386,7 +367,7 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -386,7 +367,7 @@ pub fn generateZirData(self: *Autodoc) !void {
386 \\ var zigAnalysis=367 \\ var zigAnalysis=
387 , .{});368 , .{});
388 try std.json.stringifyArbitraryDepth(369 try std.json.stringifyArbitraryDepth(
389 arena_allocator.allocator(),370 self.arena,
390 data,371 data,
391 .{372 .{
392 .whitespace = .minified,373 .whitespace = .minified,
...@@ -439,14 +420,6 @@ pub fn generateZirData(self: *Autodoc) !void {...@@ -439,14 +420,6 @@ pub fn generateZirData(self: *Autodoc) !void {
439 try buffer.flush();420 try buffer.flush();
440 }421 }
441 }422 }
442
443 // copy main.js, index.html
444 var docs_dir = try self.comp_module.comp.zig_lib_directory.handle.openDir("docs", .{});
445 defer docs_dir.close();
446 try docs_dir.copyFile("main.js", output_dir, "main.js", .{});
447 try docs_dir.copyFile("ziglexer.js", output_dir, "ziglexer.js", .{});
448 try docs_dir.copyFile("commonmark.js", output_dir, "commonmark.js", .{});
449 try docs_dir.copyFile("index.html", output_dir, "index.html", .{});
450}423}
451424
452/// Represents a chain of scopes, used to resolve decl references to the425/// Represents a chain of scopes, used to resolve decl references to the
src/Compilation.zig+66-20
...@@ -118,6 +118,7 @@ self_exe_path: ?[]const u8,...@@ -118,6 +118,7 @@ self_exe_path: ?[]const u8,
118whole_bin_sub_path: ?[]u8,118whole_bin_sub_path: ?[]u8,
119/// Same as `whole_bin_sub_path` but for implibs.119/// Same as `whole_bin_sub_path` but for implibs.
120whole_implib_sub_path: ?[]u8,120whole_implib_sub_path: ?[]u8,
121whole_docs_sub_path: ?[]u8,
121zig_lib_directory: Directory,122zig_lib_directory: Directory,
122local_cache_directory: Directory,123local_cache_directory: Directory,
123global_cache_directory: Directory,124global_cache_directory: Directory,
...@@ -179,7 +180,6 @@ emit_asm: ?EmitLoc,...@@ -179,7 +180,6 @@ emit_asm: ?EmitLoc,
179emit_llvm_ir: ?EmitLoc,180emit_llvm_ir: ?EmitLoc,
180emit_llvm_bc: ?EmitLoc,181emit_llvm_bc: ?EmitLoc,
181emit_analysis: ?EmitLoc,182emit_analysis: ?EmitLoc,
182emit_docs: ?EmitLoc,
183183
184work_queue_wait_group: WaitGroup = .{},184work_queue_wait_group: WaitGroup = .{},
185astgen_wait_group: WaitGroup = .{},185astgen_wait_group: WaitGroup = .{},
...@@ -1119,6 +1119,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1119,6 +1119,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1119 cache.hash.addOptional(options.dwarf_format);1119 cache.hash.addOptional(options.dwarf_format);
1120 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);1120 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);
1121 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);1121 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);
1122 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
1122 cache.hash.addBytes(options.root_name);1123 cache.hash.addBytes(options.root_name);
1123 if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model);1124 if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model);
1124 // TODO audit this and make sure everything is in it1125 // TODO audit this and make sure everything is in it
...@@ -1171,8 +1172,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1171,8 +1172,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1171 // For whole cache mode, it is still used for builtin.zig so that the file1172 // For whole cache mode, it is still used for builtin.zig so that the file
1172 // path to builtin.zig can remain consistent during a debugging session at1173 // path to builtin.zig can remain consistent during a debugging session at
1173 // runtime. However, we don't know where to put outputs from the linker1174 // runtime. However, we don't know where to put outputs from the linker
1174 // or stage1 backend object files until the final cache hash, which is available1175 // until the final cache hash, which is available after the
1175 // after the compilation is complete.1176 // compilation is complete.
1176 //1177 //
1177 // Therefore, in whole cache mode, we additionally create a temporary cache1178 // Therefore, in whole cache mode, we additionally create a temporary cache
1178 // directory for these two kinds of build artifacts, and then rename it1179 // directory for these two kinds of build artifacts, and then rename it
...@@ -1346,6 +1347,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1346,6 +1347,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1346 };1347 };
1347 }1348 }
13481349
1350 // In case of whole cache mode, `whole_bin_sub_path` is used to distinguish
1351 // between -femit-bin and -fno-emit-bin.
1349 switch (cache_mode) {1352 switch (cache_mode) {
1350 .whole => break :blk null,1353 .whole => break :blk null,
1351 .incremental => {},1354 .incremental => {},
...@@ -1408,6 +1411,34 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1408,6 +1411,34 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1408 };1411 };
1409 };1412 };
14101413
1414 const docs_emit: ?link.Emit = blk: {
1415 const emit_docs = options.emit_docs orelse break :blk null;
1416
1417 if (emit_docs.directory) |directory| {
1418 break :blk .{
1419 .directory = directory,
1420 .sub_path = emit_docs.basename,
1421 };
1422 }
1423
1424 // This is here for the same reason as in `bin_file_emit` above.
1425 switch (cache_mode) {
1426 .whole => break :blk null,
1427 .incremental => {},
1428 }
1429
1430 // Use the same directory as the bin, if possible.
1431 if (bin_file_emit) |x| break :blk .{
1432 .directory = x.directory,
1433 .sub_path = emit_docs.basename,
1434 };
1435
1436 break :blk .{
1437 .directory = module.?.zig_cache_artifact_directory,
1438 .sub_path = emit_docs.basename,
1439 };
1440 };
1441
1411 // This is so that when doing `CacheMode.whole`, the mechanism in update()1442 // This is so that when doing `CacheMode.whole`, the mechanism in update()
1412 // can use it for communicating the result directory via `bin_file.emit`.1443 // can use it for communicating the result directory via `bin_file.emit`.
1413 // This is used to distinguish between -fno-emit-bin and -femit-bin1444 // This is used to distinguish between -fno-emit-bin and -femit-bin
...@@ -1417,6 +1448,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1417,6 +1448,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1417 const whole_bin_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_bin);1448 const whole_bin_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_bin);
1418 // Same thing but for implibs.1449 // Same thing but for implibs.
1419 const whole_implib_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_implib);1450 const whole_implib_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_implib);
1451 const whole_docs_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_docs);
14201452
1421 var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{};1453 var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{};
1422 errdefer system_libs.deinit(gpa);1454 errdefer system_libs.deinit(gpa);
...@@ -1428,6 +1460,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1428,6 +1460,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1428 const bin_file = try link.File.openPath(gpa, .{1460 const bin_file = try link.File.openPath(gpa, .{
1429 .emit = bin_file_emit,1461 .emit = bin_file_emit,
1430 .implib_emit = implib_emit,1462 .implib_emit = implib_emit,
1463 .docs_emit = docs_emit,
1431 .root_name = root_name,1464 .root_name = root_name,
1432 .module = module,1465 .module = module,
1433 .target = options.target,1466 .target = options.target,
...@@ -1552,11 +1585,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {...@@ -1552,11 +1585,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
1552 .bin_file = bin_file,1585 .bin_file = bin_file,
1553 .whole_bin_sub_path = whole_bin_sub_path,1586 .whole_bin_sub_path = whole_bin_sub_path,
1554 .whole_implib_sub_path = whole_implib_sub_path,1587 .whole_implib_sub_path = whole_implib_sub_path,
1588 .whole_docs_sub_path = whole_docs_sub_path,
1555 .emit_asm = options.emit_asm,1589 .emit_asm = options.emit_asm,
1556 .emit_llvm_ir = options.emit_llvm_ir,1590 .emit_llvm_ir = options.emit_llvm_ir,
1557 .emit_llvm_bc = options.emit_llvm_bc,1591 .emit_llvm_bc = options.emit_llvm_bc,
1558 .emit_analysis = options.emit_analysis,1592 .emit_analysis = options.emit_analysis,
1559 .emit_docs = options.emit_docs,
1560 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),1593 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
1561 .anon_work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),1594 .anon_work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
1562 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),1595 .c_object_work_queue = std.fifo.LinearFifo(*CObject, .Dynamic).init(gpa),
...@@ -1940,7 +1973,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -1940,7 +1973,7 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
1940 };1973 };
1941 };1974 };
19421975
1943 // This updates the output directory for stage1 backend and linker outputs.1976 // This updates the output directory for linker outputs.
1944 if (comp.bin_file.options.module) |module| {1977 if (comp.bin_file.options.module) |module| {
1945 module.zig_cache_artifact_directory = tmp_artifact_directory.?;1978 module.zig_cache_artifact_directory = tmp_artifact_directory.?;
1946 }1979 }
...@@ -1960,6 +1993,12 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -1960,6 +1993,12 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
1960 .sub_path = std.fs.path.basename(sub_path),1993 .sub_path = std.fs.path.basename(sub_path),
1961 };1994 };
1962 }1995 }
1996 if (comp.whole_docs_sub_path) |sub_path| {
1997 options.docs_emit = .{
1998 .directory = tmp_artifact_directory.?,
1999 .sub_path = std.fs.path.basename(sub_path),
2000 };
2001 }
1963 var old_bin_file = comp.bin_file;2002 var old_bin_file = comp.bin_file;
1964 comp.bin_file = try link.File.openPath(comp.gpa, options);2003 comp.bin_file = try link.File.openPath(comp.gpa, options);
1965 old_bin_file.destroy();2004 old_bin_file.destroy();
...@@ -2064,16 +2103,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2064,16 +2103,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2064 return;2103 return;
2065 }2104 }
20662105
2067 if (!build_options.only_c and !build_options.only_core_functionality) {
2068 if (comp.emit_docs) |doc_location| {
2069 if (comp.bin_file.options.module) |module| {
2070 var autodoc = Autodoc.init(module, doc_location);
2071 defer autodoc.deinit();
2072 try autodoc.generateZirData();
2073 }
2074 }
2075 }
2076
2077 // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and2106 // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and
2078 // -femit-asm to handle, in the case of C objects.2107 // -femit-asm to handle, in the case of C objects.
2079 comp.emitOthers();2108 comp.emitOthers();
...@@ -2122,12 +2151,21 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void...@@ -2122,12 +2151,21 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
2122 };2151 };
21232152
2124 try comp.flush(main_progress_node);2153 try comp.flush(main_progress_node);
2154 if (comp.totalErrorCount() != 0) return;
2155
2156 // TODO: do this in a separate job during performAllTheWork(). The
2157 // file copies at the end of generate() can also be extracted to
2158 // separate jobs
2159 if (!build_options.only_c and !build_options.only_core_functionality) {
2160 if (comp.bin_file.options.docs_emit) |emit| {
2161 var dir = try emit.directory.handle.makeOpenPath(emit.sub_path, .{});
2162 defer dir.close();
2163 try Autodoc.generate(module, dir);
2164 }
2165 }
2125 } else {2166 } else {
2126 try comp.flush(main_progress_node);2167 try comp.flush(main_progress_node);
2127 }2168 if (comp.totalErrorCount() != 0) return;
2128
2129 if (comp.totalErrorCount() != 0) {
2130 return;
2131 }2169 }
21322170
2133 // Failure here only means an unnecessary cache miss.2171 // Failure here only means an unnecessary cache miss.
...@@ -2190,6 +2228,15 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di...@@ -2190,6 +2228,15 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di
2190 .sub_path = sub_path,2228 .sub_path = sub_path,
2191 };2229 };
2192 }2230 }
2231
2232 if (comp.whole_docs_sub_path) |sub_path| {
2233 @memcpy(sub_path[digest_start..][0..digest.len], digest);
2234
2235 comp.bin_file.options.docs_emit = .{
2236 .directory = comp.local_cache_directory,
2237 .sub_path = sub_path,
2238 };
2239 }
2193}2240}
21942241
2195fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemory}!?[]u8 {2242fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemory}!?[]u8 {
...@@ -2265,7 +2312,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes...@@ -2265,7 +2312,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
2265 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);2312 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);
2266 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);2313 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);
2267 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_analysis);2314 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_analysis);
2268 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_docs);
22692315
2270 man.hash.addListOfBytes(comp.clang_argv);2316 man.hash.addListOfBytes(comp.clang_argv);
22712317
src/link.zig+3-1
...@@ -71,8 +71,10 @@ pub const Emit = struct {...@@ -71,8 +71,10 @@ pub const Emit = struct {
71pub const Options = struct {71pub const Options = struct {
72 /// This is `null` when `-fno-emit-bin` is used.72 /// This is `null` when `-fno-emit-bin` is used.
73 emit: ?Emit,73 emit: ?Emit,
74 /// This is `null` not building a Windows DLL, or when `-fno-emit-implib` is used.74 /// This is `null` when not building a Windows DLL, or when `-fno-emit-implib` is used.
75 implib_emit: ?Emit,75 implib_emit: ?Emit,
76 /// This is non-null when `-femit-docs` is provided.
77 docs_emit: ?Emit,
76 target: std.Target,78 target: std.Target,
77 output_mode: std.builtin.OutputMode,79 output_mode: std.builtin.OutputMode,
78 link_mode: std.builtin.LinkMode,80 link_mode: std.builtin.LinkMode,
src/main.zig+27-10
...@@ -622,7 +622,7 @@ const Emit = union(enum) {...@@ -622,7 +622,7 @@ const Emit = union(enum) {
622 }622 }
623 };623 };
624624
625 fn resolve(emit: Emit, default_basename: []const u8) !Resolved {625 fn resolve(emit: Emit, default_basename: []const u8, output_to_cache: bool) !Resolved {
626 var resolved: Resolved = .{ .data = null, .dir = null };626 var resolved: Resolved = .{ .data = null, .dir = null };
627 errdefer resolved.deinit();627 errdefer resolved.deinit();
628628
...@@ -630,7 +630,10 @@ const Emit = union(enum) {...@@ -630,7 +630,10 @@ const Emit = union(enum) {
630 .no => {},630 .no => {},
631 .yes_default_path => {631 .yes_default_path => {
632 resolved.data = Compilation.EmitLoc{632 resolved.data = Compilation.EmitLoc{
633 .directory = .{ .path = null, .handle = fs.cwd() },633 .directory = if (output_to_cache) null else .{
634 .path = null,
635 .handle = fs.cwd(),
636 },
634 .basename = default_basename,637 .basename = default_basename,
635 };638 };
636 },639 },
...@@ -2750,7 +2753,7 @@ fn buildOutputType(...@@ -2750,7 +2753,7 @@ fn buildOutputType(
2750 };2753 };
27512754
2752 const default_h_basename = try std.fmt.allocPrint(arena, "{s}.h", .{root_name});2755 const default_h_basename = try std.fmt.allocPrint(arena, "{s}.h", .{root_name});
2753 var emit_h_resolved = emit_h.resolve(default_h_basename) catch |err| {2756 var emit_h_resolved = emit_h.resolve(default_h_basename, output_to_cache) catch |err| {
2754 switch (emit_h) {2757 switch (emit_h) {
2755 .yes => |p| {2758 .yes => |p| {
2756 fatal("unable to open directory from argument '-femit-h', '{s}': {s}", .{2759 fatal("unable to open directory from argument '-femit-h', '{s}': {s}", .{
...@@ -2768,7 +2771,7 @@ fn buildOutputType(...@@ -2768,7 +2771,7 @@ fn buildOutputType(
2768 defer emit_h_resolved.deinit();2771 defer emit_h_resolved.deinit();
27692772
2770 const default_asm_basename = try std.fmt.allocPrint(arena, "{s}.s", .{root_name});2773 const default_asm_basename = try std.fmt.allocPrint(arena, "{s}.s", .{root_name});
2771 var emit_asm_resolved = emit_asm.resolve(default_asm_basename) catch |err| {2774 var emit_asm_resolved = emit_asm.resolve(default_asm_basename, output_to_cache) catch |err| {
2772 switch (emit_asm) {2775 switch (emit_asm) {
2773 .yes => |p| {2776 .yes => |p| {
2774 fatal("unable to open directory from argument '-femit-asm', '{s}': {s}", .{2777 fatal("unable to open directory from argument '-femit-asm', '{s}': {s}", .{
...@@ -2786,7 +2789,7 @@ fn buildOutputType(...@@ -2786,7 +2789,7 @@ fn buildOutputType(
2786 defer emit_asm_resolved.deinit();2789 defer emit_asm_resolved.deinit();
27872790
2788 const default_llvm_ir_basename = try std.fmt.allocPrint(arena, "{s}.ll", .{root_name});2791 const default_llvm_ir_basename = try std.fmt.allocPrint(arena, "{s}.ll", .{root_name});
2789 var emit_llvm_ir_resolved = emit_llvm_ir.resolve(default_llvm_ir_basename) catch |err| {2792 var emit_llvm_ir_resolved = emit_llvm_ir.resolve(default_llvm_ir_basename, output_to_cache) catch |err| {
2790 switch (emit_llvm_ir) {2793 switch (emit_llvm_ir) {
2791 .yes => |p| {2794 .yes => |p| {
2792 fatal("unable to open directory from argument '-femit-llvm-ir', '{s}': {s}", .{2795 fatal("unable to open directory from argument '-femit-llvm-ir', '{s}': {s}", .{
...@@ -2804,7 +2807,7 @@ fn buildOutputType(...@@ -2804,7 +2807,7 @@ fn buildOutputType(
2804 defer emit_llvm_ir_resolved.deinit();2807 defer emit_llvm_ir_resolved.deinit();
28052808
2806 const default_llvm_bc_basename = try std.fmt.allocPrint(arena, "{s}.bc", .{root_name});2809 const default_llvm_bc_basename = try std.fmt.allocPrint(arena, "{s}.bc", .{root_name});
2807 var emit_llvm_bc_resolved = emit_llvm_bc.resolve(default_llvm_bc_basename) catch |err| {2810 var emit_llvm_bc_resolved = emit_llvm_bc.resolve(default_llvm_bc_basename, output_to_cache) catch |err| {
2808 switch (emit_llvm_bc) {2811 switch (emit_llvm_bc) {
2809 .yes => |p| {2812 .yes => |p| {
2810 fatal("unable to open directory from argument '-femit-llvm-bc', '{s}': {s}", .{2813 fatal("unable to open directory from argument '-femit-llvm-bc', '{s}': {s}", .{
...@@ -2822,7 +2825,7 @@ fn buildOutputType(...@@ -2822,7 +2825,7 @@ fn buildOutputType(
2822 defer emit_llvm_bc_resolved.deinit();2825 defer emit_llvm_bc_resolved.deinit();
28232826
2824 const default_analysis_basename = try std.fmt.allocPrint(arena, "{s}-analysis.json", .{root_name});2827 const default_analysis_basename = try std.fmt.allocPrint(arena, "{s}-analysis.json", .{root_name});
2825 var emit_analysis_resolved = emit_analysis.resolve(default_analysis_basename) catch |err| {2828 var emit_analysis_resolved = emit_analysis.resolve(default_analysis_basename, output_to_cache) catch |err| {
2826 switch (emit_analysis) {2829 switch (emit_analysis) {
2827 .yes => |p| {2830 .yes => |p| {
2828 fatal("unable to open directory from argument '-femit-analysis', '{s}': {s}", .{2831 fatal("unable to open directory from argument '-femit-analysis', '{s}': {s}", .{
...@@ -2839,7 +2842,7 @@ fn buildOutputType(...@@ -2839,7 +2842,7 @@ fn buildOutputType(
2839 };2842 };
2840 defer emit_analysis_resolved.deinit();2843 defer emit_analysis_resolved.deinit();
28412844
2842 var emit_docs_resolved = emit_docs.resolve("docs") catch |err| {2845 var emit_docs_resolved = emit_docs.resolve("docs", output_to_cache) catch |err| {
2843 switch (emit_docs) {2846 switch (emit_docs) {
2844 .yes => |p| {2847 .yes => |p| {
2845 fatal("unable to open directory from argument '-femit-docs', '{s}': {s}", .{2848 fatal("unable to open directory from argument '-femit-docs', '{s}': {s}", .{
...@@ -2873,7 +2876,7 @@ fn buildOutputType(...@@ -2873,7 +2876,7 @@ fn buildOutputType(
2873 const default_implib_basename = try std.fmt.allocPrint(arena, "{s}.lib", .{root_name});2876 const default_implib_basename = try std.fmt.allocPrint(arena, "{s}.lib", .{root_name});
2874 var emit_implib_resolved = switch (emit_implib) {2877 var emit_implib_resolved = switch (emit_implib) {
2875 .no => Emit.Resolved{ .data = null, .dir = null },2878 .no => Emit.Resolved{ .data = null, .dir = null },
2876 .yes => |p| emit_implib.resolve(default_implib_basename) catch |err| {2879 .yes => |p| emit_implib.resolve(default_implib_basename, output_to_cache) catch |err| {
2877 fatal("unable to open directory from argument '-femit-implib', '{s}': {s}", .{2880 fatal("unable to open directory from argument '-femit-implib', '{s}': {s}", .{
2878 p, @errorName(err),2881 p, @errorName(err),
2879 });2882 });
...@@ -3566,7 +3569,21 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {...@@ -3566,7 +3569,21 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {
3566 defer error_bundle.deinit(gpa);3569 defer error_bundle.deinit(gpa);
3567 if (error_bundle.errorMessageCount() > 0) {3570 if (error_bundle.errorMessageCount() > 0) {
3568 try s.serveErrorBundle(error_bundle);3571 try s.serveErrorBundle(error_bundle);
3569 } else if (comp.bin_file.options.emit) |emit| {3572 return;
3573 }
3574 // This logic is a bit counter-intuitive because the protocol implies that
3575 // each emitted artifact could possibly be in a different location, when in
3576 // reality, there is only one artifact output directory, and the build
3577 // system depends on that fact. So, until the protocol is changed to
3578 // reflect this, this logic only needs to ensure that emit_bin_path is
3579 // emitted for at least one thing, if there are any artifacts.
3580 if (comp.bin_file.options.emit) |emit| {
3581 const full_path = try emit.directory.join(gpa, &.{emit.sub_path});
3582 defer gpa.free(full_path);
3583 try s.serveEmitBinPath(full_path, .{
3584 .flags = .{ .cache_hit = comp.last_update_was_cache_hit },
3585 });
3586 } else if (comp.bin_file.options.docs_emit) |emit| {
3570 const full_path = try emit.directory.join(gpa, &.{emit.sub_path});3587 const full_path = try emit.directory.join(gpa, &.{emit.sub_path});
3571 defer gpa.free(full_path);3588 defer gpa.free(full_path);
3572 try s.serveEmitBinPath(full_path, .{3589 try s.serveEmitBinPath(full_path, .{