]> granicus.if.org Git - esp-idf/commitdiff
cmake: Add component dependency support
authorAngus Gratton <angus@espressif.com>
Thu, 22 Mar 2018 06:27:10 +0000 (17:27 +1100)
committerAngus Gratton <gus@projectgus.com>
Sun, 29 Apr 2018 23:59:20 +0000 (09:59 +1000)
Components should set the COMPONENT_REQUIRES & COMPONENT_PRIVATE_REQUIRES variables to define their
requirements.

56 files changed:
components/app_trace/CMakeLists.txt
components/app_update/CMakeLists.txt
components/app_update/esp_ota_ops.c
components/app_update/include/esp_ota_ops.h
components/aws_iot/CMakeLists.txt
components/bootloader/CMakeLists.txt
components/bootloader/subproject/CMakeLists.txt
components/bootloader_support/CMakeLists.txt
components/bt/CMakeLists.txt
components/coap/CMakeLists.txt
components/console/CMakeLists.txt
components/cxx/CMakeLists.txt
components/driver/CMakeLists.txt
components/esp-tls/CMakeLists.txt [new file with mode: 0644]
components/esp32/CMakeLists.txt
components/esp_adc_cal/CMakeLists.txt
components/ethernet/CMakeLists.txt
components/expat/CMakeLists.txt
components/fatfs/CMakeLists.txt
components/freertos/CMakeLists.txt
components/heap/CMakeLists.txt
components/idf_test/CMakeLists.txt
components/jsmn/CMakeLists.txt
components/json/CMakeLists.txt
components/libsodium/CMakeLists.txt
components/log/CMakeLists.txt
components/lwip/CMakeLists.txt
components/mbedtls/CMakeLists.txt
components/mdns/CMakeLists.txt
components/micro-ecc/CMakeLists.txt
components/newlib/CMakeLists.txt
components/nghttp/CMakeLists.txt
components/nvs_flash/CMakeLists.txt
components/openssl/CMakeLists.txt
components/partition_table/CMakeLists.txt
components/pthread/CMakeLists.txt
components/sdmmc/CMakeLists.txt
components/smartconfig/CMakeLists.txt
components/soc/CMakeLists.txt
components/spi_flash/CMakeLists.txt
components/spiffs/CMakeLists.txt
components/tcpip_adapter/CMakeLists.txt
components/ulp/CMakeLists.txt
components/vfs/CMakeLists.txt
components/wear_levelling/CMakeLists.txt
components/wpa_supplicant/CMakeLists.txt
components/xtensa-debug-module/CMakeLists.txt
docs/en/api-guides/build-system-cmake.rst
docs/en/api-guides/build-system.rst
examples/protocols/http2_request/components/sh2lib/CMakeLists.txt
tools/cmake/components.cmake
tools/cmake/convert_to_cmake.py
tools/cmake/idf_functions.cmake
tools/cmake/kconfig.cmake
tools/cmake/project.cmake
tools/cmake/scripts/expand_requirements.cmake [new file with mode: 0644]

index fec9b921d6b15f93695e14e539fb21b206869e56..5a6f19dbbecd15b9e07b9788a888b2287950bd10 100644 (file)
@@ -14,6 +14,9 @@ if(CONFIG_SYSVIEW_ENABLE)
         "sys_view/esp32")
 endif()
 
+set(COMPONENT_REQUIRES)
+set(COMPONENT_PRIV_REQUIRES xtensa-debug-module)
+
 register_component()
 
 # disable --coverage for this component, as it is used as transport
index ba2fa9c7e7969fc30c1581d965c214f584dd777e..44663f68eade5c8b8fa68fa37f4a97b4b1d94624 100644 (file)
@@ -1,4 +1,7 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_REQUIRES "")
+set(COMPONENT_PRIV_REQUIRES bootloader_support spi_flash)
+
 register_component()
index 8e26ba162af2e3fc8cfc080909070627859df1ce..1047d2117fdbca97815ee1617d149a907302f573 100644 (file)
@@ -28,6 +28,7 @@
 #include "esp_image_format.h"
 #include "esp_secure_boot.h"
 #include "esp_flash_encrypt.h"
+#include "esp_spi_flash.h"
 #include "sdkconfig.h"
 
 #include "esp_ota_ops.h"
index a089a92be0519a6d3d8cdff68640e22bb4257848..8fcf622d373be8ab0a19f46b6eef7cd581df708c 100755 (executable)
@@ -20,7 +20,6 @@
 #include <stddef.h>
 #include "esp_err.h"
 #include "esp_partition.h"
-#include "esp_spi_flash.h"
 
 #ifdef __cplusplus
 extern "C"
index f8bfb26a27888f9283eec5cb27b2b578c1fd9c3f..f7644bd7a3f15a521976ce3c86d02bdf20f9b016 100644 (file)
@@ -1,8 +1,11 @@
-if(NOT CONFIG_AWS_IOT_SDK)
-    return()
+if(CONFIG_AWS_IOT_SDK)
+    set(COMPONENT_ADD_INCLUDEDIRS "include aws-iot-device-sdk-embedded-C/include")
+    set(COMPONENT_SRCDIRS "aws-iot-device-sdk-embedded-C/src port")
+else()
+    message(STATUS "Building empty aws_iot component due to configuration")
 endif()
 
-set(COMPONENT_ADD_INCLUDEDIRS "include aws-iot-device-sdk-embedded-C/include")
-set(COMPONENT_SRCDIRS "aws-iot-device-sdk-embedded-C/src port")
+set(COMPONENT_REQUIRES "mbedtls")
+set(COMPONENT_PRIV_REQUIRES "jsmn")
 
 register_component()
index 1b694f38194b9d2759ee1419c6814bd2702c5edd..d38b8ff8e17bfc6319c6424dfdcd30d32febad33 100644 (file)
@@ -1,2 +1,7 @@
-# TODO: add config stuff for bootloader here
+# bootloader component logic is all in project_include.cmake,
+# and subproject/CMakeLists.txt.
+#
+# This file is only included so the build system finds the
+# component
+
 
