CMake:缺失外部预编译库时自动复制库文件的实现问题
预编译库依赖的CMake配置问题解决
问题背景
我有一个依赖外部预编译库mylib的C++项目simple_test,现有CMake配置可正常构建链接。需求是:当external_dependencies目录下的libmylib.a不存在时,从其他位置将其复制到该目录。尝试两种方案均存在问题:
- 使用
add_custom_command+自定义目标:能完成复制,但每次构建都会执行复制操作; - 使用IMPORTED库:出现
no rule found错误,无法构建。
项目文件结构
CMakeLists.txt main.cpp external_dependencies/ libmylib.a
初始可正常构建的CMake配置
cmake_minimum_required(VERSION 3.17) project(simple_test) set(CMAKE_CXX_STANDARD 17) add_executable(simple_test main.cpp) target_link_directories(simple_test PUBLIC external_dependencies/ ) target_link_libraries(simple_test mylib )
两种尝试的错误分析与修正
方案一:add_custom_command+自定义目标(每次构建都执行复制)
原错误配置
add_custom_command( OUTPUT external_dependencies/libmylib.a WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cp depsrc/libmylib.a external_dependencies/ COMMENT "CreatedLib" ) add_custom_target(mylib_target DEPENDS external_dependencies/libmylib.a ) add_dependencies(simple_test mylib_target )
问题原因
自定义目标mylib_target默认被标记为总是需要重新构建,因此每次执行make时都会触发对应的add_custom_command,即使libmylib.a已经存在且未发生变化。
修正方案
给add_custom_command添加源文件依赖,仅当源文件depsrc/libmylib.a更新或目标文件external_dependencies/libmylib.a不存在时,才执行复制操作:
add_custom_command( OUTPUT external_dependencies/libmylib.a WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cp depsrc/libmylib.a external_dependencies/ COMMENT "Copying mylib to external_dependencies" # 添加源文件依赖,仅当源文件变化或目标文件不存在时执行 DEPENDS depsrc/libmylib.a ) add_custom_target(mylib_target DEPENDS external_dependencies/libmylib.a) add_dependencies(simple_test mylib_target)
如果希望完全避免无意义的命令执行,也可以在COMMAND中加入存在性判断:
COMMAND if [ ! -f external_dependencies/libmylib.a ]; then cp depsrc/libmylib.a external_dependencies/; fi
方案二:IMPORTED库(出现no rule found错误)
原错误配置
target_link_libraries(simple_test mylib_target ) add_library(mylib_target STATIC IMPORTED) set_property(TARGET mylib_target PROPERTY IMPORTED_LOCATION external_dependencies/libmylib.a ) add_custom_command( OUTPUT external_dependencies/libmylib.a WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cp depsrc/libmylib.a external_dependencies/ COMMENT "CreatedLib" )
问题原因
- 顺序错误:
target_link_libraries在add_library定义mylib_target之前调用,CMake无法识别该目标; - 未关联依赖:IMPORTED库的目标文件
external_dependencies/libmylib.a由自定义命令生成,但未将IMPORTED目标与该生成操作关联,CMake不知道如何生成这个文件。
修正方案
调整命令顺序,并将IMPORTED目标与自定义命令的输出关联:
# 1. 先定义生成目标文件的自定义命令 add_custom_command( OUTPUT external_dependencies/libmylib.a WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND cp depsrc/libmylib.a external_dependencies/ COMMENT "Copying mylib to external_dependencies" DEPENDS depsrc/libmylib.a ) # 2. 定义IMPORTED库目标 add_library(mylib_target STATIC IMPORTED GLOBAL) set_target_properties(mylib_target PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/external_dependencies/libmylib.a ) # 3. 让IMPORTED库依赖于自定义命令的输出,确保复制操作先于链接执行 add_dependencies(mylib_target external_dependencies/libmylib.a) # 4. 最后链接到可执行文件 target_link_libraries(simple_test mylib_target)
内容的提问来源于stack exchange,提问作者David Woo
相关产品推荐
相关产品推荐

