Merge branch 'feature/generic_cmake_support' into 'master'

Generic CMake Support

See merge request idf/esp-idf!3543
This commit is contained in:
Angus Gratton 2018-11-28 10:42:47 +08:00
commit 6f8e2b018f
70 changed files with 1203 additions and 727 deletions

View file

@ -33,6 +33,7 @@ exclude =
components/mbedtls/mbedtls,
components/expat/expat,
components/unity/unity,
examples/build_system/cmake/import_lib/main/lib/tinyxml2
# temporary list (should be empty)
components/app_update/dump_otadata.py,
components/app_update/gen_empty_partition.py,

3
.gitignore vendored
View file

@ -71,3 +71,6 @@ test_multi_heap_host
# Results for the checking of the Python coding style
flake8_output.txt
# ESP-IDF library
build

5
.gitmodules vendored
View file

@ -61,6 +61,11 @@
[submodule "components/protobuf-c/protobuf-c"]
path = components/protobuf-c/protobuf-c
url = https://github.com/protobuf-c/protobuf-c
[submodule "components/unity/unity"]
path = components/unity/unity
url = https://github.com/ThrowTheSwitch/Unity
[submodule "examples/build_system/cmake/import_lib/main/lib/tinyxml2"]
path = examples/build_system/cmake/import_lib/main/lib/tinyxml2
url = https://github.com/leethomason/tinyxml2

153
CMakeLists.txt Normal file
View file

@ -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()

View file

@ -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)

View file

@ -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()

View file

@ -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()

View file

@ -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"

View file

@ -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)

View file

@ -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()

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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)

View file

@ -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"
)

View file

@ -1 +1 @@
${APP_PARTITION_OFFSET} ${PROJECT_NAME}.bin
${APP_PARTITION_OFFSET} ${IDF_PROJECT_BIN}

View file

@ -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}

View file

@ -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}"

View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -1,101 +1,57 @@
set(COMPONENT_ADD_INCLUDEDIRS port/include mbedtls/include)
set(COMPONENT_SRCS "mbedtls/library/aes.c"
"mbedtls/library/aesni.c"
"mbedtls/library/arc4.c"
"mbedtls/library/aria.c"
"mbedtls/library/asn1parse.c"
"mbedtls/library/asn1write.c"
"mbedtls/library/base64.c"
"mbedtls/library/bignum.c"
"mbedtls/library/blowfish.c"
"mbedtls/library/camellia.c"
"mbedtls/library/ccm.c"
"mbedtls/library/certs.c"
"mbedtls/library/chacha20.c"
"mbedtls/library/chachapoly.c"
"mbedtls/library/cipher.c"
"mbedtls/library/cipher_wrap.c"
"mbedtls/library/cmac.c"
"mbedtls/library/ctr_drbg.c"
"mbedtls/library/debug.c"
"mbedtls/library/des.c"
"mbedtls/library/dhm.c"
"mbedtls/library/ecdh.c"
"mbedtls/library/ecdsa.c"
"mbedtls/library/ecjpake.c"
"mbedtls/library/ecp.c"
"mbedtls/library/ecp_curves.c"
"mbedtls/library/entropy.c"
"mbedtls/library/entropy_poll.c"
"mbedtls/library/error.c"
"mbedtls/library/gcm.c"
"mbedtls/library/havege.c"
"mbedtls/library/hkdf.c"
"mbedtls/library/hmac_drbg.c"
"mbedtls/library/md.c"
"mbedtls/library/md2.c"
"mbedtls/library/md4.c"
"mbedtls/library/md5.c"
"mbedtls/library/md_wrap.c"
"mbedtls/library/memory_buffer_alloc.c"
"mbedtls/library/net_sockets.c"
"mbedtls/library/nist_kw.c"
"mbedtls/library/oid.c"
"mbedtls/library/padlock.c"
"mbedtls/library/pem.c"
"mbedtls/library/pk.c"
"mbedtls/library/pk_wrap.c"
"mbedtls/library/pkcs11.c"
"mbedtls/library/pkcs12.c"
"mbedtls/library/pkcs5.c"
"mbedtls/library/pkparse.c"
"mbedtls/library/pkwrite.c"
"mbedtls/library/platform.c"
"mbedtls/library/platform_util.c"
"mbedtls/library/poly1305.c"
"mbedtls/library/ripemd160.c"
"mbedtls/library/rsa.c"
"mbedtls/library/rsa_internal.c"
"mbedtls/library/sha1.c"
"mbedtls/library/sha256.c"
"mbedtls/library/sha512.c"
"mbedtls/library/ssl_cache.c"
"mbedtls/library/ssl_ciphersuites.c"
"mbedtls/library/ssl_cli.c"
"mbedtls/library/ssl_cookie.c"
"mbedtls/library/ssl_srv.c"
"mbedtls/library/ssl_ticket.c"
"mbedtls/library/ssl_tls.c"
"mbedtls/library/threading.c"
"mbedtls/library/timing.c"
"mbedtls/library/version.c"
"mbedtls/library/version_features.c"
"mbedtls/library/x509.c"
"mbedtls/library/x509_create.c"
"mbedtls/library/x509_crl.c"
"mbedtls/library/x509_crt.c"
"mbedtls/library/x509_csr.c"
"mbedtls/library/x509write_crt.c"
"mbedtls/library/x509write_csr.c"
"mbedtls/library/xtea.c"
"port/esp_bignum.c"
"port/esp_hardware.c"
"port/esp_mem.c"
"port/esp_sha1.c"
"port/esp_sha256.c"
"port/esp_sha512.c"
"port/mbedtls_debug.c"
"port/net_sockets.c")
set(COMPONENT_ADD_INCLUDEDIRS "port/include" "mbedtls/include")
set(COMPONENT_SRCS "mbedtls.c")
set(COMPONENT_REQUIRES lwip)
register_component()
target_compile_definitions(mbedtls PUBLIC
-DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h"
)
# Only build mbedtls libraries
set(ENABLE_TESTING CACHE BOOL OFF)
set(ENABLE_PROGRAMS CACHE BOOL OFF)
# Use same policy between IDF and mbedtls build
function(project)
set(_args ARGV)
_project(${${_args}})
cmake_policy(SET CMP0022 NEW)
endfunction()
# Needed to for include_next includes to work from within mbedtls
include_directories("${COMPONENT_PATH}/port/include")
# Import mbedtls library targets
add_subdirectory(mbedtls)
set(mbedtls_targets mbedtls mbedcrypto mbedx509)
# Add port files to mbedtls targets
target_sources(mbedtls PRIVATE "${COMPONENT_PATH}/port/esp_bignum.c"
"${COMPONENT_PATH}/port/esp_hardware.c"
"${COMPONENT_PATH}/port/esp_mem.c"
"${COMPONENT_PATH}/port/esp_sha1.c"
"${COMPONENT_PATH}/port/esp_sha256.c"
"${COMPONENT_PATH}/port/esp_sha512.c"
"${COMPONENT_PATH}/port/mbedtls_debug.c"
"${COMPONENT_PATH}/port/net_sockets.c")
foreach(target ${mbedtls_targets})
# Propagate compile options to mbedtls library targets
target_include_directories(${target} PRIVATE "${IDF_INCLUDE_DIRECTORIES}")
target_compile_options(${target} PRIVATE "${IDF_COMPILE_OPTIONS};${IDF_C_COMPILE_OPTIONS}")
target_compile_definitions(${target} PRIVATE "${IDF_COMPILE_DEFINITIONS}")
target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h")
# The mbedtls targets also depends on core components
foreach(common ${IDF_COMPONENT_REQUIRES_COMMON})
component_get_target(common_target ${common})
set_property(TARGET ${target} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${common_target})
set_property(TARGET ${target} APPEND PROPERTY LINK_LIBRARIES ${common_target})
endforeach()
endforeach()
# Link mbedtls libraries to component library
target_link_libraries(${COMPONENT_TARGET} ${mbedtls_targets})
# Catch usage of deprecated mbedTLS functions when building tests
if(mbedtls_test IN_LIST BUILD_TEST_COMPONENTS)
add_definitions(-DMBEDTLS_DEPRECATED_WARNING)
endif()
endif()

