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 {
17071707 panic("unable to find module '{s}'", .{name});
17081708 };
17091709 }
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 }
17101719};
17111720
17121721pub 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 {
17241733 inline for (@typeInfo(deps.packages).Struct.decls) |decl| {
17251734 if (mem.eql(u8, decl.name, pkg_hash)) {
17261735 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);
17281737 }
17291738 }
17301739
......@@ -1801,7 +1810,7 @@ pub fn dependencyInner(
18011810 b: *Build,
18021811 name: []const u8,
18031812 build_root_string: []const u8,
1804 comptime build_zig: type,
1813 comptime build_zig: ?type,
18051814 pkg_deps: AvailableDeps,
18061815 args: anytype,
18071816) *Dependency {
......@@ -1821,11 +1830,14 @@ pub fn dependencyInner(
18211830 process.exit(1);
18221831 },
18231832 };
1833
18241834 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()) {
1828 std.debug.dumpCurrentStackTrace(@returnAddress());
1838 if (sub_builder.validateUserInputDidItFail()) {
1839 std.debug.dumpCurrentStackTrace(@returnAddress());
1840 }
18291841 }
18301842
18311843 const dep = b.allocator.create(Dependency) catch @panic("OOM");
......@@ -1892,6 +1904,11 @@ pub const LazyPath = union(enum) {
18921904 /// Use of this tag indicates a dependency on the host system.
18931905 cwd_relative: []const u8,
18941906
1907 dependency: struct {
1908 dependency: *Dependency,
1909 sub_path: []const u8,
1910 },
1911
18951912 /// Returns a new file source that will have a relative path to the build root guaranteed.
18961913 /// Asserts the parameter is not an absolute path.
18971914 pub fn relative(path: []const u8) LazyPath {
......@@ -1905,13 +1922,14 @@ pub const LazyPath = union(enum) {
19051922 return switch (self) {
19061923 .path, .cwd_relative => self.path,
19071924 .generated => "generated",
1925 .dependency => "dependency",
19081926 };
19091927 }
19101928
19111929 /// Adds dependencies this file source implies to the given step.
19121930 pub fn addStepDependencies(self: LazyPath, other_step: *Step) void {
19131931 switch (self) {
1914 .path, .cwd_relative => {},
1932 .path, .cwd_relative, .dependency => {},
19151933 .generated => |gen| other_step.dependOn(gen.step),
19161934 }
19171935 }
......@@ -1937,6 +1955,12 @@ pub const LazyPath = union(enum) {
19371955 dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {};
19381956 @panic("misconfigured build script");
19391957 },
1958 .dependency => |dep| {
1959 return dep.dependency.builder.pathJoin(&[_][]const u8{
1960 dep.dependency.builder.build_root.path.?,
1961 dep.sub_path,
1962 });
1963 },
19401964 }
19411965 }
19421966
......@@ -1946,6 +1970,7 @@ pub const LazyPath = union(enum) {
19461970 .path => |p| .{ .path = b.dupePath(p) },
19471971 .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) },
19481972 .generated => |gen| .{ .generated = gen },
1973 .dependency => |dep| .{ .dependency = dep },
19491974 };
19501975 }
19511976};
lib/std/Build/Step/Compile.zig+1-1
......@@ -1896,7 +1896,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
18961896 continue;
18971897 }
18981898 },
1899 .generated => {},
1899 .generated, .dependency => {},
19001900 };
19011901
19021902 zig_args.appendAssumeCapacity(rpath.getPath2(b, step));
src/Package.zig+76-30
......@@ -327,30 +327,45 @@ pub fn fetchAndAddDependencies(
327327 name,
328328 );
329329
330 if (!sub.found_existing) {
331 try sub.mod.fetchAndAddDependencies(
332 deps_pkg,
333 arena,
334 thread_pool,
335 http_client,
336 sub.mod.root_src_directory,
337 global_cache_directory,
338 local_cache_directory,
339 dependencies_source,
340 error_bundle,
341 all_modules,
342 root_prog_node,
343 dep.hash.?,
344 );
345 }
330 if (sub.mod) |mod| {
331 if (!sub.found_existing) {
332 try mod.fetchAndAddDependencies(
333 deps_pkg,
334 arena,
335 thread_pool,
336 http_client,
337 mod.root_src_directory,
338 global_cache_directory,
339 local_cache_directory,
340 dependencies_source,
341 error_bundle,
342 all_modules,
343 root_prog_node,
344 dep.hash.?,
345 );
346 }
346347
347 try pkg.add(gpa, name, sub.mod);
348 if (deps_pkg.table.get(dep.hash.?)) |other_sub| {
349 // This should be the same package (and hence module) since it's the same hash
350 // TODO: dedup multiple versions of the same package
351 assert(other_sub == sub.mod);
352 } else {
353 try deps_pkg.add(gpa, dep.hash.?, sub.mod);
348 try pkg.add(gpa, name, mod);
349 if (deps_pkg.table.get(dep.hash.?)) |other_sub| {
350 // This should be the same package (and hence module) since it's the same hash
351 // TODO: dedup multiple versions of the same package
352 assert(other_sub == mod);
353 } else {
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 });
354369 }
355370 }
356371
......@@ -480,7 +495,10 @@ const MultiHashHexDigest = [hex_multihash_len]u8;
480495/// This is to avoid creating multiple modules for the same build.zig file.
481496/// If the value is `null`, the package is a known dependency, but has not yet
482497/// 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
485503fn ProgressReader(comptime ReaderType: type) type {
486504 return struct {
......@@ -535,7 +553,7 @@ fn fetchAndUnpack(
535553 /// This does not have to be any form of canonical or fully-qualified name: it
536554 /// is only intended to be human-readable for progress reporting.
537555 name_for_prog: []const u8,
538) !struct { mod: *Package, found_existing: bool } {
556) !struct { mod: ?*Package, found_existing: bool } {
539557 const gpa = http_client.allocator;
540558 const s = fs.path.sep_str;
541559
......@@ -556,13 +574,27 @@ fn fetchAndUnpack(
556574 const gop = try all_modules.getOrPut(gpa, hex_digest.*);
557575 if (gop.found_existing) {
558576 if (gop.value_ptr.*) |mod| {
559 return .{
560 .mod = mod,
561 .found_existing = true,
577 return switch (mod) {
578 .zig_pkg => |pkg| .{
579 .mod = pkg,
580 .found_existing = true,
581 },
582 .non_zig_pkg => .{
583 .mod = null,
584 .found_existing = true,
585 },
562586 };
563587 }
564588 }
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
566598 const build_root = try global_cache_directory.join(gpa, &.{pkg_dir_sub_path});
567599 errdefer gpa.free(build_root);
568600
......@@ -583,7 +615,7 @@ fn fetchAndUnpack(
583615 .root_src_path = owned_src_path,
584616 };
585617
586 gop.value_ptr.* = ptr;
618 gop.value_ptr.* = .{ .zig_pkg = ptr };
587619 return .{
588620 .mod = ptr,
589621 .found_existing = false,
......@@ -722,8 +754,22 @@ fn fetchAndUnpack(
722754 return error.PackageFetchFailed;
723755 }
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
725771 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 });
727773 return .{
728774 .mod = mod,
729775 .found_existing = false,