Skip to content

Commit aa7d68d

Browse files
Improve asset directory to support generated directories (#67)
**Changes** - Update asset and resources directory to automatically recursively add each file in a sub-folder as a file dependency to the run action. - Fix SDL2 example being broken after previous version bump on Zig 0.15.2 **Testing completed** - SDL2 example with Zig 0.15.2 on Linux via Android Studio <img width="340" height="952" alt="image" src="https://github.com/user-attachments/assets/36c85ce8-4fa5-4a84-8d64-25bb576f48b4" /> Fixes #66
1 parent 44bb4df commit aa7d68d

5 files changed

Lines changed: 91 additions & 28 deletions

File tree

examples/sdl2/build.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ pub fn build(b: *std.Build) void {
3737
const key_store_file = android_sdk.createKeyStore(.example);
3838
apk.setKeyStore(key_store_file);
3939
apk.setAndroidManifest(b.path("android/AndroidManifest.xml"));
40+
41+
const generated_asset_dir = b.addNamedWriteFiles("android_asset_directory");
42+
_ = generated_asset_dir.addCopyFile(b.path("src/zig.bmp"), "zig.bmp");
43+
apk.addAssetDirectory(generated_asset_dir.getDirectory());
4044
apk.addResourceDirectory(b.path("android/res"));
4145

4246
// Add Java files

examples/sdl2/src/sdl-zig-demo.zig

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,12 @@ pub fn main() !void {
6969
};
7070
defer sdl.SDL_DestroyRenderer(renderer);
7171

72-
const zig_bmp = @embedFile("zig.bmp");
73-
const rw = sdl.SDL_RWFromConstMem(zig_bmp, zig_bmp.len) orelse {
74-
log.info("Unable to get RWFromConstMem: {s}", .{sdl.SDL_GetError()});
75-
return error.SDLInitializationFailed;
76-
};
72+
const rw = sdl.SDL_RWFromFile(if (builtin.abi.isAndroid())
73+
// For Android, we setup the build to dynamically add "zig.bmp" to the Android assets folder
74+
// so it's accessible without "src/" prefix
75+
"zig.bmp"
76+
else
77+
"src/zig.bmp", "rb");
7778
defer assert(sdl.SDL_RWclose(rw) == 0);
7879

7980
const zig_surface = sdl.SDL_LoadBMP_RW(rw, 0) orelse {

examples/sdl2/third-party/sdl2/build.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ const generic_src_files = [_][]const u8{
266266
"src/stdlib/SDL_malloc.c",
267267
"src/stdlib/SDL_mslibc.c",
268268
"src/stdlib/SDL_qsort.c",
269-
//"src/stdlib/SDL_stdmod.c", // Removed between 2.32.2 and 2.32.10
269+
"src/stdlib/SDL_stdlib.c", // "src/stdlib/SDL_stdmod.c", // Renamed between 2.32.2 and 2.32.10
270270
"src/stdlib/SDL_string.c",
271271
"src/stdlib/SDL_strtokr.c",
272272
"src/thread/SDL_thread.c",
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//! DirectoryFileInput adds files within a directory to the dependencies of the given Step.Run command
2+
//! This is required so that generated directories will work.
3+
4+
const std = @import("std");
5+
const androidbuild = @import("androidbuild.zig");
6+
const builtin = @import("builtin");
7+
const Build = std.Build;
8+
const Step = Build.Step;
9+
const Run = Build.Step.Run;
10+
const LazyPath = Build.LazyPath;
11+
const fs = std.fs;
12+
const mem = std.mem;
13+
const assert = std.debug.assert;
14+
15+
step: Step,
16+
17+
/// Runner to update
18+
run: *Build.Step.Run,
19+
20+
/// The directory that will contain the files to glob
21+
dir: LazyPath,
22+
23+
pub fn create(owner: *std.Build, run: *Run, dir: LazyPath) void {
24+
const self = owner.allocator.create(DirectoryFileInput) catch @panic("OOM");
25+
self.* = .{
26+
.step = Step.init(.{
27+
.id = .custom,
28+
.name = androidbuild.runNameContext("directory-file-input"),
29+
.owner = owner,
30+
.makeFn = make,
31+
}),
32+
.run = run,
33+
.dir = dir,
34+
};
35+
// Run step relies on DirectoryFileInput finishing
36+
run.step.dependOn(&self.step);
37+
// If dir is generated then this will wait for that dir to generate
38+
dir.addStepDependencies(&self.step);
39+
}
40+
41+
fn make(step: *Step, _: Build.Step.MakeOptions) !void {
42+
const b = step.owner;
43+
const arena = b.allocator;
44+
const self: *DirectoryFileInput = @fieldParentPtr("step", step);
45+
46+
const run = self.run;
47+
const dir_path = self.dir.getPath3(b, step);
48+
49+
// NOTE(jae): 2025-07-23
50+
// As of Zig 0.15.0-dev.1092+d772c0627, package_name_path.openDir("") is not possible as it assumes you're appending a sub-path
51+
var dir = if (builtin.zig_version.major == 0 and builtin.zig_version.minor <= 15)
52+
try dir_path.root_dir.handle.openDir(dir_path.sub_path, .{ .iterate = true })
53+
else
54+
try dir_path.root_dir.handle.openDir(b.graph.io, dir_path.sub_path, .{ .iterate = true });
55+
defer if (builtin.zig_version.major == 0 and builtin.zig_version.minor <= 15)
56+
dir.close()
57+
else
58+
dir.close(b.graph.io);
59+
60+
var walker = try dir.walk(arena);
61+
defer walker.deinit();
62+
while (if (builtin.zig_version.major == 0 and builtin.zig_version.minor <= 15)
63+
try walker.next()
64+
else
65+
try walker.next(b.graph.io)) |entry|
66+
{
67+
if (entry.kind != .file) continue;
68+
69+
// Add file as dependency to run command
70+
run.addFileInput(LazyPath{
71+
.cwd_relative = try dir_path.root_dir.join(b.allocator, &.{ dir_path.sub_path, entry.path }),
72+
});
73+
}
74+
}
75+
76+
const DirectoryFileInput = @This();

src/androidbuild/apk.zig

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33
const androidbuild = @import("androidbuild.zig");
44
const Sdk = @import("tools.zig");
55
const BuiltinOptionsUpdate = @import("builtin_options_update.zig");
6+
const DirectoryFileInput = @import("DirectoryFileInput.zig");
67

78
const Ndk = @import("Ndk.zig");
89
const BuildTools = @import("BuildTools.zig");
@@ -362,28 +363,8 @@ fn doInstallApk(apk: *Apk) std.mem.Allocator.Error!*Step.InstallFile {
362363
.directory => |asset_dir_path| {
363364
aapt2link.addArg("-A");
364365
aapt2link.addDirectoryArg(asset_dir_path.source);
365-
366-
var asset_dir = (
367-
if (builtin.zig_version.major == 0 and builtin.zig_version.minor <= 15)
368-
asset_dir_path.source.getPath3(b, null).openDir("", .{ .iterate = true })
369-
else
370-
(asset_dir_path.source.getPath4(b, null) catch |err| @panic(@errorName(err))).openDir(b.graph.io, "", .{ .iterate = true })
371-
) catch |err| @panic(@errorName(err));
372-
373-
defer if (builtin.zig_version.major == 0 and builtin.zig_version.minor <= 15) asset_dir.close() else asset_dir.close(b.graph.io);
374-
375-
var walker = try asset_dir.walk(b.allocator);
376-
defer walker.deinit();
377-
378-
while ((
379-
if (builtin.zig_version.major == 0 and builtin.zig_version.minor <= 15)
380-
walker.next()
381-
else
382-
walker.next(b.graph.io)
383-
) catch |err| @panic(@errorName(err))) |entry| {
384-
if (entry.kind == .file) aapt2link.addFileInput(try asset_dir_path.source.join(b.allocator, entry.path));
385-
}
386-
}
366+
DirectoryFileInput.create(b, aapt2link, asset_dir_path.source);
367+
},
387368
}
388369
}
389370

@@ -404,6 +385,7 @@ fn doInstallApk(apk: *Apk) std.mem.Allocator.Error!*Step.InstallFile {
404385
// add directory
405386
aapt2compile.addArg("--dir");
406387
aapt2compile.addDirectoryArg(resource_directory.source);
388+
DirectoryFileInput.create(b, aapt2compile, resource_directory.source);
407389

408390
aapt2compile.addArg("-o");
409391
const resources_flat_zip_file = aapt2compile.addOutputFileArg("resource_dir.flat.zip");

0 commit comments

Comments
 (0)