Skip to content

Commit 32d42a3

Browse files
committed
use builtin.zig instead of adding a new buildpkgs.zig
1 parent c3dc5ed commit 32d42a3

File tree

8 files changed

+166
-151
lines changed

8 files changed

+166
-151
lines changed

src/Compilation.zig

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,10 @@ emit_llvm_ir: ?EmitLoc,
137137
emit_analysis: ?EmitLoc,
138138
emit_docs: ?EmitLoc,
139139

140+
/// This is used to generate the pkg_names and add the `hasPkg`
141+
/// function in builtin.zig. This is meant to be used by `build.zig` only.
142+
build_pkg_table: ?*Package.Table,
143+
140144
work_queue_wait_group: WaitGroup,
141145

142146
pub const InnerError = Module.InnerError;
@@ -503,6 +507,7 @@ pub const InitOptions = struct {
503507
test_filter: ?[]const u8 = null,
504508
test_name_prefix: ?[]const u8 = null,
505509
subsystem: ?std.Target.SubSystem = null,
510+
build_pkg_table: ?*Package.Table = null,
506511
};
507512

508513
fn addPackageTableToCacheHash(
@@ -1120,6 +1125,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
11201125
.test_evented_io = options.test_evented_io,
11211126
.debug_compiler_runtime_libs = options.debug_compiler_runtime_libs,
11221127
.work_queue_wait_group = undefined,
1128+
.build_pkg_table = options.build_pkg_table,
11231129
};
11241130
break :comp comp;
11251131
};
@@ -2987,6 +2993,51 @@ pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8
29872993
}
29882994
}
29892995

2996+
if (comp.build_pkg_table) |pkg_table| {
2997+
try buffer.writer().writeAll(
2998+
\\
2999+
\\pub const pkg_names = &[_][]const u8 {
3000+
\\
3001+
);
3002+
{
3003+
var pkg_it = pkg_table.iterator();
3004+
while (pkg_it.next()) |pkg| {
3005+
try buffer.writer().print(" \"{s}\",\n", .{pkg.key});
3006+
}
3007+
}
3008+
try buffer.writer().writeAll(
3009+
\\};
3010+
\\
3011+
\\// using .Inline to force this to be comptime
3012+
\\pub fn hasPkg(comptime name: []const u8) callconv(.Inline) bool {
3013+
\\ if (!isComptime()) {
3014+
\\ @compileError("builtin.hasPkg MUST be called with comptime");
3015+
\\ }
3016+
\\ inline for (pkg_names) |has_name| {
3017+
\\ if (@import("std").mem.eql(u8, name, has_name)) return true;
3018+
\\ }
3019+
\\ return false;
3020+
\\}
3021+
\\
3022+
\\// A temporary workaround until https://github.com/ziglang/zig/issues/425
3023+
\\// is implemented and the callconv(.Inline) on the `hasPkg` function forces
3024+
\\// it to be comptime
3025+
\\fn isComptime() bool {
3026+
\\ var t: bool = true;
3027+
\\ const x = if (t) @as(u7, 0) else @as(u8, 0);
3028+
\\ return @TypeOf(x) == u7;
3029+
\\}
3030+
\\
3031+
);
3032+
} else {
3033+
try buffer.writer().writeAll(
3034+
\\
3035+
\\pub const pkg_names = @compileError("builtin.pkg_names is only available in build.zig");
3036+
\\pub const hasPkg = @compileError("builtin.hasPkg is only available in build.zig");
3037+
\\
3038+
);
3039+
}
3040+
29903041
return buffer.toOwnedSlice();
29913042
}
29923043

src/main.zig

Lines changed: 1 addition & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -2565,14 +2565,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
25652565

25662566
gimmeMoreOfThoseSweetSweetFileDescriptors();
25672567

2568-
var buildpkgs_dir = try generateBuildPkgs(arena, local_cache_directory, build_pkg.table);
2569-
defer buildpkgs_dir.handle.close();
2570-
var buildpkgs_pkg: Package = .{
2571-
.root_src_directory = buildpkgs_dir,
2572-
.root_src_path = "buildpkgs.zig",
2573-
};
2574-
try build_pkg.table.put(arena, "buildpkgs", &buildpkgs_pkg);
2575-
25762568
const cross_target: std.zig.CrossTarget = .{};
25772569
const target_info = try detectNativeTargetInfo(gpa, cross_target);
25782570

