Skip to content

Commit 1ed3836

Browse files
authored
added minimal example for raylib (#35)
Fixes #31
1 parent 04b2eb6 commit 1ed3836

File tree

7 files changed

+262
-0
lines changed

7 files changed

+262
-0
lines changed

examples/raylib/README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Raylib Example
2+
**Note**:
3+
Due to [an upstream bug](https://github.com/ziglang/zig/issues/20476), you will probably receive a warning (or multiple warnings if building for multiple targets) like this:
4+
```
5+
error: warning(link): unexpected LLD stderr:
6+
ld.lld: warning: <path-to-project>/.zig-cache/o/4227869d730f094811a7cdaaab535797/libraylib.a: archive member '<path-to-ndk>/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/35/libGLESv2.so' is neither ET_REL nor LLVM bitcode
7+
```
8+
You can ignore this error for now.
9+
10+
### Build, install to test one target against a local emulator and run
11+
12+
```sh
13+
zig build -Dtarget=x86_64-linux-android
14+
adb install ./zig-out/bin/raylib.apk
15+
adb shell am start -S -W -n com.zig.raylib/android.app.NativeActivity
16+
```
17+
18+
### Build and install for all supported Android targets
19+
20+
```sh
21+
zig build -Dandroid=true
22+
adb install ./zig-out/bin/raylib.apk
23+
```
24+
25+
### Build and run natively on your operating system
26+
27+
```sh
28+
zig build run
29+
```
30+
31+
### Uninstall your application
32+
33+
If installing your application fails with something like:
34+
```
35+
adb: failed to install ./zig-out/bin/raylib.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Existing package com.zig.raylib signatures do not match newer version; ignoring!]
36+
```
37+
38+
```sh
39+
adb uninstall "com.zig.raylib"
40+
```
41+
42+
### View logs of application
43+
44+
Powershell (app doesn't need to be running)
45+
```sh
46+
adb logcat | Select-String com.zig.raylib:
47+
```
48+
49+
Bash (app doesn't need running to be running)
50+
```sh
51+
adb logcat com.zig.raylib:D *:S
52+
```
53+
54+
Bash (app must be running, logs everything by the process including modules)
55+
```sh
56+
adb logcat --pid=`adb shell pidof -s com.zig.raylib`
57+
```
58+
59+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
package="com.zig.raylib">
5+
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
6+
<uses-sdk android:minSdkVersion="9" />
7+
8+
<application
9+
android:icon="@mipmap/ic_launcher"
10+
android:label="@string/app_name"
11+
android:hasCode="false"
12+
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
13+
tools:targetApi="29"
14+
android:alwaysRetainTaskState="true"
15+
android:launchMode="singleInstance"
16+
android:configChanges="layoutDirection|locale|orientation|uiMode|screenLayout|screenSize|smallestScreenSize|keyboard|keyboardHidden|navigation"
17+
>
18+
<activity
19+
android:name="android.app.NativeActivity"
20+
android:exported="true"
21+
android:label="@string/app_name">
22+
<meta-data android:name="android.app.lib_name" android:value="main"/>
23+
<intent-filter>
24+
<action android:name="android.intent.action.MAIN" />
25+
<category android:name="android.intent.category.LAUNCHER" />
26+
</intent-filter>
27+
</activity>
28+
</application>
29+
30+
</manifest>
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<resources>
3+
<!-- Pretty name of your app -->
4+
<string name="app_name">Zig Raylib</string>
5+
<!--
6+
This is required for the APK name. This identifies your app, Android will associate
7+
your signing key with this identifier and will prevent updates if the key changes.
8+
-->
9+
<string name="package_name">com.zig.raylib</string>
10+
</resources>

examples/raylib/build.zig

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
const android = @import("android");
2+
const std = @import("std");
3+
4+
//This is targeting android version 10 / API level 29.
5+
//Change the value here and in android/AndroidManifest.xml to target your desired API level
6+
const android_version: android.APILevel = .android10;
7+
const android_api = std.fmt.comptimePrint("{}", .{@intFromEnum(android_version)});
8+
const exe_name = "raylib";
9+
10+
pub fn build(b: *std.Build) void {
11+
const root_target = b.standardTargetOptions(.{});
12+
const optimize = b.standardOptimizeOption(.{});
13+
const android_targets = android.standardTargets(b, root_target);
14+
15+
var root_target_single = [_]std.Build.ResolvedTarget{root_target};
16+
const targets: []std.Build.ResolvedTarget = if (android_targets.len == 0)
17+
root_target_single[0..]
18+
else
19+
android_targets;
20+
21+
const android_apk: ?*android.APK = blk: {
22+
if (android_targets.len == 0) {
23+
break :blk null;
24+
}
25+
const android_tools = android.Tools.create(b, .{
26+
.api_level = android_version,
27+
.build_tools_version = "35.0.1",
28+
.ndk_version = "29.0.13113456",
29+
});
30+
const apk = android.APK.create(b, android_tools);
31+
32+
const key_store_file = android_tools.createKeyStore(android.CreateKey.example());
33+
apk.setKeyStore(key_store_file);
34+
apk.setAndroidManifest(b.path("android/AndroidManifest.xml"));
35+
apk.addResourceDirectory(b.path("android/res"));
36+
37+
break :blk apk;
38+
};
39+
40+
for (targets) |target| {
41+
const lib_mod = b.createModule(.{
42+
.root_source_file = b.path("src/main.zig"),
43+
.target = target,
44+
.optimize = optimize,
45+
});
46+
const lib = b.addLibrary(.{
47+
.linkage = .dynamic,
48+
.name = exe_name,
49+
.root_module = lib_mod,
50+
});
51+
lib.linkLibC();
52+
b.installArtifact(lib);
53+
54+
const android_ndk_path = if(android_apk) |apk| (b.fmt("{s}/ndk/{s}", .{ apk.tools.android_sdk_path, apk.tools.ndk_version })) else "";
55+
const raylib_dep = if (target.result.abi.isAndroid()) (
56+
b.dependency("raylib_zig", .{
57+
.target = target,
58+
.optimize = optimize,
59+
.android_api_version = @as([]const u8, android_api),
60+
.android_ndk = @as([]const u8, android_ndk_path),
61+
})) else (
62+
b.dependency("raylib_zig", .{
63+
.target = target,
64+
.optimize = optimize,
65+
.shared = true
66+
}));
67+
const raylib_artifact = raylib_dep.artifact("raylib");
68+
lib.linkLibrary(raylib_artifact);
69+
const raylib_mod = raylib_dep.module("raylib");
70+
lib.root_module.addImport("raylib", raylib_mod);
71+
72+
if (target.result.abi.isAndroid()) {
73+
const apk: *android.APK = android_apk orelse @panic("Android APK should be initialized");
74+
const android_dep = b.dependency("android", .{
75+
.optimize = optimize,
76+
.target = target,
77+
});
78+
lib.root_module.linkSystemLibrary("android", .{ .preferred_link_mode = .dynamic });
79+
lib.root_module.addImport("android", android_dep.module("android"));
80+
81+
const native_app_glue_dir: std.Build.LazyPath = .{ .cwd_relative = b.fmt("{s}/sources/android/native_app_glue", .{android_ndk_path}) };
82+
lib.root_module.addCSourceFile(.{ .file = native_app_glue_dir.path(b, "android_native_app_glue.c") });
83+
lib.root_module.addIncludePath(native_app_glue_dir);
84+
85+
lib.root_module.linkSystemLibrary("log", .{ .preferred_link_mode = .dynamic });
86+
apk.addArtifact(lib);
87+
} else {
88+
const exe = b.addExecutable(.{ .name = exe_name, .optimize = optimize, .root_module = lib_mod });
89+
b.installArtifact(exe);
90+
91+
const run_exe = b.addRunArtifact(exe);
92+
const run_step = b.step("run", "Run the application");
93+
run_step.dependOn(&run_exe.step);
94+
}
95+
}
96+
if (android_apk) |apk| {
97+
apk.installApk();
98+
}
99+
}

examples/raylib/build.zig.zon

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
.{
2+
.name = .raylib,
3+
.version = "0.0.0",
4+
.minimum_zig_version = "0.14.0",
5+
.fingerprint = 0x13035e5cf42e313f,
6+
.dependencies = .{
7+
.raylib_zig = .{
8+
.url = "git+https://github.com/lumenkeyes/raylib-zig#b00d4c2b973665e3a88c2565b6cd63c56d0173c2",
9+
.hash = "raylib_zig-5.6.0-dev-KE8REPwqBQC35iWa2sFblBUNWkTlEi1gjit9dtyOLu_b"
10+
},
11+
.android = .{ .path = "../.." },
12+
},
13+
.paths = .{
14+
"build.zig",
15+
"build.zig.zon",
16+
"src",
17+
},
18+
}

examples/raylib/src/main.zig

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const std = @import("std");
2+
const builtin = @import("builtin");
3+
const android = @import("android");
4+
const rl = @import("raylib");
5+
6+
pub fn main() void {
7+
const screenWidth = 800;
8+
const screenHeight = 450;
9+
rl.initWindow(screenWidth, screenHeight, "raylib-zig [core] example - basic window");
10+
defer rl.closeWindow();
11+
rl.setTargetFPS(60);
12+
while (!rl.windowShouldClose()) {
13+
rl.beginDrawing();
14+
defer rl.endDrawing();
15+
16+
rl.clearBackground(.white);
17+
18+
rl.drawText("Congrats! You created your first window!", 190, 200, 20, .light_gray);
19+
}
20+
}
21+
22+
/// custom panic handler for Android
23+
pub const panic = if (builtin.abi.isAndroid())
24+
android.panic
25+
else
26+
std.debug.FullPanic(std.debug.defaultPanic);
27+
28+
/// custom standard options for Android
29+
pub const std_options: std.Options = if (builtin.abi.isAndroid())
30+
.{
31+
.logFn = android.logFn,
32+
}
33+
else
34+
.{};
35+
36+
comptime {
37+
if (builtin.abi.isAndroid()) {
38+
// Setup exported C-function as defined in AndroidManifest.xml
39+
// ie. <meta-data android:name="android.app.lib_name" android:value="main"/>
40+
@export(&androidMain, .{ .name = "main" });
41+
}
42+
}
43+
44+
fn androidMain() callconv(.c) c_int {
45+
return std.start.callMain();
46+
}

0 commit comments

Comments
 (0)