zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit aa0652ff8dc9add09567d69a92ddaff5ad386919 (tree)
parent dd51fc30f884aa1c3305793010a30d826689be89
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Tue, 17 Mar 2026 12:18:56 -0700

maker: implement InstallArtifact and InstallFile

Diffstat:
MBRANCH_TODO | 6+++++-
Mlib/compiler/Maker.zig | 214++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mlib/compiler/Maker/Graph.zig | 3++-
Mlib/compiler/Maker/Step.zig | 60++++++++++++++++++++++++++----------------------------------
Mlib/compiler/Maker/Step/Compile.zig | 45++++++---------------------------------------
Mlib/compiler/Maker/Step/InstallArtifact.zig | 137+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Alib/compiler/Maker/Step/InstallFile.zig | 25+++++++++++++++++++++++++
Mlib/compiler/configurer.zig | 35+++++++++++++++++++++++------------
Mlib/std/Build/Cache/Path.zig | 7+++++++
Mlib/std/Build/Configuration.zig | 67+++++++++++++++++++++++++++++++++++++++++++++++--------------------
Mlib/std/Build/Step/Compile.zig | 35-----------------------------------
Mlib/std/Build/Step/InstallArtifact.zig | 58++++++++++++++++++++++------------------------------------
Mlib/std/Build/Step/InstallFile.zig | 12------------
13 files changed, 421 insertions(+), 283 deletions(-)

