概述
cmake生成和使用so库,主要用到了add_library,target_link_libraries这两个命令。
测试项目1(指定so库位置)
概述
我们首先在/home/SOTest路径下创建两个项目,demo1和demo2,其中build为文件夹,格式如下:
demo1
该项目为生成一个测试的so库,供demo2调用使用。
代码
hello.c文件,提供hello方法,可打印hello:
#include <stdio.h>
void hello() {
printf("hello\n");
}
CMakeLists.txt:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (HelloSharedLib)
# 创建共享库,SHARED代表为生成动态库
add_library(hello_shared_lib SHARED hello.c)
生成
cd build
cmake ..
make
执行后,可以在build中看到生成so文件:
demo2
该项目为应用程序,调用demo1生成的so库。
代码
main.c文件:
// main.c
#include <stdio.h>
// 前置声明hello函数
void hello();
int main() {
hello();
return 0;
}
CMakeLists.txt:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (HelloApp)
# 添加可执行文件
add_executable(hello_app main.c)
# 链接共享库到主程序
target_link_libraries(hello_app "/home/SOTest/demo1/build/libhello_shared_lib.so")
生成
cd build
cmake ..
make
执行后,运行程序,可以看到输出hello代表调用so库成功:
测试项目2(指定系统库)
概述
观察测试项目1的demo2的CMakeLists.txt的target_link_libraries,可以看到是指定了so库的绝对路径,其实target_link_libraries也可以直接链接系统的库,本项目将demo1生成so库安装到系统,然后demo2直接链接系统库。
demo1
代码
CMakeLists.txt:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (HelloSharedLib)
# 创建共享库
add_library(hello_shared_lib SHARED hello.c)
# 设置库的安装路径
# 其中lib为要安装的路径,最好是全路径,如果仅指定了目录名称,默认会输出到/usr/local/XXX目录下
install(TARGETS hello_shared_lib LIBRARY DESTINATION lib)
生成
cd build
cmake ..
make
make install
需要执行make install才行,执行后make install后,可以看到/usr/local/lib下有so文件:
demo2
代码
CMakeLists.txt:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (HelloApp)
# 添加可执行文件
add_executable(hello_app main.c)
# 找系统的库,实际库的文件名为libhello_shared_lib.so,下面是支持/不支持的名称:
# 1.libhello_shared_lib.so 支持
# 2.hello_shared_lib.so 不支持
# 3.libhello_shared_lib 不支持
# 4.hello_shared_lib 支持
find_library(hello-lib hello_shared_lib)
# 链接共享库到主程序
target_link_libraries(hello_app ${hello-lib})
生成
cd build
cmake ..
make
执行后,运行程序,可以看到输出hello代表调用so库成功:
扩展
find_library不一定只能用到找系统的库上,也能支持指定路径,假设/home/SOTest/demo1/build中有libhello_shared_lib.so,格式如:
find_library(hello-lib hello_shared_lib HINTS /home/SOTest/demo1/build)
其中hello_shared_lib为库名,/home/SOTest/demo1/build为要找的目录路径。
疑问
观察上面的CMakeLists.txt,我们可以会想,如果去掉
find_library(hello-lib hello_shared_lib)
这一行代码,然后把
target_link_libraries(hello_app ${hello-lib})
直接替换成
target_link_libraries(hello_app hello_shared_lib)
这样可不可行?
通过测试,虽然能行make成功,但是运行时会报错:
测试项目3(so库链接so库)
概述
so库可以链接so库,再给程序调用。
demo1
demo1参考测试项目1
demo_transit
代码
hello.c
#include <stdio.h>
void hello();
void helloTransit() {
hello();
}
CMakeLists.txt:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (HelloSharedLib)
# 创建共享库
add_library(hello_shared_lib_transit SHARED hello.c)
# 链接共享库
target_link_libraries(hello_shared_lib_transit "/home/SOTest/demo1/build/libhello_shared_lib.so")
生成
cd build
cmake ..
make
demo2
代码
main.c文件:
// main.c
#include <stdio.h>
// 前置声明helloTransit函数
void helloTransit();
int main() {
helloTransit();
return 0;
}
CMakeLists.txt:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (HelloApp)
# 添加可执行文件
add_executable(hello_app main.c)
# 链接共享库到主程序
target_link_libraries(hello_app "/home/SOTest/demo_transit/build/libhello_shared_lib_transit.so")
生成
cd build
cmake ..
make
疑问
demo_transit项目中,能不能不写helloTransit方法,只有hello方法,然后demo2直接去调用hello方法?
经过测试,不行,会报类似以下错误:
问题
so库如果有main方法,会不会跟调用该库的程序冲突?
通常,共享库不应该包含 main 函数。不过经测试,没有影响,调用该库的程序运行后,能执行该main。通常,链接器会使用可执行文件中的 main 函数作为程序的入口点,而忽略共享库中的 main 函数。