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

CMake中从库生成可执行文件并实现跨库链接的问题

问题原因与解决方法

你犯的核心错误是把库目标名当成源文件传给了add_executable。add_executable的参数规则是:第一个是可执行目标名,后面跟的都是编译该可执行文件需要的源文件路径,CMake会把foo-lib、bar-lib当成源文件名去磁盘查找,自然找不到,所以报错。

正确的CMake写法

要实现「用库生成可执行文件+库之间互相链接」,应该遵循「先定义库/可执行目标,再通过target_link_libraries建立链接依赖」的规则:

# 构建foo静态库
add_library(foo-lib STATIC src/foo.cpp)
target_include_directories(foo-lib PUBLIC include) # 把include目录暴露给依赖foo-lib的目标

# 构建foo的测试可执行文件:这里要传测试源文件,比如foo的单元测试代码src/foo_ut.cpp
add_executable(foo-ut src/foo_ut.cpp)
target_link_libraries(foo-ut PRIVATE foo-lib lib1 lib2) # 把foo-lib和其他依赖库链接到foo-ut

# 构建bar静态库,并链接foo-lib
add_library(bar-lib STATIC src/bar.cpp)
target_link_libraries(bar-lib PRIVATE foo-lib) # bar-lib依赖foo-lib,自动继承foo-lib的include目录
target_include_directories(bar-lib PUBLIC include)

# 构建bar的测试可执行文件
add_executable(bar-ut src/bar_ut.cpp)
target_link_libraries(bar-ut PRIVATE bar-lib) # 只需要链接bar-lib,bar-lib已经依赖foo-lib,会自动传递链接

关键细节说明

  • target_include_directories用PUBLIC/PRIVATE控制目录的可见性:如果库的头文件需要被依赖它的目标使用,就用PUBLIC,这样依赖方不需要再重复写include目录。
  • target_link_libraries里的库目标会自动处理依赖传递,比如bar-ut链接bar-lib后,CMake会自动把foo-lib也链接进去,不需要手动重复写。

关于直接添加源文件的方式

你提到的add_executable(bar-ut src/foo.cpp src/bar.cpp)确实能运行,但非常不推荐:

  • 重复编译:foo.cpp会被编译两次(一次在foo-lib,一次在bar-ut),浪费编译时间。
  • 维护性差:如果后续foo.cpp的路径、文件名修改,你需要手动在所有直接引用它的地方更新,而用库的话只需要修改foo-lib的定义即可。
  • 依赖关系混乱:无法清晰体现bar-ut是依赖bar-lib和foo-lib的,CMake的目标依赖管理能力完全没用到。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 22:50:28