zig
zig copied to clipboard
Set libc.txt file for a whole tree in build.zig
Targeting android, zig doesn't provide a libc, so my application needs to use a libc.txt file:
// my_app/build.zig:
const libc_file = b.path("android_libc.txt");
const harfbuzz_dep = b.dependency("harfbuzz", .{ .target = target, .optimize = optimize });
my_app.root_module.linkLibrary(harfbuzz_dep.artifact("harfbuzz");
my_app.setLibCFile(libc_file);
my_app.linkLibC();
// harfbuzz/build.zig:
const harfbuzz = b.addStaticLibrary(.{ .name = "harfbuzz", ... });
harfbuzz.linkLibC();
b.installArtifact(harfbuzz);
The problem is that the harfbuzz module does not get the libc file, and then fails to compile.
Allowing my_app to pass a libc file would require adding a LazyPath option to harfbuzz and using it to setLibCFile:
// my_app/build.zig:
const libc_file = b.path("android_libc.txt");
- const harfbuzz_dep = b.dependency("harfbuzz", .{ .target = target, .optimize = optimize });
+ const harfbuzz_dep = b.dependency("harfbuzz", .{ .target = target, .optimize = optimize, .libc = libc_file });
my_app.root_module.linkLibrary(harfbuzz_dep.artifact("harfbuzz");
my_app.setLibCFile(libc_file);
my_app.linkLibC();
// harfbuzz/build.zig:
+ const libc_file = b.option(std.Build.LazyPath, "libc", "libc file for compilation");
const harfbuzz = b.addStaticLibrary(.{ .name = "harfbuzz", ... });
+ if(libc_file) |f| harfbuzz.setLibCFile(f);
harfbuzz.linkLibC();
b.installArtifact(harfbuzz);
Currently, zero libraries in allyourcodebase do this. This seems like an unresonable ask for libraries to implement.
Proposal
Instead, libc.txt could be part of 'target', so it gets automatically passed down correctly without opt-in from dependencies.
// my_app/build.zig:
- const libc_file = b.path("android_libc.txt");
+ const target = b.resolveTargetQuery(.{
+ ...
+ .libc = b.path("android_libc.txt"),
+ });
const harfbuzz_dep = b.dependency("harfbuzz", .{ .target = target, .optimize = optimize });
my_app.root_module.linkLibrary(harfbuzz_dep.artifact("harfbuzz");
- my_app.setLibCFile(libc_file);
my_app.linkLibC();
// harfbuzz/build.zig:
const harfbuzz = b.addStaticLibrary(.{ .name = "harfbuzz", ... });
harfbuzz.linkLibC();
b.installArtifact(harfbuzz);
This way, no changes are needed to any dependencies. It could also possibly replace the --libc option in system integration options if libc file is added to the end of the target quadruple, like aarch64-linux-android-lp64-libc.txt or something
Alternatives
- Using
--libcto set the libc file for the whole build could maybe work, but any tools which want to run on the host system (.target = b.resolveTargetQuery(.{})+b.addRunArtifact()) get their libc file replaced which makes them fail to build. - Update every dependency to add a
libcoption, like described above. - Currently, I'm using a hack where I explore the
b.graph.dependency_cache, find every installed artifact, and set the libc file on each one: https://github.com/pfgithub/blockeditor/blob/9c4bf03fe706e3cf679b8ff41dd626637807eb74/packages/beui_impl_android/build.zig#L135-L143 b.linkLibC()->b.linkLibrary(b.standardLibCOption(.{}))& update allb.dependency()to.{ .target, .optimize, .libc = b.standardLibCOption(.{}) }- Something else?
It appears libc_file can be set manually on a std.Build as well to achieve this, but that only accepts a []const u8 and not a LazyPath. It might be easier in the short term to change that to a lazy path?
It appears
libc_filecan be set manually on astd.Buildas well to achieve this, but that only accepts a[]const u8and not a LazyPath. It might be easier in the short term to change that to a lazy path?
what values are you setting in your libc file to work for android?
@coffeebe4code Mine gets the values from cmake from an android build: https://github.com/pfgithub/blockeditor/blob/5b5e65877d2915387fb07c51f9c8d7598ba3b49c/packages/android/Aztest/app/src/main/cpp/CMakeLists.txt#L17-L24
And then it uses those in build.zig to generate a libc.txt file: https://github.com/pfgithub/blockeditor/blob/5b5e65877d2915387fb07c51f9c8d7598ba3b49c/packages/beui_impl_android/build.zig#L177-L184
And then it does some hacky stuff to update the dependency tree so every target building for *-android has the correct libc.txt file: https://github.com/pfgithub/blockeditor/blob/5b5e65877d2915387fb07c51f9c8d7598ba3b49c/packages/beui_impl_android/build.zig#L136-L162
@coffeebe4code Mine gets the values from cmake from an android build: https://github.com/pfgithub/blockeditor/blob/5b5e65877d2915387fb07c51f9c8d7598ba3b49c/packages/android/Aztest/app/src/main/cpp/CMakeLists.txt#L17-L24
And then it uses those in build.zig to generate a libc.txt file: https://github.com/pfgithub/blockeditor/blob/5b5e65877d2915387fb07c51f9c8d7598ba3b49c/packages/beui_impl_android/build.zig#L177-L184
And then it does some hacky stuff to update the dependency tree so every target building for
*-androidhas the correct libc.txt file: https://github.com/pfgithub/blockeditor/blob/5b5e65877d2915387fb07c51f9c8d7598ba3b49c/packages/beui_impl_android/build.zig#L136-L162
sorry. I meant like down and dirty where relative to the sdk sysroot are these.
include_dir=/usr/include sys_include_dir=/usr/include/sys? crt_dir=?
I have no idea what these values should be
I'm not sure the exact values, but the cmake script looks for specific files. So you can search in the sysroot for these items to find them:
In libc.txt:
- include_dir is the folder containing
stdlib.h - sys_include_dir is $INCLUDE_DIR/aarch64-linux-android (see https://github.com/pfgithub/blockeditor/blob/5b5e65877d2915387fb07c51f9c8d7598ba3b49c/packages/beui_impl_android/build.zig#L10-L13 for the names for different targets)
- crt_dir is the parent folder of the folder containing
libc.so - The rest are left empty.