参考这个博客: cmake配置项目引用动态库
编写CMakeLists.txt
指定cmake版本:
cmake_minimum_required(VERSION 3.18)
指定项目名:
PROJECT(lib_demo)
将主项目src文件夹下的所有源文件拷贝到变量demo_src中:
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src demo_src)
指定 cmake搜索库路径:
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
重点来了,项目引用动态库:
FIND_PACKAGE(calc REQUIRED)
创建可执行程序:
add_executable(${PROJECT_NAME} ${demo_src})
生成静态库 libmylib.a :
add_library(mylib STATIC ${SOURCES})
生成动态库 libmylib.so :
add_library(mylib SHARED test.cpp)
指定要生成的静态库(STATIC)或动态库(SHARED),如果不指定,则根据BUILD_SHARED_LIBS选项是否打开来生成默认的版本,ON 生成动态库,OFF 生成静态库
主项目指定库头文件路径:
target_include_directories(${PROJECT_NAME} PUBLIC ${calc_INCLUDE_DIR})
注意: calc_INCLUDE_DIR
来自cmake文件中定义的变量,方便下游使用
主项目链接库:
target_link_libraries(${PROJECT_NAME} PUBLIC ${calc_LIBRARY})
例:target_link_libraries(demo PUBLIC test)
demo是可执行文件名 或者 库名,该指令会在链接库目录(包括系统默认库目录和指定的自定义库目录)下搜索文件:
- Windows下会搜索
test.lib
文件; - Linux下会搜索
libtest.a
和libtest.so
对于target_link_libraries()
- 如果 target 是一个 library,该命令可以用来指定依赖本仓库的 target 还需要链接另外的仓库,用于解决循环依赖;
- 如果 target 是可执行文件,则该命令用于指定其需要链接的库;
- 如果link的target已经
include
过XXX了,就不用再target_include_directories
添加库文件路径了。
以下举例一句一句说明:
# 代码路径
set(SOURCES_PATH ../../../src)
glob_sources(TEST_NODE_SOURCES ${SOURCES_PATH}/pinecone/nodes/camera/lane_detection)
#创建可执行程序,test_node就是生成的可执行文件名
add_executable(test_node ${TEST_SOURCES})
#指定本节点动态库头文件路径,即指定编译 target 所需要的头文件。PUBLIC 和 INTERFACE 具有依赖传递性,而 PRIVATE 没有。:
target_include_directories(test_node PUBLIC ${SOURCES_PATH})
# 为可执行文件链接库
target_link_libraries(test_node pinecone camera_common camera_rosap opencv tensorrt-pix2pix h265decoder)
set_target_properties(test_node PROPERTIES LINK_FLAGS ${COMMON_LINK_FLAG})
本例中target_link_libraries()
是为可执行文件链接库时,其中的一个库camera_common
库是通过下面的命令生成的库:
glob_sources(CAMERA_COMMON_SOURCES ${SOURCES_PATH}/pinecone/nodes/camera/common)
add_library(camera_common ${CAMERA_COMMON_SOURCES})
target_include_directories(camera_common PUBLIC ${SOURCES_PATH})
target_link_libraries(camera_common pinecone opencv )
若要测试动态链接是否成功,可以使用ldd指令查看:
ldd 二进制程序