Build a C/C++ dynamic-link library
Contents
Sometimes we need to provide or use a third-party C/C++ dynamic-link libraries. This blog aims to teach how to build, install and use a C/C++ dynamic-link library.
Build and use manually
First, this is our construction:
1 | . |
Now we have a source file called hello.cc and a head file called hello.h:
1 | // hello.cc |
1 | // hello.h |
Compile source code to object(.o) file
1 | g++ hello.cc -c -fPIC |
- -c: only compile the source code and not link it with other files;
- -fPIC: the flag tells the complier to generate PIC(position-independent code), this is common in building dynamic library.
Link object file to library(libxxx.so) file
1 | g++ hello.o -shared -o libhello.so |
- -shared: to create a shared library;
- -o libxxx.so: to name the output file as libxxx.so.
Use the shared library
There is a source code called main.cc
use this shared library:
1 |
|
Now we can compile and link it to libhello.so:
1 | g++ main.cc -o main.out -L . -l hello |
- -L: tells the linker to look for library files in which directory, now it is current directory.
- -l xxx: tells the linker to link with the library file libxxx.so.
After we run command above, we can get a executable file called main.out, so we can execute it:
1 | ./main.out |
If met error that can’t load shared library like this:
1 | ./main.out: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory |
It’s related with default LD_LIBRARY_PATH, export it as current directory:
1 | export LD_LIBRARY_PATH=`pwd` |
Then we can get the sequence as we hope:
1 | Hello form dynamic-link libaray! |
Install header file
There is a new problem: if we use this shared library in other directories, source code can’t find needed head file like:
1 | main.cc:1:10: fatal error: hello.h: No such file or directory |
In order to make it convenient to include header file, we need to copy our head file to default search path, such as usr/local/include
or usr/include
.
1 | sudo cp ~/shared-lib-demo/hello.h /usr/local/include |
and run:
1 | g++ main.cc -o main.out -L ../shared-lib-demo/ -l hello |
Similar as we copy header file to default header file search path, we can also copy libhello.so to default library search path or add a link which point to libxxx.so in LD_LIBRARY_PATH, so that we don’t need to use -L ../shared-lib-demo/
.
Then we can get what we want:
1 | ./main |
Build and use with CMake
Dynamic-link library construction:
1 | . |
hello.h and hello.cc are as same as above, and test.cc is similar to main.cc.
The differences between building manually and building with CMake is that we just need to write a CMakeLists.txt rather than run command line by line. Of course, we should install Cmake and GNU make before we use it.
Let’s take a consideration about what we need do to build and use a dynamic-link library:
- Adding source code to shared library;
- Including header directories when write code that use the library;
- Linking new project with our library.
Build source code for shared library
In order to link it conveniently, we can install our library so that we can use it directly.
So the CMakeLists.txt looks like:
1 | # set version requirement and project name |
For test it, we can make a directory called build and cd build
, run:
1 | cmake .. # out source compile |
Then you well get a executable called test.out which can let you run and test it.
To install, just run make install
after run make
.
Use installed library in new project
New project directory:
1 | . |
main.cc:
1 |
|
It’s no doubt that we need tell the new project that it should depend the shard library, so write it in cmake:
1 | cmake_minimum_required(VERSION 3.16) |
Run
1 | mkdir build |
You can get main.out as we expect.