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
70 changed files with 1203 additions and 727 deletions

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