You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake中添加的导入库目标为何在install时提示不存在?

问题描述

以下是一段CMake代码,定义了用于添加导入库目标的宏,并调用该宏添加了两个导入目标:

cmake_minimum_required(VERSION 3.24)
project(dummy)

# etc. etc.

set(installation_targets "")
macro(add_cc_lib lib_name static_or_shared relative_lib_archive_path)
    set(tgt ${lib_name})
    if(${static_or_shared} STREQUAL "STATIC")
        string(APPEND tgt "_static")
    endif()
    add_library(${tgt} ${static_or_shared} IMPORTED)
    message("added library ${tgt} with mode ${static_or_shared} IMPORTED GLOBAL")
    set_target_properties(${tgt} PROPERTIES IMPORTED_LOCATION ${PETMR_CLEARCASE_DEVEL_ROOT}/${relative_lib_archive_path})
    foreach(arg IN ITEMS ${ARGN})
        if(${arg} STREQUAL "NO_SONAME")
            set_target_properties(${tgt} PROPERTIES IMPORTED_NO_SONAME TRUE)
        else()
            target_include_directories(${tgt} SYSTEM INTERFACE ${PETMR_CLEARCASE_DEVEL_ROOT}/${arg})
        endif()
    endforeach()
    list(APPEND installation_targets ${tgt})
endmacro()

add_cc_lib( bar STATIC foo/bar.a   foo/include )
add_cc_lib( baz SHARED foo/baz.a   foo/include )

include(GNUInstallDirs)

message(STATUS "installation_targets are \"${installation_targets}\"")
install(
    TARGETS ${installation_targets}
    EXPORT ${PROJECT_NAME}_export
    RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
    ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
    LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
    INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)

在GNU/Linux系统上使用CMake 3.31.6执行该代码时,能看到目标名称已被添加到installation_targets列表,但执行install指令时,CMake提示目标不存在,报错信息如下:

$ cmake -B build
added library bar_static with mode STATIC IMPORTED
added library baz with mode SHARED IMPORTED
installation_targets are "bar_static;baz"
CMake Error at CMakeLists.txt:31 (install):
  install TARGETS given target "bar_static" which does not exist.


-- Configuring incomplete, errors occurred!
问题原因

核心原因是宏内部创建的导入目标默认仅存在于宏的作用域内,宏执行完毕后,这些目标会超出作用域,后续的install指令无法找到它们。

CMake的宏(macro)基于文本替换实现,其作用域与调用上下文隔离——在宏内部通过add_library创建的导入目标,默认不会暴露到宏外部的全局作用域。虽然目标名称被添加到了installation_targets列表,但实际的目标实体在宏执行结束后就失效了,导致install指令无法识别对应的目标。

解决方法:在创建导入目标时添加GLOBAL关键字,将目标注册为全局可见:

add_library(${tgt} ${static_or_shared} IMPORTED GLOBAL)

添加后,目标会保留在全局作用域中,宏执行完毕后依然有效,install指令就能正常处理这些目标了。

内容的提问来源于stack exchange,提问作者einpoklum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 15:05:06