Skip to content

Commit

Permalink
build.zig code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
floooh committed Jan 8, 2024
1 parent d17c82b commit 38ef7eb
Showing 1 changed file with 108 additions and 117 deletions.
225 changes: 108 additions & 117 deletions build.zig
Original file line number Diff line number Diff line change
@@ -1,51 +1,41 @@
const std = @import("std");
const builtin = @import("builtin");
const Build = std.Build;
const CompileStep = std.Build.Step.Compile;
const Module = std.Build.Module;
const ResolvedTarget = std.Build.ResolvedTarget;
const OptimizeMode = std.builtin.OptimizeMode;

pub const Backend = enum {
auto, // Windows: D3D11, macOS/iOS: Metal, otherwise: GL
d3d11,
metal,
gl,
gles3,
wgpu,
};

pub const LibSokolOptions = struct {
resolved_target: ResolvedTarget,
optimize: OptimizeMode,
build_root: ?[]const u8 = null,
backend: Backend = .auto,
force_egl: bool = false,
enable_x11: bool = true,
enable_wayland: bool = false,
};

// build system entry point
pub fn build(b: *Build) void {
const force_gl = b.option(bool, "gl", "Force GL backend") orelse false;
const resolved_target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const mod_sokol = b.addModule("sokol", .{ .root_source_file = .{ .path = "src/sokol/sokol.zig" } });

// the static link library compiled from the C sources
const opt_force_gl = b.option(bool, "gl", "Force GL backend") orelse false;
const opt_linux_enable_wayland = b.option(bool, "wayland", "Compile with wayland-support (default: false)") orelse false;
const opt_linux_enable_x11 = b.option(bool, "x11", "Compile with x11-support (default: true)") orelse true;
const opt_linux_force_egl = b.option(bool, "egl", "Use EGL instead of GLX if possible (default: false)") orelse false;
const lib_sokol = buildLibSokol(b, .{
.resolved_target = resolved_target,
.optimize = optimize,
.backend = if (force_gl) .gl else .auto,
.enable_wayland = b.option(bool, "wayland", "Compile with wayland-support (default: false)") orelse false,
.enable_x11 = b.option(bool, "x11", "Compile with x11-support (default: true)") orelse true,
.force_egl = b.option(bool, "egl", "Use EGL instead of GLX if possible (default: false)") orelse false,
.backend = if (opt_force_gl) .gl else .auto,
.linux = .{
.enable_wayland = opt_linux_enable_wayland,
.enable_x11 = opt_linux_enable_x11,
.force_egl = opt_linux_force_egl,
},
}) catch |err| {
std.log.err("buildLibSokol return with error {}", .{err});
return;
};
// make the sokol library available to the package manager as artifact

// the Zig module for the bindings
const mod_sokol = b.addModule("sokol", .{ .root_source_file = .{ .path = "src/sokol/sokol.zig" } });

// add the static link library as dependency to the module
mod_sokol.linkLibrary(lib_sokol);

// make the sokol library available to the package manager as artifact (FIXME: still needed?)
b.installArtifact(lib_sokol);

// add example build steps
const examples = .{
"clear",
"triangle",
Expand All @@ -71,39 +61,52 @@ pub fn build(b: *Build) void {
buildExample(b, example, .{
.resolved_target = resolved_target,
.optimize = optimize,
.lib_sokol = lib_sokol,
.mod_sokol = mod_sokol,
});
}

// a utility build step for compiling the GLSL shaders via sokol-shdc
buildShaders(b);
}

const ExampleOptions = struct {
resolved_target: ResolvedTarget,
optimize: OptimizeMode,
lib_sokol: *CompileStep,
mod_sokol: *Module,
pub const Backend = enum {
auto, // Windows: D3D11, macOS/iOS: Metal, otherwise: GL
d3d11,
metal,
gl,
gles3,
wgpu,
};

pub const LibSokolOptions = struct {
resolved_target: Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
build_root: ?[]const u8 = null,
backend: Backend = .auto,
linux: struct {
force_egl: bool = false,
enable_x11: bool = true,
enable_wayland: bool = false,
},
};

// build sokol into a static library
pub fn buildLibSokol(b: *Build, options: LibSokolOptions) !*CompileStep {
pub fn buildLibSokol(b: *Build, options: LibSokolOptions) !*Build.Step.Compile {
var resolved_target = options.resolved_target;
const is_wasm = resolved_target.result.cpu.arch == .wasm32;

// special case wasm, must compile as wasm32-emscripten, not wasm32-freestanding
if (is_wasm) {
resolved_target.result.os.tag = .emscripten;
}
const target = resolved_target.result;

const lib = b.addStaticLibrary(.{
.name = "sokol",
.target = resolved_target,
.optimize = options.optimize,
.link_libc = true,
});
if (is_wasm) {
// need to add Emscripten SDK include path
// for WASM: need to add Emscripten SDK include path and __EMSCRIPTEN__ define
if (b.sysroot == null) {
std.log.err("Must provide Emscripten sysroot via '--sysroot [path/to/emsdk]/upstream/emscripten/cache/sysroot'", .{});
return error.Wasm32SysRootExpected;
Expand All @@ -113,35 +116,23 @@ pub fn buildLibSokol(b: *Build, options: LibSokolOptions) !*CompileStep {
lib.addIncludePath(.{ .path = include_path });
lib.defineCMacro("__EMSCRIPTEN__", "1");
}
var sokol_path: []const u8 = "src/sokol/c";
if (options.build_root) |build_root| {
sokol_path = try std.fmt.allocPrint(b.allocator, "{s}/src/sokol/c", .{build_root});
}
const csources = [_][]const u8{
"sokol_log.c",
"sokol_app.c",
"sokol_gfx.c",
"sokol_time.c",
"sokol_audio.c",
"sokol_gl.c",
"sokol_debugtext.c",
"sokol_shape.c",
};
var _backend = options.backend;
if (_backend == .auto) {
if (target.isDarwin()) {
_backend = .metal;
} else if (target.os.tag == .windows) {
_backend = .d3d11;
} else if (target.cpu.arch == .wasm32) {
_backend = .gles3;
} else if (target.isAndroid()) {
_backend = .gles3;

// select the 3D backend to use
var backend = options.backend;
if (backend == .auto) {
if (lib.rootModuleTarget().isDarwin()) {
backend = .metal;
} else if (lib.rootModuleTarget().os.tag == .windows) {
backend = .d3d11;
} else if (lib.rootModuleTarget().cpu.arch == .wasm32) {
backend = .gles3;
} else if (lib.rootModuleTarget().isAndroid()) {
backend = .gles3;
} else {
_backend = .gl;
backend = .gl;
}
}
const backend_option = switch (_backend) {
const backend_option = switch (backend) {
.d3d11 => "-DSOKOL_D3D11",
.metal => "-DSOKOL_METAL",
.gl => "-DSOKOL_GLCORE33",
Expand All @@ -150,66 +141,52 @@ pub fn buildLibSokol(b: *Build, options: LibSokolOptions) !*CompileStep {
else => unreachable,
};

if (target.isDarwin()) {
for (csources) |csrc| {
lib.addCSourceFile(.{
.file = .{ .path = try std.fmt.allocPrint(b.allocator, "{s}/{s}", .{ sokol_path, csrc }) },
.flags = &[_][]const u8{ "-ObjC", "-DIMPL", backend_option },
});
}
// platform-specific configuration (C compilation flags and linking with system libraries)
var c_flags: []const []const u8 = &.{ "-DIMPL", backend_option };
if (lib.rootModuleTarget().isDarwin()) {
c_flags = &.{ "-ObjC", "-DIMPL", backend_option };
lib.linkFramework("Foundation");
lib.linkFramework("AudioToolbox");
if (.metal == _backend) {
if (.metal == backend) {
lib.linkFramework("MetalKit");
lib.linkFramework("Metal");
}
if (target.os.tag == .ios) {
if (lib.rootModuleTarget().os.tag == .ios) {
lib.linkFramework("UIKit");
lib.linkFramework("AVFoundation");
if (.gl == _backend) {
if (.gl == backend) {
lib.linkFramework("OpenGLES");
lib.linkFramework("GLKit");
}
} else if (target.os.tag == .macos) {
} else if (lib.rootModuleTarget().os.tag == .macos) {
lib.linkFramework("Cocoa");
lib.linkFramework("QuartzCore");
if (.gl == _backend) {
if (.gl == backend) {
lib.linkFramework("OpenGL");
}
}
} else if (target.isAndroid()) {
if (.gles3 != _backend) {
} else if (lib.rootModuleTarget().isAndroid()) {
if (.gles3 != backend) {
@panic("For android targets, you must have backend set to GLES3");
}
for (csources) |csrc| {
lib.addCSourceFile(.{
.file = .{ .path = try std.fmt.allocPrint(b.allocator, "{s}/{s}", .{ sokol_path, csrc }) },
.flags = &[_][]const u8{ "-DIMPL", backend_option },
});
}
lib.linkSystemLibrary("GLESv3");
lib.linkSystemLibrary("EGL");
lib.linkSystemLibrary("android");
lib.linkSystemLibrary("log");
} else if (target.os.tag == .linux) {
const egl_flag = if (options.force_egl) "-DSOKOL_FORCE_EGL " else "";
const x11_flag = if (!options.enable_x11) "-DSOKOL_DISABLE_X11 " else "";
const wayland_flag = if (!options.enable_wayland) "-DSOKOL_DISABLE_WAYLAND" else "";
const link_egl = options.force_egl or options.enable_wayland;
for (csources) |csrc| {
lib.addCSourceFile(.{
.file = .{ .path = try std.fmt.allocPrint(b.allocator, "{s}/{s}", .{ sokol_path, csrc }) },
.flags = &[_][]const u8{ "-DIMPL", backend_option, egl_flag, x11_flag, wayland_flag },
});
}
} else if (lib.rootModuleTarget().os.tag == .linux) {
const egl_flag = if (options.linux.force_egl) "-DSOKOL_FORCE_EGL " else "";
const x11_flag = if (!options.linux.enable_x11) "-DSOKOL_DISABLE_X11 " else "";
const wayland_flag = if (!options.linux.enable_wayland) "-DSOKOL_DISABLE_WAYLAND" else "";
const link_egl = options.linux.force_egl or options.linux.enable_wayland;
c_flags = &.{ "-DIMPL", backend_option, egl_flag, x11_flag, wayland_flag };
lib.linkSystemLibrary("asound");
lib.linkSystemLibrary("GL");
if (options.enable_x11) {
if (options.linux.enable_x11) {
lib.linkSystemLibrary("X11");
lib.linkSystemLibrary("Xi");
lib.linkSystemLibrary("Xcursor");
}
if (options.enable_wayland) {
if (options.linux.enable_wayland) {
lib.linkSystemLibrary("wayland-client");
lib.linkSystemLibrary("wayland-cursor");
lib.linkSystemLibrary("wayland-egl");
Expand All @@ -218,41 +195,55 @@ pub fn buildLibSokol(b: *Build, options: LibSokolOptions) !*CompileStep {
if (link_egl) {
lib.linkSystemLibrary("egl");
}
} else if (target.os.tag == .windows) {
for (csources) |csrc| {
lib.addCSourceFile(.{
.file = .{ .path = try std.fmt.allocPrint(b.allocator, "{s}/{s}", .{ sokol_path, csrc }) },
.flags = &[_][]const u8{ "-DIMPL", backend_option },
});
}
} else if (lib.rootModuleTarget().os.tag == .windows) {
lib.linkSystemLibrary("kernel32");
lib.linkSystemLibrary("user32");
lib.linkSystemLibrary("gdi32");
lib.linkSystemLibrary("ole32");
if (.d3d11 == _backend) {
if (.d3d11 == backend) {
lib.linkSystemLibrary("d3d11");
lib.linkSystemLibrary("dxgi");
}
} else {
for (csources) |csrc| {
lib.addCSourceFile(.{
.file = .{ .path = try std.fmt.allocPrint(b.allocator, "{s}/{s}", .{ sokol_path, csrc }) },
.flags = &[_][]const u8{ "-DIMPL", backend_option },
});
}
}

// add the C source files to the library target
var sokol_path: []const u8 = "src/sokol/c";
if (options.build_root) |build_root| {
sokol_path = try std.fmt.allocPrint(b.allocator, "{s}/src/sokol/c", .{build_root});
}
const csources = [_][]const u8{
"sokol_log.c",
"sokol_app.c",
"sokol_gfx.c",
"sokol_time.c",
"sokol_audio.c",
"sokol_gl.c",
"sokol_debugtext.c",
"sokol_shape.c",
};
for (csources) |csrc| {
lib.addCSourceFile(.{
.file = .{ .path = try std.fmt.allocPrint(b.allocator, "{s}/{s}", .{ sokol_path, csrc }) },
.flags = c_flags,
});
}
return lib;
}

// build one of the example exes
const ExampleOptions = struct {
resolved_target: Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
mod_sokol: *Build.Module,
};

// build one of the examples
fn buildExample(b: *Build, comptime name: []const u8, options: ExampleOptions) void {
const e = b.addExecutable(.{
.name = name,
.root_source_file = .{ .path = "src/examples/" ++ name ++ ".zig" },
.target = options.resolved_target,
.optimize = options.optimize,
});
e.linkLibrary(options.lib_sokol);
e.root_module.addImport("sokol", options.mod_sokol);
b.installArtifact(e);
const run = b.addRunArtifact(e);
Expand Down

0 comments on commit 38ef7eb

Please sign in to comment.