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

如何将一个CMake对象库链接到另一个CMake对象库?

关于CMake对象库依赖传递的链接问题

问题场景

调用链:main 调用 object2 的函数,object2 调用 object1 的函数。object2 和 object1 均为CMake对象库(object libraries),通过$<TARGET_OBJECTS:xxx>传递对象文件,用target_link_libraries设置依赖关系,但构建时出现链接错误。

项目结构

project
 |-- main
 |    |-- main.c
 |-- object2
 |    |-- object2.h
 |    |-- object2.c
 |-- object1
 |    |-- object1.h
 |    |-- object1.c
 |-- CMakeLists.txt

初始CMakeLists.txt内容

// CMakeLists.txt

project(objlibs)

# Object library 1
add_library(ObjectLibrary1 OBJECT object1/object1.c)
target_include_directories(ObjectLibrary1 INTERFACE object1)

# Object library 2
add_library(ObjectLibrary2 OBJECT object2/object2.c $<TARGET_OBJECTS:ObjectLibrary1>)
target_include_directories(ObjectLibrary2 INTERFACE object2)
target_link_libraries(ObjectLibrary2 PUBLIC ObjectLibrary1)

# Final executable or library
add_executable(MyTarget
    main/main.c
    $<TARGET_OBJECTS:ObjectLibrary2>
)
target_link_libraries(MyTarget PRIVATE ObjectLibrary2)

链接错误信息

ld.exe: CMakeFiles/ObjectLibrary2.dir/object2/object2.obj:object2.c:(.text+0x18): undefined reference to `obj1func'
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

临时解决方法

手动在add_executable中添加$<TARGET_OBJECTS:ObjectLibrary1>即可正常链接:

add_executable(MyTarget
    main/main.c
    $<TARGET_OBJECTS:ObjectLibrary2>
    $<TARGET_OBJECTS:ObjectLibrary1>
)

但从依赖关系逻辑来看,这一步应该是多余的——ObjectLibrary2已经依赖ObjectLibrary1,理应自动传递对象文件。

源码文件内容

object1.h

#ifndef OBJECT1_H
#define OBJECT1_H
void obj1func(void);
#endif // OBJECT1_H

object1.c

#include "object1.h"
#include <stdio.h>
void obj1func(void){
    printf("obj1func\n");
}

object2.h

#ifndef OBJECT2_H
#define OBJECT2_H
void obj2func(void);
#endif // OBJECT2_H

object2.c

#include "object2.h"
#include <stdio.h>
#include "object1.h"
void obj2func(void){
    printf("obj2func\n");
    obj1func();
}

main.c

#include <stdio.h>
#include "object2.h"
int main(){
    printf("Hello world\n");
    obj2func();
}

测试环境

  • WSL (Ubuntu 20.04.5 LTS), Ninja (1.10.0), clang (10.0.0)
  • WSL (Ubuntu 20.04.5 LTS), makefiles (4.2.1), gcc (9.4.0)
  • Windows (10 22H2 19045.2486), Visual Studio 16, MSVC (19.29.30146.0)
  • Windows (10 22H2 19045.2486), Ninja (1.11.0), clang (15.0.0)
  • Windows (10 22H2 19045.2486), makefiles (4.3 for Win32), gcc (12.2.0)

构建命令

cmake -B build/main -S .
cmake --build build/main --config Debug --verbose --clean-first

所有环境下均出现相同问题。


问题原因与正确写法

CMake对象库的target_link_libraries仅会传递使用要求(如头文件路径、编译选项),不会自动传递依赖对象库的文件本身。初始写法中,虽然ObjectLibrary2的源列表里包含了$<TARGET_OBJECTS:ObjectLibrary1>,但CMake不会将这些嵌套的对象文件自动传递到引用ObjectLibrary2的最终可执行目标中。

推荐写法:直接将对象库作为源文件

不需要手动使用$<TARGET_OBJECTS:xxx>,直接把对象库添加到可执行目标的源列表中,CMake会自动处理所有依赖的对象文件:

project(objlibs)

# Object library 1
add_library(ObjectLibrary1 OBJECT object1/object1.c)
target_include_directories(ObjectLibrary1 INTERFACE object1)

# Object library 2
add_library(ObjectLibrary2 OBJECT object2/object2.c)
target_include_directories(ObjectLibrary2 INTERFACE object2)
target_link_libraries(ObjectLibrary2 PUBLIC ObjectLibrary1)

# Final executable
add_executable(MyTarget
    main/main.c
    ObjectLibrary2
    ObjectLibrary1
)
target_link_libraries(MyTarget PRIVATE ObjectLibrary2)

补充说明

不要在对象库的add_library中嵌套$<TARGET_OBJECTS:>,这种写法不仅无法传递对象文件到上层目标,还可能导致重复编译问题(当多个目标引用该对象库时)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:10:40