View file

@ -0,0 +1 @@
// Empty file

View file

@ -27,7 +27,6 @@
#include <assert.h>
#include <stdlib.h>
#include <sys/param.h>
#include "mbedtls/bignum.h"
#include "rom/bigint.h"
#include "soc/hwcrypto_reg.h"
#include "esp_system.h"
@ -36,6 +35,8 @@
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#include <mbedtls/bignum.h>
#include "soc/dport_reg.h"
#include "freertos/FreeRTOS.h"

View file

@ -9,6 +9,8 @@
#include <stdio.h>
#include <esp_system.h>
#include "mbedtls/entropy_poll.h"
#ifndef MBEDTLS_ENTROPY_HARDWARE_ALT
#error "MBEDTLS_ENTROPY_HARDWARE_ALT should always be set in ESP-IDF"
#endif

View file

@ -15,6 +15,7 @@
#include <esp_attr.h>
#include <esp_heap_caps.h>
#include <sdkconfig.h>
#include "esp_mem.h"
#ifndef CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC

View file

@ -20,6 +20,7 @@
#include "mbedtls/ssl.h"
#include "mbedtls/esp_debug.h"
#ifdef CONFIG_MBEDTLS_DEBUG
static const char *TAG = "mbedtls";
static void mbedtls_esp_debug(void *ctx, int level,
@ -28,9 +29,9 @@ static void mbedtls_esp_debug(void *ctx, int level,
void mbedtls_esp_enable_debug_log(mbedtls_ssl_config *conf, int threshold)
{
esp_log_level_t level = ESP_LOG_NONE;
mbedtls_debug_set_threshold(threshold);
mbedtls_ssl_conf_dbg(conf, mbedtls_esp_debug, NULL);
esp_log_level_t level = ESP_LOG_NONE;
switch(threshold) {
case 1:
level = ESP_LOG_WARN;
@ -53,6 +54,7 @@ void mbedtls_esp_disable_debug_log(mbedtls_ssl_config *conf)
mbedtls_ssl_conf_dbg(conf, NULL, NULL);
}
/* Default mbedtls debug function that translates mbedTLS debug output
to ESP_LOGx debug output.
*/
@ -89,3 +91,4 @@ static void mbedtls_esp_debug(void *ctx, int level,
break;
}
}
#endif

View file

@ -131,6 +131,10 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
{
int ret;
struct addrinfo hints, *addr_list, *cur;
struct sockaddr_in *serv_addr = NULL;
#if SO_REUSE
int n = 1;
#endif
if ( ( ret = net_prepare() ) != 0 ) {
return ( ret );
@ -157,7 +161,6 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
/*SO_REUSEADDR option dafault is disable in source code(lwip)*/
#if SO_REUSE
int n = 1;
if ( setsockopt( fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &n, sizeof( n ) ) != 0 ) {
close( fd );
@ -166,7 +169,6 @@ int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char
}
#endif
/*bind interface dafault don't process the addr is 0xffffffff for TCP Protocol*/
struct sockaddr_in *serv_addr = NULL;
serv_addr = (struct sockaddr_in *)cur->ai_addr;
serv_addr->sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
if ( bind( fd, (struct sockaddr *)serv_addr, cur->ai_addrlen ) != 0 ) {

View file

@ -3,4 +3,4 @@ set(COMPONENT_ADD_INCLUDEDIRS ".")
set(COMPONENT_REQUIRES unity test_utils mbedtls)
register_component()
register_component()

View file

@ -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)

View file

@ -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()

View file

@ -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:

View file

@ -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")

View file

@ -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=$<TARGET_PROPERTY:${COMPONENT_NAME},INTERFACE_INCLUDE_DIRECTORIES>
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
-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()

View file

@ -14,7 +14,7 @@ endif()
register_component()
target_compile_definitions(unity PUBLIC
target_compile_definitions(${COMPONENT_TARGET} PUBLIC
-DUNITY_INCLUDE_CONFIG_H
)

View file

@ -313,6 +313,7 @@ The following component-specific variables are available for use inside componen
- ``COMPONENT_PATH``: The component directory. Evaluates to the absolute path of the directory containing ``component.mk``. The component path cannot contain spaces. This is the same as the ``CMAKE_CURRENT_SOURCE_DIR`` variable.
- ``COMPONENT_NAME``: Name of the component. Same as the name of the component directory.
- ``COMPONENT_TARGET``: Name of the library target created internally by the build system for the component.
The following variables are set at the project level, but available for use in component CMakeLists:
@ -637,7 +638,7 @@ file called graphics_lib.c::
VERBATIM)
add_custom_target(logo DEPENDS logo.h)
add_dependencies(${COMPONENT_NAME} logo)
add_dependencies(${COMPONENT_TARGET} logo)
set_property(DIRECTORY "${COMPONENT_PATH}" APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES logo.h)
@ -652,7 +653,7 @@ it is added to the `ADDITIONAL_MAKE_CLEAN_FILES`_ property.
.. note::
If generating files as part of the project CMakeLists.txt file, not a component CMakeLists.txt, then use ``${PROJECT_PATH}`` instead of ``${COMPONENT_PATH}`` and ``${PROJECT_NAME}.elf`` instead of ``${COMPONENT_NAME}``.)
If generating files as part of the project CMakeLists.txt file, not a component CMakeLists.txt, then use ``${PROJECT_PATH}`` instead of ``${COMPONENT_PATH}`` and ``${PROJECT_NAME}.elf`` instead of ``${COMPONENT_TARGET}``.)
If a a source file from another component included ``logo.h``, then ``add_dependencies`` would need to be called to add a dependency between
the two components, to ensure that the component source files were always compiled in the correct order.
@ -838,6 +839,96 @@ Here is an example minimal "pure CMake" component CMakeLists file for a componen
- This file is quite simple as there are not a lot of source files. For components with a large number of files, the globbing behaviour of ESP-IDF's component logic can make the component CMakeLists style simpler.)
- Any time a component adds a library target with the component name, the ESP-IDF build system will automatically add this to the build, expose public include directories, etc. If a component wants to add a library target with a different name, dependencies will need to be added manually via CMake commands.
Using Third-Party CMake Projects with Components
================================================
CMake is used for a lot of open-source C and C++ projects — code that users can tap into for their applications. One of the benefits of having a CMake build system
is the ability to import these third-party projects, sometimes even without modification! This allows for users to be able to get functionality that may
not yet be provided by a component, or use another library for the same functionality.
.. highlight:: cmake
Importing a library might look like this for a hypothetical library ``foo`` to be used in the ``main`` component::
# Register the component
register_component()
# Set values of hypothetical variables that control the build of `foo`
set(FOO_BUILD_STATIC OFF)
set(FOO_BUILD_TESTS OFF)
# Create and import the library targets
add_subdirectory(foo)
# Propagate IDF-wide compile settings/definitions/options to `foo`
target_include_directories(foo ${IDF_INCLUDE_DIRECTORIES})
target_compile_options(foo ${IDF_COMPILE_OPTIONS})
target_compile_definitions(foo ${IDF_COMPILE_DEFINITIONS})
# Link `foo` to `main` component
target_link_libraries(main 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
import it from other projects. Studying the library's CMakeLists.txt and build structure can also be helpful.
It is also possible to wrap a third-party library to be used as a component in this manner. For example, the :component:`mbedtls` component is a wrapper for
Espressif's fork of `mbedtls <https://github.com/ARMmbed/mbedtls>`_. See its :component_file:`component CMakeLists.txt <mbedtls/CMakeLists.txt>`.
Using ESP-IDF in Custom CMake Projects
======================================
ESP-IDF provides a template CMake project for easily creating an application. However, in some instances the user might already
have an existing CMake project or may want to create one. In these cases it is desirable to be able to consume IDF components
as libraries to be linked to the user's targets (libraries/ executables).
.. highlight:: cmake
It is possible to do so by using functions ``idf_import_components``
and ``idf_link_components`` provided provided by :idf_file:`tools/cmake/idf_functions.cmake`. For example::
cmake_minimum_required(VERSION 3.5)
project(my_custom_app C)
# The source file main.c contains app_main() definition
add_executable(${CMAKE_PROJECT_NAME}.elf main.c)
# Provides idf_import_components and idf_link_components
include($ENV{IDF_PATH}/tools/cmake/idf_functions.cmake)
# Do some configuration for idf_import_components. This enables creation of artifacts (which might not be
# needed) for some projects
set(IDF_BUILD_ARTIFACTS ON)
set(IDF_PROJECT_EXECUTABLE ${CMAKE_PROJECT_NAME}.elf)
set(IDF_BUILD_ARTIFACTS_DIR ${CMAKE_BINARY_DIR})
# Wraps add_subdirectory() to create library targets for components, and then `return` them using the given variable.
# In this case the variable is named `component`
idf_import_components(components $ENV{IDF_PATH} esp-idf)
# Wraps target_link_libraries() to link processed components by idf_import_components to target
idf_link_components(${CMAKE_PROJECT_NAME}.elf "${components}")
The snippet above includes all of the components in the ESP-IDF directory and uses KConfig defaults.
It also builds artifacts (partition table, project information json files, bootloader, etc.). There are also other build
parameters which can be set, the full list of which is as follows:
- ``IDF_BUILD_ARTIFACTS``: Build artifacts such as bootloader, partition table binary file, partition binaries, project information json typically needed for flashing binaries to the target chip. Requires ``IDF_PROJECT_EXECUTABLE`` and ``IDF_BUILD_ARTIFACTS_DIR`` to be set as well.
- ``IDF_PROJECT_EXECUTABLE``: Name of the final executable file. This parameter is needed for creating some of the artifacts.
- ``IDF_BUILD_ARTIFACTS_DIR``: Location where created artifacts are to be placed.
- ``IDF_EXTRA_COMPONENTS_DIR``: Locations to search for components in aside from the :idf:`default components directory <components>`
- ``IDF_COMPONENTS``: A list of components to import. Use this to trim down the imported components to only what is needed for faster builds. If not set, all components found from the default components directory as well as ``IDF_EXTRA_COMPONENTS_DIR`` (if specified) are imported. Note that dependencies of components in this list (other than ``IDF_COMPONENT_REQUIRES_COMMON``) will also get pulled into the build.
- ``IDF_COMPONENT_REQUIRES_COMMON``: List of components that every component requires. Components in this list (and their dependencies) are imported regardless of the value of ``IDF_COMPONENTS``. By default, this variable is set to the minimal set of core "system" components.
- ``IDF_SDKCONFIG_DEFAULTS``: Path to the configuration override file. If unset, components are built with default configurations.
- ``IDF_BUILD_TESTS``: Include component tests in the build. By default, all component tests are included. The component tests are filtered using ``IDF_TEST_COMPONENTS`` and ``IDF_TEST_EXCLUDE_COMPONENTS``.
- ``IDF_TEST_COMPONENTS``: If ``IDF_BUILD_TESTS`` is set, only component tests in this list will be included in the build. Ignored if ``IDF_BUILD_TESTS`` is not set.
- ``IDF_TEST_EXCLUDE_COMPONENTS``: If ``IDF_BUILD_TESTS`` is set, component tests in this list will not be included in the build. Ignored if ``IDF_BUILD_TESTS`` is not set. This variable takes precedence over ``IDF_TEST_COMPONENTS``. This means that a component test in this list will not be included in the build even if it is also present in ``IDF_TEST_COMPONENTS``.
The example in :example:`build_system/cmake/idf_as_lib` demonstrates the creation of an application equivalent to :example:`hello world application <get-started/hello_world>`
using a custom CMake project.
.. _cmake-file-globbing:
File Globbing & Incremental Builds

View file

@ -15,6 +15,7 @@ The examples are grouped into subdirectories by category. Each category director
* `storage` contains examples showing data storage methods using SPI flash or external storage like the SD/MMC interface.
* `system` contains examples which demonstrate some internal chip features, or debugging & development tools.
* `wifi` contains examples of advanced Wi-Fi features. (For network protocol examples, see `protocols` instead.)
* `build_system` contains examples of build system features
# Using Examples

View file

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.5)
project(idf_as_lib C)
# The source file main.c contains app_main() definition
add_executable(${CMAKE_PROJECT_NAME}.elf main.c)
# Provides idf_import_components() and idf_link_components()
include($ENV{IDF_PATH}/tools/cmake/idf_functions.cmake)
# Create artifacts used for flashing the project to target chip
set(IDF_BUILD_ARTIFACTS ON)
set(IDF_PROJECT_EXECUTABLE ${CMAKE_PROJECT_NAME}.elf)
set(IDF_BUILD_ARTIFACTS_DIR ${CMAKE_BINARY_DIR})
# Trim down components included in the build. Although freertos and spi_flash are the ones needed by the application
# itself, the bootloader and esptool_py components are also needed in order to create the artifacts to be used
# for flashing to the target chip
set(IDF_COMPONENTS freertos spi_flash bootloader esptool_py)
# Wraps add_subdirectory() to create library targets for components, and then return them using the specified variable
idf_import_components(components $ENV{IDF_PATH} esp-idf)
# Wraps target_link_libraries() to link processed components by idf_import_components to target
idf_link_components(${CMAKE_PROJECT_NAME}.elf "${components}")

View file

@ -0,0 +1,69 @@
# Using ESP-IDF in Custom CMake Projects
This example illustrates using ESP-IDF components as libraries in custom CMake projects. This builds
an equivalent application to the `hello_world` example under `examples/get-started/hello_world`.
## Example Flow
Users looking at this example should focus on the [top-level CMakeLists.txt file](./CMakeLists.txt). This builds an
application that can run on targets without relying on the typical ESP-IDF application template. The application itself
follows a similar code flow to the aforementioned `hello_world` example.
### Output
```
Hello world!
This is ESP32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 0, 4MB external flash
Restarting in 10 seconds...
Restarting in 9 seconds...
Restarting in 8 seconds...
Restarting in 7 seconds...
Restarting in 6 seconds...
Restarting in 5 seconds...
Restarting in 4 seconds...
Restarting in 3 seconds...
Restarting in 2 seconds...
Restarting in 1 seconds...
Restarting in 0 seconds...
```
## Building this Example
To build this example, run the following commands from this directory:
```bash
# Create a build directory, and change location to that directory.
mkdir build; cd build
# Invoke CMake, specifying the top-level CMakeLists.txt directory and toolchain file to use. This will generate
# the build system files.
cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DIDF_TARGET=esp32
# Build using the generated build system files.
cmake --build .
```
Or, execute `build.sh` script, which contains the same commands mentioned above.
## Flashing and Running this Example
To flash this example, we will have to invoke `esptool.py` and `idf_monitor.py` manually. While still in the build directory:
### Flashing to target
```bash
# Write project binaries to flash.
esptool.py --port /dev/ttyUSB0 write_flash @flash_project_args
```
### Running on target
```bash
# Monitor the output of the flashed firmware.
idf_monitor.py --port /dev/ttyUSB0 idf_as_lib.elf
```
Of course, you should replace the specified ports in the commands specified above to the proper one where your device
is connected.
---
There is a discussion on using ESP-IDF in custom CMake projects in the programming guide under `API Guides` -> `Build System (CMake)` -> `Using ESP-IDF in Custom CMake Projects`

View file

@ -0,0 +1,8 @@
#!/bin/bash
#
# Build this example, which does not use that standard IDF app template. See README.md for
# more information about the build and how to run this example on the target once built.
mkdir build; cd build
cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DIDF_TARGET=esp32
cmake --build .

View file

@ -0,0 +1,39 @@
/* Hello World Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
void app_main()
{
printf("Hello world!\n");
/* Print chip information */
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
printf("This is ESP32 chip with %d CPU cores, WiFi%s%s, ",
chip_info.cores,
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
printf("silicon revision %d, ", chip_info.revision);
printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
for (int i = 10; i >= 0; i--) {
printf("Restarting in %d seconds...\n", i);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
printf("Restarting now.\n");
fflush(stdout);
esp_restart();
}

View file

@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(import_cmake_lib)

View file

@ -0,0 +1,36 @@
# Import Third-Party CMake Library Example
This example demonstrates how to import third-party CMake libraries.
## Example Flow
[tinyxml2](https://github.com/leethomason/tinyxml2) is a
a small C++ XML parser. It is imported, without modification, for use in the project's `main` component (see the `main` component's [CMakeLists.txt](main/CMakeLists.txt)). To demonstrate the library being used, a sample XML is embedded into the project.
This sample XML is then read and parsed later on using `tinyxml2`.
### Output
```
I (317) example: Setting up...
I (317) example: Copying sample XML to filesystem...
I (647) example: Reading XML file
I (657) example: Read XML data:
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
I (667) example: Parsed XML data:
To: Tove
From: Jani
Heading: Reminder
Body: Don't forget me this weekend!
I (677) example: Example end
```
---
There is a discussion on importing third-party CMake libraries in the programming guide under `API Guides` -> `Build System (CMake)` -> `Using Third-Party CMake Projects with Components`

View file

@ -0,0 +1,21 @@
set(COMPONENT_SRCS "main.cpp")
set(COMPONENT_ADD_INCLUDEDIRS ".")
set(COMPONENT_EMBED_TXTFILES "sample.xml")
register_component()
# Build static library, do not build test executables
option(BUILD_SHARED_LIBS OFF)
option(BUILD_TESTING OFF)
# Import tinyxml2 targets
add_subdirectory(lib/tinyxml2)
# Propagate compile settings to tinyxml2
target_include_directories(tinyxml2 PRIVATE ${IDF_INCLUDE_DIRECTORIES})
target_compile_options(tinyxml2 PRIVATE "${IDF_COMPILE_OPTIONS}")
target_compile_options(tinyxml2 PRIVATE "${IDF_CXX_COMPILE_OPTIONS}")
# Link tinyxml2 to main component
target_link_libraries(${COMPONENT_TARGET} tinyxml2)

@ -0,0 +1 @@
Subproject commit 7e8e249990ec491ec15990cf95b6d871a66cf64a

View file

@ -0,0 +1,72 @@
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_vfs_fat.h"
#include "lib/tinyxml2/tinyxml2.h"
using namespace tinyxml2;
static const char *TAG = "example";
// Handle of the wear levelling library instance
static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
// Mount path for the partition
const char *base_path = "/spiflash";
extern "C" void app_main(void)
{
// Do example setup
ESP_LOGI(TAG, "Setting up...");
esp_vfs_fat_mount_config_t mount_config;
mount_config.max_files = 4;
mount_config.format_if_mount_failed = true;
mount_config.allocation_unit_size = CONFIG_WL_SECTOR_SIZE;
esp_err_t err = esp_vfs_fat_spiflash_mount(base_path, "storage", &mount_config, &s_wl_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
return;
}
// The sample XML is embedded binary data. Create a file first containing the embedded
// so it can be accessed.
ESP_LOGI(TAG, "Copying sample XML to filesystem...");
extern const char data_start[] asm("_binary_sample_xml_start");
extern const char data_end[] asm("_binary_sample_xml_end");
FILE *f = fopen("/spiflash/sample.xml", "wb");
if (f == NULL) {
ESP_LOGE(TAG, "Failed to open file for writing");
return;
}
fwrite(data_start, sizeof(char), data_end - data_start + 1, f);
fclose(f);
// Now that the file is created, load it using tinyxml2 and parse
ESP_LOGI(TAG, "Reading XML file");
XMLDocument data;
data.LoadFile("/spiflash/sample.xml");
XMLPrinter printer;
data.Print(&printer);
ESP_LOGI(TAG, "Read XML data:\n%s", printer.CStr());
const char* to_data = data.FirstChildElement("note")->FirstChildElement("to")->GetText();
const char* from_data = data.FirstChildElement("note")->FirstChildElement("from")->GetText();
const char* heading_data = data.FirstChildElement("note")->FirstChildElement("heading")->GetText();
const char* body_data = data.FirstChildElement("note")->FirstChildElement("body")->GetText();
ESP_LOGI(TAG, "Parsed XML data:\n\nTo: %s\nFrom: %s\nHeading: %s\nBody: %s",
to_data, from_data, heading_data, body_data);
ESP_LOGI(TAG, "Example end");
}

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

View file

@ -0,0 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 1M,
storage, data, fat, , 528K,
1 # Name, Type, SubType, Offset, Size, Flags
2 # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 1M,
6 storage, data, fat, , 528K,

View file

@ -0,0 +1,5 @@
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000
CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
CONFIG_APP_OFFSET=0x10000

View file

@ -3,4 +3,4 @@
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello-world)
project(hello-world)

View file

@ -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()

View file

@ -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()

View file

@ -2,6 +2,6 @@ set(COMPONENT_SRCS "native_ota_example.c")
set(COMPONENT_ADD_INCLUDEDIRS ".")
# Embed the server root certificate into the final binary
set(COMPONENT_EMBED_TXTFILES ${PROJECT_PATH}/server_certs/ca_cert.pem)
set(COMPONENT_EMBED_TXTFILES ${IDF_PROJECT_PATH}/server_certs/ca_cert.pem)
register_component()

View file

@ -3,6 +3,6 @@ set(COMPONENT_ADD_INCLUDEDIRS ".")
# Embed the server root certificate into the final binary
set(COMPONENT_EMBED_TXTFILES ${PROJECT_PATH}/server_certs/ca_cert.pem)
set(COMPONENT_EMBED_TXTFILES ${IDF_PROJECT_PATH}/server_certs/ca_cert.pem)
register_component()

View file

@ -62,6 +62,8 @@ RESULT_ISSUES=22 # magic number result code for issues found
LOG_SUSPECTED=${LOG_PATH}/common_log.txt
touch ${LOG_SUSPECTED}
EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name Makefile | grep -v "/build_system/cmake/" | sort )
if [ $# -eq 0 ]
then
START_NUM=0
@ -84,7 +86,7 @@ else
[ -z ${NUM_OF_JOBS} ] && die "NUM_OF_JOBS is bad"
# count number of examples
NUM_OF_EXAMPLES=$( find ${IDF_PATH}/examples/ -type f -name Makefile | wc -l )
NUM_OF_EXAMPLES=$( echo "${EXAMPLE_PATHS}" | wc -l )
[ -z ${NUM_OF_EXAMPLES} ] && die "NUM_OF_EXAMPLES is bad"
# separate intervals
@ -155,17 +157,16 @@ build_example () {
EXAMPLE_NUM=0
find ${IDF_PATH}/examples -type f -name Makefile | sort | \
while read FN
for EXAMPLE_PATH in ${EXAMPLE_PATHS}
do
if [[ $EXAMPLE_NUM -lt $START_NUM || $EXAMPLE_NUM -ge $END_NUM ]]
then
EXAMPLE_NUM=$(( $EXAMPLE_NUM + 1 ))
continue
fi
echo ">>> example [ ${EXAMPLE_NUM} ] - $FN"
echo ">>> example [ ${EXAMPLE_NUM} ] - $EXAMPLE_PATH"
build_example "${EXAMPLE_NUM}" "${FN}"
build_example "${EXAMPLE_NUM}" "${EXAMPLE_PATH}"
EXAMPLE_NUM=$(( $EXAMPLE_NUM + 1 ))
done

View file

@ -126,8 +126,13 @@ build_example () {
local BUILDLOG=${LOG_PATH}/ex_${ID}_log.txt
touch ${BUILDLOG}
idf.py fullclean >>${BUILDLOG} 2>&1 &&
idf.py build >>${BUILDLOG} 2>&1 &&
if [ "$EXAMPLE_NAME" != "idf_as_lib" ]; then
idf.py fullclean >>${BUILDLOG} 2>&1 &&
idf.py build >>${BUILDLOG} 2>&1
else
rm -rf build sdkconfig &&
./build.sh >>${BUILDLOG} 2>&1
fi &&
cp build/flash_project_args build/download.config || # backwards compatible download.config filename
{
RESULT=$?; FAILED_EXAMPLES+=" ${EXAMPLE_NAME}" ;

View file

@ -2,8 +2,8 @@
# While we support GNU Make & CMake together, check the same examples are present for both
CMAKE_EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name CMakeLists.txt | grep -v "/components/" | grep -v "/main/")
MAKE_EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name Makefile )
CMAKE_EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name CMakeLists.txt | grep -v "/components/" | grep -v "/main/" | grep -v "/build_system/cmake/")
MAKE_EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name Makefile | grep -v "/build_system/cmake/")
CMAKE_EXAMPLE_PATHS="$(/usr/bin/dirname $CMAKE_EXAMPLE_PATHS | sort -n)"
MAKE_EXAMPLE_PATHS="$(/usr/bin/dirname $MAKE_EXAMPLE_PATHS | sort -n)"

View file

@ -66,4 +66,5 @@ components/espcoredump/test/test_espcoredump.py
components/espcoredump/test/test_espcoredump.sh
tools/ldgen/ldgen.py
tools/ldgen/test/test_fragments.py
tools/ldgen/test/test_generation.py
tools/ldgen/test/test_generation.py
examples/build_system/cmake/idf_as_lib/build.sh

View file

@ -1,19 +1,20 @@
components/esp32/lib @GENERAL_MIRROR_SERVER@/idf/esp32-wifi-lib.git
components/bt/lib @GENERAL_MIRROR_SERVER@/idf/esp32-bt-lib.git
components/aws_iot/aws-iot-device-sdk-embedded-C @GENERAL_MIRROR_SERVER@/idf/aws-iot-device-sdk-embedded-C.git ALLOW_TO_SYNC_FROM_PUBLIC
components/coap/libcoap @GENERAL_MIRROR_SERVER@/idf/libcoap.git ALLOW_TO_SYNC_FROM_PUBLIC
components/esptool_py/esptool @GENERAL_MIRROR_SERVER@/idf/esptool.git ALLOW_TO_SYNC_FROM_PUBLIC
components/json/cJSON @GENERAL_MIRROR_SERVER@/idf/cJSON.git ALLOW_TO_SYNC_FROM_PUBLIC
components/libsodium/libsodium @GENERAL_MIRROR_SERVER@/idf/libsodium.git ALLOW_TO_SYNC_FROM_PUBLIC
components/mbedtls/mbedtls @GENERAL_MIRROR_SERVER@/idf/mbedtls.git ALLOW_TO_SYNC_FROM_PUBLIC
components/expat/expat @GENERAL_MIRROR_SERVER@/idf/libexpat.git ALLOW_TO_SYNC_FROM_PUBLIC
components/micro-ecc/micro-ecc @GENERAL_MIRROR_SERVER@/idf/micro-ecc.git ALLOW_TO_SYNC_FROM_PUBLIC
components/nghttp/nghttp2 @GENERAL_MIRROR_SERVER@/idf/nghttp2.git ALLOW_TO_SYNC_FROM_PUBLIC
components/spiffs/spiffs @GENERAL_MIRROR_SERVER@/idf/spiffs.git ALLOW_TO_SYNC_FROM_PUBLIC
components/asio/asio @GENERAL_MIRROR_SERVER@/idf/asio.git
components/lwip/lwip @GENERAL_MIRROR_SERVER@/idf/esp-lwip.git
third-party/mruby @GENERAL_MIRROR_SERVER@/idf/mruby.git ALLOW_TO_SYNC_FROM_PUBLIC
third-party/neverbleed @GENERAL_MIRROR_SERVER@/idf/neverbleed.git ALLOW_TO_SYNC_FROM_PUBLIC
components/mqtt/esp-mqtt @GENERAL_MIRROR_SERVER@/idf/esp-mqtt.git ALLOW_TO_SYNC_FROM_PUBLIC
components/protobuf-c/protobuf-c @GENERAL_MIRROR_SERVER@/idf/protobuf-c.git ALLOW_TO_SYNC_FROM_PUBLIC
components/unity/unity @GENERAL_MIRROR_SERVER@/idf/Unity.git ALLOW_TO_SYNC_FROM_PUBLIC
components/esp32/lib @GENERAL_MIRROR_SERVER@/idf/esp32-wifi-lib.git
components/bt/lib @GENERAL_MIRROR_SERVER@/idf/esp32-bt-lib.git
components/aws_iot/aws-iot-device-sdk-embedded-C @GENERAL_MIRROR_SERVER@/idf/aws-iot-device-sdk-embedded-C.git ALLOW_TO_SYNC_FROM_PUBLIC
components/coap/libcoap @GENERAL_MIRROR_SERVER@/idf/libcoap.git ALLOW_TO_SYNC_FROM_PUBLIC
components/esptool_py/esptool @GENERAL_MIRROR_SERVER@/idf/esptool.git ALLOW_TO_SYNC_FROM_PUBLIC
components/json/cJSON @GENERAL_MIRROR_SERVER@/idf/cJSON.git ALLOW_TO_SYNC_FROM_PUBLIC
components/libsodium/libsodium @GENERAL_MIRROR_SERVER@/idf/libsodium.git ALLOW_TO_SYNC_FROM_PUBLIC
components/mbedtls/mbedtls @GENERAL_MIRROR_SERVER@/idf/mbedtls.git ALLOW_TO_SYNC_FROM_PUBLIC
components/expat/expat @GENERAL_MIRROR_SERVER@/idf/libexpat.git ALLOW_TO_SYNC_FROM_PUBLIC
components/micro-ecc/micro-ecc @GENERAL_MIRROR_SERVER@/idf/micro-ecc.git ALLOW_TO_SYNC_FROM_PUBLIC
components/nghttp/nghttp2 @GENERAL_MIRROR_SERVER@/idf/nghttp2.git ALLOW_TO_SYNC_FROM_PUBLIC
components/spiffs/spiffs @GENERAL_MIRROR_SERVER@/idf/spiffs.git ALLOW_TO_SYNC_FROM_PUBLIC
components/asio/asio @GENERAL_MIRROR_SERVER@/idf/asio.git
components/lwip/lwip @GENERAL_MIRROR_SERVER@/idf/esp-lwip.git
third-party/mruby @GENERAL_MIRROR_SERVER@/idf/mruby.git ALLOW_TO_SYNC_FROM_PUBLIC
third-party/neverbleed @GENERAL_MIRROR_SERVER@/idf/neverbleed.git ALLOW_TO_SYNC_FROM_PUBLIC
components/mqtt/esp-mqtt @GENERAL_MIRROR_SERVER@/idf/esp-mqtt.git ALLOW_TO_SYNC_FROM_PUBLIC
components/protobuf-c/protobuf-c @GENERAL_MIRROR_SERVER@/idf/protobuf-c.git ALLOW_TO_SYNC_FROM_PUBLIC
components/unity/unity @GENERAL_MIRROR_SERVER@/idf/Unity.git ALLOW_TO_SYNC_FROM_PUBLIC
examples/build_system/cmake/import_lib/main/lib/tinyxml2 @GENERAL_MIRROR_SERVER@/idf/tinyxml2.git ALLOW_TO_SYNC_FROM_PUBLIC

View file

@ -58,6 +58,7 @@ function run_tests()
BOOTLOADER_BINS="bootloader/bootloader.elf bootloader/bootloader.bin"
APP_BINS="app-template.elf app-template.bin"
PARTITION_BIN="partition_table/partition-table.bin"
IDF_COMPONENT_PREFIX="idf_component"
print_status "Initial clean build"
# if build fails here, everything fails
@ -71,14 +72,14 @@ function run_tests()
take_build_snapshot
touch ${IDF_PATH}/components/esp32/cpu_start.c
idf.py build || failure "Failed to partial build"
assert_rebuilt ${APP_BINS} esp32/libesp32.a esp32/CMakeFiles/esp32.dir/cpu_start.c.obj
assert_not_rebuilt lwip/liblwip.a freertos/libfreertos.a ${BOOTLOADER_BINS} ${PARTITION_BIN}
assert_rebuilt ${APP_BINS} esp-idf/esp32/libesp32.a esp-idf/esp32/CMakeFiles/${IDF_COMPONENT_PREFIX}_esp32.dir/cpu_start.c.obj
assert_not_rebuilt esp-idf/lwip/liblwip.a esp-idf/freertos/libfreertos.a ${BOOTLOADER_BINS} ${PARTITION_BIN}
print_status "Bootloader source file rebuilds bootloader"
take_build_snapshot
touch ${IDF_PATH}/components/bootloader/subproject/main/bootloader_start.c
idf.py build || failure "Failed to partial build bootloader"
assert_rebuilt ${BOOTLOADER_BINS} bootloader/main/CMakeFiles/main.dir/bootloader_start.c.obj
assert_rebuilt ${BOOTLOADER_BINS} bootloader/esp-idf/main/CMakeFiles/${IDF_COMPONENT_PREFIX}_main.dir/bootloader_start.c.obj
assert_not_rebuilt ${APP_BINS} ${PARTITION_BIN}
print_status "Partition CSV file rebuilds partitions"
@ -172,9 +173,9 @@ function run_tests()
assert_rebuilt config/sdkconfig.h
# pick one each of .c, .cpp, .S that #includes sdkconfig.h
# and therefore should rebuild
assert_rebuilt newlib/CMakeFiles/newlib.dir/syscall_table.c.obj
assert_rebuilt nvs_flash/CMakeFiles/nvs_flash.dir/src/nvs_api.cpp.obj
assert_rebuilt freertos/CMakeFiles/freertos.dir/xtensa_vectors.S.obj
assert_rebuilt esp-idf/newlib/CMakeFiles/${IDF_COMPONENT_PREFIX}_newlib.dir/syscall_table.c.obj
assert_rebuilt esp-idf/nvs_flash/CMakeFiles/${IDF_COMPONENT_PREFIX}_nvs_flash.dir/src/nvs_api.cpp.obj
assert_rebuilt esp-idf/freertos/CMakeFiles/${IDF_COMPONENT_PREFIX}_freertos.dir/xtensa_vectors.S.obj
print_status "Updating project CMakeLists.txt triggers full recompile"
clean_build_dir
@ -186,9 +187,9 @@ function run_tests()
idf.py build || failure "Build failed"
mv CMakeLists.bak CMakeLists.txt
# similar to previous test
assert_rebuilt newlib/CMakeFiles/newlib.dir/syscall_table.c.obj
assert_rebuilt nvs_flash/CMakeFiles/nvs_flash.dir/src/nvs_api.cpp.obj
assert_rebuilt freertos/CMakeFiles/freertos.dir/xtensa_vectors.S.obj
assert_rebuilt esp-idf/newlib/CMakeFiles/${IDF_COMPONENT_PREFIX}_newlib.dir/syscall_table.c.obj
assert_rebuilt esp-idf/nvs_flash/CMakeFiles/${IDF_COMPONENT_PREFIX}_nvs_flash.dir/src/nvs_api.cpp.obj
assert_rebuilt esp-idf/freertos/CMakeFiles/${IDF_COMPONENT_PREFIX}_freertos.dir/xtensa_vectors.S.obj
print_status "Can build with Ninja (no idf.py)"
clean_build_dir

View file

@ -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'
#

View file

@ -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 $<$<COMPILE_LANGUAGE:C>:${IDF_C_COMPILE_OPTIONS}>)
target_compile_options(${COMPONENT_TARGET} PUBLIC $<$<COMPILE_LANGUAGE:CXX>:${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()

View file

@ -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()

View file

@ -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()

View file

@ -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()

View file

@ -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()

View file

@ -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}",

View file

@ -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()

View file

@ -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})

View file

@ -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}")