ESP32-IDF编译时出现undefined reference to function()
在编译ESP32项目时出现了奇怪的错误,在Link CXX executable test.elf
时失败,并报错undefined reference to 'lv_demo_music'
。是编译报错。这里记录解决方法。
原因分析
上面的报错意思很简单,其实就是虽然声明了这个函数(有头文件),没有报错undeclare
,但是由于**没有编译这个函数(没编译.c文件)**,导致编译器在链接的时候找不到。
这其实是CMake文件没有写好编译范围,导致没有将目标文件编译的原因。
解决方法
解决方法也很简单,参考官方文档的构建系统。该文档中说明,可以使用SRCS
SRC_DIRS
指定要编译的文件,文件夹。
添加编译单个文件:
1 | idf_component_register(SRCS library/a.c library/b.c platform/platform.c |
添加编译包含多个文件的文件夹:
1 | idf_component_register(SRC_DIRS library platform |
后台会使用通配符在指定的目录中查找源文件。但是请注意,在使用这种方法的时候,如果组件中添加了一个新的源文件,CMake 并不知道重新运行配置,最终该文件也没有被加入构建中。这在使用命令行单步编译时需要注意。
问题解决
我是在移植lvgl时出现的BUG,由于ESP公司是LVGl的合作伙伴,lvgl对ESP-IDF做了专门的适配,其直接克隆的仓库就可以做为一个组件使用。在项目CMakeList.txt中,可以看到这一行:
1 | include(${CMAKE_CURRENT_LIST_DIR}/env_support/cmake/esp.cmake)c |
引用了env_support
目录下的cmake文件,打开该文件。
1 | file(GLOB_RECURSE SOURCES ${LVGL_ROOT_DIR}/src/*.c)# ${LVGL_ROOT_DIR}/demos/*.c) |
可以看到,两次idf_component_register()
使用的源文件为${SOURCES}
,而该变量定义在:
1 | file(GLOB_RECURSE SOURCES ${LVGL_ROOT_DIR}/src/*.c) |
可以看到,只编译了src文件夹,我们使用的函数在demos
文件夹下,因此可以直接修改为
1 | file(GLOB_RECURSE SOURCES ${LVGL_ROOT_DIR}/src/*.c ${LVGL_ROOT_DIR}/demos/*.c) |
重新编译,问题解决。