Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

including static libraries with -all_load flag

In what cases exactly do you need -all_load flag?

Lets say I have something like

g++ source.cpp -o test libA.a libB.a libC.a

From what i recall if there is some reference to a symbol used in source.cpp that is present in say libB.a file then that libB.a will be linked (just that symbol or whole code in that library? ) and libA.a and libC.a will be ignored (their code will not be present in final executable).

  • What happens to other libraries when i use -all_load flag as follows

    g++ source.cpp -o test -Wl,-all_load libA.a libB.a libC.a

  • how does 'strip' command effect the output with all_load flag?

like image 863
JamesWebbTelescopeAlien Avatar asked Jun 04 '13 20:06

JamesWebbTelescopeAlien


1 Answers

-all_load is for when you want to link compile units that are (to the linker) unnecessary. For instance, perhaps you will dynamically access functions within the static library at runtime that you know the addresses of, but haven't actually made any explicit function calls to. How would you do that? Well, the compiler could help you by storing a bunch of function pointers in the executable to be read at run time, and then you'd build a lookup system for finding those functions using a string, and you'd call the whole thing Objective-C, which is probably the most common user of -all_load (at least if Google is any guide).

The most common case of this in ObjC is when you have a category in its own compile unit. The complier may not be able to tell that you reference it and so won't link it. So ObjC programmers use -all_load (or -force_load) more often than other C-like programmers. In fact, -all_load is a Darwin-specific extension in gcc.

But there are cases where people might want to use -all_load outside of ObjC. For instance, there might be some inter-dependencies in libA and libB. Consider this case:

  • source.cpp requires A() and B()

  • libA defines A() in a.o and Aprime() in aprime.o

  • libB defines B() in b.o and requires Aprime()

This typically won't link (*). The compiler will start with source.o and make a list of requirements: A() and B(). It'll then look at libA and see that it defines A(), so it'll link a.o (but not aprime.o). Then it will look at libB and see that it defines B() and requires Aprime(). It is now out of libraries, and it hasn't resolved Aprime(). It fails.

(*) Actually, it will with clang because clang is quite smart about this. But it won't with g++ at least up through 4.6.

The best solution would be to reorder it so that libB comes first (**). But if the dependencies were circular, you could get completely stuck. -all_load and -force_load let you work around these situations by turning off the linker's optimization.

(**) The really best solution is usually to redesign your libraries to avoid this kind of interdependency, but that may be hoping too much.

If you want to play around with the issue, see https://gist.github.com/rnapier/5710509.

strip just removes symbols from executables. That's not particularly related to static linking and -all_load (though it does impact dynamic linking). strip(1) has lots of discussion of that.

like image 83
Rob Napier Avatar answered Oct 21 '22 11:10

Rob Napier