45

I have a program and a static library:

// main.cpp
int main() {}

// mylib.cpp
#include <iostream>
struct S {
    S() { std::cout << "Hello World\n";}
};
S s;

I want to link the static library (libmylib.a) to the program object (main.o), although the latter does not use any symbol of the former directly.

The following commands do not seem to the job with g++ 4.7. They will run without any errors or warnings, but apparently libmylib.a will not be linked:

g++ -o program main.o -Wl,--no-as-needed /path/to/libmylib.a

or

g++ -o program main.o -L/path/to/ -Wl,--no-as-needed -lmylib

Do you have any better ideas?

Martin
  • 9,089
  • 11
  • 52
  • 87
  • @chris I have made the question more clear -lmylib does not change the situation – Martin Jan 02 '13 at 03:11
  • 2
    The static s may be initialized anywhere from before main until the first call to a function within that translation unit... that means that never instantiating s is valid according to the standard, given that no function from that translation unit is ever called. – K-ballo Jan 02 '13 at 03:15
  • +1, I ran into exactly the same situation a couple of weeks ago. I had some small libraries and a bigger one using all smaller ones (well, not necessarily by calling methods of them; it "bundled" them together). The final application should then use the bigger library as well as the smaller ones "bundled" with it, but they weren't there, because the bigger one didn't use them. I did a workaround by introducing a dummy method in the small libraries and used them in the bigger one... Dirty hack! :\ I'm looking forward to see a good answer to this question :) – leemes Jan 02 '13 at 03:15
  • @K-ballo but the constructor S::S() *is* called from the translation unit which defines S . Or am I missing something in your comment? – Martin Jan 02 '13 at 03:21
  • 2
    You are missing the fact that a perfectly conformant implementation can instantiate its globals right before the first function from that translation unit is called, which in your case is never... – K-ballo Jan 02 '13 at 03:22
  • You can create a script on bash for selecting libraries what you want to use. – Mihai8 Jan 02 '13 at 09:49
  • in case of merging a complete static library with another obj file (in this case the one containing main, but it's no difference) might be enough to use `ar` – Oleg Kokorin Sep 04 '18 at 06:58

4 Answers4

60

Use --whole-archive linker option.

Libraries that come after it in the command line will not have unreferenced symbols discarded. You can resume normal linking behaviour by adding --no-whole-archive after these libraries.

In your example, the command will be:

g++ -o program main.o -Wl,--whole-archive /path/to/libmylib.a

In general, it will be:

g++ -o program main.o \
    -Wl,--whole-archive -lmylib \
    -Wl,--no-whole-archive -llib1 -llib2
Alex B
  • 82,554
  • 44
  • 203
  • 280
  • Does anyone know if there is a finer control of this, like using DSO visibility? I'm thinking of tagging a few functions to be forced in. See https://gcc.gnu.org/wiki/Visibility – csl Mar 15 '16 at 12:21
  • 6
    User should anyway add `-Wl,-no-whole-archive` at the end. As [man ld](http://man7.org/linux/man-pages/man1/ld.1.html) says: *"Second, don't forget to use `-Wl,-no-whole-archive` after your list of archives, because gcc will add its own list of archives to your link and you may not want this flag to affect those as well."* – Sasha Dec 08 '16 at 19:19
8

The original suggestion was "close":

Try this: -Wl,--whole-archive -lyourlib

Community
  • 1
  • 1
paulsm4
  • 114,292
  • 17
  • 138
  • 190
6

I like the other answers better, but here is another "solution".

  1. Use the ar command to extract all the .o files from the archive.

    cd mylib ; ar x /path/to/libmylib.a
    
  2. Then add all those .o files to the linker command

    g++ -o program main.o mylib/*.o
    
melpomene
  • 84,125
  • 8
  • 85
  • 148
brian beuning
  • 2,836
  • 18
  • 22
4

If there is a specific function in the static library that is stripped by the linker as unused, but you really need it (one common example is JNI_OnLoad() function), you can force the linker to keep it (and naturally, all code that is called from this function). Add -u JNI_OnLoad to your link command.

Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • Alex, I have been trying to use `whole-archive` with Android's NDK and CMake with no success, and I think using the linker's `-u` flag is my only option. How would you this on the NDK? And is there any other alternative to do this on Android that you know of? (I can't use `LOCAL_WHOLE_STATIC_LIBRARIES ` because I am using CMake instead of `android.mk`) – Jaime Ivan Cervantes Apr 04 '18 at 04:54