authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-03-17 12:18:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:34-07:00
logaa0652ff8dc9add09567d69a92ddaff5ad386919
tree87fd48ec099c4237a30302df1e720e7aa559abbe
parentdd51fc30f884aa1c3305793010a30d826689be89

maker: implement InstallArtifact and InstallFile


13 files changed, 421 insertions(+), 283 deletions(-)

BRANCH_TODO+5-1
......@@ -1,9 +1,10 @@
1* replace b.dupe() with string internment
1* implement the build options
22* don't forget to add -listen arg back
33* get zig init template working
44* finish migrating the rest of the build steps
55* make zig-pkg path root configurable in maker (make sure --system still works)
66* eliminate calls to getPath, getPath2, getPath3
7* replace b.dupe() with string internment
78* solve the TODOs added in this branch
89* get zig tests passing
910* test a bunch of third party projects / help people migrate
......@@ -13,3 +14,6 @@
1314## Followup Issues
1415* link_eh_frame_hdr should be DefaultingBool
1516* make --foo, --no-foo CLI args uniform (make them -f args instead)
17* install steps should provide generated files for installed things, then delete the run step hack
18
19
lib/compiler/Maker.zig+170-44
......@@ -7,6 +7,7 @@ const Cache = std.Build.Cache;
77const Configuration = std.Build.Configuration;
88const File = std.Io.File;
99const Io = std.Io;
10const Dir = std.Io.Dir;
1011const Path = std.Build.Cache.Path;
1112const Writer = std.Io.Writer;
1213const assert = std.debug.assert;
......@@ -82,7 +83,7 @@ pub fn main(init: process.Init.Minimal) !void {
8283 const global_cache_root = expectArgOrFatal(args, &arg_idx, "--global-cache");
8384 const configure_path = expectArgOrFatal(args, &arg_idx, "--configuration");
8485
85 const cwd: Io.Dir = .cwd();
86 const cwd: Dir = .cwd();
8687
8788 const zig_lib_directory: Cache.Directory = .{
8889 .path = zig_lib_dir,
......@@ -497,7 +498,7 @@ pub fn main(init: process.Init.Minimal) !void {
497498
498499 const install_prefix_path: Path = if (graph.environ_map.get("DESTDIR")) |dest_dir| .{
499500 .root_dir = .cwd(),
500 .sub_path = try Io.Dir.path.join(arena, &.{ dest_dir, override_install_prefix orelse "/usr" }),
501 .sub_path = try Dir.path.join(arena, &.{ dest_dir, override_install_prefix orelse "/usr" }),
501502 } else if (override_install_prefix) |cwd_relative| .{
502503 .root_dir = .cwd(),
503504 .sub_path = cwd_relative,
......@@ -1675,7 +1676,7 @@ fn cleanTmpFiles(io: Io, steps: []const Configuration.Step.Index) void {
16751676 const wf = step_index.cast(std.Build.Step.WriteFile) orelse continue;
16761677 if (wf.mode != .tmp) continue;
16771678 const path = wf.generated_directory.path orelse continue;
1678 Io.Dir.cwd().deleteTree(io, path) catch |err| {
1679 Dir.cwd().deleteTree(io, path) catch |err| {
16791680 log.warn("failed to delete {s}: {t}", .{ path, err });
16801681 };
16811682 }
......@@ -1699,29 +1700,14 @@ pub fn resolveLazyPath(
16991700) Allocator.Error!Path {
17001701 _ = asking_step_index; // TODO use this to enhance debugability when this function fails
17011702 const c = &maker.scanned_config.configuration;
1702 const graph = maker.graph;
17031703 return switch (lazy_path) {
17041704 .source_path => |sp| try packagePath(maker, arena, sp.owner, sp.sub_path.slice(c)),
1705 .relative => |relative| switch (relative.flags.base) {
1706 .cwd => .{
1707 .root_dir = .cwd(),
1708 .sub_path = relative.sub_path.slice(c),
1709 },
1710 .local_cache => .{
1711 .root_dir = graph.local_cache_root,
1712 },
1713 .global_cache => .{
1714 .root_dir = graph.global_cache_root,
1715 },
1716 .build_root => .{
1717 .root_dir = graph.build_root_directory,
1718 },
1719 },
1705 .relative => |relative| relativePath(maker, relative),
17201706 .generated => |gen| {
1721 const base = maker.generated_files[@intFromEnum(gen.index)];
1707 const base = generatedPath(maker, gen.index);
17221708 var file_path = base;
17231709 for (0..gen.flags.up) |_| {
1724 file_path.sub_path = Io.Dir.path.dirname(file_path.sub_path) orelse
1710 file_path.sub_path = Dir.path.dirname(file_path.sub_path) orelse
17251711 fatal("invalid LazyPath traversal: up {d} times from {f}", .{ gen.flags.up, base });
17261712 }
17271713 return file_path.join(arena, gen.sub_path.slice(c));
......@@ -1750,7 +1736,7 @@ pub fn resolveLazyPathAbs(
17501736 const p = try resolveLazyPath(maker, arena, lazy_path, asking_step_index);
17511737 const root_dir_path = p.root_dir.path orelse return p.subPathOrDot();
17521738 if (p.sub_path.len == 0) return root_dir_path;
1753 return Io.Dir.path.join(arena, &.{ root_dir_path, p.sub_path });
1739 return Dir.path.join(arena, &.{ root_dir_path, p.sub_path });
17541740}
17551741
17561742/// `resolveLazyPath` is preferred, but this can be necessary when passing Path
......@@ -1765,11 +1751,11 @@ pub fn resolveLazyPathIndexAbs(
17651751 return resolveLazyPathAbs(maker, arena, lazy_path_index.get(c), asking_step_index);
17661752}
17671753
1768pub fn generatedPath(maker: *Maker, index: Configuration.GeneratedFileIndex) *Path {
1754pub fn generatedPath(maker: *const Maker, index: Configuration.GeneratedFileIndex) *Path {
17691755 return &maker.generated_files[@intFromEnum(index)];
17701756}
17711757
1772fn packagePath(
1758pub fn packagePath(
17731759 maker: *const Maker,
17741760 arena: Allocator,
17751761 package_index: Configuration.Package.Index,
......@@ -1785,43 +1771,183 @@ fn packagePath(
17851771 const pkg_root = graph.pkg_root;
17861772 return .{
17871773 .root_dir = pkg_root.root_dir,
1788 .sub_path = try Io.Dir.path.join(arena, &.{ pkg_root.sub_path, hash, sub_path }),
1774 .sub_path = try Dir.path.join(arena, &.{ pkg_root.sub_path, hash, sub_path }),
1775 };
1776}
1777
1778pub fn relativePath(maker: *const Maker, relative: Configuration.LazyPath.Relative) Path {
1779 const graph = maker.graph;
1780 const c = &maker.scanned_config.configuration;
1781 const sub_path = relative.sub_path.slice(c);
1782 return switch (relative.flags.base) {
1783 .cwd => .{
1784 .root_dir = .cwd(),
1785 .sub_path = sub_path,
1786 },
1787 .local_cache => .{
1788 .root_dir = graph.local_cache_root,
1789 .sub_path = sub_path,
1790 },
1791 .global_cache => .{
1792 .root_dir = graph.global_cache_root,
1793 .sub_path = sub_path,
1794 },
1795 .build_root => .{
1796 .root_dir = graph.build_root_directory,
1797 .sub_path = sub_path,
1798 },
17891799 };
17901800}
17911801
1792/// Wrapper around `Io.Dir.updateFile` that handles verbose and error output.
1793pub fn installFile(
1802pub fn resolveInstallDir(
17941803 maker: *Maker,
17951804 arena: Allocator,
1796 src_lazy_path: Configuration.LazyPath,
1797 dest_path: []const u8,
1805 dest_dir: Configuration.InstallDestDir,
1806) Allocator.Error!Path {
1807 const c = &maker.scanned_config.configuration;
1808 return switch (dest_dir.unpack().?) {
1809 .prefix => maker.install_paths.prefix,
1810 .lib => maker.install_paths.lib,
1811 .bin => maker.install_paths.bin,
1812 .header => maker.install_paths.include,
1813 .sub_path => |s| try maker.install_paths.prefix.join(arena, s.slice(c)),
1814 };
1815}
1816
1817pub fn installLazyPathSub(
1818 maker: *Maker,
1819 arena: Allocator,
1820 source: Configuration.LazyPath.Index,
1821 dest_dir: Configuration.InstallDestDir,
1822 sub_path: []const u8,
17981823 asking_step_index: Configuration.Step.Index,
1799) !Io.Dir.PrevStatus {
1824) !Dir.PrevStatus {
1825 const src_path = try resolveLazyPathIndex(maker, arena, source, asking_step_index);
1826 const dest_dir_path = try resolveInstallDir(maker, arena, dest_dir);
1827 const dest_path = try dest_dir_path.join(arena, sub_path);
1828 return installPath(maker, arena, src_path, dest_path, asking_step_index);
1829}
1830
1831pub fn installLazyPath(
1832 maker: *Maker,
1833 arena: Allocator,
1834 source: Configuration.LazyPath.Index,
1835 dest_dir: Configuration.InstallDestDir,
1836 asking_step_index: Configuration.Step.Index,
1837) !Dir.PrevStatus {
1838 const src_path = try resolveLazyPathIndex(maker, arena, source, asking_step_index);
1839 const dest_dir_path = try resolveInstallDir(maker, arena, dest_dir);
1840 const dest_path = try dest_dir_path.join(arena, src_path.basename());
1841 return installPath(maker, arena, src_path, dest_path, asking_step_index);
1842}
1843
1844pub fn installGenerated(
1845 maker: *Maker,
1846 arena: Allocator,
1847 source: Configuration.GeneratedFileIndex,
1848 dest_dir: Configuration.InstallDestDir,
1849 asking_step_index: Configuration.Step.Index,
1850) !Dir.PrevStatus {
1851 const src_path = generatedPath(maker, source).*;
1852 const dest_dir_path = try resolveInstallDir(maker, arena, dest_dir);
1853 const dest_path = try dest_dir_path.join(arena, src_path.basename());
1854 return installPath(maker, arena, src_path, dest_path, asking_step_index);
1855}
1856
1857pub fn installPath(
1858 maker: *Maker,
1859 arena: Allocator,
1860 src_path: Path,
1861 dest_path: Path,
1862 asking_step_index: Configuration.Step.Index,
1863) !Dir.PrevStatus {
18001864 const graph = maker.graph;
18011865 const io = graph.io;
1802 const src_path = try resolveLazyPath(maker, arena, src_lazy_path, asking_step_index);
1803 {
1804 const src_path_rendered = try src_path.toString(arena);
1805 defer arena.free(src_path_rendered);
1806 try graph.handleVerbose(.inherit, null, &.{ "install", "-C", src_path_rendered, dest_path });
1807 }
1808 return Io.Dir.updateFile(src_path.root_dir.handle, io, src_path.sub_path, .cwd(), dest_path, .{}) catch |err| {
1866 if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{
1867 "install", "-C", try src_path.toString(arena), try dest_path.toString(arena),
1868 });
1869 return Dir.updateFile(
1870 src_path.root_dir.handle,
1871 io,
1872 src_path.sub_path,
1873 dest_path.root_dir.handle,
1874 dest_path.sub_path,
1875 .{},
1876 ) catch |err| {
18091877 const s = stepByIndex(maker, asking_step_index);
1810 return s.fail(maker, "unable to update file from '{f}' to '{s}': {t}", .{ src_path, dest_path, err });
1878 return s.fail(maker, "unable to update file from {f} to {f}: {t}", .{ src_path, dest_path, err });
18111879 };
18121880}
18131881
1814/// Wrapper around `Io.Dir.createDirPathStatus` that handles verbose and error output.
1882/// Wrapper around `Dir.createDirPathStatus` that handles verbose and error output.
18151883pub fn installDir(
18161884 maker: *Maker,
1817 dest_path: []const u8,
1885 arena: Allocator,
1886 dest_path: Path,
18181887 asking_step_index: Configuration.Step.Index,
1819) !Io.Dir.CreatePathStatus {
1888) !Dir.CreatePathStatus {
18201889 const graph = maker.graph;
18211890 const io = graph.io;
1822 try graph.handleVerbose(.inherit, null, &.{ "install", "-d", dest_path });
1823 return Io.Dir.cwd().createDirPathStatus(io, dest_path, .default_dir) catch |err| {
1891 if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{
1892 "install", "-d", try dest_path.toString(arena),
1893 });
1894 return dest_path.root_dir.handle.createDirPathStatus(io, dest_path.sub_path, .default_dir) catch |err| {
18241895 const s = stepByIndex(maker, asking_step_index);
1825 return s.fail(maker, "unable to create dir '{s}': {t}", .{ dest_path, err });
1896 return s.fail(maker, "unable to create dir {f}: {t}", .{ dest_path, err });
1897 };
1898}
1899
1900pub fn installSymLinks(
1901 maker: *Maker,
1902 arena: Allocator,
1903 output_path: Path,
1904 compile_step_index: Configuration.Step.Index,
1905 asking_step_index: Configuration.Step.Index,
1906) !void {
1907 const c = &maker.scanned_config.configuration;
1908 const conf_step = compile_step_index.ptr(c);
1909 const conf_comp = conf_step.extended.get(c.extra).compile;
1910 const root_module = conf_comp.root_module.get(c);
1911 const target = root_module.resolved_target.get(c).?.result.get(c);
1912 const os_tag = target.flags.os_tag.unwrap().?;
1913
1914 assert(conf_comp.flags3.kind == .lib);
1915 assert(conf_comp.flags2.linkage == .dynamic);
1916 assert(os_tag != .windows);
1917
1918 const version = std.SemanticVersion.parse(conf_comp.version.value.?.slice(c)) catch unreachable;
1919 const name = conf_comp.root_name.slice(c);
1920
1921 const filename_major_only, const filename_name_only = if (os_tag.isDarwin()) .{
1922 try std.fmt.allocPrint(arena, "lib{s}.{d}.dylib", .{ name, version.major }),
1923 try std.fmt.allocPrint(arena, "lib{s}.dylib", .{name}),
1924 } else .{
1925 try std.fmt.allocPrint(arena, "lib{s}.so.{d}", .{ name, version.major }),
1926 try std.fmt.allocPrint(arena, "lib{s}.so", .{name}),
1927 };
1928
1929 return installSymLinksInner(maker, arena, output_path, asking_step_index, filename_major_only, filename_name_only);
1930}
1931
1932fn installSymLinksInner(
1933 maker: *Maker,
1934 arena: Allocator,
1935 output_path: Path,
1936 asking_step_index: Configuration.Step.Index,
1937 filename_major_only: []const u8,
1938 filename_name_only: []const u8,
1939) !void {
1940 const io = maker.graph.io;
1941 const step = stepByIndex(maker, asking_step_index);
1942 const out_dir = output_path.dirname().?;
1943 // sym link for libfoo.so.1 to libfoo.so.1.2.3
1944 const major_only_path = try out_dir.join(arena, filename_major_only);
1945 output_path.root_dir.handle.symLinkAtomic(io, output_path.sub_path, major_only_path.sub_path, .{}) catch |err| {
1946 return step.fail(maker, "unable to symlink {f} -> {f}: {t}", .{ output_path, major_only_path, err });
1947 };
1948 // sym link for libfoo.so to libfoo.so.1
1949 const name_only_path = try out_dir.join(arena, filename_name_only);
1950 major_only_path.root_dir.handle.symLinkAtomic(io, major_only_path.sub_path, name_only_path.sub_path, .{}) catch |err| {
1951 return step.fail(maker, "unable to symlink {f} -> {s}: {t}", .{ name_only_path, filename_major_only, err });
18261952 };
18271953}
lib/compiler/Maker/Graph.zig+2-1
......@@ -5,6 +5,7 @@ const std = @import("std");
55const Io = std.Io;
66const Allocator = std.mem.Allocator;
77const Configuration = std.Build.Configuration;
8const Path = std.Build.Cache.Path;
89
910io: Io,
1011/// Process lifetime.
......@@ -16,7 +17,7 @@ global_cache_root: std.Build.Cache.Directory,
1617local_cache_root: std.Build.Cache.Directory,
1718zig_lib_directory: std.Build.Cache.Directory,
1819build_root_directory: std.Build.Cache.Directory,
19pkg_root: std.Build.Cache.Path,
20pkg_root: Path,
2021
2122debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null,
2223incremental: ?bool = null,
lib/compiler/Maker/Step.zig+26-34
......@@ -8,6 +8,7 @@ const std = @import("std");
88const Allocator = std.mem.Allocator;
99const Cache = std.Build.Cache;
1010const Io = std.Io;
11const Dir = std.Io.Dir;
1112const LazyPath = std.Build.Configuration.LazyPath;
1213const Package = std.Build.Configuration.Package;
1314const Path = std.Build.Cache.Path;
......@@ -19,6 +20,8 @@ const Maker = @import("../Maker.zig");
1920
2021const Compile = @import("Step/Compile.zig");
2122const Run = @import("Step/Run.zig");
23const InstallArtifact = @import("Step/InstallArtifact.zig");
24const InstallFile = @import("Step/InstallFile.zig");
2225
2326/// Avoid false sharing.
2427_: void align(std.atomic.cache_line) = {},
......@@ -69,9 +72,9 @@ pub const Extended = union(enum) {
6972 config_header: Todo,
7073 fail: Todo,
7174 fmt: Todo,
72 install_artifact: Todo,
75 install_artifact: InstallArtifact,
7376 install_dir: Todo,
74 install_file: Todo,
77 install_file: InstallFile,
7578 objcopy: Todo,
7679 options: Todo,
7780 remove_dir: Todo,
......@@ -524,7 +527,7 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi
524527 const digest = body[@sizeOf(EmitDigest)..][0..Cache.bin_digest_len];
525528 result = .{
526529 .root_dir = graph.local_cache_root,
527 .sub_path = try arena.dupe(u8, "o" ++ Io.Dir.path.sep_str ++ Cache.binToHex(digest.*)),
530 .sub_path = try arena.dupe(u8, "o" ++ Dir.path.sep_str ++ Cache.binToHex(digest.*)),
528531 };
529532 },
530533 .file_system_inputs => {
......@@ -535,14 +538,14 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi
535538 while (it.next()) |prefixed_path| {
536539 const prefix_index: std.zig.Server.Message.PathPrefix = @enumFromInt(prefixed_path[0] - 1);
537540 const sub_path = try arena.dupe(u8, prefixed_path[1..]);
538 const sub_path_dirname = Io.Dir.path.dirname(sub_path) orelse "";
541 const sub_path_dirname = Dir.path.dirname(sub_path) orelse "";
539542 switch (prefix_index) {
540543 .cwd => {
541544 const path: Path = .{
542545 .root_dir = .cwd(),
543546 .sub_path = sub_path_dirname,
544547 };
545 try addWatchInputFromPath(s, maker, path, Io.Dir.path.basename(sub_path));
548 try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path));
546549 },
547550 .zig_lib => zl: {
548551 switch (conf_step.extended.get(conf.extra)) {
......@@ -558,21 +561,21 @@ fn zigProcessUpdate(step_index: Configuration.Step.Index, maker: *Maker, zp: *Zi
558561 .root_dir = graph.zig_lib_directory,
559562 .sub_path = sub_path_dirname,
560563 };
561 try addWatchInputFromPath(s, maker, path, Io.Dir.path.basename(sub_path));
564 try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path));
562565 },
563566 .local_cache => {
564567 const path: Path = .{
565568 .root_dir = graph.local_cache_root,
566569 .sub_path = sub_path_dirname,
567570 };
568 try addWatchInputFromPath(s, maker, path, Io.Dir.path.basename(sub_path));
571 try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path));
569572 },
570573 .global_cache => {
571574 const path: Path = .{
572575 .root_dir = graph.global_cache_root,
573576 .sub_path = sub_path_dirname,
574577 };
575 try addWatchInputFromPath(s, maker, path, Io.Dir.path.basename(sub_path));
578 try addWatchInputFromPath(s, maker, path, Dir.path.basename(sub_path));
576579 },
577580 }
578581 }
......@@ -680,7 +683,7 @@ fn failWithCacheError(
680683 const pp = man.files.keys()[op.file_index].prefixed_path;
681684 const prefix = man.cache.prefixes()[pp.prefix].path orelse "";
682685 return s.fail(maker, "failed to check cache: '{s}{c}{s}' {t} {t}", .{
683 prefix, Io.Dir.path.sep, pp.sub_path, man.diagnostic, op.err,
686 prefix, Dir.path.sep, pp.sub_path, man.diagnostic, op.err,
684687 });
685688 },
686689 },
......@@ -718,14 +721,14 @@ fn setWatchInputsFromManifest(s: *Step, maker: *Maker, man: *Cache.Manifest) !vo
718721 const sub_path = try arena.dupe(u8, file.prefixed_path.sub_path);
719722 try addWatchInputFromPath(s, maker, .{
720723 .root_dir = prefixes[file.prefixed_path.prefix],
721 .sub_path = Io.Dir.path.dirname(sub_path) orelse "",
722 }, Io.Dir.path.basename(sub_path));
724 .sub_path = Dir.path.dirname(sub_path) orelse "",
725 }, Dir.path.basename(sub_path));
723726 }
724727}
725728
726729/// For steps that have a single input that never changes when re-running `make`.
727pub fn singleUnchangingWatchInput(step: *Step, maker: *Maker, lazy_path: LazyPath) Allocator.Error!void {
728 if (!step.inputs.populated()) try step.addWatchInput(maker, lazy_path);
730pub fn singleUnchangingWatchInput(step: *Step, maker: *Maker, arena: Allocator, lazy_path: LazyPath) Allocator.Error!void {
731 if (!step.inputs.populated()) try step.addWatchInput(maker, arena, lazy_path);
729732}
730733
731734pub fn clearWatchInputs(step: *Step, maker: *Maker) void {
......@@ -733,19 +736,15 @@ pub fn clearWatchInputs(step: *Step, maker: *Maker) void {
733736}
734737
735738/// Places a *file* dependency on the path.
736pub fn addWatchInput(step: *Step, maker: *Maker, lazy_file: LazyPath) Allocator.Error!void {
739pub fn addWatchInput(step: *Step, maker: *Maker, arena: Allocator, lazy_file: LazyPath) Allocator.Error!void {
740 const conf = &maker.scanned_config.configuration;
737741 switch (lazy_file) {
738 .src_path => |src_path| try addWatchInputFromBuilder(step, src_path.owner, src_path.sub_path),
739 .dependency => |d| try addWatchInputFromBuilder(step, d.dependency.builder, d.sub_path),
740 .cwd_relative => |path_string| {
741 try addWatchInputFromPath(step, maker, .{
742 .root_dir = .{
743 .path = null,
744 .handle = Io.Dir.cwd(),
745 },
746 .sub_path = Io.Dir.path.dirname(path_string) orelse "",
747 }, Io.Dir.path.basename(path_string));
742 .source_path => |source_path| {
743 const sub_path = source_path.sub_path.slice(conf);
744 const pkg_path = try maker.packagePath(arena, source_path.owner, sub_path);
745 try addWatchInputPath(step, maker, pkg_path);
748746 },
747 .relative => |relative| try addWatchInputPath(step, maker, maker.relativePath(relative)),
749748 // Nothing to watch because this dependency edge is modeled instead via `dependants`.
750749 .generated => {},
751750 }
......@@ -766,7 +765,7 @@ pub fn addDirectoryWatchInput(step: *Step, lazy_directory: LazyPath) Allocator.E
766765 try addDirectoryWatchInputFromPath(step, .{
767766 .root_dir = .{
768767 .path = null,
769 .handle = Io.Dir.cwd(),
768 .handle = .cwd(),
770769 },
771770 .sub_path = path_string,
772771 });
......@@ -789,13 +788,6 @@ pub fn addDirectoryWatchInputFromPath(step: *Step, maker: *Maker, path: Path) !v
789788 return addWatchInputFromPath(step, maker, path, ".");
790789}
791790
792fn addWatchInputFromBuilder(step: *Step, maker: *Maker, package: Package, sub_path: []const u8) !void {
793 return addWatchInputFromPath(step, maker, .{
794 .root_dir = package.build_root,
795 .sub_path = Io.Dir.path.dirname(sub_path) orelse "",
796 }, Io.Dir.path.basename(sub_path));
797}
798
799791fn addDirectoryWatchInputFromBuilder(step: *Step, package: Package, sub_path: []const u8) !void {
800792 return addDirectoryWatchInputFromPath(step, .{
801793 .root_dir = package.build_root,
......@@ -806,8 +798,8 @@ fn addDirectoryWatchInputFromBuilder(step: *Step, package: Package, sub_path: []
806798fn addWatchInputPath(step: *Step, maker: *Maker, path: Path) Allocator.Error!void {
807799 return addWatchInputFromPath(step, maker, .{
808800 .root_dir = path.root_dir,
809 .sub_path = Io.Dir.path.dirname(path.sub_path) orelse "",
810 }, Io.Dir.path.basename(path.sub_path));
801 .sub_path = Dir.path.dirname(path.sub_path) orelse "",
802 }, Dir.path.basename(path.sub_path));
811803}
812804
813805fn addWatchInputFromPath(step: *Step, maker: *Maker, directory: Path, basename: []const u8) Allocator.Error!void {
lib/compiler/Maker/Step/Compile.zig+6-39
......@@ -28,7 +28,7 @@ pub fn make(
2828 progress_node: std.Progress.Node,
2929) Step.ExtendedMakeError!void {
3030 const graph = maker.graph;
31 const step = maker.stepByIndex(compile_index);
31 const arena = graph.arena; // TODO don't leak into process arena
3232 const conf = &maker.scanned_config.configuration;
3333 const conf_step = compile_index.ptr(conf);
3434 const conf_comp = conf_step.extended.get(conf.extra).compile;
......@@ -69,16 +69,12 @@ pub fn make(
6969 }
7070
7171 if (conf_comp.flags3.kind == .lib and conf_comp.flags2.linkage == .dynamic and
72 conf_comp.version.value != null and conf_comp.generated_bin.value != null and
73 target.flags.os_tag != .windows)
72 conf_comp.version.value != null and target.flags.os_tag != .windows)
7473 {
75 if (true) @panic("TODO");
76 try doAtomicSymLinks(
77 step,
78 conf_comp.getEmittedBin().getPath2(step),
79 conf_comp.major_only_filename.?,
80 conf_comp.name_only_filename.?,
81 );
74 if (conf_comp.generated_bin.value) |generated_bin| {
75 const full_dest_path = maker.generatedPath(generated_bin).*;
76 try maker.installSymLinks(arena, full_dest_path, compile_index, compile_index);
77 }
8278 }
8379}
8480
......@@ -964,35 +960,6 @@ pub fn rebuildInFuzzMode(compile: *Compile, maker: *Maker, progress_node: std.Pr
964960 return maybe_output_bin_path.?;
965961}
966962
967pub fn doAtomicSymLinks(
968 step: *Step,
969 maker: *Maker,
970 output_path: []const u8,
971 filename_major_only: []const u8,
972 filename_name_only: []const u8,
973) !void {
974 const graph = maker.graph;
975 const arena = graph.arena; // TODO don't leak into process arena
976 const io = graph.io;
977 const out_dir = Dir.path.dirname(output_path) orelse ".";
978 const out_basename = Dir.path.basename(output_path);
979 // sym link for libfoo.so.1 to libfoo.so.1.2.3
980 const major_only_path = try Dir.path.join(arena, &.{ out_dir, filename_major_only });
981 const cwd: Io.Dir = .cwd();
982 cwd.symLinkAtomic(io, out_basename, major_only_path, .{}) catch |err| {
983 return step.fail(maker, "unable to symlink {s} -> {s}: {t}", .{
984 major_only_path, out_basename, err,
985 });
986 };
987 // sym link for libfoo.so to libfoo.so.1
988 const name_only_path = try Dir.path.join(arena, &.{ out_dir, filename_name_only });
989 cwd.symLinkAtomic(io, filename_major_only, name_only_path, .{}) catch |err| {
990 return step.fail(maker, "unable to symlink {s} -> {s}: {t}", .{
991 name_only_path, filename_major_only, err,
992 });
993 };
994}
995
996963pub const PkgConfigError = error{
997964 PkgConfigCrashed,
998965 PkgConfigFailed,
lib/compiler/Maker/Step/InstallArtifact.zig+88-49
......@@ -1,88 +1,127 @@
1const InstallArtifact = @This();
12
2fn make(step: *Step, options: Step.MakeOptions) !void {
3 _ = options;
4 const install_artifact: *InstallArtifact = @fieldParentPtr("step", step);
5 const b = step.owner;
6 const io = b.graph.io;
3const std = @import("std");
4const Io = std.Io;
5const Configuration = std.Build.Configuration;
6const assert = std.debug.assert;
7
8const Step = @import("../Step.zig");
9const Maker = @import("../../Maker.zig");
10
11pub fn make(
12 install_artifact: *InstallArtifact,
13 step_index: Configuration.Step.Index,
14 maker: *Maker,
15 progress_node: std.Progress.Node,
16) Step.ExtendedMakeError!void {
17 _ = install_artifact;
18 _ = progress_node;
19 const step = maker.stepByIndex(step_index);
20 const conf = &maker.scanned_config.configuration;
21 const graph = maker.graph;
22 const arena = graph.arena; // TODO don't leak into process arena
23 const io = graph.io;
24 const conf_step = step_index.ptr(conf);
25 const conf_ia = conf_step.extended.get(conf.extra).install_artifact;
26 const compile_step_index = conf_step.deps.get(conf).steps.slice[0];
27 const conf_comp_step = compile_step_index.ptr(conf);
28 const conf_comp = conf_comp_step.extended.get(conf.extra).compile;
29 const root_module = conf_comp.root_module.get(conf);
30 const target = root_module.resolved_target.get(conf).?.result.get(conf);
731
832 var all_cached = true;
933
10 if (install_artifact.dest_dir) |dest_dir| {
11 const full_dest_path = b.getInstallPath(dest_dir, install_artifact.dest_sub_path);
12 const p = try step.installFile(install_artifact.emitted_bin.?, full_dest_path);
13 all_cached = all_cached and p == .fresh;
34 if (conf_ia.bin_dir.value) |bin_dir| {
35 if (conf_comp.generated_bin.value) |generated_bin| {
36 const bin_sub_path = if (conf_ia.bin_sub_path.value) |s| s.slice(conf) else try std.zig.binNameAlloc(arena, .{
37 .root_name = conf_comp.root_name.slice(conf),
38 .cpu_arch = target.flags.cpu_arch.unwrap().?,
39 .os_tag = target.flags.os_tag.unwrap().?,
40 .ofmt = target.flags.object_format.unwrap().?,
41 .abi = target.flags.abi.unwrap().?,
42 .output_mode = conf_comp.flags3.kind.toOutputMode(),
43 .link_mode = conf_comp.flags2.linkage.unwrap(),
44 .version = v: {
45 const string = conf_comp.version.value orelse break :v null;
46 const slice = string.slice(conf);
47 break :v std.SemanticVersion.parse(slice) catch @panic("bad semver string");
48 },
49 });
50 const dest_dir = try maker.resolveInstallDir(arena, bin_dir);
51 const dest_path = try dest_dir.join(arena, bin_sub_path);
52 const src_path = maker.generatedPath(generated_bin).*;
53 const p = try maker.installPath(arena, src_path, dest_path, step_index);
54 all_cached = all_cached and p == .fresh;
1455
15 if (install_artifact.dylib_symlinks) |dls| {
16 try Step.Compile.doAtomicSymLinks(step, full_dest_path, dls.major_only_filename, dls.name_only_filename);
56 if (conf_ia.flags.dylib_symlinks)
57 try maker.installSymLinks(arena, dest_path, compile_step_index, step_index);
1758 }
18
19 install_artifact.artifact.installed_path = full_dest_path;
2059 }
2160
22 if (install_artifact.compiler_rt_dyn_lib_dir) |compiler_rt_dir| {
23 const full_compiler_rt_path = b.getInstallPath(compiler_rt_dir, install_artifact.emitted_compiler_rt_dyn_lib.?.basename(b, step));
24 const p = try step.installFile(install_artifact.emitted_compiler_rt_dyn_lib.?, full_compiler_rt_path);
25 all_cached = all_cached and p == .fresh;
61 if (conf_ia.implib_dir.value) |implib_dir| {
62 if (conf_comp.generated_implib.value) |generated_implib| {
63 const p = try maker.installGenerated(arena, generated_implib, implib_dir, step_index);
64 all_cached = all_cached and p == .fresh;
65 }
2666 }
2767
28 if (install_artifact.implib_dir) |implib_dir| {
29 const full_implib_path = b.getInstallPath(implib_dir, install_artifact.emitted_implib.?.basename(b, step));
30 const p = try step.installFile(install_artifact.emitted_implib.?, full_implib_path);
31 all_cached = all_cached and p == .fresh;
68 if (conf_ia.pdb_dir.value) |pdb_dir| {
69 if (conf_comp.generated_pdb.value) |generated_pdb| {
70 const p = try maker.installGenerated(arena, generated_pdb, pdb_dir, step_index);
71 all_cached = all_cached and p == .fresh;
72 }
3273 }
3374
34 if (install_artifact.pdb_dir) |pdb_dir| {
35 const full_pdb_path = b.getInstallPath(pdb_dir, install_artifact.emitted_pdb.?.basename(b, step));
36 const p = try step.installFile(install_artifact.emitted_pdb.?, full_pdb_path);
37 all_cached = all_cached and p == .fresh;
38 }
75 if (conf_ia.h_dir.value) |h_dir| {
76 const h_prefix = try maker.resolveInstallDir(arena, h_dir);
3977
40 if (install_artifact.h_dir) |h_dir| {
41 if (install_artifact.emitted_h) |emitted_h| {
42 const full_h_path = b.getInstallPath(h_dir, emitted_h.basename(b, step));
43 const p = try step.installFile(emitted_h, full_h_path);
78 if (conf_comp.generated_h.value) |generated_h| {
79 const p = try maker.installGenerated(arena, generated_h, h_dir, step_index);
4480 all_cached = all_cached and p == .fresh;
4581 }
4682
47 for (install_artifact.artifact.installed_headers.items) |installation| switch (installation) {
83 for (conf_comp.installed_headers.slice) |installation| switch (installation.get(conf.extra)) {
4884 .file => |file| {
49 const full_h_path = b.getInstallPath(h_dir, file.dest_rel_path);
50 const p = try step.installFile(file.source, full_h_path);
85 const src_path = try maker.resolveLazyPathIndex(arena, file.source, step_index);
86 const dest_path = try h_prefix.join(arena, file.dest_sub_path.slice(conf));
87 const p = try maker.installPath(arena, src_path, dest_path, step_index);
5188 all_cached = all_cached and p == .fresh;
5289 },
5390 .directory => |dir| {
54 const src_dir_path = dir.source.getPath3(b, step);
55 const full_h_prefix = b.getInstallPath(h_dir, dir.dest_rel_path);
91 const src_dir_path = try maker.resolveLazyPathIndex(arena, dir.source, step_index);
92 const full_h_prefix = try h_prefix.join(arena, dir.dest_sub_path.slice(conf));
5693
5794 var src_dir = src_dir_path.root_dir.handle.openDir(io, src_dir_path.subPathOrDot(), .{ .iterate = true }) catch |err| {
58 return step.fail("unable to open source directory '{f}': {s}", .{
59 src_dir_path, @errorName(err),
60 });
95 return step.fail(maker, "unable to open source directory {f}: {t}", .{ src_dir_path, err });
6196 };
6297 defer src_dir.close(io);
6398
64 var it = try src_dir.walk(b.allocator);
65 next_entry: while (try it.next(io)) |entry| {
66 for (dir.options.exclude_extensions) |ext| {
67 if (std.mem.endsWith(u8, entry.path, ext)) continue :next_entry;
99 var it = try src_dir.walk(arena);
100 next_entry: while (it.next(io) catch |err| switch (err) {
101 error.Canceled, error.OutOfMemory => |e| return e,
102 else => |e| return step.fail(maker, "failed to iterate directory {f}: {t}", .{ src_dir_path, e }),
103 }) |entry| {
104 for (dir.exclude_extensions.slice) |ext| {
105 if (std.mem.endsWith(u8, entry.path, ext.slice(conf))) continue :next_entry;
68106 }
69 if (dir.options.include_extensions) |incs| {
70 for (incs) |inc| {
71 if (std.mem.endsWith(u8, entry.path, inc)) break;
107 if (dir.flags.include_extensions) {
108 for (dir.include_extensions.slice) |inc| {
109 if (std.mem.endsWith(u8, entry.path, inc.slice(conf))) break;
72110 } else {
73111 continue :next_entry;
74112 }
75113 }
76114
77 const full_dest_path = b.pathJoin(&.{ full_h_prefix, entry.path });
115 const full_dest_path = try full_h_prefix.join(arena, entry.path);
78116 switch (entry.kind) {
79117 .directory => {
80 try Step.handleVerbose(b, .inherit, &.{ "install", "-d", full_dest_path });
81 const p = try step.installDir(full_dest_path);
118 const p = try maker.installDir(arena, full_dest_path, step_index);
82119 all_cached = all_cached and p == .existed;
83120 },
84121 .file => {
85 const p = try step.installFile(try dir.source.join(b.allocator, entry.path), full_dest_path);
122 const entry_dir_path = try maker.resolveLazyPathIndex(arena, dir.source, step_index);
123 const entry_path = try entry_dir_path.join(arena, entry.path);
124 const p = try maker.installPath(arena, entry_path, full_dest_path, step_index);
86125 all_cached = all_cached and p == .fresh;
87126 },
88127 else => continue,
lib/compiler/Maker/Step/InstallFile.zig created+25
......@@ -0,0 +1,25 @@
1const InstallFile = @This();
2
3const std = @import("std");
4const Configuration = std.Build.Configuration;
5
6const Step = @import("../Step.zig");
7const Maker = @import("../../Maker.zig");
8
9pub fn make(
10 install_file: *InstallFile,
11 step_index: Configuration.Step.Index,
12 maker: *Maker,
13 progress_node: std.Progress.Node,
14) Step.ExtendedMakeError!void {
15 _ = install_file;
16 _ = progress_node;
17 const arena = maker.graph.arena; // TODO don't leak into process arena
18 const step = maker.stepByIndex(step_index);
19 const conf = &maker.scanned_config.configuration;
20 const conf_step = step_index.ptr(conf);
21 const conf_if = conf_step.extended.get(conf.extra).install_file;
22 try step.singleUnchangingWatchInput(maker, arena, conf_if.source.get(conf));
23 const p = try maker.installLazyPathSub(arena, conf_if.source, conf_if.dest_dir, conf_if.dest_sub_path.slice(conf), step_index);
24 step.result_cached = p == .fresh;
25}
lib/compiler/configurer.zig+23-12
......@@ -739,21 +739,28 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
739739 const ia: *Step.InstallArtifact = @fieldParentPtr("step", step);
740740 break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.InstallArtifact, .{
741741 .flags = .{
742 .dylib_symlinks = ia.dylib_symlinks != null,
742 .dylib_symlinks = ia.dylib_symlinks,
743 .bin_dir = ia.dest_dir != null,
744 .implib_dir = ia.implib_dir != null,
745 .pdb_dir = ia.pdb_dir != null,
746 .h_dir = ia.h_dir != null,
747 .bin_sub_path = ia.dest_sub_path != null,
743748 },
744 .dest_dir = try addInstallDir(wc, ia.dest_dir),
745 .dest_sub_path = try wc.addString(ia.dest_sub_path),
746 .emitted_bin = try s.addOptionalLazyPathEnum(ia.emitted_bin),
747 .implib_dir = try addInstallDir(wc, ia.implib_dir),
748 .emitted_implib = try s.addOptionalLazyPathEnum(ia.emitted_implib),
749 .pdb_dir = try addInstallDir(wc, ia.pdb_dir),
750 .emitted_pdb = try s.addOptionalLazyPathEnum(ia.emitted_pdb),
751 .h_dir = try addInstallDir(wc, ia.h_dir),
752 .emitted_h = try s.addOptionalLazyPathEnum(ia.emitted_h),
753 .artifact = s.stepIndex(&ia.artifact.step),
749 .bin_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.dest_dir) },
750 .implib_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.implib_dir) },
751 .pdb_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.pdb_dir) },
752 .h_dir = .{ .value = try addInstallDirDefaultNull(wc, ia.h_dir) },
753 .bin_sub_path = .{ .value = try s.addOptionalString(ia.dest_sub_path) },
754 })));
755 },
756 .install_file => e: {
757 const sif: *Step.InstallFile = @fieldParentPtr("step", step);
758 break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.InstallFile, .{
759 .source = try s.addLazyPath(sif.source),
760 .dest_dir = try addInstallDir(wc, sif.dir),
761 .dest_sub_path = try wc.addString(sif.dest_rel_path),
754762 })));
755763 },
756 .install_file => @panic("TODO"),
757764 .install_dir => @panic("TODO"),
758765 .remove_dir => @panic("TODO"),
759766 .fail => @panic("TODO"),
......@@ -851,6 +858,10 @@ fn addInstallDir(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !Co
851858 }
852859}
853860
861fn addInstallDirDefaultNull(wc: *Configuration.Wip, install_dir: ?std.Build.InstallDir) !?Configuration.InstallDestDir {
862 return try addInstallDir(wc, install_dir orelse return null);
863}
864
854865/// If the given `Step` is a `Step.Compile`, adds any dependencies for that step which
855866/// are implied by the module graph rooted at `step.cast(Step.Compile).?.root_module`.
856867fn createModuleDependenciesForStep(step: *Step) Allocator.Error!void {
lib/std/Build/Cache/Path.zig+7
......@@ -213,6 +213,13 @@ pub fn stem(p: Path) []const u8 {
213213 return fs.path.stem(p.sub_path);
214214}
215215
216pub fn dirname(p: Path) ?Path {
217 return .{
218 .root_dir = p.root_dir,
219 .sub_path = fs.path.dirname(p.subPathOpt() orelse return null) orelse "",
220 };
221}
222
216223pub fn basename(p: Path) []const u8 {
217224 return fs.path.basename(p.sub_path);
218225}
lib/std/Build/Configuration.zig+47-20
......@@ -478,29 +478,25 @@ pub const Step = extern struct {
478478 };
479479 };
480480
481 /// The first dependency step index will be the compile step whose
482 /// artifacts are being installed with this step.
481483 pub const InstallArtifact = struct {
482484 flags: @This().Flags,
483
484 dest_dir: InstallDestDir,
485 dest_sub_path: String,
486 emitted_bin: LazyPath.OptionalIndex,
487
488 implib_dir: InstallDestDir,
489 emitted_implib: LazyPath.OptionalIndex,
490
491 pdb_dir: InstallDestDir,
492 emitted_pdb: LazyPath.OptionalIndex,
493
494 h_dir: InstallDestDir,
495 emitted_h: LazyPath.OptionalIndex,
496
497 /// Always a compile step.
498 artifact: Step.Index,
485 bin_dir: Storage.FlagOptional(.flags, .bin_dir, InstallDestDir),
486 implib_dir: Storage.FlagOptional(.flags, .implib_dir, InstallDestDir),
487 pdb_dir: Storage.FlagOptional(.flags, .pdb_dir, InstallDestDir),
488 h_dir: Storage.FlagOptional(.flags, .h_dir, InstallDestDir),
489 bin_sub_path: Storage.FlagOptional(.flags, .bin_sub_path, String),
499490
500491 pub const Flags = packed struct(u32) {
501492 tag: Tag = .install_artifact,
502493 dylib_symlinks: bool,
503 _: u26 = 0,
494 bin_dir: bool,
495 implib_dir: bool,
496 pdb_dir: bool,
497 h_dir: bool,
498 bin_sub_path: bool,
499 _: u21 = 0,
504500 };
505501 };
506502
......@@ -790,6 +786,14 @@ pub const Step = extern struct {
790786 .@"test", .test_obj => true,
791787 };
792788 }
789
790 pub fn toOutputMode(kind: Kind) std.builtin.OutputMode {
791 return switch (kind) {
792 .exe, .@"test" => .Exe,
793 .lib => .Lib,
794 .obj, .test_obj => .Obj,
795 };
796 }
793797 };
794798 pub const Subsystem = enum(u4) {
795799 console,
......@@ -991,7 +995,10 @@ pub const Step = extern struct {
991995 };
992996
993997 pub const InstallFile = struct {
994 flags: @This().Flags,
998 flags: @This().Flags = .{},
999 source: LazyPath.Index,
1000 dest_dir: InstallDestDir,
1001 dest_sub_path: String,
9951002
9961003 pub const Flags = packed struct(u32) {
9971004 tag: Tag = .install_file,
......@@ -1434,6 +1441,25 @@ pub const InstallDestDir = enum(u32) {
14341441 assert(@intFromEnum(sub_path) < @intFromEnum(InstallDestDir.none));
14351442 return @enumFromInt(@intFromEnum(sub_path));
14361443 }
1444
1445 pub const Unpacked = union(enum) {
1446 prefix,
1447 lib,
1448 bin,
1449 header,
1450 sub_path: String,
1451 };
1452
1453 pub fn unpack(this: @This()) ?Unpacked {
1454 return switch (this) {
1455 .none => null,
1456 .prefix => .prefix,
1457 .lib => .lib,
1458 .bin => .bin,
1459 .header => .header,
1460 _ => .{ .sub_path = @enumFromInt(@intFromEnum(this)) },
1461 };
1462 }
14371463};
14381464
14391465/// Points into `string_bytes`, null-terminated.
......@@ -2366,7 +2392,8 @@ pub const Storage = enum {
23662392 else => comptime unreachable,
23672393 },
23682394 .auto => switch (Field.storage) {
2369 .flag_optional, .enum_optional, .extended => 1,
2395 .flag_optional, .enum_optional => (@sizeOf(Field.Value) + 3) / 4,
2396 .extended => 1,
23702397 .length_prefixed_list,
23712398 .flag_length_prefixed_list,
23722399 .flag_list,
......@@ -2520,7 +2547,7 @@ pub const LoadError = Io.Reader.Error || Allocator.Error;
25202547
25212548pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
25222549 const header = try reader.takeStruct(Header, .little);
2523 var result: Configuration = .{
2550 const result: Configuration = .{
25242551 .string_bytes = try arena.alloc(u8, header.string_bytes_len),
25252552 .steps = try arena.alloc(Step, header.steps_len),
25262553 .path_deps_sub = try arena.alloc(String, header.path_deps_len),
lib/std/Build/Step/Compile.zig-35
......@@ -26,12 +26,9 @@ name: []const u8,
2626linker_script: ?LazyPath = null,
2727version_script: ?LazyPath = null,
2828out_filename: []const u8,
29out_lib_filename: []const u8,
3029linkage: ?std.builtin.LinkMode = null,
3130version: ?std.SemanticVersion,
3231kind: Kind,
33major_only_filename: ?[]const u8,
34name_only_filename: ?[]const u8,
3532formatted_panics: ?bool = null,
3633compress_debug_sections: std.zig.CompressDebugSections = .none,
3734verbose_link: bool,
......@@ -413,9 +410,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
413410 }),
414411 .version = options.version,
415412 .out_filename = out_filename,
416 .out_lib_filename = undefined,
417 .major_only_filename = null,
418 .name_only_filename = null,
419413 .installed_headers = .empty,
420414 .zig_lib_dir = null,
421415 .exec_cmd_args = null,
......@@ -463,35 +457,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
463457 lp.addStepDependencies(&compile.step);
464458 }
465459
466 if (compile.kind == .lib) {
467 if (compile.linkage != null and compile.linkage.? == .static) {
468 compile.out_lib_filename = compile.out_filename;
469 } else if (compile.version) |version| {
470 if (target.os.tag.isDarwin()) {
471 compile.major_only_filename = owner.fmt("lib{s}.{d}.dylib", .{
472 compile.name,
473 version.major,
474 });
475 compile.name_only_filename = owner.fmt("lib{s}.dylib", .{compile.name});
476 compile.out_lib_filename = compile.out_filename;
477 } else if (target.os.tag == .windows) {
478 compile.out_lib_filename = owner.fmt("{s}.lib", .{compile.name});
479 } else {
480 compile.major_only_filename = owner.fmt("lib{s}.so.{d}", .{ compile.name, version.major });
481 compile.name_only_filename = owner.fmt("lib{s}.so", .{compile.name});
482 compile.out_lib_filename = compile.out_filename;
483 }
484 } else {
485 if (target.os.tag.isDarwin()) {
486 compile.out_lib_filename = compile.out_filename;
487 } else if (target.os.tag == .windows) {
488 compile.out_lib_filename = owner.fmt("{s}.lib", .{compile.name});
489 } else {
490 compile.out_lib_filename = compile.out_filename;
491 }
492 }
493 }
494
495460 return compile;
496461}
497462
lib/std/Build/Step/InstallArtifact.zig+22-36
......@@ -8,7 +8,7 @@ const LazyPath = std.Build.LazyPath;
88step: Step,
99
1010dest_dir: ?InstallDir,
11dest_sub_path: []const u8,
11dest_sub_path: ?[]const u8,
1212emitted_bin: ?LazyPath,
1313
1414implib_dir: ?InstallDir,
......@@ -24,7 +24,7 @@ emitted_compiler_rt_dyn_lib: ?LazyPath,
2424h_dir: ?InstallDir,
2525emitted_h: ?LazyPath,
2626
27dylib_symlinks: ?DylibSymlinkInfo,
27dylib_symlinks: bool,
2828
2929artifact: *Step.Compile,
3030
......@@ -67,6 +67,16 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins
6767 },
6868 .override => |o| o,
6969 };
70 const pdb_dir: ?InstallDir = switch (options.pdb_dir) {
71 .disabled => null,
72 .default => if (artifact.producesPdbFile()) dest_dir else null,
73 .override => |o| o,
74 };
75 const implib_dir: ?InstallDir = switch (options.implib_dir) {
76 .disabled => null,
77 .default => if (artifact.producesImplib()) .lib else null,
78 .override => |o| o,
79 };
7080 install_artifact.* = .{
7181 .step = Step.init(.{
7282 .tag = base_tag,
......@@ -74,54 +84,30 @@ pub fn create(owner: *std.Build, artifact: *Step.Compile, options: Options) *Ins
7484 .owner = owner,
7585 }),
7686 .dest_dir = dest_dir,
77 .pdb_dir = switch (options.pdb_dir) {
78 .disabled => null,
79 .default => if (artifact.producesPdbFile()) dest_dir else null,
80 .override => |o| o,
81 },
82 .compiler_rt_dyn_lib_dir = switch (options.compiler_rt_dyn_lib_dir) {
83 .disabled => null,
84 .default => if (artifact.producesCompilerRtDynLib()) dest_dir else null,
85 .override => |o| o,
86 },
87 .pdb_dir = pdb_dir,
8788 .h_dir = switch (options.h_dir) {
8889 .disabled => null,
8990 .default => if (artifact.kind == .lib) .header else null,
9091 .override => |o| o,
9192 },
92 .implib_dir = switch (options.implib_dir) {
93 .disabled => null,
94 .default => if (artifact.producesImplib()) .lib else null,
95 .override => |o| o,
96 },
93 .implib_dir = implib_dir,
9794
98 .dylib_symlinks = if (options.dylib_symlinks orelse (dest_dir != null and
99 artifact.isDynamicLibrary() and
100 artifact.version != null and
101 std.Build.wantSharedLibSymLinks(artifact.rootModuleTarget()))) .{
102 .major_only_filename = artifact.major_only_filename.?,
103 .name_only_filename = artifact.name_only_filename.?,
104 } else null,
95 .dylib_symlinks = options.dylib_symlinks orelse (dest_dir != null and
96 artifact.isDynamicLibrary() and artifact.version != null and
97 std.Build.wantSharedLibSymLinks(artifact.rootModuleTarget())),
10598
106 .dest_sub_path = options.dest_sub_path orelse artifact.out_filename,
99 .dest_sub_path = options.dest_sub_path,
107100
108 .emitted_bin = null,
109 .emitted_pdb = null,
110 .emitted_compiler_rt_dyn_lib = null,
101 .emitted_bin = if (dest_dir != null) artifact.getEmittedBin() else null,
102 .emitted_pdb = if (pdb_dir != null) artifact.getEmittedPdb() else null,
103 // https://github.com/ziglang/zig/issues/9698
111104 .emitted_h = null,
112 .emitted_implib = null,
105 .emitted_implib = if (implib_dir != null) artifact.getEmittedImplib() else null,
113106
114107 .artifact = artifact,
115108 };
116109
117110 install_artifact.step.dependOn(&artifact.step);
118111
119 if (install_artifact.dest_dir != null) install_artifact.emitted_bin = artifact.getEmittedBin();
120 if (install_artifact.compiler_rt_dyn_lib_dir != null) install_artifact.emitted_compiler_rt_dyn_lib = artifact.getEmittedCompilerRtDynLib();
121 if (install_artifact.pdb_dir != null) install_artifact.emitted_pdb = artifact.getEmittedPdb();
122 // https://github.com/ziglang/zig/issues/9698
123 //if (install_artifact.h_dir != null) install_artifact.emitted_h = artifact.getEmittedH();
124 if (install_artifact.implib_dir != null) install_artifact.emitted_implib = artifact.getEmittedImplib();
125
126112 return install_artifact;
127113}
lib/std/Build/Step/InstallFile.zig-12
......@@ -25,7 +25,6 @@ pub fn create(
2525 .tag = base_tag,
2626 .name = owner.fmt("install {s} to {s}", .{ source.getDisplayName(), dest_rel_path }),
2727 .owner = owner,
28 .makeFn = make,
2928 }),
3029 .source = source.dupe(owner),
3130 .dir = dir.dupe(owner),
......@@ -34,14 +33,3 @@ pub fn create(
3433 source.addStepDependencies(&install_file.step);
3534 return install_file;
3635}
37
38fn make(step: *Step, options: Step.MakeOptions) !void {
39 _ = options;
40 const b = step.owner;
41 const install_file: *InstallFile = @fieldParentPtr("step", step);
42 try step.singleUnchangingWatchInput(install_file.source);
43
44 const full_dest_path = b.getInstallPath(install_file.dir, install_file.dest_rel_path);
45 const p = try step.installFile(install_file.source, full_dest_path);
46 step.result_cached = p == .fresh;
47}