How to force gcc to link an unused static library
Asked Answered
S

4

46

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?

Sankaran answered 2/1, 2013 at 3:1 Comment(7)
@chris I have made the question more clear -lmylib does not change the situationSankaran
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.Lives
+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 :)Bunkum
@Lives but the constructor S::S() is called from the translation unit which defines S . Or am I missing something in your comment?Sankaran
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...Lives
You can create a script on bash for selecting libraries what you want to use.Rochette
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 arIntosh
U
62

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
Unutterable answered 2/1, 2013 at 3:20 Comment(2)
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 gcc.gnu.org/wiki/VisibilityKimura
User should anyway add -Wl,-no-whole-archive at the end. As man ld 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."Wallah
T
8

The original suggestion was "close":

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

Tripoli answered 2/1, 2013 at 3:21 Comment(0)
F
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
    
Futch answered 2/1, 2013 at 5:38 Comment(0)
L
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.

Limbate answered 10/5, 2017 at 13:44 Comment(1)
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)Ailurophobe

© 2022 - 2024 — McMap. All rights reserved.