diff --git a/build.zig b/build.zig index 07130e84b051..a7d74bdc06ae 100644 --- a/build.zig +++ b/build.zig @@ -45,7 +45,8 @@ pub fn build(b: *std.Build) !void { const docgen_cmd = b.addRunArtifact(docgen_exe); docgen_cmd.addArgs(&.{ "--zig", b.zig_exe }); if (b.zig_lib_dir) |p| { - docgen_cmd.addArgs(&.{ "--zig-lib-dir", b.pathFromRoot(p) }); + docgen_cmd.addArg("--zig-lib-dir"); + docgen_cmd.addFileArg(p); } docgen_cmd.addFileArg(.{ .path = "doc/langref.html.in" }); const langref_file = docgen_cmd.addOutputFileArg("langref.html"); @@ -57,8 +58,8 @@ pub fn build(b: *std.Build) !void { const autodoc_test = b.addTest(.{ .root_source_file = .{ .path = "lib/std/std.zig" }, .target = target, + .zig_lib_dir = .{ .path = "lib" }, }); - autodoc_test.overrideZigLibDir(.{ .path = "lib" }); const install_std_docs = b.addInstallDirectory(.{ .source_dir = autodoc_test.getEmittedDocs(), .install_dir = .prefix, @@ -87,8 +88,8 @@ pub fn build(b: *std.Build) !void { .name = "check-case", .root_source_file = .{ .path = "test/src/Cases.zig" }, .optimize = optimize, + .main_pkg_path = .{ .path = "." }, }); - check_case_exe.setMainPkgPath(.{ .path = "." }); check_case_exe.stack_size = stack_size; check_case_exe.single_threaded = single_threaded; @@ -203,7 +204,7 @@ pub fn build(b: *std.Build) !void { ); if (!no_bin) { - const install_exe = b.addInstallArtifact(exe); + const install_exe = b.addInstallArtifact(exe, .{}); if (flat) { install_exe.dest_dir = .prefix; } @@ -357,8 +358,8 @@ pub fn build(b: *std.Build) !void { else &[_][]const u8{ "-DTRACY_ENABLE=1", "-fno-sanitize=undefined" }; - exe.addIncludePath(.{ .path = tracy_path }); - exe.addCSourceFile(.{ .file = .{ .path = client_cpp }, .flags = tracy_c_flags }); + exe.addIncludePath(.{ .cwd_relative = tracy_path }); + exe.addCSourceFile(.{ .file = .{ .cwd_relative = client_cpp }, .flags = tracy_c_flags }); if (!enable_llvm) { exe.linkSystemLibraryName("c++"); } @@ -597,7 +598,7 @@ fn addCmakeCfgOptionsToExe( // useful for package maintainers exe.headerpad_max_install_names = true; } - exe.addObjectFile(.{ .path = b.pathJoin(&[_][]const u8{ + exe.addObjectFile(.{ .cwd_relative = b.pathJoin(&[_][]const u8{ cfg.cmake_binary_dir, "zigcpp", b.fmt("{s}{s}{s}", .{ @@ -607,9 +608,9 @@ fn addCmakeCfgOptionsToExe( }), }) }); assert(cfg.lld_include_dir.len != 0); - exe.addIncludePath(.{ .path = cfg.lld_include_dir }); - exe.addIncludePath(.{ .path = cfg.llvm_include_dir }); - exe.addLibraryPath(.{ .path = cfg.llvm_lib_dir }); + exe.addIncludePath(.{ .cwd_relative = cfg.lld_include_dir }); + exe.addIncludePath(.{ .cwd_relative = cfg.llvm_include_dir }); + exe.addLibraryPath(.{ .cwd_relative = cfg.llvm_lib_dir }); addCMakeLibraryList(exe, cfg.clang_libraries); addCMakeLibraryList(exe, cfg.lld_libraries); addCMakeLibraryList(exe, cfg.llvm_libraries); @@ -665,7 +666,7 @@ fn addCmakeCfgOptionsToExe( } if (cfg.dia_guids_lib.len != 0) { - exe.addObjectFile(.{ .path = cfg.dia_guids_lib }); + exe.addObjectFile(.{ .cwd_relative = cfg.dia_guids_lib }); } } @@ -726,7 +727,7 @@ fn addCxxKnownPath( } return error.RequiredLibraryNotFound; } - exe.addObjectFile(.{ .path = path_unpadded }); + exe.addObjectFile(.{ .cwd_relative = path_unpadded }); // TODO a way to integrate with system c++ include files here // c++ -E -Wp,-v -xc++ /dev/null @@ -746,7 +747,7 @@ fn addCMakeLibraryList(exe: *std.Build.Step.Compile, list: []const u8) void { } else if (exe.target.isWindows() and mem.endsWith(u8, lib, ".lib") and !fs.path.isAbsolute(lib)) { exe.linkSystemLibrary(lib[0 .. lib.len - ".lib".len]); } else { - exe.addObjectFile(.{ .path = lib }); + exe.addObjectFile(.{ .cwd_relative = lib }); } } } diff --git a/lib/build_runner.zig b/lib/build_runner.zig index cdedba90b2d6..7d036fa5bf4b 100644 --- a/lib/build_runner.zig +++ b/lib/build_runner.zig @@ -188,10 +188,10 @@ pub fn main() !void { usageAndErr(builder, false, stderr_stream); }; } else if (mem.eql(u8, arg, "--zig-lib-dir")) { - builder.zig_lib_dir = nextArg(args, &arg_idx) orelse { + builder.zig_lib_dir = .{ .cwd_relative = nextArg(args, &arg_idx) orelse { std.debug.print("Expected argument after {s}\n\n", .{arg}); usageAndErr(builder, false, stderr_stream); - }; + } }; } else if (mem.eql(u8, arg, "--debug-log")) { const next_arg = nextArg(args, &arg_idx) orelse { std.debug.print("Expected argument after {s}\n\n", .{arg}); diff --git a/lib/std/Build.zig b/lib/std/Build.zig index 08da650d640b..a7dc16e75dd6 100644 --- a/lib/std/Build.zig +++ b/lib/std/Build.zig @@ -19,8 +19,6 @@ const NativeTargetInfo = std.zig.system.NativeTargetInfo; const Sha256 = std.crypto.hash.sha2.Sha256; const Build = @This(); -const build_util = @import("Build/util.zig"); - pub const Cache = @import("Build/Cache.zig"); /// deprecated: use `Step.Compile`. @@ -59,6 +57,8 @@ pub const RunStep = @import("Build/Step/Run.zig"); pub const TranslateCStep = @import("Build/Step/TranslateC.zig"); /// deprecated: use `Step.WriteFile`. pub const WriteFileStep = @import("Build/Step/WriteFile.zig"); +/// deprecated: use `LazyPath`. +pub const FileSource = LazyPath; install_tls: TopLevelStep, uninstall_tls: TopLevelStep, @@ -95,8 +95,7 @@ build_root: Cache.Directory, cache_root: Cache.Directory, global_cache_root: Cache.Directory, cache: *Cache, -/// If non-null, overrides the default zig lib dir. -zig_lib_dir: ?[]const u8, +zig_lib_dir: ?LazyPath, vcpkg_root: VcpkgRoot = .unattempted, pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null, args: ?[][]const u8 = null, @@ -483,6 +482,8 @@ pub const ExecutableOptions = struct { single_threaded: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, + zig_lib_dir: ?LazyPath = null, + main_pkg_path: ?LazyPath = null, }; pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile { @@ -499,6 +500,8 @@ pub fn addExecutable(b: *Build, options: ExecutableOptions) *Step.Compile { .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, + .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, + .main_pkg_path = options.main_pkg_path, }); } @@ -512,6 +515,8 @@ pub const ObjectOptions = struct { single_threaded: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, + zig_lib_dir: ?LazyPath = null, + main_pkg_path: ?LazyPath = null, }; pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile { @@ -526,6 +531,8 @@ pub fn addObject(b: *Build, options: ObjectOptions) *Step.Compile { .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, + .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, + .main_pkg_path = options.main_pkg_path, }); } @@ -540,6 +547,8 @@ pub const SharedLibraryOptions = struct { single_threaded: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, + zig_lib_dir: ?LazyPath = null, + main_pkg_path: ?LazyPath = null, }; pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile { @@ -556,6 +565,8 @@ pub fn addSharedLibrary(b: *Build, options: SharedLibraryOptions) *Step.Compile .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, + .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, + .main_pkg_path = options.main_pkg_path, }); } @@ -570,6 +581,8 @@ pub const StaticLibraryOptions = struct { single_threaded: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, + zig_lib_dir: ?LazyPath = null, + main_pkg_path: ?LazyPath = null, }; pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile { @@ -586,6 +599,8 @@ pub fn addStaticLibrary(b: *Build, options: StaticLibraryOptions) *Step.Compile .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, + .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, + .main_pkg_path = options.main_pkg_path, }); } @@ -602,6 +617,8 @@ pub const TestOptions = struct { single_threaded: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, + zig_lib_dir: ?LazyPath = null, + main_pkg_path: ?LazyPath = null, }; pub fn addTest(b: *Build, options: TestOptions) *Step.Compile { @@ -618,6 +635,8 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile { .single_threaded = options.single_threaded, .use_llvm = options.use_llvm, .use_lld = options.use_lld, + .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, + .main_pkg_path = options.main_pkg_path, }); } @@ -627,6 +646,7 @@ pub const AssemblyOptions = struct { target: CrossTarget, optimize: std.builtin.Mode, max_rss: usize = 0, + zig_lib_dir: ?LazyPath = null, }; pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile { @@ -637,6 +657,7 @@ pub fn addAssembly(b: *Build, options: AssemblyOptions) *Step.Compile { .target = options.target, .optimize = options.optimize, .max_rss = options.max_rss, + .zig_lib_dir = options.zig_lib_dir orelse b.zig_lib_dir, }); obj_step.addAssemblyLazyPath(options.source_file.dupe(b)); return obj_step; @@ -1259,12 +1280,21 @@ fn printCmd(ally: Allocator, cwd: ?[]const u8, argv: []const []const u8) void { std.debug.print("{s}\n", .{text}); } +/// This creates the install step and adds it to the dependencies of the +/// top-level install step, using all the default options. +/// See `addInstallArtifact` for a more flexible function. pub fn installArtifact(self: *Build, artifact: *Step.Compile) void { - self.getInstallStep().dependOn(&self.addInstallArtifact(artifact).step); + self.getInstallStep().dependOn(&self.addInstallArtifact(artifact, .{}).step); } -pub fn addInstallArtifact(self: *Build, artifact: *Step.Compile) *Step.InstallArtifact { - return Step.InstallArtifact.create(self, artifact); +/// This merely creates the step; it does not add it to the dependencies of the +/// top-level install step. +pub fn addInstallArtifact( + self: *Build, + artifact: *Step.Compile, + options: Step.InstallArtifact.Options, +) *Step.InstallArtifact { + return Step.InstallArtifact.create(self, artifact, options); } ///`dest_rel_path` is relative to prefix path @@ -1330,6 +1360,7 @@ pub fn addCheckFile( return Step.CheckFile.create(b, file_source, options); } +/// deprecated: https://github.com/ziglang/zig/issues/14943 pub fn pushInstalledFile(self: *Build, dir: InstallDir, dest_rel_path: []const u8) void { const file = InstalledFile{ .dir = dir, @@ -1632,19 +1663,27 @@ pub const GeneratedFile = struct { } }; -pub const FileSource = LazyPath; // DEPRECATED, use LazyPath now - /// A reference to an existing or future path. pub const LazyPath = union(enum) { - /// A plain file path, relative to build root or absolute. + /// A source file path relative to build root. + /// This should not be an absolute path, but in an older iteration of the zig build + /// system API, it was allowed to be absolute. Absolute paths should use `cwd_relative`. path: []const u8, /// A file that is generated by an interface. Those files usually are /// not available until built by a build step. generated: *const GeneratedFile, + /// An absolute path or a path relative to the current working directory of + /// the build runner process. + /// This is uncommon but used for system environment paths such as `--zig-lib-dir` which + /// ignore the file system path of build.zig and instead are relative to the directory from + /// which `zig build` was invoked. + /// Use of this tag indicates a dependency on the host system. + cwd_relative: []const u8, + /// Returns a new file source that will have a relative path to the build root guaranteed. - /// This should be preferred over setting `.path` directly as it documents that the files are in the project directory. + /// Asserts the parameter is not an absolute path. pub fn relative(path: []const u8) LazyPath { std.debug.assert(!std.fs.path.isAbsolute(path)); return LazyPath{ .path = path }; @@ -1654,7 +1693,7 @@ pub const LazyPath = union(enum) { /// Either returns the path or `"generated"`. pub fn getDisplayName(self: LazyPath) []const u8 { return switch (self) { - .path => self.path, + .path, .cwd_relative => self.path, .generated => "generated", }; } @@ -1662,26 +1701,34 @@ pub const LazyPath = union(enum) { /// Adds dependencies this file source implies to the given step. pub fn addStepDependencies(self: LazyPath, other_step: *Step) void { switch (self) { - .path => {}, + .path, .cwd_relative => {}, .generated => |gen| other_step.dependOn(gen.step), } } - /// Should only be called during make(), returns a path relative to the build root or absolute. + /// Returns a path relative to the current process's current working directory, suitable + /// for direct file system operations. + /// + /// Intended to be used during the make phase only. pub fn getPath(self: LazyPath, src_builder: *Build) []const u8 { return getPath2(self, src_builder, null); } - /// Should only be called during make(), returns a path relative to the build root or absolute. - /// asking_step is only used for debugging purposes; it's the step being run that is asking for - /// the path. + /// Returns a path relative to the current process's current working directory, suitable + /// for direct file system operations. + /// + /// Intended to be used during the make phase only. + /// + /// `asking_step` is only used for debugging purposes; it's the step being + /// run that is asking for the path. pub fn getPath2(self: LazyPath, src_builder: *Build, asking_step: ?*Step) []const u8 { switch (self) { .path => |p| return src_builder.pathFromRoot(p), + .cwd_relative => |p| return p, .generated => |gen| return gen.path orelse { std.debug.getStderrMutex().lock(); const stderr = std.io.getStdErr(); - build_util.dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {}; + dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {}; @panic("misconfigured build script"); }, } @@ -1691,11 +1738,60 @@ pub const LazyPath = union(enum) { pub fn dupe(self: LazyPath, b: *Build) LazyPath { return switch (self) { .path => |p| .{ .path = b.dupePath(p) }, + .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) }, .generated => |gen| .{ .generated = gen }, }; } }; +/// In this function the stderr mutex has already been locked. +pub fn dumpBadGetPathHelp( + s: *Step, + stderr: fs.File, + src_builder: *Build, + asking_step: ?*Step, +) anyerror!void { + const w = stderr.writer(); + try w.print( + \\getPath() was called on a GeneratedFile that wasn't built yet. + \\ source package path: {s} + \\ Is there a missing Step dependency on step '{s}'? + \\ + , .{ + src_builder.build_root.path orelse ".", + s.name, + }); + + const tty_config = std.io.tty.detectConfig(stderr); + tty_config.setColor(w, .red) catch {}; + try stderr.writeAll(" The step was created by this stack trace:\n"); + tty_config.setColor(w, .reset) catch {}; + + const debug_info = std.debug.getSelfDebugInfo() catch |err| { + try w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}); + return; + }; + const ally = debug_info.allocator; + std.debug.writeStackTrace(s.getStackTrace(), w, ally, debug_info, tty_config) catch |err| { + try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}); + return; + }; + if (asking_step) |as| { + tty_config.setColor(w, .red) catch {}; + try stderr.writeAll(" The step that is missing a dependency on the above step was created by this stack trace:\n"); + tty_config.setColor(w, .reset) catch {}; + + std.debug.writeStackTrace(as.getStackTrace(), w, ally, debug_info, tty_config) catch |err| { + try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}); + return; + }; + } + + tty_config.setColor(w, .red) catch {}; + try stderr.writeAll(" Hope that helps. Proceeding to panic.\n"); + tty_config.setColor(w, .reset) catch {}; +} + /// Allocates a new string for assigning a value to a named macro. /// If the value is omitted, it is set to 1. /// `name` and `value` need not live longer than the function call. diff --git a/lib/std/Build/Step.zig b/lib/std/Build/Step.zig index 274188f7f2f3..8fd60b4ad618 100644 --- a/lib/std/Build/Step.zig +++ b/lib/std/Build/Step.zig @@ -423,15 +423,7 @@ pub fn evalZigProcess( }); } - if (s.cast(Compile)) |compile| { - if (compile.generated_bin == null) // TODO(xq): How to handle this properly?! - return result; - } - - return result orelse return s.fail( - "the following command failed to communicate the compilation result:\n{s}", - .{try allocPrintCmd(arena, null, argv)}, - ); + return result; } fn sendMessage(file: std.fs.File, tag: std.zig.Client.Message.Tag) !void { diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 9898fe6df5bb..d0352b257c78 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -21,8 +21,6 @@ const InstallDir = std.Build.InstallDir; const GeneratedFile = std.Build.GeneratedFile; const Compile = @This(); -const build_util = @import("../util.zig"); - pub const base_id: Step.Id = .compile; step: Step, @@ -68,7 +66,9 @@ max_memory: ?u64 = null, shared_memory: bool = false, global_base: ?u64 = null, c_std: std.Build.CStd, +/// Set via options; intended to be read-only after that. zig_lib_dir: ?LazyPath, +/// Set via options; intended to be read-only after that. main_pkg_path: ?LazyPath, exec_cmd_args: ?[]const ?[]const u8, filter: ?[]const u8, @@ -80,12 +80,7 @@ wasi_exec_model: ?std.builtin.WasiExecModel = null, export_symbol_names: []const []const u8 = &.{}, root_src: ?LazyPath, -out_h_filename: []const u8, -out_ll_filename: []const u8, -out_bc_filename: []const u8, -out_asm_filename: []const u8, out_lib_filename: []const u8, -out_pdb_filename: []const u8, modules: std.StringArrayHashMap(*Module), link_objects: ArrayList(LinkObject), @@ -96,8 +91,6 @@ is_linking_libc: bool, is_linking_libcpp: bool, vcpkg_bin_path: ?[]const u8 = null, -/// This may be set in order to override the default install directory -override_dest_dir: ?InstallDir, installed_path: ?[]const u8, /// Base address for an executable image. @@ -207,9 +200,7 @@ use_lld: ?bool, /// otherwise. expect_errors: []const []const u8 = &.{}, -force_build: bool, - -emit_directory: GeneratedFile, +emit_directory: ?*GeneratedFile, generated_docs: ?*GeneratedFile, generated_asm: ?*GeneratedFile, @@ -221,6 +212,7 @@ generated_llvm_ir: ?*GeneratedFile, generated_h: ?*GeneratedFile, pub const CSourceFiles = struct { + /// Relative to the build root. files: []const []const u8, flags: []const []const u8, }; @@ -289,6 +281,8 @@ pub const Options = struct { single_threaded: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, + zig_lib_dir: ?LazyPath = null, + main_pkg_path: ?LazyPath = null, }; pub const BuildId = union(enum) { @@ -376,17 +370,6 @@ 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; @@ -451,12 +434,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { }), .version = options.version, .out_filename = out_filename, - .out_h_filename = owner.fmt("{s}.h", .{name}), - .out_ll_filename = owner.fmt("{s}.bc", .{name}), - .out_bc_filename = owner.fmt("{s}.ll", .{name}), - .out_asm_filename = owner.fmt("{s}.s", .{name}), .out_lib_filename = undefined, - .out_pdb_filename = owner.fmt("{s}.pdb", .{name}), .major_only_filename = null, .name_only_filename = null, .modules = std.StringArrayHashMap(*Module).init(owner.allocator), @@ -477,14 +455,10 @@ pub fn create(owner: *std.Build, options: Options) *Compile { .disable_sanitize_c = false, .sanitize_thread = false, .rdynamic = false, - .override_dest_dir = null, .installed_path = null, .force_undefined_symbols = StringHashMap(void).init(owner.allocator), - .force_build = false, - - .emit_directory = GeneratedFile{ .step = &self.step }, - + .emit_directory = null, .generated_docs = null, .generated_asm = null, .generated_bin = null, @@ -503,6 +477,16 @@ pub fn create(owner: *std.Build, options: Options) *Compile { .use_lld = options.use_lld, }; + if (options.zig_lib_dir) |lp| { + self.zig_lib_dir = lp.dupe(self.step.owner); + lp.addStepDependencies(&self.step); + } + + if (options.main_pkg_path) |lp| { + self.main_pkg_path = lp.dupe(self.step.owner); + lp.addStepDependencies(&self.step); + } + if (self.kind == .lib) { if (self.linkage != null and self.linkage.? == .static) { self.out_lib_filename = self.out_filename; @@ -636,7 +620,8 @@ pub fn checkObject(self: *Compile) *Step.CheckObject { return Step.CheckObject.create(self.step.owner, self.getEmittedBin(), self.target_info.target.ofmt); } -pub const setLinkerScriptPath = setLinkerScript; // DEPRECATED, use setLinkerScript +/// deprecated: use `setLinkerScript` +pub const setLinkerScriptPath = setLinkerScript; pub fn setLinkerScript(self: *Compile, source: LazyPath) void { const b = self.step.owner; @@ -700,12 +685,17 @@ pub fn isStaticLibrary(self: *Compile) bool { pub fn producesPdbFile(self: *Compile) bool { // TODO: Is this right? Isn't PDB for *any* PE/COFF file? + // TODO: just share this logic with the compiler, silly! if (!self.target.isWindows() and !self.target.isUefi()) return false; if (self.target.getObjectFormat() == .c) return false; if (self.strip == true or (self.strip == null and self.optimize == .ReleaseSmall)) return false; return self.isDynamicLibrary() or self.kind == .exe or self.kind == .@"test"; } +pub fn producesImplib(self: *Compile) bool { + return self.isDynamicLibrary() and self.target.isWindows(); +} + pub fn linkLibC(self: *Compile) void { self.is_linking_libc = true; } @@ -961,16 +951,6 @@ pub fn setVerboseCC(self: *Compile, value: bool) void { self.verbose_cc = value; } -pub fn overrideZigLibDir(self: *Compile, dir_path: LazyPath) void { - self.zig_lib_dir = dir_path.dupe(self.step.owner); - dir_path.addStepDependencies(&self.step); -} - -pub fn setMainPkgPath(self: *Compile, dir_path: LazyPath) void { - self.main_pkg_path = dir_path.dupe(self.step.owner); - dir_path.addStepDependencies(&self.step); -} - pub fn setLibCFile(self: *Compile, libc_file: ?LazyPath) void { const b = self.step.owner; self.libc_file = if (libc_file) |f| f.dupe(b) else null; @@ -987,34 +967,17 @@ 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; -} +/// deprecated: use `getEmittedBinDirectory` +pub const getOutputDirectorySource = getEmittedBinDirectory; -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(), - } +/// Returns the path to the directory that contains the emitted binary file. +pub fn getEmittedBinDirectory(self: *Compile) LazyPath { + _ = self.getEmittedBin(); + return self.getEmittedFileGeneric(&self.emit_directory); } -pub const getOutputDirectorySource = getEmitDirectory; // DEPRECATED, use getEmitDirectory - -/// Returns the path to the output directory. -pub fn getEmitDirectory(self: *Compile) LazyPath { - return .{ .generated = &self.emit_directory }; -} - -pub const getOutputSource = getEmittedBin; // DEPRECATED, use getEmittedBin +/// deprecated: use `getEmittedBin` +pub const getOutputSource = getEmittedBin; /// Returns the path to the generated executable, library or object file. /// To run an executable built with zig build, use `run`, or create an install step and invoke it. @@ -1022,15 +985,18 @@ pub fn getEmittedBin(self: *Compile) LazyPath { return self.getEmittedFileGeneric(&self.generated_bin); } -pub const getOutputLibSource = getEmittedImplib; // DEPRECATED, use getEmittedImplib +/// deprecated: use `getEmittedImplib` +pub const getOutputLibSource = getEmittedImplib; -/// Returns the path to the generated import library. This function can only be called for libraries. +/// Returns the path to the generated import library. +/// This function can only be called for libraries. pub fn getEmittedImplib(self: *Compile) LazyPath { assert(self.kind == .lib); return self.getEmittedFileGeneric(&self.generated_implib); } -pub const getOutputHSource = getEmittedH; // DEPRECATED, use getEmittedH +/// deprecated: use `getEmittedH` +pub const getOutputHSource = getEmittedH; /// Returns the path to the generated header file. /// This function can only be called for libraries or objects. @@ -1039,11 +1005,14 @@ pub fn getEmittedH(self: *Compile) LazyPath { return self.getEmittedFileGeneric(&self.generated_h); } -pub const getOutputPdbSource = getEmittedPdb; // DEPRECATED, use getEmittedPdb +/// deprecated: use `getEmittedPdb`. +pub const getOutputPdbSource = getEmittedPdb; -/// Returns the generated PDB file. This function can only be called for Windows and UEFI. +/// Returns the generated PDB file. +/// If the compilation does not produce a PDB file, this causes a FileNotFound error +/// at build time. pub fn getEmittedPdb(self: *Compile) LazyPath { - assert(self.producesPdbFile()); + _ = self.getEmittedBin(); return self.getEmittedFileGeneric(&self.generated_pdb); } @@ -1198,13 +1167,11 @@ pub fn setExecCmd(self: *Compile, args: []const ?[]const u8) void { } fn linkLibraryOrObject(self: *Compile, other: *Compile) void { - other.forceEmit(.bin); - - if (other.target.isWindows() and other.isDynamicLibrary()) { // TODO(xq): Is this the correct logic here? - other.forceEmit(.implib); + other.getEmittedBin().addStepDependencies(&self.step); + if (other.target.isWindows() and other.isDynamicLibrary()) { + other.getEmittedImplib().addStepDependencies(&self.step); } - self.step.dependOn(&other.step); self.link_objects.append(.{ .other_step = other }) catch @panic("OOM"); self.include_dirs.append(.{ .other_step = other }) catch @panic("OOM"); @@ -1330,7 +1297,7 @@ fn getGeneratedFilePath(self: *Compile, comptime tag_name: []const u8, asking_st std.debug.getStderrMutex().lock(); const stderr = std.io.getStdErr(); - build_util.dumpBadGetPathHelp(&self.step, stderr, self.step.owner, asking_step) catch {}; + std.Build.dumpBadGetPathHelp(&self.step, stderr, self.step.owner, asking_step) catch {}; @panic("missing emit option for " ++ tag_name); }; @@ -1339,7 +1306,7 @@ fn getGeneratedFilePath(self: *Compile, comptime tag_name: []const u8, asking_st std.debug.getStderrMutex().lock(); const stderr = std.io.getStdErr(); - build_util.dumpBadGetPathHelp(&self.step, stderr, self.step.owner, asking_step) catch {}; + std.Build.dumpBadGetPathHelp(&self.step, stderr, self.step.owner, asking_step) catch {}; @panic(tag_name ++ " is null. Is there a missing step dependency?"); }; @@ -1432,11 +1399,12 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { break :l; } - // TODO(xq): Is that the right way? - const full_path_lib = if (other.isDynamicLibrary() and other.target.isWindows()) - other.getGeneratedFilePath("generated_implib", &self.step) // For DLLs, we gotta link against the implib, + // For DLLs, we gotta link against the implib. For + // everything else, we directly link against the library file. + const full_path_lib = if (other.producesImplib()) + other.getGeneratedFilePath("generated_implib", &self.step) else - other.getGeneratedFilePath("generated_bin", &self.step); // for everything else, we directly link against the library file + other.getGeneratedFilePath("generated_bin", &self.step); try zig_args.append(full_path_lib); if (other.linkage == Linkage.dynamic and !self.target.isWindows()) { @@ -1579,36 +1547,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (b.verbose_cc or self.verbose_cc) try zig_args.append("--verbose-cc"); if (b.verbose_llvm_cpu_features) try zig_args.append("--verbose-llvm-cpu-features"); - const Emitter = struct { - ptr: ?*GeneratedFile, - emit_suffix: []const u8, - }; - - const generated_files = [_]Emitter{ - .{ .ptr = self.generated_asm, .emit_suffix = "asm" }, - .{ .ptr = self.generated_bin, .emit_suffix = "bin" }, - .{ .ptr = self.generated_docs, .emit_suffix = "docs" }, - .{ .ptr = self.generated_implib, .emit_suffix = "implib" }, - .{ .ptr = self.generated_llvm_bc, .emit_suffix = "llvm-bc" }, - .{ .ptr = self.generated_llvm_ir, .emit_suffix = "llvm-ir" }, - .{ .ptr = self.generated_h, .emit_suffix = "h" }, - }; - var any_emitted_file = false; - for (generated_files) |file| { - try zig_args.append(if (file.ptr != null) - b.fmt("-femit-{s}", .{file.emit_suffix}) - else - b.fmt("-fno-emit-{s}", .{file.emit_suffix})); - - if (file.ptr != null) any_emitted_file = true; - } - - 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*()`? If not, use `.forceBuild()` or `.forceEmit(…)` to make sure it builds anyways.", .{self.name}); - } + if (self.generated_asm != null) try zig_args.append("-femit-asm"); + if (self.generated_bin == null) try zig_args.append("-fno-emit-bin"); + if (self.generated_docs != null) try zig_args.append("-femit-docs"); + if (self.generated_implib != null) try zig_args.append("-femit-implib"); + if (self.generated_llvm_bc != null) try zig_args.append("-femit-llvm-bc"); + if (self.generated_llvm_ir != null) try zig_args.append("-femit-llvm-ir"); + if (self.generated_h != null) try zig_args.append("-femit-h"); try addFlag(&zig_args, "strip", self.strip); try addFlag(&zig_args, "unwind-tables", self.unwind_tables); @@ -1895,7 +1840,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { zig_args.appendAssumeCapacity("-rpath"); if (self.target_info.target.isDarwin()) switch (rpath) { - .path => |path| { + .path, .cwd_relative => |path| { // On Darwin, we should not try to expand special runtime paths such as // * @executable_path // * @loader_path @@ -1993,9 +1938,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (self.zig_lib_dir) |dir| { try zig_args.append("--zig-lib-dir"); try zig_args.append(dir.getPath(b)); - } else if (b.zig_lib_dir) |dir| { - try zig_args.append("--zig-lib-dir"); - try zig_args.append(dir); } if (self.main_pkg_path) |dir| { @@ -2093,37 +2035,30 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (maybe_output_bin_path) |output_bin_path| { const output_dir = fs.path.dirname(output_bin_path).?; - self.emit_directory.path = output_dir; + if (self.emit_directory) |lp| { + lp.path = output_dir; + } // -femit-bin[=path] (default) Output machine code if (self.generated_bin) |bin| { - bin.path = b.pathJoin( - &.{ output_dir, self.out_filename }, - ); + bin.path = b.pathJoin(&.{ output_dir, self.out_filename }); } + const sep = std.fs.path.sep; + // output PDB if someone requested it if (self.generated_pdb) |pdb| { - std.debug.assert(self.producesPdbFile()); - pdb.path = b.pathJoin( - &.{ output_dir, self.out_pdb_filename }, - ); + pdb.path = b.fmt("{s}{c}{s}.pdb", .{ output_dir, sep, self.name }); } // -femit-implib[=path] (default) Produce an import .lib when building a Windows DLL - if (self.kind == .lib) { - if (self.generated_implib) |lib| { - lib.path = b.pathJoin( - &.{ output_dir, self.out_lib_filename }, - ); - } + if (self.generated_implib) |implib| { + implib.path = b.fmt("{s}{c}{s}.lib", .{ output_dir, sep, self.name }); } // -femit-h[=path] Generate a C header file (.h) - if (self.generated_h) |lazy_path| { - lazy_path.path = b.pathJoin( - &.{ output_dir, self.out_h_filename }, - ); + if (self.generated_h) |lp| { + lp.path = b.fmt("{s}{c}{s}.h", .{ output_dir, sep, self.name }); } // -femit-docs[=path] Create a docs/ dir with html documentation @@ -2132,24 +2067,18 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } // -femit-asm[=path] Output .s (assembly code) - if (self.generated_asm) |lazy_path| { - lazy_path.path = b.pathJoin( - &.{ output_dir, self.out_asm_filename }, - ); + if (self.generated_asm) |lp| { + lp.path = b.fmt("{s}{c}{s}.s", .{ output_dir, sep, self.name }); } // -femit-llvm-ir[=path] Produce a .ll file with optimized LLVM IR (requires LLVM extensions) - if (self.generated_llvm_ir) |lazy_path| { - lazy_path.path = b.pathJoin( - &.{ output_dir, self.out_ll_filename }, - ); + if (self.generated_llvm_ir) |lp| { + lp.path = b.fmt("{s}{c}{s}.ll", .{ output_dir, sep, self.name }); } // -femit-llvm-bc[=path] Produce an optimized LLVM module as a .bc file (requires LLVM extensions) - if (self.generated_llvm_bc) |lazy_path| { - lazy_path.path = b.pathJoin( - &.{ output_dir, self.out_bc_filename }, - ); + if (self.generated_llvm_bc) |lp| { + lp.path = b.fmt("{s}{c}{s}.bc", .{ output_dir, sep, self.name }); } } diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig index dbf63a9df448..df090ea94856 100644 --- a/lib/std/Build/Step/ConfigHeader.zig +++ b/lib/std/Build/Step/ConfigHeader.zig @@ -15,7 +15,8 @@ pub const Style = union(enum) { /// Start with nothing, like blank, and output a nasm .asm file. nasm, - pub const getFileSource = getPath; // DEPRECATED, use getPath + /// deprecated: use `getPath` + pub const getFileSource = getPath; pub fn getPath(style: Style) ?std.Build.LazyPath { switch (style) { @@ -100,9 +101,10 @@ pub fn addValues(self: *ConfigHeader, values: anytype) void { return addValuesInner(self, values) catch @panic("OOM"); } -pub const getFileSource = getTemplate; // DEPRECATED, use getOutput +/// deprecated: use `getOutput` +pub const getFileSource = getOutput; -pub fn getTemplate(self: *ConfigHeader) std.Build.LazyPath { +pub fn getOutput(self: *ConfigHeader) std.Build.LazyPath { return .{ .generated = &self.output_file }; } diff --git a/lib/std/Build/Step/InstallArtifact.zig b/lib/std/Build/Step/InstallArtifact.zig index a9696867eff3..b662854746fc 100644 --- a/lib/std/Build/Step/InstallArtifact.zig +++ b/lib/std/Build/Step/InstallArtifact.zig @@ -3,67 +3,117 @@ const Step = std.Build.Step; const InstallDir = std.Build.InstallDir; const InstallArtifact = @This(); const fs = std.fs; - -pub const base_id = .install_artifact; +const LazyPath = std.Build.LazyPath; step: Step, -artifact: *Step.Compile, -dest_dir: InstallDir, + +dest_dir: ?InstallDir, +dest_sub_path: []const u8, +emitted_bin: ?LazyPath, + +implib_dir: ?InstallDir, +emitted_implib: ?LazyPath, + pdb_dir: ?InstallDir, +emitted_pdb: ?LazyPath, + h_dir: ?InstallDir, -/// If non-null, adds additional path components relative to dest_dir, and -/// overrides the basename of the Compile step. -dest_sub_path: ?[]const u8, +emitted_h: ?LazyPath, + +dylib_symlinks: ?DylibSymlinkInfo, + +artifact: *Step.Compile, + +const DylibSymlinkInfo = struct { + major_only_filename: []const u8, + name_only_filename: []const u8, +}; + +pub const base_id = .install_artifact; + +pub const Options = struct { + /// Which installation directory to put the main output file into. + dest_dir: Dir = .default, + pdb_dir: Dir = .default, + h_dir: Dir = .default, + implib_dir: Dir = .default, + + /// Whether to install symlinks along with dynamic libraries. + dylib_symlinks: ?bool = null, + /// If non-null, adds additional path components relative to bin dir, and + /// overrides the basename of the Compile step for installation purposes. + dest_sub_path: ?[]const u8 = null, -pub fn create(owner: *std.Build, artifact: *Step.Compile) *InstallArtifact { + pub const Dir = union(enum) { + disabled, + default, + override: InstallDir, + }; +}; + +pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *InstallArtifact { const self = owner.allocator.create(InstallArtifact) catch @panic("OOM"); - self.* = InstallArtifact{ + const dest_dir: ?InstallDir = switch (options.dest_dir) { + .disabled => null, + .default => switch (artifact.kind) { + .obj => @panic("object files have no standard installation procedure"), + .exe, .@"test" => InstallDir{ .bin = {} }, + .lib => InstallDir{ .lib = {} }, + }, + .override => |o| o, + }; + self.* = .{ .step = Step.init(.{ .id = base_id, .name = owner.fmt("install {s}", .{artifact.name}), .owner = owner, .makeFn = make, }), - .artifact = artifact, - .dest_dir = artifact.override_dest_dir orelse switch (artifact.kind) { - .obj => @panic("Cannot install a .obj build artifact."), - .exe, .@"test" => InstallDir{ .bin = {} }, - .lib => InstallDir{ .lib = {} }, + .dest_dir = dest_dir, + .pdb_dir = switch (options.pdb_dir) { + .disabled => null, + .default => if (artifact.producesPdbFile()) dest_dir else null, + .override => |o| o, }, - .pdb_dir = if (artifact.producesPdbFile()) blk: { - if (artifact.kind == .exe or artifact.kind == .@"test") { - break :blk InstallDir{ .bin = {} }; - } else { - break :blk InstallDir{ .lib = {} }; - } + .h_dir = switch (options.h_dir) { + .disabled => null, + .default => switch (artifact.kind) { + .lib => .header, + else => null, + }, + .override => |o| o, + }, + .implib_dir = switch (options.implib_dir) { + .disabled => null, + .default => if (artifact.producesImplib()) dest_dir else null, + .override => |o| o, + }, + + .dylib_symlinks = if (options.dylib_symlinks orelse (dest_dir != null and + artifact.isDynamicLibrary() and + artifact.version != null and + artifact.target.wantSharedLibSymLinks())) .{ + .major_only_filename = artifact.major_only_filename.?, + .name_only_filename = artifact.name_only_filename.?, } else null, - .h_dir = if (artifact.kind == .lib and artifact.generated_h != null) .header else null, - .dest_sub_path = null, + + .dest_sub_path = options.dest_sub_path orelse artifact.out_filename, + + .emitted_bin = null, + .emitted_pdb = null, + .emitted_h = null, + .emitted_implib = null, + + .artifact = artifact, }; + self.step.dependOn(&artifact.step); - artifact.forceEmit(.bin); + if (self.dest_dir != null) self.emitted_bin = artifact.getEmittedBin(); + if (self.pdb_dir != null) self.emitted_pdb = artifact.getEmittedPdb(); + if (self.h_dir != null) self.emitted_h = artifact.getEmittedH(); + if (self.implib_dir != null) self.emitted_implib = artifact.getEmittedImplib(); - owner.pushInstalledFile(self.dest_dir, artifact.out_filename); - if (self.artifact.isDynamicLibrary()) { - if (artifact.major_only_filename) |name| { - owner.pushInstalledFile(.lib, name); - } - if (artifact.name_only_filename) |name| { - owner.pushInstalledFile(.lib, name); - } - if (self.artifact.target.isWindows()) { - owner.pushInstalledFile(.lib, artifact.out_lib_filename); - } - } - if (self.pdb_dir) |pdb_dir| { - _ = artifact.getEmittedPdb(); // force creation - owner.pushInstalledFile(pdb_dir, artifact.out_pdb_filename); - } - if (self.h_dir) |h_dir| { - _ = artifact.getEmittedH(); // force creation - owner.pushInstalledFile(h_dir, artifact.out_h_filename); - } return self; } @@ -71,35 +121,30 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { _ = prog_node; const self = @fieldParentPtr(InstallArtifact, "step", step); const dest_builder = step.owner; - - const dest_sub_path = if (self.dest_sub_path) |sub_path| sub_path else self.artifact.out_filename; - const full_dest_path = dest_builder.getInstallPath(self.dest_dir, dest_sub_path); const cwd = fs.cwd(); var all_cached = true; - { - const full_src_path = self.artifact.generated_bin.?.path.?; + if (self.dest_dir) |dest_dir| { + const full_dest_path = dest_builder.getInstallPath(dest_dir, self.dest_sub_path); + const full_src_path = self.emitted_bin.?.getPath2(step.owner, step); const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_dest_path, .{}) catch |err| { return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ full_src_path, full_dest_path, @errorName(err), }); }; all_cached = all_cached and p == .fresh; - } - if (self.artifact.isDynamicLibrary() and - self.artifact.version != null and - self.artifact.target.wantSharedLibSymLinks()) - { - try Step.Compile.doAtomicSymLinks(step, full_dest_path, self.artifact.major_only_filename.?, self.artifact.name_only_filename.?); + if (self.dylib_symlinks) |dls| { + try Step.Compile.doAtomicSymLinks(step, full_dest_path, dls.major_only_filename, dls.name_only_filename); + } + + self.artifact.installed_path = full_dest_path; } - if (self.artifact.isDynamicLibrary() and - self.artifact.target.isWindows() and - self.artifact.generated_implib != null) - { - const full_src_path = self.artifact.generated_implib.?.path.?; - const full_implib_path = dest_builder.getInstallPath(self.dest_dir, self.artifact.out_lib_filename); + + if (self.implib_dir) |implib_dir| { + const full_src_path = self.emitted_implib.?.getPath2(step.owner, step); + const full_implib_path = dest_builder.getInstallPath(implib_dir, fs.path.basename(full_src_path)); const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_implib_path, .{}) catch |err| { return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ full_src_path, full_implib_path, @errorName(err), @@ -107,9 +152,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { }; all_cached = all_cached and p == .fresh; } + if (self.pdb_dir) |pdb_dir| { - const full_src_path = self.artifact.generated_pdb.?.path.?; - const full_pdb_path = dest_builder.getInstallPath(pdb_dir, self.artifact.out_pdb_filename); + const full_src_path = self.emitted_pdb.?.getPath2(step.owner, step); + const full_pdb_path = dest_builder.getInstallPath(pdb_dir, fs.path.basename(full_src_path)); const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_pdb_path, .{}) catch |err| { return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ full_src_path, full_pdb_path, @errorName(err), @@ -117,9 +163,10 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { }; all_cached = all_cached and p == .fresh; } + if (self.h_dir) |h_dir| { - const full_src_path = self.artifact.generated_h.?.path.?; - const full_h_path = dest_builder.getInstallPath(h_dir, self.artifact.out_h_filename); + const full_src_path = self.emitted_h.?.getPath2(step.owner, step); + const full_h_path = dest_builder.getInstallPath(h_dir, fs.path.basename(full_src_path)); const p = fs.Dir.updateFile(cwd, full_src_path, cwd, full_h_path, .{}) catch |err| { return step.fail("unable to update file from '{s}' to '{s}': {s}", .{ full_src_path, full_h_path, @errorName(err), @@ -127,6 +174,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { }; all_cached = all_cached and p == .fresh; } - self.artifact.installed_path = full_dest_path; + step.result_cached = all_cached; } diff --git a/lib/std/Build/Step/ObjCopy.zig b/lib/std/Build/Step/ObjCopy.zig index 77f1c2a0de9e..1fc6aa9a4175 100644 --- a/lib/std/Build/Step/ObjCopy.zig +++ b/lib/std/Build/Step/ObjCopy.zig @@ -60,7 +60,8 @@ pub fn create( return self; } -pub const getOutputSource = getOutput; // DEPRECATED, use getOutput +/// deprecated: use getOutput +pub const getOutputSource = getOutput; pub fn getOutput(self: *const ObjCopy) std.Build.LazyPath { return .{ .generated = &self.output_file }; diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig index 0f058cab05a0..575ee747d15e 100644 --- a/lib/std/Build/Step/Options.zig +++ b/lib/std/Build/Step/Options.zig @@ -13,7 +13,7 @@ step: Step, generated_file: GeneratedFile, contents: std.ArrayList(u8), -args: std.ArrayList(OptionLazyPathArg), +args: std.ArrayList(Arg), pub fn create(owner: *std.Build) *Options { const self = owner.allocator.create(Options) catch @panic("OOM"); @@ -26,7 +26,7 @@ pub fn create(owner: *std.Build) *Options { }), .generated_file = undefined, .contents = std.ArrayList(u8).init(owner.allocator), - .args = std.ArrayList(OptionLazyPathArg).init(owner.allocator), + .args = std.ArrayList(Arg).init(owner.allocator), }; self.generated_file = .{ .step = &self.step }; @@ -166,7 +166,8 @@ fn printLiteral(out: anytype, val: anytype, indent: u8) !void { } } -pub const addOptionFileSource = addOptionPath; // DEPRECATED, use addPathOption +/// deprecated: use `addOptionPath` +pub const addOptionFileSource = addOptionPath; /// The value is the path in the cache dir. /// Adds a dependency automatically. @@ -182,14 +183,9 @@ pub fn addOptionPath( path.addStepDependencies(&self.step); } -/// The value is the path in the cache dir. -/// Adds a dependency automatically. +/// Deprecated: use `addOptionPath(options, name, artifact.getEmittedBin())` instead. pub fn addOptionArtifact(self: *Options, name: []const u8, artifact: *Step.Compile) void { - self.args.append(.{ - .name = self.step.owner.dupe(name), - .artifact = artifact.getEmittedBin, - }) catch @panic("OOM"); - self.step.dependOn(&artifact.step); + return addOptionPath(self, name, artifact.getEmittedBin()); } pub fn createModule(self: *Options) *std.Build.Module { @@ -199,7 +195,8 @@ pub fn createModule(self: *Options) *std.Build.Module { }); } -pub const getSource = getOutput; // DEPRECATED, use getOutput +/// deprecated: use `getOutput` +pub const getSource = getOutput; pub fn getOutput(self: *Options) LazyPath { return .{ .generated = &self.generated_file }; @@ -226,7 +223,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { var hash = b.cache.hash; // Random bytes to make unique. Refresh this with new random bytes when // implementation is modified in a non-backwards-compatible way. - hash.add(@as(u32, 0x38845ef8)); + hash.add(@as(u32, 0xad95e922)); hash.addBytes(self.contents.items); const sub_path = "c" ++ fs.path.sep_str ++ hash.final() ++ fs.path.sep_str ++ basename; @@ -291,7 +288,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { } } -const OptionLazyPathArg = struct { +const Arg = struct { name: []const u8, path: LazyPath, }; diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig index 55278e2d5b53..1721e9dbc5d6 100644 --- a/lib/std/Build/Step/Run.zig +++ b/lib/std/Build/Step/Run.zig @@ -164,12 +164,9 @@ pub fn enableTestRunnerMode(self: *Run) void { } pub fn addArtifactArg(self: *Run, artifact: *Step.Compile) void { - // enforce creation of the binary file by invoking getEmittedBin const bin_file = artifact.getEmittedBin(); bin_file.addStepDependencies(&self.step); - self.argv.append(Arg{ .artifact = artifact }) catch @panic("OOM"); - self.step.dependOn(&artifact.step); } /// This provides file path as a command line argument to the command being @@ -201,32 +198,36 @@ pub fn addPrefixedOutputFileArg( return .{ .generated = &output.generated_file }; } -pub const addFileSourceArg = addFileArg; // DEPRECATED, use addFileArg +/// deprecated: use `addFileArg` +pub const addFileSourceArg = addFileArg; -pub fn addFileArg(self: *Run, file_source: std.Build.LazyPath) void { - self.addPrefixedFileArg("", file_source); +pub fn addFileArg(self: *Run, lp: std.Build.LazyPath) void { + self.addPrefixedFileArg("", lp); } -pub const addPrefixedFileSourceArg = addPrefixedFileArg; // DEPRECATED, use addPrefixedFileArg +// deprecated: use `addPrefixedFileArg` +pub const addPrefixedFileSourceArg = addPrefixedFileArg; -pub fn addPrefixedFileArg(self: *Run, prefix: []const u8, file_source: std.Build.LazyPath) void { +pub fn addPrefixedFileArg(self: *Run, prefix: []const u8, lp: std.Build.LazyPath) void { const b = self.step.owner; const prefixed_file_source: PrefixedLazyPath = .{ .prefix = b.dupe(prefix), - .file_source = file_source.dupe(b), + .file_source = lp.dupe(b), }; self.argv.append(.{ .file_source = prefixed_file_source }) catch @panic("OOM"); - file_source.addStepDependencies(&self.step); + lp.addStepDependencies(&self.step); } -pub const addDirectorySourceArg = addDirectoryArg; // DEPRECATED, use addDirectoryArg +/// deprecated: use `addDirectoryArg` +pub const addDirectorySourceArg = addDirectoryArg; pub fn addDirectoryArg(self: *Run, directory_source: std.Build.LazyPath) void { self.addPrefixedDirectoryArg("", directory_source); } -pub const addPrefixedDirectorySourceArg = addPrefixedDirectoryArg; // DEPRECATED, use addPrefixedDirectoryArg +// deprecated: use `addPrefixedDirectoryArg` +pub const addPrefixedDirectorySourceArg = addPrefixedDirectoryArg; pub fn addPrefixedDirectoryArg(self: *Run, prefix: []const u8, directory_source: std.Build.LazyPath) void { const b = self.step.owner; diff --git a/lib/std/Build/Step/WriteFile.zig b/lib/std/Build/Step/WriteFile.zig index f8fc60621671..51db4bb3c391 100644 --- a/lib/std/Build/Step/WriteFile.zig +++ b/lib/std/Build/Step/WriteFile.zig @@ -28,7 +28,8 @@ pub const File = struct { sub_path: []const u8, contents: Contents, - pub const getFileSource = getPath; // DEPRECATED, use getPath + /// deprecated: use `getPath` + pub const getFileSource = getPath; pub fn getPath(self: *File) std.Build.LazyPath { return .{ .generated = &self.generated_file }; diff --git a/lib/std/Build/util.zig b/lib/std/Build/util.zig deleted file mode 100644 index 5c1b91f3d646..000000000000 --- a/lib/std/Build/util.zig +++ /dev/null @@ -1,53 +0,0 @@ -const std = @import("std"); -const fs = std.fs; - -const Build = std.Build; -const Step = std.Build.Step; - -/// In this function the stderr mutex has already been locked. -pub fn dumpBadGetPathHelp( - s: *Step, - stderr: fs.File, - src_builder: *Build, - asking_step: ?*Step, -) anyerror!void { - const w = stderr.writer(); - try w.print( - \\getPath() was called on a GeneratedFile that wasn't built yet. - \\ source package path: {s} - \\ Is there a missing Step dependency on step '{s}'? - \\ - , .{ - src_builder.build_root.path orelse ".", - s.name, - }); - - const tty_config = std.io.tty.detectConfig(stderr); - tty_config.setColor(w, .red) catch {}; - try stderr.writeAll(" The step was created by this stack trace:\n"); - tty_config.setColor(w, .reset) catch {}; - - const debug_info = std.debug.getSelfDebugInfo() catch |err| { - try w.print("Unable to dump stack trace: Unable to open debug info: {s}\n", .{@errorName(err)}); - return; - }; - const ally = debug_info.allocator; - std.debug.writeStackTrace(s.getStackTrace(), w, ally, debug_info, tty_config) catch |err| { - try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}); - return; - }; - if (asking_step) |as| { - tty_config.setColor(w, .red) catch {}; - try stderr.writeAll(" The step that is missing a dependency on the above step was created by this stack trace:\n"); - tty_config.setColor(w, .reset) catch {}; - - std.debug.writeStackTrace(as.getStackTrace(), w, ally, debug_info, tty_config) catch |err| { - try stderr.writer().print("Unable to dump stack trace: {s}\n", .{@errorName(err)}); - return; - }; - } - - tty_config.setColor(w, .red) catch {}; - try stderr.writeAll(" Hope that helps. Proceeding to panic.\n"); - tty_config.setColor(w, .reset) catch {}; -} diff --git a/test/link/glibc_compat/build.zig b/test/link/glibc_compat/build.zig index 8f80a37b0258..a104633fd764 100644 --- a/test/link/glibc_compat/build.zig +++ b/test/link/glibc_compat/build.zig @@ -4,7 +4,7 @@ pub fn build(b: *std.Build) void { const test_step = b.step("test", "Test"); b.default_step = test_step; - inline for (.{ "aarch64-linux-gnu.2.27", "aarch64-linux-gnu.2.34" }) |t| { + for ([_][]const u8{ "aarch64-linux-gnu.2.27", "aarch64-linux-gnu.2.34" }) |t| { const exe = b.addExecutable(.{ .name = t, .root_source_file = .{ .path = "main.c" }, @@ -13,7 +13,8 @@ pub fn build(b: *std.Build) void { ) catch unreachable, }); exe.linkLibC(); - exe.forceBuild(); + // TODO: actually test the output + _ = exe.getEmittedBin(); test_step.dependOn(&exe.step); } } diff --git a/test/link/macho/dylib/build.zig b/test/link/macho/dylib/build.zig index aecc9b38ec10..b05e4f5677b3 100644 --- a/test/link/macho/dylib/build.zig +++ b/test/link/macho/dylib/build.zig @@ -41,8 +41,8 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} }); exe.linkSystemLibrary("a"); - exe.addLibraryPath(dylib.getEmitDirectory()); - exe.addRPath(dylib.getEmitDirectory()); + exe.addLibraryPath(dylib.getEmittedBinDirectory()); + exe.addRPath(dylib.getEmittedBinDirectory()); exe.linkLibC(); const check_exe = exe.checkObject(); diff --git a/test/link/macho/needed_library/build.zig b/test/link/macho/needed_library/build.zig index c24569e06d61..de5d6b1ae6e3 100644 --- a/test/link/macho/needed_library/build.zig +++ b/test/link/macho/needed_library/build.zig @@ -23,7 +23,6 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize }); dylib.addCSourceFile(.{ .file = .{ .path = "a.c" }, .flags = &.{} }); dylib.linkLibC(); - dylib.forceEmit(.bin); // enforce library creation, we import it below // -dead_strip_dylibs // -needed-la @@ -35,8 +34,8 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} }); exe.linkLibC(); exe.linkSystemLibraryNeeded("a"); - exe.addLibraryPath(dylib.getEmitDirectory()); - exe.addRPath(dylib.getEmitDirectory()); + exe.addLibraryPath(dylib.getEmittedBinDirectory()); + exe.addRPath(dylib.getEmittedBinDirectory()); exe.dead_strip_dylibs = true; const check = exe.checkObject(); diff --git a/test/link/macho/search_strategy/build.zig b/test/link/macho/search_strategy/build.zig index d802bddbf41a..574782617b18 100644 --- a/test/link/macho/search_strategy/build.zig +++ b/test/link/macho/search_strategy/build.zig @@ -57,10 +57,6 @@ fn createScenario( }); static.addCSourceFile(.{ .file = .{ .path = "a.c" }, .flags = &.{} }); static.linkLibC(); - static.override_dest_dir = std.Build.InstallDir{ - .custom = "static", - }; - static.forceEmit(.bin); const dylib = b.addSharedLibrary(.{ .name = name, @@ -70,10 +66,6 @@ fn createScenario( }); dylib.addCSourceFile(.{ .file = .{ .path = "a.c" }, .flags = &.{} }); dylib.linkLibC(); - dylib.override_dest_dir = std.Build.InstallDir{ - .custom = "dynamic", - }; - dylib.forceEmit(.bin); // we want the binary to be built as we use it further below const exe = b.addExecutable(.{ .name = name, @@ -83,8 +75,8 @@ fn createScenario( exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} }); exe.linkSystemLibraryName(name); exe.linkLibC(); - exe.addLibraryPath(static.getEmitDirectory()); - exe.addLibraryPath(dylib.getEmitDirectory()); - exe.addRPath(dylib.getEmitDirectory()); + exe.addLibraryPath(static.getEmittedBinDirectory()); + exe.addLibraryPath(dylib.getEmittedBinDirectory()); + exe.addRPath(dylib.getEmittedBinDirectory()); return exe; } diff --git a/test/link/macho/tbdv3/build.zig b/test/link/macho/tbdv3/build.zig index 3b27b5a0ca5c..ba11004f29b9 100644 --- a/test/link/macho/tbdv3/build.zig +++ b/test/link/macho/tbdv3/build.zig @@ -25,7 +25,6 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize }); lib.addCSourceFile(.{ .file = .{ .path = "a.c" }, .flags = &.{} }); lib.linkLibC(); - lib.forceEmit(.bin); // will be referenced by the tbd file const tbd_file = b.addWriteFile("liba.tbd", \\--- !tapi-tbd-v3 @@ -47,7 +46,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} }); exe.linkSystemLibrary("a"); exe.addLibraryPath(tbd_file.getDirectory()); - exe.addRPath(lib.getEmitDirectory()); + exe.addRPath(lib.getEmittedBinDirectory()); exe.linkLibC(); const run = b.addRunArtifact(exe); diff --git a/test/link/macho/weak_library/build.zig b/test/link/macho/weak_library/build.zig index 3d0819c19b15..f66316693e99 100644 --- a/test/link/macho/weak_library/build.zig +++ b/test/link/macho/weak_library/build.zig @@ -33,8 +33,8 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &[0][]const u8{} }); exe.linkLibC(); exe.linkSystemLibraryWeak("a"); - exe.addLibraryPath(dylib.getEmitDirectory()); - exe.addRPath(dylib.getEmitDirectory()); + exe.addLibraryPath(dylib.getEmittedBinDirectory()); + exe.addRPath(dylib.getEmittedBinDirectory()); const check = exe.checkObject(); check.checkStart(); diff --git a/test/src/Cases.zig b/test/src/Cases.zig index 1cb9b0fcdcff..08aadaf0d42a 100644 --- a/test/src/Cases.zig +++ b/test/src/Cases.zig @@ -551,12 +551,6 @@ pub fn lowerToBuildSteps( }), }; - if (case.emit_bin) { - artifact.forceEmit(.bin); - } else { - artifact.forceBuild(); - } - if (case.link_libc) artifact.linkLibC(); switch (case.backend) { diff --git a/test/standalone.zig b/test/standalone.zig index dc9d7e291872..3725456fa1da 100644 --- a/test/standalone.zig +++ b/test/standalone.zig @@ -141,15 +141,15 @@ pub const build_cases = [_]BuildCase{ .import = @import("standalone/install_raw_hex/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"), - // }, + //.{ + // .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/issue_12588", + // .import = @import("standalone/issue_12588/build.zig"), + //}, .{ .build_root = "test/standalone/child_process", .import = @import("standalone/child_process/build.zig"), diff --git a/test/standalone/compiler_rt_panic/build.zig b/test/standalone/compiler_rt_panic/build.zig index 9bfe7f73fae7..6bce2cef4ee4 100644 --- a/test/standalone/compiler_rt_panic/build.zig +++ b/test/standalone/compiler_rt_panic/build.zig @@ -14,9 +14,13 @@ pub fn build(b: *std.Build) void { .optimize = optimize, .target = target, }); - exe.addCSourceFile("main.c", &.{}); + exe.addCSourceFile(.{ + .file = .{ .path = "main.c" }, + .flags = &.{}, + }); exe.link_gc_sections = false; exe.bundle_compiler_rt = true; + exe.linkLibC(); // Verify compiler_rt hasn't pulled in any debug handlers const check_exe = exe.checkObject(); diff --git a/test/standalone/embed_generated_file/build.zig b/test/standalone/embed_generated_file/build.zig index 220220b15f5f..ca05c33c39a6 100644 --- a/test/standalone/embed_generated_file/build.zig +++ b/test/standalone/embed_generated_file/build.zig @@ -22,7 +22,8 @@ pub fn build(b: *std.Build) void { .source_file = bootloader.getEmittedBin(), }); - exe.forceBuild(); + // TODO: actually check the output + _ = exe.getEmittedBin(); test_step.dependOn(&exe.step); } diff --git a/test/standalone/emit_asm_and_bin/build.zig b/test/standalone/emit_asm_and_bin/build.zig index 57df1185eebd..2f671bb6cce5 100644 --- a/test/standalone/emit_asm_and_bin/build.zig +++ b/test/standalone/emit_asm_and_bin/build.zig @@ -8,8 +8,9 @@ pub fn build(b: *std.Build) void { .root_source_file = .{ .path = "main.zig" }, .optimize = b.standardOptimizeOption(.{}), }); - main.forceEmit(.bin); - main.forceEmit(.@"asm"); + // TODO: actually check these two artifacts for correctness + _ = main.getEmittedBin(); + _ = main.getEmittedAsm(); test_step.dependOn(&b.addRunArtifact(main).step); } diff --git a/test/standalone/issue_339/build.zig b/test/standalone/issue_339/build.zig index 6afb0125ea0d..d53ba992ea3e 100644 --- a/test/standalone/issue_339/build.zig +++ b/test/standalone/issue_339/build.zig @@ -14,7 +14,8 @@ pub fn build(b: *std.Build) void { .optimize = optimize, }); - obj.forceBuild(); + // TODO: actually check the output + _ = obj.getEmittedBin(); test_step.dependOn(&obj.step); } diff --git a/test/standalone/issue_5825/build.zig b/test/standalone/issue_5825/build.zig index 48c43242b26b..9a790f6bb927 100644 --- a/test/standalone/issue_5825/build.zig +++ b/test/standalone/issue_5825/build.zig @@ -27,7 +27,8 @@ pub fn build(b: *std.Build) void { exe.linkSystemLibrary("ntdll"); exe.addObject(obj); - exe.forceBuild(); + // TODO: actually check the output + _ = exe.getEmittedBin(); test_step.dependOn(&exe.step); } diff --git a/test/standalone/issue_794/build.zig b/test/standalone/issue_794/build.zig index 8ef5cf4e9f3c..eb05aa9b4fd5 100644 --- a/test/standalone/issue_794/build.zig +++ b/test/standalone/issue_794/build.zig @@ -9,7 +9,8 @@ pub fn build(b: *std.Build) void { }); test_artifact.addIncludePath(.{ .path = "a_directory" }); - test_artifact.forceBuild(); + // TODO: actually check the output + _ = test_artifact.getEmittedBin(); test_step.dependOn(&test_artifact.step); } diff --git a/test/standalone/main_pkg_path/build.zig b/test/standalone/main_pkg_path/build.zig index bbe7cfb53b52..d1b67592b5b0 100644 --- a/test/standalone/main_pkg_path/build.zig +++ b/test/standalone/main_pkg_path/build.zig @@ -6,8 +6,8 @@ pub fn build(b: *std.Build) void { const test_exe = b.addTest(.{ .root_source_file = .{ .path = "a/test.zig" }, + .main_pkg_path = .{ .path = "." }, }); - test_exe.setMainPkgPath(.{ .path = "." }); test_step.dependOn(&b.addRunArtifact(test_exe).step); } diff --git a/test/standalone/strip_empty_loop/build.zig b/test/standalone/strip_empty_loop/build.zig index 77a1a08f754a..e64781d99142 100644 --- a/test/standalone/strip_empty_loop/build.zig +++ b/test/standalone/strip_empty_loop/build.zig @@ -15,7 +15,8 @@ pub fn build(b: *std.Build) void { }); main.strip = true; - main.forceBuild(); + // TODO: actually check the output + _ = main.getEmittedBin(); test_step.dependOn(&main.step); } diff --git a/test/tests.zig b/test/tests.zig index 4174fc0147c8..d42344cb883a 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -588,7 +588,7 @@ pub fn addStandaloneTests( }); if (case.link_libc) exe.linkLibC(); - exe.forceBuild(); + _ = exe.getEmittedBin(); step.dependOn(&exe.step); } @@ -1008,6 +1008,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { .single_threaded = test_target.single_threaded, .use_llvm = test_target.use_llvm, .use_lld = test_target.use_lld, + .zig_lib_dir = .{ .path = "lib" }, }); const single_threaded_suffix = if (test_target.single_threaded == true) "-single" else ""; const backend_suffix = if (test_target.use_llvm == true) @@ -1019,7 +1020,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { else ""; - these_tests.overrideZigLibDir(.{ .path = "lib" }); these_tests.addIncludePath(.{ .path = "test" }); const qualified_name = b.fmt("{s}-{s}-{s}{s}{s}{s}", .{ @@ -1039,8 +1039,8 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { .name = qualified_name, .link_libc = test_target.link_libc, .target = altered_target, + .zig_lib_dir = .{ .path = "lib" }, }); - compile_c.overrideZigLibDir(.{ .path = "lib" }); compile_c.addCSourceFile(.{ .file = these_tests.getEmittedBin(), .flags = &.{