Say I have a.so and b.so.
Can I produce c.so as a single shared library with all the functions exported by a and b, of course resolving all intra-dependencies (i.e. all functions of b.so called by a.so and the other way around)?
I tried
gcc -shared -Wl,soname,c.so -o c.so a.so b.so
but it doesn't work.
Same goes if I archive a.o and b.o in a.a and b.a (which shouldn't modify a.o and b.o), and do
gcc -shared -Wl,soname,c.so -o c.so a.a b.a
Thanks
Merging multiple shared libraries into one is indeed practically impossible on all UNIXen, except AIX: the linker considers the .so a "final" product.
But merging archives into .so should not be a problem:
gcc -shared -o c.so -Wl,--whole-archive a.a b.a -Wl,--no-whole-archive
In practice it is not possible.
From linker point of view, a SO library is a final product that does not contain relocation information required for linking.
If you have access to either source or object files for both libraries, it is straightforward to compile/link a combined SO from them.
Related
I know that the question is strange because we all know that a static .a library can be linked only at compile time.
I have a confidential code that I cannot share, but my question is what can let a code compiles and links against a static library successfully, but at runtime it complains about a missing symbol that is present in the .a lib which was linked with the code in the first place ?
What I can share is a little:
add_library(${NAME} STATIC ${NAME_SOURCES})
then this library is added to a global variable called LIBS that has all libraries needed to link to final binary.
I found the static library and I did an objdump on it and found the missing symbol.
So, it compiled the static lib then it compiled the final binary using that library, so why it complains about not finding it at runtime ?
There are many ways to cause this behaviour, here's one.
Suppose you have a shared library libA.so and a static library libB.a. Both export the same symbol foo.
// foo.c
void foo() {}
gcc -fPIC -shared -o libA.so foo.c
gcc -c foo.c && ar r libB.a foo.o
You link your program against both libraries:
// main.c
extern void foo();
int main() { foo(); }
gcc -o myexe main.c -L. -lA -lB -Wl,-rpath=. # dangerous, do not really do this
foo is resolved against libA.so.
Now suppose that at run time you have a different version of libA.so, one that does not export foo. Perhaps you have several versions of the library lying around, or maybe there is a software update.
// foo.c v2.0
void nofoo() {}
gcc -fPIC -shared -o libA.so foo.c
When you try to run myexe, the system will complain about
./myexe: symbol lookup error: ./myexe: undefined symbol: foo
myexe is linked againsg libB.a which defines foo, but as you can see, this doesn't help one little bit.
For background, I'm creating some C++ software that uses dynamically loaded shared library plugins for hardware output (the specifics of it aren't relevant here).
I'm building the executable by compiling everything into object files and then linking the ones needed, which is simple using an exclusion list. I can then build the shared library by specifying its primary object file (the one that's dynamically loaded and accessed at runtime) along with every other object file referenced by the primary one.
My question is this: Is there a way to provide the linker with the primary object file, and create a shared library containing only the objects it depends upon? All of the object files are in the same directory, I'm not using a Makefile (yet; if one could solve the problem, it's a valid answer), and compilation speed isn't an issue.
I've looked into the linker options --as-needed, --gc-sections, and --no-undefined, but I haven't been able to piece together a working build process.
Example: For source files main.cpp, a.cpp, b.cpp, a.h, and b.h, where main.cpp and a.cpp both include b.h:
gcc -fPIC -c *.cpp -I. builds object files main.o, a.o, and b.o.
gcc -o main.out *.o builds the final executable main.out from the object files... including a.o, which is unused. (--gc-sections should fix this.)
gcc -fPIC -shared -o a.so a.o -Wl,--as-needed !(a).o builds the final shared library a.so from all of the object files... including main.o, which is unused. How do I prevent main.o from being included in a.so?
Is there a way to provide the linker with the primary object file, and create a shared library containing only the objects it depends upon?
Yes: package all objects into an archive library liball.a, then link like this:
gcc -shared -o a.so a.o liball.a
The linker will then pull out from liball.a all objects that a.o depends on, and only these objects, as explained here.
Note: liball.a may contain a.o, there is no harm (as above link explains).
Update:
Is there a way to do it without needing to create an archive first?
I don't know of any portable way to do that. The Gold linker has --start-lib and --end-lib command line flags that achieve exactly that.
Suppose a.cc defines a function f_a() that uses a function f_b() defined in b.cc. From a.cc and b.cc I create a dynamic library libdynamic.so.
Suppose the file main.cc uses f_a, I'd compile it as follows:
g++ -o main main.cc -ldynamic
How does the dynamic linker bring the definition of f_a (and subsequently f_b) into the executable? Is the definition of f_a in libdynamic.so already resolved with f_b? Or the dynamic linker will also resolve this (internal) dependency at runtime?
Since you're using a shared library (*.so), the definition is not brought into the executable. It remains in the library itself and is resolved at run time, which is why if you remove the shared library the program will not function correctly.
On the other hand, all the internal symbols in the library (in your example, f_a and f_b) must be resolved when the library is built. This is evident from the compilation process:
g++ -fPIC -c a.cc
g++ -fPIC -c b.cc
g++ -shared -Wl,-soname,libdynamic.so -o libdynamic.so a.o b.o
In the last stage, g++ calls the linker (ld) to link f_a.o and f_b.o. In fact, you could (probably) call the linker directly instead:
ld -shared -soname=libdynamic.so -o libdynamic.so a.o b.o
If you're still curious about the whole process and all its gory details, here is a useful reference article: Linkers and Loaders, by Sandeep Grover.
Basically Dynamic libraries are linked with the Executable file at Run time(That is when you are running ./main). The compiler will take care about the solving the dependency at run time. If you want to check the dependency is resolved or not by nm command. The default information that the ‘nm’ command provides is-
Virtual address of the symbol
A character which depicts the symbol type. If the character is in lower case then the symbol is local but if the character is in upper case then the symbol is external
Name of the symbol
For more information nm.
After compiling your program just execute nm exefilename(i think for your's nm main).
Say I have a libmy.a static library, and I want to know what libraries it links dynamically. Actually I need that for the following: I am gonna create a new dynamic lib say libmy2.so which will link say an .o file (object file) and the libmy.a. So I wonder what libs will load libmy2.so eventually.
Static libraries do not link other libraries, either static or dynamic.
OK, assuming two C++ files, a.cpp and b.cpp.
g++ -c a.cpp -o a.o // compile a.cpp to a.o
rm -f lib1.a // no existing lib1.a (this is not essential)
ar rvs lib1.a a.o // create library lib1.a and add a.o to it
g++ -c b.cpp -o b.o // compile b.cpp to b.o
ar rvs lib1.a b.o // ad b.o to existing lib1.a
You can obviously do any amount of copying between stages to produce the library with the name you want. You can also do
ar --help
to get the ar options which might simplify the process slightly. Frankly, it's a command I almost never use except to build static libraries from a list of objects.
on a mac, it would be
nm -m C libname.a
You can use the folllowing commands to check the contents of your static libraries:
nm -C libname.a | less
or
$ar -vt libname.a
The dynamic library will dynamically link only to those dynamic libraries which you specify with -l when building it. Static libraries are principally linking time entities representing a set of *.o files and they must be processed by linker to produce executable code so there is no requirement that all implementations must be provided when building a static library. All is set up during the final link of the target executable.
Here is a C++ project, and its lib dependency is
Hello.exe
-> A.so
-> B.a
B.a
-> A.so
Hello.exe depends on B.a and A.so, and B.a depends on A.so.
GCC compiler will link Hello.exe successful?
And if there is a b.cc file in B.a which includes a header file a.h of A.so, and also uses some interfaces of A.so, then with right "include" path setting, compiling b.cc to b.o should be successful.
But if without A.so as input, the link of B.a would be failed, right?
gcc -c b.cc -I../A/include ;; successful
gcc -a B.a b.o ;; fail
Where I can find detail library link documents about these complex reference relationship ...
Thanks.
A static library is just a collection of object files created from compiled .c/.cpp files.
It cannot have link relationships.
You will need to specify link dependencies to both A.so and B.a when you compile Hello.exe
off the top of my head it would be something like
gcc -o Hello.exe B.a A.so
As a side note you should rename A.so to libA.so and instead do
gcc -o Hello.exe -lA B.a
Linking to A.so directly like example 1 will require that A.so is always in the same directory as Hello.exe
If you use example 2, you can put libA.so anywhere and use LD_LIBRARY_PATH to point to the right directory.