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 {
2424
2525 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;
2728 const single_threaded = b.option(bool, "single-threaded", "Build artifacts that run in single threaded mode");
2829 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
3031 const test_step = b.step("test", "Run all the tests");
3132 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;
3233 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;
3335 const no_bin = b.option(bool, "no-bin", "skip emitting compiler binary") orelse false;
3436
3537 const docgen_exe = b.addExecutable(.{
......@@ -52,8 +54,34 @@ pub fn build(b: *std.Build) !void {
5254 b.getInstallStep().dependOn(&install_langref.step);
5355 }
5456
55 const docs_step = b.step("docs", "Build documentation");
56 docs_step.dependOn(&docgen_cmd.step);
57 const autodoc_test = b.addTest(.{
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
5886 const check_case_exe = b.addExecutable(.{
5987 .name = "check-case",
......@@ -104,10 +132,10 @@ pub fn build(b: *std.Build) !void {
104132 const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h");
105133
106134 if (!skip_install_lib_files) {
107 b.installDirectory(InstallDirectoryOptions{
135 b.installDirectory(.{
108136 .source_dir = .{ .path = "lib" },
109 .install_dir = .lib,
110 .install_subdir = "zig",
137 .install_dir = if (flat) .prefix else .lib,
138 .install_subdir = if (flat) "lib" else "zig",
111139 .exclude_extensions = &[_][]const u8{
112140 // exclude files from lib/std/compress/testdata
113141 ".gz",
......@@ -167,6 +195,9 @@ pub fn build(b: *std.Build) !void {
167195 exe.pie = pie;
168196 exe.sanitize_thread = sanitize_thread;
169197 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
170201 if (no_bin) exe.emit_bin = .no_emit;
171202
172203 exe.build_id = b.option(
......@@ -175,7 +206,13 @@ pub fn build(b: *std.Build) !void {
175206 "Request creation of '.note.gnu.build-id' section",
176207 );
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
180217 test_step.dependOn(&exe.step);
181218
ci/aarch64-linux-debug.sh+9-6
......@@ -40,6 +40,7 @@ cmake .. \
4040 -DZIG_TARGET_TRIPLE="$TARGET" \
4141 -DZIG_TARGET_MCPU="$MCPU" \
4242 -DZIG_STATIC=ON \
43 -DZIG_NO_LIB=ON \
4344 -GNinja
4445
4546# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
......@@ -49,16 +50,18 @@ unset CXX
4950
5051ninja install
5152
53# TODO: move this to a build.zig step (check-fmt)
5254echo "Looking for non-conforming code formatting..."
5355stage3-debug/bin/zig fmt --check .. \
5456 --exclude ../test/cases/ \
5557 --exclude ../build-debug
5658
5759# simultaneously test building self-hosted without LLVM and with 32-bit arm
58stage3-debug/bin/zig build -Dtarget=arm-linux-musleabihf
60stage3-debug/bin/zig build \
61 -Dtarget=arm-linux-musleabihf \
62 -Dno-lib
5963
6064# TODO: add -fqemu back to this line
61
6265stage3-debug/bin/zig build test docs \
6366 --maxrss 24696061952 \
6467 -fwasmtime \
......@@ -68,10 +71,8 @@ stage3-debug/bin/zig build test docs \
6871 --zig-lib-dir "$(pwd)/../lib"
6972
7073# Look for HTML errors.
71tidy --drop-empty-elements no -qe "stage3-debug/doc/langref.html"
72
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
74# TODO: move this to a build.zig flag (-Denable-tidy)
75tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
7576
7677# Ensure that updating the wasm binary from this commit will result in a viable build.
7778stage3-debug/bin/zig build update-zig1
......@@ -91,6 +92,7 @@ cmake .. \
9192 -DZIG_TARGET_TRIPLE="$TARGET" \
9293 -DZIG_TARGET_MCPU="$MCPU" \
9394 -DZIG_STATIC=ON \
95 -DZIG_NO_LIB=ON \
9496 -GNinja
9597
9698unset CC
......@@ -102,6 +104,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test
102104stage3/bin/zig build -p stage4 \
103105 -Dstatic-llvm \
104106 -Dtarget=native-native-musl \
107 -Dno-lib \
105108 --search-prefix "$PREFIX" \
106109 --zig-lib-dir "$(pwd)/../lib"
107110stage4/bin/zig test ../test/behavior.zig -I../test
ci/aarch64-linux-release.sh+9-6
......@@ -40,6 +40,7 @@ cmake .. \
4040 -DZIG_TARGET_TRIPLE="$TARGET" \
4141 -DZIG_TARGET_MCPU="$MCPU" \
4242 -DZIG_STATIC=ON \
43 -DZIG_NO_LIB=ON \
4344 -GNinja
4445
4546# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
......@@ -49,16 +50,18 @@ unset CXX
4950
5051ninja install
5152
53# TODO: move this to a build.zig step (check-fmt)
5254echo "Looking for non-conforming code formatting..."
5355stage3-release/bin/zig fmt --check .. \
5456 --exclude ../test/cases/ \
5557 --exclude ../build-release
5658
5759# simultaneously test building self-hosted without LLVM and with 32-bit arm
58stage3-release/bin/zig build -Dtarget=arm-linux-musleabihf
60stage3-release/bin/zig build \
61 -Dtarget=arm-linux-musleabihf \
62 -Dno-lib
5963
6064# TODO: add -fqemu back to this line
61
6265stage3-release/bin/zig build test docs \
6366 --maxrss 24696061952 \
6467 -fwasmtime \
......@@ -68,10 +71,8 @@ stage3-release/bin/zig build test docs \
6871 --zig-lib-dir "$(pwd)/../lib"
6972
7073# Look for HTML errors.
71tidy --drop-empty-elements no -qe "stage3-release/doc/langref.html"
72
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
74# TODO: move this to a build.zig flag (-Denable-tidy)
75tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
7576
7677# Ensure that updating the wasm binary from this commit will result in a viable build.
7778stage3-release/bin/zig build update-zig1
......@@ -91,6 +92,7 @@ cmake .. \
9192 -DZIG_TARGET_TRIPLE="$TARGET" \
9293 -DZIG_TARGET_MCPU="$MCPU" \
9394 -DZIG_STATIC=ON \
95 -DZIG_NO_LIB=ON \
9496 -GNinja
9597
9698unset CC
......@@ -102,6 +104,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test
102104stage3/bin/zig build -p stage4 \
103105 -Dstatic-llvm \
104106 -Dtarget=native-native-musl \
107 -Dno-lib \
105108 --search-prefix "$PREFIX" \
106109 --zig-lib-dir "$(pwd)/../lib"
107110stage4/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 .. \
3939 -DZIG_TARGET_TRIPLE="$TARGET" \
4040 -DZIG_TARGET_MCPU="$MCPU" \
4141 -DZIG_STATIC=ON \
42 -DZIG_NO_LIB=ON \
4243 -GNinja
4344
4445$HOME/local/bin/ninja install
......@@ -49,6 +50,3 @@ stage3-debug/bin/zig build test docs \
4950 -Dstatic-llvm \
5051 -Dskip-non-native \
5152 --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 .. \
3939 -DZIG_TARGET_TRIPLE="$TARGET" \
4040 -DZIG_TARGET_MCPU="$MCPU" \
4141 -DZIG_STATIC=ON \
42 -DZIG_NO_LIB=ON \
4243 -GNinja
4344
4445$HOME/local/bin/ninja install
......@@ -50,9 +51,6 @@ stage3-release/bin/zig build test docs \
5051 -Dskip-non-native \
5152 --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
5654# Ensure that stage3 and stage4 are byte-for-byte identical.
5755stage3-release/bin/zig build \
5856 --prefix stage4-release \
ci/aarch64-windows.ps1+2-9
......@@ -55,7 +55,8 @@ $Env:ZIG_LOCAL_CACHE_DIR="$(Get-Location)\zig-local-cache"
5555 -DZIG_AR_WORKAROUND=ON `
5656 -DZIG_TARGET_TRIPLE="$TARGET" `
5757 -DZIG_TARGET_MCPU="$MCPU" `
58 -DZIG_STATIC=ON
58 -DZIG_STATIC=ON `
59 -DZIG_NO_LIB=ON
5960CheckLastExitCode
6061
6162ninja install
......@@ -69,11 +70,3 @@ Write-Output "Main test suite..."
6970 -Dskip-non-native `
7071 -Denable-symlinks-windows
7172CheckLastExitCode
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 .. \
4040 -DZIG_TARGET_TRIPLE="$TARGET" \
4141 -DZIG_TARGET_MCPU="$MCPU" \
4242 -DZIG_STATIC=ON \
43 -DZIG_NO_LIB=ON \
4344 -GNinja
4445
4546# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
......@@ -49,13 +50,16 @@ unset CXX
4950
5051ninja install
5152
53# TODO: move this to a build.zig step (check-fmt)
5254echo "Looking for non-conforming code formatting..."
5355stage3-debug/bin/zig fmt --check .. \
5456 --exclude ../test/cases/ \
5557 --exclude ../build-debug
5658
5759# simultaneously test building self-hosted without LLVM and with 32-bit arm
58stage3-debug/bin/zig build -Dtarget=arm-linux-musleabihf
60stage3-debug/bin/zig build \
61 -Dtarget=arm-linux-musleabihf \
62 -Dno-lib
5963
6064stage3-debug/bin/zig build test docs \
6165 --maxrss 21000000000 \
......@@ -67,10 +71,8 @@ stage3-debug/bin/zig build test docs \
6771 --zig-lib-dir "$(pwd)/../lib"
6872
6973# Look for HTML errors.
70tidy --drop-empty-elements no -qe "stage3-debug/doc/langref.html"
71
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
74# TODO: move this to a build.zig flag (-Denable-tidy)
75tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
7476
7577# Ensure that updating the wasm binary from this commit will result in a viable build.
7678stage3-debug/bin/zig build update-zig1
......@@ -90,6 +92,7 @@ cmake .. \
9092 -DZIG_TARGET_TRIPLE="$TARGET" \
9193 -DZIG_TARGET_MCPU="$MCPU" \
9294 -DZIG_STATIC=ON \
95 -DZIG_NO_LIB=ON \
9396 -GNinja
9497
9598unset CC
......@@ -101,6 +104,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test
101104stage3/bin/zig build -p stage4 \
102105 -Dstatic-llvm \
103106 -Dtarget=native-native-musl \
107 -Dno-lib \
104108 --search-prefix "$PREFIX" \
105109 --zig-lib-dir "$(pwd)/../lib"
106110stage4/bin/zig test ../test/behavior.zig -I../test
ci/x86_64-linux-release.sh+9-5
......@@ -40,6 +40,7 @@ cmake .. \
4040 -DZIG_TARGET_TRIPLE="$TARGET" \
4141 -DZIG_TARGET_MCPU="$MCPU" \
4242 -DZIG_STATIC=ON \
43 -DZIG_NO_LIB=ON \
4344 -GNinja
4445
4546# Now cmake will use zig as the C/C++ compiler. We reset the environment variables
......@@ -49,6 +50,7 @@ unset CXX
4950
5051ninja install
5152
53# TODO: move this to a build.zig step (check-fmt)
5254echo "Looking for non-conforming code formatting..."
5355stage3-release/bin/zig fmt --check .. \
5456 --exclude ../test/cases/ \
......@@ -56,7 +58,9 @@ stage3-release/bin/zig fmt --check .. \
5658 --exclude ../build-release
5759
5860# simultaneously test building self-hosted without LLVM and with 32-bit arm
59stage3-release/bin/zig build -Dtarget=arm-linux-musleabihf
61stage3-release/bin/zig build \
62 -Dtarget=arm-linux-musleabihf \
63 -Dno-lib
6064
6165stage3-release/bin/zig build test docs \
6266 --maxrss 21000000000 \
......@@ -68,10 +72,8 @@ stage3-release/bin/zig build test docs \
6872 --zig-lib-dir "$(pwd)/../lib"
6973
7074# Look for HTML errors.
71tidy --drop-empty-elements no -qe "stage3-release/doc/langref.html"
72
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
75# TODO: move this to a build.zig flag (-Denable-tidy)
76tidy --drop-empty-elements no -qe "zig-out/doc/langref.html"
7577
7678# Ensure that stage3 and stage4 are byte-for-byte identical.
7779stage3-release/bin/zig build \
......@@ -107,6 +109,7 @@ cmake .. \
107109 -DZIG_TARGET_TRIPLE="$TARGET" \
108110 -DZIG_TARGET_MCPU="$MCPU" \
109111 -DZIG_STATIC=ON \
112 -DZIG_NO_LIB=ON \
110113 -GNinja
111114
112115unset CC
......@@ -118,6 +121,7 @@ stage3/bin/zig test ../test/behavior.zig -I../test
118121stage3/bin/zig build -p stage4 \
119122 -Dstatic-llvm \
120123 -Dtarget=native-native-musl \
124 -Dno-lib \
121125 --search-prefix "$PREFIX" \
122126 --zig-lib-dir "$(pwd)/../lib"
123127stage4/bin/zig test ../test/behavior.zig -I../test
ci/x86_64-macos-release.sh+2-4
......@@ -43,7 +43,8 @@ cmake .. \
4343 -DCMAKE_CXX_COMPILER="$ZIG;c++;-target;$TARGET;-mcpu=$MCPU" \
4444 -DZIG_TARGET_TRIPLE="$TARGET" \
4545 -DZIG_TARGET_MCPU="$MCPU" \
46 -DZIG_STATIC=ON
46 -DZIG_STATIC=ON \
47 -DZIG_NO_LIB=ON
4748
4849make $JOBS install
4950
......@@ -54,9 +55,6 @@ stage3/bin/zig build test docs \
5455 -Dskip-non-native \
5556 --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
6058# Ensure that stage3 and stage4 are byte-for-byte identical.
6159stage3/bin/zig build \
6260 --prefix stage4 \
ci/x86_64-windows-debug.ps1+2-8
......@@ -45,7 +45,8 @@ Set-Location -Path 'build-debug'
4545 -DCMAKE_CXX_COMPILER="$($ZIG -Replace "\\", "/");c++;-target;$TARGET;-mcpu=$MCPU" `
4646 -DZIG_TARGET_TRIPLE="$TARGET" `
4747 -DZIG_TARGET_MCPU="$MCPU" `
48 -DZIG_STATIC=ON
48 -DZIG_STATIC=ON `
49 -DZIG_NO_LIB=ON
4950CheckLastExitCode
5051
5152ninja install
......@@ -60,13 +61,6 @@ Write-Output "Main test suite..."
6061 -Denable-symlinks-windows
6162CheckLastExitCode
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
7064Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..."
7165& "stage3-debug\bin\zig.exe" test `
7266 ..\test\behavior.zig `
ci/x86_64-windows-release.ps1+2-8
......@@ -45,7 +45,8 @@ Set-Location -Path 'build-release'
4545 -DCMAKE_CXX_COMPILER="$($ZIG -Replace "\\", "/");c++;-target;$TARGET;-mcpu=$MCPU" `
4646 -DZIG_TARGET_TRIPLE="$TARGET" `
4747 -DZIG_TARGET_MCPU="$MCPU" `
48 -DZIG_STATIC=ON
48 -DZIG_STATIC=ON `
49 -DZIG_NO_LIB=ON
4950CheckLastExitCode
5051
5152ninja install
......@@ -60,13 +61,6 @@ Write-Output "Main test suite..."
6061 -Denable-symlinks-windows
6162CheckLastExitCode
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
7064Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..."
7165& "stage3-release\bin\zig.exe" test `
7266 ..\test\behavior.zig `
lib/std/Build/Step/Compile.zig+17-3
......@@ -49,7 +49,6 @@ verbose_cc: bool,
4949emit_analysis: EmitOption = .default,
5050emit_asm: EmitOption = .default,
5151emit_bin: EmitOption = .default,
52emit_docs: EmitOption = .default,
5352emit_implib: EmitOption = .default,
5453emit_llvm_bc: EmitOption = .default,
5554emit_llvm_ir: EmitOption = .default,
......@@ -217,6 +216,7 @@ output_lib_path_source: GeneratedFile,
217216output_h_path_source: GeneratedFile,
218217output_pdb_path_source: GeneratedFile,
219218output_dirname_source: GeneratedFile,
219generated_docs: ?*GeneratedFile,
220220
221221pub const CSourceFiles = struct {
222222 files: []const []const u8,
......@@ -433,7 +433,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
433433 }) catch @panic("OOM");
434434
435435 const self = owner.allocator.create(Compile) catch @panic("OOM");
436 self.* = Compile{
436 self.* = .{
437437 .strip = null,
438438 .unwind_tables = null,
439439 .verbose_link = false,
......@@ -486,6 +486,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
486486 .output_h_path_source = GeneratedFile{ .step = &self.step },
487487 .output_pdb_path_source = GeneratedFile{ .step = &self.step },
488488 .output_dirname_source = GeneratedFile{ .step = &self.step },
489 .generated_docs = null,
489490
490491 .target_info = target_info,
491492
......@@ -1004,6 +1005,15 @@ pub fn getOutputPdbSource(self: *Compile) FileSource {
10041005 return .{ .generated = &self.output_pdb_path_source };
10051006}
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
10071017pub fn addAssemblyFile(self: *Compile, path: []const u8) void {
10081018 const b = self.step.owner;
10091019 self.link_objects.append(.{
......@@ -1509,7 +1519,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
15091519 if (self.emit_analysis.getArg(b, "emit-analysis")) |arg| try zig_args.append(arg);
15101520 if (self.emit_asm.getArg(b, "emit-asm")) |arg| try zig_args.append(arg);
15111521 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");
15131523 if (self.emit_implib.getArg(b, "emit-implib")) |arg| try zig_args.append(arg);
15141524 if (self.emit_llvm_bc.getArg(b, "emit-llvm-bc")) |arg| try zig_args.append(arg);
15151525 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 {
20222032 &.{ output_dir, self.out_pdb_filename },
20232033 );
20242034 }
2035
2036 if (self.generated_docs) |generated_docs| {
2037 generated_docs.path = b.pathJoin(&.{ output_dir, "docs" });
2038 }
20252039 }
20262040
20272041 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);
1515const renderer = @import("autodoc/render_source.zig");
1616
1717comp_module: *CompilationModule,
18doc_location: Compilation.EmitLoc,
1918arena: std.mem.Allocator,
2019
2120// The goal of autodoc is to fill up these arrays
......@@ -74,28 +73,23 @@ const Section = struct {
7473 };
7574};
7675
77var arena_allocator: std.heap.ArenaAllocator = undefined;
78pub fn init(m: *CompilationModule, doc_location: Compilation.EmitLoc) Autodoc {
79 arena_allocator = std.heap.ArenaAllocator.init(m.gpa);
80 return .{
81 .comp_module = m,
82 .doc_location = doc_location,
76pub fn generate(cm: *CompilationModule, output_dir: std.fs.Dir) !void {
77 var arena_allocator = std.heap.ArenaAllocator.init(cm.gpa);
78 defer arena_allocator.deinit();
79 var autodoc: Autodoc = .{
80 .comp_module = cm,
8381 .arena = arena_allocator.allocator(),
8482 };
85}
83 try autodoc.generateZirData(output_dir);
8684
87pub fn deinit(_: *Autodoc) void {
88 arena_allocator.deinit();
85 const lib_dir = cm.comp.zig_lib_directory.handle;
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", .{});
8990}
9091
91/// The entry point of the Autodoc generation process.
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
92fn generateZirData(self: *Autodoc, output_dir: std.fs.Dir) !void {
9993 const root_src_dir = self.comp_module.main_pkg.root_src_directory;
10094 const root_src_path = self.comp_module.main_pkg.root_src_path;
10195 const joined_src_path = try root_src_dir.join(self.arena, &.{root_src_path});
......@@ -362,19 +356,6 @@ pub fn generateZirData(self: *Autodoc) !void {
362356 .guide_sections = self.guide_sections,
363357 };
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
378359 {
379360 const data_js_f = try output_dir.createFile("data.js", .{});
380361 defer data_js_f.close();
......@@ -386,7 +367,7 @@ pub fn generateZirData(self: *Autodoc) !void {
386367 \\ var zigAnalysis=
387368 , .{});
388369 try std.json.stringifyArbitraryDepth(
389 arena_allocator.allocator(),
370 self.arena,
390371 data,
391372 .{
392373 .whitespace = .minified,
......@@ -439,14 +420,6 @@ pub fn generateZirData(self: *Autodoc) !void {
439420 try buffer.flush();
440421 }
441422 }
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", .{});
450423}
451424
452425/// 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,
118118whole_bin_sub_path: ?[]u8,
119119/// Same as `whole_bin_sub_path` but for implibs.
120120whole_implib_sub_path: ?[]u8,
121whole_docs_sub_path: ?[]u8,
121122zig_lib_directory: Directory,
122123local_cache_directory: Directory,
123124global_cache_directory: Directory,
......@@ -179,7 +180,6 @@ emit_asm: ?EmitLoc,
179180emit_llvm_ir: ?EmitLoc,
180181emit_llvm_bc: ?EmitLoc,
181182emit_analysis: ?EmitLoc,
182emit_docs: ?EmitLoc,
183183
184184work_queue_wait_group: WaitGroup = .{},
185185astgen_wait_group: WaitGroup = .{},
......@@ -1119,6 +1119,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
11191119 cache.hash.addOptional(options.dwarf_format);
11201120 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_bin);
11211121 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_implib);
1122 cache_helpers.addOptionalEmitLoc(&cache.hash, options.emit_docs);
11221123 cache.hash.addBytes(options.root_name);
11231124 if (options.target.os.tag == .wasi) cache.hash.add(wasi_exec_model);
11241125 // TODO audit this and make sure everything is in it
......@@ -1171,8 +1172,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
11711172 // For whole cache mode, it is still used for builtin.zig so that the file
11721173 // path to builtin.zig can remain consistent during a debugging session at
11731174 // 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 available
1175 // after the compilation is complete.
1175 // until the final cache hash, which is available after the
1176 // compilation is complete.
11761177 //
11771178 // Therefore, in whole cache mode, we additionally create a temporary cache
11781179 // directory for these two kinds of build artifacts, and then rename it
......@@ -1346,6 +1347,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
13461347 };
13471348 }
13481349
1350 // In case of whole cache mode, `whole_bin_sub_path` is used to distinguish
1351 // between -femit-bin and -fno-emit-bin.
13491352 switch (cache_mode) {
13501353 .whole => break :blk null,
13511354 .incremental => {},
......@@ -1408,6 +1411,34 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14081411 };
14091412 };
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
14111442 // This is so that when doing `CacheMode.whole`, the mechanism in update()
14121443 // can use it for communicating the result directory via `bin_file.emit`.
14131444 // This is used to distinguish between -fno-emit-bin and -femit-bin
......@@ -1417,6 +1448,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14171448 const whole_bin_sub_path: ?[]u8 = try prepareWholeEmitSubPath(arena, options.emit_bin);
14181449 // Same thing but for implibs.
14191450 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
14211453 var system_libs: std.StringArrayHashMapUnmanaged(SystemLib) = .{};
14221454 errdefer system_libs.deinit(gpa);
......@@ -1428,6 +1460,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
14281460 const bin_file = try link.File.openPath(gpa, .{
14291461 .emit = bin_file_emit,
14301462 .implib_emit = implib_emit,
1463 .docs_emit = docs_emit,
14311464 .root_name = root_name,
14321465 .module = module,
14331466 .target = options.target,
......@@ -1552,11 +1585,11 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
15521585 .bin_file = bin_file,
15531586 .whole_bin_sub_path = whole_bin_sub_path,
15541587 .whole_implib_sub_path = whole_implib_sub_path,
1588 .whole_docs_sub_path = whole_docs_sub_path,
15551589 .emit_asm = options.emit_asm,
15561590 .emit_llvm_ir = options.emit_llvm_ir,
15571591 .emit_llvm_bc = options.emit_llvm_bc,
15581592 .emit_analysis = options.emit_analysis,
1559 .emit_docs = options.emit_docs,
15601593 .work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
15611594 .anon_work_queue = std.fifo.LinearFifo(Job, .Dynamic).init(gpa),
15621595 .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
19401973 };
19411974 };
19421975
1943 // This updates the output directory for stage1 backend and linker outputs.
1976 // This updates the output directory for linker outputs.
19441977 if (comp.bin_file.options.module) |module| {
19451978 module.zig_cache_artifact_directory = tmp_artifact_directory.?;
19461979 }
......@@ -1960,6 +1993,12 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
19601993 .sub_path = std.fs.path.basename(sub_path),
19611994 };
19621995 }
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 }
19632002 var old_bin_file = comp.bin_file;
19642003 comp.bin_file = try link.File.openPath(comp.gpa, options);
19652004 old_bin_file.destroy();
......@@ -2064,16 +2103,6 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
20642103 return;
20652104 }
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
20772106 // Flush takes care of -femit-bin, but we still have -femit-llvm-ir, -femit-llvm-bc, and
20782107 // -femit-asm to handle, in the case of C objects.
20792108 comp.emitOthers();
......@@ -2122,12 +2151,21 @@ pub fn update(comp: *Compilation, main_progress_node: *std.Progress.Node) !void
21222151 };
21232152
21242153 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 }
21252166 } else {
21262167 try comp.flush(main_progress_node);
2127 }
2128
2129 if (comp.totalErrorCount() != 0) {
2130 return;
2168 if (comp.totalErrorCount() != 0) return;
21312169 }
21322170
21332171 // Failure here only means an unnecessary cache miss.
......@@ -2190,6 +2228,15 @@ fn wholeCacheModeSetBinFilePath(comp: *Compilation, digest: *const [Cache.hex_di
21902228 .sub_path = sub_path,
21912229 };
21922230 }
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 }
21932240}
21942241
21952242fn prepareWholeEmitSubPath(arena: Allocator, opt_emit: ?EmitLoc) error{OutOfMemory}!?[]u8 {
......@@ -2265,7 +2312,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes
22652312 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_ir);
22662313 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_llvm_bc);
22672314 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_analysis);
2268 cache_helpers.addOptionalEmitLoc(&man.hash, comp.emit_docs);
22692315
22702316 man.hash.addListOfBytes(comp.clang_argv);
22712317
src/link.zig+3-1
......@@ -71,8 +71,10 @@ pub const Emit = struct {
7171pub const Options = struct {
7272 /// This is `null` when `-fno-emit-bin` is used.
7373 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.
7575 implib_emit: ?Emit,
76 /// This is non-null when `-femit-docs` is provided.
77 docs_emit: ?Emit,
7678 target: std.Target,
7779 output_mode: std.builtin.OutputMode,
7880 link_mode: std.builtin.LinkMode,
src/main.zig+27-10
......@@ -622,7 +622,7 @@ const Emit = union(enum) {
622622 }
623623 };
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 {
626626 var resolved: Resolved = .{ .data = null, .dir = null };
627627 errdefer resolved.deinit();
628628
......@@ -630,7 +630,10 @@ const Emit = union(enum) {
630630 .no => {},
631631 .yes_default_path => {
632632 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 },
634637 .basename = default_basename,
635638 };
636639 },
......@@ -2750,7 +2753,7 @@ fn buildOutputType(
27502753 };
27512754
27522755 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| {
27542757 switch (emit_h) {
27552758 .yes => |p| {
27562759 fatal("unable to open directory from argument '-femit-h', '{s}': {s}", .{
......@@ -2768,7 +2771,7 @@ fn buildOutputType(
27682771 defer emit_h_resolved.deinit();
27692772
27702773 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| {
27722775 switch (emit_asm) {
27732776 .yes => |p| {
27742777 fatal("unable to open directory from argument '-femit-asm', '{s}': {s}", .{
......@@ -2786,7 +2789,7 @@ fn buildOutputType(
27862789 defer emit_asm_resolved.deinit();
27872790
27882791 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| {
27902793 switch (emit_llvm_ir) {
27912794 .yes => |p| {
27922795 fatal("unable to open directory from argument '-femit-llvm-ir', '{s}': {s}", .{
......@@ -2804,7 +2807,7 @@ fn buildOutputType(
28042807 defer emit_llvm_ir_resolved.deinit();
28052808
28062809 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| {
28082811 switch (emit_llvm_bc) {
28092812 .yes => |p| {
28102813 fatal("unable to open directory from argument '-femit-llvm-bc', '{s}': {s}", .{
......@@ -2822,7 +2825,7 @@ fn buildOutputType(
28222825 defer emit_llvm_bc_resolved.deinit();
28232826
28242827 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| {
28262829 switch (emit_analysis) {
28272830 .yes => |p| {
28282831 fatal("unable to open directory from argument '-femit-analysis', '{s}': {s}", .{
......@@ -2839,7 +2842,7 @@ fn buildOutputType(
28392842 };
28402843 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| {
28432846 switch (emit_docs) {
28442847 .yes => |p| {
28452848 fatal("unable to open directory from argument '-femit-docs', '{s}': {s}", .{
......@@ -2873,7 +2876,7 @@ fn buildOutputType(
28732876 const default_implib_basename = try std.fmt.allocPrint(arena, "{s}.lib", .{root_name});
28742877 var emit_implib_resolved = switch (emit_implib) {
28752878 .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| {
28772880 fatal("unable to open directory from argument '-femit-implib', '{s}': {s}", .{
28782881 p, @errorName(err),
28792882 });
......@@ -3566,7 +3569,21 @@ fn serveUpdateResults(s: *Server, comp: *Compilation) !void {
35663569 defer error_bundle.deinit(gpa);
35673570 if (error_bundle.errorMessageCount() > 0) {
35683571 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| {
35703587 const full_path = try emit.directory.join(gpa, &.{emit.sub_path});
35713588 defer gpa.free(full_path);
35723589 try s.serveEmitBinPath(full_path, .{