diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index f4d9cb9257..09abd87f7f 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -605,6 +605,23 @@ The order of components in the ``BUILD_COMPONENTS`` variable determines other or - Order that :ref:`project_include.cmake` files are included into the project. - Order that the list of header paths is generated for compilation (via ``-I`` argument). (Note that for a given component's source files, only that component's dependency's header paths are passed to the compiler.) +Adding link-time dependencies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. highlight:: cmake + +The ESP-IDF CMake helper function ``idf_component_add_link_dependency`` adds a link-only dependency between one component and another. In almost all cases, it's better to use the ``PRIV_REQUIRES`` feature in ``idf_component_register`` to create a dependency. However in some cases it's necessary the link-time dependency of another component to this component, i.e. the reverse order to ``PRIV_REQUIRES`` (for example: :doc:`/api-reference/storage/spi_flash_override_driver`). + +To make another component depend on this component at link time:: + + idf_component_add_link_dependency(FROM other_component) + +Place this line after the line with ``idf_component_register``. + +It's also possible to specify both components by name:: + + idf_component_add_link_dependency(FROM other_component TO that_component) + .. _override_project_config: Overriding Parts of the Project diff --git a/docs/en/api-reference/storage/spi_flash_override_driver.rst b/docs/en/api-reference/storage/spi_flash_override_driver.rst index c1da0dbc23..75baac920d 100644 --- a/docs/en/api-reference/storage/spi_flash_override_driver.rst +++ b/docs/en/api-reference/storage/spi_flash_override_driver.rst @@ -17,6 +17,8 @@ Users should note the following when customizing chip drivers: Steps For Creating Custom Chip Drivers and Overriding the IDF Default Driver List --------------------------------------------------------------------------------- +.. highlight: cmake + 1. Enable the :ref:`CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST` config option. This will prevent compilation and linking of the Default Chip Driver List (`default_registered_chips`) provided by IDF. Instead, the linker will search for the structure of the same name (`default_registered_chips`) that must be provided by the user. 2. Add a new component in your project, e.g. `custom_chip_driver`. 3. Copy the necessary chip driver files from the `spi_flash` component in IDF. This may include: @@ -25,7 +27,11 @@ Steps For Creating Custom Chip Drivers and Overriding the IDF Default Driver Lis - Any of the `spi_flash_chip_*.c` files that matches your own flash model best - `CMakeLists.txt` and `linker.lf` files - Modify the files above properly. + Modify the files above properly. Including: + + - Change the ``default_registered_chips`` variable to non-static and remove the #ifdef logic around it. + - Update `linker.lf` file to rename the fragment header and the library name to match the new component. + - If reusing other drivers, some header names need prefixing with ``spi_flash/`` when included from outside spi_flash component. .. note:: - When writing your own flash chip driver, you can set your flash chip capabilities through `spi_flash_chip_***(vendor)_get_caps` and points the function pointer `get_chip_caps` for protection to the `spi_flash_chip_***_get_caps` function. The steps are as follows. @@ -56,10 +62,16 @@ Steps For Creating Custom Chip Drivers and Overriding the IDF Default Driver Lis - You also can see how to implement this in the example :example:`storage/custom_flash_driver`. -4. Add linking dependency from `spi_flash` component to the new `custom_chip_driver` component, by adding the following lines after the `idf_component_register`, in the `CMakeLists.txt` file of the `custom_chip_driver` component: +4. Write a new `CMakeLists.txt` file for the `custom_chip_driver` component, including an additional line to add a linker dependency from `spi_flash` to `custom_chip_driver`:: - idf_component_get_property(spi_flash_lib spi_flash COMPONENT_LIB) - set_property(TARGET ${spi_flash_lib} APPEND PROPERTY INTERFACE_LINK_LIBRARIES $) + idf_component_register(SRCS "spi_flash_chip_drivers.c" + "spi_flash_chip_mychip.c" # modify as needed + REQUIRES hal + PRIV_REQUIRES spi_flash + LDFRAGMENTS linker.lf) + idf_component_add_link_dependency(FROM spi_flash) + + - An example of this component CMakeLists.txt can be found in :example_file:`storage/custom_flash_driver/components/custom_chip_driver/CMakeLists.txt` 5. The `linker.lf` is used to put every chip driver that you are going to use whilst cache is disabled into internal RAM. See :doc:`/api-guides/linker-script-generation` for more details. Make sure this file covers all the source files that you add. diff --git a/examples/storage/custom_flash_driver/components/custom_chip_driver/CMakeLists.txt b/examples/storage/custom_flash_driver/components/custom_chip_driver/CMakeLists.txt index 9af56cb870..01da9109b2 100644 --- a/examples/storage/custom_flash_driver/components/custom_chip_driver/CMakeLists.txt +++ b/examples/storage/custom_flash_driver/components/custom_chip_driver/CMakeLists.txt @@ -3,5 +3,4 @@ idf_component_register(SRCS "chip_drivers.c" "spi_flash_chip_eon.c" LDFRAGMENTS linker.lf INCLUDE_DIRS "") -idf_component_get_property(spi_flash_lib spi_flash COMPONENT_LIB) -set_property(TARGET ${spi_flash_lib} APPEND PROPERTY INTERFACE_LINK_LIBRARIES $) +idf_component_add_link_dependency(FROM spi_flash) diff --git a/tools/cmake/component.cmake b/tools/cmake/component.cmake index 36132d31d0..6f5f00efbc 100644 --- a/tools/cmake/component.cmake +++ b/tools/cmake/component.cmake @@ -604,6 +604,33 @@ function(idf_component_optional_requires req_type) endforeach() endfunction() +# idf_component_add_link_dependency +# +# @brief Specify than an ESP-IDF component library depends on another component +# library at link time only. +# +# @note Almost always it's better to use idf_component_register() REQUIRES or +# PRIV_REQUIRES for this. However using this function allows adding a dependency +# from inside a different component, as a last resort. +# +# @param[in, required] FROM Component the dependency is from (this component depends on the other component) +# @param[in, optional] TO Component the dependency is to (this component is depended on by FROM). If omitted +# then the current component is assumed. For this default value to work, this function must be called after +# idf_component_register() in the component CMakeLists.txt file. +function(idf_component_add_link_dependency) + set(single_value FROM TO) + cmake_parse_arguments(_ "" "${single_value}" "" ${ARGN}) + + idf_component_get_property(from_lib ${__FROM} COMPONENT_LIB) + if(__TO) + idf_component_get_property(to_lib ${__TO} COMPONENT_LIB) + else() + set(to_lib ${COMPONENT_LIB}) + endif() + set_property(TARGET ${from_lib} APPEND PROPERTY INTERFACE_LINK_LIBRARIES $) +endfunction() + + # # Deprecated functions #