feat: improve generation and add source downloader

This commit is contained in:
Kai Angulo 2024-10-12 22:31:02 -07:00
parent d4e4d00353
commit 22571ddc60

139
build.zig
View file

@ -14,7 +14,8 @@ pub fn build(b: *Build) !void {
const shared_tools = b.option(bool, "shared_tools", "Build and link spirv-tools as a shared library.") orelse false; const shared_tools = b.option(bool, "shared_tools", "Build and link spirv-tools as a shared library.") orelse false;
const standalone_glslang = b.option(bool, "standalone", "Build glslang.exe standalone command-line compiler.") orelse false; const standalone_glslang = b.option(bool, "standalone", "Build glslang.exe standalone command-line compiler.") orelse false;
const standalone_spvremap = b.option(bool, "standalone_remap", "Build spirv-remap.exe standalone command-line remapper.") orelse false; const standalone_spvremap = b.option(bool, "standalone_remap", "Build spirv-remap.exe standalone command-line remapper.") orelse false;
const minimal_test_exe = b.option(bool, "minimal_test", "Build a minimal test for linking") orelse false; const regenerate_headers = b.option(bool, "regenerate_headers", "Regenerate glslang header libraries.") orelse false;
const minimal_test_exe = b.option(bool, "minimal_test", "Build a minimal test for linking.") orelse false;
if (shared and (standalone_glslang or standalone_spvremap)) { if (shared and (standalone_glslang or standalone_spvremap)) {
log.err("Cannot build standalone sources with shared glslang. Recompile without `-Dshared` or `-Dstandalone/-Dstandalone-remap`", .{}); log.err("Cannot build standalone sources with shared glslang. Recompile without `-Dshared` or `-Dstandalone/-Dstandalone-remap`", .{});
@ -48,13 +49,8 @@ pub fn build(b: *Build) !void {
try cppflags.appendSlice(base_flags); try cppflags.appendSlice(base_flags);
_ = std.fs.openDirAbsolute(sdkPath("/External/spirv-tools"), .{}) catch |err| { downloadOrPull(b, "sinnwrig", "SPIRV-Tools-zig", &b.path("External/spirv-tools"));
if (err == error.FileNotFound) { downloadOrPull(b, "KhronosGroup", "SPIRV-Headers", &b.path("External/spirv-tools/external/spirv-headers"));
log.err("SPIRV-Tools build directory was not found - ensure sources have been cloned with `./update_glslang_sources.py --site zig`.", .{});
}
std.process.exit(1);
};
var tools_lib: *Build.Step.Compile = undefined; var tools_lib: *Build.Step.Compile = undefined;
var tools_opt: *Build.Step.Compile = undefined; var tools_opt: *Build.Step.Compile = undefined;
@ -70,10 +66,11 @@ pub fn build(b: *Build) !void {
.header_path = path, .header_path = path,
.no_link = true, .no_link = true,
.no_reduce = true, .no_reduce = true,
.rebuild_headers = regenerate_headers
})) |dep| { })) |dep| {
tools_lib = dep.artifact("SPIRV-Tools"); tools_lib = dep.artifact("SPIRV-Tools");
tools_opt = dep.artifact("SPIRV-Tools-opt"); tools_opt = dep.artifact("SPIRV-Tools-opt");
tools_val = dep.artifact("SPIRV-Tools-val"); tools_val = dep.artifact("SPIRV-Tools-val");
} }
if (tools_lib == undefined or tools_opt == undefined or tools_val == undefined) { if (tools_lib == undefined or tools_opt == undefined or tools_val == undefined) {
@ -89,8 +86,6 @@ pub fn build(b: *Build) !void {
var glslang_lib: *std.Build.Step.Compile = undefined; var glslang_lib: *std.Build.Step.Compile = undefined;
generateHeaders(b.allocator);
if (shared) { if (shared) {
glslang_lib = b.addSharedLibrary(.{ glslang_lib = b.addSharedLibrary(.{
.name = "glslang", .name = "glslang",
@ -99,8 +94,6 @@ pub fn build(b: *Build) !void {
.target = target, .target = target,
}); });
glslang_lib.rdynamic = true;
glslang_lib.defineCMacro("GLSLANG_IS_SHARED_LIBRARY", ""); glslang_lib.defineCMacro("GLSLANG_IS_SHARED_LIBRARY", "");
glslang_lib.defineCMacro("GLSLANG_EXPORTING", ""); glslang_lib.defineCMacro("GLSLANG_EXPORTING", "");
} else { } else {
@ -112,6 +105,10 @@ pub fn build(b: *Build) !void {
}); });
} }
if (regenerate_headers) {
glslang_lib.step.dependOn(generateHeaders(b));
}
glslang_lib.addCSourceFiles(.{ glslang_lib.addCSourceFiles(.{
.files = &sources, .files = &sources,
.flags = cppflags.items, .flags = cppflags.items,
@ -273,7 +270,7 @@ pub fn build(b: *Build) !void {
} }
fn addIncludes(b: *Build, step: *std.Build.Step.Compile) void { fn addIncludes(b: *Build, step: *std.Build.Step.Compile) void {
step.addIncludePath(b.path(output_path)); step.addIncludePath(b.path(header_output_path));
step.addIncludePath(b.path("")); step.addIncludePath(b.path(""));
step.addIncludePath(b.path("External/spirv-tools/include")); step.addIncludePath(b.path("External/spirv-tools/include"));
} }
@ -299,86 +296,82 @@ fn ensureCommandExists(allocator: std.mem.Allocator, name: []const u8, exist_che
return true; return true;
} }
fn exec(allocator: std.mem.Allocator, argv: []const []const u8, cwd: []const u8) !void { // --------------------------
log.info("cd {s}", .{cwd}); // spirv-tools download logic
var buf = std.ArrayList(u8).init(allocator); // --------------------------
for (argv) |arg| {
try std.fmt.format(buf.writer(), "{s} ", .{arg});
}
log.info("{s}", .{buf.items});
var child = std.process.Child.init(argv, allocator); fn downloadOrPull(b: *Build, comptime user: []const u8, comptime repo: []const u8, out_path: *const std.Build.LazyPath) void {
child.cwd = cwd; if (!ensureCommandExists(b.allocator, "git", "--version")) {
_ = try child.spawnAndWait(); log.err("'git --version' failed. Ensure a valid git installation is present on the path.", .{});
}
fn sdkPath(comptime suffix: []const u8) []const u8 {
if (suffix[0] != '/') @compileError("suffix must be an absolute path");
return comptime blk: {
const root_dir = std.fs.path.dirname(@src().file) orelse ".";
break :blk root_dir ++ suffix;
};
}
fn ensurePython(allocator: std.mem.Allocator) void {
if (!ensureCommandExists(allocator, "python3", "--version")) {
log.err("'python3 --version' failed. Is python not installed?", .{});
std.process.exit(1); std.process.exit(1);
} }
}
fn runPython(allocator: std.mem.Allocator, args: []const []const u8, errMsg: []const u8) void { const git_cmd = b.addSystemCommand(&.{ "git" });
exec(allocator, args, sdkPath("/")) catch |err| { git_cmd.setCwd(out_path.dirname());
log.err("{s}. error: {s}", .{ errMsg, @errorName(err) });
std.process.exit(1); _ = std.fs.openDirAbsolute(out_path.getPath(b), .{}) catch |err| {
if (err == error.FileNotFound) {
_ = b.run(&.{
"git", "clone", "https://github.com/" ++ user ++ "/" ++ repo, out_path.getPath(b)
});
return;
}
}; };
_ = b.run(&.{
"git", "-C", out_path.getPath(b), "pull",
});
} }
// ------------------------------------------ // -----------------------
// Include generation logic // Header generation logic
// ------------------------------------------ // -----------------------
pub const output_path = "build"; pub const header_output_path = "generated-include";
const build_info_script = "build_info.py"; const build_info_script = "build_info.py";
const ext_header_script = "gen_extension_headers.py"; const ext_header_script = "gen_extension_headers.py";
fn outPath(comptime out_name: []const u8) []const u8 { fn genBuildInfo(b: *Build) *Build.Step.Run {
if (out_name[0] != '/') @compileError("suffix must be an absolute path"); const python_cmd = b.addSystemCommand(&.{ "python3" });
return sdkPath("/" ++ output_path ++ out_name);
python_cmd.setCwd(b.path("."));
python_cmd.addFileArg(b.path(build_info_script));
python_cmd.addFileArg(b.path("."));
python_cmd.addArg("-i");
python_cmd.addFileArg(b.path("build_info.h.tmpl"));
python_cmd.addArg("-o");
python_cmd.addFileArg(b.path(header_output_path).path(b, "glslang").path(b, "build_info.h"));
return python_cmd;
} }
// Script usage derived from the BUILD.gn fn genExtensionHeaders(b: *Build) *Build.Step.Run {
const python_cmd = b.addSystemCommand(&.{ "python3" });
fn genBuildInfo(allocator: std.mem.Allocator) void { python_cmd.setCwd(b.path("."));
const args = &[_][]const u8{ python_cmd.addFileArg(b.path(ext_header_script));
"python3", build_info_script, python_cmd.addArg("-i");
sdkPath("/"), python_cmd.addFileArg(b.path("glslang").path(b, "ExtensionHeaders"));
"-i", sdkPath("/build_info.h.tmpl"), python_cmd.addArg("-o");
"-o", outPath("/glslang/build_info.h"), python_cmd.addFileArg(b.path(header_output_path).path(b, "glslang").path(b, "glsl_intrinsic_header.h"));
};
runPython(allocator, args, "Failed to generate build info file."); return python_cmd;
} }
fn genExtensionHeaders(allocator: std.mem.Allocator) void { fn generateHeaders(b: *Build) *std.Build.Step {
const args = &[_][]const u8 { if (!ensureCommandExists(b.allocator, "python3", "--version")) {
"python3", ext_header_script, log.err("'python3 --version' failed. Ensure a valid python3 installation is present on the path.", .{});
"-i", sdkPath("/glslang/ExtensionHeaders"),
"-o", outPath("/glslang/glsl_intrinsic_header.h"),
};
runPython(allocator, args, "Failed to generate extension headers");
}
fn generateHeaders(allocator: std.mem.Allocator) void {
if (!ensureCommandExists(allocator, "python3", "--version")) {
log.err("'python3 --version' failed. Is python not installed?", .{});
std.process.exit(1); std.process.exit(1);
} }
genBuildInfo(allocator); const headers_step = b.step("build-headers", "Build glslang headers");
genExtensionHeaders(allocator);
headers_step.dependOn(&genBuildInfo(b).step);
headers_step.dependOn(&genExtensionHeaders(b).step);
return headers_step;
} }