188

It feels strange to me to use -Wl,-Bstatic in order to tell gcc which libraries I want to link with statically. After all I'm telling gcc directly all other information about linking with libraries (-Ldir, -llibname).

Is it possible to tell the gcc driver directly which libraries should be linked statically?

Clarification: I know that if a certain library exists only in static versions it'll use it without -Wl,-Bstatic, but I want to imply gcc to prefer the static library. I also know that specifying the library file directly would link with it, but I prefer to keep the semantic for including static and dynamic libraries the same.

Elazar Leibovich
  • 32,750
  • 33
  • 122
  • 169

2 Answers2

291

Use -l: instead of -l. For example -l:libXYZ.a to link with libXYZ.a. Notice the lib and .a are written out, as opposed to -lXYZ which would auto-expand to libXYZ.so/libXYZ.a.

It is an option of the GNU ld linker:

-l namespec ... If namespec is of the form :filename, ld will search the library path for a file called filename, otherwise it will search the library path for a file called libnamespec.a. ... on ELF ... systems, ld will search a directory for a library called libnamespec.so before searching for one called libnamespec.a. ... Note that this behavior does not apply to :filename, which always specifies a file called filename."

(Since binutils 2.18)

Note that this only works with the GNU linker. If your ld isn't the GNU one you're out of luck.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Radek
  • 2,926
  • 1
  • 12
  • 2
  • 89
    God if only Gnu had made this the default in the first place instead of the lib prefix madness. Oh the time and frustration we would have saved. – Timmmm Mar 06 '15 at 10:39
  • 29
    GNU is nowhere responsible for this interface, it was inherited from the Unix toolchain. – akim Dec 04 '17 at 09:02
  • In this case you could also do simple search and replace, like this: pkg-config --libs libpng | sed -E 's/-l([a-z0-9]*)/-l:\1.a/g' it will take output -lpng16 -lz and convert it into -l:png16.a -l:z.a – Tomaz Stih Jan 19 '23 at 22:01
171

You can add .a file in the linking command:

  gcc yourfiles /path/to/library/libLIBRARY.a

But this is not talking with gcc driver, but with ld linker as options like -Wl,anything are.

When you tell gcc or ld -Ldir -lLIBRARY, linker will check both static and dynamic versions of library (you can see a process with -Wl,--verbose). To change order of library types checked you can use -Wl,-Bstatic and -Wl,-Bdynamic. Here is a man page of gnu LD: http://linux.die.net/man/1/ld

To link your program with lib1, lib3 dynamically and lib2 statically, use such gcc call:

gcc program.o -llib1 -Wl,-Bstatic -llib2 -Wl,-Bdynamic -llib3

Assuming that default setting of ld is to use dynamic libraries (it is on Linux).

pevik
  • 4,523
  • 3
  • 33
  • 44
osgx
  • 90,338
  • 53
  • 357
  • 513
  • 6
    Short version: There's no way to do that with current `gcc`. – Elazar Leibovich Jul 05 '11 at 06:29
  • 8
    Elazar Leibovich, but `gcc program.o -llib1 -Wl,-Bstatic -llib2 -Wl,-Bdynamic -llib3` does the trick. – osgx Jul 05 '11 at 06:35
  • Yeah, but the question was specifically how to do that WITHOUT resorting to direct `ld` options. – Elazar Leibovich Jul 05 '11 at 07:42
  • 14
    The linking (and searching of dyn/static libs) is done by linker, So, you must to use Linker options. `-l` and `-L` are linker options too. – osgx Jul 05 '11 at 10:06
  • The compilation is done by the compiler, but you can still send options to the driver that would invoke the compiler. It's better to speak directly to the `gcc` driver, with a language it understands, since then you're less depend on the linker (if the linker changes, the driver would still translate your options correctly). That said, no one will change `gcc` or `ld` anytime soon. – Elazar Leibovich Jul 05 '11 at 11:07
  • 2
    Compilation is done by compiler, but compilation results not in executable file. Object files, produced by compilation must be linked with libraries by linker. So, if you want link your program not only by binutils `ld` or `gold`, you can use `libtool`. – osgx Jul 05 '11 at 11:36
  • 5
    Is this answer upvoted because of `gcc yourfiles /path/to/library/libLIBRARY.a` or `-Wl,-Bstatic`? – Tor Klingberg May 24 '17 at 14:53
  • @TorKlingberg, because it is older (and for https://stackoverflow.com/help/badges/62/populist badge too)? Can you post better answer with all variants in it to be upvoted? Accepted answer was upvoted by me, but it still have no documentation links and gcc/ld versions to use `-l:`. It will work for gcc, but may not work for other compilers. – osgx May 24 '17 at 15:45
  • @osgx: I don't know the pros and cons of each variant, or which one is preferred. That's what I was hoping the vote scores would tell me. In this case, the accepted answer says one thing, and the most upvoted says two other things. – Tor Klingberg May 24 '17 at 15:48
  • 10
    @TorKlingberg, Variant 1 `/path/to/library/libLIBRARY.a` needs full path to be written, variant 2 `-Wl,-Bstatic -llib2 -Wl,-Bdynamic` is just long and adds 2 extra options and assumes default mode as Bdynamic, and accepted variant 3 `-l:libXYZ.a` is short and just works. All three will work for many cases, and variant 2 may not work when linking static programs. Actual linking step for the lib is the same in all variants as I understand. – osgx May 24 '17 at 17:03
  • @osgx, can Variant 1 be replaced with `../../relative/path/to/library/libLIBRARY.a` just as well? – shuhalo Sep 28 '20 at 00:56
  • My experice with ´-Wl,-Bstatic´ is that the linker complains about (implicitly attracted) shared system libraries, which cannot be linked statically, so I switched to the ´-l:libXYZ.a´-pattern – Sam Ginrich May 24 '21 at 14:58