Skip to content

Commit c95c100

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 0461a64 commit c95c100

File tree

3 files changed

+106
-42
lines changed

3 files changed

+106
-42
lines changed

lib/std/Build.zig

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,15 @@ pub const Dependency = struct {
15561556
panic("unable to find module '{s}'", .{name});
15571557
};
15581558
}
1559+
1560+
pub fn path(d: *Dependency, sub_path: []const u8) LazyPath {
1561+
return .{
1562+
.dependency = .{
1563+
.dependency = d,
1564+
.sub_path = sub_path,
1565+
},
1566+
};
1567+
}
15591568
};
15601569

15611570
pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
@@ -1573,6 +1582,18 @@ pub fn dependency(b: *Build, name: []const u8, args: anytype) *Dependency {
15731582
}
15741583
}
15751584

1585+
// If the name wasn't found among the imports this dependency might not have a build.zig file,
1586+
// we therefore look through the build roots aswell.
1587+
inline for (@typeInfo(deps.build_root).Struct.decls) |decl| {
1588+
if (mem.startsWith(u8, decl.name, b.dep_prefix) and
1589+
mem.endsWith(u8, decl.name, name) and
1590+
decl.name.len == b.dep_prefix.len + name.len)
1591+
{
1592+
const build_root = @field(deps.build_root, decl.name);
1593+
return dependencyInner(b, name, build_root, null, args);
1594+
}
1595+
}
1596+
15761597
const full_path = b.pathFromRoot("build.zig.zon");
15771598
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 });
15781599
process.exit(1);
@@ -1601,7 +1622,7 @@ pub fn dependencyInner(
16011622
b: *Build,
16021623
name: []const u8,
16031624
build_root_string: []const u8,
1604-
comptime build_zig: type,
1625+
comptime maybe_build_zig: ?type,
16051626
args: anytype,
16061627
) *Dependency {
16071628
if (b.initialized_deps.get(build_root_string)) |dep| {
@@ -1619,10 +1640,12 @@ pub fn dependencyInner(
16191640
},
16201641
};
16211642
const sub_builder = b.createChild(name, build_root, args) catch @panic("unhandled error");
1622-
sub_builder.runBuild(build_zig) catch @panic("unhandled error");
1643+
if (maybe_build_zig) |build_zig| {
1644+
sub_builder.runBuild(build_zig) catch @panic("unhandled error");
16231645

1624-
if (sub_builder.validateUserInputDidItFail()) {
1625-
std.debug.dumpCurrentStackTrace(@returnAddress());
1646+
if (sub_builder.validateUserInputDidItFail()) {
1647+
std.debug.dumpCurrentStackTrace(@returnAddress());
1648+
}
16261649
}
16271650

16281651
const dep = b.allocator.create(Dependency) catch @panic("OOM");
@@ -1687,6 +1710,11 @@ pub const LazyPath = union(enum) {
16871710
/// Use of this tag indicates a dependency on the host system.
16881711
cwd_relative: []const u8,
16891712

1713+
dependency: struct {
1714+
dependency: *Dependency,
1715+
sub_path: []const u8,
1716+
},
1717+
16901718
/// Returns a new file source that will have a relative path to the build root guaranteed.
16911719
/// Asserts the parameter is not an absolute path.
16921720
pub fn relative(path: []const u8) LazyPath {
@@ -1700,13 +1728,14 @@ pub const LazyPath = union(enum) {
17001728
return switch (self) {
17011729
.path, .cwd_relative => self.path,
17021730
.generated => "generated",
1731+
.dependency => "dependency",
17031732
};
17041733
}
17051734

17061735
/// Adds dependencies this file source implies to the given step.
17071736
pub fn addStepDependencies(self: LazyPath, other_step: *Step) void {
17081737
switch (self) {
1709-
.path, .cwd_relative => {},
1738+
.path, .cwd_relative, .dependency => {},
17101739
.generated => |gen| other_step.dependOn(gen.step),
17111740
}
17121741
}
@@ -1732,6 +1761,12 @@ pub const LazyPath = union(enum) {
17321761
dumpBadGetPathHelp(gen.step, stderr, src_builder, asking_step) catch {};
17331762
@panic("misconfigured build script");
17341763
},
1764+
.dependency => |dep| {
1765+
return dep.dependency.builder.pathJoin(&[_][]const u8{
1766+
dep.dependency.builder.build_root.path.?,
1767+
dep.sub_path,
1768+
});
1769+
},
17351770
}
17361771
}
17371772

@@ -1741,6 +1776,7 @@ pub const LazyPath = union(enum) {
17411776
.path => |p| .{ .path = b.dupePath(p) },
17421777
.cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) },
17431778
.generated => |gen| .{ .generated = gen },
1779+
.dependency => |dep| .{ .dependency = dep },
17441780
};
17451781
}
17461782
};

lib/std/Build/Step/Compile.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1841,7 +1841,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
18411841
continue;
18421842
}
18431843
},
1844-
.generated => {},
1844+
.generated, .dependency => {},
18451845
};
18461846

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

src/Package.zig

Lines changed: 64 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,20 @@ fn fetchAndUnpack(
673689
std.zig.fmtId(fqn), std.zig.fmtEscapes(build_root),
674690
});
675691

692+
{
693+
var build_root_dir = try std.fs.openDirAbsolute(build_root, .{});
694+
defer build_root_dir.close();
695+
build_root_dir.access(build_zig_basename, .{}) catch {
696+
try all_modules.put(gpa, actual_hex, .non_zig_pkg);
697+
return .{
698+
.mod = null,
699+
.found_existing = false,
700+
};
701+
};
702+
}
703+
676704
const mod = try createWithDir(gpa, global_cache_directory, pkg_dir_sub_path, build_zig_basename);
677-
try all_modules.put(gpa, actual_hex, mod);
705+
try all_modules.put(gpa, actual_hex, .{ .zig_pkg = mod });
678706
return .{
679707
.mod = mod,
680708
.found_existing = false,

0 commit comments

Comments
 (0)