zig icon indicating copy to clipboard operation
zig copied to clipboard

Set libc.txt file for a whole tree in build.zig

Open pfgithub opened this issue 10 months ago • 1 comments
trafficstars

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 --libc to 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 libc option, 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 all b.dependency() to .{ .target, .optimize, .libc = b.standardLibCOption(.{}) }
  • Something else?

pfgithub avatar Dec 24 '24 22:12 pfgithub

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?

mitchellh avatar May 29 '25 21:05 mitchellh

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?

what values are you setting in your libc file to work for android?

coffeebe4code avatar Sep 30 '25 20:09 coffeebe4code

@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

pfgithub avatar Oct 01 '25 00:10 pfgithub

@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

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

coffeebe4code avatar Oct 01 '25 03:10 coffeebe4code

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.

pfgithub avatar Oct 01 '25 04:10 pfgithub