Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# SPDX-FileCopyrightText: © 2025 Mark Delk <jethrodaniel@gmail.com>
#
# SPDX-License-Identifier: Zlib

name: ci

on: [pull_request]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: license check
uses: fsfe/reuse-action@v4

- name: setup zig
uses: mlugg/setup-zig@v2
with:
version: 0.14.1

- name: Install SDL dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y build-essential git make pkg-config cmake ninja-build gnome-desktop-testing libasound2-dev libpulse-dev libaudio-dev libjack-dev libsndio-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libxtst-dev libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev libpipewire-0.3-dev libwayland-dev libdecor-0-dev liburing-dev

- name: zig build
run: zig build --summary all

- name: Build SDL test programs
run: zig build --summary all sdl-test

- name: Build SDL example programs
run: zig build --summary all sdl-examples

- name: Build Zig examples
run: zig build --summary all zig-examples
15 changes: 0 additions & 15 deletions .github/workflows/reuse.yaml

This file was deleted.

8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SPDX-License-Identifier: Zlib

# SDL.zig

Build [SDL](https://github.com/libsdl-org/SDL) using [zig](https://ziglang.org) (version 0.13.0).
Build [SDL](https://github.com/libsdl-org/SDL) 3 using [zig](https://ziglang.org) (version 0.14.1).

Also includes

Expand All @@ -16,6 +16,10 @@ Also includes

TODO

## Alternatives / anti-endorsement

You'll probably want to use https://github.com/castholm/SDL instead, it's more complete and better maintained.

## Tests

Build all of SDL's test programs:
Expand All @@ -28,7 +32,7 @@ Build and run a specific SDL test:

```
zig build sdl-test-testaudiohotplug
zig build sdl-test-testcamera -- --camera 'Razer Kiyo'
zig build sdl-test-testcamera
```

## Examples
Expand Down
137 changes: 80 additions & 57 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,34 @@ pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});

const linkage = b.option(
std.builtin.LinkMode,
"linkage",
"`.static` or `.dynamic` (default is `.dynamic`)",
) orelse .dynamic;

const sdl_dep = b.dependency("sdl", .{});
const sdl_ttf_dep = b.dependency("sdl_ttf", .{});
const freetype_dep = b.dependency("freetype", .{});
const freetype_dep = b.dependency("freetype", .{
.linkage = linkage,
.optimize = optimize,
});
const wayland_scanner_dep = b.dependency("wayland_scanner", .{
.target = b.host,
.target = b.graph.host,
.optimize = .ReleaseFast,
});
const font_dep = b.dependency("fonts", .{});

//

