Note: This is not a duplicate question, because no other answer considers multiple definition challenges.
I am trying to combine two static libraries into one. (This works).
Then convert that static library into a dynamic library. (This does not work due to multiple definition error).
I have made a public repo with example sources.
Here are the key components:
return_zero.cpp
int return_zero() { return 0; }
int version() { return 0; }
return_one.cpp
int return_one() { return 1; }
int version() { return 1; }
Note how each library has it's own version function.
I can build each of these into their own static libraries.
libreturn_zero.a and libreturn_one.a.
I can combine them into libreturn.a with the ar utility.
When I dump the symbols using nm utility:
$ nm -C libreturn.a
return_one.cpp.o:
0000000000000000 T return_one()
000000000000000b T version()
return_zero.cpp.o:
0000000000000000 T return_zero()
000000000000000b T version()
Next, I try to convert this aggregate static library into a shared library.
I use a dummy source file, and link libreturn.a using the --whole-archive linker flag.
Here is what the link command looks like:
g++ -fPIC -shared -Wl,-soname,libreturn.so -o libreturn.so "dummy.cpp.o" -Wl,--push-state,--whole-archive libreturn.a -Wl,--pop-state
The above looks like what I want, but it fails because there are two definitions of version.
libreturn.a(return_zero.cpp.o): In function `version()':
return_zero.cpp:(.text+0xb): multiple definition of `version()'
libreturn.a(return_one.cpp.o):return_one.cpp:(.text+0xb): first defined here
collect2: error: ld returned 1 exit status
CMakeFiles/return-shared.dir/build.make:97: recipe for target 'libreturn.so' failed
make[2]: *** [libreturn.so] Error 1
I thought that by merging the two static libraries into one static library, the archiver would remove redundant symbols.
How do I go about merging static libraries into one shared library when there is a chance of symbol name conflicts?
You can't use the aggregate static library if you have code that calls both
return_one()andreturn_zero()because you will get duplicate symbol problems with theversion()functions.How will you decide which
version()function you want to call if you link with the aggregate library?You're going to have to resolve that issue — and that probably means something like prefixing all the functions from
return_zero.cppwith a prefix such asr0_(or, in C++, placing them innamespace return_zero { … }), and — for symmetry, if for no better reason — prefixing all the functions fromreturn_one.cppwith a prefix such asr1_(or placing them innamespace return_one { … }). Your calling code would then use the prefixed names (or prefix the functions with the appropriate namespace name).