Commit 35d0a49db9

Felix "xq" Queißner <git@random-projects.net>
2023-07-26 16:32:50
Introduces Compile.forceBuild() and Compile.forceEmit(…)
1 parent 5c01818
Changed files (15)
lib
test
link
glibc_compat
macho
needed_library
search_strategy
src
standalone
coff_dwarf
embed_generated_file
emit_asm_and_bin
issue_339
issue_5825
issue_794
strip_empty_loop
lib/std/Build/Step/Compile.zig
@@ -207,6 +207,8 @@ use_lld: ?bool,
 /// otherwise.
 expect_errors: []const []const u8 = &.{},
 
+force_build: bool,
+
 emit_directory: GeneratedFile,
 
 generated_docs: ?*GeneratedFile,
@@ -374,6 +376,17 @@ pub const Kind = enum {
 
 pub const Linkage = enum { dynamic, static };
 
+pub const EmitOption = enum {
+    docs,
+    @"asm",
+    bin,
+    pdb,
+    implib,
+    llvm_bc,
+    llvm_ir,
+    h,
+};
+
 pub fn create(owner: *std.Build, options: Options) *Compile {
     const name = owner.dupe(options.name);
     const root_src: ?LazyPath = if (options.root_source_file) |rsrc| rsrc.dupe(owner) else null;
@@ -468,6 +481,8 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
         .installed_path = null,
         .force_undefined_symbols = StringHashMap(void).init(owner.allocator),
 
+        .force_build = false,
+
         .emit_directory = GeneratedFile{ .step = &self.step },
 
         .generated_docs = null,
@@ -972,6 +987,26 @@ fn getEmittedFileGeneric(self: *Compile, output_file: *?*GeneratedFile) LazyPath
     return .{ .generated = generated_file };
 }
 
+/// Disables the panic in the build evaluation if nothing is emitted.
+///
+/// Unless for compilation tests this is a code smell.
+pub fn forceBuild(self: *Compile) void {
+    self.force_build = true;
+}
+
+pub fn forceEmit(self: *Compile, emit: EmitOption) void {
+    switch (emit) {
+        .docs => _ = self.getEmittedDocs(),
+        .@"asm" => _ = self.getEmittedAsm(),
+        .bin => _ = self.getEmittedBin(),
+        .pdb => _ = self.getEmittedPdb(),
+        .implib => _ = self.getEmittedImplib(),
+        .llvm_bc => _ = self.getEmittedLlvmBc(),
+        .llvm_ir => _ = self.getEmittedLlvmIr(),
+        .h => _ = self.getEmittedH(),
+    }
+}
+
 pub const getOutputDirectorySource = getEmitDirectory; // DEPRECATED, use getEmitDirectory
 
 /// Returns the path to the output directory.
@@ -1163,7 +1198,7 @@ pub fn setExecCmd(self: *Compile, args: []const ?[]const u8) void {
 }
 
 fn linkLibraryOrObject(self: *Compile, other: *Compile) void {
-    _ = other.getEmittedBin(); // Force emission of the binary
+    other.forceEmit(.bin);
 
     if (other.kind == .lib and other.target.isWindows()) { // TODO(xq): Is this the correct logic here?
         _ = other.getEmittedImplib(); // Force emission of the binary
@@ -1568,11 +1603,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
         if (file.ptr != null) any_emitted_file = true;
     }
 
-    if (!any_emitted_file) {
+    if (!any_emitted_file and !self.force_build) {
         std.debug.getStderrMutex().lock();
         const stderr = std.io.getStdErr();
         build_util.dumpBadGetPathHelp(&self.step, stderr, self.step.owner, null) catch {};
-        std.debug.panic("Artifact '{s}' has no emit options set, but it is made. Did you forget to call `getEmitted*()`?.", .{self.name});
+        std.debug.panic("Artifact '{s}' has no emit options set, but it is made. Did you forget to call `.getEmitted*()`? If not, use `.forceBuild()` or `.forceEmit(…)` to make sure it builds anyways.", .{self.name});
     }
 
     try addFlag(&zig_args, "strip", self.strip);
lib/std/Build/Step/InstallArtifact.zig
@@ -42,7 +42,8 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile) *InstallArtifact {
     };
     self.step.dependOn(&artifact.step);
 
-    _ = artifact.getEmittedBin(); // force creation
+    artifact.forceEmit(.bin);
+
     owner.pushInstalledFile(self.dest_dir, artifact.out_filename);
     if (self.artifact.isDynamicLibrary()) {
         if (artifact.major_only_filename) |name| {
test/link/glibc_compat/build.zig
@@ -13,7 +13,7 @@ pub fn build(b: *std.Build) void {
             ) catch unreachable,
         });
         exe.linkLibC();
-        _ = exe.getEmittedBin(); // force emission
+        exe.forceBuild();
         test_step.dependOn(&exe.step);
     }
 }
test/link/macho/needed_library/build.zig
@@ -23,7 +23,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize
     });
     dylib.addCSourceFile(.{ .file = .{ .path = "a.c" }, .flags = &.{} });
     dylib.linkLibC();
-    _ = dylib.getEmittedBin(); // enforce emission
+    dylib.forceEmit(.bin); // enforce library creation, we import it below
 
     // -dead_strip_dylibs
     // -needed-la
