如何为‘UNKNOWN IMPORTED’库添加add_dependencies?附Googletest依赖问题
我来帮你搞定这个CMake构建GoogleTest时的依赖坑!你遇到的问题核心在于:当你把GoogleTest标记为IMPORTED目标但它还没被实际构建出来时,CMake会将其归类为"UNKNOWN IMPORTED",这时候add_dependencies()确实会被静默忽略——因为CMake默认认为IMPORTED目标是已经存在的系统级库,不需要额外依赖构建。
下面给你几种针对性的解决方案,按推荐优先级排序:
1. 推荐用FetchContent(CMake 3.14+)的标准写法
这是目前CMake管理第三方依赖最省心的方式,它会自动处理GoogleTest的下载、构建和依赖关联,完全不需要手动加add_dependencies():
include(FetchContent) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.12.1 # 替换成你需要的版本号 ) # Windows下强制使用和项目一致的CRT,避免运行时冲突 set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) # 自动完成下载、配置、构建,并导入GTest的目标 FetchContent_MakeAvailable(googletest) # 创建你的测试可执行文件 add_executable(my_test test.cpp) # 直接链接GTest的官方目标,CMake会自动处理依赖关系 target_link_libraries(my_test PRIVATE GTest::gtest GTest::gtest_main)
FetchContent_MakeAvailable会把GoogleTest的目标(GTest::gtest、GTest::gtest_main等)从"UNKNOWN IMPORTED"转为可构建的目标,构建时Ninja会自动先编译GoogleTest,再编译你的测试程序。
2. 旧版本CMake用ExternalProject的处理方式
如果你的CMake版本低于3.14,只能用ExternalProject,这时候需要手动把ExternalProject的构建目标和你的测试目标关联:
include(ExternalProject) ExternalProject_Add( googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG release-1.12.1 # 指定安装目录,方便后续find_package找到 CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/gtest_install -Dgtest_force_shared_crt=ON ) # 从安装目录导入GTest的目标 find_package(GTest REQUIRED PATHS ${CMAKE_BINARY_DIR}/gtest_install) # 创建测试可执行文件 add_executable(my_test test.cpp) target_link_libraries(my_test PRIVATE GTest::gtest GTest::gtest_main) # 关键:把ExternalProject创建的googletest目标作为测试程序的依赖 add_dependencies(my_test googletest)
这里要注意:你要依赖的是ExternalProject_Add创建的googletest目标(也就是下载构建GTest的那个任务),而不是find_package得到的GTest::gtest——后者依然是IMPORTED目标,依赖它没用。
为什么你之前的add_dependencies()没效果?
你大概率是把依赖加给了GTest::gtest这个IMPORTED目标,但CMake对IMPORTED目标的依赖规则是:只有当该目标的IMPORTED_LOCATION等属性被正确设置,且是"已解析"的导入目标时,add_dependencies()才会生效。而当GTest还没被构建时,这个目标处于"UNKNOWN"状态,CMake会直接忽略对它的依赖添加请求。
额外排查小技巧
- 检查CMake输出日志,看GoogleTest是否被正确下载和初始化,有没有报错信息;
- 用
ninja -v运行构建,查看详细的链接命令,确认是否包含了GoogleTest的构建目录; - 确保没有在
FetchContent_MakeAvailable之前调用find_package(GTest),否则CMake会优先找系统自带的GTest,跳过你要构建的版本。
内容的提问来源于stack exchange,提问作者dani

