How to setup CMAKE to compile with more than one executable(main.c)?

MikeLemon
Posts: 45
Joined: Tue Feb 02, 2021 5:55 pm

How to setup CMAKE to compile with more than one executable(main.c)?

Postby MikeLemon » Tue Apr 26, 2022 4:02 pm

the main file main.c in my project got quite large more than 1000 lines a code with more than 30 lines of lib #include<lib.h> code.

I'd like to split the main source file into two or more files and have them work as one and shade includes and relation with each other like how you're able to split executables with more than one .ino file in arduino, my question is how do you setup CMake in ESP IDF to achieve it? here's the content of my projects CMAKE according to their directories:

project/CMakeLists.txt:

Code: Select all

# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)



# set(COMPONENT_DIRS C:/Coding/ESP32_sketches/libraries/esp-idf-lib/components)
set(EXTRA_COMPONENT_DIRS C:/Coding/ESP32_sketches/libraries/esp-idf-lib/components;
                   $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(my_timer)
project/main/CMakeLists.txt:

Code: Select all

# Edit following two lines to set component requirements (see docs)
set(COMPONENT_REQUIRES)
set(COMPONENT_PRIV_REQUIRES)

set(COMPONENT_SRCS "u8g2_esp32_hal.c" "main.c") 

set(COMPONENT_SRCDIRS "." "../components")
set(COMPONENT_ADD_INCLUDEDIRS "." "../components")



register_component()
I saw in stackoverflow that you do it with add_executable() how it's suppose to be typed in terms of syntax with more than one source file, and how to integrate it with the Custom mess the ESP IDF creates and can't find and explanation for it, is something I don't understand.
Last edited by MikeLemon on Wed Apr 27, 2022 4:33 pm, edited 1 time in total.

ESP_igrr
Posts: 2071
Joined: Tue Dec 01, 2015 8:37 am

Re: How to setup CMAKE to compile with more than one executable(main.c)?

Postby ESP_igrr » Tue Apr 26, 2022 9:02 pm

Hi MikeLemon,

IDF projects are built from components. Each component may contain multiple source and header files. Components may depend on other components. The minimal IDF project consists of the root CMakeLists.txt file and the 'main' component. You can also add more components by creating them inside 'components' subdirectory of the project, or by referencing them using EXTRA_COMPONENT_DIRS, or using the IDF component manager. Every component you create (including the 'main' component) has its own CMakeLists.txt file.

Let's say you are starting from the minimal project:

Code: Select all

project/
- CMakeLists.txt
- main/
  - CMakeLists.txt
  - main.c
In this case, CMakeLists.txt in the 'main' component directory should contain:

Code: Select all

idf_component_register(SRCS main.c)
Now suppose you need to add another source file. You can do this next to main.c:

Code: Select all

project/
- CMakeLists.txt
- main/
  - CMakeLists.txt
  - main.c
  - helper.c
  - helper.h
The new source file has to be added to the sources list:

Code: Select all

idf_component_register(SRCS main.c helper.c)
Now let's say that the code in 'helper.c' becomes self-sufficient and you would like to split it into a separate component. You can change project layout like this:

Code: Select all

project/
- CMakeLists.txt
- main/
  - CMakeLists.txt
  - main.c
- components/
  - helper/
    - CMakeLists.txt
    - helper.c
    - include/
      - helper.h
CMakeLists.txt of the 'helper' component becomes:

Code: Select all

idf_component_register(SRCS helper.c INCLUDE_DIRS include)
It's very similar to what we had before, but this time INCLUDE_DIRS specifies a public include directory. This directory will be added to the include directory list when compiling sources of this component, and also of all components which depend on "helper".
The CMakeLists.txt file of the main component becomes:

Code: Select all

idf_component_register(SRCS main.c REQUIRES helper)
This component still has one source file, but this time it declares a dependency on "helper" component. This tells the build system that the include directories and compilation flags of "helper" have to be propagated to the "main" component. If you are using some other components aside from "helper", you have to list them as well.
The main idea of components is that you declare include directories at component level and then specify dependencies between components. If you have to specify an include directory one level above your component directory (such as ../something), this is usually a bad pattern. Try to define include directories at component level instead.

If you are familiar with "modern CMake", you will find the concept very similar. In modern CMake, each library declares its include directories using target_include_directories command, and libraries express dependencies on each other using target_link_libraries. In fact, idf_component_register is just a wrapper for some of these functions. You can still use standard CMake target_include_directories and target_link_libraries, if you like.

The concept of component dependencies is explained in the docs here: https://docs.espressif.com/projects/esp ... quirements

More on writing component CMakeLists.txt files: https://docs.espressif.com/projects/esp ... cmakelists

For an IDF example with multiple source files, please see https://github.com/espressif/esp-idf/bl ... eLists.txt

Hope this helps! If something isn't clear, please don't hesitate to ask.

MikeLemon
Posts: 45
Joined: Tue Feb 02, 2021 5:55 pm

Re: How to setup CMAKE to compile with more than one executable(main.c)?

Postby MikeLemon » Wed Apr 27, 2022 4:26 pm

Hello igrr, good component day for you :)

