I have files: main.cpp, test1.cpp, test1.hpp, test2.cpp, test2.hpp, test3.cpp, test3.hpp …
How can I build those files to flash into ESP32. (I use ESP-IDF v5.3.0 in VS Code).
Thank you!
I try to config CMakeList.txt, but I don’t know.
I have files:
// main.cpp
#include <iostream>
#include "Student.hpp"
void app_main(void)
{
Student st;
st.inputInfo();
int *arr, n;
inputArray(arr, n);
}
// Student.hpp
#pragma once
#include <iostream>
#include <string>
using namespace std;
struct Student
{
string name;
int age, grade;
float score1, score2, score3;
float getAVG() { return (score1 + score2 + score3) / 3; }
void inputInfo();
};
void inputArray(int *&arr, int &n);
// Student.cpp
#include "Student.hpp"
#include <iostream>
#include <string>
using namespace std;
void Student::inputInfo()
{
cout << "Enter Name: ";
getline(cin, name);
cout << "Enter Score:";
cin >> score1 >> score2 >> score3;
}
void inputArray(int *&arr, int &n)
{
cout << "Number: ";
cin >> n;
arr = new int[n];
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
}
//CMakeList.txt #1
idf_component_register(SRCS "main.cpp" "Student.cpp")
//CMakeList.txt #2
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(testCppV2)
And I run idf.py build
It has error:
FAILED: testCppV2.elf
cmd.exe /C "cd . && C:Espressiftoolsxtensa-esp-elfesp-13.2.0_20240530xtensa-esp-elfbinxtensa-esp32-elf-g++.exe -mlongcalls -Wno-frame-address -fno-builtin-memcpy -fno-builtin-memset -fno-builtin-bzero -fno-builtin-stpcpy -fno-builtin-strncpy -Wl,--cref -Wl,--defsym=IDF_TARGET_ESP32=0 -Wl,--Map=C:/Users/GiaQuang/Downloads/testCppV2/build/testCppV2.map -Wl,--no-warn-rwx-segments -fno-rtti -fno-lto -Wl,--gc-sections -Wl,--warn-common -T esp32.peripherals.ld -T esp32.rom.ld -T esp32.rom.api.ld -T esp32.rom.libgcc.ld -T esp32.rom.newlib-data.ld -T esp32.rom.syscalls.ld -T esp32.rom.newlib-funcs.ld -T memory.ld -T sections.ld @CMakeFilestestCppV2.elf.rsp -o testCppV2.elf && cd ."
C:/Espressif/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/13.2.0/../../../../xtensa-esp-elf/bin/ld.exe: esp-idf/freertos/libfreertos.a(app_startup.c.obj):(.literal.main_task+0x24): undefined reference to `app_main'
C:/Espressif/tools/xtensa-esp-elf/esp-13.2.0_20240530/xtensa-esp-elf/bin/../lib/gcc/xtensa-esp-elf/13.2.0/../../../../xtensa-esp-elf/bin/ld.exe: esp-idf/freertos/libfreertos.a(app_startup.c.obj): in function `main_task':
C:/Espressif/frameworks/esp-idf-v5.3/components/freertos/app_startup.c:199:(.text.main_task+0x99): undefined reference to `app_main'
collect2.exe: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
A canonical project in ESP IDF build system has a top-level CMakeLists.txt
file which doesn’t contain any source files. Instead, it pulls in components which have their own CMakeLists.txt
files that specify the source files to compile. The simplest project has only one component named main
.
So a simple project structure would look something like this:
myProject/
CMakeLists.txt
main/
CMakeLists.txt
main.cpp
test1.hpp
test1.cpp
test2.hpp
test2.cpp
...
The minimal top level CMakeLists.txt
would be:
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(myProject)
This pulls in component named main
by default. The absolutely minimal component main/CMakeLists.txt
would have:
idf_component_register(SRCS "main.cpp" "test1.cpp" "test2.cpp" "test3.cpp")
The .hpp
files are not specified in CMakeLists.txt
, CMake is smart enough to figure those out itself.
Then it’s just a matter of running idf.py build
in the top level directory.
If your main.cpp
holding C++ code creates linker errors saying undefined reference to 'app_main'
then the reason is simple. ESP IDF is C and is expecting you to define app_main()
so the C linker can find it. Note that it can still contain C++ code. Surround the function with extern "C"
:
extern "C" {
void app_main(void) {
Student st;
st.inputInfo();
int *arr, n;
inputArray(arr, n);
}
}
2