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
On Linux, shared libraries can be made by also linking other shared libraries inside them. So you could
- Compile all source code (including the C wrapping code) with
-fPIC
into *.pic.o
files
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).