Skip to content

Commit a49fd17

Browse files
committed
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.
1 parent 1a0e6bc commit a49fd17

File tree

3 files changed

+108
-42
lines changed

3 files changed

+108
-42
lines changed

lib/std/Build.zig

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,15 @@ pub const Dependency = struct {
16991699
panic("unable to find module '{s}'", .{name});
17001700
};
17011701
}
1702+
1703+
pub fn path(d: *Dependency, sub_path: []const u8) LazyPath {
1704+
return .{
1705+
.dependency = .{
1706+
.dependency = d,
1707+
.sub_path = sub_path,
1708+
},
1709+
};
1710+
}
17021711
};
17031712

17041713
pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
@@ -1716,6 +1725,18 @@ pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
17161725
}
17171726
}
17181727

1728+
// If the name wasn't found among the imports this dependency might not have a build.zig file,
1729+
// we therefore look through the build roots aswell.
1730+
inline for (@typeInfo(deps.build_root).Struct.decls) |decl| {
1731+
if (mem.startsWith(u8, decl.name, b.dep_prefix) and
1732+
mem.endsWith(u8, decl.name, name) and
1733+
decl.name.len == b.dep_prefix.len + name.len)
1734+
{
1735+
const build_root = @field(deps.build_root, decl.name);
1736+
return dependencyInner(b, name, build_root, null, args);
1737+
}
1738+
}
1739+
17191740
const full_path = b.pathFromRoot("build.zig.zon");
17201741
std.debug.print("no dependency named '{s}' in '{s}'. All packages used in build.zig must be declared in this file.\n", .{ name, full_path });
17211742
process.exit(1);
@@ -1791,7 +1812,7 @@ pub fn dependencyInner(
17911812
b: *Build,
17921813
name: []const u8,
17931814
build_root_string: []const u8,
1794-
comptime build_zig: type,
1815+
comptime maybe_build_zig: ?type,
17951816
args: anytype,
17961817
) *Dependency {
17971818
const user_input_options = userInputOptionsFromArgs(b.allocator, args);
@@ -1811,10 +1832,12 @@ pub fn dependencyInner(
18111832
},
18121833
};
18131834
const sub_builder = b.createChild(name, build_root, user_input_options) catch @panic("unhandled error");
1814-
sub_builder.runBuild(build_zig) catch @panic("unhandled error");
1835+
if (maybe_build_zig) |build_zig| {
1836+
sub_builder.runBuild(build_zig) catch @panic("unhandled error");
18151837

1816-
if (sub_builder.validateUserInputDidItFail()) {
1817-
std.debug.dumpCurrentStackTrace(@returnAddress());
1838+
if (sub_builder.validateUserInputDidItFail()) {
1839+
std.debug.dumpCurrentStackTrace(@returnAddress());
1840+
}
18181841
}
18191842

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

1907+
dependency: struct {
1908+
dependency: *Dependency,
1909+
sub_path: []const u8,
1910+
},
1911+
18841912
/// Returns a new file source that will have a relative path to the build root guaranteed.
18851913
/// Asserts the parameter is not an absolute path.
18861914
pub fn relative(path: []const u8) LazyPath {
@@ -1894,13 +1922,14 @@ pub const LazyPath = union(enum) {
18941922
return switch (self) {
18951923
.path, .cwd_relative => self.path,
18961924
.generated => "generated",
1925+
.dependency => "dependency",
18971926
};
18981927
}
18991928

19001929
/// Adds dependencies this file source implies to the given step.
19011930
pub fn addStepDependencies(self: LazyPath, other_step: *Step) void {
19021931
switch (self) {
1903-
.path, .cwd_relative => {},
1932+
.path, .cwd_relative, .dependency => {},
19041933
.generated => |gen| other_step.dependOn(gen.step),
19051934
}
19061935
}
@@ -1926,6 +1955,12 @@ pub const LazyPath = union(enum) {
19261955
dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {};
19271956
@panic("misconfigured build script");
19281957
},
1958+
.dependency => |dep| {
1959+
return dep.dependency.builder.pathJoin(&[_][]const u8{
1960+
dep.dependency.builder.build_root.path.?,
1961+
dep.sub_path,
1962+
});
1963+
},
19291964
}
19301965
}
19311966

@@ -1935,6 +1970,7 @@ pub const LazyPath = union(enum) {
19351970
.path => |p| .{ .path = b.dupePath(p) },
19361971
.cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) },
19371972
.generated => |gen| .{ .generated = gen },
1973+
.dependency => |dep| .{ .dependency = dep },
19381974
};
19391975
}
19401976
};

lib/std/Build/Step/Compile.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1836,7 +1836,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
18361836
continue;
18371837
}
18381838
},
1839-
.generated => {},
1839+
.generated, .dependency => {},
18401840
};
18411841

18421842
zig_args.appendAssumeCapacity(rpath.getPath2(b, step));

src/Package.zig

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -303,36 +303,38 @@ pub fn fetchAndAddDependencies(
303303
root_prog_node,
304304
);
305305