index 5ac887a4046a0e9c621b26c99cea173cecf995bb..719d9fb9da26f9ce037bbafe5754e6e33bfad411 100644 (file)
@@ -9,6 +9,8 @@ set(COMPONENTS bootloader esptool_py esp32 soc bootloader_support log spi_flash
 set(BOOTLOADER_BUILD 1)
 add_definitions(-DBOOTLOADER_BUILD=1)
 
+set(COMPONENT_REQUIRES_COMMON log esp32 soc)
+
 set(MAIN_SRCS main/bootloader_start.c)
 
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
index 6df7b24db93f93ca959a8493fffdeaa2700be256..21978397e8c345a2b3f20f0349c8a2c6508e9ed2 100644 (file)
@@ -2,9 +2,13 @@ set(COMPONENT_SRCDIRS "src")
 
 if(${BOOTLOADER_BUILD})
     set(COMPONENT_ADD_INCLUDEDIRS "include include_priv")
+    set(COMPONENT_REQUIRES)
+    set(COMPONENT_PRIV_REQUIRES spi_flash micro-ecc)
 else()
     set(COMPONENT_ADD_INCLUDEDIRS "include")
     set(COMPONENT_PRIV_INCLUDEDIRS "include_priv")
+    set(COMPONENT_REQUIRES)
+    set(COMPONENT_PRIV_REQUIRES spi_flash mbedtls micro-ecc)
 endif()
 
 register_component()
index 9431645e8404b4511f1221ae9cea897c77e0c886..c2134be8f444ad1a6a27042b42cb6c6c03d79dfe 100644 (file)
@@ -1,83 +1,90 @@
-if(NOT CONFIG_BT_ENABLED)
-    return()
-endif()
-
-set(COMPONENT_SRCDIRS .)
-set(COMPONENT_ADD_INCLUDEDIRS include)
+if(CONFIG_BT_ENABLED)
 
-if(CONFIG_BLUEDROID_ENABLED)
+    set(COMPONENT_SRCDIRS .)
+    set(COMPONENT_ADD_INCLUDEDIRS include)
 
-    list(APPEND COMPONENT_ADD_INCLUDEDIRS
-        bluedroid/bta/include
-        bluedroid/bta/sys/include
-        bluedroid/btcore/include
-        bluedroid/device/include
-        bluedroid/hci/include
-        bluedroid/osi/include
-        bluedroid/external/sbc/decoder/include
-        bluedroid/external/sbc/encoder/include
-        bluedroid/btc/profile/esp/blufi/include
-        bluedroid/btc/profile/esp/include
-        bluedroid/btc/profile/std/a2dp/include
-        bluedroid/btc/profile/std/include
-        bluedroid/btc/include
-        bluedroid/stack/gap/include
-        bluedroid/stack/gatt/include
-        bluedroid/stack/l2cap/include
-        bluedroid/stack/sdp/include
-        bluedroid/stack/smp/include
-        bluedroid/stack/avct/include
-        bluedroid/stack/avrc/include
-        bluedroid/stack/avdt/include
-        bluedroid/stack/a2dp/include
-        bluedroid/stack/rfcomm/include
-        bluedroid/stack/include
-        bluedroid/api/include
-        bluedroid/include)
+    if(CONFIG_BLUEDROID_ENABLED)
 
-    list(APPEND COMPONENT_SRCDIRS
-        bluedroid/bta/dm
-        bluedroid/bta/gatt
-        bluedroid/bta/hh
-        bluedroid/bta/sdp
-        bluedroid/bta/av
-        bluedroid/bta/ar
-        bluedroid/bta/sys
-        bluedroid/bta/jv
-        bluedroid/btcore
-        bluedroid/btif
-        bluedroid/device
-        bluedroid/hci
-        bluedroid/main
-        bluedroid/osi
-        bluedroid/external/sbc/decoder/srce
-        bluedroid/external/sbc/encoder/srce
-        bluedroid/btc/core
-        bluedroid/btc/profile/esp/blufi
-        bluedroid/btc/profile/std/gap
-        bluedroid/btc/profile/std/gatt
-        bluedroid/btc/profile/std/a2dp
-        bluedroid/btc/profile/std/avrc
-        bluedroid/btc/profile/std/spp
-        bluedroid/stack/btm
-        bluedroid/stack/btu
-        bluedroid/stack/gap
-        bluedroid/stack/gatt
-        bluedroid/stack/hcic
-        bluedroid/stack/l2cap
-        bluedroid/stack/sdp
-        bluedroid/stack/smp
-        bluedroid/stack/avct
-        bluedroid/stack/avrc
-        bluedroid/stack/avdt
-        bluedroid/stack/a2dp
-        bluedroid/stack/rfcomm
-        bluedroid/api
-        )
+        list(APPEND COMPONENT_ADD_INCLUDEDIRS
+            bluedroid/bta/include
+                   bluedroid/bta/sys/include
+                   bluedroid/btcore/include
+                   bluedroid/device/include
+                   bluedroid/hci/include
+                   bluedroid/osi/include
+                   bluedroid/external/sbc/decoder/include
+                   bluedroid/external/sbc/encoder/include
+                   bluedroid/btc/profile/esp/blufi/include
+                   bluedroid/btc/profile/esp/include
+                   bluedroid/btc/profile/std/a2dp/include
+                   bluedroid/btc/profile/std/include
+                   bluedroid/btc/include
+                   bluedroid/stack/gap/include
+                   bluedroid/stack/gatt/include
+                   bluedroid/stack/l2cap/include
+                   bluedroid/stack/sdp/include
+                   bluedroid/stack/smp/include
+                   bluedroid/stack/avct/include
+                   bluedroid/stack/avrc/include
+                   bluedroid/stack/avdt/include
+                   bluedroid/stack/a2dp/include
+                   bluedroid/stack/rfcomm/include
+                   bluedroid/stack/include
+                   bluedroid/api/include
+                   bluedroid/include
+            )
 
+        list(APPEND COMPONENT_SRCDIRS
+            bluedroid/bta/dm
+                   bluedroid/bta/gatt
+                   bluedroid/bta/hh
+                   bluedroid/bta/sdp
+                   bluedroid/bta/av
+                   bluedroid/bta/ar
+                   bluedroid/bta/sys
+                   bluedroid/bta/jv
+                   bluedroid/btcore
+                   bluedroid/btif
+                   bluedroid/device
+                   bluedroid/hci
+                   bluedroid/main
+                   bluedroid/osi
+                   bluedroid/external/sbc/decoder/srce
+                   bluedroid/external/sbc/encoder/srce
+                   bluedroid/btc/core
+                   bluedroid/btc/profile/esp/blufi
+                   bluedroid/btc/profile/std/gap
+                   bluedroid/btc/profile/std/gatt
+                   bluedroid/btc/profile/std/a2dp
+                   bluedroid/btc/profile/std/avrc
+                   bluedroid/btc/profile/std/spp
+                   bluedroid/stack/btm
+                   bluedroid/stack/btu
+                   bluedroid/stack/gap
+                   bluedroid/stack/gatt
+                   bluedroid/stack/hcic
+                   bluedroid/stack/l2cap
+                   bluedroid/stack/sdp
+                   bluedroid/stack/smp
+                   bluedroid/stack/avct
+                   bluedroid/stack/avrc
+                   bluedroid/stack/avdt
+                   bluedroid/stack/a2dp
+                   bluedroid/stack/rfcomm
+                   bluedroid/api
+            )
+    endif()
 endif()
 
+# requirements can't depend on config
+set(COMPONENT_PRIV_REQUIRES lwip nvs_flash)
+
+# currently uses libcoap's hash table in hashkey.h
+set(COMPONENT_REQUIRES coap)
+
 register_component()
 
-target_link_libraries(bt "-L${CMAKE_CURRENT_LIST_DIR}/lib")
-target_link_libraries(bt btdm_app)
+if(CONFIG_BT_ENABLED)
+    target_link_libraries(bt "-L${CMAKE_CURRENT_LIST_DIR}/lib")
+    target_link_libraries(bt btdm_app)
+endif()
index cadd463fafa8fe671fcdc29740d98d880f765ba1..faba933094b5d5e87ef93bafa10bc16157a0d219 100644 (file)
@@ -19,6 +19,8 @@ set(COMPONENT_SRCS
     port/coap_io_socket.c
     )
 
+set(COMPONENT_REQUIRES lwip)
+
 register_component()
 
 # Needed for coap headers in public builds, also.
index 1c5648654cd3e03bbbf9fde2aa36488e113760a0..0b0da5394ac981dd9742193f7bbdf65965cdaca5 100644 (file)
@@ -1,5 +1,7 @@
 set(COMPONENT_ADD_INCLUDEDIRS .)
 set(COMPONENT_SRCDIRS linenoise argtable3 .)
 
+set(COMPONENT_REQUIRES)
+
 register_component()
 
index 255f4f3fd7cd2a490581ed5ce2f3a7a056467b66..a797640cc01b40908bd76c9d1debb38942c0f0ce 100644 (file)
@@ -1,4 +1,5 @@
 set(COMPONENT_SRCDIRS ".")
+set(COMPONENT_REQUIRES)
 register_component()
 
 target_link_libraries(cxx stdc++)
index 8ccaad2c32dcc7de1a1b25ff8f8b331c3f614ca3..0c72aecc439891c8f051e96eb87f46206e69c15a 100644 (file)
@@ -2,4 +2,6 @@ set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 set(COMPONENT_PRIV_INCLUDEDIRS "include/driver")
 
+set(COMPONENT_REQUIRES)
+
 register_component()
diff --git a/components/esp-tls/CMakeLists.txt b/components/esp-tls/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9bad428
--- /dev/null
@@ -0,0 +1,7 @@
+set(COMPONENT_SRCDIRS ".")
+set(COMPONENT_ADD_INCLUDEDIRS ".")
+
+set(COMPONENT_REQUIRES mbedtls)
+set(COMPONENT_PRIV_REQUIRES lwip nghttp)
+
+register_component()
index 1172dda7fb48d8ed45d525db2e6a63ff0996f988..b231bfd0d72f39bf48a56b8ec2af107172adcedb 100644 (file)
@@ -1,7 +1,9 @@
 if(BOOTLOADER_BUILD)
     # For bootloader, all we need from esp32 is headers
-    add_library(esp32 INTERFACE)
-    target_include_directories(esp32 INTERFACE include)
+    set(COMPONENT_ADD_INCLUDEDIRS include)
+    set(COMPONENT_REQUIRES ${COMPONENTS})
+    set(COMPONENT_SRCDIRS "")
+    register_component(esp32)
 
     # as cmake won't attach linker args to a header-only library, attach
     # linker args directly to the bootloader.elf
@@ -18,6 +20,11 @@ else()
     set(COMPONENT_SRCDIRS ". hwcrypto")
     set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+    set(COMPONENT_REQUIRES driver)  # required because esp_sleep.h uses gpio_num_t & touch_pad_t
+    set(COMPONENT_PRIV_REQUIRES
+        adapter app bootloader_debug ethernet_flash flash_log mbedtls_module nvs_pthread
+        spi-supplicant-support tcpip trace_vfs wpa xtensa)
+
     register_component()
 
     target_link_libraries(esp32 "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib")
index ba2fa9c7e7969fc30c1581d965c214f584dd777e..fc21f1ecac84ac577c41ad875b366452f8fcf13a 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_REQUIRES)
+
 register_component()
