Skip to content

Commit

Permalink
Support non zig dependencies
Browse files Browse the repository at this point in the history
Dependencies no longer require a build.zig file.

Adds path function to Dependency struct which
returns a LazyPath into a dependency.
  • Loading branch information
antlilja authored and mlugg committed Sep 24, 2023
1 parent c9413a8 commit 8eff0a0
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 37 deletions.
37 changes: 31 additions & 6 deletions lib/std/Build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,15 @@ pub const Dependency = struct {
panic("unable to find module '{s}'", .{name});
};
}

pub fn path(d: *Dependency, sub_path: []const u8) LazyPath {
return .{
.dependency = .{
.dependency = d,
.sub_path = sub_path,
},
};
}
};

pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
Expand All @@ -1724,7 +1733,7 @@ pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
inline for (@typeInfo(deps.packages).Struct.decls) |decl| {
if (mem.eql(u8, decl.name, pkg_hash)) {
const pkg = @field(deps.packages, decl.name);
return dependencyInner(b, name, pkg.build_root, pkg.build_zig, pkg.deps, args);
return dependencyInner(b, name, pkg.build_root, if (@hasDecl(pkg, "build_zig")) pkg.build_zig else null, pkg.deps, args);
}
}

Expand Down Expand Up @@ -1801,7 +1810,7 @@ pub fn dependencyInner(
b: *Build,
name: []const u8,
build_root_string: []const u8,
comptime build_zig: type,
comptime build_zig: ?type,
pkg_deps: AvailableDeps,
args: anytype,
) *Dependency {
Expand All @@ -1821,11 +1830,14 @@ pub fn dependencyInner(
process.exit(1);
},
};

const sub_builder = b.createChild(name, build_root, pkg_deps, user_input_options) catch @panic("unhandled error");
sub_builder.runBuild(build_zig) catch @panic("unhandled error");
if (build_zig) |bz| {
sub_builder.runBuild(bz) catch @panic("unhandled error");

if (sub_builder.validateUserInputDidItFail()) {
std.debug.dumpCurrentStackTrace(@returnAddress());
if (sub_builder.validateUserInputDidItFail()) {
std.debug.dumpCurrentStackTrace(@returnAddress());
}
}

const dep = b.allocator.create(Dependency) catch @panic("OOM");
Expand Down Expand Up @@ -1892,6 +1904,11 @@ pub const LazyPath = union(enum) {
/// Use of this tag indicates a dependency on the host system.
cwd_relative: []const u8,

dependency: struct {
dependency: *Dependency,
sub_path: []const u8,
},

/// Returns a new file source that will have a relative path to the build root guaranteed.
/// Asserts the parameter is not an absolute path.
pub fn relative(path: []const u8) LazyPath {
Expand All @@ -1905,13 +1922,14 @@ pub const LazyPath = union(enum) {
return switch (self) {
.path, .cwd_relative => self.path,
.generated => "generated",
.dependency => "dependency",
};
}

/// Adds dependencies this file source implies to the given step.
pub fn addStepDependencies(self: LazyPath, other_step: *Step) void {
switch (self) {
.path, .cwd_relative => {},
.path, .cwd_relative, .dependency => {},
.generated => |gen| other_step.dependOn(gen.step),
}
}
Expand All @@ -1937,6 +1955,12 @@ pub const LazyPath = union(enum) {
dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {};
@panic("misconfigured build script");
},
.dependency => |dep| {
return dep.dependency.builder.pathJoin(&[_][]const u8{
dep.dependency.builder.build_root.path.?,
dep.sub_path,
});
},
}
}

Expand All @@ -1946,6 +1970,7 @@ pub const LazyPath = union(enum) {
.path => |p| .{ .path = b.dupePath(p) },
.cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) },
.generated => |gen| .{ .generated = gen },
.dependency => |dep| .{ .dependency = dep },
};
}
};
Expand Down
2 changes: 1 addition & 1 deletion lib/std/Build/Step/Compile.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1896,7 +1896,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
continue;
}
},
.generated => {},
.generated, .dependency => {},
};

zig_args.appendAssumeCapacity(rpath.getPath2(b, step));
Expand Down
106 changes: 76 additions & 30 deletions src/Package.zig
Original file line number Diff line number Diff line change
Expand Up @@ -327,30 +327,45 @@ pub fn fetchAndAddDependencies(
name,
);