const lib = b.addStaticLibrary(.{
const lib = b.addLibrary(.{
.name = "SDL3",
.target = target,
.optimize = optimize,
.strip = true,
.linkage = linkage,
.root_module = b.createModule(.{
.root_source_file = null,
.target = target,
.optimize = optimize,
}),
});
{
lib.addIncludePath(sdl_dep.path("src"));
Expand All @@ -41,12 +53,12 @@ pub fn build(b: *std.Build) !void {
.ReleaseFast, .ReleaseSmall, .ReleaseSafe => 0,
.Debug => 3,
};
lib.defineCMacro("SDL_ASSERT_LEVEL", b.fmt("{d}", .{SDL_ASSERT_LEVEL}));
lib.root_module.addCMacro("SDL_ASSERT_LEVEL", b.fmt("{d}", .{SDL_ASSERT_LEVEL}));

if (optimize != .Debug) {
lib.defineCMacro("NDEBUG", "1");
lib.defineCMacro("__FILE__", "\"__FILE__\"");
lib.defineCMacro("__LINE__", "0");
lib.root_module.addCMacro("NDEBUG", "1");
lib.root_module.addCMacro("__FILE__", "\"__FILE__\"");
lib.root_module.addCMacro("__LINE__", "0");
}

lib.linkLibC();
Expand All @@ -65,7 +77,7 @@ pub fn build(b: *std.Build) !void {
lib.linkSystemLibrary("version");
lib.linkSystemLibrary("oleaut32");
lib.linkSystemLibrary("ole32");
lib.defineCMacro("SDL_USE_BUILTIN_OPENGL_DEFINITIONS", "1");
lib.root_module.addCMacro("SDL_USE_BUILTIN_OPENGL_DEFINITIONS", "1");
},
.macos => {
lib.addCSourceFiles(.{
Expand All @@ -78,7 +90,7 @@ pub fn build(b: *std.Build) !void {
.files = &objective_c_src_files,
.flags = &.{"-fobjc-arc"},
});
lib.defineCMacro("SDL_USE_BUILTIN_OPENGL_DEFINITIONS", "1");
lib.root_module.addCMacro("SDL_USE_BUILTIN_OPENGL_DEFINITIONS", "1");

// TODO: re-check which frameworks are needed
lib.linkFramework("AudioToolbox");
Expand All @@ -94,14 +106,14 @@ pub fn build(b: *std.Build) !void {
lib.linkFramework("CoreVideo");
lib.linkFramework("ForceFeedback");
lib.linkFramework("Foundation");
lib.linkFrameworkWeak("GameController");
lib.linkFramework("GameController");
lib.linkFramework("IOKit");
lib.linkFrameworkWeak("Metal");
lib.linkFrameworkWeak("QuartzCore");
lib.linkFrameworkWeak("UniformTypeIdentifiers");
lib.linkFramework("Metal");
lib.linkFramework("QuartzCore");
lib.linkFramework("UniformTypeIdentifiers");
lib.linkSystemLibrary("objc");

const sdk = std.zig.system.darwin.getSdk(b.allocator, b.host.result) orelse
const sdk = std.zig.system.darwin.getSdk(b.allocator, b.graph.host.result) orelse
@panic("macOS SDK is missing");
lib.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) });
lib.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) });
Expand Down Expand Up @@ -345,8 +357,6 @@ pub fn build(b: *std.Build) !void {
.SDL_CAMERA_DRIVER_DUMMY = 1,
.SDL_CAMERA_DRIVER_V4L2 = 1,

// #define DYNAPI_NEEDS_DLOPEN 1

.SDL_USE_IME = 1,

.SDL_LIBDECOR_VERSION_MAJOR = 0,
Expand All @@ -361,12 +371,33 @@ pub fn build(b: *std.Build) !void {
.SDL_PROCESS_POSIX = 1,
.SDL_PROCESS_DUMMY = 1,
};
lib.installConfigHeader(b.addConfigHeader(.{
.style = .{ .cmake = sdl_dep.path(
"include/build_config/SDL_build_config.h.cmake",
) },

const fix_header_exe = b.addExecutable(.{
.name = "fix-header",
.root_module = b.createModule(.{
.root_source_file = b.path("src/fix_header.zig"),
.target = b.graph.host,
.optimize = optimize,
}),
});
const fix_header = b.addRunArtifact(fix_header_exe);
{
fix_header.addFileArg(sdl_dep.path("include/build_config/SDL_build_config.h.cmake"));
}
const fixed_header = fix_header.captureStdOut();

const installFixedHeader = b.addInstallFile(fixed_header, "fixed_header.h");

const config_header = b.addConfigHeader(.{
.style = .{ .cmake = fixed_header },
.include_path = "SDL_build_config.h",
}, values));
}, values);

// NOTE: needed to allow `b.addConfigHeader` to use a generated
// file with `.cmake`. (zig build system issue?)
config_header.step.dependOn(&installFixedHeader.step);

lib.installConfigHeader(config_header);

lib.addCSourceFiles(.{
.root = sdl_dep.path(""),
Expand All @@ -376,18 +407,22 @@ pub fn build(b: *std.Build) !void {

inline for (std.meta.fields(@TypeOf(values))) |f| {
const value = b.fmt("{any}", .{@field(values, f.name)});
lib.defineCMacro(f.name, value);
lib.root_module.addCMacro(f.name, value);
}

if (linkage == .dynamic) {
lib.setVersionScript(sdl_dep.path("src/dynapi/SDL_dynapi.sym"));
}

// SDL3_DYNAMIC_API=/my/actual/libSDL3.so.0
//
// If we want to _avoid_ dyn api, we can do so:
// lib.defineCMacro("SDL_dynapi_h_", "1");
// lib.defineCMacro("SDL_DYNAMIC_API", "0");
// lib.root_module.addCMacro("SDL_dynapi_h_", "1");
// lib.root_module.addCMacro("SDL_DYNAMIC_API", "0");

// Avoid
// SDL/include/build_config/SDL_build_config_minimal.h
lib.defineCMacro("SDL_build_config_minimal_h_", "1");
// lib.root_module.addCMacro("SDL_build_config_minimal_h_", "1");

//--

Expand Down Expand Up @@ -485,25 +520,14 @@ pub fn build(b: *std.Build) !void {
b.installArtifact(lib);
}

// needed to allow SDL_ttf to #include "SDL.h"
const sdl_for_libs = b.addStaticLibrary(.{
.name = "SDL3-for-libs",
.target = target,
.optimize = optimize,
.root_source_file = b.addWriteFiles().add("stub.c", ""),
.strip = true,
});
{
sdl_for_libs.addIncludePath(sdl_dep.path("include"));
sdl_for_libs.installHeadersDirectory(sdl_dep.path("include"), "", .{});
b.installArtifact(sdl_for_libs);
}

const SDL_ttf = b.addStaticLibrary(.{
const SDL_ttf = b.addLibrary(.{
.name = "SDL3_ttf",
.target = target,
.optimize = optimize,
.strip = true,
.linkage = linkage,
.root_module = b.createModule(.{
.root_source_file = null,
.target = target,
.optimize = optimize,
}),
});
{
SDL_ttf.addCSourceFiles(.{
Expand All @@ -521,16 +545,17 @@ pub fn build(b: *std.Build) !void {
SDL_ttf.installHeadersDirectory(sdl_ttf_dep.path("include/SDL3_ttf"), "SDL3_ttf", .{});

SDL_ttf.linkLibrary(freetype_dep.artifact("freetype"));
SDL_ttf.linkLibrary(lib);

if (target.result.os.tag == .macos) {
const sdk = std.zig.system.darwin.getSdk(b.allocator, b.host.result) orelse
const sdk = std.zig.system.darwin.getSdk(b.allocator, b.graph.host.result) orelse
@panic("macOS SDK is missing");
SDL_ttf.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) });
SDL_ttf.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) });
SDL_ttf.addLibraryPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/lib" }) });
}

SDL_ttf.linkLibrary(sdl_for_libs);
SDL_ttf.addIncludePath(sdl_dep.path("include"));

b.installArtifact(SDL_ttf);
}
Expand All @@ -545,7 +570,6 @@ pub fn build(b: *std.Build) !void {
\\});
\\pub const fonts = @import("fonts");
),
.link_libc = true,
});
{
module.linkLibrary(lib);
Expand Down Expand Up @@ -577,12 +601,11 @@ pub fn build(b: *std.Build) !void {
.target = target,
.root_source_file = b.path(b.fmt("src/{s}.zig", .{name})),
.optimize = optimize,
.strip = true,
});
exe.root_module.addImport("sdl", module);