index a9eb903703dbb909095baddfbf4da27532e54232..165d89fbe1c38b4040fee839b47acd7edb829826 100644 (file)
@@ -1,4 +1,7 @@
 set(COMPONENT_SRCDIRS . eth_phy)
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_REQUIRES)
+set(COMPONENT_PRIV_REQUIRES tcpip_adapter)
+
 register_component()
index 9e77a825c44b14c9761c34ccba808d644f586877..5791a265990cd7f5b7704207daaae09332377153 100644 (file)
@@ -1,6 +1,8 @@
 set(COMPONENT_ADD_INCLUDEDIRS port/include include/expat)
 set(COMPONENT_SRCDIRS library port)
 
+set(COMPONENT_REQUIRES)
+
 register_component()
 
 component_compile_definitions(HAVE_EXPAT_CONFIG_H)
index c9f5a0fcfd5a1b10799a9e834dd0c0df4ee78827..3d24c50bf97d7f47cde1c6e4708dadd0a84cbfee 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS src)
 set(COMPONENT_ADD_INCLUDEDIRS src)
 
+set(COMPONENT_REQUIRES wear_levelling sdmmc)
+
 register_component()
index 0a5172dc10b7acfafe4a8eda1585c18070ec0a96..a0be8f0862872006e2fc7ebcf4370b947f49a414 100644 (file)
@@ -1,6 +1,8 @@
 set(COMPONENT_ADD_INCLUDEDIRS include)
 set(COMPONENT_PRIV_INCLUDEDIRS include/freertos)
 set(COMPONENT_SRCDIRS ".")
+set(COMPONENT_REQUIRES)
+
 register_component()
 
 target_link_libraries(freertos "-Wl,--undefined=uxTopUsedPriority")
index 08e78e84580760a9fdb392fc492df0b2cfb1496e..b7dd5d9ac106fd8be923ee961e0a48a8fd3e59db 100644 (file)
@@ -6,6 +6,8 @@ endif()
 
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_REQUIRES "")
+
 register_component()
 
 if(CONFIG_HEAP_TRACING)
index e307838a8b2d096e8fc025f0144306699eb4b32c..cf64054dd8bf583c9463f8b6b6ac356e0fa2a436 100644 (file)
@@ -1,2 +1,3 @@
 set(COMPONENT_ADD_INCLUDEDIRS "include")
+set(COMPONENT_REQUIRES)
 register_component()
index 2eabcf5fe616966a4905b890011a9592df717b85..7c19d9ccba93f2600d6d6808b69365cf7e14b55d 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS "src")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_REQUIRES "")
+
 register_component()
index c19ec43fa8b4e281f93f6e652de56c93dba85e83..0b8ba83d66b34edfac5bfb350737bca3ee5184bb 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS cJSON)
 set(COMPONENT_ADD_INCLUDEDIRS cJSON)
 
+set(COMPONENT_REQUIRES "")
+
 register_component()
index 48e5a3f6908305c4faa664e5db2ebdc307d0067d..674534c91680b328c60ff0b51f730d79f4d07b03 100644 (file)
@@ -1,5 +1,7 @@
 set(SRC libsodium/src/libsodium)
 
+set(COMPONENT_REQUIRES "mbedtls")
+
 set(COMPONENT_SRCDIRS
     port
 
index eebd20a046213a730b2a05b8158054f12fe16925..ad162fe1e1c2529624178672769534783d694e44 100644 (file)
@@ -1,3 +1,4 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
+set(COMPONENT_REQUIRES)
 register_component()
index 5474c4daad285eaf1fe79176a8938274cc9a103a..03deae43696e2f48b27ee6b28359422c9eb11576 100644 (file)
@@ -16,6 +16,9 @@ set(COMPONENT_SRCDIRS
     ${LWIP_PPP_DIRS} netif
     port/freertos port/netif port/debug port)
 
+set(COMPONENT_REQUIRES "")
+set(COMPONENT_PRIV_REQUIRES ethernet tcpip_adapter)
+
 register_component()
 
 component_compile_options(-Wno-address)
index 56dfce17cf82ebf017a306c19f74d81ec8e78308..44410c1492e83eae4b9722d2b26e9862a11f17cf 100644 (file)
@@ -1,6 +1,8 @@
 set(COMPONENT_ADD_INCLUDEDIRS port/include include)
 set(COMPONENT_SRCDIRS library port)
 
+set(COMPONENT_REQUIRES lwip)
+
 register_component()
 
 target_compile_definitions(mbedtls PUBLIC
index 149dcb0bccbc899a5b30c91b1cfaa07af04a9a35..4ab664110912d53d0ce12acbefa8716ecdb71de6 100644 (file)
@@ -1,5 +1,7 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 set(COMPONENT_PRIV_INCLUDEDIRS "private_include")
+set(COMPONENT_REQUIRES lwip mbedtls console tcpip_adapter)
+
 register_component()
 
index 13bc9cfb64946c37b841db87ace334197397f0bb..24e0a9e6f6dadbbc769fcd6b22a16fcc60ed4c9b 100644 (file)
@@ -3,4 +3,6 @@ set(COMPONENT_SRCS micro-ecc/uECC.c)
 
 set(COMPONENT_ADD_INCLUDEDIRS micro-ecc)
 
+set(COMPONENT_REQUIRES)
+
 register_component()
index c92518deb3820b4928fba94f1c2f1d44eecd1820..4bc0db3f903cab9535ad119bdb94609c6761d664 100644 (file)
@@ -15,6 +15,8 @@ else()
     set(LIBM m)
 endif()
 
+set(COMPONENT_REQUIRES vfs)  # for sys/ioctl.h
+
 register_component()
 
 target_link_libraries(newlib "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib")
index c7e4b754b87f7f89795a9868e6e10c51fb4884f4..bf3f72746888ca46b12ffbe2c5cc2e9b6c5530de 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_ADD_INCLUDEDIRS port/include nghttp2/lib/includes)
 set(COMPONENT_SRCDIRS nghttp2/lib port)
 
+set(COMPONENT_REQUIRES lwip mbedtls)
+
 register_component()
index 5970a79154b9f61cd40a8024748e9f360a2697df..1fe5ecf26e12175f2168ca61d4809ffea46f07c8 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS src)
 set(COMPONENT_ADD_INCLUDEDIRS include)
 
+set(COMPONENT_REQUIRES spi_flash)
+
 register_component()
index 347ade63871917d02af7478b9adeaf3f3b7cc3f1..84d02ffe8807ddbba96f573642a1f0fe7ca3fa93 100644 (file)
@@ -2,4 +2,6 @@ set(COMPONENT_ADD_INCLUDEDIRS include)
 set(COMPONENT_PRIV_INCLUDEDIRS include/internal include/platform include/openssl)
 set(COMPONENT_SRCDIRS library platform)
 
