Skip to content
Open
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
75 changes: 73 additions & 2 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,22 @@ pub fn build(b: *std.Build) !void {
,
) orelse .static;

const main_callbacks = b.option(bool, "main_callbacks",
\\build SDL3_main to enter the app through SDL_AppInit/Iterate/Event/Quit rather
\\than a classic SDL_main, defaults to false
) orelse false;

const can_san = target.result.os.tag != .ios;

// Cross-compiling to a target whose SDK isn't bundled with Zig (iOS, Android) needs the
// SDK's headers/frameworks/libs passed in explicitly. Scoped to the SDL library only, unlike
// `--sysroot` this does not re-roots paths across the whole build graph.
const system_paths: SystemPaths = .{
// On Apple, if paths are not passed explicitly then fall back to the SDK found via `xcrun`.
const system_paths = withAppleSdkFallback(b, target.result, .{
.include = b.option(std.Build.LazyPath, "include_path", "SDK include dir, e.g. $(xcrun --sdk iphoneos --show-sdk-path)/usr/include or <ndk sysroot>/usr/include"),
.framework = b.option(std.Build.LazyPath, "framework_path", "SDK framework dir, e.g. $(xcrun --sdk iphoneos --show-sdk-path)/System/Library/Frameworks"),
.library = b.option(std.Build.LazyPath, "library_path", "SDK library dir, e.g. $(xcrun --sdk iphoneos --show-sdk-path)/usr/lib"),
};
});

// Get the SO version. This is the same as the SDL version, but the major version is elided
// since it's baked into the name. This mirrors the official build process.
Expand All @@ -73,6 +81,7 @@ pub fn build(b: *std.Build) !void {
.target = target,
.optimize = optimize,
.link_libc = true,
.sanitize_c = if (can_san) null else .off,
}),
.linkage = linkage,
.version = sdl_so_version,
Expand Down Expand Up @@ -103,6 +112,24 @@ pub fn build(b: *std.Build) !void {
.flags = flags,
});

const main_lib = b.addLibrary(.{
.name = "SDL3_main",
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
.link_libc = true,
.sanitize_c = if (can_san) null else .off,
}),
.linkage = .static,
});
main_lib.root_module.addIncludePath(upstream.path("include"));
if (main_callbacks) {
main_lib.root_module.addCMacro("SDL_MAIN_USE_CALLBACKS", "1");
}
main_lib.root_module.addCSourceFile(.{ .file = b.path("src/sdl_main.c") });
addSystemPathsToModule(b, main_lib.root_module, system_paths);
b.installArtifact(main_lib);

if (default_target_config) {
const build_config_h = b.addConfigHeader(.{
.style = .{ .cmake = upstream.path("include/build_config/SDL_build_config.h.cmake") },
Expand Down Expand Up @@ -152,6 +179,7 @@ pub fn build(b: *std.Build) !void {
translate_c.defineCMacro("USING_GENERATED_CONFIG_H", "1");
translate_c.addIncludePath(upstream.path("include"));
translate_c.addIncludePath(upstream.path("src/video/khronos"));
addSystemPathsToTranslateC(b, translate_c, system_paths);
const module = translate_c.addModule("sdl3");
module.linkLibrary(lib);

Expand Down Expand Up @@ -206,3 +234,46 @@ pub fn addDepIncludePath(
lib.root_module.addIncludePath(dep.path(sub_path));
}
}

/// Fill in any of `paths` from the SDK found with `xcrun`. Left unset outside Apple or if no SDK is found.
pub fn withAppleSdkFallback(b: *std.Build, target: std.Target, paths: SystemPaths) SystemPaths {
if (!target.os.tag.isDarwin()) return paths;
if (paths.include != null and paths.framework != null) return paths;

const sdk = std.zig.system.darwin.getSdk(b.allocator, b.graph.io, &target) orelse return paths;

return .{
.include = paths.include orelse .{ .cwd_relative = b.pathJoin(&.{ sdk, "usr/include" }) },
.framework = paths.framework orelse .{ .cwd_relative = b.pathJoin(&.{ sdk, "System/Library/Frameworks" }) },
.library = paths.library orelse .{ .cwd_relative = b.pathJoin(&.{ sdk, "usr/lib" }) },
};
}

fn addSystemPathsToModule(b: *std.Build, module: *std.Build.Module, paths: SystemPaths) void {
if (paths.include) |p| module.addSystemIncludePath(p);
if (paths.framework) |p| {
module.addSystemFrameworkPath(p);
module.addSystemFrameworkPath(p.dirname().path(b, "SubFrameworks"));
}
if (paths.library) |p| module.addLibraryPath(p);
}

fn addSystemPathsToTranslateC(b: *std.Build, translate_c: *std.Build.Step.TranslateC, paths: SystemPaths) void {
if (paths.include) |p| translate_c.addSystemIncludePath(p);
if (paths.framework) |p| {
translate_c.addSystemFrameworkPath(p);
translate_c.addSystemFrameworkPath(p.dirname().path(b, "SubFrameworks"));
}
}

pub fn addAppleSdkPathsToModule(b: *std.Build, target: std.Target, module: *std.Build.Module) void {
if (!target.os.tag.isDarwin()) return;

const sdk = std.zig.system.darwin.getSdk(b.allocator, b.graph.io, &target) orelse
@panic("Couldn't detect Apple SDK");

module.addSystemIncludePath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "usr/include" }) });
module.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "System/Library/Frameworks" }) });
module.addSystemFrameworkPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "System/Library/SubFrameworks" }) });
module.addLibraryPath(.{ .cwd_relative = b.pathJoin(&.{ sdk, "usr/lib" }) });
}
3 changes: 3 additions & 0 deletions src/sdl_main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#ifdef SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL_main.h>
#endif