skip to Main Content

NOTE: I am using Stack.
When we do (say on a CentOS machine)

stack install --ghc-options='-optl-static -optl-pthread' --force-dirty --local-bin-path path-to-executable(my-project-exe)

Can the newly created my-project-exe executable run across machines (having the same OS/Architecture) just by running ./my-project-exe ?
Sorry if the question seems very basic but I want to understand this from the first principles.

What really is this haskell executable? : Is this some single file that has all the dependencies installed within it apart from basic system/OS calls?

My usecase: I have an haskell executable created on my machine for my project. What is the minimal number of installs that is required such that I can run this executable by simply copying it to another machine with the same OS? Zero number of new installs would be the best.

PS: ./my-project-exe works like a charm on the machine on which I ran stack-install command.

2

Answers


  1. Maybe.

    There’s a couple reasons that an executable built on one machine might not work well on another machine. You can work your way down the list and think about how each applies to your specific case. (The first three you’ve touched on already, but I include them anyway for completeness.)

    1. Different OS. Each operating system has its own container format for binaries, and they are not typically inter-operable. However, it is very common for the container format to stay the same across OS versions.
    2. Different architecture. The CPUs built by different companies typically have completely different instruction sets. These days, almost all consumer-level computers use the x86-64 instruction set, so unless you are doing something fairly special, this should not be an issue. However, if you are developing for an embedded system or other niche market you may have to pay more attention to this.
    3. Different dynamic libraries. Many programs use code from external libraries, and typically rely on the OS to locate and load those libraries. Even with static linking, there are a few core libraries that are almost always exceptions to the “dump all the code directly into the binary” request. On Linux, you may ask ldd which libraries a particular binary is expecting to be able to link with. There is of course a versioning story to be aware of here, too, for each linked library.
    4. Different peripherals/hardware. For example, one computer may be somebody’s pet supercomputer with 128GB of RAM, and the other is running on their aging work laptop with 4GB of RAM. But there are many less obvious examples of possible problems as well: perhaps one display is HD and the other 4K; or one computer has a GPU and the other doesn’t; or one computer has a microphone and the other doesn’t; or a million other small differences that can sneak up on you.
    5. Different filesystem properties. The biggest gotcha here is that some filesystems are case-insensitive and some aren’t. Your program might work differently than you expect if you developed for one and ran on another.
    6. Different on-disk resources. Many programs rely on files with data they need to run; for example, games come bundled with sound effects, level maps, sprites, and the like, while web servers often come with a collection of files they expect to serve from a static directory, or a CRUD app might come with a file describing the layout of its GUI widgets, or an orchestration layer might expect certain auxiliary programs to be installed. These files will need to be transferred to appropriate locations on the other machine for the program to work properly.
    7. Different services. Many programs do inter-process communication, for example by connecting to ports, sending messages on DBUS, looking for specific sockets, and so on. If the service that provides these mechanisms is not installed or has not been started yet, this can prevent the program from working correctly.
    8. Different environment variables. Properly transferring a program might involve setting up some configuration information via the environment.

    There are probably others, but these spring directly to mind.

    Login or Signup to reply.
  2. By default, Stack creates an executable with the GHC runtime and compiled Haskell libraries statically linked into the executable. However, it will typically be linked against dynamic versions of standard O/S libraries (e.g., libc, libpthread) and — more importantly — external C libraries used by Haskell packages. For example, I have a Stack project that uses the hmatrix and hmatrix-glpk packages. These use the BLAS, LAPACK, and GLPK libraries, and the executable has dependencies on the shared versions on those libraries, among other things:

    $ ldd ctest
        linux-vdso.so.1 (0x00007fff791bd000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fd45e197000)
        libglpk.so.40 => /lib/x86_64-linux-gnu/libglpk.so.40 (0x00007fd45deb8000)
        libblas.so.3 => /lib/x86_64-linux-gnu/libblas.so.3 (0x00007fd45de4b000)
        liblapack.so.3 => /lib/x86_64-linux-gnu/liblapack.so.3 (0x00007fd45d7b1000)
        libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fd45d730000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fd45d725000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd45d71d000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd45d6fa000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd45d509000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fd45e301000)
        libcolamd.so.2 => /lib/x86_64-linux-gnu/libcolamd.so.2 (0x00007fd45d500000)
        libamd.so.2 => /lib/x86_64-linux-gnu/libamd.so.2 (0x00007fd45d4f5000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fd45d4d9000)
        libltdl.so.7 => /lib/x86_64-linux-gnu/libltdl.so.7 (0x00007fd45d4cc000)
        libgfortran.so.5 => /lib/x86_64-linux-gnu/libgfortran.so.5 (0x00007fd45d22c000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fd45d212000)
        libsuitesparseconfig.so.5 => /lib/x86_64-linux-gnu/libsuitesparseconfig.so.5 (0x00007fd45d20d000)
        libquadmath.so.0 => /lib/x86_64-linux-gnu/libquadmath.so.0 (0x00007fd45d1c3000)
    

    Other than these dependencies on shared libraries, the executable is self-contained, so it can be copied to another machine even without Stack or GHC installed, and it’ll run fine as long as the shared libraries are there.

    If you can convince Stack to create a truly static binary, then it should be entirely self-contained (well, except for any explicit dependencies on other resources introduced by you or by some library).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search