if (!sub.found_existing) {
try sub.mod.fetchAndAddDependencies(
deps_pkg,
arena,
thread_pool,
http_client,
sub.mod.root_src_directory,
global_cache_directory,
local_cache_directory,
dependencies_source,
error_bundle,
all_modules,
root_prog_node,
dep.hash.?,
);
}
if (sub.mod) |mod| {
if (!sub.found_existing) {
try mod.fetchAndAddDependencies(
deps_pkg,
arena,
thread_pool,
http_client,
mod.root_src_directory,
global_cache_directory,
local_cache_directory,
dependencies_source,
error_bundle,
all_modules,
root_prog_node,
dep.hash.?,
);
}

try pkg.add(gpa, name, sub.mod);
if (deps_pkg.table.get(dep.hash.?)) |other_sub| {
// This should be the same package (and hence module) since it's the same hash
// TODO: dedup multiple versions of the same package
assert(other_sub == sub.mod);
} else {
try deps_pkg.add(gpa, dep.hash.?, sub.mod);
try pkg.add(gpa, name, mod);
if (deps_pkg.table.get(dep.hash.?)) |other_sub| {
// This should be the same package (and hence module) since it's the same hash
// TODO: dedup multiple versions of the same package
assert(other_sub == mod);
} else {
try deps_pkg.add(gpa, dep.hash.?, mod);
}
} else if (!sub.found_existing) {
const pkg_dir_sub_path = "p" ++ fs.path.sep_str ++ (dep.hash.?)[0..hex_multihash_len];
const build_root = try global_cache_directory.join(arena, &.{pkg_dir_sub_path});
try dependencies_source.writer().print(
\\ pub const {} = struct {{
\\ pub const build_root = "{}";
\\ pub const deps: []const struct {{ []const u8, []const u8 }} = &.{{}};
\\ }};
\\
, .{
std.zig.fmtId(dep.hash.?),
std.zig.fmtEscapes(build_root),
});
}
}

Expand Down Expand Up @@ -480,7 +495,10 @@ const MultiHashHexDigest = [hex_multihash_len]u8;
/// This is to avoid creating multiple modules for the same build.zig file.
/// If the value is `null`, the package is a known dependency, but has not yet
/// been fetched.
pub const AllModules = std.AutoHashMapUnmanaged(MultiHashHexDigest, ?*Package);
pub const AllModules = std.AutoHashMapUnmanaged(MultiHashHexDigest, ?union(enum) {
zig_pkg: *Package,
non_zig_pkg: void,
});

fn ProgressReader(comptime ReaderType: type) type {
return struct {
Expand Down Expand Up @@ -535,7 +553,7 @@ fn fetchAndUnpack(
/// This does not have to be any form of canonical or fully-qualified name: it
/// is only intended to be human-readable for progress reporting.
name_for_prog: []const u8,
) !struct { mod: *Package, found_existing: bool } {
) !struct { mod: ?*Package, found_existing: bool } {
const gpa = http_client.allocator;
const s = fs.path.sep_str;

Expand All @@ -556,13 +574,27 @@ fn fetchAndUnpack(
const gop = try all_modules.getOrPut(gpa, hex_digest.*);
if (gop.found_existing) {
if (gop.value_ptr.*) |mod| {
return .{
.mod = mod,
.found_existing = true,
return switch (mod) {
.zig_pkg => |pkg| .{
.mod = pkg,
.found_existing = true,
},
.non_zig_pkg => .{
.mod = null,
.found_existing = true,
},
};
}
}

pkg_dir.access(build_zig_basename, .{}) catch {
gop.value_ptr.* = .non_zig_pkg;
return .{
.mod = null,
.found_existing = false,
};
};

const build_root = try global_cache_directory.join(gpa, &.{pkg_dir_sub_path});
errdefer gpa.free(build_root);

Expand All @@ -583,7 +615,7 @@ fn fetchAndUnpack(
.root_src_path = owned_src_path,
};

gop.value_ptr.* = ptr;
gop.value_ptr.* = .{ .zig_pkg = ptr };
return .{
.mod = ptr,
.found_existing = false,
Expand Down Expand Up @@ -722,8 +754,22 @@ fn fetchAndUnpack(
return error.PackageFetchFailed;
}

const build_zig_path = try std.fs.path.join(gpa, &.{ pkg_dir_sub_path, build_zig_basename });
defer gpa.free(build_zig_path);

global_cache_directory.handle.access(build_zig_path, .{}) catch |err| switch (err) {
error.FileNotFound => {
try all_modules.put(gpa, actual_hex, .non_zig_pkg);
return .{
.mod = null,
.found_existing = false,
};
},
else => return err,
};

const mod = try createWithDir(gpa, global_cache_directory, pkg_dir_sub_path, build_zig_basename);
try all_modules.put(gpa, actual_hex, mod);
try all_modules.put(gpa, actual_hex, .{ .zig_pkg = mod });
return .{
.mod = mod,
.found_existing = false,
Expand Down

0 comments on commit 8eff0a0

Please sign in to comment.