{"id":5985,"date":"2020-05-04T13:54:00","date_gmt":"2020-05-04T20:54:00","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=5985"},"modified":"2025-09-09T20:24:51","modified_gmt":"2025-09-10T03:24:51","slug":"advanced-esp-idf-project-structure","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/documentation\/espidf\/","title":{"rendered":"Advanced ESP-IDF Project Structure"},"content":{"rendered":"<p>This page explains the typical structure of an ESP32 project, lists the involved components, and outlines the most common errors that may prevent the project from working correctly.<\/p>\n<h2>Contents<\/h2>\n<p><a href=\"#idf\">ESP-IDF and Toolchains<\/a><br \/>\n<a href=\"#structure\">Project Structure<\/a><br \/>\n<a href=\"#build\">Build Systems<\/a><br \/>\n<a href=\"#debug\">Debugging ESP32 Boards<\/a><br \/>\n<a href=\"#configuration\">Configuration<\/a><br \/>\n<a href=\"#tests\">Unit Tests<\/a><br \/>\n<a href=\"#headers\">Header Files<\/a><br \/>\n<a href=\"#buildproblems\">Troubleshooting Build Problems<\/a><br \/>\n<a href=\"#troubleshooting\">Troubleshooting ESP-IDF\/Toolchain Problems<\/a><br \/>\n<a href=\"#toolchains\">Installing Multiple Toolchains<\/a><br \/>\n<a href=\"#python\">Resetting Python environment<\/a><br \/>\n<a href=\"#espadf\">ESP-ADF Structure<\/a><br \/>\n<a href=\"#espidf5\">ESP-IDF 5.5<\/a><\/p>\n<h2><a id=\"idf\"><\/a>ESP-IDF and Toolchains<\/h2>\n<p>ESP32 projects are based on ESP-IDF &#8211; an open-source framework from Espressif. You can find documentation on ESP-IDF <a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/\">here<\/a>, or a list of official releases on the <a href=\"https:\/\/github.com\/espressif\/esp-idf\/releases\">Espressif&#8217;s Github Repository<\/a>.<\/p>\n<p>VisualGDB ESP-IDF-based projects are specifically designed as to work as a thin wrapper on top of the ESP-IDF build system. While VisualGDB provides convenient GUI for many common ESP-IDF tasks, it does not introduce any changes to the underlying build process. This ensures that:<strong><br \/>\n<\/strong><\/p>\n<ul>\n<li>The projects edited with VisualGDB can still be built via command-line ESP-IDF tools, producing <strong>exactly<\/strong> the same results.<\/li>\n<li>Any project that can be built via ESP-IDF tools, can also be built with VisualGDB.<\/li>\n<li>Any extensions or examples that that work with the original ESP-IDF, will also work with VisualGDB-based projects.<\/li>\n<\/ul>\n<p><span style=\"text-decoration: underline;\"><strong>Update:<\/strong><\/span> VisualGDB 6.1 and later now understands the the same IDF and tool layout that is used by the Espressif&#8217;s VS Code extension. You no longer need to download a separate toolchain from us, and can use the latest tools from Espressif, producing the same results as VS Code. See <a href=\"https:\/\/visualgdb.com\/documentation\/espidf\/consolidated\/\">this page<\/a> for details.<\/p>\n<h2><a id=\"structure\"><\/a>Project Structure<\/h2>\n<p>A typical ESP-IDF-based project consists of the following components:<\/p>\n<ol>\n<li>The main component containing the <strong>app_main()<\/strong> function.<\/li>\n<li>Zero or more additional project-specific components.<\/li>\n<li>Multiple ESP-IDF-specific components.<\/li>\n<li>Zero or more unit test components.<\/li>\n<\/ol>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/idfstruct.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5986\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/idfstruct.png\" alt=\"\" width=\"350\" height=\"313\" \/><\/a>The contents of the main component are shown directly under the project&#8217;s node, while other components can be found under the <strong>Components<\/strong> node.<\/p>\n<p>Each component is internally defined as a static library. The final firmware build by the project is obtained by linking all of the project&#8217;s components together.<\/p>\n<p>Each component can define its own properties (e.g. include directories or preprocessor macros) via the regular VS Properties dialogs:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/props.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5987\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/props.png\" alt=\"\" width=\"786\" height=\"509\" \/><\/a>You can create new components in arbitrary locations, or reference existing component directories via the context menu on the <strong>Components<\/strong> node in Solution Explorer.<\/p>\n<h2><a id=\"build\"><\/a>Build Systems<\/h2>\n<p>ESP-IDF projects are built using CMake scripts included in the ESP-IDF. If you encounter problems building the project, see the <a href=\"#buildproblems\">build problem troubleshooting<\/a> section.<\/p>\n<h2><a id=\"debug\"><\/a>Debugging ESP32 Boards<\/h2>\n<p>ESP32 devices can be debugged via JTAG (this includes the ESP32 Arduino core). Generally, we advise using the <a href=\"https:\/\/visualgdb.com\/tutorials\/esp32\/wrover\/\">ESP32-WROVER-KIT module<\/a>, as it includes an on-board JTAG debugger and can be debugged out-of-the-box. Many other boards do not include a JTAG connector and require soldering in order get debugging to work. You can find example schematics for popular boards in our <a href=\"https:\/\/visualgdb.com\/w\/tutorials\/tag\/esp32\/\">ESP32 tutorials<\/a>.<\/p>\n<p>If you do not have a JTAG debugger, you can still program the FLASH memory of the ESP32 module via the COM port by right-clicking on the project in Solution Explorer and selecting &#8220;<strong>Program FLASH Memory<\/strong>&#8220;.<\/p>\n<h2><a id=\"configuration\"><\/a>Configuration<\/h2>\n<p>You can configure various parameters of the ESP32 projects via VisualGDB Project Properties -&gt; ESP-IDF Project -&gt; ESP-IDF Configuration:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/cfg.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5988\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/cfg.png\" alt=\"\" width=\"1038\" height=\"788\" \/><\/a>The configuration will be saved in the <strong>sdkconfig<\/strong> file that is used by the ESP-IDF build system when building the project.<\/p>\n<h2><a id=\"tests\"><\/a>Unit Tests<\/h2>\n<p>You can create and run unit tests on the ESP32 devices, as long as you have a JTAG debugger. See <a href=\"https:\/\/visualgdb.com\/tutorials\/esp32\/tests\/\">this tutorial<\/a> for detailed step-by-step instructions.<\/p>\n<h2><a id=\"headers\"><\/a>Header Files<\/h2>\n<p>Because the ESP-IDF framework does not explicitly reference header files in the component definitions, VisualGDB tries to discover them dynamically based on the component&#8217;s source directory. Unless the automatic discovery of header files is disabled, adding existing headers to Solution Explorer will have no effect if the headers are not located in a place where they can be automatically discovered.<\/p>\n<p>You can change the way VisualGDB discovers the headers for each target via per-target properties in Solution Explorer:\u00a0<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/headers-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6618\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/headers-1.png\" alt=\"\" width=\"1091\" height=\"532\" \/><\/a>Note that unlike the regular Advanced CMake projects, header settings for ESP-IDF project node (1) will only affect the main component (<strong>&lt;Project Directory&gt;\\main<\/strong>).<\/p>\n<p>If you set the <strong>Header File Search Mode<\/strong> to <strong>Disabled<\/strong>, adding headers to a target explicitly add them to the <strong>idf_component_register()<\/strong> statement together with the sources.<\/p>\n<h2><a id=\"buildproblems\"><\/a>Troubleshooting Build Problems<\/h2>\n<p>As the ESP32 projects are built by ESP-IDF itself, rather than by VisualGDB, many build issues are caused by incompatible configuration settings, missing external dependencies or unsupported combinations of ESP-IDF and toolchain (see <a href=\"#troubleshooting\">this section<\/a>). VisualGDB can help you narrow down the issue by exporting the exact build command line used by it, as we will show below.<\/p>\n<p>Before you begin troubleshooting a build issue, make sure you understand whether it happens during the <strong>configuration phase<\/strong>, or <strong>build phase<\/strong>. The <strong>configuration phase<\/strong> happens when you just load the project. If it fails, the project will have an error icon in Solution Explorer. If this happens, try reloading the project (or doing a clean reload) via the context menu:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/reload.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5993\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/reload.png\" alt=\"\" width=\"380\" height=\"321\" \/><\/a>The build phase happens when you actually build the project via the <strong>Build Solution<\/strong> command.<\/p>\n<p>Configuration problems are often caused by errors in CMake scripts or corrupt toolchain\/ESP-IDF environments. Build problems are typically triggered by errors in the source code, or when trying to build a project created for an older ESP-IDF version. For both build and configuration, you can find out the exact command line used by VisualGDB to launch the ESP-IDF tools in the VisualGDB Build window:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/log.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5994\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/log.png\" alt=\"\" width=\"765\" height=\"274\" \/><\/a>You can dump the command line to a batch file using the context menu. The file will include the working directory and any environment variables, so you will be able to reproduce the problem outside VisualGDB. Note that the same build log can contain multiple command lines. Each command line that can be dumped into a batch file is shown in <span style=\"color: #009999;\">cyan<\/span>.<\/p>\n<p>If you determine that the build or configuration fails due to missing environment variables, you can specify them via <strong>VisualGDB Project Properties -&gt; CMake Build Settings<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/vars.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5995\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/vars.png\" alt=\"\" width=\"1052\" height=\"644\" \/><\/a><\/p>\n<h2><a id=\"troubleshooting\"><\/a>Troubleshooting ESP-IDF\/Toolchain Compatibility<\/h2>\n<p><strong>Update:<\/strong> VisualGDB 6.1 or later directly supports the same tool layout as used by Espressif&#8217;s VS Code extension. This simplifies troubleshooting and eliminates the need to download extra toolchains. Read more about it <a href=\"https:\/\/visualgdb.com\/documentation\/espidf\/consolidated\/\">here<\/a>.<\/p>\n<p>If you encounter issues with an older version of the toolchain, please follow the steps below to ensure your ESP-IDF checkout and the toolchain are compatible:<\/p>\n<ol>\n<li>Delete all existing ESP32 toolchains via Tools-&gt;VisualGDB-&gt;Manage VisualGDB Packages:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/pkg.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5989\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/pkg.png\" alt=\"\" width=\"661\" height=\"535\" \/><\/a><\/li>\n<li>Start the ESP-IDF project wizard and download a new toolchain using it (see <a href=\"https:\/\/visualgdb.com\/support\/esp32\/\">this page<\/a> for a full list of toolchains and compatible ESP-IDF versions). Make sure you use the ESP-IDF checkout shipped with the toolchain and <strong>DO NOT<\/strong> install one from Github or from elsewhere:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/checkouts.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5990\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/checkouts.png\" alt=\"\" width=\"600\" height=\"151\" \/><\/a><\/li>\n<li>Clone the &#8220;Blink&#8221; project sample and ensure it builds correctly.<\/li>\n<li>If the newly created project works, while your existing project doesn&#8217;t, the ESP-IDF version you are using may not be backward-compatible with your project. If this is the case, try downloading <a href=\"https:\/\/visualgdb.com\/support\/esp32\/\">older ESP32 toolchains<\/a> and building the project with them.<\/li>\n<li>Unless you are prepared to troubleshoot the ESP32 toolchain\/IDF compatibility, <strong>DO NOT <\/strong>use the &#8220;Clone an SDK release from GitHub&#8221; or &#8220;Locate and existing SDK checkout&#8221; buttons in the VisualGDB GUI.<\/li>\n<\/ol>\n<p>If it still doesn&#8217;t help, see the <strong>Resetting Python Environment section<\/strong> below.<\/p>\n<p>If you would like to try a pre-release ESP-IDF version (e.g. v4.1 or later) that is not yet shipped with our toolchains, please make sure you use VisualGDB 5.5 Preview 6 or later and the <strong>esp32-gcc8.2.0-r3.exe<\/strong> toolchain (or later), as the older toolchains use a layout that is incompatible with newer ESP-IDF versions. It may still not work as expected, so unless you are prepared to troubleshoot toolchain\/Python issues, please consider using\u00a0 stable ESP-IDF release shipped with our toolchains.<\/p>\n<h2><a id=\"toolchains\"><\/a>Installing Multiple Toolchains<\/h2>\n<p>VisualGDB distinguishes different toolchain versions by comparing the following parameters:<\/p>\n<ul>\n<li>GCC version<\/li>\n<li>GDB version<\/li>\n<li>Toolchain revision<\/li>\n<\/ul>\n<p>Normally, the toolchain revision increases for bugfix releases that completely supersede the prior ones, however this is not the case for ESP32 toolchains, where multiple different revisions may be needed at the same time.<\/p>\n<p>You can configure VisualGDB to recognize multiple ESP32 toolchains with the same GCC\/GDB versions using one of the 2 methods below:<\/p>\n<ol>\n<li>Manually add another entry in registry to <strong>HKEY_CURRENT_USER\\SOFTWARE\\Sysprogs\\GNUToolchains<\/strong>. The value name should start with <strong>SysGCC-<\/strong>, but otherwise can be arbitrary. The value should point to the toolchain directory.<\/li>\n<li>In the VisualGDB toolchain selector, click &#8220;<strong>Select a third party toolchain by locating gdb.exe<\/strong>&#8220;, change the filter from <strong>GDB executables<\/strong> to <strong>Toolchain Definition Files<\/strong> and point it to the <strong>toolchain.xml<\/strong> file in the toolchain directory.<\/li>\n<\/ol>\n<p>Note that automatically managing multiple toolchain\/BSP versions is supported starting from the Custom edition. If you are using a lower edition, consider manually changing the toolchain ID in the <strong>toolchain.xml<\/strong> file, so that VisualGDB will consider it a separate toolchain.<\/p>\n<h2><a id=\"python\"><\/a>Resetting Python Environment<\/h2>\n<p><strong>Update:<\/strong> VisualGDB 6.1 or later directly supports the <a href=\"https:\/\/visualgdb.com\/documentation\/espidf\/consolidated\/\">same tool layout<\/a> as used by Espressif&#8217;s VS Code extension, eliminating the need for troubleshooting steps below.<\/p>\n<p>If you are using the ESP32 toolchain\u00a0 <strong>v8.2.0r3<\/strong> or later, the Python environment would not be a part of the toolchain and would not be reset by reinstalling the toolchain. If you encounter Python-related problems, follow the steps below to reset the Python environment:<\/p>\n<ol>\n<li>Clear the <strong>Tools-&gt;Options-&gt;VisualGDB-&gt;General-&gt;Python Directory<\/strong> setting:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/python.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5991\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/python.png\" alt=\"\" width=\"700\" height=\"475\" \/><\/a>See <a href=\"https:\/\/visualgdb.com\/documentation\/python\/\">this page<\/a> for more information about VisualGDB-managed Python installations.<\/li>\n<li>Delete the <strong>%LOCALAPPDATA%\\VisualGDB\\Python*<\/strong> directories<\/li>\n<li>Delete\/rename the <strong>%USERPROFILE%\\.espressif<\/strong> folder that contains virtual Python environments<\/li>\n<li>Launch the ESP-IDF project wizard and let VisualGDB install the Python 3.x package:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/getpython.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-5992\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/getpython.png\" alt=\"\" width=\"700\" height=\"567\" \/><\/a>Unless you are prepared to troubleshoot Python issues, do not use any other Python environment.<\/li>\n<\/ol>\n<h2><a id=\"espadf\"><\/a>ESP-ADF Structure<\/h2>\n<p>You can use VisualGDB to create projects based on the <a href=\"https:\/\/github.com\/espressif\/esp-adf\">ESP-ADF<\/a> framework as well. In order to do so, you can check out the ESP-ADF repository into your ESP32 toolchain: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/clone.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7658\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/05\/clone.png\" alt=\"\" width=\"863\" height=\"484\" \/><\/a>Note that <strong>ESP-ADF<\/strong> includes a separate copy of <strong>ESP-IDF<\/strong> as a Git submodule. However, there is a difference between the way it is handled by VisualGDB vs. the command-line Espressif tools:<\/p>\n<ul>\n<li>The Espressif&#8217;s command-line environment sets the <strong>IDF_PATH<\/strong> environment variable to the location of your <strong>ESP-IDF<\/strong> installation, that is separate from <strong>ESP-ADF<\/strong>. This effectively <a href=\"https:\/\/github.com\/espressif\/esp-adf\/blob\/a481b291fd420d77222c74c4a0396e07888cfec1\/CMakeLists.txt#L6\">overrides<\/a> the copy of <strong>ESP-IDF<\/strong> contained inside <strong>ESP-ADF<\/strong>. Updating your <strong>ESP-IDF<\/strong> later will implicitly affect the projects built with <strong>ESP-ADF<\/strong>, potentially causing problems after the update.<\/li>\n<li>VisualGDB sets the <strong>IDF_PATH <\/strong>variable based on the SDK version selected in the project properties. When building the <strong>ESP-ADF<\/strong> projects, it uses the <strong>ESP-IDF<\/strong> copy referenced by the selected <strong>ESP-ADF<\/strong> checkout (<strong>esp-adf\\&lt;version&gt;\\esp-idf).<\/strong> This allows having multiple <strong>ESP-ADF<\/strong> and <strong>ESP-IDF<\/strong> checkouts completely separated from each other. There are no implicit dependencies between them, and updating your <strong>ESP-IDF<\/strong> installations will not break <strong>ESP-ADF<\/strong> projects or vice versa.<\/li>\n<\/ul>\n<p>As of <strong>ESP-ADF<\/strong> 2.3, the version of <strong>ESP-IDF<\/strong> referenced as a Git submodule is very old and may not work with some projects. To work around it, you need to manually go to the <strong>c:\\SysGCC\\esp32\\esp-adf\\&lt;version&gt;\\esp-idf<\/strong> directory and run the following commands there:<\/p>\n<pre class=\"\">git checkout &lt;ESP-IDF tag name&gt;\r\ngit submodule update --recursive<\/pre>\n<p>You can find out the exact tag name by running &#8220;<strong>git describe \u2013tags<\/strong>&#8221; in your ESP-IDF checkout.<\/p>\n<p>Note that not all versions of <strong>ESP-IDF<\/strong> and <strong>ESP-ADF<\/strong> are compatible. You can find out the ESP-IDF versions compatible with a specific ESP-ADF release by checking the <strong>&lt;esp-adf&gt;\\docs\\en\\get-started\\index.rst<\/strong> file (search for &#8220;ESP-IDF versions&#8221;).<\/p>\n<h2><a id=\"espidf5\"><\/a>ESP-IDF 5.5<\/h2>\n<p>ESP-IDF 5.5 and later versions are only supported using the new <a href=\"https:\/\/visualgdb.com\/documentation\/espidf\/consolidated\/\">consolidated toolchain layout<\/a>. Make sure you use VisualGDB 6.1 or later.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This page explains the typical structure of an ESP32 project, lists the involved components, and outlines the most common errors<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[201],"tags":[160,138],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/5985"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=5985"}],"version-history":[{"count":21,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/5985\/revisions"}],"predecessor-version":[{"id":9049,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/5985\/revisions\/9049"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=5985"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=5985"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=5985"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}