@@ -2604,6 +2596,7 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
26042596
.optimize_mode = .Debug,
26052597
.self_exe_path = self_exe_path,
26062598
.thread_pool = &thread_pool,
2599+
.build_pkg_table = &build_pkg.table,
26072600
}) catch |err| {
26082601
fatal("unable to create compilation: {s}", .{@errorName(err)});
26092602
};
@@ -2640,76 +2633,6 @@ pub fn cmdBuild(gpa: *Allocator, arena: *Allocator, args: []const []const u8) !v
26402633
}
26412634
}
26422635

2643-
fn generateBuildPkgs(arena: *Allocator, local_cache_directory: Compilation.Directory, pkg_table: Package.Table) !Compilation.Directory {
2644-
const src = blk: {
2645-
var src_array = std.ArrayList(u8).init(arena);
2646-
defer src_array.deinit();
2647-
const writer = src_array.writer();
2648-
try writer.writeAll(
2649-
\\pub const names = &[_][]const u8 {
2650-
\\
2651-
);
2652-
var pkg_it = pkg_table.iterator();
2653-
while (pkg_it.next()) |pkg| {
2654-
try writer.print(" \"{s}\",\n", .{pkg.key});
2655-
}
2656-
try writer.writeAll(
2657-
\\};
2658-
\\
2659-
\\// using .Inline to force this to be comptime
2660-
\\pub fn has(comptime name: []const u8) callconv(.Inline) bool {
2661-
\\ if (!isComptime()) {
2662-
\\ @compileError("buildpkgs.has must be called with comptime");
2663-
\\ }
2664-
\\ inline for (names) |has_name| {
2665-
\\ if (@import("std").mem.eql(u8, name, has_name)) return true;
2666-
\\ }
2667-
\\ return false;
2668-
\\}
2669-
\\
2670-
\\// A temporary workaround until https://github.com/ziglang/zig/issues/425
2671-
\\// is implemented and the callconv(.Inline) on the `has` function forces
2672-
\\// it to be comptime
2673-
\\fn isComptime() bool {
2674-
\\ var t: bool = true;
2675-
\\ const x = if (t) @as(u7, 0) else @as(u8, 0);
2676-
\\ return @TypeOf(x) == u7;
2677-
\\}
2678-
\\
2679-
);
2680-
break :blk src_array.toOwnedSlice();
2681-
};
2682-
defer arena.free(src);
2683-
2684-
var zig_cache_tmp_dir = try local_cache_directory.handle.makeOpenPath("tmp", .{});
2685-
defer zig_cache_tmp_dir.close();
2686-
var zig_cache_tmp_buildpkgs_dir = try zig_cache_tmp_dir.makeOpenPath("buildpkgs", .{});
2687-
defer zig_cache_tmp_buildpkgs_dir.close();
2688-
2689-
const hex_digest = blk: {
2690-
var hash = Cache.HashHelper { };
2691-
hash.addBytes(src);
2692-
break :blk hash.final();
2693-
};
2694-
const pkg_dir_name: []const u8 = &hex_digest;
2695-
2696-
var buildpkgs_dir = try zig_cache_tmp_buildpkgs_dir.makeOpenPath(pkg_dir_name, .{});
2697-
errdefer buildpkgs_dir.close();
2698-
2699-
if (buildpkgs_dir.access("buildpkgs.zig", .{ .read = true })) { } else |_| {
2700-
{
2701-
const buildpkgs = try buildpkgs_dir.createFile("buildpkgs.zig.tmp", .{});
2702-
defer buildpkgs.close();
2703-
try buildpkgs.writer().writeAll(src);
2704-
}
2705-
try buildpkgs_dir.rename("buildpkgs.zig.tmp", "buildpkgs.zig");
2706-
}
2707-
return Compilation.Directory {
2708-
.path = try local_cache_directory.join(arena, &[_][]const u8 { "tmp", "buildpkgs", pkg_dir_name }),
2709-
.handle = buildpkgs_dir,
2710-
};
2711-
}
2712-
27132636
fn argvCmd(allocator: *Allocator, argv: []const []const u8) ![]u8 {
27142637
var cmd = std.ArrayList(u8).init(allocator);
27152638
defer cmd.deinit();
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
const std = @import("std");
2+
const Builder = std.build.Builder;
3+
4+
pub fn build(b: *Builder) !void {
5+
if (comptime @import("std").builtin.hasPkg("androidbuild")) {
6+
std.debug.print("we have the 'androidbuild' package\n", .{});
7+
const androidbuild = @import("androidbuild");
8+
androidbuild.makeApk(b);
9+
} else {
10+
std.debug.print("missing package 'androidbuild'\n", .{});
11+
}
12+
}
Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,64 @@
11
const Builder = @import("std").build.Builder;
2-
const buildpkgs = @import("buildpkgs");
32

43
pub fn build(b: *Builder) void {
5-
if (comptime buildpkgs.has("androidbuild")) {
6-
const androidbuild = @import("androidbuild");
7-
androidbuild.makeApk(b);
8-
} else {
9-
const resolveandroid = b.addExecutable("resolveandroid", "resolveandroid.zig");
10-
resolveandroid.setBuildMode(b.standardReleaseOptions());
11-
const run_resolveandroid = resolveandroid.run();
12-
run_resolveandroid.addArg("expect-pass");
13-
run_resolveandroid.addArg(b.zig_exe);
4+
const test_step = b.step("test", "Resolve android and test the zig build files");
145

15-
const test_build_error = b.addExecutable("test-build-error", "resolveandroid.zig");
16-
test_build_error.setBuildMode(b.standardReleaseOptions());
17-
const run_test_build_error = test_build_error.run();
18-
run_test_build_error.addArg("expect-fail");
19-
run_test_build_error.addArg(b.zig_exe);
20-
run_test_build_error.addArg("--build-file");
21-
run_test_build_error.addArg("invalid-build.zig");
6+
{
7+
const exe = b.addExecutable("without-android", "run.zig");
8+
exe.setBuildMode(b.standardReleaseOptions());
9+
const run = exe.run();
10+
run.addArg("pass");
11+
run.addArg("missing package 'androidbuild'");
12+
run.addArg(b.zig_exe);
13+
run.addArg("build");
14+
run.addArg("--build-file");
15+
run.addArg("androidexample-build.zig");
16+
test_step.dependOn(&run.step);
17+
}
18+
19+
{
20+
const exe = b.addExecutable("with-android", "run.zig");
21+
exe.setBuildMode(b.standardReleaseOptions());
22+
const run = exe.run();
23+
run.addArg("pass");
24+
run.addArg("we have the 'androidbuild' package");
25+
run.addArg(b.zig_exe);
26+
run.addArg("build");
27+
run.addArg("--build-file");
28+
run.addArg("androidexample-build.zig");
29+
run.addArg("--pkg-begin");
30+
run.addArg("androidbuild");
31+
run.addArg("androidbuild.zig");
32+
run.addArg("--pkg-end");
33+
test_step.dependOn(&run.step);
34+
}
35+
36+
{
37+
const exe = b.addExecutable("invalid-build", "run.zig");
38+
exe.setBuildMode(b.standardReleaseOptions());
39+
const run = exe.run();
40+
run.addArg("fail");
41+
run.addArg("builtin.hasPkg MUST be called with comptime");
42+
run.addArg(b.zig_exe);
43+
run.addArg("build");
44+
run.addArg("--build-file");
45+
run.addArg("invalid-build.zig");
46+
run.addArg("--pkg-begin");
47+
run.addArg("androidbuild");
48+
run.addArg("androidbuild.zig");
49+
run.addArg("--pkg-end");
50+
test_step.dependOn(&run.step);
51+
}
2252

23-
const test_step = b.step("test", "Resolve android and test the zig build files");
24-
test_step.dependOn(&run_resolveandroid.step);
25-
test_step.dependOn(&run_test_build_error.step);
53+
{
54+
const exe = b.addExecutable("calling-haspkg-outside-build", "run.zig");
55+
exe.setBuildMode(b.standardReleaseOptions());
56+
const run = exe.run();
57+
run.addArg("fail");
58+
run.addArg("builtin.hasPkg is only available in build.zig");
59+
run.addArg(b.zig_exe);
60+
run.addArg("build-exe");
61+
run.addArg("calling-haspkg-outside-build.zig");
62+
test_step.dependOn(&run.step);
2663
}
2764
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub fn main() void {
2+
if (@import("std").builtin.hasPkg("foo")) {
3+
@compileError("calling hasPkg outside of build.zig should be a compile error");
4+
}
5+
}

test/standalone/build_zig_pkgs/invalid-build.zig

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
1-
//! Currently the user MUST specify comptime when calling buidpkgs.has
1+
//! Currently the user MUST specify comptime when calling builtin.hasPkg
22
//! until https://github.com/ziglang/zig/issues/425 is implemented.
3-
//! This build.zig file tries to call buildpkgs.has without comptime and the
3+
//! This build.zig file tries to call builtin.hasPkg without comptime and the
44
//! test is to make sure it produces a compile error.
55
//!
6-
//! Note that the reason why "has" must be evaluated at comptime is
6+
//! Note that the reason why "hasPkg" must be evaluated at comptime is
77
//! because it will always surround an @import statement. The problem is
88
//! that if they forget to add "comptime" to their call, then their build.zig
99
//! file will "sometimes work" so long as they are building with the necessary
1010
//! packages configured, but then it will fail once the @import is missing
11-
//! which defeats the whole purpose of providing "has" in the first place.
11+
//! which defeats the whole purpose of providing "hasPkg" in the first place.
1212
//!
1313
const Builder = @import("std").build.Builder;
14-
const buildpkgs = @import("buildpkgs");
1514

1615
pub fn build(b: *Builder) void {
1716
// This should be a compile error because it's not marked as comptime
18-
if (buildpkgs.has("androidbuild")) {
17+
if (@import("std").builtin.hasPkg("androidbuild")) {
1918
const androidbuild = @import("androidbuild");
2019
androidbuild.makeApk(b);
2120
}

test/standalone/build_zig_pkgs/resolveandroid.zig

Lines changed: 0 additions & 47 deletions
This file was deleted.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const std = @import("std");
2+
3+
pub fn main() !void {
4+
const args = try std.process.argsAlloc(std.heap.page_allocator);
5+
6+
const expect_fail = blk: {
7+
if (std.mem.eql(u8, args[1], "fail")) break :blk true;
8+
if (std.mem.eql(u8, args[1], "pass")) break :blk false;
9+
std.debug.panic("unexpected first arg '{s}'", .{args[1]});
10+
};
11+
const expected_output = args[2];
12+
const child = try std.ChildProcess.init(args[3..], std.heap.page_allocator);
13+
defer child.deinit();
14+
child.stderr_behavior = .Pipe;
15+
try child.spawn();
16+
const stderr = try child.stderr.?.reader().readAllAlloc(std.heap.page_allocator, std.math.maxInt(usize));
17+
errdefer {
18+
// if we fail, dump the stderr we captured
19+
std.io.getStdErr().writeAll(stderr) catch @panic("failed to dump stderr in errdefer");
20+
}
21+
const passed = switch (try child.wait()) {
22+
.Exited => |e| e == 0,
23+
else => false,
24+
};
25+
26+
if (passed) {
27+
if (expect_fail) return error.ZigBuildUnexpectedlyPassed;
28+
} else {
29+
if (!expect_fail) return error.ZigBuildFailed;
30+
}
31+
_ = std.mem.indexOf(u8, stderr, expected_output) orelse {
32+
std.debug.print("Error: did not get expected output '{s}':\n", .{expected_output});
33+
return error.UnexpectedOutput;
34+
};
35+
}

0 commit comments

Comments
 (0)