From 22548d0ea49ad8beb0ffde94d4f22cd8a309dcac Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Thu, 22 Aug 2019 09:38:33 +0800 Subject: [PATCH 01/12] cmake: hide internal targets Use imported library, which does not create additional rules, but still allows attaching arbitraty properties instead of custom targets. This allows the targets to not appear in the target list of IDEs such as CLion. --- tools/cmake/build.cmake | 2 +- tools/cmake/component.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 73533980bc..53684a59d4 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -128,7 +128,7 @@ endfunction() # function(__build_init idf_path) # Create the build target, to which the ESP-IDF build properties, dependencies are attached to - add_custom_target(__idf_build_target) + add_library(__idf_build_target STATIC IMPORTED) set_default(python "python") diff --git a/tools/cmake/component.cmake b/tools/cmake/component.cmake index 8358bf2dfe..8eb2f3f974 100644 --- a/tools/cmake/component.cmake +++ b/tools/cmake/component.cmake @@ -173,7 +173,7 @@ function(__component_add component_dir prefix) # 'override' components added earlier. if(NOT component_target IN_LIST component_targets) if(NOT TARGET ${component_target}) - add_custom_target(${component_target} EXCLUDE_FROM_ALL) + add_library(${component_target} STATIC IMPORTED) endif() idf_build_set_property(__COMPONENT_TARGETS ${component_target} APPEND) endif() From b69898257ac8447cc674fa056a89da537b7e7f09 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 27 Aug 2019 15:24:31 +0800 Subject: [PATCH 02/12] cmake: make build components available before immediately Previous implementation only builds list of components included in the build during component registration. Since the build components is known as the requirements expansion is ongoing, update the list here instead. --- tools/cmake/build.cmake | 4 ++++ tools/cmake/component.cmake | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 53684a59d4..01b1883340 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -219,6 +219,10 @@ function(__build_expand_requirements component_target) idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS) if(NOT component_target IN_LIST build_component_targets) idf_build_set_property(__BUILD_COMPONENT_TARGETS ${component_target} APPEND) + __component_get_property(component_lib ${component_target} COMPONENT_LIB) + idf_build_set_property(__BUILD_COMPONENTS ${component_lib} APPEND) + __component_get_property(component_alias ${component_target} COMPONENT_ALIAS) + idf_build_set_property(BUILD_COMPONENTS ${component_alias} APPEND) endif() endfunction() diff --git a/tools/cmake/component.cmake b/tools/cmake/component.cmake index 8eb2f3f974..d10ac365b5 100644 --- a/tools/cmake/component.cmake +++ b/tools/cmake/component.cmake @@ -482,10 +482,6 @@ function(idf_component_register) # Set dependencies __component_set_all_dependencies() - # Add the component to built components - idf_build_set_property(__BUILD_COMPONENTS ${component_lib} APPEND) - idf_build_set_property(BUILD_COMPONENTS ${component_alias} APPEND) - # Make the COMPONENT_LIB variable available in the component CMakeLists.txt set(COMPONENT_LIB ${component_lib} PARENT_SCOPE) # COMPONENT_TARGET is deprecated but is made available with same function From ecce2bc926c2e1433c22b8c6f52c240f28471276 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 27 Aug 2019 20:40:29 +0800 Subject: [PATCH 03/12] cmake: introduce BUILD_COMPONENT_ALIASES This commit makes it so that BUILD_COMPONENT holds only the component, and a new property BUILD_COMPONENT_ALIASES hold the full name of the component. This also removes erroneous check for duplicate components, as this can never happen: (1) if two components have the same name but different prefixes, the internal names are still unique between them (2)if two components happen to have the same name and same prefix, the latter would override the former --- docs/en/api-guides/build-system.rst | 3 ++- tools/cmake/build.cmake | 16 +++++++++++++++- tools/cmake/component.cmake | 10 +++------- tools/cmake/project.cmake | 7 +++++-- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index 106d4f3aed..2e72baaaef 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -1142,7 +1142,8 @@ For example, to get the Python interpreter used for the build: message(STATUS "The Python intepreter is: ${python}") - BUILD_DIR - build directory; set from ``idf_build_process`` BUILD_DIR argument - - BUILD_COMPONENTS - list of components (more specifically, component aliases) included in the build; set by ``idf_build_process`` + - BUILD_COMPONENTS - list of components included in the build; set by ``idf_build_process`` + - BUILD_COMPONENTS_ALIASES - list of library alias of components included in the build; set by ``idf_build_process`` - C_COMPILE_OPTIONS - compile options applied to all components' C source files - COMPILE_OPTIONS - compile options applied to all components' source files, regardless of it being C or C++ - COMPILE_DEFINITIONS - compile definitions applied to all component source files diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 01b1883340..e0386e7023 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -219,10 +219,24 @@ function(__build_expand_requirements component_target) idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS) if(NOT component_target IN_LIST build_component_targets) idf_build_set_property(__BUILD_COMPONENT_TARGETS ${component_target} APPEND) + __component_get_property(component_lib ${component_target} COMPONENT_LIB) idf_build_set_property(__BUILD_COMPONENTS ${component_lib} APPEND) + + idf_build_get_property(prefix __PREFIX) + __component_get_property(component_prefix ${component_target} __PREFIX) + __component_get_property(component_alias ${component_target} COMPONENT_ALIAS) - idf_build_set_property(BUILD_COMPONENTS ${component_alias} APPEND) + + idf_build_set_property(BUILD_COMPONENT_ALIASES ${component_alias} APPEND) + + # Only put in the prefix in the name if it is not the default one + if(component_prefix STREQUAL prefix) + __component_get_property(component_name ${component_target} COMPONENT_NAME) + idf_build_set_property(BUILD_COMPONENTS ${component_name} APPEND) + else() + idf_build_set_property(BUILD_COMPONENTS ${component_alias} APPEND) + endif() endif() endfunction() diff --git a/tools/cmake/component.cmake b/tools/cmake/component.cmake index d10ac365b5..5591ad44f4 100644 --- a/tools/cmake/component.cmake +++ b/tools/cmake/component.cmake @@ -56,13 +56,8 @@ function(__component_get_target var name_or_alias) foreach(component_target ${component_targets}) __component_get_property(_component_name ${component_target} COMPONENT_NAME) if(name_or_alias STREQUAL _component_name) - # There should only be one component of the same name - if(NOT target) - set(target ${component_target}) - else() - message(FATAL_ERROR "Multiple components with name '${name_or_alias}' found.") - return() - endif() + set(target ${component_target}) + break() endif() endforeach() set(${var} ${target} PARENT_SCOPE) @@ -191,6 +186,7 @@ function(__component_add component_dir prefix) __component_set_property(${component_target} COMPONENT_NAME ${component_name}) __component_set_property(${component_target} COMPONENT_DIR ${component_dir}) __component_set_property(${component_target} COMPONENT_ALIAS ${component_alias}) + __component_set_property(${component_target} __PREFIX ${prefix}) # Set Kconfig related properties on the component diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index 3deb014889..531c263540 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -353,13 +353,16 @@ macro(project project_name) # so that it treats components equally. # # This behavior should only be when user did not set REQUIRES/PRIV_REQUIRES manually. - idf_build_get_property(build_components BUILD_COMPONENTS) + idf_build_get_property(build_components BUILD_COMPONENT_ALIASES) if(idf::main IN_LIST build_components) __component_get_target(main_target idf::main) __component_get_property(reqs ${main_target} REQUIRES) __component_get_property(priv_reqs ${main_target} PRIV_REQUIRES) idf_build_get_property(common_reqs __COMPONENT_REQUIRES_COMMON) if(reqs STREQUAL common_reqs AND NOT priv_reqs) #if user has not set any requirements + if(test_components) + list(REMOVE_ITEM build_components ${test_components}) + endif() list(REMOVE_ITEM build_components idf::main) __component_get_property(lib ${main_target} COMPONENT_LIB) set_property(TARGET ${lib} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${build_components}") @@ -392,7 +395,7 @@ macro(project project_name) target_link_libraries(${project_elf} "-Wl,--no-whole-archive") endif() - idf_build_get_property(build_components BUILD_COMPONENTS) + idf_build_get_property(build_components BUILD_COMPONENT_ALIASES) if(test_components) list(REMOVE_ITEM build_components ${test_components}) endif() From c9ca3a05fc68e4b86808825f2a78df3bdec762f1 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Wed, 28 Aug 2019 14:52:09 +0800 Subject: [PATCH 04/12] docs: fix typo of build component aliases name --- docs/en/api-guides/build-system.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index 2e72baaaef..59a48c406c 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -1143,7 +1143,7 @@ For example, to get the Python interpreter used for the build: - BUILD_DIR - build directory; set from ``idf_build_process`` BUILD_DIR argument - BUILD_COMPONENTS - list of components included in the build; set by ``idf_build_process`` - - BUILD_COMPONENTS_ALIASES - list of library alias of components included in the build; set by ``idf_build_process`` + - BUILD_COMPONENT_ALIASES - list of library alias of components included in the build; set by ``idf_build_process`` - C_COMPILE_OPTIONS - compile options applied to all components' C source files - COMPILE_OPTIONS - compile options applied to all components' source files, regardless of it being C or C++ - COMPILE_DEFINITIONS - compile definitions applied to all component source files From 8300945189b18adfc3e7a71bd096ad2355e0d83c Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 17 Sep 2019 18:07:47 +0800 Subject: [PATCH 05/12] cxx: force pthread to appear later in link line --- components/cxx/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/components/cxx/CMakeLists.txt b/components/cxx/CMakeLists.txt index 57e0aec7c0..852c4c884d 100644 --- a/components/cxx/CMakeLists.txt +++ b/components/cxx/CMakeLists.txt @@ -1,9 +1,17 @@ idf_component_register(SRCS "cxx_exception_stubs.cpp" - "cxx_guards.cpp") + "cxx_guards.cpp" + # Make sure that pthread is in component list + PRIV_REQUIRES pthread) target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ gcc) target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxa_guard_dummy") +# Force pthread to also appear later than stdc++ in link line +add_library(stdcpp_pthread INTERFACE) +idf_component_get_property(pthread pthread COMPONENT_LIB) +target_link_libraries(stdcpp_pthread INTERFACE stdc++ $) +target_link_libraries(${COMPONENT_LIB} PUBLIC stdcpp_pthread) + if(NOT CONFIG_COMPILER_CXX_EXCEPTIONS) target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxx_fatal_exception") endif() From bc3134594ddcd32eb1e63b51f6cf79b6c0b659e6 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 20 Aug 2019 16:09:24 +0800 Subject: [PATCH 06/12] esptool_py: add missing phony build targets for CMake Adds targets erase_flash and monitor for users not using idf.py. Closes https://github.com/espressif/esp-idf/issues/2420. --- components/esptool_py/get_port_args.cmake | 18 +++++++++ components/esptool_py/project_include.cmake | 23 ++++++++++- components/esptool_py/run_cmd.cmake | 15 +++++++ components/esptool_py/run_esptool.cmake | 43 +++++---------------- components/esptool_py/run_idf_monitor.cmake | 21 ++++++++++ 5 files changed, 85 insertions(+), 35 deletions(-) create mode 100644 components/esptool_py/get_port_args.cmake create mode 100644 components/esptool_py/run_cmd.cmake create mode 100644 components/esptool_py/run_idf_monitor.cmake diff --git a/components/esptool_py/get_port_args.cmake b/components/esptool_py/get_port_args.cmake new file mode 100644 index 0000000000..52c388d0d7 --- /dev/null +++ b/components/esptool_py/get_port_args.cmake @@ -0,0 +1,18 @@ +# Note: we can't expand these environment variables in the main IDF CMake build, +# because we want to expand them at flashing time not at CMake runtime (so they can change +# without needing a CMake re-run) +set(ESPPORT $ENV{ESPPORT}) +if(NOT ESPPORT) + message("Note: ${TOOL} will search for a serial port. To specify a port, set the ESPPORT environment variable.") +else() + set(port_arg "-p ${ESPPORT}") +endif() + +set(ESPBAUD $ENV{ESPBAUD}) +if(NOT ESPBAUD) + message("Note: ${TOOL} will attempt to set baud rate automatically. " + "To specify a baud rate, set the ESPBAUD environment variable.") +else() + set(baud_arg "-b ${ESPBAUD}") +endif() + diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index af676a626b..27078aa240 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -138,13 +138,34 @@ function(esptool_py_custom_target target_name flasher_filename dependencies) -D IDF_PATH="${idf_path}" -D ESPTOOLPY="${ESPTOOLPY}" -D ESPTOOL_ARGS="write_flash;@flash_${flasher_filename}_args" - -D ESPTOOL_WORKING_DIR="${build_dir}" + -D WORKING_DIRECTORY="${build_dir}" -P run_esptool.cmake WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} USES_TERMINAL ) endfunction() +add_custom_target(erase_flash + COMMAND ${CMAKE_COMMAND} + -D IDF_PATH="${idf_path}" + -D ESPTOOLPY="${ESPTOOLPY}" + -D ESPTOOL_ARGS="erase_flash" + -P run_esptool.cmake + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + USES_TERMINAL + ) + +add_custom_target(monitor + COMMAND ${CMAKE_COMMAND} + -D IDF_PATH="${idf_path}" + -D IDF_MONITOR="${idf_path}/tools/idf_monitor.py" + -D ELF_FILE="${elf}" + -D WORKING_DIRECTORY="${build_dir}" + -P run_idf_monitor.cmake + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + USES_TERMINAL + ) + esptool_py_custom_target(flash project "app;partition_table;bootloader") esptool_py_custom_target(app-flash app "app") diff --git a/components/esptool_py/run_cmd.cmake b/components/esptool_py/run_cmd.cmake new file mode 100644 index 0000000000..8eefabbc21 --- /dev/null +++ b/components/esptool_py/run_cmd.cmake @@ -0,0 +1,15 @@ +if(NOT IDF_PATH) + message(FATAL_ERROR "IDF_PATH not set.") +endif() +include("${IDF_PATH}/tools/cmake/utilities.cmake") +spaces2list(CMD) + +execute_process(COMMAND ${CMD} + WORKING_DIRECTORY "${WORKING_DIRECTORY}" + RESULT_VARIABLE result + ) + +if(${result}) + # No way to have CMake silently fail, unfortunately + message(FATAL_ERROR "${TOOL} failed") +endif() diff --git a/components/esptool_py/run_esptool.cmake b/components/esptool_py/run_esptool.cmake index a63eb55f0b..348af7a565 100644 --- a/components/esptool_py/run_esptool.cmake +++ b/components/esptool_py/run_esptool.cmake @@ -8,39 +8,14 @@ # cmake_minimum_required(VERSION 3.5) -if(NOT IDF_PATH OR NOT ESPTOOLPY OR NOT ESPTOOL_ARGS OR NOT ESPTOOL_WORKING_DIR) - message(FATAL_ERROR "IDF_PATH, ESPTOOLPY, ESPTOOL_ARGS, and ESPTOOL_WORKING_DIR must " - "be specified on the CMake command line. For direct esptool execution, it is " - "strongly recommended to run esptool.py directly.") +set(TOOL "esptool.py") + +if(NOT ESPTOOLPY OR NOT ESPTOOL_ARGS) + message(FATAL_ERROR "ESPTOOLPY and ESPTOOL_ARGS must " + "be specified on the CMake command line. For direct execution, it is " + "strongly recommended to run ${TOOL} directly.") endif() -# Note: we can't expand these environment variables in the main IDF CMake build, -# because we want to expand them at flashing time not at CMake runtime (so they can change -# without needing a CMake re-run) -set(ESPPORT $ENV{ESPPORT}) -if(NOT ESPPORT) - message("Note: esptool.py will search for a serial port. To specify a port, set the ESPPORT environment variable.") -else() - set(port_arg "-p ${ESPPORT}") -endif() - -set(ESPBAUD $ENV{ESPBAUD}) -if(NOT ESPBAUD) - message("Note: Using default baud rate 460800. To modify, set ESPBAUD environment variable.") - set(ESPBAUD 460800) -endif() - -include("${IDF_PATH}/tools/cmake/utilities.cmake") - -set(cmd "${ESPTOOLPY} ${port_arg} -b ${ESPBAUD} ${ESPTOOL_ARGS}") -spaces2list(cmd) - -execute_process(COMMAND ${cmd} - WORKING_DIRECTORY "${ESPTOOL_WORKING_DIR}" - RESULT_VARIABLE result - ) - -if(${result}) - # No way to have CMake silently fail, unfortunately - message(FATAL_ERROR "esptool.py failed") -endif() +include("${CMAKE_CURRENT_LIST_DIR}/get_port_args.cmake") +set(CMD "${ESPTOOLPY} ${port_arg} ${baud_arg} ${ESPTOOL_ARGS}") +include("${CMAKE_CURRENT_LIST_DIR}/run_cmd.cmake") \ No newline at end of file diff --git a/components/esptool_py/run_idf_monitor.cmake b/components/esptool_py/run_idf_monitor.cmake new file mode 100644 index 0000000000..56b58de3da --- /dev/null +++ b/components/esptool_py/run_idf_monitor.cmake @@ -0,0 +1,21 @@ +# A CMake script to run idf_monitor from within ninja or make +# or another cmake-based build runner +# +# (Needed to expand environment variables, for backwards compatibility.) +# +# It is recommended to NOT USE this CMake script if you have the option of +# running idf_monitor.py directly. This script exists only for use inside CMake builds. +# +cmake_minimum_required(VERSION 3.5) + +set(TOOL "idf_monitor.py") + +if(NOT IDF_MONITOR OR NOT ELF_FILE) + message(FATAL_ERROR "IDF_MONITOR and ELF_FILE must " + "be specified on the CMake command line. For direct execution, it is " + "strongly recommended to run ${TOOL} directly.") +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/get_port_args.cmake") +set(CMD "${IDF_MONITOR} ${port_arg} ${baud_arg} ${ELF_FILE}") +include("${CMAKE_CURRENT_LIST_DIR}/run_cmd.cmake") From 95b5745c3c7b56e67c8edaf058d01f8453f49748 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 6 Aug 2019 11:14:44 +0800 Subject: [PATCH 07/12] cmake: treat unregistered components as unresolved --- tools/cmake/build.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index e0386e7023..c3bbdeafff 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -180,7 +180,8 @@ endfunction() # function(__build_resolve_and_add_req var component_target req type) __component_get_target(_component_target ${req}) - if(NOT _component_target) + __component_get_property(_component_registered ${component_target} __COMPONENT_REGISTERED) + if(NOT _component_target OR NOT _component_registered) message(FATAL_ERROR "Failed to resolve component '${req}'.") endif() __component_set_property(${component_target} ${type} ${_component_target} APPEND) From a6d40e358372bafaa58e924e1ad74cd4f99642ce Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Wed, 9 Oct 2019 11:00:56 +0800 Subject: [PATCH 08/12] docs: cmake docs fixes --- docs/en/api-guides/build-system.rst | 51 +++++++++++++++++------------ docs/en/api-guides/ulp.rst | 4 +-- docs/en/api-guides/unit-tests.rst | 2 +- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index 59a48c406c..ffd59b2777 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -702,12 +702,15 @@ depending on the options selected in the project configuration. ``CMakeLists.txt``:: - set(COMPONENT_SRCS "foo.c" "more_foo.c") + set(srcs "foo.c" "more_foo.c") if(CONFIG_FOO_ENABLE_BAR) - list(APPEND COMPONENT_SRCS "bar.c") + list(APPEND srcs "bar.c") endif() + idf_component_register(SRCS "${srcs}" + ...) + This example makes use of the CMake `if `_ function and `list APPEND `_ function. This can also be used to select or stub out an implementation, as such: @@ -736,16 +739,18 @@ This can also be used to select or stub out an implementation, as such: ``CMakeLists.txt``:: if(CONFIG_ENABLE_LCD_OUTPUT) - set(COMPONENT_SRCS lcd-real.c lcd-spi.c) + set(srcs lcd-real.c lcd-spi.c) else() - set(COMPONENT_SRCS lcd-dummy.c) + set(srcs lcd-dummy.c) endif() # We need font if either console or plot is enabled if(CONFIG_ENABLE_LCD_CONSOLE OR CONFIG_ENABLE_LCD_PLOT) - list(APPEND COMPONENT_SRCS "font.c") + list(APPEND srcs "font.c") endif() + idf_component_register(SRCS "${srcs}" + ...) Conditions which depend on the target ------------------------------------- @@ -800,13 +805,13 @@ Embedding Binary Data Sometimes you have a file with some binary or text data that you'd like to make available to your component - but you don't want to reformat the file as C source. -You can specify argument ``COMPONENT_EMBED_FILES`` in the component registration, giving space-delimited names of the files to embed:: +You can specify argument ``EMBED_FILES`` in the component registration, giving space-delimited names of the files to embed:: idf_component_register(... EMBED_FILES server_root_cert.der) -Or if the file is a string, you can use the variable ``COMPONENT_EMBED_TXTFILES``. This will embed the contents of the text file as a null-terminated string:: +Or if the file is a string, you can use the variable ``EMBED_TXTFILES``. This will embed the contents of the text file as a null-terminated string:: idf_component_register(... EMBED_TXTFILES server_root_cert.pem) @@ -818,7 +823,7 @@ The file's contents will be added to the .rodata section in flash, and are avail extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_root_cert_pem_start"); extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_root_cert_pem_end"); -The names are generated from the full name of the file, as given in ``COMPONENT_EMBED_FILES``. Characters /, ., etc. are replaced with underscores. The _binary prefix in the symbol name is added by objcopy and is the same for both text and binary files. +The names are generated from the full name of the file, as given in ``EMBED_FILES``. Characters /, ., etc. are replaced with underscores. The _binary prefix in the symbol name is added by objcopy and is the same for both text and binary files. .. highlight:: cmake @@ -994,7 +999,7 @@ not yet be provided by a component, or use another library for the same function Importing a library might look like this for a hypothetical library ``foo`` to be used in the ``main`` component:: # Register the component - idf_component_register() + idf_component_register(...) # Set values of hypothetical variables that control the build of `foo` set(FOO_BUILD_STATIC OFF) @@ -1003,8 +1008,8 @@ Importing a library might look like this for a hypothetical library ``foo`` to b # Create and import the library targets add_subdirectory(foo) - # Link `foo` to `main` component - target_link_libraries(main foo) + # Publicly link `foo` to `main` component + target_link_libraries(main PUBLIC foo) For an actual example, take a look at :example:`build_system/cmake/import_lib`. Take note that what needs to be done in order to import the library may vary. It is recommended to read up on the library's documentation for instructions on how to @@ -1290,7 +1295,7 @@ For project components (not part of ESP-IDF), there are a few different options: - If keeping your project file in Git, ESP-IDF will automatically track the Git revision and re-run CMake if the revision changes. - If some components are kept in a third git repository (not the project repository or ESP-IDF repository), you can add a call to the ``git_describe`` function in a component CMakeLists file in order to automatically trigger re-runs of CMake when the Git revision changes. - If not using Git, remember to manually run ``idf.py reconfigure`` whenever a source file may change. -- To avoid this problem entirely, use ``COMPONENT_SRCS`` to list all source files in project components. +- To avoid this problem entirely, use ``SRCS`` argument to ``idf_component_register`` to list all source files in project components. The best option will depend on your particular project and its users. @@ -1362,7 +1367,10 @@ Any combination of "load", "set", and "save" can be sent in a single command and Migrating from ESP-IDF GNU Make System ====================================== -Some aspects of the CMake-based ESP-IDF build system are very similar to the older GNU Make-based system. For example, to adapt a ``component.mk`` file to ``CMakeLists.txt`` variables like ``COMPONENT_ADD_INCLUDEDIRS`` and ``COMPONENT_SRCDIRS`` can stay the same and the syntax only needs changing to CMake syntax. +Some aspects of the CMake-based ESP-IDF build system are very similar to the older GNU Make-based system. The developer needs to provide values +the include directories, source files etc. There is a syntactical difference, however, as the developer needs to pass these as arguments +to the registration command, `idf_component_register`. + Automatic Conversion Tool ------------------------- @@ -1393,27 +1401,28 @@ Some features are significantly different or removed in the CMake-based system. - ``COMPONENT_ADD_LDFLAGS``: Used to override linker flags. Use the CMake `target_link_libraries`_ command instead. - ``COMPONENT_ADD_LINKER_DEPS``: List of files that linking should depend on. `target_link_libraries`_ will usually infer these dependencies automatically. For linker scripts, use the provided custom CMake function ``target_linker_scripts``. - ``COMPONENT_SUBMODULES``: No longer used, the build system will automatically enumerate all submodules in the ESP-IDF repository. -- ``COMPONENT_EXTRA_INCLUDES``: Used to be an alternative to ``COMPONENT_PRIV_INCLUDEDIRS`` for absolute paths. Use ``COMPONENT_PRIV_INCLUDEDIRS`` for all cases now (can be relative or absolute). -- ``COMPONENT_OBJS``: Previously, component sources could be specified as a list of object files. Now they can be specified as an list of source files via ``COMPONENT_SRCS``. -- ``COMPONENT_OBJEXCLUDE``: Has been replaced with ``COMPONENT_SRCEXCLUDE``. Specify source files (as absolute paths or relative to component directory), instead. +- ``COMPONENT_EXTRA_INCLUDES``: Used to be an alternative to ``COMPONENT_PRIV_INCLUDEDIRS`` for absolute paths. Use ``PRIV_INCLUDE_DIRS`` argument to ``idf_component_register`` for all cases now (can be relative or absolute). +- ``COMPONENT_OBJS``: Previously, component sources could be specified as a list of object files. Now they can be specified as a list of source files via ``SRCS`` argument to `idf_component_register`. +- ``COMPONENT_OBJEXCLUDE``: Has been replaced with ``EXCLUDE_SRCS`` argument to ``idf_component_register``. Specify source files (as absolute paths or relative to component directory), instead. - ``COMPONENT_EXTRA_CLEAN``: Set property ``ADDITIONAL_MAKE_CLEAN_FILES`` instead but note :ref:`CMake has some restrictions around this functionality `. - ``COMPONENT_OWNBUILDTARGET`` & ``COMPONENT_OWNCLEANTARGET``: Use CMake `ExternalProject`_ instead. See :ref:`component-build-full-override` for full details. -- ``COMPONENT_CONFIG_ONLY``: Call ``register_config_only_component()`` instead. See `Configuration-Only Components`_. +- ``COMPONENT_CONFIG_ONLY``: Call ``idf_component_register`` without any arguments instead. See `Configuration-Only Components`_. - ``CFLAGS``, ``CPPFLAGS``, ``CXXFLAGS``: Use equivalent CMake commands instead. See `Controlling Component Compilation`_. No Default Values ----------------- -The following variables no longer have default values: +Unlike in the legacy Make-based build system, the following have no default values: -- ``COMPONENT_SRCDIRS`` -- ``COMPONENT_ADD_INCLUDEDIRS`` +- Source directories (``COMPONENT_SRCDIRS`` variable in Make, ``SRC_DIRS`` argument to ``idf_component_register`` in CMake) +- Include directories (``COMPONENT_ADD_INCLUDEDIRS`` variable in Make, ``INCLUDE_DIRS`` argument to ``idf_component_register`` in CMake) No Longer Necessary ------------------- -It is no longer necessary to set ``COMPONENT_SRCDIRS`` if setting ``COMPONENT_SRCS`` (in fact, in the CMake-based system ``COMPONENT_SRCS`` is ignored if ``COMPONENT_SRCDIRS`` is set). +- In the legacy Make-based build system, it is required to also set ``COMPONENT_SRCDIRS`` if ``COMPONENT_SRCS`` is set. In CMake, the equivalent is not necessary i.e. specifying ``SRC_DIRS`` to ``idf_component_register`` if ``SRCS`` is also specified (in fact, ``SRCS`` is ignored if ``SRC_DIRS`` is specified). + Flashing from make ------------------ diff --git a/docs/en/api-guides/ulp.rst b/docs/en/api-guides/ulp.rst index 505af97b79..8cc9761f55 100644 --- a/docs/en/api-guides/ulp.rst +++ b/docs/en/api-guides/ulp.rst @@ -28,12 +28,12 @@ To compile ULP code as part of a component, the following steps must be taken: 1. ULP code, written in assembly, must be added to one or more files with `.S` extension. These files must be placed into a separate directory inside component directory, for instance `ulp/`. -.. note: This directory should not be added to the ``COMPONENT_SRCDIRS`` environment variable. The logic behind this is that the ESP-IDF build system will compile files found in ``COMPONENT_SRCDIRS`` based on their extensions. For ``.S`` files, ``xtensa-esp32-elf-as`` assembler is used. This is not desirable for ULP assembly files, so the easiest way to achieve the distinction is by placing ULP assembly files into a separate directory. The ULP assembly source files should also **not** be added to ``COMPONENT_SRCS`` for the same reason. See the step below for how to properly add ULP assembly source files. +.. note: When registering the component (via ``idf_component_register``), this directory should not be added to the ``SRC_DIRS`` argument. The logic behind this is that the ESP-IDF build system will compile files found in ``SRC_DIRS`` based on their extensions. For ``.S`` files, ``xtensa-esp32-elf-as`` assembler is used. This is not desirable for ULP assembly files, so the easiest way to achieve the distinction is by placing ULP assembly files into a separate directory. The ULP assembly source files should also **not** be added to ``SRCS`` for the same reason. See the step below for how to properly add ULP assembly source files. 2. Call ``ulp_embed_binary`` from the component CMakeLists.txt after registration. For example:: ... - register_component() + idf_component_register() set(ulp_app_name ulp_${COMPONENT_NAME}) set(ulp_s_sources ulp/ulp_assembly_source_file.S) diff --git a/docs/en/api-guides/unit-tests.rst b/docs/en/api-guides/unit-tests.rst index f2b564aa68..3e1fb25758 100644 --- a/docs/en/api-guides/unit-tests.rst +++ b/docs/en/api-guides/unit-tests.rst @@ -29,7 +29,7 @@ There is no need to add a main function with ``UNITY_BEGIN()`` and ``​UNITY_EN The ``test`` subdirectory should contain a :ref:`component CMakeLists.txt `, since they are themselves, components. ESP-IDF uses the test framework ``unity`` and should be specified as a requirement for the component. Normally, components :ref:`should list their sources manually `; for component tests however, this requirement is relaxed and the -use of ``COMPONENT_SRCDIRS`` is advised. +use of ``SRC_DIRS`` argument to ``idf_component_register`` is advised. Overall, the minimal ``test`` subdirectory CMakeLists.txt file may look like as follows: From 308e4fcce175938629b5035d6c3aa1523678f504 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 22 Oct 2019 13:09:25 +0800 Subject: [PATCH 09/12] cmake: do not check if sdkconfig exists --- tools/cmake/project.cmake | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index 531c263540..483b660605 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -317,10 +317,6 @@ macro(project project_name) if(SDKCONFIG) get_filename_component(sdkconfig "${SDKCONFIG}" ABSOLUTE) - if(NOT EXISTS "${sdkconfig}") - message(FATAL_ERROR "SDKCONFIG '${sdkconfig}' does not exist.") - endif() - set(sdkconfig ${SDKCONFIG}) else() set(sdkconfig "${CMAKE_CURRENT_LIST_DIR}/sdkconfig") endif() From e4137cc6cab189943a55e2cdc0576ad95623297c Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Mon, 4 Nov 2019 20:19:13 +0800 Subject: [PATCH 10/12] cmake: support git worktree Use rev-parse to get the HEAD directory instead of manually looking for it. This method works in the main repository, worktrees and submodules. Closes https://github.com/espressif/esp-idf/issues/4136 --- tools/ci/test_build_system_cmake.sh | 8 + .../GetGitRevisionDescription.cmake | 159 +++++++++--------- 2 files changed, 88 insertions(+), 79 deletions(-) diff --git a/tools/ci/test_build_system_cmake.sh b/tools/ci/test_build_system_cmake.sh index 4d391fe17c..42f6ebf7a1 100755 --- a/tools/ci/test_build_system_cmake.sh +++ b/tools/ci/test_build_system_cmake.sh @@ -554,6 +554,14 @@ endmenu\n" >> ${IDF_PATH}/Kconfig; mv CMakeLists.txt.bak CMakeLists.txt rm -rf CMakeLists.txt.bak + print_status "Supports git worktree" + clean_build_dir + git branch test_build_system + git worktree add ../esp-idf-template-test test_build_system + diff <(idf.py reconfigure | grep "Project version") <(cd ../esp-idf-template-test && idf.py reconfigure | grep "Project version") \ + || failure "Version on worktree should have been properly resolved" + git worktree remove ../esp-idf-template-test + print_status "All tests completed" if [ -n "${FAILURES}" ]; then echo "Some failures were detected:" diff --git a/tools/cmake/third_party/GetGitRevisionDescription.cmake b/tools/cmake/third_party/GetGitRevisionDescription.cmake index 1de63b3623..ab048d6439 100644 --- a/tools/cmake/third_party/GetGitRevisionDescription.cmake +++ b/tools/cmake/third_party/GetGitRevisionDescription.cmake @@ -34,7 +34,7 @@ # to get revision of other repositories if(__get_git_revision_description) - return() + return() endif() set(__get_git_revision_description YES) @@ -43,95 +43,96 @@ set(__get_git_revision_description YES) get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) function(get_git_head_revision _refspecvar _hashvar _repo_dir) - set(GIT_PARENT_DIR "${_repo_dir}") - set(GIT_DIR "${GIT_PARENT_DIR}/.git") - while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories - set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") - get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) - if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) - # We have reached the root directory, we are not in git - set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) - set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) - return() - endif() - set(GIT_DIR "${GIT_PARENT_DIR}/.git") - endwhile() - # check if this is a submodule - if(NOT IS_DIRECTORY ${GIT_DIR}) - file(READ ${GIT_DIR} submodule) - string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) - get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) - get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) - endif() - set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") - if(NOT EXISTS "${GIT_DATA}") - file(MAKE_DIRECTORY "${GIT_DATA}") - endif() + execute_process(COMMAND + "${GIT_EXECUTABLE}" + rev-parse + --git-dir + WORKING_DIRECTORY + ${_repo_dir} + RESULT_VARIABLE + res + OUTPUT_VARIABLE + GIT_DIR + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(NOT res EQUAL 0) + return() + endif() - if(NOT EXISTS "${GIT_DIR}/HEAD") - return() - endif() - set(HEAD_FILE "${GIT_DATA}/HEAD") - configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + get_filename_component(GIT_DIR "${GIT_DIR}" ABSOLUTE BASE_DIR "${_repo_dir}") - configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" - "${GIT_DATA}/grabRef.cmake" - @ONLY) - include("${GIT_DATA}/grabRef.cmake") + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() - set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) - set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" + @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) + set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) endfunction() function(git_describe _var _repo_dir) - if(NOT GIT_FOUND) - find_package(Git QUIET) - endif() - get_git_head_revision(refspec hash "${_repo_dir}") - if(NOT GIT_FOUND) - set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) - return() - endif() - if(NOT hash) - set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) - return() - endif() + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash "${_repo_dir}") + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + + endif() - # TODO sanitize - #if((${ARGN}" MATCHES "&&") OR - # (ARGN MATCHES "||") OR - # (ARGN MATCHES "\\;")) - # message("Please report the following error to the project!") - # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") - #endif() + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() - #message(STATUS "Arguments to execute_process: ${ARGN}") + #message(STATUS "Arguments to execute_process: ${ARGN}") - execute_process(COMMAND - "${GIT_EXECUTABLE}" - "-C" - ${_repo_dir} - describe - "--always" - "--tags" - "--dirty" - ${ARGN} - WORKING_DIRECTORY - "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE - res - OUTPUT_VARIABLE - out - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if(NOT res EQUAL 0) - set(out "${out}-${res}-NOTFOUND") - endif() + execute_process(COMMAND + "${GIT_EXECUTABLE}" + "-C" + ${_repo_dir} + describe + "--always" + "--tags" + "--dirty" + ${ARGN} + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() - set(${_var} "${out}" PARENT_SCOPE) + set(${_var} "${out}" PARENT_SCOPE) endfunction() function(git_get_exact_tag _var _repo_dir) - git_describe(out "${_repo_dir}" --exact-match ${ARGN}) - set(${_var} "${out}" PARENT_SCOPE) + git_describe(out "${_repo_dir}" --exact-match ${ARGN}) + set(${_var} "${out}" PARENT_SCOPE) endfunction() From 0c2202ef3e5da1147ed6c011da03de06b6ad69cf Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Fri, 8 Nov 2019 16:03:27 +0800 Subject: [PATCH 11/12] examples: fix idf as library example build on macOS GCC prefixes underscore on symbol names on macOS, and so the set undefined symbol `-u app_main` won't work. However, this is unecessary, as the source file that defines it is specified directly to the executable, and not through a static library. Closes https://github.com/espressif/esp-idf/issues/4168 --- .../build_system/cmake/idf_as_lib/stubs/esp32/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/build_system/cmake/idf_as_lib/stubs/esp32/CMakeLists.txt b/examples/build_system/cmake/idf_as_lib/stubs/esp32/CMakeLists.txt index e8d2da010d..15d3145a92 100644 --- a/examples/build_system/cmake/idf_as_lib/stubs/esp32/CMakeLists.txt +++ b/examples/build_system/cmake/idf_as_lib/stubs/esp32/CMakeLists.txt @@ -2,5 +2,4 @@ add_library(stub_esp32 STATIC system_api.c flash_ops.c cpu_start.c) target_include_directories(stub_esp32 PUBLIC .) add_library(stub::esp32 ALIAS stub_esp32) -target_link_libraries(stub_esp32 "-u app_main") target_link_libraries(stub_esp32 stub::spi_flash) \ No newline at end of file From d49077c13b1a8ea219bb71e120b38bb196b786bf Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 5 Nov 2019 14:52:14 +0800 Subject: [PATCH 12/12] spiffs: fix build issue on clean project From issue: I did some poking around in components/spiffs/project_include.cmake and it looks like what is failing is it isn't getting an offset from parttool.py. I think what the problem is that the parttool.py cannot determine the offset of the storage partition as I can't run menuconfig to set the custom partitions. I have tested that this problem is solvable by manually setting the custom partitions in sdkconfig and that is a workaround but there should be at least a better error message in the configuration when it cannot find the partition as this would also happen if the partition name was misspelled. Closes https://github.com/espressif/esp-idf/issues/4236 --- components/spiffs/project_include.cmake | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/components/spiffs/project_include.cmake b/components/spiffs/project_include.cmake index 31f63b5111..c8d1ad33b9 100644 --- a/components/spiffs/project_include.cmake +++ b/components/spiffs/project_include.cmake @@ -15,6 +15,16 @@ function(spiffs_create_partition_image partition base_dir) partition_table_get_partition_info(size "--partition-name ${partition}" "size") partition_table_get_partition_info(offset "--partition-name ${partition}" "offset") + if(NOT "${size}") + message(WARNING "spiffsgen: Unable to resolve size of partition '${partition}'. " + "Check config if using correct partition table.") + endif() + + if(NOT "${offset}") + message(WARNING "spiffsgen: Unable to resolve offset of partition '${partition}'. " + "Check config if using correct partition table.") + endif() + set(image_file ${CMAKE_BINARY_DIR}/${partition}.bin) if(CONFIG_SPIFFS_USE_MAGIC) @@ -42,8 +52,8 @@ function(spiffs_create_partition_image partition base_dir) ${image_file}) if(arg_FLASH_IN_PROJECT) - esptool_py_flash_project_args(${partition} ${offset} ${image_file} FLASH_IN_PROJECT) + esptool_py_flash_project_args("${partition}" "${offset}" "${image_file}" FLASH_IN_PROJECT) else() - esptool_py_flash_project_args(${partition} ${offset} ${image_file}) + esptool_py_flash_project_args("${partition}" "${offset}" "${image_file}") endif() endfunction() \ No newline at end of file