Embed all external references when creating a stat

2019-03-05 11:36发布

问题:

I need to create a wrapper library for C code that wraps my C++ library. Is there a way to create that wrapper library in such a way, that the user needs to link only this wrapper library and doesn't have to include all the (C++) libraries on the linker command line as well?

The structure of my test project looks like this:

.
├── lib
│   ├── cpp
│   │   ├── print.cc
│   │   └── print.h
│   ├── lib.cc
│   ├── lib.h
└── main.c

The main.c is an example C application that uses my library. The lib.h and lib.cc files are the wrapper library containing the C bindings. My C++ library resides in the cpp subfolder.

At the moment I have it working by using the following chain of commands:

cd lib
g++ -c lib.cc
ar rcs libib.a lib.o
cd ..
gcc -Ilib -Llib main.c -lib -lstdc++

However, as you can see the linker step of the user needs to include the C++ libraries used in my C++ library. In this case the libstdc++.so (or libstdc++.a if -static is used).

I'd like to include all C++ libraries in my libib.a such that the user can simply use the following command for compilation:

gcc -Ilib -Llib main.c -lib

回答1:

On Linux, shared libraries can be made by also linking other shared libraries inside them. So you could

  1. Compile all source code (including the C wrapping code) with -fPIC into *.pic.o files
  2. Merge all these files into a shared library linking needed libraries, e.g.

    g++ -shared *.pic.o -o libmy.so -lQt -lrt -lstdc++

Then you can use simply your libmy.so as gcc main.o -L. -lmy and this will link the other libraries.

Look for example at Parma Polyhedra Library, it has a libppl_c.so in C wrapping a libppl.so in C++. Use ldd to list the dependent libraries:

 % ldd /usr/lib/x86_64-linux-gnu/libppl_c.so.4
linux-vdso.so.1 =>  (0x00007fffa17cf000)
libppl.so.9 => /usr/local/lib/libppl.so.9 (0x00007fcfec5f1000)
libpwl.so.5 => /usr/local/lib/libpwl.so.5 (0x00007fcfec3ed000)
libgmpxx.so.4 => /usr/lib/x86_64-linux-gnu/libgmpxx.so.4 (0x00007fcfec1c5000)
libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fcfebf56000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fcfebc4f000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fcfeb9cc000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcfeb645000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fcfeb42f000)
libgmp.so.3 => /usr/lib/libgmp.so.3 (0x00007fcfeb1d2000)
/lib64/ld-linux-x86-64.so.2 (0x00007fcfecf11000)

This is on Debian/Sid/AMD64

A general advice is to avoid building static libraries (using ar and possibly ranlib). Build shared libraries instead.

You cannot do equivalent things on static libraries because a static library is simply a sequence of object files, nothing more. (there is no metadata space for the dependency information you dream about).