Error while cross compiling a NIF with Earthly and Zig

Iโ€™m trying to cross compile a NIF using Earthly and Zig but Iโ€™m getting some compilation errors. Anyone have done something similar or knows what is the problem?

earthly +build

 1. Init ๐Ÿš€
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”

           buildkitd | Found buildkit daemon as docker container (earthly-buildkitd)


 2. Build ๐Ÿ”ง
โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”โ€”

           debian:11 | --> Load metadata linux/amd64
           erlang:25 | --> Load metadata linux/amd64
             +erlang | --> FROM erlang:25
                +zig | --> FROM debian:11
             context | --> local context .
             +erlang | [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ] 100% resolve docker.io/library/erlang:25@sha256:c89aca1f15f73fcaff3c5822ef36fefc6ab0da8bb4145f64dd0630626357f7da
                +zig | [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ] 100% resolve docker.io/library/debian:11@sha256:87eefc7c15610cca61db5c0fd280911c6a737c0680d807432c0bd80cd0cca39b
             ongoing | context (5 seconds ago)
             context | [          ]   0% transferring .:
             context | [โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ] 100% transferring .:
                +zig | *cached* --> RUN apt-get update && apt-get install --yes --no-install-recommends curl=7.* ca-certificates=2021* xz-utils=5.* && rm -rf /var/lib/apt/lists/*
                +zig | *cached* --> RUN curl -o zig.tar.xz -S https://ziglang.org/download/$VERSION/zig-linux-x86_64-$VERSION.tar.xz && tar -xf zig.tar.xz && rm -Rf zig.tar.xz && mv zig-linux-x86_64-$VERSION /opt/zig
             +erlang | *cached* --> SAVE ARTIFACT /usr/local/lib/erlang/usr/include +erlang/include
       +build-runner | TARGET=x86_64-macos
       +build-runner | *cached* --> COPY +erlang/* /usr/local/lib/erlang/usr/include
       +build-runner | TARGET=x86_64-macos
       +build-runner | *cached* --> COPY priv/main.c .
       +build-runner | TARGET=x86_64-macos
       +build-runner | --> RUN zig cc -target $TARGET -I/usr/local/lib/erlang/usr/include -o main.so -fpic -shared main.c
       +build-runner | error(link): undefined reference to symbol '_enif_make_string'
       +build-runner | error(link):   first referenced in '/root/.cache/zig/o/293eead21e1fbccbd7f86cd9439cca95/main.o'
       +build-runner | error: UndefinedSymbolReference
       +build-runner | Command /bin/sh -c 'zig cc -target $TARGET -I/usr/local/lib/erlang/usr/include -o main.so -fpic -shared main.c' failed with exit code 1
       +build-runner |
       +build-runner | ERROR: Command exited with non-zero code: RUN zig cc -target $TARGET -I/usr/local/lib/erlang/usr/include -o main.so -fpic -shared main.c

This is the earthly file:

build:
  BUILD +build-runner --TARGET=x86_64-macos

build-runner:
  ARG --required TARGET
  FROM +zig
  COPY +erlang/* /usr/local/lib/erlang/usr/include
  COPY priv/main.c .
  RUN zig cc -target $TARGET -I/usr/local/lib/erlang/usr/include -o main.so -fpic -shared main.c
  SAVE ARTIFACT main.so AS LOCAL main.so

erlang:
  FROM erlang:25
  SAVE ARTIFACT /usr/local/lib/erlang/usr/include

zig:
  ARG VERSION=0.9.1
  FROM debian:11
  RUN apt-get update \
    && apt-get install --yes --no-install-recommends curl=7.* ca-certificates=2021* xz-utils=5.* \
    && rm -rf /var/lib/apt/lists/*
  RUN curl -o zig.tar.xz -S https://ziglang.org/download/$VERSION/zig-linux-x86_64-$VERSION.tar.xz \
    && tar -xf zig.tar.xz \
    && rm -Rf zig.tar.xz \
    && mv zig-linux-x86_64-$VERSION /opt/zig
  ENV PATH $PATH:/opt/zig

And this is the main.c file:

#include <erl_nif.h>

static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    return enif_make_string(env, "Hello world!", ERL_NIF_LATIN1);
}

static ErlNifFunc nif_funcs[] =
{
    {"hello", 0, hello}
};

ERL_NIF_INIT(Elixir.NifTest, nif_funcs, NULL, NULL, NULL, NULL)

Check out the Burrito project on GitHub. They use Zig to cross compile NIFs (not using Earthly though).

1 Like

Try passing -Wl,-undefined=dynamic_lookup when targeting macOS. It might be that Zigler is putting together that command in which case please send a patch. :slight_smile: See macho: allow undefined symbols in dylibs by kubkon ยท Pull Request #10314 ยท ziglang/zig ยท GitHub.

1 Like

Thanks @wojtekmach, your suggestion solved the problem.

build:
  BUILD +build-runner --TARGET=x86_64-macos

build-runner:
  ARG --required TARGET
  FROM +zig
  COPY +erlang/* /usr/local/lib/erlang/usr/include
  COPY priv/main.c .
  RUN zig cc -target $TARGET -I/usr/local/lib/erlang/usr/include -fpic -shared -Wl,-undefined=dynamic_lookup -o main.so main.c
  SAVE ARTIFACT main.so AS LOCAL main.so

erlang:
  FROM erlang:25
  SAVE ARTIFACT /usr/local/lib/erlang/usr/include

zig:
  ARG VERSION=0.9.1
  FROM debian:11
  RUN apt-get update \
    && apt-get install --yes --no-install-recommends curl=7.* ca-certificates=2021* xz-utils=5.* \
    && rm -rf /var/lib/apt/lists/*
  RUN curl -o zig.tar.xz -S https://ziglang.org/download/$VERSION/zig-linux-x86_64-$VERSION.tar.xz \
    && tar -xf zig.tar.xz \
    && rm -Rf zig.tar.xz \
    && mv zig-linux-x86_64-$VERSION /opt/zig
  ENV PATH $PATH:/opt/zig
1 Like