Is it possible to compile statically with gcc or g++ on Linux based systems?

10,002

Solution 1

Compiling with -static appears to work for basic c++ programs, probably all of the standard library?

However when using with other libraries, this may no longer work.

Solution 2

Is it possible to compile statically with gcc or g++ on Linux based systems?

It depends.

You might try to compile and link all your code with gcc -static or g++ -static. In several cases (e.g. pure command-line applications, like your hello world), it would work.

Linux distributions like a lot shared libraries. Most of them are using shared libraries extensively (notably for graphical applications). Read Drepper's How to Write Shared Libraries paper for more.

You might have some licensing issues. To simplify outrageously, it might be illegal (against the LGPL license) to ship code statically linked to some LGPL (or GPL) library. The evil is in the details.

Some core features, notably DNS related (e.g. getaddrinfo(3) & getnameinfo(3)) are internally using plugin techniques à la dlopen(3), so sort-of requires a dynamic libc.so (see nsswitch.conf(5) for more).

Some X11 things, in particular font related, are also expecting plugin related things (IIRC, Xft); perhaps SFML uses them. BTW, SFML is very probably installed as shared libraries, so you'll need to rebuild SFML from source code...

At last, a statically linked program might be more tied to some particular kernel version that a dynamically linked one (in principle, this is not the case). It might happen that you could have incompatibilities with very old or future kernels (but usually not).

See also ldd(1), file(1), pmap(1), proc(5), vdso(7)

It might be actually simpler to ship the source code to the target system, ask the sysadmin to install required dependencies, and build your code on the remote target (e.g. using ssh)

You could try to link statically most libraries but not all (e.g. link statically libstdc++.a and dynamically libc.so) by playing with GCC linking options. See this & that

Perhaps you'll first should try to link statically some SFML demo.... or simply scp your (dynamically linked) binary program and try to run it remotely (it might be able to run).

Share:
10,002
FreelanceConsultant
Author by

FreelanceConsultant

No longer available for hire for contract work Expertise include: Research (Any) Data Analysis, Signal Processing Mathematics C, C++ and Python Multi-thread, parallel and networked CUDA, OpenCL

Updated on June 06, 2022

Comments

  • FreelanceConsultant
    FreelanceConsultant about 2 years

    I am working on a project which I would like to be able to "ship" to other Linux based computers as a complete executable with no dependencies. (In order that I can copy just the 1 file to other systems, and then run that file on those systems.)

    In the windows world, I think static linking is done just by passing -static to the compiler, perhaps with some other options for specific libraries*, if you are using Visual Studio.

    *eg: Using SFML you also have to define SFML_STATIC for some reason?

    Is this possible using gcc / g++, and if so how? I tried searching for this but didn't manage to find anything. I have heard before that this may be a non-trivial task.

    Edits:

    BasileStarynkevitch suggested compiling with the flag -static.

    I don't know if this is what I want, but I wrote a test program to try it out:

    #include <iostream>
    
    int main()
    {
        std::cout << "Link statically please" << std::endl;
    
        return 0;
    }
    

    And then compiled with:

    g++ main.cpp -o a.out -static
    g++ main.cpp -o b.out
    

    The results are:

    -rwxr-xr-x  1  1653098  a.out
    -rwxr-xr-x  1     9167  b.out
    

    So it looks like it might be working?

    TonyD suggested a method of checking:

    ldd a.out 
    not a dynamic executable
    
    ldd b.out
    linux-vdso.so.1 =>  (0x00007fff3d5ac000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fce5e34a000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fce5df85000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fce5dc7e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fce5e677000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fce5da67000)