示例项目结构
假设你的项目结构如下所示:
项目根目录/
├── CMakeLists.txt
├── include/
│ └── head.h
├── lib/
│ └── libcalc.a
└── src/
└── main.cpp
链接库
link_directories和 target_link_libraries指令用于配置和链接库文件。
link_directories
link_directories指令用于向链接器添加库文件搜索路径。这意味着当CMake生成构建系统时,它会告诉链接器在哪些额外的目录中搜索库文件。
语法
link_directories(directory1 directory2 ...)
示例
link_directories(${PROJECT_SOURCE_DIR}/libs)
这会将 ${PROJECT_SOURCE_DIR}/libs目录添加到库搜索路径中,链接器将会在这个目录下寻找库文件。
target_link_libraries
target_link_libraries指令用于为特定的目标(如可执行文件或其他库)指定要链接的库。这不仅包括链接库的名称,还可以指定链接的特定属性,如私有( PRIVATE)、接口( INTERFACE)或公共( PUBLIC)链接。
语法
target_link_libraries(target <PRIVATE|INTERFACE|PUBLIC> lib1 lib2 ...)
- target:指定要链接库的目标(可执行文件或库)。
- <PRIVATE|INTERFACE|PUBLIC>:指定链接范围,默认是 PUBLIC。如果各个动态库之间没有依赖关系,无需做任何设置,三者没有没有区别,一般无需指定,使用默认的 PUBLIC 即可。动态库的链接具有传递性,如果动态库 A 链接了动态库B、C,动态库D链接了动态库A,此时动态库D相当于也链接了动态库B、C,并可以使用动态库B、C中定义的方法。PRIVATE表示库仅用于该目标,不会传递给依赖它的其他目标; INTERFACE表示库仅用于目标的接口,用于目标的消费者; PUBLIC表示库既用于该目标,又用于依赖它的目标。
target_link_libraries(A B C)
target_link_libraries(D A)
- lib1 lib2...:要链接的库名称。如果库在标准路径下,直接使用库名即可;如果在非标准路径,确保已经通过 link_directories或其他机制添加了库的搜索路径。
示例
add_executable(myApp main.cpp)
target_link_libraries(myApp PRIVATE myLib)
这会为名为 myApp的目标链接名为 myLib的库。链接为 PRIVATE,意味着 myLib仅用于 myApp,不会传递给其他依赖 myApp的目标。
CMakeLists.txt配置
cmake_minimum_required(VERSION 3.0)
project(MyProject)
# 设置C++标准
set(CMAKE_CXX_STANDARD 11)
# 设置可执行文件的输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/)
# 添加头文件搜索路径
include_directories(${PROJECT_SOURCE_DIR}/include)
# 查找当前目录下的所有源文件,并将名称保存到 SRC_LIST 变量
file(GLOB SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c)
# 添加库搜索路径
link_directories(${PROJECT_SOURCE_DIR}/lib)
# 添加可执行文件
add_executable(app ${SRC_LIST})
# 链接静态库到可执行文件
target_link_libraries(app calc)
在这里, calc是库的名称(不包括前缀 lib和后缀 .a)。CMake智能地处理库名称,自动解析为正确的文件名。
如果是windows环境的动态库,还需要将dll复制到bin目录下。可以加上下面的命令或者手动翻译。
# 根据平台设置库文件名
if(WIN32)
set(LIB_FILE_NAME calc.dll)
else()
set(LIB_FILE_NAME libcalc.so)
endif()
# 复制动态库到可执行文件目录
add_custom_command(TARGET app POST_BUILD COMMAND
${CMAKE_COMMAND} -E copy_if_different
"${PROJECT_SOURCE_DIR}/lib/${LIB_FILE_NAME}"
lt;TARGET_FILE_DIR:app>
)