const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); if (target.result.os.tag != .macos and target.result.os.tag != .windows and target.result.os.tag != .linux) @panic("Uhdk supports macOS, Windows and Linux."); const optimize = b.standardOptimizeOption(.{}); const shared = b.option(bool, "shared", "Build libuhdk as a shared library instead of static") orelse false; const tracy = b.option(bool, "tracy", "Emit Tracy 0.14.1 on-demand hooks; consumer must link the client") orelse false; if (tracy and shared) @panic("Tracy instrumentation requires static linking"); const lib = createLibraryNamed(b, target, optimize, shared, tracy, "uhdk"); const module = lib.root_module; const install_lib = b.addInstallArtifact(lib, .{}); const install_headers = b.addInstallDirectory(.{ .source_dir = b.path("include"), .install_dir = .header, .install_subdir = "", }); const lib_step = b.step("lib", "Build and install the Uhdk library and headers"); lib_step.dependOn(&install_lib.step); lib_step.dependOn(&install_headers.step); b.getInstallStep().dependOn(&install_lib.step); b.getInstallStep().dependOn(&install_headers.step); const unit = b.addTest(.{ .root_module = module }); const check_step = b.step("check", "Compile library and core tests without running them"); check_step.dependOn(&lib.step); check_step.dependOn(&unit.step); if (target.result.os.tag == .linux) @import("src/linux/build.zig").addTests(b, lib, target, optimize, check_step); const unit_run = b.addRunArtifact(unit); b.step("test", "Run core library tests").dependOn(&unit_run.step); const public_c = b.addTranslateC(.{ .root_source_file = b.path("include/uhdk.h"), .target = target, .optimize = optimize, }); public_c.defineCMacro("UHDK_ENABLE_OPENGL", "1"); public_c.defineCMacro("UHDK_ENABLE_NATIVE", "1"); public_c.addIncludePath(b.path("include")); if (shared) public_c.defineCMacro("UHDK_SHARED", "1"); const public_module = b.addModule("uhdk", .{ .root_source_file = public_c.getOutput(), .target = target, .optimize = optimize, }); public_module.linkLibrary(lib); } // Create a library artifact without installing it. Instrumented static builds // require the consumer to link a matching Tracy client. pub fn createLibrary(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, shared: bool, instrumented: bool) *std.Build.Step.Compile { return createLibraryNamed(b, target, optimize, shared, instrumented, if (instrumented) "uhdk-instrumented" else "uhdk"); } fn createLibraryNamed(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, shared: bool, instrumented: bool, artifact_name: []const u8) *std.Build.Step.Compile { std.debug.assert(!shared or !instrumented); const module = b.createModule(.{ .root_source_file = b.path("src/root.zig"), .target = target, .optimize = optimize, .link_libc = true, }); const native = b.addTranslateC(.{ .root_source_file = b.path("src/native.h"), .target = target, .optimize = optimize, }); native.addIncludePath(b.path("include")); module.addImport("native", native.createModule()); module.addImport("profile", createProfileModule(b, target, optimize, instrumented)); module.addIncludePath(b.path("include")); module.addIncludePath(b.path("src")); if (instrumented) module.addCMacro("UHDK_INTERNAL_TRACY", "1"); if (target.result.os.tag == .macos) { module.addCSourceFile(.{ .file = b.path("src/macos/native.m"), .flags = &.{ "-fobjc-arc", "-fblocks", "-Wno-deprecated-declarations", "-Wall", "-Wextra", "-Werror", }, }); module.linkFramework("Cocoa", .{}); module.linkFramework("OpenGL", .{}); module.linkFramework("CoreServices", .{}); } else if (target.result.os.tag == .linux) { @import("src/linux/build.zig").configure(b, module, target, optimize); } else { module.addCSourceFile(.{ .file = b.path("src/windows/native.c"), .flags = &.{ "-std=c11", "-Wall", "-Wextra", "-Werror", "-DUNICODE", "-D_UNICODE" } }); for ([_][]const u8{ "user32", "gdi32", "opengl32", "shell32", "ole32", "uuid", "imm32", "comctl32", "shlwapi", "advapi32" }) |name| module.linkSystemLibrary(name, .{}); } module.addCSourceFile(.{ .file = b.path("src/glad.c"), .flags = if (shared) &.{ "-std=c99", "-DGLAD_API_CALL_EXPORT", "-DGLAD_API_CALL_EXPORT_BUILD" } else &.{"-std=c99"} }); const lib = b.addLibrary(.{ .name = artifact_name, .linkage = if (shared) .dynamic else .static, .root_module = module, }); return lib; } pub fn createProfileModule(b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, enabled: bool) *std.Build.Module { const options = b.addOptions(); options.addOption(bool, "enabled", enabled); const profile = b.createModule(.{ .root_source_file = b.path("src/Profile.zig"), .target = target, .optimize = optimize, }); profile.addOptions("profile_options", options); return profile; }