如何在安装时完全忽略BUILD_INTERFACE关联的依赖库?
问题:阻止私有依赖库被自动安装
我通过$<BUILD_INTERFACE:>表达式链接私有库,这些库不会出现在导出目标中,但它们自身链接的库会被包含进来,执行install规则时这些依赖库也会被自动安装。我无权修改这些依赖库的代码,请问怎么阻止它们被安装?
测试示例
TestingExports/CMakeLists.txt
cmake_minimum_required(VERSION 3.20 FATAL_ERROR) project(TestinExports CXX) add_subdirectory(ThatThing) file(WRITE main.cc "int main() { }") add_executable(${PROJECT_NAME} main.cc) target_link_libraries(${PROJECT_NAME} PRIVATE $<BUILD_INTERFACE:ThatThing>) install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Config) install(EXPORT ${PROJECT_NAME}Config DESTINATION lib/cmake)
ThatThing/CMakeLists.txt
cmake_minimum_required(VERSION 3.20 FATAL_ERROR) project(ThatThing CXX) add_subdirectory(ThoseLibraries) file(WRITE that_thing.cc "void Function() { }") add_library(${PROJECT_NAME} STATIC that_thing.cc) target_link_libraries(${PROJECT_NAME} PRIVATE ThoseLibraries)
ThatThing/ThoseLibraries/CMakeLists.txt
cmake_minimum_required(VERSION 3.20 FATAL_ERROR) project(ThoseLibraries CXX) file(WRITE those_libraries.cc "void AnotherFunction() { }") add_library(${PROJECT_NAME} STATIC those_libraries.cc) install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Config) install(EXPORT ${PROJECT_NAME}Config DESTINATION lib/cmake)
构建安装后的现象
执行以下命令后,ThoseLibraries会被自动安装:
$ cmake -B build -DCMAKE_INSTALL_PREFIX=$PWD/install $ cmake --build build $ cmake --install build -- Install configuration: "" -- Installing: /tmp/export_set/install/lib/libThoseLibraries.a -- Installing: /tmp/export_set/install/lib/cmake/ThoseLibrariesConfig.cmake -- Installing: /tmp/export_set/install/lib/cmake/ThoseLibrariesConfig-noconfig.cmake -- Installing: /tmp/export_set/install/bin/TestinExports -- Installing: /tmp/export_set/install/lib/cmake/TestinExportsConfig.cmake -- Installing: /tmp/export_set/install/lib/cmake/TestinExportsConfig-noconfig.cmake
已尝试的无效方案
- 使用
EXCLUDE_FROM_ALL完全无效:不想将目标从ALL目标中移除,同时需要保留IDE所需的完整项目信息。 - 重写
install()宏的方案失效:该方法会导致CMake忽略所有安装规则,无法保留自身项目的私有安装逻辑,示例代码如下:
macro(install) endmacro() add_subdirectory(ThatThing) macro(install) _install(${ARGV}) endmacro(install)
可行解决方案
通过临时禁用CMake的安装规则,跳过依赖库的install指令,同时保留自身项目的安装逻辑。具体修改主项目的CMakeLists.txt如下:
cmake_minimum_required(VERSION 3.20 FATAL_ERROR) project(TestinExports CXX) # 保存当前安装规则状态,临时禁用所有install规则 set(ORIGINAL_SKIP_INSTALL_RULES ${CMAKE_SKIP_INSTALL_RULES}) set(CMAKE_SKIP_INSTALL_RULES ON) # 添加依赖子目录,此时子目录中的install规则会被忽略 add_subdirectory(ThatThing) # 恢复原始安装规则状态,确保主项目的install规则正常执行 set(CMAKE_SKIP_INSTALL_RULES ${ORIGINAL_SKIP_INSTALL_RULES}) file(WRITE main.cc "int main() { }") add_executable(${PROJECT_NAME} main.cc) target_link_libraries(${PROJECT_NAME} PRIVATE $<BUILD_INTERFACE:ThatThing>) install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}Config) install(EXPORT ${PROJECT_NAME}Config DESTINATION lib/cmake)
原理说明
CMAKE_SKIP_INSTALL_RULES是CMake内置变量,当设为ON时,所有后续的install指令都会被跳过。- 在添加依赖子目录前临时开启该变量,就能忽略依赖库中的所有安装逻辑;添加完成后恢复变量状态,主项目的安装规则不受影响。
- 该方案无需修改依赖库的代码,也不会移除
ALL目标中的依赖库构建任务,能保留IDE的完整项目信息。
内容的提问来源于stack exchange,提问作者Ghasem Ramezani
相关产品推荐
相关产品推荐

