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
22 changes: 1 addition & 21 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ jobs:
include:
- os: "ubuntu-22.04"
- os: "windows-latest"
- os: "macos-12" # x86_64
- os: "macos-14" # arm64 as per table: https://github.com/actions/runner-images/blob/8a1eeaf6ac70c66f675a04078d1a7222edd42008/README.md#available-images

runs-on: ${{matrix.os}}
Expand All @@ -36,7 +35,7 @@ jobs:
- name: Setup Android SDK
uses: android-actions/setup-android@v3
with:
packages: 'tools platform-tools platforms;android-35 build-tools;35.0.0 ndk;27.0.12077973'
packages: 'tools platform-tools platforms;android-35 build-tools;35.0.0 ndk;29.0.13113456'

- name: Setup Zig 0.13.0
# note(jae): 2024-09-15
Expand All @@ -53,22 +52,3 @@ jobs:
- name: Build SDL2 Example (Zig 0.13.0)
run: zig build -Dandroid=true --verbose
working-directory: examples/sdl2

- name: Setup Zig Nightly
uses: mlugg/setup-zig@v1
with:
version: "master"

- name: Build Minimal Example (Zig Nightly)
run: zig build -Dandroid=true --verbose
working-directory: examples/minimal

- name: Build SDL2 Example (Zig Nightly)
# "zig build -Dandroid=true" fails for 0.14.0-dev.1632
#
# android/sdk/ndk/27.0.12077973/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/android/hardware_buffer.h:322:42:
# error: expression is not an integral constant expression
#
# See: https://github.com/silbinarywolf/zig-android-sdk/actions/runs/10979711793/job/30484520174?pr=5#step:10:30
run: zig build -Dtarget=x86_64-linux-android --verbose
working-directory: examples/sdl2
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ zig build -Dandroid=true
```zig
// This is an overly simplified example to give you the gist
// of how this library works, see: examples/minimal/build.zig
const android = @import("zig-android-sdk");
const android = @import("android");
pub fn build(b: *std.Build) !void {
const android_tools = android.Tools.create(b, ...);
Expand Down Expand Up @@ -52,7 +52,7 @@ Add the following to your build.zig.zon file and run `zig build`.
```zig
.{
.dependencies = .{
.@"zig-android-sdk" = .{
.android = .{
.path = "https://github.com/silbinarywolf/zig-android-sdk/archive/REPLACE_WITH_WANTED_COMMIT.tar.gz",
// .hash = REPLACE_WITH_HASH_FROM_BUILD_ERROR
},
Expand Down
4 changes: 3 additions & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
.{
.name = "zig-android-sdk",
.name = "android",
.version = "0.1.0",
.dependencies = .{},
.paths = .{
"build.zig",
"build.zig.zon",
"src",
},
.minimum_zig_version = "0.13.0",
.fingerprint = 0x92bcb62d42fb2cee,
}
8 changes: 4 additions & 4 deletions examples/minimal/build.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
const android = @import("zig-android-sdk");
const android = @import("android");

pub fn build(b: *std.Build) void {
const exe_name: []const u8 = "minimal";
Expand All @@ -22,7 +22,7 @@ pub fn build(b: *std.Build) void {
const android_tools = android.Tools.create(b, .{
.api_level = .android15,
.build_tools_version = "35.0.0",
.ndk_version = "27.0.12077973",
.ndk_version = "29.0.13113456",
});
const apk = android.APK.create(b, android_tools);

Expand Down Expand Up @@ -52,9 +52,9 @@ pub fn build(b: *std.Build) void {
// if building as library for Android, add this target
// NOTE: Android has different CPU targets so you need to build a version of your
// code for x86, x86_64, arm, arm64 and more
if (target.result.isAndroid()) {
if (target.result.abi == .android) {
const apk: *android.APK = android_apk orelse @panic("Android APK should be initialized");
const android_dep = b.dependency("zig-android-sdk", .{
const android_dep = b.dependency("android", .{
.optimize = optimize,
.target = target,
});
Expand Down
3 changes: 2 additions & 1 deletion examples/minimal/build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.name = "minimal",
.version = "0.0.0",
.dependencies = .{
.@"zig-android-sdk" = .{
.android = .{
.path = "../..",
},
},
Expand All @@ -11,4 +11,5 @@
"build.zig.zon",
"src",
},
.fingerprint = 0x4037f28ad1eb4832,
}
1 change: 0 additions & 1 deletion examples/sdl2/android/src/ZigSDLActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ public class ZigSDLActivity extends SDLActivity {
// @Override
// protected String[] getLibraries() {
// return new String[] {
// "hidapi",
// "SDL2",
// // "SDL2_image",
// // "SDL2_mixer",
Expand Down
27 changes: 15 additions & 12 deletions examples/sdl2/build.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
const android = @import("zig-android-sdk");
const android = @import("android");

pub fn build(b: *std.Build) void {
const root_target = b.standardTargetOptions(.{});
Expand All @@ -21,7 +21,16 @@ pub fn build(b: *std.Build) void {
const android_tools = android.Tools.create(b, .{
.api_level = .android15,
.build_tools_version = "35.0.0",
.ndk_version = "27.0.12077973",
.ndk_version = "29.0.13113456",
// NOTE(jae): 2025-03-09
// Previously this example used 'ndk' "27.0.12077973".
//
// However that has issues with the latest SDL2 version when including 'hardware_buffer.h'
// for 32-bit builds.
//
// - AHARDWAREBUFFER_USAGE_FRONT_BUFFER = 1UL << 32
// - ndk/27.0.12077973/toolchains/llvm/prebuilt/{OS}-x86_64/sysroot/usr/include/android/hardware_buffer.h:322:42:
// - error: expression is not an integral constant expression
});
const apk = android.APK.create(b, android_tools);

Expand All @@ -47,7 +56,7 @@ pub fn build(b: *std.Build) void {

for (targets) |target| {
const exe_name: []const u8 = "sdl-zig-demo";
var exe: *std.Build.Step.Compile = if (target.result.isAndroid()) b.addSharedLibrary(.{
var exe: *std.Build.Step.Compile = if (target.result.abi == .android) b.addSharedLibrary(.{
.name = exe_name,
.root_source_file = b.path("src/sdl-zig-demo.zig"),
.target = target,
Expand All @@ -65,7 +74,7 @@ pub fn build(b: *std.Build) void {
.optimize = .ReleaseFast,
.target = target,
});
if (target.result.os.tag == .linux and !target.result.isAndroid()) {
if (target.result.os.tag == .linux and target.result.abi != .android) {
// The SDL package doesn't work for Linux yet, so we rely on system
// packages for now.
exe.linkSystemLibrary("SDL2");
Expand All @@ -75,22 +84,16 @@ pub fn build(b: *std.Build) void {
exe.linkLibrary(sdl_lib);
}

// NOTE(jae): 2024-09-22
// Load additional dynamic libraries that SDLActivity.java loads such as hidapi
if (target.result.isAndroid()) {
exe.linkLibrary(sdl_dep.artifact("hidapi"));
}

const sdl_module = sdl_dep.module("sdl");
exe.root_module.addImport("sdl", sdl_module);
}

// if building as library for Android, add this target
// NOTE: Android has different CPU targets so you need to build a version of your
// code for x86, x86_64, arm, arm64 and more
if (target.result.isAndroid()) {
if (target.result.abi == .android) {
const apk: *android.APK = android_apk orelse @panic("Android APK should be initialized");
const android_dep = b.dependency("zig-android-sdk", .{
const android_dep = b.dependency("android", .{
.optimize = optimize,
.target = target,
});
Expand Down
5 changes: 3 additions & 2 deletions examples/sdl2/build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
.{
.name = "minimal",
.name = "sdl2",
.version = "0.0.0",
.dependencies = .{
.@"zig-android-sdk" = .{
.android = .{
.path = "../..",
},
.sdl2 = .{
Expand All @@ -14,4 +14,5 @@
"build.zig.zon",
"src",
},
.fingerprint = 0x168fc6b9a7d0df48,
}
167 changes: 84 additions & 83 deletions examples/sdl2/third-party/sdl2/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -72,89 +72,88 @@ pub fn build(b: *std.Build) !void {
lib.linkFramework("CoreHaptics");
},
else => {
switch (target.result.abi) {
.android => {
lib.root_module.addCSourceFiles(.{
.root = sdl_path,
.files = &android_src_files,
});

// This is needed for "src/render/opengles/SDL_render_gles.c" to compile
lib.root_module.addCMacro("GL_GLEXT_PROTOTYPES", "1");

// Add Java files to dependency
const java_dir = sdl_dep.path("android-project/app/src/main/java/org/libsdl/app");
const java_files: []const []const u8 = &.{
"SDL.java",
"SDLSurface.java",
"SDLActivity.java",
"SDLAudioManager.java",
"SDLControllerManager.java",
"HIDDevice.java",
"HIDDeviceUSB.java",
"HIDDeviceManager.java",
"HIDDeviceBLESteamController.java",
};
const java_write_files = b.addNamedWriteFiles("sdljava");
for (java_files) |java_file_basename| {
_ = java_write_files.addCopyFile(java_dir.path(b, java_file_basename), java_file_basename);
}

// https://github.com/libsdl-org/SDL/blob/release-2.30.6/Android.mk#L82C62-L82C69
lib.linkSystemLibrary("dl");
lib.linkSystemLibrary("GLESv1_CM");
lib.linkSystemLibrary("GLESv2");
lib.linkSystemLibrary("OpenSLES");
lib.linkSystemLibrary("log");
lib.linkSystemLibrary("android");

// SDLActivity.java's getMainFunction defines the entrypoint as "SDL_main"
// So your main / root file will need something like this for Android
//
// fn android_sdl_main() callconv(.C) void {
// _ = std.start.callMain();
// }
// comptime {
// if (builtin.abi == .android) @export(android_sdl_main, .{ .name = "SDL_main", .linkage = .strong });
// }

const use_hidapi = true;
if (!use_hidapi) {
lib.root_module.addCMacro("SDL_HIDAPI_DISABLED", "");
} else {
// NOTE(jae): 2024-09-22
// Build settings taken from: src/hidapi/android/jni/Android.mk
// SDLActivity.java by default expects to be able to load this library.
const hidapi_lib = b.addSharedLibrary(.{
.name = "hidapi",
.target = target,
.optimize = optimize,
.link_libc = true,
});
hidapi_lib.addIncludePath(sdl_include_path);
hidapi_lib.root_module.addCSourceFiles(.{
.root = sdl_path,
.files = &[_][]const u8{
"src/hidapi/android/hid.cpp",
},
.flags = &.{"-std=c++11"},
});
hidapi_lib.linkSystemLibrary("log");
hidapi_lib.linkLibCpp();
lib.linkLibrary(hidapi_lib);
b.installArtifact(hidapi_lib);
}
},
else => {
const config_header = b.addConfigHeader(.{
.style = .{ .cmake = sdl_include_path.path(b, "SDL_config.h.cmake") },
.include_path = "SDL/SDL_config.h",
}, .{});
sdl_config_header = config_header;

lib.addConfigHeader(config_header);
lib.installConfigHeader(config_header);
},
if (target.result.abi == .android) {
lib.root_module.addCSourceFiles(.{
.root = sdl_path,
.files = &android_src_files,
});

// This is needed for "src/render/opengles/SDL_render_gles.c" to compile
lib.root_module.addCMacro("GL_GLEXT_PROTOTYPES", "1");

// Add Java files to dependency
const java_dir = sdl_dep.path("android-project/app/src/main/java/org/libsdl/app");
const java_files: []const []const u8 = &.{
"SDL.java",
"SDLSurface.java",
"SDLActivity.java",
"SDLAudioManager.java",
"SDLControllerManager.java",
"HIDDevice.java",
"HIDDeviceUSB.java",
"HIDDeviceManager.java",
"HIDDeviceBLESteamController.java",
};
const java_write_files = b.addNamedWriteFiles("sdljava");
for (java_files) |java_file_basename| {
_ = java_write_files.addCopyFile(java_dir.path(b, java_file_basename), java_file_basename);
}

// https://github.com/libsdl-org/SDL/blob/release-2.30.6/Android.mk#L82C62-L82C69
lib.linkSystemLibrary("dl");
lib.linkSystemLibrary("GLESv1_CM");
lib.linkSystemLibrary("GLESv2");
lib.linkSystemLibrary("OpenSLES");
lib.linkSystemLibrary("log");
lib.linkSystemLibrary("android");

// SDLActivity.java's getMainFunction defines the entrypoint as "SDL_main"
// So your main / root file will need something like this for Android
//
// fn android_sdl_main() callconv(.C) void {
// _ = std.start.callMain();
// }
// comptime {
// if (builtin.abi == .android) @export(android_sdl_main, .{ .name = "SDL_main", .linkage = .strong });
// }

const hidapi_lib = b.addStaticLibrary(.{
.name = "hidapi",
.target = target,
.optimize = optimize,
.link_libc = true,
});
hidapi_lib.addIncludePath(sdl_include_path);

// Avoid linking with linkLibCpp() as that causes issues as Zig 0.14.0 attempts to mix
// its own C++ includes with those auto-included by the Zig Android SDK.
//
// However, not linking c++ means when loading on X86_64 systems, you get
// unresolved symbol "_Unwind_Resume" when SDL2 is loaded, so to workaround that
// we link the "unwind" library
hidapi_lib.linkSystemLibrary("unwind");

// NOTE(jae): 2024-09-22
// Build settings taken from: SDL2-2.32.2/src/hidapi/android/jni/Android.mk
// SDLActivity.java by default expects to be able to load this library
hidapi_lib.root_module.linkSystemLibrary("log", .{});
hidapi_lib.root_module.addCSourceFiles(.{
.root = sdl_path,
.files = &[_][]const u8{
"src/hidapi/android/hid.cpp",
},
.flags = &.{"-std=c++11"},
});
lib.linkLibrary(hidapi_lib);
} else {
const config_header = b.addConfigHeader(.{
.style = .{ .cmake = sdl_include_path.path(b, "SDL_config.h.cmake") },
.include_path = "SDL/SDL_config.h",
}, .{});
sdl_config_header = config_header;

lib.addConfigHeader(config_header);
lib.installConfigHeader(config_header);
}
},
}
Expand All @@ -167,6 +166,8 @@ pub fn build(b: *std.Build) !void {
b.installArtifact(lib);

var module = b.addModule("sdl", .{
.target = b.graph.host,
.optimize = .ReleaseFast,
.root_source_file = b.path("src/sdl.zig"),
});
if (sdl_config_header) |config_header| {
Expand Down
Loading