diff --git a/BRANCH_TODO b/BRANCH_TODO @@ -1,9 +1,10 @@ -* replace b.dupe() with string internment +* implement the build options * don't forget to add -listen arg back * get zig init template working * finish migrating the rest of the build steps * make zig-pkg path root configurable in maker (make sure --system still works) * eliminate calls to getPath, getPath2, getPath3 +* replace b.dupe() with string internment * solve the TODOs added in this branch * get zig tests passing * test a bunch of third party projects / help people migrate @@ -13,3 +14,6 @@ ## Followup Issues * link_eh_frame_hdr should be DefaultingBool * make --foo, --no-foo CLI args uniform (make them -f args instead) +* install steps should provide generated files for installed things, then delete the run step hack + + diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig @@ -7,6 +7,7 @@ const Cache = std.Build.Cache; const Configuration = std.Build.Configuration; const File = std.Io.File; const Io = std.Io; +const Dir = std.Io.Dir; const Path = std.Build.Cache.Path; const Writer = std.Io.Writer; const assert = std.debug.assert; @@ -82,7 +83,7 @@ pub fn main(init: process.Init.Minimal) !void { const global_cache_root = expectArgOrFatal(args, &arg_idx, "--global-cache"); const configure_path = expectArgOrFatal(args, &arg_idx, "--configuration"); - const cwd: Io.Dir = .cwd(); + const cwd: Dir = .cwd(); const zig_lib_directory: Cache.Directory = .{ .path = zig_lib_dir, @@ -497,7 +498,7 @@ pub fn main(init: process.Init.Minimal) !void { const install_prefix_path: Path = if (graph.environ_map.get("DESTDIR")) |dest_dir| .{ .root_dir = .cwd(), - .sub_path = try Io.Dir.path.join(arena, &.{ dest_dir, override_install_prefix orelse "/usr" }), + .sub_path = try Dir.path.join(arena, &.{ dest_dir, override_install_prefix orelse "/usr" }), } else if (override_install_prefix) |cwd_relative| .{ .root_dir = .cwd(), .sub_path = cwd_relative, @@ -1675,7 +1676,7 @@ fn cleanTmpFiles(io: Io, steps: []const Configuration.Step.Index) void { const wf = step_index.cast(std.Build.Step.WriteFile) orelse continue; if (wf.mode != .tmp) continue; const path = wf.generated_directory.path orelse continue; - Io.Dir.cwd().deleteTree(io, path) catch |err| { + Dir.cwd().deleteTree(io, path) catch |err| { log.warn("failed to delete {s}: {t}", .{ path, err }); }; } @@ -1699,29 +1700,14 @@ pub fn resolveLazyPath( ) Allocator.Error!Path { _ = asking_step_index; // TODO use this to enhance debugability when this function fails const c = &maker.scanned_config.configuration; - const graph = maker.graph; return switch (lazy_path) { .source_path => |sp| try packagePath(maker, arena, sp.owner, sp.sub_path.slice(c)), - .relative => |relative| switch (relative.flags.base) { - .cwd => .{ - .root_dir = .cwd(), - .sub_path = relative.sub_path.slice(c), - }, - .local_cache => .{ - .root_dir = graph.local_cache_root, - }, - .global_cache => .{ - .root_dir = graph.global_cache_root, - }, - .build_root => .{ - .root_dir = graph.build_root_directory, - }, - }, + .relative => |relative| relativePath(maker, relative), .generated => |gen| { - const base = maker.generated_files[@intFromEnum(gen.index)]; + const base = generatedPath(maker, gen.index); var file_path = base; for (0..gen.flags.up) |_| { - file_path.sub_path = Io.Dir.path.dirname(file_path.sub_path) orelse + file_path.sub_path = Dir.path.dirname(file_path.sub_path) orelse fatal("invalid LazyPath traversal: up {d} times from {f}", .{ gen.flags.up, base }); } return file_path.join(arena, gen.sub_path.slice(c)); @@ -1750,7 +1736,7 @@ pub fn resolveLazyPathAbs( const p = try resolveLazyPath(maker, arena, lazy_path, asking_step_index); const root_dir_path = p.root_dir.path orelse return p.subPathOrDot(); if (p.sub_path.len == 0) return root_dir_path; - return Io.Dir.path.join(arena, &.{ root_dir_path, p.sub_path }); + return Dir.path.join(arena, &.{ root_dir_path, p.sub_path }); } /// `resolveLazyPath` is preferred, but this can be necessary when passing Path @@ -1765,11 +1751,11 @@ pub fn resolveLazyPathIndexAbs( return resolveLazyPathAbs(maker, arena, lazy_path_index.get(c), asking_step_index); } -pub fn generatedPath(maker: *Maker, index: Configuration.GeneratedFileIndex) *Path { +pub fn generatedPath(maker: *const Maker, index: Configuration.GeneratedFileIndex) *Path { return &maker.generated_files[@intFromEnum(index)]; } -fn packagePath( +pub fn packagePath( maker: *const Maker, arena: Allocator, package_index: Configuration.Package.Index, @@ -1785,43 +1771,183 @@ fn packagePath( const pkg_root = graph.pkg_root; return .{ .root_dir = pkg_root.root_dir, - .sub_path = try Io.Dir.path.join(arena, &.{ pkg_root.sub_path, hash, sub_path }), + .sub_path = try Dir.path.join(arena, &.{ pkg_root.sub_path, hash, sub_path }), + }; +} + +pub fn relativePath(maker: *const Maker, relative: Configuration.LazyPath.Relative) Path { + const graph = maker.graph; + const c = &maker.scanned_config.configuration; + const sub_path = relative.sub_path.slice(c); + return switch (relative.flags.base) { + .cwd => .{ + .root_dir = .cwd(), + .sub_path = sub_path, + }, + .local_cache => .{ + .root_dir = graph.local_cache_root, + .sub_path = sub_path, + }, + .global_cache => .{ + .root_dir = graph.global_cache_root, + .sub_path = sub_path, + }, + .build_root => .{ + .root_dir = graph.build_root_directory, + .sub_path = sub_path, + }, }; } -/// Wrapper around `Io.Dir.updateFile` that handles verbose and error output. -pub fn installFile( +pub fn resolveInstallDir( maker: *Maker, arena: Allocator, - src_lazy_path: Configuration.LazyPath, - dest_path: []const u8, + dest_dir: Configuration.InstallDestDir, +) Allocator.Error!Path { + const c = &maker.scanned_config.configuration; + return switch (dest_dir.unpack().?) { + .prefix => maker.install_paths.prefix, + .lib => maker.install_paths.lib, + .bin => maker.install_paths.bin, + .header => maker.install_paths.include, + .sub_path => |s| try maker.install_paths.prefix.join(arena, s.slice(c)), + }; +} + +pub fn installLazyPathSub( + maker: *Maker, + arena: Allocator, + source: Configuration.LazyPath.Index, + dest_dir: Configuration.InstallDestDir, + sub_path: []const u8, asking_step_index: Configuration.Step.Index, -) !Io.Dir.PrevStatus { +) !Dir.PrevStatus { + const src_path = try resolveLazyPathIndex(maker, arena, source, asking_step_index); + const dest_dir_path = try resolveInstallDir(maker, arena, dest_dir); + const dest_path = try dest_dir_path.join(arena, sub_path); + return installPath(maker, arena, src_path, dest_path, asking_step_index); +} + +pub fn installLazyPath( + maker: *Maker, + arena: Allocator, + source: Configuration.LazyPath.Index, + dest_dir: Configuration.InstallDestDir, + asking_step_index: Configuration.Step.Index, +) !Dir.PrevStatus { + const src_path = try resolveLazyPathIndex(maker, arena, source, asking_step_index); + const dest_dir_path = try resolveInstallDir(maker, arena, dest_dir); + const dest_path = try dest_dir_path.join(arena, src_path.basename()); + return installPath(maker, arena, src_path, dest_path, asking_step_index); +} + +pub fn installGenerated( + maker: *Maker, + arena: Allocator, + source: Configuration.GeneratedFileIndex, + dest_dir: Configuration.InstallDestDir, + asking_step_index: Configuration.Step.Index, +) !Dir.PrevStatus { + const src_path = generatedPath(maker, source).*; + const dest_dir_path = try resolveInstallDir(maker, arena, dest_dir); + const dest_path = try dest_dir_path.join(arena, src_path.basename()); + return installPath(maker, arena, src_path, dest_path, asking_step_index); +} + +pub fn installPath( + maker: *Maker, + arena: Allocator, + src_path: Path, + dest_path: Path, + asking_step_index: Configuration.Step.Index, +) !Dir.PrevStatus { const graph = maker.graph; const io = graph.io; - const src_path = try resolveLazyPath(maker, arena, src_lazy_path, asking_step_index); - { - const src_path_rendered = try src_path.toString(arena); - defer arena.free(src_path_rendered); - try graph.handleVerbose(.inherit, null, &.{ "install", "-C", src_path_rendered, dest_path }); - } - return Io.Dir.updateFile(src_path.root_dir.handle, io, src_path.sub_path, .cwd(), dest_path, .{}) catch |err| { + if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{ + "install", "-C", try src_path.toString(arena), try dest_path.toString(arena), + }); + return Dir.updateFile( + src_path.root_dir.handle, + io, + src_path.sub_path, + dest_path.root_dir.handle, + dest_path.sub_path, + .{}, + ) catch |err| { const s = stepByIndex(maker, asking_step_index); - return s.fail(maker, "unable to update file from '{f}' to '{s}': {t}", .{ src_path, dest_path, err }); + return s.fail(maker, "unable to update file from {f} to {f}: {t}", .{ src_path, dest_path, err }); }; } -/// Wrapper around `Io.Dir.createDirPathStatus` that handles verbose and error output. +/// Wrapper around `Dir.createDirPathStatus` that handles verbose and error output. pub fn installDir( maker: *Maker, - dest_path: []const u8, + arena: Allocator, + dest_path: Path, asking_step_index: Configuration.Step.Index, -) !Io.Dir.CreatePathStatus { +) !Dir.CreatePathStatus { const graph = maker.graph; const io = graph.io; - try graph.handleVerbose(.inherit, null, &.{ "install", "-d", dest_path }); - return Io.Dir.cwd().createDirPathStatus(io, dest_path, .default_dir) catch |err| { + if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{ + "install", "-d", try dest_path.toString(arena), + }); + return dest_path.root_dir.handle.createDirPathStatus(io, dest_path.sub_path, .default_dir) catch |err| { const s = stepByIndex(maker, asking_step_index); - return s.fail(maker, "unable to create dir '{s}': {t}", .{ dest_path, err }); + return s.fail(maker, "unable to create dir {f}: {t}", .{ dest_path, err }); + }; +} + +pub fn installSymLinks( + maker: *Maker, + arena: Allocator, + output_path: Path, + compile_step_index: Configuration.Step.Index, + asking_step_index: Configuration.Step.Index, +) !void { + const c = &maker.scanned_config.configuration; + const conf_step = compile_step_index.ptr(c); + const conf_comp = conf_step.extended.get(c.extra).compile; + const root_module = conf_comp.root_module.get(c); + const target = root_module.resolved_target.get(c).?.result.get(c); + const os_tag = target.flags.os_tag.unwrap().?; + + assert(conf_comp.flags3.kind == .lib); + assert(conf_comp.flags2.linkage == .dynamic); + assert(os_tag != .windows); + + const version = std.SemanticVersion.parse(conf_comp.version.value.?.slice(c)) catch unreachable; + const name = conf_comp.root_name.slice(c); + + const filename_major_only, const filename_name_only = if (os_tag.isDarwin()) .{ + try std.fmt.allocPrint(arena, "lib{s}.{d}.dylib", .{ name, version.major }), + try std.fmt.allocPrint(arena, "lib{s}.dylib", .{name}), + } else .{ + try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ name, version.major }), + try std.fmt.allocPrint(arena, "lib{s}.so", .{name}), + }; + + return installSymLinksInner(maker, arena, output_path, asking_step_index, filename_major_only, filename_name_only); +} + +fn installSymLinksInner( + maker: *Maker, + arena: Allocator, + output_path: Path, + asking_step_index: Configuration.Step.Index, + filename_major_only: []const u8, + filename_name_only: []const u8, +) !void { + const io = maker.graph.io; + const step = stepByIndex(maker, asking_step_index); + const out_dir = output_path.dirname().?; + // sym link for libfoo.so.1 to libfoo.so.1.2.3 + const major_only_path = try out_dir.join(arena, filename_major_only); + output_path.root_dir.handle.symLinkAtomic(io, output_path.sub_path, major_only_path.sub_path, .{}) catch |err| { + return step.fail(maker, "unable to symlink {f} -> {f}: {t}", .{ output_path, major_only_path, err }); + }; + // sym link for libfoo.so to libfoo.so.1 + const name_only_path = try out_dir.join(arena, filename_name_only); + major_only_path.root_dir.handle.symLinkAtomic(io, major_only_path.sub_path, name_only_path.sub_path, .{}) catch |err| { + return step.fail(maker, "unable to symlink {f} -> {s}: {t}", .{ name_only_path, filename_major_only, err }); }; } diff --git a/lib/compiler/Maker/Graph.zig b/lib/compiler/Maker/Graph.zig @@ -5,6 +5,7 @@ const std = @import("std"); const Io = std.Io; const Allocator = std.mem.Allocator; const Configuration = std.Build.Configuration; +const Path = std.Build.Cache.Path; io: Io, /// Process lifetime. @@ -16,7 +17,7 @@ global_cache_root: std.Build.Cache.Directory, local_cache_root: std.Build.Cache.Directory, zig_lib_directory: std.Build.Cache.Directory, build_root_directory: std.Build.Cache.Directory, -pkg_root: std.Build.Cache.Path, +pkg_root: Path, debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null, incremental: ?bool = null, diff --git a/lib/compiler/Maker/Step.zig b/lib/compiler/Maker/Step.zig @@ -8,6 +8,7 @@ const std = @import("std"); const Allocator = std.mem.Allocator; const Cache = std.Build.Cache; const Io = std.Io; +const Dir = std.Io.Dir; const LazyPath = std.Build.Configuration.LazyPath; const Package = std.Build.Configuration.Package; const Path = std.Build.Cache.Path; @@ -19,6 +20,8 @@ const Maker = @import("../Maker.zig"); const Compile = @import("Step/Compile.zig"); const Run = @import("Step/Run.zig"); +const InstallArtifact = @import("Step/InstallArtifact.zig"); +const InstallFile = @import("Step/InstallFile.zig"); /// Avoid false sharing. _: void align(std.atomic.cache_line) = {}, @@ -69,9 +72,9 @@ pub const Extended = union(enum) { config_header: Todo, fail: Todo, fmt: Todo, - install_artifact: Todo, + install_artifact: InstallArtifact, install_dir: Todo, - install_file: Todo, + install_file: InstallFile, objcopy: Todo, options: Todo, remove_dir: Todo, @@ -524,7 +527,7 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi const digest = body[@sizeOf(EmitDigest)..][0..Cache.bin_digest_len]; result = .{ .root_dir = graph.local_cache_root, - .sub_path = try arena.dupe(u8, "o" ++ Io.Dir.path.sep_str ++ Cache.binToHex(digest.*)), + .sub_path = try arena.dupe(u8, "o" ++ Dir.path.sep_str ++ Cache.binToHex(digest.*)), }; }, .file_system_inputs => { @@ -535,14 +538,14 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi while (it.next()) |prefixed_path| { const prefix_index: std.zig.Server.Message.PathPrefix = @enumFromInt(prefixed_path[0] - 1); const sub_path = try arena.dupe(u8, prefixed_path[1..]); - const sub_path_dirname = Io.Dir.path.dirname(sub_path) orelse ""; + const sub_path_dirname = Dir.path.dirname(sub_path) orelse ""; switch (prefix_index) { .cwd => { const path: Path = .{ .root_dir = .cwd(), .sub_path = sub_path_dirname, }; - try addWatchInputFromPath(s, maker, path, Io.Dir.path.basename(sub_path)); + try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path)); }, .zig_lib => zl: { switch (conf_step.extended.get(conf.extra)) { @@ -558,21 +561,21 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi .root_dir = graph.zig_lib_directory, .sub_path = sub_path_dirname, }; - try addWatchInputFromPath(s, maker, path, Io.Dir.path.basename(sub_path)); + try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path)); }, .local_cache => { const path: Path = .{ .root_dir = graph.local_cache_root, .sub_path = sub_path_dirname, }; - try addWatchInputFromPath(s, maker, path, Io.Dir.path.basename(sub_path)); + try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path)); }, .global_cache => { const path: Path = .{ .root_dir = graph.global_cache_root, .sub_path = sub_path_dirname, }; - try addWatchInputFromPath(s, maker, path, Io.Dir.path.basename(sub_path)); + try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path)); }, } } @@ -680,7 +683,7 @@ fn failWithCacheError( const pp = man.files.keys()[op.file_index].prefixed_path; const prefix = man.cache.prefixes()[pp.prefix].path orelse ""; return s.fail(maker, "failed to check cache: '{s}{c}{s}' {t} {t}", .{ - prefix, Io.Dir.path.sep, pp.sub_path, man.diagnostic, op.err, + prefix, Dir.path.sep, pp.sub_path, man.diagnostic, op.err, }); }, }, @@ -718,14 +721,14 @@ fn setWatchInputsFromManifest(s: *Step, maker: *Maker, man: *Cache.Manifest) !vo const sub_path = try arena.dupe(u8, file.prefixed_path.sub_path); try addWatchInputFromPath(s, maker, .{ .root_dir = prefixes[file.prefixed_path.prefix], - .sub_path = Io.Dir.path.dirname(sub_path) orelse "", - }, Io.Dir.path.basename(sub_path)); + .sub_path = Dir.path.dirname(sub_path) orelse "", + }, Dir.path.basename(sub_path)); } } /// For steps that have a single input that never changes when re-running `make`. -pub fn singleUnchangingWatchInput(step: *Step, maker: *Maker, lazy_path: LazyPath) Allocator.Error!void { - if (!step.inputs.populated()) try step.addWatchInput(maker, lazy_path); +pub fn singleUnchangingWatchInput(step: *Step, maker: *Maker, arena: Allocator, lazy_path: LazyPath) Allocator.Error!void { + if (!step.inputs.populated()) try step.addWatchInput(maker, arena, lazy_path); } pub fn clearWatchInputs(step: *Step, maker: *Maker) void { @@ -733,19 +736,15 @@ pub fn clearWatchInputs(step: *Step, maker: *Maker) void { } /// Places a *file* dependency on the path. -pub fn addWatchInput(step: *Step, maker: *Maker, lazy_file: LazyPath) Allocator.Error!void { +pub fn addWatchInput(step: *Step, maker: *Maker, arena: Allocator, lazy_file: LazyPath) Allocator.Error!void { + const conf = &maker.scanned_config.configuration; switch (lazy_file) { - .src_path => |src_path| try addWatchInputFromBuilder(step, src_path.owner, src_path.sub_path), - .dependency => |d| try addWatchInputFromBuilder(step, d.dependency.builder, d.sub_path), - .cwd_relative => |path_string| { - try addWatchInputFromPath(step, maker, .{ - .root_dir = .{ - .path = null, - .handle = Io.Dir.cwd(), - }, - .sub_path = Io.Dir.path.dirname(path_string) orelse "", - }, Io.Dir.path.basename(path_string)); + .source_path => |source_path| { + const sub_path = source_path.sub_path.slice(conf); + const pkg_path = try maker.packagePath(arena, source_path.owner, sub_path); + try addWatchInputPath(step, maker, pkg_path); }, + .relative => |relative| try addWatchInputPath(step, maker, maker.relativePath(relative)), // Nothing to watch because this dependency edge is modeled instead via `dependants`. .generated => {}, } @@ -766,7 +765,7 @@ pub fn addDirectoryWatchInput(step: *Step, lazy_directory: LazyPath) Allocator.E try addDirectoryWatchInputFromPath(step, .{ .root_dir = .{ .path = null, - .handle = Io.Dir.cwd(), + .handle = .cwd(), }, .sub_path = path_string, }); @@ -789,13 +788,6 @@ pub fn addDirectoryWatchInputFromPath(step: *Step, maker: *Maker, path: Path) !v return addWatchInputFromPath(step, maker, path, "."); } -fn addWatchInputFromBuilder(step: *Step, maker: *Maker, package: Package, sub_path: []const u8) !void { - return addWatchInputFromPath(step, maker, .{ - .root_dir = package.build_root, - .sub_path = Io.Dir.path.dirname(sub_path) orelse "", - }, Io.Dir.path.basename(sub_path)); -} - fn addDirectoryWatchInputFromBuilder(step: *Step, package: Package, sub_path: []const u8) !void { return addDirectoryWatchInputFromPath(step, .{ .root_dir = package.build_root, @@ -806,8 +798,8 @@ fn addDirectoryWatchInputFromBuilder(step: *Step, package: Package, sub_path: [] fn addWatchInputPath(step: *Step, maker: *Maker, path: Path) Allocator.Error!void { return addWatchInputFromPath(step, maker, .{ .root_dir = path.root_dir, - .sub_path = Io.Dir.path.dirname(path.sub_path) orelse "", - }, Io.Dir.path.basename(path.sub_path)); + .sub_path = Dir.path.dirname(path.sub_path) orelse "", + }, Dir.path.basename(path.sub_path)); } fn addWatchInputFromPath(step: *Step, maker: *Maker, directory: Path, basename: []const u8) Allocator.Error!void { diff --git a/lib/compiler/Maker/Step/Compile.zig b/lib/compiler/Maker/Step/Compile.zig @@ -28,7 +28,7 @@ pub fn make( progress_node: std.Progress.Node, ) Step.ExtendedMakeError!void { const graph = maker.graph; - const step = maker.stepByIndex(compile_index); + const arena = graph.arena; // TODO don't leak into process arena const conf = &maker.scanned_config.configuration; const conf_step = compile_index.ptr(conf); const conf_comp = conf_step.extended.get(conf.extra).compile; @@ -69,16 +69,12 @@ pub fn make( } if (conf_comp.flags3.kind == .lib and conf_comp.flags2.linkage == .dynamic and - conf_comp.version.value != null and conf_comp.generated_bin.value != null and - target.flags.os_tag != .windows) + conf_comp.version.value != null and target.flags.os_tag != .windows) { - if (true) @panic("TODO"); - try doAtomicSymLinks( - step, - conf_comp.getEmittedBin().getPath2(step), - conf_comp.major_only_filename.?, - conf_comp.name_only_filename.?, - ); + if (conf_comp.generated_bin.value) |generated_bin| { + const full_dest_path = maker.generatedPath(generated_bin).*; + try maker.installSymLinks(arena, full_dest_path, compile_index, compile_index); + } } } @@ -964,35 +960,6 @@ pub fn rebuildInFuzzMode(compile: *Compile, maker: *Maker, progress_node: std.Pr return maybe_output_bin_path.?; } -pub fn doAtomicSymLinks( - step: *Step, - maker: *Maker, - output_path: []const u8, - filename_major_only: []const u8, - filename_name_only: []const u8, -) !void { - const graph = maker.graph; - const arena = graph.arena; // TODO don't leak into process arena - const io = graph.io; - const out_dir = Dir.path.dirname(output_path) orelse "."; - const out_basename = Dir.path.basename(output_path); - // sym link for libfoo.so.1 to libfoo.so.1.2.3 - const major_only_path = try Dir.path.join(arena, &.{ out_dir, filename_major_only }); - const cwd: Io.Dir = .cwd(); - cwd.symLinkAtomic(io, out_basename, major_only_path, .{}) catch |err| { - return step.fail(maker, "unable to symlink {s} -> {s}: {t}", .{ - major_only_path, out_basename, err, - }); - }; - // sym link for libfoo.so to libfoo.so.1 - const name_only_path = try Dir.path.join(arena, &.{ out_dir, filename_name_only }); - cwd.symLinkAtomic(io, filename_major_only, name_only_path, .{}) catch |err| { - return step.fail(maker, "unable to symlink {s} -> {s}: {t}", .{ - name_only_path, filename_major_only, err, - }); - }; -} - pub const PkgConfigError = error{ PkgConfigCrashed, PkgConfigFailed, diff --git a/lib/compiler/Maker/Step/InstallArtifact.zig b/lib/compiler/Maker/Step/InstallArtifact.zig @@ -1,88 +1,127 @@ +const InstallArtifact = @This(); -fn make(step: *Step, options: Step.MakeOptions) !void { - _ = options; - const install_artifact: *InstallArtifact = @fieldParentPtr("step", step); - const b = step.owner; - const io = b.graph.io; +const std = @import("std"); +const Io = std.Io; +const Configuration = std.Build.Configuration; +const assert = std.debug.assert; + +const Step = @import("../Step.zig"); +const Maker = @import("../../Maker.zig"); + +pub fn make( + install_artifact: *InstallArtifact, + step_index: Configuration.Step.Index, + maker: *Maker, + progress_node: std.Progress.Node, +) Step.ExtendedMakeError!void { + _ = install_artifact; + _ = progress_node; + const step = maker.stepByIndex(step_index); + const conf = &maker.scanned_config.configuration; + const graph = maker.graph; + const arena = graph.arena; // TODO don't leak into process arena + const io = graph.io; + const conf_step = step_index.ptr(conf); + const conf_ia = conf_step.extended.get(conf.extra).install_artifact; + const compile_step_index = conf_step.deps.get(conf).steps.slice[0]; + const conf_comp_step = compile_step_index.ptr(conf); + const conf_comp = conf_comp_step.extended.get(conf.extra).compile; + const root_module = conf_comp.root_module.get(conf); + const target = root_module.resolved_target.get(conf).?.result.get(conf); var all_cached = true; - if (install_artifact.dest_dir) |dest_dir| { - const full_dest_path = b.getInstallPath(dest_dir, install_artifact.dest_sub_path); - const p = try step.installFile(install_artifact.emitted_bin.?, full_dest_path); - all_cached = all_cached and p == .fresh; + if (conf_ia.bin_dir.value) |bin_dir| { + if (conf_comp.generated_bin.value) |generated_bin| { + const bin_sub_path = if (conf_ia.bin_sub_path.value) |s| s.slice(conf) else try std.zig.binNameAlloc(arena, .{ + .root_name = conf_comp.root_name.slice(conf), + .cpu_arch = target.flags.cpu_arch.unwrap().?, + .os_tag = target.flags.os_tag.unwrap().?, + .ofmt = target.flags.object_format.unwrap().?, + .abi = target.flags.abi.unwrap().?, + .output_mode = conf_comp.flags3.kind.toOutputMode(), + .link_mode = conf_comp.flags2.linkage.unwrap(), + .version = v: { + const string = conf_comp.version.value orelse break :v null; + const slice = string.slice(conf); + break :v std.SemanticVersion.parse(slice) catch @panic("bad semver string"); + }, + }); + const dest_dir = try maker.resolveInstallDir(arena, bin_dir); + const dest_path = try dest_dir.join(arena, bin_sub_path); + const src_path = maker.generatedPath(generated_bin).*; + const p = try maker.installPath(arena, src_path, dest_path, step_index); + all_cached = all_cached and p == .fresh; - if (install_artifact.dylib_symlinks) |dls| { - try Step.Compile.doAtomicSymLinks(step, full_dest_path, dls.major_only_filename, dls.name_only_filename); + if (conf_ia.flags.dylib_symlinks) + try maker.installSymLinks(arena, dest_path, compile_step_index, step_index); } - - install_artifact.artifact.installed_path = full_dest_path; } - if (install_artifact.compiler_rt_dyn_lib_dir) |compiler_rt_dir| { - const full_compiler_rt_path = b.getInstallPath(compiler_rt_dir, install_artifact.emitted_compiler_rt_dyn_lib.?.basename(b, step)); - const p = try step.installFile(install_artifact.emitted_compiler_rt_dyn_lib.?, full_compiler_rt_path); - all_cached = all_cached and p == .fresh; + if (conf_ia.implib_dir.value) |implib_dir| { + if (conf_comp.generated_implib.value) |generated_implib| { + const p = try maker.installGenerated(arena, generated_implib, implib_dir, step_index); + all_cached = all_cached and p == .fresh; + } } - if (install_artifact.implib_dir) |implib_dir| { - const full_implib_path = b.getInstallPath(implib_dir, install_artifact.emitted_implib.?.basename(b, step)); - const p = try step.installFile(install_artifact.emitted_implib.?, full_implib_path); - all_cached = all_cached and p == .fresh; + if (conf_ia.pdb_dir.value) |pdb_dir| { + if (conf_comp.generated_pdb.value) |generated_pdb| { + const p = try maker.installGenerated(arena, generated_pdb, pdb_dir, step_index); + all_cached = all_cached and p == .fresh; + } } - if (install_artifact.pdb_dir) |pdb_dir| { - const full_pdb_path = b.getInstallPath(pdb_dir, install_artifact.emitted_pdb.?.basename(b, step)); - const p = try step.installFile(install_artifact.emitted_pdb.?, full_pdb_path); - all_cached = all_cached and p == .fresh; - } + if (conf_ia.h_dir.value) |h_dir| { + const h_prefix = try maker.resolveInstallDir(arena, h_dir); - if (install_artifact.h_dir) |h_dir| { - if (install_artifact.emitted_h) |emitted_h| { - const full_h_path = b.getInstallPath(h_dir, emitted_h.basename(b, step)); - const p = try step.installFile(emitted_h, full_h_path); + if (conf_comp.generated_h.value) |generated_h| { + const p = try maker.installGenerated(arena, generated_h, h_dir, step_index); all_cached = all_cached and p == .fresh; } - for (install_artifact.artifact.installed_headers.items) |installation| switch (installation) { + for (conf_comp.installed_headers.slice) |installation| switch (installation.get(conf.extra)) { .file => |file| { - const full_h_path = b.getInstallPath(h_dir, file.dest_rel_path); - const p = try step.installFile(file.source, full_h_path); + const src_path = try maker.resolveLazyPathIndex(arena, file.source, step_index); + const dest_path = try h_prefix.join(arena, file.dest_sub_path.slice(conf)); + const p = try maker.installPath(arena, src_path, dest_path, step_index); all_cached = all_cached and p == .fresh; }, .directory => |dir| { - const src_dir_path = dir.source.getPath3(b, step); - const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path); + const src_dir_path = try maker.resolveLazyPathIndex(arena, dir.source, step_index); + const full_h_prefix = try h_prefix.join(arena, dir.dest_sub_path.slice(conf)); var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| { - return step.fail("unable to open source directory '{f}': {s}", .{ - src_dir_path, @errorName(err), - }); + return step.fail(maker, "unable to open source directory {f}: {t}", .{ src_dir_path, err }); }; defer src_dir.close(io); - var it = try src_dir.walk(b.allocator); - next_entry: while (try it.next(io)) |entry| { - for (dir.options.exclude_extensions) |ext| { - if (std.mem.endsWith(u8, entry.path, ext)) continue :next_entry; + var it = try src_dir.walk(arena); + next_entry: while (it.next(io) catch |err| switch (err) { + error.Canceled, error.OutOfMemory => |e| return e, + else => |e| return step.fail(maker, "failed to iterate directory {f}: {t}", .{ src_dir_path, e }), + }) |entry| { + for (dir.exclude_extensions.slice) |ext| { + if (std.mem.endsWith(u8, entry.path, ext.slice(conf))) continue :next_entry; } - if (dir.options.include_extensions) |incs| { - for (incs) |inc| { - if (std.mem.endsWith(u8, entry.path, inc)) break; + if (dir.flags.include_extensions) { + for (dir.include_extensions.slice) |inc| { + if (std.mem.endsWith(u8, entry.path, inc.slice(conf))) break; } else { continue :next_entry; } } - const full_dest_path = b.pathJoin(&.{ full_h_prefix, entry.path }); + const full_dest_path = try full_h_prefix.join(arena, entry.path); switch (entry.kind) { .directory => { - try Step.handleVerbose(b, .inherit, &.{ "install", "-d", full_dest_path }); - const p = try step.installDir(full_dest_path); + const p = try maker.installDir(arena, full_dest_path, step_index); all_cached = all_cached and p == .existed; }, .file => { - const p = try step.installFile(try dir.source.join(b.allocator, entry.path), full_dest_path); + const entry_dir_path = try maker.resolveLazyPathIndex(arena, dir.source, step_index); + const entry_path = try entry_dir_path.join(arena, entry.path); + const p = try maker.installPath(arena, entry_path, full_dest_path, step_index); all_cached = all_cached and p == .fresh; }, else => continue, diff --git a/lib/compiler/Maker/Step/InstallFile.zig b/lib/compiler/Maker/Step/InstallFile.zig @@ -0,0 +1,25 @@ +const InstallFile = @This(); + +const std = @import("std"); +const Configuration = std.Build.Configuration; + +const Step = @import("../Step.zig"); +const Maker = @import("../../Maker.zig"); + +pub fn make( + install_file: *InstallFile, + step_index: Configuration.Step.Index, + maker: *Maker, + progress_node: std.Progress.Node, +) Step.ExtendedMakeError!void { + _ = install_file; + _ = progress_node; + const arena = maker.graph.arena; // TODO don't leak into process arena + const step = maker.stepByIndex(step_index); + const conf = &maker.scanned_config.configuration; + const conf_step = step_index.ptr(conf); + const conf_if = conf_step.extended.get(conf.extra).install_file; + try step.singleUnchangingWatchInput(maker, arena, conf_if.source.get(conf)); + const p = try maker.installLazyPathSub(arena, conf_if.source, conf_if.dest_dir, conf_if.dest_sub_path.slice(conf), step_index); + step.result_cached = p == .fresh; +} diff --git a/lib/compiler/configurer.zig b/lib/compiler/configurer.zig @@ -739,21 +739,28 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { const ia: *Step.InstallArtifact = @fieldParentPtr("step", step); break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{ .flags = .{ - .dylib_symlinks = ia.dylib_symlinks != null, + .dylib_symlinks = ia.dylib_symlinks, + .bin_dir = ia.dest_dir != null, + .implib_dir = ia.implib_dir != null, + .pdb_dir = ia.pdb_dir != null, + .h_dir = ia.h_dir != null, + .bin_sub_path = ia.dest_sub_path != null, }, - .dest_dir = try addInstallDir(wc, ia.dest_dir), - .dest_sub_path = try wc.addString(ia.dest_sub_path), - .emitted_bin = try s.addOptionalLazyPathEnum(ia.emitted_bin), - .implib_dir = try addInstallDir(wc, ia.implib_dir), - .emitted_implib = try s.addOptionalLazyPathEnum(ia.emitted_implib), - .pdb_dir = try addInstallDir(wc, ia.pdb_dir), - .emitted_pdb = try s.addOptionalLazyPathEnum(ia.emitted_pdb), - .h_dir = try addInstallDir(wc, ia.h_dir), - .emitted_h = try s.addOptionalLazyPathEnum(ia.emitted_h), - .artifact = s.stepIndex(&ia.artifact.step), + .bin_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.dest_dir) }, + .implib_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.implib_dir) }, + .pdb_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.pdb_dir) }, + .h_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.h_dir) }, + .bin_sub_path = .{ .value = try s.addOptionalString(ia.dest_sub_path) }, + }))); + }, + .install_file => e: { + const sif: *Step.InstallFile = @fieldParentPtr("step", step); + break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.InstallFile, .{ + .source = try s.addLazyPath(sif.source), + .dest_dir = try addInstallDir(wc, sif.dir), + .dest_sub_path = try wc.addString(sif.dest_rel_path), }))); }, - .install_file => @panic("TODO"), .install_dir => @panic("TODO"), .remove_dir => @panic("TODO"), .fail => @panic("TODO"), @@ -851,6 +858,10 @@ fn addInstallDir(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !Co } } +fn addInstallDirDefaultNull(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !?Configuration.InstallDestDir { + return try addInstallDir(wc, install_dir orelse return null); +} + /// If the given `Step` is a `Step.Compile`, adds any dependencies for that step which /// are implied by the module graph rooted at `step.cast(Step.Compile).?.root_module`. fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void { diff --git a/lib/std/Build/Cache/Path.zig b/lib/std/Build/Cache/Path.zig @@ -213,6 +213,13 @@ pub fn stem(p: Path) []const u8 { return fs.path.stem(p.sub_path); } +pub fn dirname(p: Path) ?Path { + return .{ + .root_dir = p.root_dir, + .sub_path = fs.path.dirname(p.subPathOpt() orelse return null) orelse "", + }; +} + pub fn basename(p: Path) []const u8 { return fs.path.basename(p.sub_path); } diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig @@ -478,29 +478,25 @@ pub const Step = extern struct { }; }; + /// The first dependency step index will be the compile step whose + /// artifacts are being installed with this step. pub const InstallArtifact = struct { flags: @This().Flags, - - dest_dir: InstallDestDir, - dest_sub_path: String, - emitted_bin: LazyPath.OptionalIndex, - - implib_dir: InstallDestDir, - emitted_implib: LazyPath.OptionalIndex, - - pdb_dir: InstallDestDir, - emitted_pdb: LazyPath.OptionalIndex, - - h_dir: InstallDestDir, - emitted_h: LazyPath.OptionalIndex, - - /// Always a compile step. - artifact: Step.Index, + bin_dir: Storage.FlagOptional(.flags, .bin_dir, InstallDestDir), + implib_dir: Storage.FlagOptional(.flags, .implib_dir, InstallDestDir), + pdb_dir: Storage.FlagOptional(.flags, .pdb_dir, InstallDestDir), + h_dir: Storage.FlagOptional(.flags, .h_dir, InstallDestDir), + bin_sub_path: Storage.FlagOptional(.flags, .bin_sub_path, String), pub const Flags = packed struct(u32) { tag: Tag = .install_artifact, dylib_symlinks: bool, - _: u26 = 0, + bin_dir: bool, + implib_dir: bool, + pdb_dir: bool, + h_dir: bool, + bin_sub_path: bool, + _: u21 = 0, }; }; @@ -790,6 +786,14 @@ pub const Step = extern struct { .@"test", .test_obj => true, }; } + + pub fn toOutputMode(kind: Kind) std.builtin.OutputMode { + return switch (kind) { + .exe, .@"test" => .Exe, + .lib => .Lib, + .obj, .test_obj => .Obj, + }; + } }; pub const Subsystem = enum(u4) { console, @@ -991,7 +995,10 @@ pub const Step = extern struct { }; pub const InstallFile = struct { - flags: @This().Flags, + flags: @This().Flags = .{}, + source: LazyPath.Index, + dest_dir: InstallDestDir, + dest_sub_path: String, pub const Flags = packed struct(u32) { tag: Tag = .install_file, @@ -1434,6 +1441,25 @@ pub const InstallDestDir = enum(u32) { assert(@intFromEnum(sub_path) < @intFromEnum(InstallDestDir.none)); return @enumFromInt(@intFromEnum(sub_path)); } + + pub const Unpacked = union(enum) { + prefix, + lib, + bin, + header, + sub_path: String, + }; + + pub fn unpack(this: @This()) ?Unpacked { + return switch (this) { + .none => null, + .prefix => .prefix, + .lib => .lib, + .bin => .bin, + .header => .header, + _ => .{ .sub_path = @enumFromInt(@intFromEnum(this)) }, + }; + } }; /// Points into `string_bytes`, null-terminated. @@ -2366,7 +2392,8 @@ pub const Storage = enum { else => comptime unreachable, }, .auto => switch (Field.storage) { - .flag_optional, .enum_optional, .extended => 1, + .flag_optional, .enum_optional => (@sizeOf(Field.Value) + 3) / 4, + .extended => 1, .length_prefixed_list, .flag_length_prefixed_list, .flag_list, @@ -2520,7 +2547,7 @@ pub const LoadError = Io.Reader.Error || Allocator.Error; pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration { const header = try reader.takeStruct(Header, .little); - var result: Configuration = .{ + const result: Configuration = .{ .string_bytes = try arena.alloc(u8, header.string_bytes_len), .steps = try arena.alloc(Step, header.steps_len), .path_deps_sub = try arena.alloc(String, header.path_deps_len), diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig @@ -26,12 +26,9 @@ name: []const u8, linker_script: ?LazyPath = null, version_script: ?LazyPath = null, out_filename: []const u8, -out_lib_filename: []const u8, linkage: ?std.builtin.LinkMode = null, version: ?std.SemanticVersion, kind: Kind, -major_only_filename: ?[]const u8, -name_only_filename: ?[]const u8, formatted_panics: ?bool = null, compress_debug_sections: std.zig.CompressDebugSections = .none, verbose_link: bool, @@ -413,9 +410,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile { }), .version = options.version, .out_filename = out_filename, - .out_lib_filename = undefined, - .major_only_filename = null, - .name_only_filename = null, .installed_headers = .empty, .zig_lib_dir = null, .exec_cmd_args = null, @@ -463,35 +457,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile { lp.addStepDependencies(&compile.step); } - if (compile.kind == .lib) { - if (compile.linkage != null and compile.linkage.? == .static) { - compile.out_lib_filename = compile.out_filename; - } else if (compile.version) |version| { - if (target.os.tag.isDarwin()) { - compile.major_only_filename = owner.fmt("lib{s}.{d}.dylib", .{ - compile.name, - version.major, - }); - compile.name_only_filename = owner.fmt("lib{s}.dylib", .{compile.name}); - compile.out_lib_filename = compile.out_filename; - } else if (target.os.tag == .windows) { - compile.out_lib_filename = owner.fmt("{s}.lib", .{compile.name}); - } else { - compile.major_only_filename = owner.fmt("lib{s}.so.{d}", .{ compile.name, version.major }); - compile.name_only_filename = owner.fmt("lib{s}.so", .{compile.name}); - compile.out_lib_filename = compile.out_filename; - } - } else { - if (target.os.tag.isDarwin()) { - compile.out_lib_filename = compile.out_filename; - } else if (target.os.tag == .windows) { - compile.out_lib_filename = owner.fmt("{s}.lib", .{compile.name}); - } else { - compile.out_lib_filename = compile.out_filename; - } - } - } - return compile; } diff --git a/lib/std/Build/Step/InstallArtifact.zig b/lib/std/Build/Step/InstallArtifact.zig @@ -8,7 +8,7 @@ const LazyPath = std.Build.LazyPath; step: Step, dest_dir: ?InstallDir, -dest_sub_path: []const u8, +dest_sub_path: ?[]const u8, emitted_bin: ?LazyPath, implib_dir: ?InstallDir, @@ -24,7 +24,7 @@ emitted_compiler_rt_dyn_lib: ?LazyPath, h_dir: ?InstallDir, emitted_h: ?LazyPath, -dylib_symlinks: ?DylibSymlinkInfo, +dylib_symlinks: bool, artifact: *Step.Compile, @@ -67,6 +67,16 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins }, .override => |o| o, }; + const pdb_dir: ?InstallDir = switch (options.pdb_dir) { + .disabled => null, + .default => if (artifact.producesPdbFile()) dest_dir else null, + .override => |o| o, + }; + const implib_dir: ?InstallDir = switch (options.implib_dir) { + .disabled => null, + .default => if (artifact.producesImplib()) .lib else null, + .override => |o| o, + }; install_artifact.* = .{ .step = Step.init(.{ .tag = base_tag, @@ -74,54 +84,30 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins .owner = owner, }), .dest_dir = dest_dir, - .pdb_dir = switch (options.pdb_dir) { - .disabled => null, - .default => if (artifact.producesPdbFile()) dest_dir else null, - .override => |o| o, - }, - .compiler_rt_dyn_lib_dir = switch (options.compiler_rt_dyn_lib_dir) { - .disabled => null, - .default => if (artifact.producesCompilerRtDynLib()) dest_dir else null, - .override => |o| o, - }, + .pdb_dir = pdb_dir, .h_dir = switch (options.h_dir) { .disabled => null, .default => if (artifact.kind == .lib) .header else null, .override => |o| o, }, - .implib_dir = switch (options.implib_dir) { - .disabled => null, - .default => if (artifact.producesImplib()) .lib else null, - .override => |o| o, - }, + .implib_dir = implib_dir, - .dylib_symlinks = if (options.dylib_symlinks orelse (dest_dir != null and - artifact.isDynamicLibrary() and - artifact.version != null and - std.Build.wantSharedLibSymLinks(artifact.rootModuleTarget()))) .{ - .major_only_filename = artifact.major_only_filename.?, - .name_only_filename = artifact.name_only_filename.?, - } else null, + .dylib_symlinks = options.dylib_symlinks orelse (dest_dir != null and + artifact.isDynamicLibrary() and artifact.version != null and + std.Build.wantSharedLibSymLinks(artifact.rootModuleTarget())), - .dest_sub_path = options.dest_sub_path orelse artifact.out_filename, + .dest_sub_path = options.dest_sub_path, - .emitted_bin = null, - .emitted_pdb = null, - .emitted_compiler_rt_dyn_lib = null, + .emitted_bin = if (dest_dir != null) artifact.getEmittedBin() else null, + .emitted_pdb = if (pdb_dir != null) artifact.getEmittedPdb() else null, + // https://github.com/ziglang/zig/issues/9698 .emitted_h = null, - .emitted_implib = null, + .emitted_implib = if (implib_dir != null) artifact.getEmittedImplib() else null, .artifact = artifact, }; install_artifact.step.dependOn(&artifact.step); - if (install_artifact.dest_dir != null) install_artifact.emitted_bin = artifact.getEmittedBin(); - if (install_artifact.compiler_rt_dyn_lib_dir != null) install_artifact.emitted_compiler_rt_dyn_lib = artifact.getEmittedCompilerRtDynLib(); - if (install_artifact.pdb_dir != null) install_artifact.emitted_pdb = artifact.getEmittedPdb(); - // https://github.com/ziglang/zig/issues/9698 - //if (install_artifact.h_dir != null) install_artifact.emitted_h = artifact.getEmittedH(); - if (install_artifact.implib_dir != null) install_artifact.emitted_implib = artifact.getEmittedImplib(); - return install_artifact; } diff --git a/lib/std/Build/Step/InstallFile.zig b/lib/std/Build/Step/InstallFile.zig @@ -25,7 +25,6 @@ pub fn create( .tag = base_tag, .name = owner.fmt("install {s} to {s}", .{ source.getDisplayName(), dest_rel_path }), .owner = owner, - .makeFn = make, }), .source = source.dupe(owner), .dir = dir.dupe(owner), @@ -34,14 +33,3 @@ pub fn create( source.addStepDependencies(&install_file.step); return install_file; } - -fn make(step: *Step, options: Step.MakeOptions) !void { - _ = options; - const b = step.owner; - const install_file: *InstallFile = @fieldParentPtr("step", step); - try step.singleUnchangingWatchInput(install_file.source); - - const full_dest_path = b.getInstallPath(install_file.dir, install_file.dest_rel_path); - const p = try step.installFile(install_file.source, full_dest_path); - step.result_cached = p == .fresh; -}