# Can't build to android

**URL:** <https://ziggit.dev/t/cant-build-to-android/9158>\
**Category:** Help\
**Tags:** build-system\
**Created:** [March 19, 2025, 6:49am UTC](https://ziggit.dev/t/cant-build-to-android/9158 "2025-03-19T06:49:25Z")\
**Posts on this page:** 1\
**Showing post:** 4

<div class="post-metadata">

**Author:** ![vkensou](https://ziggit.dev/user_avatar/ziggit.dev/vkensou/32/3948_2.png) [@vkensou](https://ziggit.dev/u/vkensou)\
**Post date:** [March 20, 2025, 2:43am UTC](https://ziggit.dev/t/cant-build-to-android/9158/4 "2025-03-20T02:43:58Z")

</div>

Write file is ok:

```zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const lib = b.addLibrary(.{
        .name = "testso",
        .linkage = .dynamic,
        .root_module = b.createModule(.{
            .target = target,
            .optimize = optimize,
        }),
    });

    lib.linkLibC();

    const system_target = getAndroidTriple(lib.rootModuleTarget()) catch |err| @panic(@errorName(err));

    const android_api_version: u32 = 34;

    const libc = createLibC(b, system_target, android_api_version, "E:\\SDKs\\AndroidSDK\\ndk\\27.0.12077973\\toolchains\\llvm\\prebuilt\\windows-x86_64\\sysroot", "27.0.12077973");

    lib.setLibCFile(libc);

    lib.root_module.addCSourceFile(.{ .file = b.path("test.c") });

    b.installArtifact(lib);
}

fn getAndroidTriple(target: std.Target) error{InvalidAndroidTarget}![]const u8 {
    if (target.abi != .android) return error.InvalidAndroidTarget;
    return switch (target.cpu.arch) {
        .x86 => "i686-linux-android",
        .x86_64 => "x86_64-linux-android",
        .arm => "arm-linux-androideabi",
        .aarch64 => "aarch64-linux-android",
        .riscv64 => "riscv64-linux-android",
        else => error.InvalidAndroidTarget,
    };
}

fn createLibC(b: *std.Build, system_target: []const u8, android_api_version: u32, ndk_sysroot_path: []const u8, ndk_version: []const u8) std.Build.LazyPath {
    const libc_file_format =
        \\# Generated by zig-android-sdk. DO NOT EDIT.
        \\
        \\# The directory that contains `stdlib.h`.
        \\# On POSIX-like systems, include directories be found with: `cc -E -Wp,-v -xc /dev/null`
        \\include_dir={[include_dir]s}
        \\
        \\# The system-specific include directory. May be the same as `include_dir`.
        \\# On Windows it's the directory that includes `vcruntime.h`.
        \\# On POSIX it's the directory that includes `sys/errno.h`.
        \\sys_include_dir={[sys_include_dir]s}
        \\
        \\# The directory that contains `crt1.o`.
        \\# On POSIX, can be found with `cc -print-file-name=crt1.o`.
        \\# Not needed when targeting MacOS.
        \\crt_dir={[crt_dir]s}
        \\
        \\# The directory that contains `vcruntime.lib`.
        \\# Only needed when targeting MSVC on Windows.
        \\msvc_lib_dir=
        \\
        \\# The directory that contains `kernel32.lib`.
        \\# Only needed when targeting MSVC on Windows.
        \\kernel32_lib_dir=
        \\
        \\gcc_dir=
    ;

    const include_dir = b.fmt("{s}/usr/include", .{ndk_sysroot_path});
    const sys_include_dir = b.fmt("{s}/usr/include/{s}", .{ ndk_sysroot_path, system_target });
    const crt_dir = b.fmt("{s}/usr/lib/{s}/{d}", .{ ndk_sysroot_path, system_target, android_api_version });

    const libc_file_contents = b.fmt(libc_file_format, .{
        .include_dir = include_dir,
        .sys_include_dir = sys_include_dir,
        .crt_dir = crt_dir,
    });

    const filename = b.fmt("android-libc_target-{s}_version-{d}_ndk-{s}.conf", .{ system_target, android_api_version, if (ndk_version.len > 0) ndk_version else "unknown" });

    const write_file = b.addWriteFiles();
    const android_libc_path = write_file.add(filename, libc_file_contents);
    return android_libc_path;
}

```

seems `--libc [file]` command line argument isn’t work.

> <https://github.com/ziglang/zig/issues/20327>
>
> Right now, the \`--libc \[file\]\` command line argument isn't really well exposed i…n \`std.Build.Step.Compile\`:
> 
> https://github.com/ziglang/zig/blob/455899668b620dfda40252501c748c0a983555bd/lib/std/Build/Step/Compile.zig#L87
> 
> This implementation doesn't really give us the options to pass down ad-hoc compiled libcs like \[Foundation libc\](https://github.com/ZigEmbeddedGroup/foundation-libc) or newlib inside build.zig.
> 
> The fields available in a \`libc.txt\` file are these:
> 
> \`\`\`ini
> \# The directory that contains \`stdlib.h\`.
> \# On POSIX-like systems, include directories be found with: \`cc -E -Wp,-v -xc /dev/null\`
> include\_dir=/nix/store/i58yz1rxjxpha40l17hgg7cz62jck9q3-glibc-2.38-77-dev/include
> 
> \# The system-specific include directory. May be the same as \`include\_dir\`.
> \# On Windows it's the directory that includes \`vcruntime.h\`.
> \# On POSIX it's the directory that includes \`sys/errno.h\`.
> sys\_include\_dir=/nix/store/i58yz1rxjxpha40l17hgg7cz62jck9q3-glibc-2.38-77-dev/include
> 
> \# The directory that contains \`crt1.o\` or \`crt2.o\`.
> \# On POSIX, can be found with \`cc -print-file-name=crt1.o\`.
> \# Not needed when targeting MacOS.
> crt\_dir=/nix/store/j0by58xwyc66f884x0q8rpzvgpwvjmf2-glibc-2.38-77/lib
> 
> \# The directory that contains \`vcruntime.lib\`.
> \# Only needed when targeting MSVC on Windows.
> msvc\_lib\_dir=
> 
> \# The directory that contains \`kernel32.lib\`.
> \# Only needed when targeting MSVC on Windows.
> kernel32\_lib\_dir=
> 
> \# The directory that contains \`crtbeginS.o\` and \`crtendS.o\`
> \# Only needed when targeting Haiku.
> gcc\_dir=
> \`\`\`
> 
> These options could be exposed inside a struct \`std.Build.LibC\`:
> 
> \`\`\`zig
> pub const LibC = struct {
> /// The directory that contains \`stdlib.h\`.
> /// On POSIX-like systems, include directories be found with: \`cc -E -Wp,-v -xc /dev/null\`
> include\_dirs: \[\]const LazyPath,
> 
> /// A list of additional object files or static libraries that might be linked with the final executable.
> /// These objects are required when using custom libc files.
> link\_objects: \[\]const LazyPath = &.{},
> 
> /// The system-specific include directory. May be the same as \`include\_dir\`.
> /// On Windows it's the directory that includes \`vcruntime.h\`.
> /// On POSIX it's the directory that includes \`sys/errno.h\`.
> sys\_include\_dirs: \[\]const LazyPath = &.{},
> 
> /// The directory that contains \`crt1.o\` or \`crt2.o\`.
> /// On POSIX, can be found with \`cc -print-file-name=crt1.o\`.
> /// Not needed when targeting MacOS.
> crt\_dir: ?LazyPath = null,
> 
> /// The directory that contains \`vcruntime.lib\`.
> /// Only needed when targeting MSVC on Windows.
> msvc\_lib\_dir: ?LazyPath = null,
> 
> /// The directory that contains \`kernel32.lib\`.
> /// Only needed when targeting MSVC on Windows.
> kernel32\_lib\_dir: ?LazyPath = null,
> 
> /// The directory that contains \`crtbeginS.o\` and \`crtendS.o\`
> /// Only needed when targeting Haiku.
> gcc\_dir: ?LazyPath = null,
> };
> \`\`\`
> 
> which could be used like this then:
> 
> \`\`\`diff
> \- libc\_file: ?LazyPath = null, 
> + libc: ?std.Build.LibC = null, 
> \`\`\`
> 
> \*\*Pre-defined libc:\*\*
> 
> \`\`\`zig
> pub fn build(b: \*std.Build) void {
> // Emulate "--libc custom.txt":
> const libc = b.parseLibCFile(p.path("custom.txt"));
> 
> const exe = b.addExecutable(.{
> .libc = libc,
> …
> });
> }
> \`\`\`
> 
> \*\*Custom libc:\*\*
> 
> \`\`\`zig
> pub fn build(b: \*std.Build) void {
> const foundation\_libc = foundation\_mod.artifact("foundation");
> 
> const libc = std.Build.LibC {
> .include\_dirs = &.{
> foundation\_libc.getEmittedIncludeTree(),
> },
> .link\_objects = &.{
> foundation\_libc.getEmittedBin(),
> },
> };
> 
> const exe = b.addExecutable(.{
> .libc = libc,
> …
> });
> }
> \`\`\`

---

_[View the full topic](https://ziggit.dev/t/cant-build-to-android/9158)._