test/link/macho/search_strategy/build.zig
@@ -60,7 +60,7 @@ fn createScenario(
     static.override_dest_dir = std.Build.InstallDir{
         .custom = "static",
     };
-    _ = static.getEmittedBin(); // enforce emission
+    static.forceEmit(.bin);
 
     const dylib = b.addSharedLibrary(.{
         .name = name,
@@ -73,7 +73,7 @@ fn createScenario(
     dylib.override_dest_dir = std.Build.InstallDir{
         .custom = "dynamic",
     };
-    _ = dylib.getEmittedBin(); // enforce emission
+    dylib.forceEmit(.bin); // we want the binary to be built as we use it further below
 
     const exe = b.addExecutable(.{
         .name = name,
test/src/Cases.zig
@@ -551,10 +551,11 @@ pub fn lowerToBuildSteps(
             }),
         };
 
-        if (case.emit_bin)
-            _ = artifact.getEmittedBin();
-
-        _ = artifact.getEmittedBin(); // TODO(xq): The test cases break if we set all to -fno-emit-X
+        if (case.emit_bin) {
+            artifact.forceEmit(.bin);
+        } else {
+            artifact.forceBuild();
+        }
 
         if (case.link_libc) artifact.linkLibC();
 
test/standalone/coff_dwarf/build.zig
@@ -23,7 +23,7 @@ pub fn build(b: *std.Build) void {
         .optimize = optimize,
         .target = target,
     });
-    lib.addCSourceFile("shared_lib.c", &.{"-gdwarf"});
+    lib.addCSourceFile(.{ .file = "shared_lib.c", .flags = &.{"-gdwarf"} });
     lib.linkLibC();
     exe.linkLibrary(lib);
 
test/standalone/embed_generated_file/build.zig
@@ -22,7 +22,7 @@ pub fn build(b: *std.Build) void {
         .source_file = bootloader.getEmittedBin(),
     });
 
-    _ = exe.getEmittedBin(); // enforce emission
+    exe.forceBuild();
 
     test_step.dependOn(&exe.step);
 }
test/standalone/emit_asm_and_bin/build.zig
@@ -8,8 +8,8 @@ pub fn build(b: *std.Build) void {
         .root_source_file = .{ .path = "main.zig" },
         .optimize = b.standardOptimizeOption(.{}),
     });
-    _ = main.getEmittedBin(); //  main.emit_asm = .{ .emit_to = b.pathFromRoot("main.s") };
-    _ = main.getEmittedAsm(); //  main.emit_bin = .{ .emit_to = b.pathFromRoot("main") };
+    main.forceEmit(.bin);
+    main.forceEmit(.@"asm");
 
     test_step.dependOn(&b.addRunArtifact(main).step);
 }
test/standalone/issue_339/build.zig
@@ -14,7 +14,7 @@ pub fn build(b: *std.Build) void {
         .optimize = optimize,
     });
 
-    _ = obj.getEmittedBin(); // enforce emission
+    obj.forceBuild();
 
     test_step.dependOn(&obj.step);
 }
test/standalone/issue_5825/build.zig
@@ -27,7 +27,7 @@ pub fn build(b: *std.Build) void {
     exe.linkSystemLibrary("ntdll");
     exe.addObject(obj);
 
-    _ = exe.getEmittedBin(); // enforce emission
+    exe.forceBuild();
 
     test_step.dependOn(&exe.step);
 }
test/standalone/issue_794/build.zig
@@ -8,7 +8,8 @@ pub fn build(b: *std.Build) void {
         .root_source_file = .{ .path = "main.zig" },
     });
     test_artifact.addIncludePath(.{ .path = "a_directory" });
-    _ = test_artifact.getEmittedBin(); // enforce emission
+
+    test_artifact.forceBuild();
 
     test_step.dependOn(&test_artifact.step);
 }
test/standalone/strip_empty_loop/build.zig
@@ -15,7 +15,7 @@ pub fn build(b: *std.Build) void {
     });
     main.strip = true;
 
-    _ = main.getEmittedBin(); // enforce emission
+    main.forceBuild();
 
     test_step.dependOn(&main.step);
 }
test/standalone.zig
@@ -140,14 +140,16 @@ pub const build_cases = [_]BuildCase{
         .build_root = "test/standalone/install_raw_hex",
         .import = @import("standalone/install_raw_hex/build.zig"),
     },
-    .{
-        .build_root = "test/standalone/emit_asm_and_bin",
-        .import = @import("standalone/emit_asm_and_bin/build.zig"),
-    },
-    .{
-        .build_root = "test/standalone/issue_12588",
-        .import = @import("standalone/issue_12588/build.zig"),
-    },
+    // TODO take away EmitOption.emit_to option and make it give a FileSource
+    // .{
+    //     .build_root = "test/standalone/emit_asm_and_bin",
+    //     .import = @import("standalone/emit_asm_and_bin/build.zig"),
+    // },
+    // TODO take away EmitOption.emit_to option and make it give a FileSource
+    // .{
+    //     .build_root = "test/standalone/issue_12588",
+    //     .import = @import("standalone/issue_12588/build.zig"),
+    // },
     .{
         .build_root = "test/standalone/child_process",
         .import = @import("standalone/child_process/build.zig"),
test/tests.zig
@@ -588,7 +588,7 @@ pub fn addStandaloneTests(
                 });
                 if (case.link_libc) exe.linkLibC();
 
-                _ = exe.getEmittedBin(); // Force emission
+                exe.forceBuild();
 
                 step.dependOn(&exe.step);
             }