no sources given to target 错误主因是add_library()传入空源文件列表,常见于变量未定义、glob无匹配、路径错误、作用域失效或类型参数位置颠倒。

直接说结论:No SOURCES given to target 错误,90% 是因为 add_library() 调用时传入的源文件列表为空或路径无效 —— 不是 CMake 本身坏了,而是你给它“空篮子”让它编译。
为什么 add_library 报“No SOURCES given to target”?
这个错误发生在 CMake 配置阶段(configure),说明 add_library() 命令展开后实际收到的是空参数,比如:
-
add_library(mylib ${SOURCES})中SOURCES变量未定义、为空,或被覆盖成空字符串 -
file(GLOB SOURCES "*.cpp")执行后目录下根本没匹配到任何.cpp文件(注意:GLOB 不会递归,除非加_RECURSE) - 用了
aux_source_directory(./src SRCS),但当前目录下根本没有./src这个子目录 - 在子目录
CMakeLists.txt里定义了变量,却在父目录里直接引用,作用域失效
add_library 源文件路径写错的典型表现
相对路径始终以 CMAKE_CURRENT_SOURCE_DIR 为起点,不是项目根目录,也不是执行 cmake 命令的路径。常见踩坑点:
-
add_library(mylib src/main.cpp)→ 如果CMakeLists.txt在project/目录,而src/实际在project/app/src/,就会找不到 -
file(GLOB SRCS "src/*.cpp")→ 若CMakeLists.txt在project/app/,那"src/*.cpp"就是相对于app/src/,而非project/src/ - Qt 项目中漏掉
.h文件:含Q_OBJECT的头文件必须显式加入源列表,或用qt6_wrap_cpp()处理,否则 MOC 步骤失败,有时也表现为 SOURCES 为空
怎么安全地收集源文件并传给 add_library?
别依赖手写路径拼接,优先用 file(GLOB_RECURSE) 并加 CONFIGURE_DEPENDS 保证增量构建可靠:
file(GLOB_RECURSE MY_SOURCES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
)
# 确保非空再调用
if(NOT MY_SOURCES)
message(FATAL_ERROR "No source files found in src/ directory")
endif()
add_library(mylib ${MY_SOURCES})
-
CONFIGURE_DEPENDS让 CMake 在每次 configure 时重新扫描文件,避免删了文件后仍缓存旧列表 - 用
${CMAKE_CURRENT_SOURCE_DIR}显式锚定路径,杜绝相对路径歧义 - Qt 项目中若用
set(CMAKE_AUTOMOC ON),.h文件可不列进add_library(),但必须确保它们被target_include_directories()覆盖,且Q_OBJECT宏存在
add_library 类型和变量混用的隐性陷阱
类型参数(STATIC/SHARED)和源文件列表位置不能颠倒,且变量展开必须可见:
- 错误写法:
add_library(mylib ${SRC_LIST} SHARED)→ 类型必须紧挨库名,否则 CMake 当作源文件名处理,SHARED被当成一个不存在的源文件 - 正确顺序:
add_library(mylib SHARED ${SRC_LIST}) - 如果全局设置了
set(BUILD_SHARED_LIBS ON),又没显式指定类型,add_library(mylib ${SRC_LIST})会生成动态库;但若某处误设BUILD_SHARED_LIBS OFF,同一行就变成静态库 —— 类型不明确容易引发跨平台行为差异 - 用
INTERFACE或OBJECT库时,源文件列表是必需的,但语义不同:add_library(myobj OBJECT foo.cpp)生成中间对象,不能直接链接,必须用$<myobj></myobj>引用
最常被忽略的一点:CMake 不报错不代表源文件真被用了。即使 add_library() 成功执行,若后续没通过 target_include_directories() 暴露头文件路径,或没用 target_link_libraries() 关联依赖,编译仍会在链接或头文件包含阶段失败 —— “过了 configure”不等于“能跑通”。











