Referencing of component only works with cyclic dependency CMAKE
Posted: Fri Feb 24, 2023 12:58 pm
Hi i have a problem, i have 2 components. "ComponentA" controls pin output. It defines functions for this. The idea is,that the other component "ComponentB" calls this function and can set the pins.
ComponentB needs these functions. They call the componentA_function in its own functions. So i included the headers, and put "requires componentA" in the cmake. However, during linking the build terminal then tells me "undefined reference to function"
There were 2 ways to make the programm link:
1. Call the ComponentA_function(s) in main_app. After that, the call in ComponentB was not undefined in the linking step.
2. Introduce a dependency to componentB in the cmakelists.txt of componentA. However, this should NOT be necessary. ComponentA does not use a single line of code of componentB. So why does the code only compile if set "componentB" as REQUIRED in the cmakelists.txt of "componentA". I don't like introducing unnecessary cyclic redundancies i hope you understand. Especially if i dont see a reason for them, in a month or two I will not understand the dependency anymore if i want to debug anything.. I do not want to include a errorsource i cannot find later on.
Do you know similar errors? Is there a common mistake i did?
Thanks in advance for your help.
Below i List the Project structure and the different cmake files
//////////////CmakeLists.text of ComponentA <----- PROBLEM
/////////////////////////////////////////
//////////////CmakeLists.text of ComponentB
/////////////////////////////////////////
//////////////CmakeLists.text of main
/////////////////////////////////////////
//////////////CmakeLists.text toplevel
/////////////////////////////////////////
ComponentB needs these functions. They call the componentA_function in its own functions. So i included the headers, and put "requires componentA" in the cmake. However, during linking the build terminal then tells me "undefined reference to function"
There were 2 ways to make the programm link:
1. Call the ComponentA_function(s) in main_app. After that, the call in ComponentB was not undefined in the linking step.
2. Introduce a dependency to componentB in the cmakelists.txt of componentA. However, this should NOT be necessary. ComponentA does not use a single line of code of componentB. So why does the code only compile if set "componentB" as REQUIRED in the cmakelists.txt of "componentA". I don't like introducing unnecessary cyclic redundancies i hope you understand. Especially if i dont see a reason for them, in a month or two I will not understand the dependency anymore if i want to debug anything.. I do not want to include a errorsource i cannot find later on.
Do you know similar errors? Is there a common mistake i did?
Thanks in advance for your help.
Below i List the Project structure and the different cmake files
- components
- \__componentA
- \__include
- \__componentA.h
- \__CmakeLists.txt
- \__componentA.c
- \__componentB
- \__include
- \__componentB_0.h //calls functions of componentB_1.h
- \__componentB_1.h //calls functions of componentB_2.h
- \__componentB_2.h //calls functions of componentA.h
- \__CmakeLists.txt
- \__componentB_0.c
- \__componentB_1.c
- \__componentB_2.c
- main
- \__CmakeLists.txt
- \__main.c
- CmakeLists.txt
/////////////////////////////////////////
- idf_component_register(SRCS "componentA.c"
- INCLUDE_DIRS "include"
- REQUIRES driver freertos nvs_flash "main" "componentB" log spi_flash)<----- PROBLEM
- #"componentB" should NOT be a dependency, since componentB only calls componentA functions, <----- PROBLEM
- #but if you dont include "componentB" here, the componentA reference to the functions is undefined.
- include($ENV{IDF_PATH}/tools/cmake/project.cmake)
/////////////////////////////////////////
- idf_component_register(SRCS "componentB_0.c" "componentB_1.c" "componentB_2.c"
- INCLUDE_DIRS "include"
- REQUIRES "main" "componentA " "SPI" freertos
- )
- include($ENV{IDF_PATH}/tools/cmake/project.cmake)
/////////////////////////////////////////
- idf_build_get_property(project_dir PROJECT_DIR)
- idf_component_register(SRCS "native_ota_example.c"
- INCLUDE_DIRS "."
- )
/////////////////////////////////////////
- # 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.16)
- # (Not part of the boilerplate)
- # This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
- set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
- include($ENV{IDF_PATH}/tools/cmake/project.cmake)
- project(native_ota)