authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2023-09-17 19:38:19+02:00
committergravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-09-24 02:47:21+01:00
log8eff0a0a669dbdacf9cebbc96fdf20536f3073ee
tree316411f9bb95eb8df2bc34cd9bfcba83ad246835
parentc9413a880be0e5817d31a35c95d4c8f7d1f81eff

Support non zig dependencies

Dependencies no longer require a build.zig file. Adds path function to Dependency struct which returns a LazyPath into a dependency.

3 files changed, 108 insertions(+), 37 deletions(-)

lib/std/Build.zig+31-6
...@@ -1707,6 +1707,15 @@ pub const Dependency = struct {...@@ -1707,6 +1707,15 @@ pub const Dependency = struct {
1707 panic("unable to find module '{s}'", .{name});1707 panic("unable to find module '{s}'", .{name});
1708 };1708 };
1709 }1709 }
1710
1711 pub fn path(d: *Dependency, sub_path: []const u8) LazyPath {
1712 return .{
1713 .dependency = .{
1714 .dependency = d,
1715 .sub_path = sub_path,
1716 },
1717 };
1718 }
1710};1719};
17111720
1712pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {1721pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
...@@ -1724,7 +1733,7 @@ pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {...@@ -1724,7 +1733,7 @@ pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
1724 inline for (@typeInfo(deps.packages).Struct.decls) |decl| {1733 inline for (@typeInfo(deps.packages).Struct.decls) |decl| {
1725 if (mem.eql(u8, decl.name, pkg_hash)) {1734 if (mem.eql(u8, decl.name, pkg_hash)) {
1726 const pkg = @field(deps.packages, decl.name);1735 const pkg = @field(deps.packages, decl.name);
1727 return dependencyInner(b, name, pkg.build_root, pkg.build_zig, pkg.deps, args);1736 return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg.deps, args);
1728 }1737 }
1729 }1738 }
17301739
...@@ -1801,7 +1810,7 @@ pub fn dependencyInner(...@@ -1801,7 +1810,7 @@ pub fn dependencyInner(
1801 b: *Build,1810 b: *Build,
1802 name: []const u8,1811 name: []const u8,
1803 build_root_string: []const u8,1812 build_root_string: []const u8,
1804 comptime build_zig: type,1813 comptime build_zig: ?type,
1805 pkg_deps: AvailableDeps,1814 pkg_deps: AvailableDeps,
1806 args: anytype,1815 args: anytype,
1807) *Dependency {1816) *Dependency {
...@@ -1821,11 +1830,14 @@ pub fn dependencyInner(...@@ -1821,11 +1830,14 @@ pub fn dependencyInner(
1821 process.exit(1);1830 process.exit(1);
1822 },1831 },
1823 };1832 };
1833
1824 const sub_builder = b.createChild(name, build_root, pkg_deps, user_input_options) catch @panic("unhandled error");1834 const sub_builder = b.createChild(name, build_root, pkg_deps, user_input_options) catch @panic("unhandled error");
1825 sub_builder.runBuild(build_zig) catch @panic("unhandled error");1835 if (build_zig) |bz| {
1836 sub_builder.runBuild(bz) catch @panic("unhandled error");
18261837
1827 if (sub_builder.validateUserInputDidItFail()) {1838 if (sub_builder.validateUserInputDidItFail()) {
1828 std.debug.dumpCurrentStackTrace(@returnAddress());1839 std.debug.dumpCurrentStackTrace(@returnAddress());
1840 }
1829 }1841 }
18301842
1831 const dep = b.allocator.create(Dependency) catch @panic("OOM");1843 const dep = b.allocator.create(Dependency) catch @panic("OOM");
...@@ -1892,6 +1904,11 @@ pub const LazyPath = union(enum) {...@@ -1892,6 +1904,11 @@ pub const LazyPath = union(enum) {
1892 /// Use of this tag indicates a dependency on the host system.1904 /// Use of this tag indicates a dependency on the host system.
1893 cwd_relative: []const u8,1905 cwd_relative: []const u8,
18941906
1907 dependency: struct {
1908 dependency: *Dependency,
1909 sub_path: []const u8,
1910 },
1911
1895 /// Returns a new file source that will have a relative path to the build root guaranteed.1912 /// Returns a new file source that will have a relative path to the build root guaranteed.
1896 /// Asserts the parameter is not an absolute path.1913 /// Asserts the parameter is not an absolute path.
1897 pub fn relative(path: []const u8) LazyPath {1914 pub fn relative(path: []const u8) LazyPath {
...@@ -1905,13 +1922,14 @@ pub const LazyPath = union(enum) {...@@ -1905,13 +1922,14 @@ pub const LazyPath = union(enum) {
1905 return switch (self) {1922 return switch (self) {
1906 .path, .cwd_relative => self.path,1923 .path, .cwd_relative => self.path,
1907 .generated => "generated",1924 .generated => "generated",
1925 .dependency => "dependency",
1908 };1926 };
1909 }1927 }
19101928
1911 /// Adds dependencies this file source implies to the given step.1929 /// Adds dependencies this file source implies to the given step.
1912 pub fn addStepDependencies(self: LazyPath, other_step: *Step) void {1930 pub fn addStepDependencies(self: LazyPath, other_step: *Step) void {
1913 switch (self) {1931 switch (self) {
1914 .path, .cwd_relative => {},1932 .path, .cwd_relative, .dependency => {},
1915 .generated => |gen| other_step.dependOn(gen.step),1933 .generated => |gen| other_step.dependOn(gen.step),
1916 }1934 }
1917 }1935 }
...@@ -1937,6 +1955,12 @@ pub const LazyPath = union(enum) {...@@ -1937,6 +1955,12 @@ pub const LazyPath = union(enum) {
1937 dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {};1955 dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {};
1938 @panic("misconfigured build script");1956 @panic("misconfigured build script");
1939 },1957 },
1958 .dependency => |dep| {
1959 return dep.dependency.builder.pathJoin(&[_][]const u8{
1960 dep.dependency.builder.build_root.path.?,
1961 dep.sub_path,
1962 });
1963 },
1940 }1964 }
1941 }1965 }
19421966
...@@ -1946,6 +1970,7 @@ pub const LazyPath = union(enum) {...@@ -1946,6 +1970,7 @@ pub const LazyPath = union(enum) {
1946 .path => |p| .{ .path = b.dupePath(p) },1970 .path => |p| .{ .path = b.dupePath(p) },
1947 .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) },1971 .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) },
1948 .generated => |gen| .{ .generated = gen },1972 .generated => |gen| .{ .generated = gen },
1973 .dependency => |dep| .{ .dependency = dep },
1949 };1974 };
1950 }1975 }
1951};1976};
lib/std/Build/Step/Compile.zig+1-1
...@@ -1896,7 +1896,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {...@@ -1896,7 +1896,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
1896 continue;1896 continue;
1897 }1897 }
1898 },1898 },
1899 .generated => {},1899 .generated, .dependency => {},
1900 };1900 };
19011901
1902 zig_args.appendAssumeCapacity(rpath.getPath2(b, step));1902 zig_args.appendAssumeCapacity(rpath.getPath2(b, step));
src/Package.zig+76-30
...@@ -327,30 +327,45 @@ pub fn fetchAndAddDependencies(...@@ -327,30 +327,45 @@ pub fn fetchAndAddDependencies(
327 name,327 name,
328 );328 );
329329
330 if (!sub.found_existing) {330 if (sub.mod) |mod| {
331 try sub.mod.fetchAndAddDependencies(331 if (!sub.found_existing) {
332 deps_pkg,332 try mod.fetchAndAddDependencies(
333 arena,333 deps_pkg,
334 thread_pool,334 arena,
335 http_client,335 thread_pool,
336 sub.mod.root_src_directory,336 http_client,
337 global_cache_directory,337 mod.root_src_directory,
338 local_cache_directory,338 global_cache_directory,
339 dependencies_source,339 local_cache_directory,
340 error_bundle,340 dependencies_source,
341 all_modules,341 error_bundle,
342 root_prog_node,342 all_modules,
343 dep.hash.?,343 root_prog_node,
344 );344 dep.hash.?,
345 }345 );
346 }
346347
347 try pkg.add(gpa, name, sub.mod);348 try pkg.add(gpa, name, mod);
348 if (deps_pkg.table.get(dep.hash.?)) |other_sub| {349 if (deps_pkg.table.get(dep.hash.?)) |other_sub| {
349 // This should be the same package (and hence module) since it's the same hash350 // This should be the same package (and hence module) since it's the same hash
350 // TODO: dedup multiple versions of the same package351 // TODO: dedup multiple versions of the same package
351 assert(other_sub == sub.mod);352 assert(other_sub == mod);
352 } else {353 } else {
353 try deps_pkg.add(gpa, dep.hash.?, sub.mod);354 try deps_pkg.add(gpa, dep.hash.?, mod);
355 }
356 } else if (!sub.found_existing) {
357 const pkg_dir_sub_path = "p" ++ fs.path.sep_str ++ (dep.hash.?)[0..hex_multihash_len];
358 const build_root = try global_cache_directory.join(arena, &.{pkg_dir_sub_path});
359 try dependencies_source.writer().print(
360 \\ pub const {} = struct {{
361 \\ pub const build_root = "{}";
362 \\ pub const deps: []const struct {{ []const u8, []const u8 }} = &.{{}};
363 \\ }};
364 \\
365 , .{
366 std.zig.fmtId(dep.hash.?),
367 std.zig.fmtEscapes(build_root),
368 });
354 }369 }
355 }370 }
356371
...@@ -480,7 +495,10 @@ const MultiHashHexDigest = [hex_multihash_len]u8;...@@ -480,7 +495,10 @@ const MultiHashHexDigest = [hex_multihash_len]u8;
480/// This is to avoid creating multiple modules for the same build.zig file.495/// This is to avoid creating multiple modules for the same build.zig file.
481/// If the value is `null`, the package is a known dependency, but has not yet496/// If the value is `null`, the package is a known dependency, but has not yet
482/// been fetched.497/// been fetched.
483pub const AllModules = std.AutoHashMapUnmanaged(MultiHashHexDigest, ?*Package);498pub const AllModules = std.AutoHashMapUnmanaged(MultiHashHexDigest, ?union(enum) {
499 zig_pkg: *Package,
500 non_zig_pkg: void,
501});
484502
485fn ProgressReader(comptime ReaderType: type) type {503fn ProgressReader(comptime ReaderType: type) type {
486 return struct {504 return struct {
...@@ -535,7 +553,7 @@ fn fetchAndUnpack(...@@ -535,7 +553,7 @@ fn fetchAndUnpack(
535 /// This does not have to be any form of canonical or fully-qualified name: it553 /// This does not have to be any form of canonical or fully-qualified name: it
536 /// is only intended to be human-readable for progress reporting.554 /// is only intended to be human-readable for progress reporting.
537 name_for_prog: []const u8,555 name_for_prog: []const u8,
538) !struct { mod: *Package, found_existing: bool } {556) !struct { mod: ?*Package, found_existing: bool } {
539 const gpa = http_client.allocator;557 const gpa = http_client.allocator;
540 const s = fs.path.sep_str;558 const s = fs.path.sep_str;
541559
...@@ -556,13 +574,27 @@ fn fetchAndUnpack(...@@ -556,13 +574,27 @@ fn fetchAndUnpack(
556 const gop = try all_modules.getOrPut(gpa, hex_digest.*);574 const gop = try all_modules.getOrPut(gpa, hex_digest.*);
557 if (gop.found_existing) {575 if (gop.found_existing) {
558 if (gop.value_ptr.*) |mod| {576 if (gop.value_ptr.*) |mod| {
559 return .{577 return switch (mod) {
560 .mod = mod,578 .zig_pkg => |pkg| .{
561 .found_existing = true,579 .mod = pkg,
580 .found_existing = true,
581 },
582 .non_zig_pkg => .{
583 .mod = null,
584 .found_existing = true,
585 },
562 };586 };
563 }587 }
564 }588 }
565589
590 pkg_dir.access(build_zig_basename, .{}) catch {
591 gop.value_ptr.* = .non_zig_pkg;
592 return .{
593 .mod = null,
594 .found_existing = false,
595 };
596 };
597
566 const build_root = try global_cache_directory.join(gpa, &.{pkg_dir_sub_path});598 const build_root = try global_cache_directory.join(gpa, &.{pkg_dir_sub_path});
567 errdefer gpa.free(build_root);599 errdefer gpa.free(build_root);
568600
...@@ -583,7 +615,7 @@ fn fetchAndUnpack(...@@ -583,7 +615,7 @@ fn fetchAndUnpack(
583 .root_src_path = owned_src_path,615 .root_src_path = owned_src_path,
584 };616 };
585617
586 gop.value_ptr.* = ptr;618 gop.value_ptr.* = .{ .zig_pkg = ptr };
587 return .{619 return .{
588 .mod = ptr,620 .mod = ptr,
589 .found_existing = false,621 .found_existing = false,
...@@ -722,8 +754,22 @@ fn fetchAndUnpack(...@@ -722,8 +754,22 @@ fn fetchAndUnpack(
722 return error.PackageFetchFailed;754 return error.PackageFetchFailed;
723 }755 }
724756
757 const build_zig_path = try std.fs.path.join(gpa, &.{ pkg_dir_sub_path, build_zig_basename });
758 defer gpa.free(build_zig_path);
759
760 global_cache_directory.handle.access(build_zig_path, .{}) catch |err| switch (err) {
761 error.FileNotFound => {
762 try all_modules.put(gpa, actual_hex, .non_zig_pkg);
763 return .{
764 .mod = null,
765 .found_existing = false,
766 };
767 },
768 else => return err,
769 };
770
725 const mod = try createWithDir(gpa, global_cache_directory, pkg_dir_sub_path, build_zig_basename);771 const mod = try createWithDir(gpa, global_cache_directory, pkg_dir_sub_path, build_zig_basename);
726 try all_modules.put(gpa, actual_hex, mod);772 try all_modules.put(gpa, actual_hex, .{ .zig_pkg = mod });
727 return .{773 return .{
728 .mod = mod,774 .mod = mod,
729 .found_existing = false,775 .found_existing = false,