Search code examples
dependenciesstatic-linkingcrystal-lang

How can I produce a Crystal executable with no dependencies?


I'm writing a program in Crystal, that I intend to compile and move to other systems for execution. Ideally, it should have no dependencies, as the target systems will be fresh installations of linux.

Sadly, I can't get around the libc dependency, so I will presumably have to compile the executable on a system possessing the lowest version of libc I wish to target. I figure it should be forward-compatible.

I'm having difficulty with libssl, however. Default installations of Debian Wheezy don't seem to come with libssl, so I get this error when running my executable:

error while loading shared libraries: libssl.so.1.0.0:
cannot open shared object file: No such file or directory

I assume this dependency exists because I require "http/client" in my source. However, I make no ssl-related calls, as I only use it to connect to unsecured websites.

I apparently also have a dependency on libevent-2.0.so.5. Presumably all Crystal programs do. Who knows how many other dependencies Crystal has?

My executables have to run on a freshly-installed linux system. So, how can I produce a Crystal executable with no dependencies? Other than libc, I suppose.


Solution

  • In Linux, you can list the shared libraries that an executable needs using the ldd command. In OSX, otool -L could be used for the same purpose.

    Normally, the linker will use shared libraries while building the executable if it can find them. So, what you need to do, is force the linker to use static libraries instead. (In the future we might add a flag to the compiler to force this choice)

    You should find some of these static libraries in /opt/crystal/embedded/lib. We use these to generate a portable Crystal compiler.

    In order to use these libraries you can run:

    $ LIBRARY_PATH=/opt/crystal/embedded/lib crystal build my_app.cr
    

    That should prefer libraries available in that directory before considering others installed in the standard locations.

    Unfortunately, OpenSSL is not distributed with Crystal, so you must either copy or build a static version of libssl and libcrypto. It's a common library anyway, available in any Linux distribution.

    Regarding libc, that's more tricky. We compile the Crystal binary for releases using old CentOS and Debian distributions to make it compatible with many more libc versions.