Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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