Creating Advanced ESP32 Projects with ESP-IDF

This tutorial shows how to use the new advanced ESP-IDF project subsystem to create projects based on the ESP-IDF framework. Unlike MSBuild-based projects, ESP-IDF based projects do not require a specific version of ESP-IDF and provide the best level of integration with various ESP-IDF components and settings.

Before you begin, install VisualGDB 5.4 or later and the latest ESP32 toolchain.

We will now build the basic “Hello, World” sample from ESP-IDF and show how to use VisualGDB to edit and debug it.

  1. Start Visual Studio and open the ESP-IDF Project Wizard:01-prj
  2. Select “Create a new project based on a sample project” and click “Next”:02-new
  3. On the next page select your ESP32 toolchain. If you don’t have it installed yet (or are not using the latest toolchain, click “download” in the toolchain selector to install it automatically):
    03-toolchainOnce the toolchain is selected, ensure you select the ESP-IDF checkout you want to use. We recommend starting with the default checkout included in the toolchain; once you confirm that the project building and debugging works, you can install another ESP-IDF release directly from Github via VisualGDB Project Properties.
  4. On the next page select a sample project you want to use. In this example we will use the hello_world project to demonstrate the basics of building and debugging:sample
  5. Finally select your debug method. If you haven’t done this before, follow this tutorial to setup JTAG debugging for your board:
  6. Press “Finish” to create the project. VisualGDB will launch the ESP-IDF build system to query the precise project structure:06-loading
  7. Once the project structure is loaded, VisualGDB will display it in Solution Explorer and will open the main source file:07-loadedIf you are using a preview VisualGDB build, you may get a spurious “found 1 additional include directory” message immediately after creating the project. It is shown because the project is missing some include files that are generated on first build. Simply build the project and re-open your source file to eliminate the message.
  8. VisualGDB will use the ESP-IDF build scripts to build the project, producing exactly the same result as if you were using command-line tools. It will automatically detect the number of CPU cores on your machine and run a multi-threaded build using the corresponding amount of threads:08-built
  9. If you are using the Custom edition or higher, Open VisualGDB Project Properties and enable raw terminal on the COM port corresponding to your ESP32 board. If not, use any other terminal program to connect to it:09-port
  10. Set a breakpoint in app_main() and start debugging. The breakpoint will hit and you will see the output printed by the board:10-debug
  11. You can use the Threads window to see the state of different threads of your program:11-threads
  12. Now we will show how to add new source files to your ESP-IDF projects. Stop debugging, right-click on “Source Files” and select “Add->New Item”:12-newfile
  13. Then choose “C++ Source File” and add “subdir” to the location field:13-subdir
  14. VisualGDB will automatically edit the COMPONENT_SRCDIRS variable in the corresponding file to reference the new directory. This will also work when adding existing files.
    14-componentsNote that adding one file from a directory will automatically add all source files from the same directory due to the way ESP-IDF handles source files. If this happens, VisualGDB will let you double-check the implicitly added files before proceeding.
  15. Add a new function in the newly created source file: 15-func
  16. Now create a header and declaration for this function. Note that if you want the header to be used by both C and C++ files, you need to use conditionally compiled extern “C” wrapper:
    #pragma once
    #ifdef __cplusplus
    extern "C"
     void func();
    #ifdef __cplusplus


  17. Include <header.h> from your main file. VisualGDB will automatically suggest adding “subdir” to the include directory list:
  18. Click “Add now” and VisualGDB will automatically insert the correct relative path to
  19. If the header case doesn’t match the case of the physical file name, VisualGDB will show a warning and let you automatically fix it so you will be able to build the your sources on case-sensitive Linux systems:
  20. You can also use the regular VS property pages to edit various project/target properties. See how the “subdir” is now shown in the “additional include directories” field:19-subdir
  21. You can configure various properties of the ESP-IDF projects using the first page of VisualGDB Project Properties. This is equivalent to the the “make menuconfig” command, but provides an easier searchable graphical interface:
  22. For each ESP-IDF-based project VisualGDB will automatically parse the ESP-IDF sources and make them available to the Find All References, Go To Definition and Code Map. You can use these features to explore the relations between different parts of ESP-IDF and to diagnose tough problems:map
  23. Note that for debug configurations ESP-IDF will use the “-Og” optimization setting instead of “-O0”. This doesn’t affect most of debugging functionality, however can make some scenarios less convenient (e.g. may eliminate unused variables created just for checking values via watch). You can override this via Project Properties for your project or specific components:21-optim
  24. DO NOT use this setting for built-in ESP-IDF components, as it would result in random crashes. If your project suddenly stops working after using this setting, double-check all files for the code replacing -Og with -O0 and remove it if necessary (or simply disable the setting via Project Properties so VisualGDB will remove those lines for you):22-flags

If you want to check the project into a source control system, such as Git, simply check in the files in the project directory (including the .vgdbproj and .sln files) and add the following subdirectories to .gitignore:

  • CodeDB (contains IntelliSense cache)
  • VisualGDB (contains built objects and libraries)
  • VisualGDBCache (contains parameters queried from the toolchain)