ChatGPT解决这个技术问题 Extra ChatGPT

Use both static and dynamically linked libraries in gcc

I need to distribute a binary that will run on as many x86 Linux distributions as possible. That means that I have to statically link some libraries, like glibc, because the user might not have the version I use. Other libraries have to be dynamically linked, like fontconfig, because it relies on a cache file format and hard coded locations that may differ on each system.

What are the command line options to do this? If I specify -static, then gcc will refuse to dynamically link any libraries at all.


E
Employed Russian

Statically linking against any system library, and especially against libc, on modern UNIX or Linux systems makes the binary significantly less portable. Just don't do it.

Instead, use backward compatibility (binaries linked on an older system continue to run on all newer ones) to your advantage, either by linking your binary on an old system (I use RedHat 6.2, and I have not seen a Linux system where my binary will not run in the last 8 years), or by using something like autopackage (which has been deleted after this answer was written).

To answer your original question:

gcc main.o -Wl,-Bstatic -lfoo -Wl,-Bdynamic

will cause linker to use archive version of libfoo. [It is important to have the trailing -Wl,-Bdynamic precisely so you don't force static libc.]


first time I've seen an explanation for that trailing dynamic, cheers
Your advice has stood the test of time. Now I always build on the oldest Linux I want to support.
"Statically linking against any system library, and especially against libc, on modern UNIX or Linux systems makes the binary significantly less portable." What does this mean? Do you mind explaining why this is true? From what I've seen, statically linking means that users don't have to worry about dependencies on their systems, making it more portable. Is this wrong?
With container based software delivery, portability drops much lower on the list of priorities. Especially binary portability. But even source compatibility drops in value. Thus, the benefits of static linking rise to the top of the priority list, chiefly ease of installation. Just copy the executable file somewhere in the $PATH and you're good to go. That said, it's typically better to dynamically link to a short list of common shared libs, e.g. glibc, openssl, curl, ... your list may be different. But the mix of static and dynamic is the sweet spot for lots of apps. YMMV
b
bdonlan

It should be noted that, under Linux, you can only (safely) statically link a library if none of the dynamic libraries depend on it. This means that if you're using any dynamic libraries at all, you can forget about statically linking libc. Just use a fairly old version to build against for libc's case; libc has maintained strong ABI backwards-compatiblity over the years.


M
Mihai Limbășan

Try passing in the paths to the library files you're linking against on the linker command line (be they .a or .so libraries) and drop -static. That should do the trick.


When there is no -static there is also -l: option of ld, which can be used to link some library by full name, without ld expanding it to lib + name + .so: -l:libsome_library.a (sourceware.org/binutils/docs-2.18/ld/Options.html - -lnamespec "If namespec is of the form :filename, ld will search the library path for a file called filename, otherise it will search the library path for a file called libnamespec.a.")