if (target.result.os.tag == .macos) {
const sdk = std.zig.system.darwin.getSdk(b.allocator, b.host.result) orelse
const sdk = std.zig.system.darwin.getSdk(b.allocator, b.graph.host.result) orelse
@panic("macOS SDK is missing");
exe.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) });
exe.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) });
Expand Down Expand Up @@ -855,7 +878,7 @@ pub fn build(b: *std.Build) !void {
exe.linkLibrary(test_utils);

if (target.result.os.tag == .macos) {
const sdk = std.zig.system.darwin.getSdk(b.allocator, b.host.result) orelse
const sdk = std.zig.system.darwin.getSdk(b.allocator, b.graph.host.result) orelse
@panic("macOS SDK is missing");
exe.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) });
exe.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) });
Expand Down Expand Up @@ -928,7 +951,7 @@ pub fn build(b: *std.Build) !void {
exe.linkLibrary(lib);

if (target.result.os.tag == .macos) {
const sdk = std.zig.system.darwin.getSdk(b.allocator, b.host.result) orelse
const sdk = std.zig.system.darwin.getSdk(b.allocator, b.graph.host.result) orelse
@panic("macOS SDK is missing");
exe.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/include" }) });
exe.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/System/Library/Frameworks" }) });
Expand Down Expand Up @@ -1025,14 +1048,14 @@ const generic_src_files = [_][]const u8{
"src/gpu/vulkan/SDL_gpu_vulkan.c",

"src/haptic/SDL_haptic.c",
"src/haptic/dummy/SDL_syshaptic.c",
// "src/haptic/dummy/SDL_syshaptic.c",

"src/hidapi/SDL_hidapi.c",

"src/joystick/SDL_gamepad.c",
"src/joystick/SDL_joystick.c",
"src/joystick/SDL_steam_virtual_gamepad.c",
// "src/joystick/dummy/SDL_sysjoystick.c",
"src/joystick/dummy/SDL_sysjoystick.c",
"src/joystick/controller_type.c",
"src/joystick/virtual/SDL_virtualjoystick.c",

Expand Down Expand Up @@ -1078,7 +1101,7 @@ const generic_src_files = [_][]const u8{
"src/power/SDL_power.c",

"src/process/SDL_process.c",
"src/process/dummy/SDL_dummyprocess.c",
// "src/process/dummy/SDL_dummyprocess.c",

"src/render/SDL_d3dmath.c",
"src/render/SDL_render.c",
Expand Down Expand Up @@ -1154,7 +1177,7 @@ const generic_src_files = [_][]const u8{
"src/timer/SDL_timer.c",

"src/tray/SDL_tray_utils.c",
"src/tray/dummy/SDL_tray.c",
// "src/tray/dummy/SDL_tray.c",

"src/video/SDL_RLEaccel.c",
"src/video/SDL_blit.c",
Expand Down
Loading