When I put only idf_component_register(SRCS "main.c" "u8g2_esp32_hal.c" "my_inits.c"
SRC_DIRS "." "../components"
INCLUDE_DIRS "../components")

it gives me errors making me unable to even build a directory unlike using the method I used in the posted in the code in this thread post and you might haven't got me but I want to achieve,
say the file "my_inits.c" to be a regular source file like main.c that initializes the global variables and struct configs and function
*not as a library but as the main source file start* and have main.c be able to access the function and variables there normally in code typing terms rather than through #include<lib.h> to hide the stuff I don't want to see and scroll through when I'm working on a particular part of the code that includes controlling many aspects of the global system so passing pointers around to simplify code is not ideal especially when accessing ISR and callback function.

ESP_igrr
Posts: 2071
Joined: Tue Dec 01, 2015 8:37 am

Re: How to setup CMAKE to compile with more than one executable(main.c)?

Postby ESP_igrr » Wed Apr 27, 2022 4:58 pm

Could you please share your project code (either as a .zip file or in a Github repository)? I'll see if I can suggest you specific changes to make that work.

I'm sorry, I am unable to fully understand your last comment. One thing I did notice is that you are calling idf_component_register with both SRCS and SRC_DIRS. You only need SRCS. Also please see my suggestion from the previous post about not adding external directories to the component include directory list (i.e. "../components").

If you share you code (or a simplified version of it) somewhere, it will be easier for me to see the full picture and to suggest you the solution.

MikeLemon
Posts: 45
Joined: Tue Feb 02, 2021 5:55 pm

Re: How to setup CMAKE to compile with more than one executable(main.c)?

Postby MikeLemon » Wed Apr 27, 2022 5:43 pm

ESP_igrr wrote:
Wed Apr 27, 2022 4:58 pm
Could you please share your project code (either as a .zip file or in a Github repository)? I'll see if I can suggest you specific changes to make that work.

I'm sorry, I am unable to fully understand your last comment. One thing I did notice is that you are calling idf_component_register with both SRCS and SRC_DIRS. You only need SRCS. Also please see my suggestion from the previous post about not adding external directories to the component include directory list (i.e. "../components").

If you share you code (or a simplified version of it) somewhere, it will be easier for me to see the full picture and to suggest you the solution.

Sure there it is, it's not finished yet but should build nicely once my_inits.c definitions can be read by main.c:

I learned using cmake with esp IDF by meir with his ESP32 course so that stuck and got integrated into the normal routine, but now I find that I need to split my code to make it more developable and debugable like how arduino is able to do it by adding another tab which just creates another .ino source file that can relate to each other in the same folder.
Attachments
My_Timer - Copy.zip
(1.31 MiB) Downloaded 366 times

Who is online

Users browsing this forum: MicroController and 186 guests