+set(COMPONENT_REQUIRES mbedtls)
+
 register_component()
index 87f12da943df0e4af718c6d9ea8ea047c7917f53..cde193dce9709d4cb28c82da63f69a102226c17a 100644 (file)
@@ -1,5 +1,7 @@
 set(partition_table_offset 0x8000)
 
+register_config_only_component()
+
 # Set partition_csv to the configured partition source file
 #
 if(CONFIG_PARTITION_TABLE_CUSTOM)
@@ -56,4 +58,3 @@ set_property(GLOBAL APPEND_STRING PROPERTY
     ESPTOOL_WRITE_FLASH_ARGS
     "${partition_table_offset} ${final_partition_bin} ")
 
-register_config_only_component()
index eebd20a046213a730b2a05b8158054f12fe16925..ad162fe1e1c2529624178672769534783d694e44 100644 (file)
@@ -1,3 +1,4 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
+set(COMPONENT_REQUIRES)
 register_component()
index ba2fa9c7e7969fc30c1581d965c214f584dd777e..58b9aeb6797c2f806c2d71f23b7ee3d3a2635e16 100644 (file)
@@ -1,4 +1,4 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
-
+set(COMPONENT_REQUIRES driver)
 register_component()
index ba2fa9c7e7969fc30c1581d965c214f584dd777e..8b18007dea201fb976e6ebc2a7066dc43e539b80 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_PRIV_REQUIRES lwip tcpip_adapter)
+
 register_component()
index 24e859551461c1f1ecdda01a1d8dfa446718b4f9..b4c088edd72c2f28b085c8c11ccfb17300169c6f 100644 (file)
@@ -3,4 +3,7 @@ set(SOC_NAME esp32)
 set(COMPONENT_SRCDIRS ${SOC_NAME})
 set(COMPONENT_ADD_INCLUDEDIRS ${SOC_NAME}/include include)
 
+set(COMPONENT_REQUIRES)
+
+
 register_component()
index f64a6ec117f74b568c43ae932df2df62425f6c24..1eafba54d4ecd3c32e530a71041440841dc63f5d 100644 (file)
@@ -2,10 +2,13 @@ if(BOOTLOADER_BUILD)
     # Bootloader needs SPIUnlock from this file, but doesn't
     # need other parts of this component
     set(COMPONENT_SRCS spi_flash_rom_patch.c)
+    set(COMPONENT_PRIV_REQUIRES bootloader_support)
 else()
     set(COMPONENT_SRCDIRS .)
+    set(COMPONENT_PRIV_REQUIRES bootloader_support app_update)
 endif()
 
 set(COMPONENT_ADD_INCLUDEDIRS include)
+set(COMPONENT_REQUIRES)
 
 register_component()
index 5e0027f52da90bb1fc2e03fb78e0adcf9bf91777..a85f98d2b3ee4e4b3b30ac26019f6c529ab93d15 100644 (file)
@@ -1,5 +1,9 @@
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 set(COMPONENT_PRIV_INCLUDEDIRS "spiffs/src")
 set(COMPONENT_SRCDIRS ". spiffs/src")
+
+set(COMPONENT_REQUIRES spi_flash)
+set(COMPONENT_PRIV_REQUIRES bootloader_support)
+
 register_component()
 
index ba2fa9c7e7969fc30c1581d965c214f584dd777e..24deb2f24796c5f05a1bf87caa34bc59937fdce7 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_REQUIRES lwip)
+
 register_component()
index ba2fa9c7e7969fc30c1581d965c214f584dd777e..fc21f1ecac84ac577c41ad875b366452f8fcf13a 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_REQUIRES)
+
 register_component()
index ba2fa9c7e7969fc30c1581d965c214f584dd777e..fc21f1ecac84ac577c41ad875b366452f8fcf13a 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_REQUIRES)
+
 register_component()
index a72d0f565f69974b6602dd3628424a73abc9a30b..8b5db6231dea4cc5828816733ec14f6a4aa03554 100644 (file)
@@ -1,4 +1,5 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 set(COMPONENT_PRIV_INCLUDEDIRS private_include)
+set(COMPONENT_REQUIRES spi_flash)
 register_component()
index 1d2091656a0b548313e2253487cba883a532b0ed..fc0c323fc9d0488fa2d0d32363b58efe965bfe9d 100644 (file)
@@ -1,6 +1,9 @@
 set(COMPONENT_SRCDIRS src/crypto port src/fast_crypto)
 set(COMPONENT_ADD_INCLUDEDIRS include port/include)
 
+set(COMPONENT_REQUIRES "")
+set(COMPONENT_PRIV_REQUIRES lwip mbedtls)
+
 register_component()
 
 component_compile_definitions(__ets__)
index ba2fa9c7e7969fc30c1581d965c214f584dd777e..810d299d134e418f94661ec05e283d37da5c8abc 100644 (file)
@@ -1,4 +1,6 @@
 set(COMPONENT_SRCDIRS ".")
 set(COMPONENT_ADD_INCLUDEDIRS "include")
 
+set(COMPONENT_REQUIRES "")
+
 register_component()
index a4de8406084f6a24072f1b6b789424e8282236c0..03eb0c206fe8f377cb3138c75306163032300153 100644 (file)
@@ -78,7 +78,7 @@ The :ref:`getting started guide <get-started-configure-cmake>` contains a brief
 
 ``idf.py`` should be run in an ESP-IDF "project" directory, ie one containing a ``CMakeLists.txt`` file. Older style projects with a Makefile will not work with ``idf.py``.
 
-Type ``idf.py --help`` for a full list of commands. Here are a summary of a few:
+Type ``idf.py --help`` for a full list of commands. Here are a summary of the most useful ones:
 
 - ``idf.py menuconfig`` runs the "menuconfig" tool to configure the project.
 - ``idf.py build`` will build the project found in the current directory. This can involve multiple steps:
@@ -207,7 +207,8 @@ These variables all have default values that can be overridden for custom behavi
 
 - ``COMPONENT_DIRS``: Directories to search for components. Defaults to `${IDF_PATH}/components`, `${PROJECT_PATH}/components`, and ``EXTRA_COMPONENT_DIRS``. Override this variable if you don't want to search for components in these places.
 - ``EXTRA_COMPONENT_DIRS``: Optional list of additional directories to search for components. Paths can be relative to the project directory, or absolute.
-- ``COMPONENTS``: A list of component names to build into the project. Defaults to all components found in the ``COMPONENT_DIRS`` directories. Use this variable to "trim down" the project for faster build times.
+- ``COMPONENTS``: A list of component names to build into the project. Defaults to all components found in the ``COMPONENT_DIRS`` directories. Use this variable to "trim down" the project for faster build times. Note that any component which "requires" another component via ``COMPONENT_REQUIRES`` will automatically have it added to this list, so the ``COMPONENTS`` list doesn't need to include dependencies in this way.
+- ``COMPONENT_REQUIRES_COMMON``: A list of components that every component requires. These components are automatically treated to be in every component's ``COMPONENT_PRIV_REQUIRES`` list and also the project's ``COMPONENTS`` list. By default, this is set to the minimal set of core "system" components needed for any ESP-IDF project.
 
 Any paths in these variables can be absolute paths, or set relative to the project directory.
 
@@ -273,22 +274,18 @@ The following variables are set at the project level, but available for use in c
 
 If you modify any of these variables inside ``CMakeLists.txt`` then this will not prevent other components from building but it may make your component hard to build and/or debug.
 
-Optional Project-Wide Component Variables
------------------------------------------
-
-The following variables can be set inside component ``CMakeLists.txt`` to control build settings across the entire project:
 
 - ``COMPONENT_ADD_INCLUDEDIRS``: Paths, relative to the component
   directory, which will be added to the include search path for
-  all components in the project. If an include directory is only needed to compile
+  all other components which require this one. If an include directory is only needed to compile
   this specific component, add it to ``COMPONENT_PRIV_INCLUDEDIRS`` instead.
