Tomáš Zato
Tomáš Zato

Reputation: 53119

Create shared .so library that has all it's dependencies statically linked

I am trying to build my .so library with all dependencies (mostly boost) statically linked. Currently, I can build statically linked static library and dynamically linked shared library:

image description

I would like to add other dependencies to .so library so that it has 20MB and does not require user to install anything. Note that this is just a temporary solution before we upgrade to new Boost 1.55 on production servers.

I define libraries like this in Makefile ($ARCH can be either 32 or 64):

## Multi-arch library locations
LIB32=/usr/lib/i386-linux-gnu/
LIB64=/usr/lib/x86_64-linux-gnu/
LIBDIR:=$(LIB$(ARCH))
##Library directory
LIB=-L $(LIBDIR)
## DYNAMIC
LIBS=-lboost_serialization -lboost_thread -lboost_date_time -lboost_signals -lboost_iostreams -lboost_system -llog4cplus -lcrypto -lssl -lm
## STATIC
SLIBS=$(LIBDIR)libboost_serialization.a $(LIBDIR)libboost_thread.a $(LIBDIR)libboost_date_time.a $(LIBDIR)libboost_signals.a $(LIBDIR)libboost_iostreams.a $(LIBDIR)libboost_system.a $(LIBDIR)liblog4cplus.a

Shared lib with dynamic linking:

This is my shared lib GCC command:

And it works.

Shared lib with static linking:

I thought I can just replace -shared with -static:

g++ -m64 -Wl,--trace -D NDEBUG -I /usr/include/ -I /usr/local/include  -L /usr/lib/x86_64-linux-gnu/ -static -lboost_serialization -lboost_thread -lboost_date_time -lboost_signals -lboost_iostreams -lboost_system -llog4cplus -lcrypto -lssl -lm -Wl,-soname,libLIBNAMEx64_static_link.so -o ../Release/libLIBNAMEx64_static_link.so ... and much more .o files ...

But I get undefined reference errors everywhere.

So where do I configure how are dependencies linked with my binary? How can I achieve my goal?

More things I tried (edit)

-Wl,--library:

I also tried passing libraries directly to linker in a very assertive manner:

-Wl,--library=:/usr/lib/x86_64-linux-gnu/libboost_serialization.a

And without : (which prevents searching for .a):

 -Wl,--library=/usr/lib/x86_64-linux-gnu/libboost_serialization.a

But I get the error:

  /usr/bin/ld: cannot find -l/usr/lib/x86_64-linux-gnu/libboost_serialization.a

Of course, the file exists at that path.

Pass just library names:

Of course, here it's not even interpreted as linking command:

g++: error: libboost_serialization.a: No such file or directory

Interesting is that if I pass full path instead (/usr/lib/x86_64-linux-gnu/libboost_iostreams.a), GCC doubles it:

g++: error: /usr/lib/x86_64-linux-gnu//usr/lib/x86_64-linux-gnu/libboost_signals.a: No such file or directory

Upvotes: 5

Views: 4406

Answers (2)

Jack47
Jack47

Reputation: 194

Use command man ld, I got this information:

-static

Do not link against shared libraries. It affects library searching for -l options which follow it. This option also implies --unresolved-symbols=report-all. This option can be used with -shared. Doing so means that a shared library is being created but that all of the library's external references must be resolved by pulling in entries from static libraries.

This option is exactly what you want: create a shared library with all dependencies (mostly boost) statically linked.

-l parameter is used to specify the library name, so you should use boost_serialization instead of /path/libboost_serialization.a:

-larchive

If you specify -lcommon, then ld will search its path-list for occurrences of "libcommon.a" for every common specified.

You can use -L parameter many times to specify the library paths when ld try to search static libraries:

-Lsearchdir

For example: -L/usr/lib/x86_64-linux-gnu/

Upvotes: 2

Devolus
Devolus

Reputation: 22074

You could try -Wl,--whole-archive ${your library} -Wl,--no-whole-archive.

Upvotes: 0

Related Questions