306-
if (!sub.found_existing) {
307-
try sub.mod.fetchAndAddDependencies(
308-
deps_pkg,
309-
arena,
310-
thread_pool,
311-
http_client,
312-
sub.mod.root_src_directory,
313-
global_cache_directory,
314-
local_cache_directory,
315-
dependencies_source,
316-
build_roots_source,
317-
sub_prefix,
318-
error_bundle,
319-
all_modules,
320-
root_prog_node,
321-
);
322-
}
306+
if (sub.mod) |mod| {
307+
if (!sub.found_existing) {
308+
try mod.fetchAndAddDependencies(
309+
deps_pkg,
310+
arena,
311+
thread_pool,
312+
http_client,
313+
mod.root_src_directory,
314+
global_cache_directory,
315+
local_cache_directory,
316+
dependencies_source,
317+
build_roots_source,
318+
sub_prefix,
319+
error_bundle,
320+
all_modules,
321+
root_prog_node,
322+
);
323+
}
323324

324-
try pkg.add(gpa, name, sub.mod);
325-
if (deps_pkg.table.get(dep.hash.?)) |other_sub| {
326-
// This should be the same package (and hence module) since it's the same hash
327-
// TODO: dedup multiple versions of the same package
328-
assert(other_sub == sub.mod);
329-
} else {
330-
try deps_pkg.add(gpa, dep.hash.?, sub.mod);
331-
}
325+
try pkg.add(gpa, name, mod);
326+
if (deps_pkg.table.get(dep.hash.?)) |other_sub| {
327+
// This should be the same package (and hence module) since it's the same hash
328+
// TODO: dedup multiple versions of the same package
329+
assert(other_sub == mod);
330+
} else {
331+
try deps_pkg.add(gpa, dep.hash.?, mod);
332+
}
332333

333-
try dependencies_source.writer().print(" pub const {s} = @import(\"{}\");\n", .{
334-
std.zig.fmtId(fqn), std.zig.fmtEscapes(dep.hash.?),
335-
});
334+
try dependencies_source.writer().print(" pub const {s} = @import(\"{}\");\n", .{
335+
std.zig.fmtId(fqn), std.zig.fmtEscapes(dep.hash.?),
336+
});
337+
}
336338
}
337339
}
338340

@@ -420,7 +422,10 @@ const MultiHashHexDigest = [hex_multihash_len]u8;
420422
/// This is to avoid creating multiple modules for the same build.zig file.
421423
/// If the value is `null`, the package is a known dependency, but has not yet
422424
/// been fetched.
423-
pub const AllModules = std.AutoHashMapUnmanaged(MultiHashHexDigest, ?*Package);
425+
pub const AllModules = std.AutoHashMapUnmanaged(MultiHashHexDigest, ?union(enum) {
426+
zig_pkg: *Package,
427+
non_zig_pkg: void,
428+
});
424429

425430
fn ProgressReader(comptime ReaderType: type) type {
426431
return struct {
@@ -474,7 +479,7 @@ fn fetchAndUnpack(
474479
fqn: []const u8,
475480
all_modules: *AllModules,
476481
root_prog_node: *std.Progress.Node,
477-
) !struct { mod: *Package, found_existing: bool } {
482+
) !struct { mod: ?*Package, found_existing: bool } {
478483
const gpa = http_client.allocator;
479484
const s = fs.path.sep_str;
480485

@@ -503,15 +508,26 @@ fn fetchAndUnpack(
503508
if (gop.found_existing) {
504509
if (gop.value_ptr.*) |mod| {
505510
gpa.free(build_root);
506-
return .{
507-
.mod = mod,
508-
.found_existing = true,
509-
};
511+
switch (mod) {
512+
.zig_pkg => |pkg| return .{
513+
.mod = pkg,
514+
.found_existing = true,
515+
},
516+
.non_zig_pkg => return .{
517+
.mod = null,
518+
.found_existing = true,
519+
},
520+
}
510521
}
511522
}
512523

513524
root_prog_node.completeOne();
514525

526+
pkg_dir.access(build_zig_basename, .{}) catch return .{
527+
.mod = null,
528+
.found_existing = false,
529+
};
530+
515531
const ptr = try gpa.create(Package);
516532
errdefer gpa.destroy(ptr);
517533

@@ -527,7 +543,7 @@ fn fetchAndUnpack(
527543
.root_src_path = owned_src_path,
528544
};
529545

530-
gop.value_ptr.* = ptr;
546+
gop.value_ptr.* = .{ .zig_pkg = ptr };
531547
return .{
532548
.mod = ptr,
533549
.found_existing = false,
@@ -673,8 +689,22 @@ fn fetchAndUnpack(
673689
std.zig.fmtId(fqn), std.zig.fmtEscapes(build_root),
674690
});
675691

692+
const build_zig_path = try std.fs.path.join(gpa, &.{ pkg_dir_sub_path, build_zig_basename });
693+
defer gpa.free(build_zig_path);
694+
695+
global_cache_directory.handle.access(build_zig_path, .{}) catch |err| switch (err) {
696+
error.FileNotFound => {
697+
try all_modules.put(gpa, actual_hex, .non_zig_pkg);
698+
return .{
699+
.mod = null,
700+
.found_existing = false,
701+
};
702+
},
703+
else => return err,
704+
};
705+
676706
const mod = try createWithDir(gpa, global_cache_directory, pkg_dir_sub_path, build_zig_basename);
677-
try all_modules.put(gpa, actual_hex, mod);
707+
try all_modules.put(gpa, actual_hex, .{ .zig_pkg = mod });
678708
return .{
679709
.mod = mod,
680710
.found_existing = false,

0 commit comments

Comments
 (0)