How to embed a static library in a shared library (Linux)?

Viewed 179

I have a static library which I do not have the source code, and need its symbols to be called dynamically from the LuaJIT FFI.

As it is static, I can't load it dynamically, so I'm trying to embed it in a shared library and then load the shared library at runtime.

Problem is that exported symbols of the static library are present in the symbols table of the shared lib, but are undefined.

nm libUSBDevices.a

shows a lot of lines, among which the symbols that interest me:

00001d80 T _ZN9USBDevice16FlightControllerC1EPKc
00001e30 T _ZN9USBDevice16FlightControllerD1Ev
00000140 T _ZN9USBDevice7AxisFctC1Ev
00000180 T _ZN9USBDevice7AxisFctclEv

Then I compiled the shared library using these two g++ commands :

g++ -m32 -c -Wall -Werror -fpic USBDevicesLoader.cpp -llibUSBDevices.a

which outputs USBDevicesLoader.o (USBDevicesLoader.cpp contains some exported functions which call symbols inside the static library, those ones are correctly present in the .so)

g++ -m32 -shared -o libUSBDevicesLoader.so USBDevicesLoader.o

This outputs the shared lib, but when loaded at runtime, it shows this:

[...] symbol lookup error: /home/me/USBDevices-loader/libUSBDevicesLoader.so: undefined symbol: _ZN9USBDevice16FlightControllerC1EPKc

And when I run nm on the shared lib, it shows the symbols as undefined:

U _ZN9USBDevice16FlightControllerC1EPKc
U _ZN9USBDevice7AxisFctclEv

I suggest the problem is somewhere in the compilation commands, I also tried to build the shared lib directly out of the .a without compiling the cpp first (just replace USBDevicesLoader.o in the second command by the .a, skip the first command) but the problem stays the same.

So, is there a way to embed all symbols of a static library (without having the source) in a dynamic lib which can then be loaded and used at runtime? Thanks

1 Answers

You can use the --whole-archive option to achieve this as seen here and in the docs:

--whole-archive: For each archive mentioned on the command line after the --whole-archive option, include every object file in the archive in the link, rather than searching the archive for the required object files. This is normally used to turn an archive file into a shared library, forcing every object to be included in the resulting shared library. This option may be used more than once.

As an example:

g++ -shared -o libnew.so -Wl,--whole-archive libmylib_static.a -Wl,--no-whole-archive

You can then link to the shared libnew.so library as you would normally do.

Related