1const InstallArtifact = @This();
2
3const std = @import("std");
4const Step = std.Build.Step;
5const InstallDir = std.Build.InstallDir;
6const LazyPath = std.Build.LazyPath;
7
8step: Step,
9
10dest_dir: ?InstallDir,
11dest_sub_path: ?[]const u8,
12emitted_bin: ?LazyPath,
13
14implib_dir: ?InstallDir,
15emitted_implib: ?LazyPath,
16
17pdb_dir: ?InstallDir,
18emitted_pdb: ?LazyPath,
19
20h_dir: ?InstallDir,
21emitted_h: ?LazyPath,
22
23dylib_symlinks: bool,
24
25artifact: *Step.Compile,
26
27const DylibSymlinkInfo = struct {
28 major_only_filename: []const u8,
29 name_only_filename: []const u8,
30};
31
32pub const base_tag: Step.Tag = .install_artifact;
33
34pub const Options = struct {
35 /// Which installation directory to put the main output file into.
36 dest_dir: Dir = .default,
37 pdb_dir: Dir = .default,
38 compiler_rt_dyn_lib_dir: Dir = .default,
39 h_dir: Dir = .default,
40 implib_dir: Dir = .default,
41
42 /// Whether to install symlinks along with dynamic libraries.
43 dylib_symlinks: ?bool = null,
44 /// If non-null, adds additional path components relative to bin dir, and
45 /// overrides the basename of the Compile step for installation purposes.
46 dest_sub_path: ?[]const u8 = null,
47
48 pub const Dir = union(enum) {
49 disabled,
50 default,
51 override: InstallDir,
52 };
53};
54
55pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *InstallArtifact {
56 const install_artifact = owner.allocator.create(InstallArtifact) catch @panic("OOM");
57 const dest_dir: ?InstallDir = switch (options.dest_dir) {
58 .disabled => null,
59 .default => switch (artifact.kind) {
60 .obj, .test_obj => @panic("object files have no standard installation procedure"),
61 .exe, .@"test" => .bin,
62 .lib => if (artifact.isDll()) .bin else .lib,
63 },
64 .override => |o| o,
65 };
66 const pdb_dir: ?InstallDir = switch (options.pdb_dir) {
67 .disabled => null,
68 .default => if (artifact.producesPdbFile()) dest_dir else null,
69 .override => |o| o,
70 };
71 const implib_dir: ?InstallDir = switch (options.implib_dir) {
72 .disabled => null,
73 .default => if (artifact.producesImplib()) .lib else null,
74 .override => |o| o,
75 };
76 install_artifact.* = .{
77 .step = Step.init(.{
78 .tag = base_tag,
79 .name = owner.fmt("install {s}", .{artifact.name}),
80 .owner = owner,
81 }),
82 .dest_dir = dest_dir,
83 .pdb_dir = pdb_dir,
84 .h_dir = switch (options.h_dir) {
85 .disabled => null,
86 .default => if (artifact.kind == .lib) .header else null,
87 .override => |o| o,
88 },
89 .implib_dir = implib_dir,
90
91 .dylib_symlinks = options.dylib_symlinks orelse (dest_dir != null and
92 artifact.isDynamicLibrary() and artifact.version != null and
93 std.Build.wantSharedLibSymLinks(artifact.rootModuleTarget())),
94
95 .dest_sub_path = options.dest_sub_path,
96
97 .emitted_bin = if (dest_dir != null) artifact.getEmittedBin() else null,
98 .emitted_pdb = if (pdb_dir != null) artifact.getEmittedPdb() else null,
99 // https://github.com/ziglang/zig/issues/9698
100 .emitted_h = null,
101 .emitted_implib = if (implib_dir != null) artifact.getEmittedImplib() else null,
102
103 .artifact = artifact,
104 };
105
106 install_artifact.step.dependOn(&artifact.step);
107
108 return install_artifact;
109}