-- ``COMPONENT_DEPENDS``: Optional list of component names that should be
-  compiled before this component. This is not necessary for
-  link-time dependencies, because all component include directories
-  are available at all times. It is necessary if one component
-  generates an include file which you then want to include in another
-  component. Most components do not need to set this variable.
+- ``COMPONENT_REQUIRES`` is a (space-separated) list of components that are required to include this project's header files into other components. If a public header header file listed in ``COMPONENT_ADD_INCLUDEDIRS`` includes a header from another component, that component should be listed in ``COMPONENT_REQUIRES``. Requirements are recursive.
+
+  The ``COMPONENT_REQUIRES`` list can be empty because some very common components (like newlib for libc, freertos for RTOS functions, etc) are always required by all components. This list is found in the project-level variable ``COMPONENT_REQUIRES_COMMON``.
 
+  If a component only requires another component's headers to compile its source files (not for including this component's headers), then these components should be listed in ``COMPONENT_PRIV_REQUIRES`` instead.
+
+  See `Component Requirements` for more details.
 
 Optional Component-Specific Variables
 -------------------------------------
@@ -298,6 +295,7 @@ The following variables can be set inside ``component.mk`` to control the build
 - ``COMPONENT_PRIV_INCLUDEDIRS``: Directory paths, must be relative to
   the component directory, which will be added to the include search
   path for this component's source files only.
+- ``COMPONENT_PRIV_REQUIRES`` is a (space-separated) list of components that are required to either compile or link this component's source files. These components' header paths do not propagate to other components which require it, they are only used to compile this component's sources. See `Component Requirements` for more details.
 - ``COMPONENT_SRCDIRS``: Directory paths, must be relative to the
   component directory, which will be searched for source files (``*.cpp``,
   ``*.c``, ``*.S``). Set this to specify a list of directories
@@ -345,6 +343,45 @@ The ESP-IDF build system adds the following C preprocessor definitions on the co
 - ``ESP_PLATFORM`` â€” Can be used to detect that build happens within ESP-IDF.
 - ``IDF_VER`` â€” Defined to a git version string.  E.g. ``v2.0`` for a tagged release or ``v1.0-275-g0efaa4f`` for an arbitrary commit.
 
