Skip to content

Commit 65f1b6f

Browse files
committed
v8 caching + os and release tagging
1 parent 39d5a6c commit 65f1b6f

File tree

1 file changed

+151
-44
lines changed

1 file changed

+151
-44
lines changed

build.zig

Lines changed: 151 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ pub fn build(b: *std.Build) !void {
1717

1818
const prebuilt_v8_path = b.option([]const u8, "prebuilt_v8_path", "Path to prebuilt libc_v8.a");
1919

20-
const prepared_v8 = try prepareV8Sources(b);
21-
const bootstrapped_v8 = bootstrapV8(b, prepared_v8);
20+
const cache_root = b.cache_root.path orelse ".zig-cache";
21+
const v8_dir = b.fmt("{s}/v8-{s}", .{ cache_root, V8_VERSION });
22+
23+
const bootstrapped_v8 = try bootstrapV8(b, v8_dir);
2224

2325
const built_v8 = if (prebuilt_v8_path) |path| blk: {
2426
// Use prebuilt_v8 if available.
@@ -27,11 +29,10 @@ pub fn build(b: *std.Build) !void {
2729
break :blk wf;
2830
} else blk: {
2931
// Otherwise, go through build process.
30-
break :blk try buildV8(b, prepared_v8, bootstrapped_v8, target, optimize);
32+
break :blk try buildV8(b, v8_dir, bootstrapped_v8, target, optimize);
3133
};
3234

3335
const prepare_step = b.step("prepare-v8", "Prepare V8 source code");
34-
prepare_step.dependOn(&prepared_v8.step);
3536
prepare_step.dependOn(&bootstrapped_v8.step);
3637

3738
const build_step = b.step("build-v8", "Build v8");
@@ -98,10 +99,96 @@ pub fn build(b: *std.Build) !void {
9899
}
99100
}
100101

101-
fn prepareV8Sources(b: *std.Build) !*std.Build.Step.WriteFile {
102-
const wf = b.addWriteFiles();
102+
fn bootstrapV8(b: *std.Build, v8_dir: []const u8) !*std.Build.Step.Run {
103+
const depot_tools = b.dependency("depot_tools", .{});
104+
const marker_file = b.fmt("{s}/.bootstrap-complete", .{v8_dir});
105+
106+
// Check if already bootstrapped
107+
const needs_full_bootstrap = blk: {
108+
std.fs.cwd().access(marker_file, .{}) catch break :blk true;
109+
break :blk false;
110+
};
111+
112+
if (!needs_full_bootstrap) {
113+
const needs_source_update = blk: {
114+
if (needs_full_bootstrap) break :blk false;
115+
116+
// Check if marker exists
117+
const marker_stat = std.fs.cwd().statFile(marker_file) catch break :blk true;
118+
const marker_mtime = marker_stat.mtime;
119+
120+
const source_dirs = [_][]const u8{ "src", "build-tools" };
121+
122+
for (source_dirs) |dir_path| {
123+
var dir = try std.fs.cwd().openDir(dir_path, .{ .iterate = true });
124+
defer dir.close();
125+
126+
var walker = try dir.walk(b.allocator);
127+
while (try walker.next()) |entry| {
128+
switch (entry.kind) {
129+
.file => {
130+
const file = try entry.dir.openFile(entry.path, .{});
131+
defer file.close();
132+
const stat = try file.stat();
133+
const mtime = stat.mtime;
134+
135+
if (mtime > marker_mtime) {
136+
std.debug.print("Source file {s} changed, updating bootstrap\n", .{entry.path});
137+
break :blk true;
138+
}
139+
},
140+
// Doesn't currently search into subfolders.
141+
else => {},
142+
}
143+
}
144+
}
145+
146+
break :blk false;
147+
};
148+
149+
if (needs_source_update) {
150+
// Just needs the bindings to be updated, will reuse cached dir.
151+
std.debug.print("Updating source files in V8 bootstrap\n", .{});
152+
153+
// Just copy the updated files
154+
const copy_binding = b.addSystemCommand(&.{"cp"});
155+
copy_binding.addFileArg(b.path("src/binding.cpp"));
156+
copy_binding.addArg(b.fmt("{s}/binding.cpp", .{v8_dir}));
157+
158+
const copy_inspector = b.addSystemCommand(&.{"cp"});
159+
copy_inspector.addFileArg(b.path("src/inspector.h"));
160+
copy_inspector.addArg(b.fmt("{s}/inspector.h", .{v8_dir}));
161+
copy_inspector.step.dependOn(&copy_binding.step);
162+
163+
const copy_build_gn = b.addSystemCommand(&.{"cp"});
164+
copy_build_gn.addFileArg(b.path("build-tools/BUILD.gn"));
165+
copy_build_gn.addArg(b.fmt("{s}/zig/BUILD.gn", .{v8_dir}));
166+
copy_build_gn.step.dependOn(&copy_inspector.step);
167+
168+
const copy_gn = b.addSystemCommand(&.{"cp"});
169+
copy_gn.addFileArg(b.path("build-tools/.gn"));
170+
copy_gn.addArg(b.fmt("{s}/zig/.gn", .{v8_dir}));
171+
copy_gn.step.dependOn(&copy_build_gn.step);
172+
173+
// Touch marker to update timestamp
174+
const update_marker = b.addSystemCommand(&.{ "touch", marker_file });
175+
update_marker.step.dependOn(&copy_gn.step);
176+
177+
return update_marker;
178+
} else {
179+
// Cached V8 is still valid.
180+
std.debug.print("Using cached V8 bootstrap from {s}\n", .{v8_dir});
181+
const noop = b.addSystemCommand(&.{"true"});
182+
return noop;
183+
}
184+
}
185+
186+
std.debug.print("Bootstrapping V8 {s} in {s} (this will take a while)...\n", .{ V8_VERSION, v8_dir });
187+
188+
// Create cache directory
189+
const mkdir = b.addSystemCommand(&.{ "mkdir", "-p", v8_dir });
103190

104-
// Create .gclient file for gclient
191+
// Write .gclient file
105192
const gclient_content = b.fmt(
106193
\\solutions = [
107194
\\ {{
@@ -114,54 +201,72 @@ fn prepareV8Sources(b: *std.Build) !*std.Build.Step.WriteFile {
114201
\\]
115202
\\
116203
, .{V8_VERSION});
117-
_ = wf.add(".gclient", gclient_content);
118204

119-
// Copy binding files
120-
_ = wf.addCopyFile(b.path("src/binding.cpp"), "binding.cpp");
121-
_ = wf.addCopyFile(b.path("src/inspector.h"), "inspector.h");
122-
// Copy build configuration
123-
_ = wf.addCopyFile(b.path("build-tools/BUILD.gn"), "zig/BUILD.gn");
124-
// Not sure if it's a Zig bug or intended behavior but, addCopyFile won't
125-
// overwrite the original .gn. This means we put it in here and just call it from there.
126-
_ = wf.addCopyFile(b.path("build-tools/.gn"), "zig/.gn");
127-
// Generate gclient_args.gni
128-
_ = wf.add("build/config/gclient_args.gni",
129-
\\# Generated by Zig build system
130-
\\
131-
);
132-
return wf;
133-
}
134-
135-
fn bootstrapV8(b: *std.Build, prepared_v8: *std.Build.Step.WriteFile) *std.Build.Step.Run {
136-
const depot_tools = b.dependency("depot_tools", .{});
205+
const write_gclient = b.addSystemCommand(&.{ "sh", "-c" });
206+
write_gclient.addArg(b.fmt("echo '{s}' > {s}/.gclient", .{ gclient_content, v8_dir }));
207+
write_gclient.step.dependOn(&mkdir.step);
137208

138-
// Sync dependencies for this version
209+
// Copy binding files
210+
const copy_binding = b.addSystemCommand(&.{"cp"});
211+
copy_binding.addFileArg(b.path("src/binding.cpp"));
212+
copy_binding.addArg(b.fmt("{s}/binding.cpp", .{v8_dir}));
213+
copy_binding.step.dependOn(&write_gclient.step);
214+
215+
const copy_inspector = b.addSystemCommand(&.{"cp"});
216+
copy_inspector.addFileArg(b.path("src/inspector.h"));
217+
copy_inspector.addArg(b.fmt("{s}/inspector.h", .{v8_dir}));
218+
copy_inspector.step.dependOn(&copy_binding.step);
219+
220+
// Create zig directory and copy build files
221+
const mkdir_zig = b.addSystemCommand(&.{ "mkdir", "-p", b.fmt("{s}/zig", .{v8_dir}) });
222+
mkdir_zig.step.dependOn(&copy_inspector.step);
223+
224+
const copy_build_gn = b.addSystemCommand(&.{"cp"});
225+
copy_build_gn.addFileArg(b.path("build-tools/BUILD.gn"));
226+
copy_build_gn.addArg(b.fmt("{s}/zig/BUILD.gn", .{v8_dir}));
227+
copy_build_gn.step.dependOn(&mkdir_zig.step);
228+
229+
const copy_gn = b.addSystemCommand(&.{"cp"});
230+
copy_gn.addFileArg(b.path("build-tools/.gn"));
231+
copy_gn.addArg(b.fmt("{s}/zig/.gn", .{v8_dir}));
232+
copy_gn.step.dependOn(&copy_build_gn.step);
233+
234+
// Create gclient_args.gni
235+
const mkdir_build_config = b.addSystemCommand(&.{ "mkdir", "-p", b.fmt("{s}/build/config", .{v8_dir}) });
236+
mkdir_build_config.step.dependOn(&copy_gn.step);
237+
238+
const write_gclient_args = b.addSystemCommand(&.{ "sh", "-c" });
239+
write_gclient_args.addArg(b.fmt("echo '# Generated by Zig build system' > {s}/build/config/gclient_args.gni", .{v8_dir}));
240+
write_gclient_args.step.dependOn(&mkdir_build_config.step);
241+
242+
// Run gclient sync
139243
var gclient_sync = std.Build.Step.Run.create(b, "run gclient sync");
140244
gclient_sync.addFileArg(depot_tools.path("gclient"));
141245
gclient_sync.addArgs(&.{"sync"});
142-
// gclient_sync.setEnvironmentVariable("DEPOT_TOOLS_UPDATE", "0");
143-
gclient_sync.setCwd(prepared_v8.getDirectory());
144-
gclient_sync.step.dependOn(&prepared_v8.step);
145-
146-
// Run clang update script after copying
147-
const clang_update = b.addSystemCommand(&.{
148-
"python3",
149-
"tools/clang/scripts/update.py",
150-
});
151-
clang_update.setCwd(prepared_v8.getDirectory());
246+
gclient_sync.setCwd(.{ .cwd_relative = v8_dir });
247+
gclient_sync.step.dependOn(&write_gclient_args.step);
248+
249+
// Run clang update
250+
const clang_update = b.addSystemCommand(&.{ "python3", "tools/clang/scripts/update.py" });
251+
clang_update.setCwd(.{ .cwd_relative = v8_dir });
152252
clang_update.step.dependOn(&gclient_sync.step);
153-
return clang_update;
253+
254+
// Create marker file
255+
const create_marker = b.addSystemCommand(&.{ "touch", marker_file });
256+
create_marker.step.dependOn(&clang_update.step);
257+
258+
return create_marker;
154259
}
155260

156261
fn buildV8(
157262
b: *std.Build,
158-
prepared_v8: *std.Build.Step.WriteFile,
263+
v8_cache: []const u8,
159264
bootstrapped_v8: *std.Build.Step.Run,
160265
target: std.Build.ResolvedTarget,
161266
optimize: std.builtin.OptimizeMode,
162267
) !*std.Build.Step.WriteFile {
163268
const depot_tools = b.dependency("depot_tools", .{});
164-
const v8_dir = prepared_v8.getDirectory();
269+
const v8_dir: LazyPath = .{ .cwd_relative = v8_cache };
165270

166271
const allocator = b.allocator;
167272

@@ -199,29 +304,31 @@ fn buildV8(
199304
else => {},
200305
}
201306

307+
const out_dir = b.fmt("out/{s}/{s}", .{ @tagName(tag), if (is_debug) "debug" else "release" });
308+
202309
var gn_run = std.Build.Step.Run.create(b, "run gn");
203310
gn_run.addFileArg(depot_tools.path("gn"));
204311
gn_run.addArgs(&.{
205312
"--root=.",
206313
"--root-target=//zig",
207314
"--dotfile=zig/.gn",
208315
"gen",
209-
"out",
316+
out_dir,
210317
b.fmt("--args={s}", .{gn_args.items}),
211318
});
212319
gn_run.setCwd(v8_dir);
213-
gn_run.step.dependOn(&prepared_v8.step);
214320
gn_run.step.dependOn(&bootstrapped_v8.step);
215321

216322
var ninja_run = std.Build.Step.Run.create(b, "run ninja");
217323
ninja_run.addFileArg(depot_tools.path("ninja"));
218-
ninja_run.addArgs(&.{ "-C", "out", "c_v8" });
324+
ninja_run.addArgs(&.{ "-C", out_dir, "c_v8" });
219325
ninja_run.setCwd(v8_dir);
220326
ninja_run.step.dependOn(&gn_run.step);
221327

222328
const wf = b.addWriteFiles();
223329
wf.step.dependOn(&ninja_run.step);
224-
_ = wf.addCopyFile(v8_dir.path(b, "out/obj/zig/libc_v8.a"), "libc_v8.a");
330+
const libc_v8_path = b.fmt("{s}/obj/zig/libc_v8.a", .{out_dir});
331+
_ = wf.addCopyFile(v8_dir.path(b, libc_v8_path), "libc_v8.a");
225332

226333
return wf;
227334
}

0 commit comments

Comments
 (0)