Search code examples
compilationdynamic-linkingnim-langmusl

How to dynamically link your nim-application against musl?


I've written a web-server in nim using the prologue framework. I would like to deploy that application using an alpine-docker-container. As far as I'm aware, compiling means you dynamically link against your system libraries for whatever you need, that system library on any normal distro being glibc. On alpine however you do not use glibc, you use musl, so dynamically linking against glibc means my application will expect glibc functions with glibc names that do not exist since there are only musl functions.

The big question that arises out of this for me as a python developer that jumped onto nim and knows very little about compilers: How do I compile, so that I link dynamically against musl?


Solution

  • The folks from nim discord's brought me to the answer. It consists of passing flags to the nim-compiler to swap out the compiler nim normally uses for its generated C-code, in order to use musl-gcc. This can be done by using the --gcc.exe:"musl-gcc" and --gcc.linkerexe:"musl-gcc" flags.

    Here an example for Linux:

    1. install musl to get access to musl-gcc
    • download the tar file from the official musl page
    • Unpack the tar file somewhere
    • Run bash configure in the unpacked directory. WARNING: Make sure that you do NOT install musl with --prefix being /usr/local, as that may adversely affect your system. Use somewhere else where it is unlikely to override files, e.g. /usr/local/musl. This path will further be referred to as <MUSL_INSTALL_PATH>
    • Run make && make install in the unpacked directory
    • Add <MUSL_INSTALL_PATH> to your PATH environment variable
    • Validate whether you set everything up correctly by opening a new terminal and seeing whether you have access to the musl-gcc command
    2. Compile with musl
    • Create a compile command with --gcc.exe:"musl-gcc" to swap out gcc with musl-gcc and --gcc.linkerexe:"musl-gcc" to swap out the default linker with musl-gcc as well. An example can look like this:
    nim c \
    --gcc.exe:"musl-gcc" \
    --gcc.linkerexe:"musl-gcc" \
    --define:release \
    --threads:on \
    --mm:orc \
    --deepcopy:on \
    --define:lto \
    --outdir:"." \
    <PATH_TO_YOUR_MAIN_PROJECT_FILE>.nim
    
    • run the command

    This should generate a binary that is dynamically linked against musl and thus can run within an alpine docker container.