diff --git a/.gitignore b/.gitignore index 478852216..51decdb5f 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,6 @@ test_multi_heap_host # Results for the checking of the Python coding style flake8_output.txt + +# ESP-IDF library +build diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 000000000..226a67d5e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,153 @@ +cmake_minimum_required(VERSION 3.5) +project(esp-idf C CXX ASM) + +if(NOT IDF_PATH) + set(IDF_PATH ${CMAKE_CURRENT_LIST_DIR}) +endif() + +include(tools/cmake/idf_functions.cmake) + +# +# Set variables that control the build configuration and the build itself +# +idf_set_variables() + +kconfig_set_variables() + +# +# Generate a component dependencies file, enumerating components to be included in the build +# as well as their dependencies. +# +execute_process(COMMAND "${CMAKE_COMMAND}" + -D "COMPONENTS=${IDF_COMPONENTS}" + -D "COMPONENT_REQUIRES_COMMON=${IDF_COMPONENT_REQUIRES_COMMON}" + -D "EXCLUDE_COMPONENTS=${IDF_EXCLUDE_COMPONENTS}" + -D "TEST_COMPONENTS=${IDF_TEST_COMPONENTS}" + -D "TEST_EXCLUDE_COMPONENTS=${IDF_TEST_EXCLUDE_COMPONENTS}" + -D "BUILD_TESTS=${IDF_BUILD_TESTS}" + -D "DEPENDENCIES_FILE=${CMAKE_BINARY_DIR}/component_depends.cmake" + -D "COMPONENT_DIRS=${IDF_COMPONENT_DIRS}" + -D "BOOTLOADER_BUILD=${BOOTLOADER_BUILD}" + -D "IDF_TARGET=${IDF_TARGET}" + -D "IDF_PATH=${IDF_PATH}" + -D "DEBUG=${DEBUG}" + -P "${IDF_PATH}/tools/cmake/scripts/expand_requirements.cmake" + WORKING_DIRECTORY "${PROJECT_PATH}") +include("${CMAKE_BINARY_DIR}/component_depends.cmake") + +# +# We now have the following component-related variables: +# +# IDF_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, obtained from the component dependencies file. +# +# Print the list of found components and test components +# +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}") + +# Print list of test components +if(TESTS_ALL EQUAL 1 OR TEST_COMPONENTS) + string(REPLACE ";" " " BUILD_TEST_COMPONENTS_SPACES "${BUILD_TEST_COMPONENTS}") + message(STATUS "Test component names: ${BUILD_TEST_COMPONENTS_SPACES}") + unset(BUILD_TEST_COMPONENTS_SPACES) + message(STATUS "Test component paths: ${BUILD_TEST_COMPONENT_PATHS}") +endif() + +# Generate project configuration +kconfig_process_config() + +# Include sdkconfig.cmake so rest of the build knows the configuration +include(${SDKCONFIG_CMAKE}) + +# Verify the environment is configured correctly +idf_verify_environment() + +# Check git revision (may trigger reruns of cmake) +## sets IDF_VER to IDF git revision +idf_get_git_revision() + +# Check that the targets set in cache, sdkconfig, and in environment all match +idf_check_config_target() + +## if project uses git, retrieve revision +git_describe(PROJECT_VER "${CMAKE_CURRENT_SOURCE_DIR}") + +# Add some idf-wide definitions +idf_set_global_compile_options() + +# generate compile_commands.json (needs to come after project) +set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + +# +# Setup variables for linker script generation +# +ldgen_set_variables() + +# Include any top-level project_include.cmake files from components +foreach(component ${BUILD_COMPONENT_PATHS}) + set(COMPONENT_PATH "${component}") + include_if_exists("${component}/project_include.cmake") + unset(COMPONENT_PATH) +endforeach() + +# +# Add each component to the build as a library +# +foreach(COMPONENT_PATH ${BUILD_COMPONENT_PATHS}) + get_filename_component(COMPONENT_NAME ${COMPONENT_PATH} NAME) + + list(FIND BUILD_TEST_COMPONENT_PATHS ${COMPONENT_PATH} idx) + + if(NOT idx EQUAL -1) + list(GET BUILD_TEST_COMPONENTS ${idx} test_component) + set(COMPONENT_NAME ${test_component}) + endif() + + component_get_target(COMPONENT_TARGET ${COMPONENT_NAME}) + + add_subdirectory(${COMPONENT_PATH} ${COMPONENT_NAME}) +endforeach() +unset(COMPONENT_NAME) +unset(COMPONENT_PATH) + +# each component should see the include directories of its requirements +# +# (we can't do this until all components are registered and targets exist in cmake, as we have +# a circular requirements graph...) +foreach(component ${BUILD_COMPONENTS}) + component_get_target(component_target ${component}) + if(TARGET ${component_target}) + get_component_requirements(${component} deps priv_deps) + + list(APPEND priv_deps ${IDF_COMPONENT_REQUIRES_COMMON}) + + foreach(dep ${deps}) + component_get_target(dep_target ${dep}) + add_component_dependencies(${component_target} ${dep_target} PUBLIC) + endforeach() + + foreach(dep ${priv_deps}) + component_get_target(dep_target ${dep}) + add_component_dependencies(${component_target} ${dep_target} PRIVATE) + endforeach() + endif() +endforeach() + +if(IDF_BUILD_ARTIFACTS) + # Write project description JSON file + make_json_list("${BUILD_COMPONENTS}" build_components_json) + make_json_list("${BUILD_COMPONENT_PATHS}" build_component_paths_json) + configure_file("${IDF_PATH}/tools/cmake/project_description.json.in" + "${IDF_BUILD_ARTIFACTS_DIR}/project_description.json") + unset(build_components_json) + unset(build_component_paths_json) +endif() + +set(BUILD_COMPONENTS ${BUILD_COMPONENTS} PARENT_SCOPE) + +ldgen_add_dependencies() diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index ffd609509..bc8d7b847 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -26,4 +26,4 @@ register_component() # for gcov component_compile_options("-fno-profile-arcs" "-fno-test-coverage") -target_link_libraries(app_trace gcov) +target_link_libraries(${COMPONENT_TARGET} gcov) diff --git a/components/app_update/CMakeLists.txt b/components/app_update/CMakeLists.txt index ef2684a2c..8eac36935 100644 --- a/components/app_update/CMakeLists.txt +++ b/components/app_update/CMakeLists.txt @@ -7,11 +7,12 @@ set(COMPONENT_PRIV_REQUIRES bootloader_support) register_component() # Add custom target for generating empty otadata partition for flashing -if(${OTADATA_PARTITION_OFFSET}) - add_custom_command(OUTPUT "${PROJECT_BINARY_DIR}/${BLANK_OTADATA_FILE}" +if(OTADATA_PARTITION_OFFSET AND IDF_BUILD_ARTIFACTS) + add_custom_command(OUTPUT "${IDF_BUILD_ARTIFACTS_DIR}/${BLANK_OTADATA_FILE}" COMMAND ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/gen_empty_partition.py - --size ${OTADATA_PARTITION_SIZE} "${PROJECT_BINARY_DIR}/${BLANK_OTADATA_FILE}") + --size ${OTADATA_PARTITION_SIZE} "${IDF_BUILD_ARTIFACTS_DIR}/${BLANK_OTADATA_FILE}") + + add_custom_target(blank_ota_data ALL DEPENDS "${IDF_BUILD_ARTIFACTS_DIR}/${BLANK_OTADATA_FILE}") - add_custom_target(blank_ota_data ALL DEPENDS "${PROJECT_BINARY_DIR}/${BLANK_OTADATA_FILE}") add_dependencies(flash blank_ota_data) endif() diff --git a/components/app_update/project_include.cmake b/components/app_update/project_include.cmake index 70b896f05..8d959bd7c 100644 --- a/components/app_update/project_include.cmake +++ b/components/app_update/project_include.cmake @@ -3,6 +3,6 @@ # partition table # (NB: because of component dependency, we know partition_table # project_include.cmake has already been included.) -if(${OTADATA_PARTITION_OFFSET}) +if(OTADATA_PARTITION_OFFSET AND IDF_BUILD_ARTIFACTS) set(BLANK_OTADATA_FILE "ota_data_initial.bin") endif() diff --git a/components/bootloader/project_include.cmake b/components/bootloader/project_include.cmake index d997510e9..e08c18f7d 100644 --- a/components/bootloader/project_include.cmake +++ b/components/bootloader/project_include.cmake @@ -2,7 +2,7 @@ if(BOOTLOADER_BUILD) set(main_project_path "${CMAKE_BINARY_DIR}/../..") else() - set(main_project_path "${PROJECT_PATH}") + set(main_project_path "${IDF_PROJECT_PATH}") endif() get_filename_component(secure_boot_signing_key @@ -19,15 +19,15 @@ else() add_custom_target(gen_secure_boot_signing_key) endif() -if(BOOTLOADER_BUILD) - return() # don't keep recursing! +if(BOOTLOADER_BUILD OR NOT IDF_BUILD_ARTIFACTS) + return() # don't keep recursing, generate on project builds endif() # Glue to build the bootloader subproject binary as an external # cmake project under this one # # -set(bootloader_build_dir "${CMAKE_BINARY_DIR}/bootloader") +set(bootloader_build_dir "${IDF_BUILD_ARTIFACTS_DIR}/bootloader") set(bootloader_binary_files "${bootloader_build_dir}/bootloader.elf" "${bootloader_build_dir}/bootloader.bin" diff --git a/components/bootloader/subproject/CMakeLists.txt b/components/bootloader/subproject/CMakeLists.txt index 2d75c0a4d..da4560434 100644 --- a/components/bootloader/subproject/CMakeLists.txt +++ b/components/bootloader/subproject/CMakeLists.txt @@ -21,8 +21,16 @@ project(bootloader) target_linker_script(bootloader.elf "main/esp32.bootloader.ld" - "main/esp32.bootloader.rom.ld") -# Imported from esp32 component + "main/esp32.bootloader.rom.ld" +) + +# as cmake won't attach linker args to a header-only library, attach +# linker args directly to the bootloader.elf +set(ESP32_BOOTLOADER_LINKER_SCRIPTS + "../../esp32/ld/esp32.rom.ld" + "../../esp32/ld/esp32.rom.spiram_incompatible_fns.ld" + "../../esp32/ld/esp32.peripherals.ld") + target_linker_script(bootloader.elf ${ESP32_BOOTLOADER_LINKER_SCRIPTS}) target_link_libraries(bootloader.elf gcc) diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index df32f9f94..07b469fe6 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -281,6 +281,6 @@ if(CONFIG_BT_ENABLED) component_compile_options(-Wno-implicit-fallthrough -Wno-unused-const-variable) endif() - target_link_libraries(bt "-L${CMAKE_CURRENT_LIST_DIR}/lib") - target_link_libraries(bt btdm_app) + target_link_libraries(${COMPONENT_TARGET} "-L${CMAKE_CURRENT_LIST_DIR}/lib") + target_link_libraries(${COMPONENT_TARGET} btdm_app) endif() diff --git a/components/coap/CMakeLists.txt b/components/coap/CMakeLists.txt index a7800e64f..01cd61e68 100644 --- a/components/coap/CMakeLists.txt +++ b/components/coap/CMakeLists.txt @@ -24,7 +24,7 @@ register_component() # Needed for coap headers in public builds, also. # # TODO: find a way to move this to a port header -target_compile_definitions(coap PUBLIC WITH_POSIX) +target_compile_definitions(${COMPONENT_TARGET} PUBLIC WITH_POSIX) set_source_files_properties( libcoap/src/debug.c diff --git a/components/cxx/CMakeLists.txt b/components/cxx/CMakeLists.txt index 29ee8016e..236bd5cf7 100644 --- a/components/cxx/CMakeLists.txt +++ b/components/cxx/CMakeLists.txt @@ -3,10 +3,10 @@ set(COMPONENT_SRCS "cxx_exception_stubs.cpp" set(COMPONENT_REQUIRES) register_component() -target_link_libraries(cxx stdc++) +target_link_libraries(${COMPONENT_TARGET} stdc++) -target_link_libraries(cxx "-u __cxa_guard_dummy") +target_link_libraries(${COMPONENT_TARGET} "-u __cxa_guard_dummy") if(NOT CONFIG_CXX_EXCEPTIONS) - target_link_libraries(cxx "-u __cxx_fatal_exception") + target_link_libraries(${COMPONENT_TARGET} "-u __cxx_fatal_exception") endif() diff --git a/components/esp32/CMakeLists.txt b/components/esp32/CMakeLists.txt index ae69d7575..d77aeb410 100644 --- a/components/esp32/CMakeLists.txt +++ b/components/esp32/CMakeLists.txt @@ -3,19 +3,9 @@ require_idf_targets(esp32) if(BOOTLOADER_BUILD) # For bootloader, all we need from esp32 is headers set(COMPONENT_ADD_INCLUDEDIRS include) - set(COMPONENT_REQUIRES ${COMPONENTS}) + set(COMPONENT_REQUIRES ${IDF_COMPONENTS}) set(COMPONENT_SRCS ) - register_component(esp32) - - # as cmake won't attach linker args to a header-only library, attach - # linker args directly to the bootloader.elf - set(ESP32_BOOTLOADER_LINKER_SCRIPTS - "${CMAKE_CURRENT_SOURCE_DIR}/ld/esp32.rom.ld" - "${CMAKE_CURRENT_SOURCE_DIR}/ld/esp32.rom.spiram_incompatible_fns.ld" - "${CMAKE_CURRENT_SOURCE_DIR}/ld/esp32.peripherals.ld" - PARENT_SCOPE - ) - + register_component() else() # Regular app build @@ -75,29 +65,31 @@ else() register_component() - target_link_libraries(esp32 "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib") + target_link_libraries(${COMPONENT_TARGET} "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib") if(NOT CONFIG_NO_BLOBS) - target_link_libraries(esp32 coexist core espnow mesh net80211 phy pp rtc smartconfig wpa2 wpa wps) + target_link_libraries(${COMPONENT_TARGET} coexist core espnow mesh net80211 phy pp rtc smartconfig wpa2 wpa wps) endif() - target_linker_script(esp32 "${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld") + target_linker_script(${COMPONENT_TARGET} "${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld") if(CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY) # This has to be linked before esp32.common.ld - target_linker_script(esp32 "ld/esp32.extram.bss.ld") + target_linker_script(${COMPONENT_TARGET} "ld/esp32.extram.bss.ld") endif() - # Process the template file through the linker script generation mechanism, and use the output for linking the - # final binary - set(esp32_common_script "${CMAKE_CURRENT_BINARY_DIR}/esp32.common.ld") - set(esp32_common_template "${CMAKE_CURRENT_LIST_DIR}/ld/esp32.common.ld.in") + if(IDF_PROJECT_EXECUTABLE) + # Process the template file through the linker script generation mechanism, and use the output for linking the + # final binary + set(esp32_common_script "${CMAKE_CURRENT_BINARY_DIR}/esp32.common.ld") + set(esp32_common_template "${CMAKE_CURRENT_LIST_DIR}/ld/esp32.common.ld.in") - ldgen_process_template(${esp32_common_template} ${esp32_common_script}) + ldgen_process_template(${esp32_common_template} ${esp32_common_script}) - target_link_libraries(esp32 "-T ${esp32_common_script}") + target_link_libraries(${COMPONENT_TARGET} "-T ${esp32_common_script}") + + set_property(TARGET ${IDF_PROJECT_EXECUTABLE} APPEND PROPERTY LINK_DEPENDS ${esp32_common_script}) + endif() - set_property(TARGET ${PROJECT_NAME}.elf APPEND PROPERTY LINK_DEPENDS ${esp32_common_script}) - - target_linker_script(esp32 + target_linker_script(${COMPONENT_TARGET} "ld/esp32.rom.ld" "ld/esp32.peripherals.ld" "ld/esp32.rom.libgcc.ld" @@ -106,25 +98,25 @@ else() if(CONFIG_SPIRAM_CACHE_WORKAROUND) add_compile_options(-mfix-esp32-psram-cache-issue) else() - target_linker_script(esp32 "ld/esp32.rom.spiram_incompatible_fns.ld") + target_linker_script(${COMPONENT_TARGET} "ld/esp32.rom.spiram_incompatible_fns.ld") endif() if(CONFIG_NEWLIB_NANO_FORMAT) - target_linker_script(esp32 "ld/esp32.rom.nanofmt.ld") + target_linker_script(${COMPONENT_TARGET} "ld/esp32.rom.nanofmt.ld") endif() if(NOT CONFIG_SPI_FLASH_ROM_DRIVER_PATCH) - target_linker_script(esp32 "ld/esp32.rom.spiflash.ld") + target_linker_script(${COMPONENT_TARGET} "ld/esp32.rom.spiflash.ld") endif() - target_link_libraries(esp32 "${CMAKE_CURRENT_SOURCE_DIR}/libhal.a") - target_link_libraries(esp32 gcc) - target_link_libraries(esp32 "-u call_user_start_cpu0") + target_link_libraries(${COMPONENT_TARGET} "${CMAKE_CURRENT_SOURCE_DIR}/libhal.a") + target_link_libraries(${COMPONENT_TARGET} gcc) + target_link_libraries(${COMPONENT_TARGET} "-u call_user_start_cpu0") #ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the #linker will ignore panic_highint_hdl.S as it has no other files depending on any #symbols in it. - target_link_libraries(esp32 "-u ld_include_panic_highint_hdl") + target_link_libraries(${COMPONENT_TARGET} "-u ld_include_panic_highint_hdl") # Preprocess esp32.ld linker script to include configuration, becomes esp32_out.ld set(LD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ld) @@ -136,10 +128,10 @@ else() VERBATIM) add_custom_target(esp32_linker_script DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld) - add_dependencies(esp32 esp32_linker_script) + add_dependencies(${COMPONENT_TARGET} esp32_linker_script) - if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION) - set(PHY_INIT_DATA_BIN phy_init_data.bin) + if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION AND IDF_BUILD_ARTIFACTS) + set(PHY_INIT_DATA_BIN ${IDF_BUILD_ARTIFACTS_DIR}/${PHY_PARTITION_BIN_FILE}) # To get the phy_init_data.bin file, compile phy_init_data.h as a C file and then objcopy # the object file to a raw binary @@ -147,14 +139,13 @@ else() OUTPUT ${PHY_INIT_DATA_BIN} DEPENDS ${CMAKE_CURRENT_LIST_DIR}/phy_init_data.h COMMAND ${CMAKE_C_COMPILER} -x c -c - -I ${CMAKE_CURRENT_LIST_DIR} -I ${CMAKE_CURRENT_LIST_DIR}/include -I ${CMAKE_BINARY_DIR} + -I ${CMAKE_CURRENT_LIST_DIR} -I ${CMAKE_CURRENT_LIST_DIR}/include -I ${IDF_BUILD_ARTIFACTS_DIR} -o phy_init_data.obj ${CMAKE_CURRENT_LIST_DIR}/phy_init_data.h COMMAND ${CMAKE_OBJCOPY} -O binary phy_init_data.obj ${PHY_INIT_DATA_BIN} ) add_custom_target(phy_init_data ALL DEPENDS ${PHY_INIT_DATA_BIN}) add_dependencies(flash phy_init_data) - endif() # Enable dynamic esp_timer overflow value if building unit tests diff --git a/components/esp32/test/CMakeLists.txt b/components/esp32/test/CMakeLists.txt index a56e6d2bb..939b386a5 100644 --- a/components/esp32/test/CMakeLists.txt +++ b/components/esp32/test/CMakeLists.txt @@ -27,4 +27,4 @@ add_definitions(-DWIFI_CRYPTO_MD5=\"${WIFI_CRYPTO_MD5}\") add_custom_target(esp32_test_logo DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/test_tjpgd_logo.h") -add_dependencies(${COMPONENT_NAME} esp32_test_logo) +add_dependencies(${COMPONENT_TARGET} esp32_test_logo) \ No newline at end of file diff --git a/components/esptool_py/CMakeLists.txt b/components/esptool_py/CMakeLists.txt index 05293be37..82750e2d6 100644 --- a/components/esptool_py/CMakeLists.txt +++ b/components/esptool_py/CMakeLists.txt @@ -9,15 +9,18 @@ if(CONFIG_SECURE_BOOT_ENABLED) set(ESPTOOLPY_FLASH_PROJECT_OPTIONS "") endif() -# Generate pre-canned flasher args files suitable for passing to esptool.py -foreach(part project app bootloader partition_table) - configure_file( - "${CMAKE_CURRENT_LIST_DIR}/flash_${part}_args.in" - "${CMAKE_BINARY_DIR}/flash_${part}_args" - ) -endforeach() +if(IDF_BUILD_ARTIFACTS) + # Generate pre-canned flasher args files suitable for passing to esptool.py + foreach(part project app bootloader partition_table) + configure_file( + "${CMAKE_CURRENT_LIST_DIR}/flash_${part}_args.in" + "${IDF_BUILD_ARTIFACTS_DIR}/flash_${part}_args" + ) + endforeach() + + configure_file( + "${CMAKE_CURRENT_LIST_DIR}/flasher_args.json.in" + "${IDF_BUILD_ARTIFACTS_DIR}/flasher_args.json" + ) +endif() -configure_file( - "${CMAKE_CURRENT_LIST_DIR}/flasher_args.json.in" - "${CMAKE_BINARY_DIR}/flasher_args.json" - ) diff --git a/components/esptool_py/flash_app_args.in b/components/esptool_py/flash_app_args.in index 6d31ca4fe..bd4f2a6e0 100644 --- a/components/esptool_py/flash_app_args.in +++ b/components/esptool_py/flash_app_args.in @@ -1 +1 @@ -${APP_PARTITION_OFFSET} ${PROJECT_NAME}.bin +${APP_PARTITION_OFFSET} ${IDF_PROJECT_BIN} diff --git a/components/esptool_py/flash_project_args.in b/components/esptool_py/flash_project_args.in index 18ee9ab2c..441144b5c 100644 --- a/components/esptool_py/flash_project_args.in +++ b/components/esptool_py/flash_project_args.in @@ -2,5 +2,5 @@ ${ESPTOOLPY_FLASH_PROJECT_OPTIONS} ${PARTITION_TABLE_OFFSET} partition_table/partition-table.bin ${PHY_PARTITION_OFFSET} ${PHY_PARTITION_BIN_FILE} ${OTADATA_PARTITION_OFFSET} ${BLANK_OTADATA_FILE} -${APP_PARTITION_OFFSET} ${PROJECT_NAME}.bin +${APP_PARTITION_OFFSET} ${IDF_PROJECT_BIN} diff --git a/components/esptool_py/flasher_args.json.in b/components/esptool_py/flasher_args.json.in index bc0e5e340..1a56d5ced 100644 --- a/components/esptool_py/flasher_args.json.in +++ b/components/esptool_py/flasher_args.json.in @@ -7,7 +7,7 @@ "${PARTITION_TABLE_OFFSET}" : "partition_table/partition-table.bin", "${PHY_PARTITION_OFFSET}" : "${PHY_PARTITION_BIN_FILE}", "${OTADATA_PARTITION_OFFSET}" : "${BLANK_OTADATA_FILE}", - "${APP_PARTITION_OFFSET}" : "${PROJECT_NAME}.bin" + "${APP_PARTITION_OFFSET}" : "${IDF_PROJECT_BIN}" }, "bootloader" : { "offset" : "${BOOTLOADER_OFFSET}", "file" : "bootloader/bootloader.bin" }, @@ -16,7 +16,7 @@ "otadata" : { "offset" : "${OTADATA_PARTITION_OFFSET}", "file" : "${BLANK_OTADATA_FILE}" }, "app" : { "offset" : "${APP_PARTITION_OFFSET}", - "file" : "${PROJECT_NAME}.bin" }, + "file" : "${IDF_PROJECT_BIN}" }, "extra_esptool_args" : { "after" : "${ESPTOOLPY_AFTER}", "before" : "${ESPTOOLPY_BEFORE}" diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake index 7ab07f5b8..83e129ae6 100644 --- a/components/esptool_py/project_include.cmake +++ b/components/esptool_py/project_include.cmake @@ -1,3 +1,7 @@ +if(NOT IDF_BUILD_ARTIFACTS) + return() +endif() + # Set some global esptool.py variables # # Many of these are read when generating flash_app_args & flash_project_args @@ -60,38 +64,44 @@ if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION) set(PHY_PARTITION_BIN_FILE "esp32/phy_init_data.bin") endif() +get_filename_component(IDF_PROJECT_NAME ${IDF_PROJECT_EXECUTABLE} NAME_WE) if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES AND NOT BOOTLOADER_BUILD) - set(unsigned_project_binary "${PROJECT_NAME}-unsigned.bin") + set(unsigned_project_binary "${IDF_PROJECT_NAME}-unsigned.bin") else() - set(unsigned_project_binary "${PROJECT_NAME}.bin") + set(unsigned_project_binary "${IDF_PROJECT_NAME}.bin") endif() # # Add 'app.bin' target - generates with elf2image # -add_custom_command(OUTPUT "${unsigned_project_binary}" +add_custom_command(OUTPUT "${IDF_BUILD_ARTIFACTS_DIR}/${unsigned_project_binary}" COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} - -o "${unsigned_project_binary}" "${PROJECT_NAME}.elf" - DEPENDS ${PROJECT_NAME}.elf + -o "${IDF_BUILD_ARTIFACTS_DIR}/${unsigned_project_binary}" "${IDF_PROJECT_EXECUTABLE}" + DEPENDS ${IDF_PROJECT_EXECUTABLE} VERBATIM + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) +get_filename_component(IDF_PROJECT_BIN ${IDF_PROJECT_EXECUTABLE} NAME_WE) +set(IDF_PROJECT_BIN ${IDF_PROJECT_BIN}.bin) + if(NOT BOOTLOADER_BUILD AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + # for locally signed secure boot image, add a signing step to get from unsigned app to signed app - add_custom_target(gen_unsigned_project_binary ALL DEPENDS "${unsigned_project_binary}") - add_custom_command(OUTPUT "${PROJECT_NAME}.bin" + add_custom_target(gen_unsigned_project_binary ALL DEPENDS "${IDF_BUILD_ARTIFACTS_DIR}/${unsigned_project_binary}") + add_custom_command(OUTPUT "${IDF_BUILD_ARTIFACTS_DIR}/${IDF_PROJECT_BIN}" COMMAND ${ESPSECUREPY} sign_data --keyfile ${secure_boot_signing_key} - -o "${PROJECT_NAME}.bin" "${unsigned_project_binary}" + -o "${IDF_BUILD_ARTIFACTS_DIR}/${IDF_PROJECT_BIN}" "${IDF_BUILD_ARTIFACTS_DIR}/${unsigned_project_binary}" DEPENDS gen_unsigned_project_binary VERBATIM ) endif() if(NOT BOOTLOADER_BUILD) - add_custom_target(app ALL DEPENDS "${PROJECT_NAME}.bin") + add_custom_target(app ALL DEPENDS "${IDF_BUILD_ARTIFACTS_DIR}/${IDF_PROJECT_BIN}") else() - add_custom_target(bootloader ALL DEPENDS "${PROJECT_NAME}.bin") + add_custom_target(bootloader ALL DEPENDS "${IDF_BUILD_ARTIFACTS_DIR}/${IDF_PROJECT_BIN}") endif() if(NOT BOOTLOADER_BUILD AND @@ -101,7 +111,7 @@ if(NOT BOOTLOADER_BUILD AND COMMAND ${CMAKE_COMMAND} -E echo "App built but not signed. Sign app before flashing" COMMAND ${CMAKE_COMMAND} -E echo - "\t${ESPSECUREPY} sign_data --keyfile KEYFILE ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.bin" + "\t${ESPSECUREPY} sign_data --keyfile KEYFILE ${IDF_BUILD_ARTIFACTS_DIR}/${IDF_PROJECT_BIN}" VERBATIM) endif() @@ -114,7 +124,7 @@ 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="${CMAKE_CURRENT_BINARY_DIR}" + -D ESPTOOL_WORKING_DIR="${IDF_BUILD_ARTIFACTS_DIR}" -P run_esptool.cmake WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} USES_TERMINAL diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index 3b0886529..a73a29fdb 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -23,7 +23,7 @@ set(COMPONENT_REQUIRES app_trace) set(COMPONENT_ADD_LDFRAGMENTS linker.lf) register_component() -target_link_libraries(freertos "-Wl,--undefined=uxTopUsedPriority") +target_link_libraries(${COMPONENT_TARGET} "-Wl,--undefined=uxTopUsedPriority") set_source_files_properties( tasks.c diff --git a/components/heap/test/CMakeLists.txt b/components/heap/test/CMakeLists.txt index 66a8c8231..aed6c9743 100644 --- a/components/heap/test/CMakeLists.txt +++ b/components/heap/test/CMakeLists.txt @@ -1,6 +1,6 @@ set(COMPONENT_SRCDIRS ".") set(COMPONENT_ADD_INCLUDEDIRS ".") -set(COMPONENT_REQUIRES unity test_utils) +set(COMPONENT_REQUIRES unity test_utils heap) register_component() \ No newline at end of file diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt index cb8ba6085..f9964f2e7 100644 --- a/components/mbedtls/CMakeLists.txt +++ b/components/mbedtls/CMakeLists.txt @@ -91,7 +91,7 @@ set(COMPONENT_REQUIRES lwip) register_component() -target_compile_definitions(mbedtls PUBLIC +target_compile_definitions(${COMPONENT_TARGET} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" ) diff --git a/components/newlib/CMakeLists.txt b/components/newlib/CMakeLists.txt index d541b87bf..893d9f7d1 100644 --- a/components/newlib/CMakeLists.txt +++ b/components/newlib/CMakeLists.txt @@ -28,7 +28,7 @@ set(COMPONENT_REQUIRES vfs) # for sys/ioctl.h register_component() -target_link_libraries(newlib "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib") -target_link_libraries(newlib ${LIBC} ${LIBM}) +target_link_libraries(${COMPONENT_TARGET} "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib") +target_link_libraries(${COMPONENT_TARGET} ${LIBC} ${LIBM}) -set_source_files_properties(syscalls.c PROPERTIES COMPILE_FLAGS -fno-builtin) +set_source_files_properties(syscalls.c PROPERTIES COMPILE_FLAGS -fno-builtin) \ No newline at end of file diff --git a/components/nvs_flash/test_nvs_host/Makefile b/components/nvs_flash/test_nvs_host/Makefile index b125aaffe..73aec3253 100644 --- a/components/nvs_flash/test_nvs_host/Makefile +++ b/components/nvs_flash/test_nvs_host/Makefile @@ -21,7 +21,7 @@ SOURCE_FILES = \ crc.cpp \ main.cpp -CPPFLAGS += -I../include -I../src -I./ -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -DCONFIG_NVS_ENCRYPTION +CPPFLAGS += -I../include -I../src -I./ -I../../esp32/include -I ../../esp_mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -DCONFIG_NVS_ENCRYPTION CFLAGS += -fprofile-arcs -ftest-coverage CXXFLAGS += -std=c++11 -Wall -Werror LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage @@ -33,8 +33,8 @@ COVERAGE_FILES = $(OBJ_FILES:.o=.gc*) $(OBJ_FILES): %.o: %.cpp $(TEST_PROGRAM): $(OBJ_FILES) - $(MAKE) -C ../../mbedtls/mbedtls/ lib - g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) ../../mbedtls/mbedtls/library/libmbedcrypto.a + $(MAKE) -C ../../esp_mbedtls/mbedtls/ lib + g++ $(LDFLAGS) -o $(TEST_PROGRAM) $(OBJ_FILES) ../../esp_mbedtls/mbedtls/library/libmbedcrypto.a $(OUTPUT_DIR): mkdir -p $(OUTPUT_DIR) @@ -56,7 +56,7 @@ coverage_report: coverage.info @echo "Coverage report is in coverage_report/index.html" clean: - $(MAKE) -C ../../mbedtls/mbedtls/ clean + $(MAKE) -C ../../esp_mbedtls/mbedtls/ clean rm -f $(OBJ_FILES) $(TEST_PROGRAM) rm -f $(COVERAGE_FILES) *.gcov rm -rf coverage_report/ diff --git a/components/partition_table/CMakeLists.txt b/components/partition_table/CMakeLists.txt index fc2ecf7ad..6020820fe 100644 --- a/components/partition_table/CMakeLists.txt +++ b/components/partition_table/CMakeLists.txt @@ -1,6 +1,6 @@ register_config_only_component() -if(NOT BOOTLOADER_BUILD) +if(NOT BOOTLOADER_BUILD AND IDF_BUILD_ARTIFACTS) set(partition_csv "${PARTITION_CSV_PATH}") @@ -28,25 +28,28 @@ else() set(partition_secure_opt "") endif() -add_custom_command(OUTPUT "${unsigned_partition_bin}" - COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py" - -q --offset ${PARTITION_TABLE_OFFSET} ${md5_opt} ${flashsize_opt} - ${partition_secure_opt} ${partition_csv} ${unsigned_partition_bin} +add_custom_command(OUTPUT "${IDF_BUILD_ARTIFACTS_DIR}/partition_table/${unsigned_partition_bin}" + COMMAND "${PYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py" + -q --offset ${PARTITION_TABLE_OFFSET} ${md5_opt} ${flashsize_opt} + ${partition_secure_opt} ${partition_csv} ${IDF_BUILD_ARTIFACTS_DIR}/partition_table/${unsigned_partition_bin} DEPENDS ${partition_csv} "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py" VERBATIM) # Add signing steps if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) - add_custom_target(gen_unsigned_partition_bin ALL DEPENDS "${unsigned_partition_bin}") - add_custom_command(OUTPUT "${final_partition_bin}" + add_custom_target(gen_unsigned_partition_bin ALL DEPENDS + "${IDF_BUILD_ARTIFACTS_DIR}/partition_table/${unsigned_partition_bin}") + + add_custom_command(OUTPUT "${IDF_BUILD_ARTIFACTS_DIR}/partition_table/${final_partition_bin}" COMMAND ${ESPSECUREPY} sign_data --keyfile "${secure_boot_signing_key}" - -o "${final_partition_bin}" "${unsigned_partition_bin}" - DEPENDS gen_unsigned_partition_bin gen_secure_boot_signing_key + -o "${IDF_BUILD_ARTIFACTS_DIR}/partition_table/${final_partition_bin}" + "${IDF_BUILD_ARTIFACTS_DIR}/partition_table/${unsigned_partition_bin}" + DEPENDS "${IDF_BUILD_ARTIFACTS_DIR}/partition_table/${unsigned_partition_bin}" VERBATIM) endif() if(EXISTS ${partition_csv}) - add_custom_target(partition_table ALL DEPENDS "${final_partition_bin}") + add_custom_target(partition_table ALL DEPENDS "${IDF_BUILD_ARTIFACTS_DIR}/partition_table/${final_partition_bin}") else() # If the partition input CSV is not found, create a phony partition_table target that # fails the build. fail_at_build_time also touches CMakeCache.txt to cause a cmake run next time @@ -73,6 +76,7 @@ add_dependencies(app partition_table) # the list of esptool write arguments for flashing set_property(GLOBAL APPEND_STRING PROPERTY ESPTOOL_WRITE_FLASH_ARGS - "${PARTITION_TABLE_OFFSET} ${final_partition_bin} ") + "${PARTITION_TABLE_OFFSET} ${IDF_BUILD_ARTIFACTS_DIR}/partition_table/${final_partition_bin} ") endif() + diff --git a/components/partition_table/gen_esp32part.py b/components/partition_table/gen_esp32part.py index e3c8a6dc4..d029127ab 100755 --- a/components/partition_table/gen_esp32part.py +++ b/components/partition_table/gen_esp32part.py @@ -29,6 +29,7 @@ import struct import sys import hashlib import binascii +import errno MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature MD5_PARTITION_BEGIN = b"\xEB\xEB" + b"\xFF" * 14 # The first 2 bytes are like magic numbers for MD5 sum @@ -480,6 +481,16 @@ def main(): raise InputError("Partitions defined in '%s' occupy %.1fMB of flash (%d bytes) which does not fit in configured flash size %dMB. Change the flash size in menuconfig under the 'Serial Flasher Config' menu." % (args.input.name, table_size / 1024.0 / 1024.0, table_size, size_mb)) + # Make sure that the output directory is created + output_dir = os.path.abspath(os.path.dirname(args.output)) + + if not os.path.exists(output_dir): + try: + os.makedirs(output_dir) + except OSError as exc: + if exc.errno != errno.EEXIST: + raise + if input_is_binary: output = table.to_csv() with sys.stdout if args.output == '-' else open(args.output, 'w') as f: diff --git a/components/partition_table/project_include.cmake b/components/partition_table/project_include.cmake index 0d168c7bd..80841ed74 100644 --- a/components/partition_table/project_include.cmake +++ b/components/partition_table/project_include.cmake @@ -1,4 +1,4 @@ -if(NOT BOOTLOADER_BUILD) +if(NOT BOOTLOADER_BUILD AND IDF_BUILD_ARTIFACTS) set(PARTITION_TABLE_OFFSET ${CONFIG_PARTITION_TABLE_OFFSET}) @@ -6,7 +6,8 @@ set(PARTITION_TABLE_OFFSET ${CONFIG_PARTITION_TABLE_OFFSET}) # absolute path if(CONFIG_PARTITION_TABLE_CUSTOM) # Custom filename expands any path relative to the project - get_filename_component(PARTITION_CSV_PATH "${CONFIG_PARTITION_TABLE_FILENAME}" ABSOLUTE BASE_DIR "${PROJECT_PATH}") + get_filename_component(PARTITION_CSV_PATH "${CONFIG_PARTITION_TABLE_FILENAME}" + ABSOLUTE BASE_DIR "${IDF_PROJECT_PATH}") if(NOT EXISTS "${PARTITION_CSV_PATH}") message(WARNING "Partition table CSV file ${PARTITION_CSV_PATH} not found. " @@ -46,7 +47,7 @@ endfunction() if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION) get_partition_info(PHY_PARTITION_OFFSET "--type data --subtype phy --offset") - set(PHY_PARTITION_BIN_FILE "${CMAKE_BINARY_DIR}/esp32/phy_init_data.bin") + set(PHY_PARTITION_BIN_FILE "esp32/phy_init_data.bin") endif() get_partition_info(APP_PARTITION_OFFSET "--default-boot-partition --offset") diff --git a/components/ulp/component_ulp_common.cmake b/components/ulp/component_ulp_common.cmake index 6b0a631ee..c42ada37e 100644 --- a/components/ulp/component_ulp_common.cmake +++ b/components/ulp/component_ulp_common.cmake @@ -35,7 +35,7 @@ if(NOT CMAKE_BUILD_EARLY_EXPANSION) -DCOMPONENT_PATH=${COMPONENT_PATH} # Even though this resolves to a ';' separated list, this is fine. This must be special behavior # for generator expressions. - -DCOMPONENT_INCLUDES=$ + -DCOMPONENT_INCLUDES=$ -DIDF_PATH=${IDF_PATH} -DSDKCONFIG=${SDKCONFIG_HEADER} BUILD_COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/${ULP_APP_NAME} --target build @@ -52,8 +52,8 @@ if(NOT CMAKE_BUILD_EARLY_EXPANSION) add_custom_target(${ULP_APP_NAME}_artifacts DEPENDS ${ULP_APP_NAME}) - add_dependencies(${COMPONENT_NAME} ${ULP_APP_NAME}_artifacts) + add_dependencies(${COMPONENT_TARGET} ${ULP_APP_NAME}_artifacts) - target_linker_script(${COMPONENT_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${ULP_APP_NAME}/${ULP_APP_NAME}.ld) - target_add_binary_data(${COMPONENT_NAME} ${CMAKE_CURRENT_BINARY_DIR}/${ULP_APP_NAME}/${ULP_APP_NAME}.bin BINARY) + target_linker_script(${COMPONENT_TARGET} ${CMAKE_CURRENT_BINARY_DIR}/${ULP_APP_NAME}/${ULP_APP_NAME}.ld) + target_add_binary_data(${COMPONENT_TARGET} ${CMAKE_CURRENT_BINARY_DIR}/${ULP_APP_NAME}/${ULP_APP_NAME}.bin BINARY) endif() \ No newline at end of file diff --git a/components/unity/CMakeLists.txt b/components/unity/CMakeLists.txt index 82a53f307..e76ffe952 100644 --- a/components/unity/CMakeLists.txt +++ b/components/unity/CMakeLists.txt @@ -14,7 +14,7 @@ endif() register_component() -target_compile_definitions(unity PUBLIC +target_compile_definitions(${COMPONENT_TARGET} PUBLIC -DUNITY_INCLUDE_CONFIG_H ) diff --git a/examples/protocols/aws_iot/subscribe_publish/main/CMakeLists.txt b/examples/protocols/aws_iot/subscribe_publish/main/CMakeLists.txt index d5fc09071..67b51b9f5 100644 --- a/examples/protocols/aws_iot/subscribe_publish/main/CMakeLists.txt +++ b/examples/protocols/aws_iot/subscribe_publish/main/CMakeLists.txt @@ -5,7 +5,7 @@ set(COMPONENT_ADD_INCLUDEDIRS ".") register_component() if(CONFIG_EXAMPLE_EMBEDDED_CERTS) -target_add_binary_data(${COMPONENT_NAME} "certs/aws-root-ca.pem" TEXT) +target_add_binary_data(${COMPONENT_TARGET} "certs/aws-root-ca.pem" TEXT) if(NOT IDF_CI_BUILD) add_custom_command(OUTPUT certs/certificate.pem.crt certs/private.pem.key @@ -17,12 +17,12 @@ if(NOT IDF_CI_BUILD) VERBATIM) add_custom_target(example_certificates DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/certs/certificate.pem.crt ${CMAKE_CURRENT_BINARY_DIR}/certs/private.pem.key) - add_dependencies(${COMPONENT_NAME} example_certificates) + add_dependencies(${COMPONENT_TARGET} example_certificates) - target_add_binary_data(${COMPONENT_NAME} "${CMAKE_CURRENT_BINARY_DIR}/certs/certificate.pem.crt" TEXT) - target_add_binary_data(${COMPONENT_NAME} "${CMAKE_CURRENT_BINARY_DIR}/certs/private.pem.key" TEXT) + target_add_binary_data(${COMPONENT_TARGET} "${CMAKE_CURRENT_BINARY_DIR}/certs/certificate.pem.crt" TEXT) + target_add_binary_data(${COMPONENT_TARGET} "${CMAKE_CURRENT_BINARY_DIR}/certs/private.pem.key" TEXT) else() - target_add_binary_data(${COMPONENT_NAME} "certs/certificate.pem.crt" TEXT) - target_add_binary_data(${COMPONENT_NAME} "certs/private.pem.key" TEXT) + target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT) + target_add_binary_data(${COMPONENT_TARGET} "certs/private.pem.key" TEXT) endif() endif() \ No newline at end of file diff --git a/examples/protocols/aws_iot/thing_shadow/main/CMakeLists.txt b/examples/protocols/aws_iot/thing_shadow/main/CMakeLists.txt index ee14baf02..0fcad6405 100644 --- a/examples/protocols/aws_iot/thing_shadow/main/CMakeLists.txt +++ b/examples/protocols/aws_iot/thing_shadow/main/CMakeLists.txt @@ -5,7 +5,7 @@ set(COMPONENT_ADD_INCLUDEDIRS ".") register_component() if(CONFIG_EXAMPLE_EMBEDDED_CERTS) -target_add_binary_data(${COMPONENT_NAME} "certs/aws-root-ca.pem" TEXT) +target_add_binary_data(${COMPONENT_TARGET} "certs/aws-root-ca.pem" TEXT) if(NOT IDF_CI_BUILD) add_custom_command(OUTPUT certs/certificate.pem.crt certs/private.pem.key @@ -17,12 +17,12 @@ if(NOT IDF_CI_BUILD) VERBATIM) add_custom_target(example_certificates DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/certs/certificate.pem.crt ${CMAKE_CURRENT_BINARY_DIR}/certs/private.pem.key) - add_dependencies(${COMPONENT_NAME} example_certificates) + add_dependencies(${COMPONENT_TARGET} example_certificates) - target_add_binary_data(${COMPONENT_NAME} "${CMAKE_CURRENT_BINARY_DIR}/certs/certificate.pem.crt" TEXT) - target_add_binary_data(${COMPONENT_NAME} "${CMAKE_CURRENT_BINARY_DIR}/certs/private.pem.key" TEXT) + target_add_binary_data(${COMPONENT_TARGET} "${CMAKE_CURRENT_BINARY_DIR}/certs/certificate.pem.crt" TEXT) + target_add_binary_data(${COMPONENT_TARGET} "${CMAKE_CURRENT_BINARY_DIR}/certs/private.pem.key" TEXT) else() - target_add_binary_data(${COMPONENT_NAME} "certs/certificate.pem.crt" TEXT) - target_add_binary_data(${COMPONENT_NAME} "certs/private.pem.key" TEXT) + target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT) + target_add_binary_data(${COMPONENT_TARGET} "certs/private.pem.key" TEXT) endif() endif() \ No newline at end of file diff --git a/tools/cmake/component_utils.cmake b/tools/cmake/component_utils.cmake index 63377a2e3..410066477 100644 --- a/tools/cmake/component_utils.cmake +++ b/tools/cmake/component_utils.cmake @@ -1,3 +1,9 @@ +function(debug message) + if(DEBUG) + message(STATUS "${message}") + endif() +endfunction() + # Given a component name (find_name) and a list of component paths (component_paths), # return the path to the component in 'variable' # diff --git a/tools/cmake/components.cmake b/tools/cmake/components.cmake index 8da2c284f..cec044358 100644 --- a/tools/cmake/components.cmake +++ b/tools/cmake/components.cmake @@ -16,7 +16,6 @@ endfunction() # function(register_component) get_filename_component(component_dir ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) - set(component ${COMPONENT_NAME}) spaces2list(COMPONENT_SRCDIRS) spaces2list(COMPONENT_ADD_INCLUDEDIRS) @@ -59,10 +58,12 @@ function(register_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}) + add_library(${COMPONENT_TARGET} STATIC ${COMPONENT_SRCS}) set(include_type PUBLIC) + + set_property(TARGET ${COMPONENT_TARGET} PROPERTY OUTPUT_NAME ${COMPONENT_NAME}) else() - add_library(${component} INTERFACE) # header-only component + add_library(${COMPONENT_TARGET} INTERFACE) # header-only component set(include_type INTERFACE) endif() @@ -75,7 +76,7 @@ function(register_component) else() set(embed_type "BINARY") endif() - target_add_binary_data("${component}" "${embed_data}" "${embed_type}") + target_add_binary_data("${COMPONENT_TARGET}" "${embed_data}" "${embed_type}") endforeach() # add component public includes @@ -85,7 +86,7 @@ function(register_component) message(FATAL_ERROR "${CMAKE_CURRENT_LIST_FILE}: " "COMPONENT_ADD_INCLUDEDIRS entry '${include_dir}' not found") endif() - target_include_directories(${component} ${include_type} ${abs_dir}) + target_include_directories(${COMPONENT_TARGET} ${include_type} ${abs_dir}) endforeach() # add component private includes @@ -100,17 +101,25 @@ function(register_component) message(FATAL_ERROR "${CMAKE_CURRENT_LIST_FILE}: " "COMPONENT_PRIV_INCLUDEDIRS entry '${include_dir}' does not exist") endif() - target_include_directories(${component} PRIVATE ${abs_dir}) + target_include_directories(${COMPONENT_TARGET} PRIVATE ${abs_dir}) endforeach() - if(component IN_LIST BUILD_TEST_COMPONENTS) - target_link_libraries(${component} "-L${CMAKE_CURRENT_BINARY_DIR}") - target_link_libraries(${component} "-Wl,--whole-archive -l${component} -Wl,--no-whole-archive") + if(${COMPONENT_NAME} IN_LIST BUILD_TEST_COMPONENTS) + target_link_libraries(${COMPONENT_TARGET} "-L${CMAKE_CURRENT_BINARY_DIR}") + target_link_libraries(${COMPONENT_TARGET} "-Wl,--whole-archive -l${COMPONENT_NAME} -Wl,--no-whole-archive") + endif() + + if(COMPONENT_SRCS OR embed_binaries) + target_include_directories(${COMPONENT_TARGET} PUBLIC ${IDF_INCLUDE_DIRECTORIES}) + target_compile_options(${COMPONENT_TARGET} PUBLIC ${IDF_COMPILE_OPTIONS}) + target_compile_options(${COMPONENT_TARGET} PUBLIC $<$:${IDF_C_COMPILE_OPTIONS}>) + target_compile_options(${COMPONENT_TARGET} PUBLIC $<$:${IDF_CXX_COMPILE_OPTIONS}>) + target_compile_definitions(${COMPONENT_TARGET} PUBLIC ${IDF_COMPILE_DEFINITIONS}) endif() if(COMPONENT_ADD_LDFRAGMENTS) spaces2list(COMPONENT_ADD_LDFRAGMENTS) - ldgen_add_fragment_files(${component} "${COMPONENT_ADD_LDFRAGMENTS}") + ldgen_add_fragment_files(${COMPONENT_TARGET} "${COMPONENT_ADD_LDFRAGMENTS}") endif() endfunction() @@ -144,56 +153,24 @@ function(require_idf_targets) endif() endfunction() -function(components_finish_registration) - - # 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 and targets exist in cmake, as we have - # a circular requirements graph...) - foreach(a ${BUILD_COMPONENTS}) - if(TARGET ${a}) - 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) - list(APPEND COMPONENT_LIBRARIES ${a}) - endif() - endif() - endforeach() - - # 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 ${BUILD_COMPONENTS}) - if(TARGET ${component}) - get_target_property(imported ${component} IMPORTED) - get_target_property(type ${component} TYPE) - if(NOT imported) - if(${type} STREQUAL STATIC_LIBRARY OR ${type} STREQUAL EXECUTABLE) - get_target_property(link_depends "${component}" LINK_DEPENDS) - if(link_depends) - set_property(TARGET ${CMAKE_PROJECT_NAME}.elf APPEND PROPERTY LINK_DEPENDS "${link_depends}") - endif() - endif() - endif() - endif() - endforeach() - - target_link_libraries(${CMAKE_PROJECT_NAME}.elf ${COMPONENT_LIBRARIES}) - - message(STATUS "Component libraries: ${COMPONENT_LIBRARIES}") - +# component_compile_options +# +# Wrapper around target_compile_options that passes the component name +function(component_compile_options) + target_compile_options(${COMPONENT_TARGET} PRIVATE ${ARGV}) endfunction() + +# component_compile_definitions +# +# Wrapper around target_compile_definitions that passes the component name +function(component_compile_definitions) + target_compile_definitions(${COMPONENT_TARGET} PRIVATE ${ARGV}) +endfunction() + +# component_get_target +# +# Get the library target created for the given component +function(component_get_target var component) + get_property(prefix GLOBAL PROPERTY __IDF_COMPONENTS_PREFIX) + set(${var} ${prefix}_${component} PARENT_SCOPE) +endfunction() \ No newline at end of file diff --git a/tools/cmake/idf_functions.cmake b/tools/cmake/idf_functions.cmake index f949ba543..65ba66351 100644 --- a/tools/cmake/idf_functions.cmake +++ b/tools/cmake/idf_functions.cmake @@ -1,52 +1,63 @@ -# Some IDF-specific functions and functions - -include(crosstool_version_check) - # -# Set some variables used by rest of the build +# Load cmake modules # -# Note at the time this macro is expanded, the config is not yet -# loaded and the toolchain and project are not yet set -# -macro(idf_set_global_variables) - # Note that CONFIG_xxx is not available when this function is called - set_default(EXTRA_COMPONENT_DIRS "") +if(NOT IDF_PATH) + set(IDF_PATH $ENV{IDF_PATH}) +endif() - # Commmon components, required by every component in the build - # - set_default(COMPONENT_REQUIRES_COMMON "cxx ${IDF_TARGET} newlib freertos heap log soc") +get_property(__idf_environment_set GLOBAL PROPERTY __IDF_ENVIRONMENT_SET) - # PROJECT_PATH has the path to the IDF project (top-level cmake directory) - # - # (cmake calls this CMAKE_SOURCE_DIR, keeping old name for compatibility.) - set(PROJECT_PATH "${CMAKE_SOURCE_DIR}") +if(NOT __idf_environment_set) + set(CMAKE_MODULE_PATH + "${IDF_PATH}/tools/cmake" + "${IDF_PATH}/tools/cmake/third_party" + ${CMAKE_MODULE_PATH}) + include(utilities) + include(components) + include(kconfig) + include(targets) + include(git_submodules) + include(GetGitRevisionDescription) + include(crosstool_version_check) + include(ldgen) - if(MAIN_SRCS) - message(WARNING "main is now a component, use of MAIN_SRCS is deprecated") - set_default(COMPONENT_DIRS "${PROJECT_PATH}/components ${EXTRA_COMPONENT_DIRS} \ - ${IDF_PATH}/components") - else() - set_default(COMPONENT_DIRS "${PROJECT_PATH}/components ${EXTRA_COMPONENT_DIRS} \ - ${IDF_PATH}/components ${PROJECT_PATH}/main") + set_default(PYTHON "python") + + if(NOT PYTHON_DEPS_CHECKED AND NOT BOOTLOADER_BUILD) + message(STATUS "Checking Python dependencies...") + execute_process(COMMAND "${PYTHON}" "${IDF_PATH}/tools/check_python_dependencies.py" + RESULT_VARIABLE result) + if(NOT result EQUAL 0) + message(FATAL_ERROR "Some Python dependencies must be installed. Check above message for details.") + endif() endif() - spaces2list(COMPONENT_DIRS) + idf_set_target() - spaces2list(COMPONENTS) + set_property(GLOBAL APPEND PROPERTY __IDF_COMPONENTS_PREFIX "idf_component") + set_property(GLOBAL PROPERTY __IDF_ENVIRONMENT_SET 1) +endif() - # Tell cmake to drop executables in the top-level build dir - set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}") +macro(idf_set_variables) + set_default(IDF_BUILD_ARTIFACTS OFF) - # path to idf.py tool - set(IDFTOOL ${PYTHON} "${IDF_PATH}/tools/idf.py") - - # Temporary trick to support both gcc5 and gcc8 builds - if(CMAKE_C_COMPILER_VERSION VERSION_EQUAL 5.2.0) - set(GCC_NOT_5_2_0 0) - else() - set(GCC_NOT_5_2_0 1) + if(IDF_BUILD_ARTIFACTS) + if(NOT IDF_BUILD_ARTIFACTS_DIR OR NOT IDF_PROJECT_EXECUTABLE) + message(FATAL_ERROR "IDF_BUILD_ARTIFACTS and IDF_PROJECT_EXECUTABLE needs to be specified \ + if IDF_BUILD_ARTIFACTS is ON.") + endif() endif() + + set_default(IDF_COMPONENT_DIRS "${IDF_EXTRA_COMPONENT_DIRS} ${IDF_PATH}/components") + set_default(IDF_COMPONENTS "") + set_default(IDF_COMPONENT_REQUIRES_COMMON "cxx ${IDF_TARGET} newlib freertos heap log soc") + + set(IDF_PROJECT_PATH "${CMAKE_SOURCE_DIR}") + + spaces2list(IDF_COMPONENT_DIRS) + spaces2list(IDF_COMPONENTS) + spaces2list(IDF_COMPONENT_REQUIRES_COMMON) endmacro() # Add all the IDF global compiler & preprocessor options @@ -55,64 +66,73 @@ endmacro() # If you only want to set options for a particular component, # don't call or edit this function. TODO DESCRIBE WHAT TO DO INSTEAD # -function(idf_set_global_compiler_options) - add_definitions(-DESP_PLATFORM) - add_definitions(-DHAVE_CONFIG_H) - - if(CONFIG_OPTIMIZATION_LEVEL_RELEASE) - add_compile_options(-Os) +function(idf_set_global_compile_options) + # Temporary trick to support both gcc5 and gcc8 builds + if(CMAKE_C_COMPILER_VERSION VERSION_EQUAL 5.2.0) + set(GCC_NOT_5_2_0 0) else() - add_compile_options(-Og) + set(GCC_NOT_5_2_0 1) endif() - add_c_compile_options(-std=gnu99) + list(APPEND compile_definitions "ESP_PLATFORM" "HAVE_CONFIG_H") - add_cxx_compile_options(-std=gnu++11 -fno-rtti) + list(APPEND compile_options "${CMAKE_C_FLAGS}") + list(APPEND c_compile_options "${CMAKE_C_FLAGS}") + list(APPEND cxx_compile_options "${CMAKE_CXX_FLAGS}") + + if(CONFIG_OPTIMIZATION_LEVEL_RELEASE) + list(APPEND compile_options "-Os") + else() + list(APPEND compile_options "-Og") + endif() + + list(APPEND c_compile_options "-std=gnu99") + list(APPEND cxx_compile_options "-std=gnu++11" "-fno-rtti") if(CONFIG_CXX_EXCEPTIONS) - add_cxx_compile_options(-fexceptions) + list(APPEND cxx_compile_options "-fexceptions") else() - add_cxx_compile_options(-fno-exceptions) + list(APPEND cxx_compile_options "-fno-exceptions") endif() # Default compiler configuration - add_compile_options(-ffunction-sections -fdata-sections -fstrict-volatile-bitfields -nostdlib) + list(APPEND compile_options "-ffunction-sections" + "-fdata-sections" + "-fstrict-volatile-bitfields" + "-nostdlib") - # Default warnings configuration - add_compile_options( - -Wall - -Werror=all - -Wno-error=unused-function - -Wno-error=unused-but-set-variable - -Wno-error=unused-variable - -Wno-error=deprecated-declarations - -Wextra - -Wno-unused-parameter - -Wno-sign-compare) - add_c_compile_options( - -Wno-old-style-declaration - ) + list(APPEND compile_options "-Wall" + "-Werror=all" + "-Wno-error=unused-function" + "-Wno-error=unused-but-set-variable" + "-Wno-error=unused-variable" + "-Wno-error=deprecated-declarations" + "-Wextra" + "-Wno-unused-parameter" + "-Wno-sign-compare") + + list(APPEND c_compile_options "-Wno-old-style-declaration") if(CONFIG_DISABLE_GCC8_WARNINGS) - add_compile_options( - -Wno-parentheses - -Wno-sizeof-pointer-memaccess - -Wno-clobbered + list(APPEND compile_options + "-Wno-parentheses" + "-Wno-sizeof-pointer-memaccess" + "-Wno-clobbered" ) # doesn't use GCC_NOT_5_2_0 because idf_set_global_variables was not called before if(NOT CMAKE_C_COMPILER_VERSION VERSION_EQUAL 5.2.0) - add_compile_options( - -Wno-format-overflow - -Wno-stringop-truncation - -Wno-misleading-indentation - -Wno-cast-function-type - -Wno-implicit-fallthrough - -Wno-unused-const-variable - -Wno-switch-unreachable - -Wno-format-truncation - -Wno-memset-elt-size - -Wno-int-in-bool-context + list(APPEND compile_options + "-Wno-format-overflow" + "-Wno-stringop-truncation" + "-Wno-misleading-indentation" + "-Wno-cast-function-type" + "-Wno-implicit-fallthrough" + "-Wno-unused-const-variable" + "-Wno-switch-unreachable" + "-Wno-format-truncation" + "-Wno-memset-elt-size" + "-Wno-int-in-bool-context" ) endif() endif() @@ -120,39 +140,40 @@ function(idf_set_global_compiler_options) # Stack protection if(NOT BOOTLOADER_BUILD) if(CONFIG_STACK_CHECK_NORM) - add_compile_options(-fstack-protector) + list(APPEND compile_options "-fstack-protector") elseif(CONFIG_STACK_CHECK_STRONG) - add_compile_options(-fstack-protector-strong) + list(APPEND compile_options "-fstack-protector-strong") elseif(CONFIG_STACK_CHECK_ALL) - add_compile_options(-fstack-protector-all) + list(APPEND compile_options "-fstack-protector-all") endif() endif() if(CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED) - add_definitions(-DNDEBUG) + list(APPEND compile_definitions "NDEBUG") endif() # Always generate debug symbols (even in Release mode, these don't # go into the final binary so have no impact on size) - add_compile_options(-ggdb) - - # Enable ccache if it's on the path - if(NOT CCACHE_DISABLE) - find_program(CCACHE_FOUND ccache) - if(CCACHE_FOUND) - message(STATUS "ccache will be used for faster builds") - set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) - endif() - endif() + list(APPEND compile_options "-ggdb") # Temporary trick to support both gcc5 and gcc8 builds - add_definitions(-DGCC_NOT_5_2_0=${GCC_NOT_5_2_0}) -endfunction() + list(APPEND compile_definitions "GCC_NOT_5_2_0=${GCC_NOT_5_2_0}") + set_default(IDF_COMPILE_DEFINITIONS "${compile_definitions}") + set_default(IDF_COMPILE_OPTIONS "${compile_options}") + set_default(IDF_C_COMPILE_OPTIONS "${c_compile_options}") + set_default(IDF_CXX_COMPILE_OPTIONS "${cxx_compile_options}") + set_default(IDF_INCLUDE_DIRECTORIES "${CONFIG_DIR}") + + set(IDF_COMPILE_DEFINITIONS ${IDF_COMPILE_DEFINITIONS} PARENT_SCOPE) + set(IDF_COMPILE_OPTIONS ${IDF_COMPILE_OPTIONS} PARENT_SCOPE) + set(IDF_C_COMPILE_OPTIONS ${IDF_C_COMPILE_OPTIONS} PARENT_SCOPE) + set(IDF_CXX_COMPILE_OPTIONS ${IDF_CXX_COMPILE_OPTIONS} PARENT_SCOPE) + set(IDF_INCLUDE_DIRECTORIES ${CONFIG_DIR} PARENT_SCOPE) +endfunction() # Verify the IDF environment is configured correctly (environment, toolchain, etc) function(idf_verify_environment) - if(NOT CMAKE_PROJECT_NAME) message(FATAL_ERROR "Internal error, IDF project.cmake should have set this variable already") endif() @@ -170,77 +191,6 @@ function(idf_verify_environment) get_expected_ctng_version(expected_toolchain expected_gcc) gcc_version_check("${expected_gcc}") crosstool_version_check("${expected_toolchain}") - -endfunction() - -# idf_add_executable -# -# Calls add_executable to add the final project executable -# Adds .map & .bin file targets -# Sets up flash-related targets -function(idf_add_executable) - set(exe_target ${PROJECT_NAME}.elf) - - if(MAIN_SRCS) - spaces2list(MAIN_SRCS) - add_executable(${exe_target} ${MAIN_SRCS}) - else() - # Create a dummy file to work around CMake requirement of having a source - # file while adding an executable - add_executable(${exe_target} "${CMAKE_CURRENT_BINARY_DIR}/dummy_main_src.c") - add_custom_command(OUTPUT dummy_main_src.c - COMMAND ${CMAKE_COMMAND} -E touch dummy_main_src.c - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - VERBATIM) - - add_custom_target(dummy_main_src DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dummy_main_src.c) - - add_dependencies(${exe_target} dummy_main_src) - endif() - - add_map_file(${exe_target}) -endfunction() - - -# add_map_file -# -# Set linker args for 'exe_target' to generate a linker Map file -function(add_map_file exe_target) - get_filename_component(basename ${exe_target} NAME_WE) - set(mapfile "${basename}.map") - target_link_libraries(${exe_target} "-Wl,--gc-sections -Wl,--cref -Wl,--Map=${mapfile} -Wl,--start-group") - set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY - ADDITIONAL_MAKE_CLEAN_FILES - "${CMAKE_CURRENT_BINARY_DIR}/${mapfile}") - - # add size targets, depend on map file, run idf_size.py - add_custom_target(size - DEPENDS ${exe_target} - COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py ${mapfile} - ) - add_custom_target(size-files - DEPENDS ${exe_target} - COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py --files ${mapfile} - ) - add_custom_target(size-components - DEPENDS ${exe_target} - COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py --archives ${mapfile} - ) - -endfunction() - -# component_compile_options -# -# Wrapper around target_compile_options that passes the component name -function(component_compile_options) - target_compile_options(${COMPONENT_NAME} PRIVATE ${ARGV}) -endfunction() - -# component_compile_definitions -# -# Wrapper around target_compile_definitions that passes the component name -function(component_compile_definitions) - target_compile_definitions(${COMPONENT_NAME} PRIVATE ${ARGV}) endfunction() # idf_get_git_revision @@ -258,4 +208,47 @@ function(idf_get_git_revision) add_definitions(-DIDF_VER=\"${IDF_VER}\") git_submodule_check("${IDF_PATH}") set(IDF_VER ${IDF_VER} PARENT_SCOPE) +endfunction() + +# idf_link_components +# +# Link library components to the target +function(idf_link_components target components) + foreach(component ${components}) + component_get_target(component_target ${component}) + + # 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...) + if(TARGET ${component_target}) + get_target_property(type ${component_target} TYPE) + get_target_property(imported ${component_target} IMPORTED) + if(NOT imported) + if(${type} STREQUAL STATIC_LIBRARY OR ${type} STREQUAL EXECUTABLE) + get_target_property(link_depends "${component_target}" LINK_DEPENDS) + if(link_depends) + set_property(TARGET ${target} APPEND PROPERTY LINK_DEPENDS "${link_depends}") + endif() + endif() + endif() + + if(${type} MATCHES .+_LIBRARY) + list(APPEND libraries ${component_target}) + endif() + endif() + endforeach() + + if(libraries) + target_link_libraries(${target} "-Wl,--start-group") + target_link_libraries(${target} ${libraries}) + message(STATUS "Component libraries: ${IDF_COMPONENT_LIBRARIES}") + endif() +endfunction() + +# idf_import_components +# +# Adds ESP-IDF as a subdirectory to the current project and imports the components +function(idf_import_components var idf_path build_path) + add_subdirectory(${idf_path} ${build_path}) + set(${var} ${BUILD_COMPONENTS} PARENT_SCOPE) endfunction() \ No newline at end of file diff --git a/tools/cmake/kconfig.cmake b/tools/cmake/kconfig.cmake index b5e5d484e..cb2a5c3ca 100644 --- a/tools/cmake/kconfig.cmake +++ b/tools/cmake/kconfig.cmake @@ -1,79 +1,18 @@ include(ExternalProject) macro(kconfig_set_variables) - set(CONFIG_DIR ${CMAKE_BINARY_DIR}/config) - set_default(SDKCONFIG ${PROJECT_PATH}/sdkconfig) + set_default(IDF_SDKCONFIG_DEFAULTS "") + + set_default(CONFIG_DIR ${IDF_BUILD_ARTIFACTS_DIR}/config) + set_default(SDKCONFIG ${IDF_PROJECT_PATH}/sdkconfig) set(SDKCONFIG_HEADER ${CONFIG_DIR}/sdkconfig.h) set(SDKCONFIG_CMAKE ${CONFIG_DIR}/sdkconfig.cmake) set(SDKCONFIG_JSON ${CONFIG_DIR}/sdkconfig.json) set(KCONFIG_JSON_MENUS ${CONFIG_DIR}/kconfig_menus.json) set(ROOT_KCONFIG ${IDF_PATH}/Kconfig) - - set_default(SDKCONFIG_DEFAULTS "${SDKCONFIG}.defaults") - - # ensure all source files can include sdkconfig.h - include_directories("${CONFIG_DIR}") endmacro() -if(CMAKE_HOST_WIN32) - # Prefer a prebuilt mconf-idf on Windows - if(DEFINED ENV{MSYSTEM}) - find_program(WINPTY winpty) - else() - unset(WINPTY CACHE) # in case previous CMake run was in a tty and this one is not - endif() - find_program(MCONF mconf-idf) - - # Fall back to the old binary which was called 'mconf' not 'mconf-idf' - if(NOT MCONF) - find_program(MCONF mconf) - if(MCONF) - message(WARNING "Falling back to mconf binary '${MCONF}' not mconf-idf. " - "This is probably because an old version of IDF mconf is installed and this is fine. " - "However if there are config problems please check the Getting Started guide for your platform.") - endif() - endif() - - if(NOT MCONF) - find_program(NATIVE_GCC gcc) - if(NOT NATIVE_GCC) - message(FATAL_ERROR - "Windows requires a prebuilt mconf-idf for your platform " - "on the PATH, or an MSYS2 version of gcc on the PATH to build mconf-idf. " - "Consult the setup docs for ESP-IDF on Windows.") - endif() - elseif(WINPTY) - set(MCONF "${WINPTY}" "${MCONF}") - endif() -endif() - -if(NOT MCONF) - # Use the existing Makefile to build mconf (out of tree) when needed - # - set(MCONF kconfig_bin/mconf-idf) - - externalproject_add(mconf-idf - SOURCE_DIR ${IDF_PATH}/tools/kconfig - CONFIGURE_COMMAND "" - BINARY_DIR "kconfig_bin" - BUILD_COMMAND make -f ${IDF_PATH}/tools/kconfig/Makefile mconf-idf - BUILD_BYPRODUCTS ${MCONF} - INSTALL_COMMAND "" - EXCLUDE_FROM_ALL 1 - ) - - file(GLOB mconf_srcfiles ${IDF_PATH}/tools/kconfig/*.c) - externalproject_add_stepdependencies(mconf-idf build - ${mconf_srcfiles} - ${IDF_PATH}/tools/kconfig/Makefile - ${CMAKE_CURRENT_LIST_FILE}) - unset(mconf_srcfiles) - - set(menuconfig_depends DEPENDS mconf-idf) - -endif() - # Find all Kconfig files for all components function(kconfig_process_config) file(MAKE_DIRECTORY "${CONFIG_DIR}") @@ -95,8 +34,8 @@ function(kconfig_process_config) endif() endforeach() - if(EXISTS ${SDKCONFIG_DEFAULTS}) - set(defaults_arg --defaults "${SDKCONFIG_DEFAULTS}") + if(IDF_SDKCONFIG_DEFAULTS) + set(defaults_arg --defaults "${IDF_SDKCONFIG_DEFAULTS}") endif() if(EXISTS "${SDKCONFIG_DEFAULTS}.${IDF_TARGET}") @@ -172,3 +111,61 @@ function(kconfig_process_config) "${SDKCONFIG_HEADER}" "${SDKCONFIG_CMAKE}") endfunction() + +if(CMAKE_HOST_WIN32) + # Prefer a prebuilt mconf-idf on Windows + if(DEFINED ENV{MSYSTEM}) + find_program(WINPTY winpty) + else() + unset(WINPTY CACHE) # in case previous CMake run was in a tty and this one is not + endif() + find_program(MCONF mconf-idf) + + # Fall back to the old binary which was called 'mconf' not 'mconf-idf' + if(NOT MCONF) + find_program(MCONF mconf) + if(MCONF) + message(WARNING "Falling back to mconf binary '${MCONF}' not mconf-idf. " + "This is probably because an old version of IDF mconf is installed and this is fine. " + "However if there are config problems please check the Getting Started guide for your platform.") + endif() + endif() + + if(NOT MCONF) + find_program(NATIVE_GCC gcc) + if(NOT NATIVE_GCC) + message(FATAL_ERROR + "Windows requires a prebuilt mconf-idf for your platform " + "on the PATH, or an MSYS2 version of gcc on the PATH to build mconf-idf. " + "Consult the setup docs for ESP-IDF on Windows.") + endif() + elseif(WINPTY) + set(MCONF "${WINPTY}" "${MCONF}") + endif() +endif() + +if(NOT MCONF) + # Use the existing Makefile to build mconf (out of tree) when needed + # + set(MCONF kconfig_bin/mconf-idf) + + externalproject_add(mconf-idf + SOURCE_DIR ${IDF_PATH}/tools/kconfig + CONFIGURE_COMMAND "" + BINARY_DIR "kconfig_bin" + BUILD_COMMAND make -f ${IDF_PATH}/tools/kconfig/Makefile mconf-idf + BUILD_BYPRODUCTS ${MCONF} + INSTALL_COMMAND "" + EXCLUDE_FROM_ALL 1 + ) + + file(GLOB mconf_srcfiles ${IDF_PATH}/tools/kconfig/*.c) + externalproject_add_stepdependencies(mconf-idf build + ${mconf_srcfiles} + ${IDF_PATH}/tools/kconfig/Makefile + ${CMAKE_CURRENT_LIST_FILE}) + unset(mconf_srcfiles) + + set(menuconfig_depends DEPENDS mconf-idf) + +endif() \ No newline at end of file diff --git a/tools/cmake/ldgen.cmake b/tools/cmake/ldgen.cmake index 26ec26f16..b69ff3bfb 100644 --- a/tools/cmake/ldgen.cmake +++ b/tools/cmake/ldgen.cmake @@ -67,6 +67,8 @@ endfunction() # ldgen_create_commands # # Create the command to generate the output scripts from templates presented. -function(ldgen_add_dependencies executable_name) - add_dependencies(${executable_name} ldgen) +function(ldgen_add_dependencies) + if(IDF_PROJECT_EXECUTABLE) + add_dependencies(${IDF_PROJECT_EXECUTABLE} ldgen) + endif() endfunction() \ No newline at end of file diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index 74042fd07..e2aa7c19f 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -2,7 +2,7 @@ # cmake_minimum_required(VERSION 3.5) -# Set IDF_PATH, as nothing else will work without this +# Set IDF_PATH, as nothing else will work without this. set(IDF_PATH "$ENV{IDF_PATH}") if(NOT IDF_PATH) # Documentation says you should set IDF_PATH in your environment, but we @@ -12,177 +12,135 @@ endif() file(TO_CMAKE_PATH "${IDF_PATH}" IDF_PATH) set(ENV{IDF_PATH} ${IDF_PATH}) +# Set the path of idf.py. +set(IDFTOOL ${PYTHON} "${IDF_PATH}/tools/idf.py") -# -# Load cmake modules -# -set(CMAKE_MODULE_PATH - "${IDF_PATH}/tools/cmake" - "${IDF_PATH}/tools/cmake/third_party" - ${CMAKE_MODULE_PATH}) -include(GetGitRevisionDescription) -include(utilities) -include(components) -include(targets) -include(kconfig) -include(git_submodules) -include(idf_functions) -include(ldgen) +# Trick to temporarily redefine project(). When functions are overriden in CMake, the originals can still be accessed +# using an underscore prefixed function of the same name. The following lines make sure that __project calls +# the original project(). See https://cmake.org/pipermail/cmake/2015-October/061751.html. +function(project) +endfunction() -set_default(PYTHON "python") +function(_project) +endfunction() -if(NOT PYTHON_DEPS_CHECKED AND NOT BOOTLOADER_BUILD) - message(STATUS "Checking Python dependencies...") - execute_process(COMMAND "${PYTHON}" "${IDF_PATH}/tools/check_python_dependencies.py" - RESULT_VARIABLE result) - if(NOT result EQUAL 0) - message(FATAL_ERROR "Some Python dependencies must be installed. Check above message for details.") - endif() -endif() +include(${IDF_PATH}/tools/cmake/idf_functions.cmake) -# project -# -# This macro wraps the cmake 'project' command to add -# all of the IDF-specific functionality required -# -# Implementation Note: This macro wraps 'project' on purpose, because cmake has -# some backwards-compatible magic where if you don't call "project" in the -# top-level CMakeLists file, it will call it implicitly. However, the implicit -# project will not have CMAKE_TOOLCHAIN_FILE set and therefore tries to -# create a native build project. -# -# Therefore, to keep all the IDF "build magic", the cleanest way is to keep the -# top-level "project" call but customize it to do what we want in the IDF build. -# macro(project name) - # Determine the build target - idf_set_target() - # Set global variables used by rest of the build - idf_set_global_variables() + # Bridge existing documented variable names with library namespaced variables in order for old projects to work. + if(COMPONENT_DIRS) + spaces2list(COMPONENT_DIRS) - # Sort the components list, as it may be found via filesystem - # traversal and therefore in a non-deterministic order - list(SORT COMPONENTS) + foreach(component_dir ${COMPONENT_DIRS}) + get_filename_component(full_path ${component_dir} ABSOLUTE) + get_filename_component(idf_path "${IDF_PATH}/components" ABSOLUTE) - execute_process(COMMAND "${CMAKE_COMMAND}" - -D "COMPONENTS=${COMPONENTS}" - -D "COMPONENT_REQUIRES_COMMON=${COMPONENT_REQUIRES_COMMON}" - -D "EXCLUDE_COMPONENTS=${EXCLUDE_COMPONENTS}" - -D "TEST_COMPONENTS=${TEST_COMPONENTS}" - -D "TEST_EXCLUDE_COMPONENTS=${TEST_EXCLUDE_COMPONENTS}" - -D "TESTS_ALL=${TESTS_ALL}" - -D "DEPENDENCIES_FILE=${CMAKE_BINARY_DIR}/component_depends.cmake" - -D "COMPONENT_DIRS=${COMPONENT_DIRS}" - -D "BOOTLOADER_BUILD=${BOOTLOADER_BUILD}" - -D "IDF_PATH=${IDF_PATH}" - -D "IDF_TARGET=${IDF_TARGET}" - -D "DEBUG=${DEBUG}" - -P "${IDF_PATH}/tools/cmake/scripts/expand_requirements.cmake" - WORKING_DIRECTORY "${PROJECT_PATH}") - 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 ";" " " BUILD_COMPONENTS_SPACES "${BUILD_COMPONENTS}") - message(STATUS "Component names: ${BUILD_COMPONENTS_SPACES}") - unset(BUILD_COMPONENTS_SPACES) - message(STATUS "Component paths: ${BUILD_COMPONENT_PATHS}") - - # Print list of test components - if(TESTS_ALL EQUAL 1 OR TEST_COMPONENTS) - string(REPLACE ";" " " BUILD_TEST_COMPONENTS_SPACES "${BUILD_TEST_COMPONENTS}") - message(STATUS "Test component names: ${BUILD_TEST_COMPONENTS_SPACES}") - unset(BUILD_TEST_COMPONENTS_SPACES) - message(STATUS "Test component paths: ${BUILD_TEST_COMPONENT_PATHS}") + if(NOT full_path STREQUAL idf_path) + set(IDF_EXTRA_COMPONENT_DIRS "${IDF_EXTRA_COMPONENT_DIRS} ${component_dir}") + endif() + endforeach() + else() + if(MAIN_SRCS) + set(IDF_EXTRA_COMPONENT_DIRS "${EXTRA_COMPONENT_DIRS} ${CMAKE_SOURCE_DIR}/components") + else() + set(IDF_EXTRA_COMPONENT_DIRS "${EXTRA_COMPONENT_DIRS} \ + ${CMAKE_SOURCE_DIR}/components ${CMAKE_SOURCE_DIR}/main") + endif() endif() - kconfig_set_variables() + if(COMPONENTS) + set(IDF_COMPONENTS "${COMPONENTS}") + endif() - kconfig_process_config() + if(COMPONENT_REQUIRES_COMMON) + set(IDF_COMPONENT_REQUIRES_COMMON "${COMPONENT_REQUIRES_COMMON}") + endif() - # Include sdkconfig.cmake so rest of the build knows the configuration - include(${SDKCONFIG_CMAKE}) + if(EXCLUDE_COMPONENTS) + set(IDF_EXCLUDE_COMPONENTS "${COMPONENT_EXCLUDES}") + endif() - # Check that the targets set in cache, sdkconfig, and in environment all match - idf_check_config_target() + if(TESTS_ALL EQUAL 1 OR TEST_COMPONENTS) + set(IDF_BUILD_TESTS 1) + endif() + + if(TEST_COMPONENTS) + set(IDF_TEST_COMPONENTS "${TEST_COMPONENTS}") + endif() + + if(TEST_EXCLUDE_COMPONENTS) + set(IDF_TEST_EXCLUDE_COMPONENTS "${TEST_EXCLUDE_COMPONENTS}") + endif() + + if(NOT SDKCONFIG_DEFAULTS) + if(EXISTS ${CMAKE_SOURCE_DIR}/sdkconfig.defaults) + set(IDF_SDKCONFIG_DEFAULTS ${CMAKE_SOURCE_DIR}/sdkconfig.defaults) + endif() + else() + set(IDF_SDKCONFIG_DEFAULTS ${SDKCONFIG_DEFAULTS}) + endif() + + # Set build variables + idf_set_variables() # Now the configuration is loaded, set the toolchain appropriately idf_set_toolchain() - # Declare the actual cmake-level project - _project(${name} ASM C CXX) + __project(${name} C CXX ASM) - # generate compile_commands.json (needs to come after project) - set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + set(IDF_BUILD_ARTIFACTS ON) + set(IDF_PROJECT_EXECUTABLE ${CMAKE_PROJECT_NAME}.elf) + set(IDF_BUILD_ARTIFACTS_DIR ${CMAKE_BINARY_DIR}) - # Verify the environment is configured correctly - idf_verify_environment() + if(MAIN_SRCS) + spaces2list(MAIN_SRCS) + add_executable(${IDF_PROJECT_EXECUTABLE} ${MAIN_SRCS}) + else() + # Create a dummy file to work around CMake requirement of having a source + # file while adding an executable + add_executable(${IDF_PROJECT_EXECUTABLE} "${CMAKE_CURRENT_BINARY_DIR}/dummy_main_src.c") + add_custom_command(OUTPUT dummy_main_src.c + COMMAND ${CMAKE_COMMAND} -E touch dummy_main_src.c + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + VERBATIM) - # Add some idf-wide definitions - idf_set_global_compiler_options() + add_custom_target(dummy_main_src DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dummy_main_src.c) - # Check git revision (may trigger reruns of cmake) - ## sets IDF_VER to IDF git revision - idf_get_git_revision() - ## if project uses git, retrieve revision - git_describe(PROJECT_VER "${CMAKE_CURRENT_SOURCE_DIR}") + add_dependencies(${IDF_PROJECT_EXECUTABLE} dummy_main_src) + endif() - # - # Add the app executable to the build (has name of PROJECT.elf) - # - idf_add_executable() + set(mapfile "${CMAKE_PROJECT_NAME}.map") - # - # Setup variables for linker script generation - # - ldgen_set_variables() + target_link_libraries(${IDF_PROJECT_EXECUTABLE} "-Wl,--gc-sections \ + -Wl,--cref -Wl,--Map=${mapfile}") - # Include any top-level project_include.cmake files from components - foreach(component ${BUILD_COMPONENT_PATHS}) - set(COMPONENT_PATH "${component}") - include_if_exists("${component}/project_include.cmake") - unset(COMPONENT_PATH) - endforeach() + set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES + "${CMAKE_CURRENT_BINARY_DIR}/${mapfile}") - # - # Add each component to the build as a library - # - foreach(COMPONENT_PATH ${BUILD_COMPONENT_PATHS}) - list(FIND BUILD_TEST_COMPONENT_PATHS ${COMPONENT_PATH} idx) + # Add size targets, depend on map file, run idf_size.py + add_custom_target(size + DEPENDS ${exe_target} + COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py ${mapfile} + ) + add_custom_target(size-files + DEPENDS ${exe_target} + COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py --files ${mapfile} + ) + add_custom_target(size-components + DEPENDS ${exe_target} + COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py --archives ${mapfile} + ) - if(NOT idx EQUAL -1) - list(GET BUILD_TEST_COMPONENTS ${idx} test_component) - set(COMPONENT_NAME ${test_component}) - else() - get_filename_component(COMPONENT_NAME ${COMPONENT_PATH} NAME) - endif() - - add_subdirectory(${COMPONENT_PATH} ${COMPONENT_NAME}) - endforeach() - unset(COMPONENT_NAME) - unset(COMPONENT_PATH) - - # At this point the fragment files have been collected, generate - # the commands needed to generate the output linker scripts - ldgen_add_dependencies(${PROJECT_NAME}.elf) - - # Write project description JSON file - make_json_list("${BUILD_COMPONENTS}" build_components_json) - make_json_list("${BUILD_COMPONENT_PATHS}" build_component_paths_json) - configure_file("${IDF_PATH}/tools/cmake/project_description.json.in" - "${CMAKE_BINARY_DIR}/project_description.json") - unset(build_components_json) - unset(build_component_paths_json) - - # - # Finish component registration (add cross-dependencies, make - # executable dependent on all components) - # - components_finish_registration() + # Since components can import third-party libraries, the original definition of project() should be restored + # before the call to add components to the build. + function(project) + set(project_ARGV ARGV) + __project(${${project_ARGV}}) + endfunction() + # Finally, add the rest of the components to the build. + idf_import_components(components $ENV{IDF_PATH} esp-idf) + idf_link_components(${IDF_PROJECT_EXECUTABLE} "${components}") endmacro() diff --git a/tools/cmake/project_description.json.in b/tools/cmake/project_description.json.in index 878dce3b3..55c3fb97d 100644 --- a/tools/cmake/project_description.json.in +++ b/tools/cmake/project_description.json.in @@ -1,11 +1,11 @@ { - "project_name": "${PROJECT_NAME}", - "project_path": "${PROJECT_PATH}", - "build_dir": "${CMAKE_BINARY_DIR}", + "project_name": "${IDF_PROJECT_NAME}", + "project_path": "${IDF_PROJECT_PATH}", + "build_dir": "${IDF_BUILD_ARTIFACTS_DIR}", "config_file": "${SDKCONFIG}", - "config_defaults": "${SDKCONFIG_DEFAULTS}", - "app_elf": "${PROJECT_NAME}.elf", - "app_bin": "${PROJECT_NAME}.bin", + "config_defaults": "${IDF_SDKCONFIG_DEFAULTS}", + "app_elf": "${IDF_PROJECT_EXECUTABLE}", + "app_bin": "${IDF_PROJECT_BIN}", "git_revision": "${IDF_VER}", "phy_data_partition": "${CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION}", "monitor_baud" : "${CONFIG_MONITOR_BAUD}", diff --git a/tools/cmake/scripts/expand_requirements.cmake b/tools/cmake/scripts/expand_requirements.cmake index 55e293bdd..bcfa76aa4 100644 --- a/tools/cmake/scripts/expand_requirements.cmake +++ b/tools/cmake/scripts/expand_requirements.cmake @@ -1,4 +1,4 @@ -# expand_requires.cmake is a utility cmake script to expand component requirements early in the build, +# expand_requirements.cmake is a utility cmake script to expand component requirements early in the build, # before the components are ready to be included. # # Parameters: @@ -44,12 +44,6 @@ spaces2list(COMPONENT_DIRS) spaces2list(COMPONENT_REQUIRES_COMMON) -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, @@ -85,10 +79,6 @@ function(require_idf_targets) endif() endfunction() -# Dummy call for ldgen_add_fragment_file -function(ldgen_add_fragment_file files) -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, @@ -160,15 +150,15 @@ macro(filter_components_list) endif() else() set(add_component 1) - endif() if(NOT ${component} IN_LIST EXCLUDE_COMPONENTS AND add_component EQUAL 1) list(APPEND components ${component}) list(APPEND component_paths ${component_path}) - if(TESTS_ALL EQUAL 1 OR TEST_COMPONENTS) - if(NOT TESTS_ALL EQUAL 1 AND TEST_COMPONENTS) + if(BUILD_TESTS EQUAL 1) + + if(TEST_COMPONENTS) if(${component} IN_LIST TEST_COMPONENTS) set(add_test_component 1) else() diff --git a/tools/cmake/targets.cmake b/tools/cmake/targets.cmake index 95f7d5e10..2092985a8 100644 --- a/tools/cmake/targets.cmake +++ b/tools/cmake/targets.cmake @@ -45,7 +45,8 @@ macro(idf_set_toolchain) set(CMAKE_TOOLCHAIN_FILE ${toolchain_file_global}) else() # Try to load the toolchain file from the directory of ${IDF_TARGET} component - find_component_path(${IDF_TARGET} "${BUILD_COMPONENTS}" "${BUILD_COMPONENT_PATHS}" target_component_path) + components_find_all("${IDF_COMPONENT_DIRS}" ALL_COMPONENT_PATHS ALL_COMPONENTS ALL_TEST_COMPONENTS) + find_component_path(${IDF_TARGET} "${ALL_COMPONENTS}" "${ALL_COMPONENT_PATHS}" target_component_path) set(toolchain_file_component ${target_component_path}/toolchain-${IDF_TARGET}.cmake) if(EXISTS ${toolchain_file_component}) set(CMAKE_TOOLCHAIN_FILE ${toolchain_file_component}) diff --git a/tools/cmake/utilities.cmake b/tools/cmake/utilities.cmake index 8abeef89a..9e7019f0e 100644 --- a/tools/cmake/utilities.cmake +++ b/tools/cmake/utilities.cmake @@ -105,7 +105,7 @@ function(target_add_binary_data target embed_file embed_type) get_filename_component(embed_file "${embed_file}" ABSOLUTE) get_filename_component(name "${embed_file}" NAME) - set(embed_srcfile "${CMAKE_BINARY_DIR}/${name}.S") + set(embed_srcfile "${IDF_BUILD_ARTIFACTS_DIR}/${name}.S") add_custom_command(OUTPUT "${embed_srcfile}" COMMAND "${CMAKE_COMMAND}" @@ -115,7 +115,7 @@ function(target_add_binary_data target embed_file embed_type) -P "${IDF_PATH}/tools/cmake/scripts/data_file_embed_asm.cmake" MAIN_DEPENDENCY "${embed_file}" DEPENDS "${IDF_PATH}/tools/cmake/scripts/data_file_embed_asm.cmake" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" + WORKING_DIRECTORY "${IDF_BUILD_ARTIFACTS_DIR}" VERBATIM) set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${embed_srcfile}")