Skip to content

Commit

Permalink
Merge pull request #20 from kassane/v0.13.0-master
Browse files Browse the repository at this point in the history
Update `build.zig` to latest zig-master
  • Loading branch information
kassane authored May 31, 2024
2 parents 771d29d + 07ab4c3 commit 3e4bfe1
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 134 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- uses: actions/checkout@v4
- uses: korandoru/setup-zig@v1
with:
zig-version: 0.12.0
zig-version: master
- uses: dlang-community/setup-dlang@v1
with:
compiler: ldc-master
Expand Down Expand Up @@ -42,4 +42,4 @@ jobs:
- name: (Zig) Build Native
run: zig build -DzigCC --summary all
- name: (Zig + emsdk) Build Wasm
run: zig build -DzigCC --summary all -Dtarget=wasm32-emscripten -Doptimize=ReleaseSmall
run: zig build -DzigCC --summary all -Dtarget=wasm32-emscripten-none -Doptimize=ReleaseSmall
28 changes: 14 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,37 @@ Auto-generated [D](https://dlang.org) bindings for the [sokol headers](https://g
#### Targets

- Native
- Wasm (`-Dtarget=wasm32-emscripten`)
- Wasm (`-Dtarget=wasm32-emscripten-none`)

## BUILD

**Required**

- [zig](https://ziglang.org/download) v0.12.0 or master
- [ldc](https://ldc-developers.github.io) v1.36.0 or latest-CI (nightly)
- [ldc](https://ldc-developers.github.io) v1.38.0 or latest-CI (nightly)

Supported platforms are: Windows, macOS, Linux (with X11)

On Linux install the following packages: libglu1-mesa-dev, mesa-common-dev, xorg-dev, libasound-dev (or generally: the dev packages required for X11, GL and ALSA development)

```bash
# build sokol library + all examples [default: static library]
zig build -Doptimize=ReleaseFast
zig build -Doptimize=ReleaseSafe

# build sokol shared library + all examples
zig build -Doptimize=ReleaseFast -Dshared
zig build -Doptimize=ReleaseSafe -Dshared

# Run Examples
zig build run-blend -Doptimize=ReleaseFast
zig build run-clear -Doptimize=ReleaseFast
zig build run-cube -Doptimize=ReleaseFast
zig build run-debugtext -Doptimize=ReleaseFast
zig build run-mrt -Doptimize=ReleaseFast
zig build run-saudio -Doptimize=ReleaseFast
zig build run-sgl_context -Doptimize=ReleaseFast
zig build run-sgl_points -Doptimize=ReleaseFast
zig build run-user_data -Doptimize=ReleaseFast
zig build run-triangle -Doptimize=ReleaseFast
zig build run-blend -Doptimize=ReleaseSafe
zig build run-clear -Doptimize=ReleaseSafe
zig build run-cube -Doptimize=ReleaseSafe
zig build run-debugtext -Doptimize=ReleaseSafe
zig build run-mrt -Doptimize=ReleaseSafe
zig build run-saudio -Doptimize=ReleaseSafe
zig build run-sgl_context -Doptimize=ReleaseSafe
zig build run-sgl_points -Doptimize=ReleaseSafe
zig build run-user_data -Doptimize=ReleaseSafe
zig build run-triangle -Doptimize=ReleaseSafe

zig build --help
# Project-Specific Options:
Expand Down
172 changes: 88 additions & 84 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ fn resolveSokolBackend(backend: SokolBackend, target: std.Target) SokolBackend {
return .metal;
} else if (target.os.tag == .windows) {
return .d3d11;
} else if (target.isWasm() or target.isAndroid()) {
} else if (target.isWasm()) {
return .gles3;
} else if (target.isAndroid()) {
return .gles3;
} else {
return .gl;
Expand All @@ -58,14 +60,16 @@ pub fn buildLibSokol(b: *Build, options: LibSokolOptions) !*CompileStep {
});
lib.root_module.sanitize_c = false;
lib.linkLibC();
lib.root_module.root_source_file = .{ .path = "src/handmade/math.zig" };
lib.root_module.root_source_file = b.path("src/handmade/math.zig");

switch (options.optimize) {
.Debug, .ReleaseSafe => lib.bundle_compiler_rt = true,
else => lib.root_module.strip = true,
}

if (options.target.result.isWasm()) {
if (options.optimize != .Debug)
lib.want_lto = true;
// make sure we're building for the wasm32-emscripten target, not wasm32-freestanding
if (lib.rootModuleTarget().os.tag != .emscripten) {
std.log.err("Please build with 'zig build -Dtarget=wasm32-emscripten", .{});
Expand All @@ -76,9 +80,7 @@ pub fn buildLibSokol(b: *Build, options: LibSokolOptions) !*CompileStep {
lib.step.dependOn(&emsdk_setup.step);
}
// add the Emscripten system include seach path
const emsdk_sysroot = b.pathJoin(&.{ emSdkPath(b, options.emsdk.?), "upstream", "emscripten", "cache", "sysroot" });
const include_path = b.pathJoin(&.{ emsdk_sysroot, "include" });
lib.addSystemIncludePath(.{ .path = include_path });
lib.addSystemIncludePath(emSdkLazyPath(b, options.emsdk.?, &.{ "upstream", "emscripten", "cache", "sysroot", "include" }));
}

// resolve .auto backend into specific backend by platform
Expand Down Expand Up @@ -172,12 +174,10 @@ pub fn buildLibSokol(b: *Build, options: LibSokolOptions) !*CompileStep {
};
for (csources) |csrc| {
lib.addCSourceFile(.{
.file = .{ .path = csrc },
.file = b.path(csrc),
.flags = cflags,
});
}

b.installArtifact(lib);
return lib;
}

Expand All @@ -188,7 +188,10 @@ pub fn build(b: *Build) !void {
const opt_use_wayland = b.option(bool, "wayland", "Force Wayland (default: false, Linux only, not supported in main-line headers)") orelse false;
const opt_use_egl = b.option(bool, "egl", "Force EGL (default: false, Linux only)") orelse false;
const sokol_backend: SokolBackend = if (opt_use_gl) .gl else if (opt_use_wgpu) .wgpu else .auto;

const dub_artifact = b.option(bool, "artifact", "Build artifacts (default: false)") orelse false;
// LDC-options options
const enable_betterC = b.option(bool, "betterC", "Omit generating some runtime information and helper functions (default: false)") orelse false;
const enable_zigcc = b.option(bool, "zigCC", "Use zig cc as compiler and linker (default: false)") orelse false;
// ldc2 w/ druntime + phobos2 works on MSVC
const target = b.standardTargetOptions(.{ .default_target = if (builtin.os.tag == .windows) try std.Target.Query.parse(.{ .arch_os_abi = "native-windows-msvc" }) else .{} });
const optimize = b.standardOptimizeOption(.{});
Expand All @@ -203,48 +206,45 @@ pub fn build(b: *Build) !void {
.use_egl = opt_use_egl,
.emsdk = emsdk,
});

// LDC-options options
const enable_betterC = b.option(bool, "betterC", "Omit generating some runtime information and helper functions (default: false)") orelse false;
const enable_zigcc = b.option(bool, "zigCC", "Use zig cc as compiler and linker (default: false)") orelse false;

// build examples
const examples = .{
"clear",
"triangle",
"cube",
"blend",
"mrt",
"saudio",
"sgl_context",
"sgl_points",
"debugtext",
"user_data", // Need GC for user data [associative array]
};

inline for (examples) |example| {
const ldc = try ldcBuildStep(b, .{
.name = example,
.artifact = lib_sokol,
.sources = &[_][]const u8{b.fmt("{s}/src/examples/{s}.d", .{ rootPath(), example })},
.betterC = if (std.mem.eql(u8, example, "user-data")) false else enable_betterC,
.dflags = &[_][]const u8{
"-w", // warnings as error
// more info: ldc2 -preview=help (list all specs)
"-preview=all",
},
.d_packages = if (target.result.isWasm()) &[_][]const u8{
b.dependency("wasmd", .{}).path("arsd-webassembly").getPath(b),
} else null,
// fixme: https://github.com/kassane/sokol-d/issues/1 - betterC works on darwin
.zig_cc = if (target.result.isDarwin() and !enable_betterC) false else enable_zigcc,
.target = target,
.optimize = optimize,
// send ldc2-obj (wasm artifact) to emcc
.kind = if (target.result.isWasm()) .obj else .exe,
.emsdk = emsdk,
});
b.getInstallStep().dependOn(&ldc.step);
if (dub_artifact) {
b.installArtifact(lib_sokol);
} else {
// build examples
const examples = .{
"clear",
"triangle",
"cube",
"blend",
"mrt",
"saudio",
"sgl_context",
"sgl_points",
"debugtext",
"user_data", // Need GC for user data [associative array]
};

inline for (examples) |example| {
const ldc = try ldcBuildStep(b, .{
.name = example,
.artifact = lib_sokol,
.sources = &[_][]const u8{b.fmt("{s}/src/examples/{s}.d", .{ rootPath(), example })},
.betterC = if (std.mem.eql(u8, example, "user-data")) false else enable_betterC,
.dflags = &[_][]const u8{
"-w", // warnings as error
// more info: ldc2 -preview=help (list all specs)
"-preview=all",
},
// fixme: https://github.com/kassane/sokol-d/issues/1 - betterC works on darwin
.zig_cc = if (target.result.isDarwin() and !enable_betterC) false else enable_zigcc,
.target = target,
.optimize = optimize,
// send ldc2-obj (wasm artifact) to emcc
.kind = if (target.result.isWasm()) .obj else .exe,
.emsdk = emsdk,
.backend = sokol_backend,
});
b.getInstallStep().dependOn(&ldc.step);
}
}
buildShaders(b);

Expand Down Expand Up @@ -357,8 +357,6 @@ pub fn ldcBuildStep(b: *Build, options: DCompileStep) !*RunStep {
// mutable state hash (ldc2 cache - llvm-ir2obj)
try cmds.append(b.fmt("-cache={s}", .{b.pathJoin(&.{ path, "o", &b.graph.cache.hash.final() })}));
}
// name object files uniquely (so the files don't collide)
try cmds.append("-oq");

// disable LLVM-IR verifier
// https://llvm.org/docs/Passes.html#verify-module-verifier
Expand Down Expand Up @@ -426,8 +424,8 @@ pub fn ldcBuildStep(b: *Build, options: DCompileStep) !*RunStep {

// library paths
for (lib_sokol.root_module.lib_paths.items) |libpath| {
if (libpath.path.len > 0) // skip empty paths
try cmds.append(b.fmt("-L-L{s}", .{libpath.path}));
if (libpath.getPath(b).len > 0) // skip empty paths
try cmds.append(b.fmt("-L-L{s}", .{libpath.getPath(b)}));
}

// link system libs
Expand Down Expand Up @@ -490,9 +488,9 @@ pub fn ldcBuildStep(b: *Build, options: DCompileStep) !*RunStep {
// ldc2 doesn't support zig native (a.k.a: native-native or native)
const mtriple = if (options.target.result.isDarwin())
b.fmt("{s}-apple-{s}", .{ if (options.target.result.cpu.arch.isAARCH64()) "arm64" else @tagName(options.target.result.cpu.arch), @tagName(options.target.result.os.tag) })
else if (options.target.result.isWasm())
else if (options.target.result.isWasm() and options.target.result.os.tag == .freestanding)
b.fmt("{s}-unknown-unknown-wasm", .{@tagName(options.target.result.cpu.arch)})
else if (options.target.result.isWasm() and options.target.result.os.tag == .wasi)
else if (options.target.result.isWasm())
b.fmt("{s}-unknown-{s}", .{ @tagName(options.target.result.cpu.arch), @tagName(options.target.result.os.tag) })
else
b.fmt("{s}-{s}-{s}", .{ @tagName(options.target.result.cpu.arch), @tagName(options.target.result.os.tag), @tagName(options.target.result.abi) });
Expand Down Expand Up @@ -527,14 +525,8 @@ pub fn ldcBuildStep(b: *Build, options: DCompileStep) !*RunStep {
const zcc_exists = !std.meta.isError(std.fs.accessAbsolute(zcc_path, .{}));
if (!zcc_exists)
ldc_exec.step.dependOn(&install.step);
try cmds.append(b.fmt("--gcc={s}", .{zcc_path}));
try cmds.append(b.fmt("--linker={s}", .{zcc_path}));
}

if (options.artifact) |lib_sokol| {
if (lib_sokol.rootModuleTarget().os.tag == .windows and lib_sokol.isDynamicLibrary()) {
ldc_exec.addArg(b.pathJoin(&.{ b.install_path, "lib", b.fmt("{s}.lib", .{lib_sokol.name}) }));
} else ldc_exec.addArtifactArg(lib_sokol);
ldc_exec.addArg(b.fmt("--gcc={s}", .{zcc_path}));
ldc_exec.addArg(b.fmt("--linker={s}", .{zcc_path}));
}

const example_run = b.addSystemCommand(&.{b.pathJoin(&.{ b.install_path, outputDir, options.name })});
Expand All @@ -546,19 +538,27 @@ pub fn ldcBuildStep(b: *Build, options: DCompileStep) !*RunStep {
b.step("test", "Run all tests");

if (options.target.result.isWasm()) {
// get D object file and put it in the wasm artifact
const artifact = addArtifact(b, options);
artifact.addObjectFile(.{ .path = b.fmt("{s}/examples.{s}.o", .{ objpath, options.name }) });
artifact.addObjectFile(.{
.src_path = .{
.sub_path = b.fmt("{s}/{s}.o", .{ objpath, options.name }),
.owner = b,
},
});
artifact.linkLibrary(options.artifact.?);
artifact.step.dependOn(&ldc_exec.step);

const backend = resolveSokolBackend(options.backend, options.target.result);
const link_step = try emLinkStep(b, .{
.lib_main = artifact,
.target = options.target,
.optimize = options.optimize,
.emsdk = options.emsdk.?,
.use_webgl2 = true,
.use_webgpu = backend == .wgpu,
.use_webgl2 = backend != .wgpu,
.use_emmalloc = true,
.use_filesystem = false,
.release_use_lto = options.artifact.?.want_lto orelse false,
.shell_file_path = "src/sokol/web/shell.html",
// NOTE: This is required to make the Zig @returnAddress() builtin work,
// which is used heavily in the stdlib allocator code (not just
Expand All @@ -571,8 +571,14 @@ pub fn ldcBuildStep(b: *Build, options: DCompileStep) !*RunStep {
const emrun = emRunStep(b, .{ .name = options.name, .emsdk = options.emsdk.? });
emrun.step.dependOn(&link_step.step);
run.dependOn(&emrun.step);
} else run.dependOn(&example_run.step);

} else {
if (options.artifact) |lib_sokol| {
if (lib_sokol.rootModuleTarget().os.tag == .windows and lib_sokol.isDynamicLibrary()) {
ldc_exec.addArg(b.pathJoin(&.{ b.install_path, "lib", b.fmt("{s}.lib", .{lib_sokol.name}) }));
} else ldc_exec.addArtifactArg(lib_sokol);
}
run.dependOn(&example_run.step);
}
return ldc_exec;
}

Expand All @@ -590,6 +596,7 @@ pub const DCompileStep = struct {
d_packages: ?[]const []const u8 = null,
artifact: ?*Build.Step.Compile = null,
emsdk: ?*Build.Dependency = null,
backend: SokolBackend = .auto,
};
pub fn addArtifact(b: *Build, options: DCompileStep) *Build.Step.Compile {
return Build.Step.Compile.create(b, .{
Expand All @@ -611,9 +618,7 @@ pub fn buildZigCC(b: *Build) *CompileStep {
.name = "zcc",
.target = b.host,
.optimize = .ReleaseSafe,
.root_source_file = .{
.path = "tools/zigcc.zig",
},
.root_source_file = b.path("tools/zigcc.zig"),
});
return exe;
}
Expand Down Expand Up @@ -675,7 +680,7 @@ pub const EmLinkOptions = struct {
// lib_sokol: *Build.Step.Compile,
emsdk: *Build.Dependency,
release_use_closure: bool = true,
release_use_lto: bool = true,
release_use_lto: bool = false,
use_webgpu: bool = false,
use_webgl2: bool = false,
use_emmalloc: bool = false,
Expand All @@ -685,7 +690,7 @@ pub const EmLinkOptions = struct {
};

pub fn emLinkStep(b: *Build, options: EmLinkOptions) !*Build.Step.Run {
const emcc_path = b.findProgram(&.{"emcc"}, &.{}) catch b.pathJoin(&.{ emSdkPath(b, options.emsdk), "upstream", "emscripten", "emcc" });
const emcc_path = b.findProgram(&.{"emcc"}, &.{}) catch emSdkLazyPath(b, options.emsdk, &.{ "upstream", "emscripten", "emcc" }).getPath(b);

// create a separate output directory zig-out/web
try std.fs.cwd().makePath(b.fmt("{s}/web", .{b.install_path}));
Expand Down Expand Up @@ -767,14 +772,14 @@ pub const EmRunOptions = struct {
emsdk: *Build.Dependency,
};
pub fn emRunStep(b: *Build, options: EmRunOptions) *Build.Step.Run {
const emrun_path = b.findProgram(&.{"emrun"}, &.{}) catch b.pathJoin(&.{ emSdkPath(b, options.emsdk), "upstream", "emscripten", "emrun" });
const emrun_path = b.findProgram(&.{"emrun"}, &.{}) catch emSdkLazyPath(b, options.emsdk, &.{ "upstream", "emscripten", "emrun" }).getPath(b);
const emrun = b.addSystemCommand(&.{ emrun_path, b.fmt("{s}/web/{s}.html", .{ b.install_path, options.name }) });
return emrun;
}

// helper function to extract emsdk path from the emsdk package dependency
fn emSdkPath(b: *Build, emsdk: *Build.Dependency) []const u8 {
return emsdk.path("").getPath(b);
fn emSdkLazyPath(b: *Build, emsdk: *Build.Dependency, subPaths: []const []const u8) Build.LazyPath {
return emsdk.path(b.pathJoin(subPaths));
}

// One-time setup of the Emscripten SDK (runs 'emsdk install + activate'). If the
Expand All @@ -783,17 +788,16 @@ fn emSdkPath(b: *Build, emsdk: *Build.Dependency) []const u8 {
// if the emsdk was already setup, null will be returned.
// NOTE: ideally this would go into a separate emsdk-zig package
fn emSdkSetupStep(b: *Build, emsdk: *Build.Dependency) !?*Build.Step.Run {
const emsdk_path = emSdkPath(b, emsdk);
const dot_emsc_path = b.pathJoin(&.{ emsdk_path, ".emscripten" });
const dot_emsc_path = emSdkLazyPath(b, emsdk, &.{".emscripten"}).getPath(b);
const dot_emsc_exists = !std.meta.isError(std.fs.accessAbsolute(dot_emsc_path, .{}));
if (!dot_emsc_exists) {
var cmd = std.ArrayList([]const u8).init(b.allocator);
defer cmd.deinit();
if (builtin.os.tag == .windows)
try cmd.append(b.pathJoin(&.{ emsdk_path, "emsdk.bat" }))
else {
if (builtin.os.tag == .windows) {
try cmd.append(emSdkLazyPath(b, emsdk, &.{"emsdk.bat"}).getPath(b));
} else {
try cmd.append("bash"); // or try chmod
try cmd.append(b.pathJoin(&.{ emsdk_path, "emsdk" }));
try cmd.append(emSdkLazyPath(b, emsdk, &.{"emsdk"}).getPath(b));
}
const emsdk_install = b.addSystemCommand(cmd.items);
emsdk_install.addArgs(&.{ "install", "latest" });
Expand Down
Loading

0 comments on commit 3e4bfe1

Please sign in to comment.