包含子目录以在 ESP32 的 ESP-IDF 中组织代码
Include subdirectories to organise code in ESP-IDF for ESP32
我正在使用 ESP-IDF 4.3.2 通过以下命令创建 ESP32 项目:
idf.py create-project --path test test
然后我修改 main/main.c 以包含以下代码:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void app_main(void)
{
int i = 0;
while (1) {
printf("[%d] Hello world!\n", i);
i++;
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
编译和运行都很好,但是如果我尝试创建 main 的子目录来组织我的代码,我似乎遇到了错误。
我将使用以下内容添加 dosomething/printsomething.h
和 dosomething/printsomething.c
:
dosomething/printsomething.h
:
void printsomething(void);
dosomething/printsomething.c
:
#include <stdio.h>
void printsomething(void)
{
printf("something\n");
}
然后我修改main.c
如下:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "dosomething/printsomething.h"
void app_main(void)
{
int i = 0;
while (1) {
printf("[%d] Hello world!\n", i);
printsomething();
i++;
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
代码构建失败,我看到“对 `printsomething' 的未定义引用”错误。
/home/builduser/.espressif/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: esp-idf/main/libmain.a(test.c.obj):(.literal.app_main+0x4): undefined reference to `printsomething'
/home/builduser/.espressif/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: esp-idf/main/libmain.a(test.c.obj): in function `app_main':
/home/builduser/Documents/code/esp/esp/test/build/../main/test.c:11: undefined reference to `printsomething'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
ninja failed with exit code 1
我可以看到 main\CMakeLists.txt
文件包含以下内容:
idf_component_register(SRCS "test.c"
INCLUDE_DIRS ".")
但是我找不到 INCLUDE_DIRS 的正确语法,这将允许我指定 C 文件和头文件所在的目录。
我对 cmake
和 ESP-IDF
不是很熟悉。我在 nvim
和 make
中使用 platformio
。但是尝试在根目录 CMakeLists.txt
中创建包含:
PROJECT(test)
SET(DIRS dosomething main)
SUBDIRS(${DIRS})
INCLUDE_DIRECTORIES(${DIRS})
在 main
目录中 CMakeLists.txt
包含:
ADD_EXECUTABLE(test main.c)
TARGET_LINK_EXECUTABLE(test something)
并且在 dosomething
目录中 CMakeLists.txt
包含:
ADD_LIBRARY(something printsomething.c)
编辑:
我在 ESP-IDF 中使用您的代码进行了测试:
main/CMakeLists.txt
:
idf_component_register(SRCS "main.c"
INCLUDE_DIRS ".")
main/main.c
:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "../dosomething/printsomething.c"
void app_main(void)
{
int i = 0;
while (1) {
printf("[%d] Hello world!\n", i);
printsomething();
i++;
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
dosomething/CMakelists.txt
:
idf_component_register(SRCS "printsomething.c"
INCLUDE_DIRS ".")
idf.py build
顺利通过
编辑二:
在 https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html?highlight=cmakelists#file-globbing-incremental-builds 上显示了更清洁的方式:
main/Cmakelists.txt
:
idf_component_register(INCLUDE_DIRS "."
SRC_DIRS "./" "../dosomething")
main/main.c
:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "../dosomething/printsomething.h"
void app_main(void)
{
int i = 0;
while (1) {
printf("[%d] Hello world!\n", i);
printsomething();
i++;
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
就是这样。
这里有一个默认文件夹。创建一个名为 components
的文件夹并将 dosomething
文件夹放入其中。 components
文件夹不应创建在 main
内,而应与 main
在同一目录中。所以你可以使用 #include "printsomething.h"
一切都会起作用。您不需要修改 CMakeLists.txt
,因为 components
是默认目录。查看更多 here.
我正在使用 ESP-IDF 4.3.2 通过以下命令创建 ESP32 项目:
idf.py create-project --path test test
然后我修改 main/main.c 以包含以下代码:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void app_main(void)
{
int i = 0;
while (1) {
printf("[%d] Hello world!\n", i);
i++;
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
编译和运行都很好,但是如果我尝试创建 main 的子目录来组织我的代码,我似乎遇到了错误。
我将使用以下内容添加 dosomething/printsomething.h
和 dosomething/printsomething.c
:
dosomething/printsomething.h
:
void printsomething(void);
dosomething/printsomething.c
:
#include <stdio.h>
void printsomething(void)
{
printf("something\n");
}
然后我修改main.c
如下:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "dosomething/printsomething.h"
void app_main(void)
{
int i = 0;
while (1) {
printf("[%d] Hello world!\n", i);
printsomething();
i++;
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
代码构建失败,我看到“对 `printsomething' 的未定义引用”错误。
/home/builduser/.espressif/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: esp-idf/main/libmain.a(test.c.obj):(.literal.app_main+0x4): undefined reference to `printsomething'
/home/builduser/.espressif/tools/xtensa-esp32-elf/esp-2021r2-8.4.0/xtensa-esp32-elf/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld: esp-idf/main/libmain.a(test.c.obj): in function `app_main':
/home/builduser/Documents/code/esp/esp/test/build/../main/test.c:11: undefined reference to `printsomething'
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
ninja failed with exit code 1
我可以看到 main\CMakeLists.txt
文件包含以下内容:
idf_component_register(SRCS "test.c"
INCLUDE_DIRS ".")
但是我找不到 INCLUDE_DIRS 的正确语法,这将允许我指定 C 文件和头文件所在的目录。
我对 cmake
和 ESP-IDF
不是很熟悉。我在 nvim
和 make
中使用 platformio
。但是尝试在根目录 CMakeLists.txt
中创建包含:
PROJECT(test)
SET(DIRS dosomething main)
SUBDIRS(${DIRS})
INCLUDE_DIRECTORIES(${DIRS})
在 main
目录中 CMakeLists.txt
包含:
ADD_EXECUTABLE(test main.c)
TARGET_LINK_EXECUTABLE(test something)
并且在 dosomething
目录中 CMakeLists.txt
包含:
ADD_LIBRARY(something printsomething.c)
编辑:
我在 ESP-IDF 中使用您的代码进行了测试:
main/CMakeLists.txt
:
idf_component_register(SRCS "main.c"
INCLUDE_DIRS ".")
main/main.c
:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "../dosomething/printsomething.c"
void app_main(void)
{
int i = 0;
while (1) {
printf("[%d] Hello world!\n", i);
printsomething();
i++;
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
dosomething/CMakelists.txt
:
idf_component_register(SRCS "printsomething.c"
INCLUDE_DIRS ".")
idf.py build
顺利通过
编辑二: 在 https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html?highlight=cmakelists#file-globbing-incremental-builds 上显示了更清洁的方式:
main/Cmakelists.txt
:
idf_component_register(INCLUDE_DIRS "."
SRC_DIRS "./" "../dosomething")
main/main.c
:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "../dosomething/printsomething.h"
void app_main(void)
{
int i = 0;
while (1) {
printf("[%d] Hello world!\n", i);
printsomething();
i++;
vTaskDelay(5000 / portTICK_PERIOD_MS);
}
}
就是这样。
这里有一个默认文件夹。创建一个名为 components
的文件夹并将 dosomething
文件夹放入其中。 components
文件夹不应创建在 main
内,而应与 main
在同一目录中。所以你可以使用 #include "printsomething.h"
一切都会起作用。您不需要修改 CMakeLists.txt
,因为 components
是默认目录。查看更多 here.