Static linked executable

Static linking of the executable compiler / libc / system libraries can help mitigate missing library issues. Dynamically / shared linked executables on Windows require the DLL path to be in the environment variable PATH or the executable directory. On Linux / BSD, the shared library path must be in the environment variable LD_LIBRARY_PATH. On macOS, the shared library path must be in the environment variable LIBRARY_PATH. If the developer switches compiler environments, or the end user is missing compiler libraries, the executable may fail to run due unresolved dynamic library path.

Relatively few Windows users have compilers installed. Missing DLLs and DLL Hell are part of distributing Windows programs, where batch scripts can be used to set environment variables and Path for the program. A typical error code for missing DLL is -1073741515 → 0xc0000135 STATUS_DLL_NOT_FOUND.

Simply specifying static compiler linking flags does not guarantee portable executables, which are a more general problem. Even using a slim libc like musl doesn’t generally work for graphical programs using X11 / Wayland. The Cosmopolitan project creates a single binary executable from C/C++ code that works across operating systems.

Compiler flags

GCC / Gfortran can statically link compiler libraries including libgfortran into the final executable using flags -static and -static-libgfortran This increases the size of the executable, which may be negligible compared to the nuisances avoided.

gfortran -static -static-libgfortran myprog.f90 mylib.f90 -o myprog.exe

Other compilers have similar static compiler library link options:

For special cases where the system libc and libc++ aren’t used, the compilers typically have additional flags like -static-libgcc and -static-libstdc++.

Caveats

Some libraries may only be available as dynamic, and the options above typically will use the dynamic version if static isn’t available. macOS static linked executable may only work on your specific computer; macOS prefers dynamic linking. In general, we use the default build system linking (dynamic or static) unless there is a reason to specify static linking.