+Component Requirements
+======================
+
+When compiling each component, the ESP-IDF build system recurisvely evaluates its components.
+
+Each component's source file is compiled with these include path directories:
+
+- The current component's ``COMPONENT_ADD_INCLUDEDIRS`` and ``COMPONENT_PRIV_INCLUDEDIRS``.
+- The ``COMPONENT_ADD_INCLUDEDIRS`` set by all components in the current component's ``COMPONENT_REQUIRES`` and ``COMPONENT_PRIV_REQUIRES`` variables (ie all the current component's public and private dependencies).
+- All of the ``COMPONENT_REQUIRES`` of those components, evaluated recursively (ie all public dependencies of this component's dependencies, recursively expanded).
+
+When writing a component
+------------------------
+
+- ``COMPONENT_REQUIRES`` should be set to all components whose header files are #included from the *public* header files of this component.
+- ``COMPONENT_PRIV_REQUIRES`` should be set to all components whose header files are #included from *any source files* of this component, unless already listed in ``COMPONENT_REQUIRES``. Or any component which is required to be linked in order for this component to function correctly.
+- ``COMPONENT_REQUIRES`` and/or ``COMPONENT_PRIV_REQUIRES`` should be set before calling ``register_component()``.
+- The values of ``COMPONENT_REQUIRES`` and ``COMPONENT_PRIV_REQUIRES`` should not depend on any configuration choices (``CONFIG_xxx`` macros). This is because requirements are expanded before configuration is loaded. Other component variables (like include paths or source files) can depend on configuration choices.
+- Not setting either or both ``REQUIRES`` variables is fine. If the component has no requirements except for the "common" components needed for RTOS, libc, etc (``COMPONENT_REQUIRES_COMMON``) then both variables can be empty or unset.
+
+When creating a project
+-----------------------
+
+- By default, every component is included in the build.
+- If you set the ``COMPONENTS`` variable to a minimal list of components used directly by your project, then the build will include:
+  - Components mentioned explicitly in ``COMPONENTS``.
+  - Those components' requirements (evaluated recursively).
+  - The "common" components that every component depends on.
+- Setting ``COMPONENTS`` to the minimal list of components you need can significantly reduce your project's compile time.
+- When compiling the project's source files (``MAIN_SRCS``), the public header directories of all components included in the build are available.
+
+Requirements in the build system implementation
+------------------------------------------------------------------
+
+- Very early in the cmake configuration process, the script ``expand_requirements.cmake`` is run. This script does a partial evaluation of all component CMakeLists.txt files and builds a graph of component requirements (this graph may have cycles). The graph is used to generate a file ``component_depends.cmake`` in the build directory.
+- The main cmake process then includes this file and uses it to determine the list of components to include in the build (internal ``BUILD_COMPONENTS`` variable).
+- Configuration is then evaluated for the components included in the build.
+- Each component is included in the build normally and the CMakeLists.txt file is evaluated again to add the component libraries to the build.
+
 Build Process Internals
 =======================
 
@@ -362,6 +399,7 @@ project function
 
 The custom ``project()`` function performs the following steps:
 
+- Evaluates component dependencies and builds the ``BUILD_COMPONENTS`` list of components to include in the build (see `above<requirements-in-the-build-system-implementation>`).
 - Finds all components in the project (searching ``COMPONENT_DIRS`` and filtering by ``COMPONENTS`` if this is set).
 - Loads the project configuration from the ``sdkconfig`` file and produces a ``cmake`` include file and a C header file, to set config macros. If the project configuration changes, cmake will automatically be re-run to reconfigure the project.
 - Sets the `CMAKE_TOOLCHAIN_FILE`_ variable to the ESP-IDF toolchain file with the Xtensa ESP32 toolchain.
@@ -525,10 +563,8 @@ why it is added to the `ADDITIONAL_MAKE_CLEAN_FILES`_ property.
 
 (Note: If generating files as part of the project CMakeLists, not a component CMakeLists, use ``${PROJECT_PATH}`` instead of ``${COMPONENT_PATH}`` and ``${PROJECT_NAME}.elf`` instead of ``${COMPONENT_NAME}``.)
 
-If a a source file from another component included ``logo.h``, then this
-component's name would have to be added to the other component's
-``COMPONENT_DEPENDS`` list to ensure that the components were built
-in-order.
+If a a source file from another component included ``logo.h``, then ``add_dependencies`` would need to be called to add a dependency between
+the two components, to ensure that the component source files were always compiled in the correct order.
 
 Embedding Binary Data
 ---------------------
index e638a36d079934c6c7b11747aa45a5c45ba446cd..8d3830c8bbd1e5adf4d36e60a2b42060f8a4ef58 100644 (file)
@@ -202,7 +202,7 @@ The following variables can be set inside ``component.mk`` to control build sett
   the app executable. Defaults to ``-l$(COMPONENT_NAME)``.  If
   adding pre-compiled libraries to this directory, add them as
   absolute paths - ie $(COMPONENT_PATH)/libwhatever.a
-- ``COMPONENT_DEPENDS``: Optional list of component names that should
+- ``COMPONENT_REQUIRES``: Optional list of component names that should
   be compiled before this component. This is not necessary for
   link-time dependencies, because all component include directories
   are available at all times. It is necessary if one component
@@ -544,7 +544,7 @@ generated before ``graphics_lib.c`` is compiled.
 
 If a a source file in another component included ``logo.h``, then this
 component's name would have to be added to the other component's
-``COMPONENT_DEPENDS`` list to ensure that the components were built
+``COMPONENT_REQUIRES`` list to ensure that the components were built
 in-order.
 
 Embedding Binary Data
index 74bb26787ef09bcc1100e3721d7468c89d506eb2..6d19bf48b69f235c2990c8df1fb569b53d9240dc 100644 (file)
@@ -2,4 +2,7 @@ set(COMPONENT_ADD_INCLUDEDIRS .)
 
 set(COMPONENT_SRCDIRS .)
 
+set(COMPONENT_REQUIRES nghttp)
+set(COMPONENT_PRIV_REQUIRES lwip esp-tls)
+
 register_component()
index 4334ffee7df903b9e6aaa6c877b58071cb6f5521..506d8a06facea4355dd6f28722ac323215f83495 100644 (file)
@@ -1,53 +1,16 @@
-# Search 'component_dirs' for components and return them
-# as a list of names in 'component_names' and a list of full paths in
-# 'component_paths'
-#
-# component_paths contains only unique component names. Directories
-# earlier in the component_dirs list take precedence.
-function(components_find_all component_dirs filter_names component_paths component_names)
-    # component_dirs entries can be files or lists of files
-    set(paths "")
-    set(names "")
-
-    # start by expanding the component_dirs list with all subdirectories
-    foreach(dir ${component_dirs})
-        # Iterate any subdirectories for values
-        file(GLOB subdirs LIST_DIRECTORIES true "${dir}/*")
-        foreach(subdir ${subdirs})
-            set(component_dirs "${component_dirs};${subdir}")
-        endforeach()
-    endforeach()
-
-    # Look for a component in each component_dirs entry
-    foreach(dir ${component_dirs})
-        file(GLOB component "${dir}/CMakeLists.txt")
-        if(component)
-            get_filename_component(component "${component}" DIRECTORY)
-            get_filename_component(name "${component}" NAME)
-            if(NOT filter_names OR (name IN_LIST filter_names))
-                if(NOT name IN_LIST names)
-                    set(names "${names};${name}")
-                    set(paths "${paths};${component}")
-                endif()
-            endif()
-
-        else()  # no CMakeLists.txt file
-            # test for legacy component.mk and warn
-            file(GLOB legacy_component "${dir}/component.mk")
-            if(legacy_component)
-                get_filename_component(legacy_component "${legacy_component}" DIRECTORY)
-                message(WARNING "Component ${legacy_component} contains old-style component.mk but no CMakeLists.txt. "
-                    "Component will be skipped.")
-            endif()
+# Given a list of components in 'component_paths', filter only paths to the components
+# mentioned in 'components' and return as a list in 'result_paths'
+function(components_get_paths component_paths components result_paths)
+    set(result "")
+    foreach(path ${component_paths})
+        get_filename_component(name "${path}" NAME)
+        if("${name}" IN_LIST components)
+            list(APPEND result "${name}")
         endif()
-
     endforeach()
-
-    set(${component_paths} ${paths} PARENT_SCOPE)
-    set(${component_names} ${names} PARENT_SCOPE)
+    set("${result_path}" "${result}" PARENT_SCOPE)
 endfunction()
 
-
 # Add a component to the build, using the COMPONENT variables defined
 # in the parent
 #
@@ -76,7 +39,7 @@ function(register_component)
         endforeach()
     endif()
 
-    # add public includes from other components when building this component
+    # add as a PUBLIC library (if there are source files) or INTERFACE (if header only)
     if(COMPONENT_SRCS OR embed_binaries)
         add_library(${component} STATIC ${COMPONENT_SRCS})
         set(include_type PUBLIC)
@@ -97,7 +60,7 @@ function(register_component)
         target_add_binary_data("${component}" "${embed_data}" "${embed_type}")
     endforeach()
 
-    # add public includes
+    # add component public includes
     foreach(include_dir ${COMPONENT_ADD_INCLUDEDIRS})
         get_filename_component(abs_dir ${include_dir} ABSOLUTE BASE_DIR ${component_dir})
         if(NOT IS_DIRECTORY ${abs_dir})
@@ -107,7 +70,7 @@ function(register_component)
         target_include_directories(${component} ${include_type} ${abs_dir})
     endforeach()
 
-    # add private includes
+    # add component private includes
     foreach(include_dir ${COMPONENT_PRIV_INCLUDEDIRS})
         if(${include_type} STREQUAL INTERFACE)
             message(FATAL_ERROR "${CMAKE_CURRENT_LIST_FILE} "
@@ -121,7 +84,6 @@ function(register_component)
         endif()
         target_include_directories(${component} PRIVATE ${abs_dir})
     endforeach()
-
 endfunction()
 
 function(register_config_only_component)
@@ -131,30 +93,47 @@ function(register_config_only_component)
     # No-op for now...
 endfunction()
 
+function(add_component_dependencies target dep dep_type)
+    get_target_property(target_type ${target} TYPE)
+    get_target_property(target_imported ${target} IMPORTED)
+
+    if(${target_type} STREQUAL STATIC_LIBRARY OR ${target_type} STREQUAL EXECUTABLE)
+        if(TARGET ${dep})
+            # Add all compile options exported by dep into target
+            target_include_directories(${target} ${dep_type}
+                $<TARGET_PROPERTY:${dep},INTERFACE_INCLUDE_DIRECTORIES>)
+            target_compile_definitions(${target} ${dep_type}
+                $<TARGET_PROPERTY:${dep},INTERFACE_COMPILE_DEFINITIONS>)
+            target_compile_options(${target} ${dep_type}
+                $<TARGET_PROPERTY:${dep},INTERFACE_COMPILE_OPTIONS>)
+        endif()
+    endif()
+endfunction()
+
 function(components_finish_registration)
-    # each component should see the include directories of each other
+
+    # have the executable target depend on all components in the build
+    set_target_properties(${CMAKE_PROJECT_NAME}.elf PROPERTIES INTERFACE_COMPONENT_REQUIRES "${BUILD_COMPONENTS}")
+
+    spaces2list(COMPONENT_REQUIRES_COMMON)
+
+    # each component should see the include directories of its requirements
     #
-    # (we can't do this until all components are registered, because if(TARGET ...) won't work
-    foreach(a ${COMPONENTS} ${CMAKE_PROJECT_NAME}.elf)
+    # (we can't do this until all components are registered and targets exist in cmake, as we have
+    # a circular requirements graph...)
+    foreach(a ${BUILD_COMPONENTS})
         if(TARGET ${a})
-            get_target_property(a_imported ${a} IMPORTED)
-            get_target_property(a_type ${a} TYPE)
-            if(NOT a_imported)
-                if(${a_type} STREQUAL STATIC_LIBRARY OR ${a_type} STREQUAL EXECUTABLE)
-                    foreach(b ${COMPONENTS})
-                        if(TARGET ${b} AND NOT ${a} STREQUAL ${b})
-                            # Add all public compile options from b in a
-                            target_include_directories(${a} PRIVATE
-                                $<TARGET_PROPERTY:${b},INTERFACE_INCLUDE_DIRECTORIES>)
-                            target_compile_definitions(${a} PRIVATE
-                                $<TARGET_PROPERTY:${b},INTERFACE_COMPILE_DEFINITIONS>)
-                            target_compile_options(${a} PRIVATE
-                                $<TARGET_PROPERTY:${b},INTERFACE_COMPILE_OPTIONS>)
-                        endif()
-                    endforeach(b)
-                endif()
-            endif()
+            get_component_requirements("${a}" a_deps a_priv_deps)
+            list(APPEND a_priv_deps ${COMPONENT_REQUIRES_COMMON})
+            foreach(b ${a_deps})
+                add_component_dependencies(${a} ${b} PUBLIC)
+            endforeach()
 
+            foreach(b ${a_priv_deps})
+                add_component_dependencies(${a} ${b} PRIVATE)
+            endforeach()
+
+            get_target_property(a_type ${a} TYPE)
             if(${a_type} MATCHES .+_LIBRARY)
                 set(COMPONENT_LIBRARIES "${COMPONENT_LIBRARIES};${a}")
             endif()
@@ -164,7 +143,7 @@ function(components_finish_registration)
     # Add each component library's link-time dependencies (which are otherwise ignored) to the executable
     # LINK_DEPENDS in order to trigger a re-link when needed (on Ninja/Makefile generators at least).
     # (maybe this should probably be something CMake does, but it doesn't do it...)
-    foreach(component ${COMPONENTS})
+    foreach(component ${BUILD_COMPONENTS})
         if(TARGET ${component})
             get_target_property(imported ${component} IMPORTED)
             get_target_property(type ${component} TYPE)
@@ -179,16 +158,6 @@ function(components_finish_registration)
         endif()
     endforeach()
 
-    # Embedded binary & text files
-    spaces2list(COMPONENT_EMBED_FILES)
-    foreach(embed_src ${COMPONENT_EMBED_FILES})
-        target_add_binary_data(${component} "${embed_src}" BINARY)
-    endforeach()
-    spaces2list(COMPONENT_EMBED_TXTFILES)
-    foreach(embed_src ${COMPONENT_EMBED_TXTFILES})
-        target_add_binary_data(${component} "${embed_src}" TEXT)
-    endforeach()
-
     target_link_libraries(${CMAKE_PROJECT_NAME}.elf ${COMPONENT_LIBRARIES})
 
     message(STATUS "Component libraries: ${COMPONENT_LIBRARIES}")
index 0cfd60263fc56f9d07829a0bbafec2675790a824..82e69717159257690c115e8a2486dbb79993ec08 100755 (executable)
@@ -180,6 +180,11 @@ def convert_component(project_path, component_path):
 
     with open(cmakelists_path, "w") as f:
         f.write("set(COMPONENT_ADD_INCLUDEDIRS %s)\n\n" % component_add_includedirs)
+
+        f.write("# Edit following two lines to set component requirements (see docs)\n")
+        f.write("set(COMPONENT_REQUIRES "")\n")
+        f.write("set(COMPONENT_PRIV_REQUIRES "")\n\n")
+
         if component_srcdirs is not None:
             f.write("set(COMPONENT_SRCDIRS %s)\n\n" % component_srcdirs)
             f.write("register_component()\n")
index e88e980af82b718cca98d94611df85c61aa02958..3415f9da295c013611e83e36831d40825a1b67be 100644 (file)
@@ -13,6 +13,10 @@ macro(idf_set_global_variables)
 
     set_default(EXTRA_COMPONENT_DIRS "")
 
+    # Commmon components, required by every component in the build
+    #
+    set_default(COMPONENT_REQUIRES_COMMON "cxx esp32 newlib freertos heap log soc")
+
     # PROJECT_PATH has the path to the IDF project (top-level cmake directory)
     #
     # (cmake calls this CMAKE_SOURCE_DIR, keeping old name for compatibility.)
index cc21563054e7ab3ffb4dfe759296646683694e0e..e313c886a66c8dfd424af9064da185c7fa037a69 100644 (file)
@@ -35,7 +35,7 @@ function(kconfig_process_config)
 
     # Find Kconfig and Kconfig.projbuild for each component as applicable
     # if any of these change, cmake should rerun
-    foreach(dir ${COMPONENT_PATHS} "${CMAKE_SOURCE_DIR}/main")
+    foreach(dir ${BUILD_COMPONENT_PATHS} "${CMAKE_SOURCE_DIR}/main")
         file(GLOB kconfig "${dir}/Kconfig")
         if(kconfig)
             set(kconfigs "${kconfigs} ${kconfig}")
index 26be56edab4608bd72968c6f37aee7b39f5f8b57..ff344a967f44bc05251c9d50ccf78816fc884142 100644 (file)
@@ -46,16 +46,32 @@ macro(project name)
     # Set global variables used by rest of the build
     idf_set_global_variables()
 
-    # Search COMPONENT_DIRS for COMPONENTS, make a list of full paths to each
-    # component in COMPONENT_PATHS
-    components_find_all("${COMPONENT_DIRS}" "${COMPONENTS}"
-        COMPONENT_PATHS COMPONENTS)
+    # Establish dependencies for components in the build
+    # (this happens before we even generate config...)
+    if(COMPONENTS)
+        # Make sure if an explicit list of COMPONENTS is given, it contains the "common" component requirements
+        # (otherwise, if COMPONENTS is empty then all components will be included in the build.)
+        set(COMPONENTS "${COMPONENTS} ${COMPONENT_REQUIRES_COMMON}")
+    endif()
+    execute_process(COMMAND "${CMAKE_COMMAND}"
+        -D "COMPONENTS=${COMPONENTS}"
+        -D "DEPENDENCIES_FILE=${CMAKE_BINARY_DIR}/component_depends.cmake"
+        -D "COMPONENT_DIRS=${COMPONENT_DIRS}"
+        -D "BOOTLOADER_BUILD=${BOOTLOADER_BUILD}"
+        -P "${IDF_PATH}/tools/cmake/scripts/expand_requirements.cmake"
+        WORKING_DIRECTORY "${IDF_PATH}/tools/cmake")
+    include("${CMAKE_BINARY_DIR}/component_depends.cmake")
+
+    # We now have the following component-related variables:
+    # COMPONENTS is the list of initial components set by the user (or empty to include all components in the build).
+    # BUILD_COMPONENTS is the list of components to include in the build.
+    # BUILD_COMPONENT_PATHS is the paths to all of these components.
 
     # Print list of components
-    string(REPLACE ";" " " COMPONENTS_SPACES "${COMPONENTS}")
-    message(STATUS "Component names: ${COMPONENTS_SPACES}")
-    unset(COMPONENTS_SPACES)
-    message(STATUS "Component paths: ${COMPONENT_PATHS}")
+    string(REPLACE ";" " " BUILD_COMPONENTS_SPACES "${BUILD_COMPONENTS}")
+    message(STATUS "Component names: ${BUILD_COMPONENTS_SPACES}")
+    unset(BUILD_COMPONENTS_SPACES)
+    message(STATUS "Component paths: ${BUILD_COMPONENT_PATHS}")
 
     kconfig_set_variables()
 
@@ -88,14 +104,14 @@ macro(project name)
     git_describe(PROJECT_VER "${CMAKE_CURRENT_SOURCE_DIR}")
 
     # Include any top-level project_include.cmake files from components
-    foreach(component ${COMPONENT_PATHS})
+    foreach(component ${BUILD_COMPONENT_PATHS})
         include_if_exists("${component}/project_include.cmake")
     endforeach()
 
     #
     # Add each component to the build as a library
     #
-    foreach(COMPONENT_PATH ${COMPONENT_PATHS})
+    foreach(COMPONENT_PATH ${BUILD_COMPONENT_PATHS})
         get_filename_component(COMPONENT_NAME ${COMPONENT_PATH} NAME)
         add_subdirectory(${COMPONENT_PATH} ${COMPONENT_NAME})
     endforeach()
diff --git a/tools/cmake/scripts/expand_requirements.cmake b/tools/cmake/scripts/expand_requirements.cmake
new file mode 100644 (file)
index 0000000..9b56cf0
--- /dev/null
@@ -0,0 +1,216 @@
+# expand_requires.cmake is a utility cmake script to expand component requirements early in the build,
+# before the components are ready to be included.
+#
+# Parameters:
+# - COMPONENTS = Space-separated list of initial components to include in the build.
+#   Can be empty, in which case all components are in the build.
+# - DEPENDENCIES_FILE = Path of generated cmake file which will contain the expanded dependencies for these
+#   components.
+# - COMPONENT_DIRS = List of paths to search for all components.
+# - DEBUG = Set -DDEBUG=1 to debug component lists in the build.
+#
+# If successful, DEPENDENCIES_FILE can be expanded to set BUILD_COMPONENTS & BUILD_COMPONENT_PATHS with all
+# components required for the build, and the get_component_requirements() function to return each component's
+# recursively expanded requirements.
+#
+# TODO: Error out if a component requirement is missing
+cmake_minimum_required(VERSION 3.5)
+include("utilities.cmake")
+
+if(NOT DEPENDENCIES_FILE)
+    message(FATAL_ERROR "DEPENDENCIES_FILE must be set.")
+endif()
+
+if(NOT COMPONENT_DIRS)
+    message(FATAL_ERROR "COMPONENT_DIRS variable must be set")
+endif()
+spaces2list(COMPONENT_DIRS)
+
+function(debug message)
+    if(DEBUG)
+        message(STATUS "${message}")
+    endif()
+endfunction()
+
+# Dummy register_component used to save requirements variables as global properties, for later expansion
+#
+# (expand_component_requirements() includes the component CMakeLists.txt, which then sets its component variables,
+# calls this dummy macro, and immediately exits again.)
+macro(register_component)
+    spaces2list(COMPONENT_REQUIRES)
+    set_property(GLOBAL PROPERTY "${COMPONENT}_REQUIRES" "${COMPONENT_REQUIRES}")
+    spaces2list(COMPONENT_PRIV_REQUIRES)
+    set_property(GLOBAL PROPERTY "${COMPONENT}_PRIV_REQUIRES" "${COMPONENT_PRIV_REQUIRES}")
+
+    # This is tricky: we override register_component() so it returns out of the component CMakeLists.txt
+    # (as we're declaring it as a macro not a function, so it doesn't have its own scope.)
+    #
+    # This means no targets are defined, and the component expansion ends early.
+    return()
+endmacro()
+
+macro(register_config_only_component)
+    register_component()
+endmacro()
+
+# Given a component name (find_name) and a list of component paths (component_paths),
+# return the path to the component in 'variable'
+#
+# Fatal error is printed if the component is not found.
+function(find_component_path find_name component_paths variable)
+    foreach(path ${component_paths})
+        get_filename_component(name "${path}" NAME)
+        if("${name}" STREQUAL "${find_name}")
+            set("${variable}" "${path}" PARENT_SCOPE)
+            return()
+        endif()
+    endforeach()
+    # TODO: find a way to print the dependency chain that lead to this not-found component
+    message(WARNING "Required component ${find_name} is not found in any of the provided COMPONENT_DIRS")
+endfunction()
+
+# components_find_all: Search 'component_dirs' for components and return them
+# as a list of names in 'component_names' and a list of full paths in
+# 'component_paths'
+#
+# component_paths contains only unique component names. Directories
+# earlier in the component_dirs list take precedence.
+function(components_find_all component_dirs component_paths component_names)
+    # component_dirs entries can be files or lists of files
+    set(paths "")
+    set(names "")
+
+    # start by expanding the component_dirs list with all subdirectories
+    foreach(dir ${component_dirs})
+        # Iterate any subdirectories for values
+        file(GLOB subdirs LIST_DIRECTORIES true "${dir}/*")
+        foreach(subdir ${subdirs})
+            set(component_dirs "${component_dirs};${subdir}")
+        endforeach()
+    endforeach()
+
+    # Look for a component in each component_dirs entry
+    foreach(dir ${component_dirs})
+        file(GLOB component "${dir}/CMakeLists.txt")
+        if(component)
+            get_filename_component(component "${component}" DIRECTORY)
+            get_filename_component(name "${component}" NAME)
+            if(NOT name IN_LIST names)
+                set(names "${names};${name}")
+                set(paths "${paths};${component}")
+            endif()
+
+        else()  # no CMakeLists.txt file
+            # test for legacy component.mk and warn
+            file(GLOB legacy_component "${dir}/component.mk")
+            if(legacy_component)
+                get_filename_component(legacy_component "${legacy_component}" DIRECTORY)
+                message(WARNING "Component ${legacy_component} contains old-style component.mk but no CMakeLists.txt. "
+                    "Component will be skipped.")
+            endif()
+        endif()
+
+    endforeach()
+
+    set(${component_paths} ${paths} PARENT_SCOPE)
+    set(${component_names} ${names} PARENT_SCOPE)
+endfunction()
+
+# expand_component_requirements: Recursively expand a component's requirements,
+# setting global properties BUILD_COMPONENTS & BUILD_COMPONENT_PATHS and
+# also invoking the components to call register_component() above,
+# which will add per-component global properties with dependencies, etc.
+function(expand_component_requirements component)
+    get_property(build_components GLOBAL PROPERTY BUILD_COMPONENTS)
+    if(${component} IN_LIST build_components)
+        return()  # already added this component
+    endif()
+
+    find_component_path("${component}" "${ALL_COMPONENT_PATHS}" component_path)
+    debug("Expanding dependencies of ${component} @ ${component_path}")
+    if(NOT component_path)
+        set_property(GLOBAL APPEND PROPERTY COMPONENTS_NOT_FOUND ${component})
+        return()
+    endif()
+
+    # include the component CMakeLists.txt to expand its properties
+    # into the global cache (via register_component(), above)
+    unset(COMPONENT_REQUIRES)
+    unset(COMPONENT_PRIV_REQUIRES)
+    set(COMPONENT ${component})
+    include(${component_path}/CMakeLists.txt)
+
+    set_property(GLOBAL APPEND PROPERTY BUILD_COMPONENT_PATHS ${component_path})
+    set_property(GLOBAL APPEND PROPERTY BUILD_COMPONENTS ${component})
+
+    get_property(requires GLOBAL PROPERTY "${component}_REQUIRES")
+    get_property(requires_priv GLOBAL PROPERTY "${component}_PRIV_REQUIRES")
+    foreach(req ${requires} ${requires_priv})
+        expand_component_requirements(${req})
+    endforeach()
+endfunction()
+
+
+# Main functionality goes here
+
+# Find every available component in COMPONENT_DIRS, save as ALL_COMPONENT_PATHS and ALL_COMPONENTS
+components_find_all("${COMPONENT_DIRS}" ALL_COMPONENT_PATHS ALL_COMPONENTS)
+
+if(NOT COMPONENTS)
+    set(COMPONENTS "${ALL_COMPONENTS}")
+endif()
+spaces2list(COMPONENTS)
+
+debug("ALL_COMPONENT_PATHS ${ALL_COMPONENT_PATHS}")
+debug("ALL_COMPONENTS ${ALL_COMPONENTS}")
+
+set_property(GLOBAL PROPERTY BUILD_COMPONENTS "")
+set_property(GLOBAL PROPERTY BUILD_COMPONENT_PATHS "")
+set_property(GLOBAL PROPERTY COMPONENTS_NOT_FOUND "")
+
+foreach(component ${COMPONENTS})
+    debug("Expanding initial component ${component}")
+    expand_component_requirements(${component})
+endforeach()
+
+get_property(build_components GLOBAL PROPERTY BUILD_COMPONENTS)
+get_property(build_component_paths GLOBAL PROPERTY BUILD_COMPONENT_PATHS)
+get_property(not_found GLOBAL PROPERTY COMPONENTS_NOT_FOUND)
+
+debug("components in build: ${build_components}")
+debug("components in build: ${build_component_paths}")
+debug("components not found: ${not_found}")
+
+function(line contents)
+    file(APPEND "${DEPENDENCIES_FILE}" "${contents}\n")
+endfunction()
+
+file(WRITE "${DEPENDENCIES_FILE}" "# Component requirements generated by expand_requirements.cmake\n\n")
+line("set(BUILD_COMPONENTS ${build_components})")
+line("set(BUILD_COMPONENT_PATHS ${build_component_paths})")
+line("")
+
+line("# get_component_requirements: Generated function to read the dependencies of a given component.")
+line("#")
+line("# Parameters:")
+line("# - component: Name of component")
+line("# - var_requires: output variable name. Set to recursively expanded COMPONENT_REQUIRES ")
+line("#   for this component.")
+line("# - var_private_requires: output variable name. Set to recursively expanded COMPONENT_PRIV_REQUIRES ")
+line("#   for this component.")
+line("#")
+line("# Throws a fatal error if 'componeont' is not found (indicates a build system problem).")
+line("#")
+line("function(get_component_requirements component var_requires var_private_requires)")
+foreach(build_component ${build_components})
+    get_property(reqs GLOBAL PROPERTY "${build_component}_REQUIRES")
+    get_property(private_reqs GLOBAL PROPERTY "${build_component}_PRIV_REQUIRES")
+    line("  if(\"\$\{component}\" STREQUAL \"${build_component}\")")
+    line("    set(\${var_requires} \"${reqs}\" PARENT_SCOPE)")
+    line("    set(\${var_private_requires} \"${private_reqs}\" PARENT_SCOPE)")
+    line("    return()")
+    line("  endif()")
+endforeach()
+
+line("  message(FATAL_ERROR \"Component not found: \${component}\")")
+line("endfunction()")