如何通过CMakeLists.txt识别FetchContent引入的正确CMake目标名称
问题
使用CMake的FetchContent功能引入第三方库时遇到如下问题:
链接nlohmann_json库时使用nlohmann_json::nlohmann_json可正常运行,但链接TgBot库时使用TgBot::TgBot会报错:
CMake Error at CMakeLists.txt:61 (target_link_libraries):
Target "tgpost1" links to:TgBot::TgBotbut the target was not found.
将其替换为TgBot则可正常运行。原本以为CMake目标名称的通用规则是PROJECT_NAME::TARGET_NAME,但为何该规则对部分库不生效?如何通过阅读目标库的CMakeLists.txt来确定正确的目标名称,而非猜测是否需要添加命名空间前缀?
相关CMakeLists.txt代码片段:
FetchContent_Declare( nlohmann_json GIT_REPOSITORY https://github.com/nlohmann/json GIT_TAG v3.11.3 GIT_SHALLOW TRUE) FetchContent_Declare( TgBot GIT_REPOSITORY https://github.com/reo7sp/tgbot-cpp GIT_TAG v1.8 GIT_SHALLOW TRUE) FetchContent_MakeAvailable(TgBot) FetchContent_MakeAvailable(nlohmann_json) add_executable(tgpost1 tgpost1.cpp) target_include_directories(tgpost1 PUBLIC ${CMAKE_SOURCE_DIR}/include) target_link_libraries(tgpost1 PUBLIC TgBot::TgBot) target_link_libraries(tgpost1 PUBLIC nlohmann_json::nlohmann_json)
解决思路与方法
为什么PROJECT_NAME::TARGET_NAME规则不通用
CMake并没有强制要求第三方库必须使用带命名空间前缀的目标名,这完全取决于库自身的CMake配置实现:
- nlohmann_json的CMake配置中,通过
add_library(nlohmann_json::nlohmann_json ALIAS nlohmann_json)这类语句,给基础目标设置了带命名空间的别名,所以可以用nlohmann_json::nlohmann_json来链接。 - TgBot的CMake配置里只创建了
TgBot这个无命名空间的基础目标,没有额外设置带命名空间的别名,因此只能直接使用TgBot作为链接目标。
如何从库的CMakeLists.txt确定正确目标名
直接查看第三方库根目录的CMakeLists.txt,重点关注以下几类语句:
- 目标创建语句:找
add_library()的调用,比如TgBot的CMakeLists.txt中会有add_library(TgBot ...)的代码,这里的TgBot就是可直接使用的目标名。 - 别名设置语句:找
add_library(... ALIAS ...)的配置,如果存在add_library(xxx::xxx ALIAS xxx)这类代码,就说明可以使用带命名空间的别名作为链接目标。 - 导出目标语句:查看
install(EXPORT ...)或export(TARGETS ...)的内容,其中列出的目标名就是库对外提供的正式链接目标。
举个实际例子:查看TgBot的CMakeLists.txt,会发现它只定义了基础目标TgBot,没有配置命名空间别名;而nlohmann_json的CMakeLists.txt明确添加了带命名空间的别名,因此两者的链接目标名格式不同。
内容的提问来源于stack exchange,提问作者JF4
相关产品推荐
相关产品推荐

