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

无需新增CMakeLists.txt,CMake项目引入子目录文件的报错解决

问题:子模块C文件函数未定义引用

项目结构

root/
 | CMakeLists.txt
 | main.cc
 | a.cc
 | a.h
 | submodule/
 |   |  b.c
 |   |  b.h

需求与尝试

不想为子模块添加额外的CMakeLists.txt(避免Git维护成本,且文件数量少,CMake配置冗余),尝试通过以下CMake配置引入子模块文件:

include_directories(${PROJECT_SOURCE_DIR}/submodule)

...

add_executable(${NAME}
    submodule/b.c
    main.cpp
    server.cc
)

还尝试添加了target_link_directories,但均出现函数未定义引用错误,报错信息如下:

/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: CMakeFiles/light.dir/
server.cc.obj: in function `tcpRecvCallback(void*, tcp_pcb*, pbuf*, signed char) [clon
e .part.0]':
server.cc:(.text._Z15tcpRecvCallbackPvP7tcp_pcbP4pbufa.part.0+0x62): undefined referen
ce to `http_req_parse(char*)'
collect2: error: ld returned 1 exit status
gmake[2]: *** [CMakeFiles/light.dir/build.make:3083: light.elf] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:1520: CMakeFiles/light.dir/all] Error 2
gmake: *** [Makefile:156: all] Error 2

注:http_req_parse是b.c中的函数,server.cc(C++文件)包含了submodule/b.h,当前为Raspberry Pi Pico W构建项目。


解决方案

核心原因:C/C++混合编译的名字修饰差异

server.cc是C源文件,b.c是C源文件,C编译器会对函数名进行名字修饰(Name Mangling),导致链接时无法匹配C文件中未被修饰的原始函数名,从而出现未定义引用错误。

具体修复步骤

1. 用extern "C"包裹C头文件的包含

在C++文件(比如server.h或server.cc)中包含b.h时,添加extern "C"块:

#ifdef __cplusplus
extern "C" {
#endif
#include "b.h"
#ifdef __cplusplus
}
#endif

也可以直接修改b.h,在文件开头和结尾添加上述宏,这样所有包含该头文件的C/C++文件都能正确识别函数名。

2. 确认CMake配置的正确性

你的原有CMake配置已经满足需求,无需额外修改:

  • include_directories正确添加了子模块的头文件路径,确保编译时能找到b.h
  • add_executable中已经包含了submodule/b.c,该文件会被C编译器正常编译,无需额外链接库操作
  • 无需使用target_link_directories,因为你是直接编译源文件,不是链接预编译库

3. 额外排查点

  • 确认b.c中确实实现了http_req_parse函数,而非仅在b.h中声明
  • 检查CMake中${NAME}变量是否正确指向你的目标可执行文件,避免拼写错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 03:45:33