diff --git a/.editorconfig b/.editorconfig index 15977c64e..edabd53b6 100644 --- a/.editorconfig +++ b/.editorconfig @@ -32,3 +32,8 @@ insert_final_newline = false [*.py] max_line_length = 119 + +[{*.cmake,CMakeLists.txt}] +indent_style = space +indent_size = 4 +max_line_length = 120 diff --git a/.gitignore b/.gitignore index df90fbb19..2d65135e7 100644 --- a/.gitignore +++ b/.gitignore @@ -52,4 +52,11 @@ examples/protocols/aws_iot/*/main/certs/*.pem.* coverage.info coverage_report/ +# Windows tools installer build +tools/windows/tool_setup/.* +tools/windows/tool_setup/input +tools/windows/tool_setup/dl +tools/windows/tool_setup/Output + test_multi_heap_host + diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dc93b3943..fe3437b1f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -195,6 +195,12 @@ build_esp_idf_tests: # build some of examples - mkdir -p ${LOG_PATH} - ${IDF_PATH}/tools/ci/build_examples.sh "${CI_JOB_NAME}" + # and again, with cmake! + - rm -rf ../build_examples_cmake + - mkdir ../build_examples_cmake + - cd ../build_examples_cmake + - mkdir -p ${LOG_PATH}_cmake + - LOG_PATH=${LOG_PATH}_cmake ${IDF_PATH}/tools/ci/build_examples_cmake.sh "${CI_JOB_NAME}" build_examples_00: <<: *build_examples_template @@ -253,13 +259,19 @@ build_docs: - make html - ../check_doc_warnings.sh +verify_cmake_style: + stage: build + image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG + script: + tools/cmake/run_cmake_lint.sh + .host_test_template: &host_test_template stage: host_test image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG tags: - host_test dependencies: [] - + test_nvs_on_host: <<: *host_test_template script: @@ -319,6 +331,12 @@ test_multi_heap_on_host: - cd components/heap/test_multi_heap_host - ./test_all_configs.sh +test_confserver: + <<: *host_test_template + script: + - cd tools/kconfig_new/test + - ./test_confserver.py + test_build_system: <<: *host_test_template script: @@ -328,6 +346,15 @@ test_build_system: - cd test_build_system - ${IDF_PATH}/tools/ci/test_build_system.sh +test_build_system_cmake: + <<: *host_test_template + script: + - ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh + - rm -rf test_build_system + - mkdir test_build_system + - cd test_build_system + - ${IDF_PATH}/tools/ci/test_build_system_cmake.sh + test_esp_err_to_name_on_host: <<: *host_test_template script: @@ -446,6 +473,20 @@ check_permissions: script: - tools/ci/check-executable.sh +check_examples_cmake_make: + stage: deploy + image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG + tags: + - build + except: + - master + - /^release\/v/ + - /^v\d+\.\d+(\.\d+)?($|-)/ + dependencies: [] + before_script: *do_nothing_before + script: + - tools/ci/check_examples_cmake_make.sh + check_submodule_sync: stage: deploy image: $CI_DOCKER_REGISTRY/esp32-ci-env$BOT_DOCKER_IMAGE_TAG diff --git a/Kconfig b/Kconfig index 9d295e671..ff1a6d017 100644 --- a/Kconfig +++ b/Kconfig @@ -4,6 +4,9 @@ # mainmenu "Espressif IoT Development Framework Configuration" +config IDF_CMAKE + bool + option env="IDF_CMAKE" menu "SDK tool configuration" config TOOLPREFIX @@ -15,11 +18,15 @@ config TOOLPREFIX config PYTHON string "Python 2 interpreter" + depends on !IDF_CMAKE default "python" help The executable name/path that is used to run python. On some systems Python 2.x may need to be invoked as python2. + (Note: This option is used with the GNU Make build system only, not idf.py + or CMake-based builds.) + config MAKE_WARN_UNDEFINED_VARIABLES bool "'make' warns on undefined variables" default "y" @@ -35,7 +42,141 @@ endmenu # SDK tool configuration source "$COMPONENT_KCONFIGS_PROJBUILD" -source "$IDF_PATH/Kconfig.compiler" +menu "Compiler options" + +choice OPTIMIZATION_COMPILER + prompt "Optimization Level" + default OPTIMIZATION_LEVEL_DEBUG + help + This option sets compiler optimization level (gcc -O argument). + + - for "Release" setting, -Os flag is added to CFLAGS. + - for "Debug" setting, -Og flag is added to CFLAGS. + + "Release" with -Os produces smaller & faster compiled code but it + may be harder to correlated code addresses to source files when debugging. + + To add custom optimization settings, set CFLAGS and/or CPPFLAGS + in project makefile, before including $(IDF_PATH)/make/project.mk. Note that + custom optimization levels may be unsupported. + +config OPTIMIZATION_LEVEL_DEBUG + bool "Debug (-Og)" +config OPTIMIZATION_LEVEL_RELEASE + bool "Release (-Os)" +endchoice + +choice OPTIMIZATION_ASSERTION_LEVEL + prompt "Assertion level" + default OPTIMIZATION_ASSERTIONS_ENABLED + help + Assertions can be: + + - Enabled. Failure will print verbose assertion details. This is the default. + + - Set to "silent" to save code size (failed assertions will abort() but user + needs to use the aborting address to find the line number with the failed assertion.) + + - Disabled entirely (not recommended for most configurations.) -DNDEBUG is added + to CPPFLAGS in this case. + +config OPTIMIZATION_ASSERTIONS_ENABLED + prompt "Enabled" + bool + help + Enable assertions. Assertion content and line number will be printed on failure. + +config OPTIMIZATION_ASSERTIONS_SILENT + prompt "Silent (saves code size)" + bool + help + Enable silent assertions. Failed assertions will abort(), user needs to + use the aborting address to find the line number with the failed assertion. + +config OPTIMIZATION_ASSERTIONS_DISABLED + prompt "Disabled (sets -DNDEBUG)" + bool + help + If assertions are disabled, -DNDEBUG is added to CPPFLAGS. + +endchoice # assertions + +menuconfig CXX_EXCEPTIONS + bool "Enable C++ exceptions" + default n + help + Enabling this option compiles all IDF C++ files with exception support enabled. + + Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws + an exception will abort instead. + + Enabling this option currently adds an additional ~500 bytes of heap overhead + when an exception is thrown in user code for the first time. + +config CXX_EXCEPTIONS_EMG_POOL_SIZE + int "Emergency Pool Size" + default 0 + depends on CXX_EXCEPTIONS + help + Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate + memory for thrown exceptions when there is not enough memory on the heap. + +choice STACK_CHECK_MODE + prompt "Stack smashing protection mode" + default STACK_CHECK_NONE + help + Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack + smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. + The guards are initialized when a function is entered and then checked when the function exits. + If a guard check fails, program is halted. Protection has the following modes: + + - In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca, + and functions with buffers larger than 8 bytes are protected. + + - STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes + additional functions to be protected -- those that have local array definitions, + or have references to local frame addresses. + + - In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected. + + Modes have the following impact on code performance and coverage: + + - performance: NORMAL > STRONG > OVERALL + + - coverage: NORMAL < STRONG < OVERALL + + +config STACK_CHECK_NONE + bool "None" +config STACK_CHECK_NORM + bool "Normal" +config STACK_CHECK_STRONG + bool "Strong" +config STACK_CHECK_ALL + bool "Overall" +endchoice + +config STACK_CHECK + bool + default !STACK_CHECK_NONE + help + Stack smashing protection. + +config WARN_WRITE_STRINGS + bool "Enable -Wwrite-strings warning flag" + default "n" + help + Adds -Wwrite-strings flag for the C/C++ compilers. + + For C, this gives string constants the type ``const char[]`` so that + copying the address of one into a non-const ``char *`` pointer + produces a warning. This warning helps to find at compile time code + that tries to write into a string constant. + + For C++, this warns about the deprecated conversion from string + literals to ``char *``. + +endmenu # Compiler Options menu "Component config" source "$COMPONENT_KCONFIGS" diff --git a/Kconfig.compiler b/Kconfig.compiler deleted file mode 100644 index ab689e88f..000000000 --- a/Kconfig.compiler +++ /dev/null @@ -1,135 +0,0 @@ -menu "Compiler options" - -choice OPTIMIZATION_COMPILER - prompt "Optimization Level" - default OPTIMIZATION_LEVEL_DEBUG - help - This option sets compiler optimization level (gcc -O argument). - - - for "Release" setting, -Os flag is added to CFLAGS. - - for "Debug" setting, -Og flag is added to CFLAGS. - - "Release" with -Os produces smaller & faster compiled code but it - may be harder to correlated code addresses to source files when debugging. - - To add custom optimization settings, set CFLAGS and/or CPPFLAGS - in project makefile, before including $(IDF_PATH)/make/project.mk. Note that - custom optimization levels may be unsupported. - -config OPTIMIZATION_LEVEL_DEBUG - bool "Debug (-Og)" -config OPTIMIZATION_LEVEL_RELEASE - bool "Release (-Os)" -endchoice - -choice OPTIMIZATION_ASSERTION_LEVEL - prompt "Assertion level" - default OPTIMIZATION_ASSERTIONS_ENABLED - help - Assertions can be: - - - Enabled. Failure will print verbose assertion details. This is the default. - - - Set to "silent" to save code size (failed assertions will abort() but user - needs to use the aborting address to find the line number with the failed assertion.) - - - Disabled entirely (not recommended for most configurations.) -DNDEBUG is added - to CPPFLAGS in this case. - -config OPTIMIZATION_ASSERTIONS_ENABLED - prompt "Enabled" - bool - help - Enable assertions. Assertion content and line number will be printed on failure. - -config OPTIMIZATION_ASSERTIONS_SILENT - prompt "Silent (saves code size)" - bool - help - Enable silent assertions. Failed assertions will abort(), user needs to - use the aborting address to find the line number with the failed assertion. - -config OPTIMIZATION_ASSERTIONS_DISABLED - prompt "Disabled (sets -DNDEBUG)" - bool - help - If assertions are disabled, -DNDEBUG is added to CPPFLAGS. - -endchoice # assertions - -menuconfig CXX_EXCEPTIONS - bool "Enable C++ exceptions" - default n - help - Enabling this option compiles all IDF C++ files with exception support enabled. - - Disabling this option disables C++ exception support in all compiled files, and any libstdc++ code which throws - an exception will abort instead. - - Enabling this option currently adds an additional ~500 bytes of heap overhead - when an exception is thrown in user code for the first time. - -config CXX_EXCEPTIONS_EMG_POOL_SIZE - int "Emergency Pool Size" - default 0 - depends on CXX_EXCEPTIONS - help - Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate - memory for thrown exceptions when there is not enough memory on the heap. - -choice STACK_CHECK_MODE - prompt "Stack smashing protection mode" - default STACK_CHECK_NONE - help - Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack - smashing attacks. This is done by adding a guard variable to functions with vulnerable objects. - The guards are initialized when a function is entered and then checked when the function exits. - If a guard check fails, program is halted. Protection has the following modes: - - - In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca, - and functions with buffers larger than 8 bytes are protected. - - - STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes - additional functions to be protected -- those that have local array definitions, - or have references to local frame addresses. - - - In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected. - - Modes have the following impact on code performance and coverage: - - - performance: NORMAL > STRONG > OVERALL - - - coverage: NORMAL < STRONG < OVERALL - - -config STACK_CHECK_NONE - bool "None" -config STACK_CHECK_NORM - bool "Normal" -config STACK_CHECK_STRONG - bool "Strong" -config STACK_CHECK_ALL - bool "Overall" -endchoice - -config STACK_CHECK - bool - default !STACK_CHECK_NONE - help - Stack smashing protection. - -config WARN_WRITE_STRINGS - bool "Enable -Wwrite-strings warning flag" - default "n" - help - Adds -Wwrite-strings flag for the C/C++ compilers. - - For C, this gives string constants the type ``const char[]`` so that - copying the address of one into a non-const ``char *`` pointer - produces a warning. This warning helps to find at compile time code - that tries to write into a string constant. - - For C++, this warns about the deprecated conversion from string - literals to ``char *``. - -endmenu # Compiler Options diff --git a/README.md b/README.md index 42d8f45b4..dadcdfb61 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ NOTE: The `-j4` option causes `make` to run 4 parallel jobs. This is much faster ## Flashing the Project -When `make all` finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this from make by running: +When the build finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this automatically by running: `make -j4 flash` @@ -88,6 +88,7 @@ Multiple make functions can be combined into one. For example: to build the app make -j5 flash monitor ``` + ## The Partition Table Once you've compiled your project, the "build" directory will contain a binary file with a name like "my_app.bin". This is an ESP32 image binary that can be loaded by the bootloader. diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt new file mode 100644 index 000000000..5a6f19dbb --- /dev/null +++ b/components/app_trace/CMakeLists.txt @@ -0,0 +1,24 @@ +set(COMPONENT_SRCDIRS "." "gcov") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +if(CONFIG_SYSVIEW_ENABLE) + list(APPEND COMPONENT_ADD_INCLUDEDIRS + sys_view/Config + sys_view/SEGGER + sys_view/Sample/OS) + + list(APPEND COMPONENT_SRCDIRS + "sys_view/SEGGER" + "sys_view/Sample/OS" + "sys_view/Sample/Config" + "sys_view/esp32") +endif() + +set(COMPONENT_REQUIRES) +set(COMPONENT_PRIV_REQUIRES xtensa-debug-module) + +register_component() + +# disable --coverage for this component, as it is used as transport +# for gcov +component_compile_options("-fno-profile-arcs" "-fno-test-coverage") diff --git a/components/app_update/CMakeLists.txt b/components/app_update/CMakeLists.txt new file mode 100644 index 000000000..e1401c685 --- /dev/null +++ b/components/app_update/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES spi_flash) +set(COMPONENT_PRIV_REQUIRES bootloader_support) + +register_component() diff --git a/components/app_update/esp_ota_ops.c b/components/app_update/esp_ota_ops.c index 48542c23f..befdd33fc 100644 --- a/components/app_update/esp_ota_ops.c +++ b/components/app_update/esp_ota_ops.c @@ -28,6 +28,7 @@ #include "esp_image_format.h" #include "esp_secure_boot.h" #include "esp_flash_encrypt.h" +#include "esp_spi_flash.h" #include "sdkconfig.h" #include "esp_ota_ops.h" diff --git a/components/app_update/include/esp_ota_ops.h b/components/app_update/include/esp_ota_ops.h index a089a92be..8fcf622d3 100644 --- a/components/app_update/include/esp_ota_ops.h +++ b/components/app_update/include/esp_ota_ops.h @@ -20,7 +20,6 @@ #include #include "esp_err.h" #include "esp_partition.h" -#include "esp_spi_flash.h" #ifdef __cplusplus extern "C" diff --git a/components/aws_iot/CMakeLists.txt b/components/aws_iot/CMakeLists.txt new file mode 100644 index 000000000..f7644bd7a --- /dev/null +++ b/components/aws_iot/CMakeLists.txt @@ -0,0 +1,11 @@ +if(CONFIG_AWS_IOT_SDK) + set(COMPONENT_ADD_INCLUDEDIRS "include aws-iot-device-sdk-embedded-C/include") + set(COMPONENT_SRCDIRS "aws-iot-device-sdk-embedded-C/src port") +else() + message(STATUS "Building empty aws_iot component due to configuration") +endif() + +set(COMPONENT_REQUIRES "mbedtls") +set(COMPONENT_PRIV_REQUIRES "jsmn") + +register_component() diff --git a/components/bootloader/CMakeLists.txt b/components/bootloader/CMakeLists.txt new file mode 100644 index 000000000..d38b8ff8e --- /dev/null +++ b/components/bootloader/CMakeLists.txt @@ -0,0 +1,7 @@ +# bootloader component logic is all in project_include.cmake, +# and subproject/CMakeLists.txt. +# +# This file is only included so the build system finds the +# component + + diff --git a/components/bootloader/project_include.cmake b/components/bootloader/project_include.cmake new file mode 100644 index 000000000..cdb18a9fa --- /dev/null +++ b/components/bootloader/project_include.cmake @@ -0,0 +1,33 @@ +if(BOOTLOADER_BUILD) + return() # don't keep recursing! +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_binary_files + "${bootloader_build_dir}/bootloader.elf" + "${bootloader_build_dir}/bootloader.bin" + "${bootloader_build_dir}/bootloader.map" + ) + +externalproject_add(bootloader + # TODO: support overriding the bootloader in COMPONENT_PATHS + SOURCE_DIR "${IDF_PATH}/components/bootloader/subproject" + BINARY_DIR "${bootloader_build_dir}" + CMAKE_ARGS -DSDKCONFIG=${SDKCONFIG} -DIDF_PATH=${IDF_PATH} + INSTALL_COMMAND "" + BUILD_ALWAYS 1 # no easy way around this... + BUILD_BYPRODUCTS ${bootloader_binary_files} + ) + +# this is a hack due to an (annoying) shortcoming in cmake, it can't +# extend the 'clean' target to the external project +# see thread: https://cmake.org/pipermail/cmake/2016-December/064660.html +# +# So for now we just have the top-level build remove the final build products... +set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES + ${bootloader_binary_files}) diff --git a/components/bootloader/subproject/CMakeLists.txt b/components/bootloader/subproject/CMakeLists.txt new file mode 100644 index 000000000..7a34d8ea2 --- /dev/null +++ b/components/bootloader/subproject/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.5) + +if(NOT SDKCONFIG) + message(FATAL_ERROR "Bootloader subproject expects the SDKCONFIG variable to be passed " + "in by the parent build process.") +endif() + +if(NOT IDF_PATH) + message(FATAL_ERROR "Bootloader subproject expects the IDF_PATH variable to be passed " + "in by the parent build process.") +endif() + +set(COMPONENTS bootloader esptool_py esp32 partition_table soc bootloader_support log spi_flash micro-ecc soc) +set(BOOTLOADER_BUILD 1) +add_definitions(-DBOOTLOADER_BUILD=1) + +set(COMPONENT_REQUIRES_COMMON log esp32 soc) + +set(MAIN_SRCS main/bootloader_start.c) + +include("${IDF_PATH}/tools/cmake/project.cmake") +project(bootloader) + +target_linker_script(bootloader.elf + "main/esp32.bootloader.ld" + "main/esp32.bootloader.rom.ld") +# Imported from esp32 component +target_linker_script(bootloader.elf ${ESP32_BOOTLOADER_LINKER_SCRIPTS}) + +target_link_libraries(bootloader.elf gcc) diff --git a/components/bootloader/subproject/main/esp32.bootloader.ld b/components/bootloader/subproject/main/esp32.bootloader.ld index b89bba124..8113987f4 100644 --- a/components/bootloader/subproject/main/esp32.bootloader.ld +++ b/components/bootloader/subproject/main/esp32.bootloader.ld @@ -36,18 +36,18 @@ SECTIONS *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */ *liblog.a:(.literal .text .literal.* .text.*) *libgcc.a:(.literal .text .literal.* .text.*) - *libbootloader_support.a:bootloader_flash.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:bootloader_random.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:bootloader_utility.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:bootloader_sha.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:efuse.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:esp_image_format.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:flash_encrypt.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:flash_partitions.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:secure_boot.o(.literal .text .literal.* .text.*) - *libbootloader_support.a:secure_boot_signatures.o(.literal .text .literal.* .text.*) - *libmicro-ecc.a:*.o(.literal .text .literal.* .text.*) - *libspi_flash.a:*.o(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:efuse.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*) + *libmicro-ecc.a:*.*(.literal .text .literal.* .text.*) + *libspi_flash.a:*.*(.literal .text .literal.* .text.*) *(.fini.literal) *(.fini) *(.gnu.version) @@ -119,13 +119,13 @@ SECTIONS . = (. + 3) & ~ 3; /* C++ constructor and destructor tables, properly ordered: */ __init_array_start = ABSOLUTE(.); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*crtbegin.*(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*crtbegin.*(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) /* C++ exception handlers table: */ diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt new file mode 100644 index 000000000..21978397e --- /dev/null +++ b/components/bootloader_support/CMakeLists.txt @@ -0,0 +1,14 @@ +set(COMPONENT_SRCDIRS "src") + +if(${BOOTLOADER_BUILD}) + set(COMPONENT_ADD_INCLUDEDIRS "include include_priv") + set(COMPONENT_REQUIRES) + set(COMPONENT_PRIV_REQUIRES spi_flash micro-ecc) +else() + set(COMPONENT_ADD_INCLUDEDIRS "include") + set(COMPONENT_PRIV_INCLUDEDIRS "include_priv") + set(COMPONENT_REQUIRES) + set(COMPONENT_PRIV_REQUIRES spi_flash mbedtls micro-ecc) +endif() + +register_component() diff --git a/components/bootloader_support/include/esp_flash_encrypt.h b/components/bootloader_support/include/esp_flash_encrypt.h index ba370644a..31b77a734 100644 --- a/components/bootloader_support/include/esp_flash_encrypt.h +++ b/components/bootloader_support/include/esp_flash_encrypt.h @@ -17,7 +17,9 @@ #include #include "esp_attr.h" #include "esp_err.h" +#ifndef BOOTLOADER_BUILD #include "esp_spi_flash.h" +#endif #include "soc/efuse_reg.h" /** diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt new file mode 100644 index 000000000..f64668f9f --- /dev/null +++ b/components/bt/CMakeLists.txt @@ -0,0 +1,92 @@ +if(CONFIG_BT_ENABLED) + + set(COMPONENT_SRCDIRS .) + set(COMPONENT_ADD_INCLUDEDIRS include) + + if(CONFIG_BLUEDROID_ENABLED) + + list(APPEND COMPONENT_PRIV_INCLUDEDIRS + bluedroid/bta/include + bluedroid/bta/ar/include + bluedroid/bta/av/include + bluedroid/bta/dm/include + bluedroid/bta/gatt/include + bluedroid/bta/hh/include + bluedroid/bta/jv/include + bluedroid/bta/sdp/include + bluedroid/bta/sys/include + bluedroid/device/include + bluedroid/hci/include + bluedroid/osi/include + bluedroid/external/sbc/decoder/include + bluedroid/external/sbc/encoder/include + bluedroid/btc/profile/esp/blufi/include + bluedroid/btc/profile/esp/include + bluedroid/btc/profile/std/a2dp/include + bluedroid/btc/profile/std/include + bluedroid/btc/include + bluedroid/stack/btm/include + bluedroid/stack/gap/include + bluedroid/stack/gatt/include + bluedroid/stack/l2cap/include + bluedroid/stack/sdp/include + bluedroid/stack/smp/include + bluedroid/stack/avct/include + bluedroid/stack/avrc/include + bluedroid/stack/avdt/include + bluedroid/stack/a2dp/include + bluedroid/stack/rfcomm/include + bluedroid/stack/include + bluedroid/common/include) + + list(APPEND COMPONENT_ADD_INCLUDEDIRS bluedroid/api/include/api) + + list(APPEND COMPONENT_SRCDIRS + bluedroid/bta/dm + bluedroid/bta/gatt + bluedroid/bta/hh + bluedroid/bta/sdp + bluedroid/bta/av + bluedroid/bta/ar + bluedroid/bta/sys + bluedroid/bta/jv + bluedroid/device + bluedroid/hci + bluedroid/main + bluedroid/osi + bluedroid/external/sbc/decoder/srce + bluedroid/external/sbc/encoder/srce + bluedroid/btc/core + bluedroid/btc/profile/esp/blufi + bluedroid/btc/profile/std/gap + bluedroid/btc/profile/std/gatt + bluedroid/btc/profile/std/a2dp + bluedroid/btc/profile/std/avrc + bluedroid/btc/profile/std/spp + bluedroid/stack/btm + bluedroid/stack/btu + bluedroid/stack/gap + bluedroid/stack/gatt + bluedroid/stack/hcic + bluedroid/stack/l2cap + bluedroid/stack/sdp + bluedroid/stack/smp + bluedroid/stack/avct + bluedroid/stack/avrc + bluedroid/stack/avdt + bluedroid/stack/a2dp + bluedroid/stack/rfcomm + bluedroid/api + ) + endif() +endif() + +# requirements can't depend on config +set(COMPONENT_PRIV_REQUIRES nvs_flash) + +register_component() + +if(CONFIG_BT_ENABLED) + target_link_libraries(bt "-L${CMAKE_CURRENT_LIST_DIR}/lib") + target_link_libraries(bt btdm_app) +endif() diff --git a/components/bt/Kconfig b/components/bt/Kconfig index 97e2f9152..952b83235 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -1014,7 +1014,7 @@ config BLE_HOST_QUEUE_CONGESTION_CHECK lost when host queue is congested. config BLE_SCAN_DUPLICATE - bool "BLE Scan Duplicate Options " + bool "BLE Scan Duplicate Options" depends on BLUEDROID_ENABLED default y help diff --git a/components/coap/CMakeLists.txt b/components/coap/CMakeLists.txt new file mode 100644 index 000000000..90b0c26e6 --- /dev/null +++ b/components/coap/CMakeLists.txt @@ -0,0 +1,42 @@ +set(COMPONENT_ADD_INCLUDEDIRS port/include port/include/coap libcoap/include libcoap/include/coap) + +set(COMPONENT_SRCS + libcoap/src/address.c + libcoap/src/async.c + libcoap/src/block.c + libcoap/src/coap_time.c + libcoap/src/debug.c + libcoap/src/encode.c + libcoap/src/hashkey.c + libcoap/src/mem.c + libcoap/src/net.c + libcoap/src/option.c + libcoap/src/pdu.c + libcoap/src/resource.c + libcoap/src/str.c + libcoap/src/subscribe.c + libcoap/src/uri.c + port/coap_io_socket.c + ) + +set(COMPONENT_REQUIRES lwip) + +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) + +set_source_files_properties( + libcoap/src/debug.c + libcoap/src/pdu.c + PROPERTIES COMPILE_FLAGS + -Wno-write-strings) + +# Temporary suppress "fallthrough" warnings until they are fixed in libcoap repo +set_source_files_properties( + libcoap/src/option.c + PROPERTIES COMPILE_FLAGS + -Wno-implicit-fallthrough) + diff --git a/components/console/CMakeLists.txt b/components/console/CMakeLists.txt new file mode 100644 index 000000000..0b0da5394 --- /dev/null +++ b/components/console/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_ADD_INCLUDEDIRS .) +set(COMPONENT_SRCDIRS linenoise argtable3 .) + +set(COMPONENT_REQUIRES) + +register_component() + diff --git a/components/cxx/CMakeLists.txt b/components/cxx/CMakeLists.txt new file mode 100644 index 000000000..a797640cc --- /dev/null +++ b/components/cxx/CMakeLists.txt @@ -0,0 +1,11 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_REQUIRES) +register_component() + +target_link_libraries(cxx stdc++) + +target_link_libraries(cxx "-u __cxa_guard_dummy") + +if(NOT CONFIG_CXX_EXCEPTIONS) + target_link_libraries(cxx "-u __cxx_fatal_exception") +endif() diff --git a/components/driver/CMakeLists.txt b/components/driver/CMakeLists.txt new file mode 100644 index 000000000..0c72aecc4 --- /dev/null +++ b/components/driver/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_PRIV_INCLUDEDIRS "include/driver") + +set(COMPONENT_REQUIRES) + +register_component() diff --git a/components/esp-tls/CMakeLists.txt b/components/esp-tls/CMakeLists.txt new file mode 100644 index 000000000..9bad42868 --- /dev/null +++ b/components/esp-tls/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +set(COMPONENT_REQUIRES mbedtls) +set(COMPONENT_PRIV_REQUIRES lwip nghttp) + +register_component() diff --git a/components/esp32/CMakeLists.txt b/components/esp32/CMakeLists.txt new file mode 100644 index 000000000..b26f5efe2 --- /dev/null +++ b/components/esp32/CMakeLists.txt @@ -0,0 +1,98 @@ +if(BOOTLOADER_BUILD) + # For bootloader, all we need from esp32 is headers + set(COMPONENT_ADD_INCLUDEDIRS include) + set(COMPONENT_REQUIRES ${COMPONENTS}) + set(COMPONENT_SRCDIRS "") + register_component(esp32) + + # as cmake won't attach linker args to a header-only library, attach + # linker args directly to the bootloader.elf + 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 + ) + +else() + # Regular app build + + set(COMPONENT_SRCDIRS ". hwcrypto") + set(COMPONENT_ADD_INCLUDEDIRS "include") + + set(COMPONENT_REQUIRES driver tcpip_adapter) + # driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t + # tcpip_adapter is a public requirement because esp_event.h uses tcpip_adapter types + set(COMPONENT_PRIV_REQUIRES + app_trace bootloader_support ethernet log mbedtls nvs_flash + pthread smartconfig_ack spi_flash vfs wpa_supplicant xtensa-debug-module) + + register_component() + + target_link_libraries(esp32 "-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) + endif() + target_linker_script(esp32 "${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld") + + target_linker_script(esp32 + "ld/esp32.common.ld" + "ld/esp32.rom.ld" + "ld/esp32.peripherals.ld" + "ld/esp32.rom.libgcc.ld" + ) + + 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") + endif() + + if(CONFIG_NEWLIB_NANO_FORMAT) + target_linker_script(esp32 "ld/esp32.rom.nanofmt.ld") + endif() + + if(NOT CONFIG_SPI_FLASH_ROM_DRIVER_PATCH) + target_linker_script(esp32 "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") + + #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") + + # Preprocess esp32.ld linker script to include configuration, becomes esp32_out.ld + set(LD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ld) + add_custom_command( + OUTPUT esp32_out.ld + COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o esp32_out.ld -I ${CONFIG_DIR} ${LD_DIR}/esp32.ld + MAIN_DEPENDENCY ${LD_DIR}/esp32.ld ${SDKCONFIG_H} + COMMENT "Generating linker script..." + VERBATIM) + add_custom_target(esp32_linker_script DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld) + add_dependencies(esp32 esp32_linker_script) + + if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION) + set(PHY_INIT_DATA_BIN phy_init_data.bin) + + # 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 + add_custom_command( + 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} + -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() + +endif() diff --git a/components/esp32/ld/esp32.common.ld b/components/esp32/ld/esp32.common.ld index 26acd7b2d..dddccbb4b 100644 --- a/components/esp32/ld/esp32.common.ld +++ b/components/esp32/ld/esp32.common.ld @@ -10,7 +10,7 @@ SECTIONS { . = ALIGN(4); *(.rtc.literal .rtc.text) - *rtc_wake_stub*.o(.literal .text .literal.* .text.*) + *rtc_wake_stub*.*(.literal .text .literal.* .text.*) } > rtc_iram_seg /* RTC slow memory holds RTC wake stub @@ -22,7 +22,7 @@ SECTIONS _rtc_data_start = ABSOLUTE(.); *(.rtc.data) *(.rtc.rodata) - *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*) _rtc_data_end = ABSOLUTE(.); } > rtc_slow_seg @@ -30,8 +30,8 @@ SECTIONS .rtc.bss (NOLOAD) : { _rtc_bss_start = ABSOLUTE(.); - *rtc_wake_stub*.o(.bss .bss.*) - *rtc_wake_stub*.o(COMMON) + *rtc_wake_stub*.*(.bss .bss.*) + *rtc_wake_stub*.*(COMMON) _rtc_bss_end = ABSOLUTE(.); } > rtc_slow_seg @@ -97,17 +97,17 @@ SECTIONS _iram_text_start = ABSOLUTE(.); *(.iram1 .iram1.*) *libfreertos.a:(.literal .text .literal.* .text.*) - *libheap.a:multi_heap.o(.literal .text .literal.* .text.*) - *libheap.a:multi_heap_poisoning.o(.literal .text .literal.* .text.*) - *libesp32.a:panic.o(.literal .text .literal.* .text.*) - *libesp32.a:core_dump.o(.literal .text .literal.* .text.*) + *libheap.a:multi_heap.*(.literal .text .literal.* .text.*) + *libheap.a:multi_heap_poisoning.*(.literal .text .literal.* .text.*) + *libesp32.a:panic.*(.literal .text .literal.* .text.*) + *libesp32.a:core_dump.*(.literal .text .literal.* .text.*) *libapp_trace.a:(.literal .text .literal.* .text.*) - *libxtensa-debug-module.a:eri.o(.literal .text .literal.* .text.*) + *libxtensa-debug-module.a:eri.*(.literal .text .literal.* .text.*) *librtc.a:(.literal .text .literal.* .text.*) *libsoc.a:(.literal .text .literal.* .text.*) *libhal.a:(.literal .text .literal.* .text.*) - *libgcc.a:lib2funcs.o(.literal .text .literal.* .text.*) - *libspi_flash.a:spi_flash_rom_patch.o(.literal .text .literal.* .text.*) + *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) + *libspi_flash.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*) *libgcov.a:(.literal .text .literal.* .text.*) INCLUDE esp32.spiram.rom-functions-iram.ld _iram_text_end = ABSOLUTE(.); @@ -128,13 +128,13 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) *(.dram1 .dram1.*) - *libesp32.a:panic.o(.rodata .rodata.*) + *libesp32.a:panic.*(.rodata .rodata.*) *libphy.a:(.rodata .rodata.*) - *libsoc.a:rtc_clk.o(.rodata .rodata.*) + *libsoc.a:rtc_clk.*(.rodata .rodata.*) *libapp_trace.a:(.rodata .rodata.*) *libgcov.a:(.rodata .rodata.*) - *libheap.a:multi_heap.o(.rodata .rodata.*) - *libheap.a:multi_heap_poisoning.o(.rodata .rodata.*) + *libheap.a:multi_heap.*(.rodata .rodata.*) + *libheap.a:multi_heap_poisoning.*(.rodata .rodata.*) INCLUDE esp32.spiram.rom-functions-dram.ld _data_end = ABSOLUTE(.); . = ALIGN(4); @@ -198,13 +198,13 @@ SECTIONS . = (. + 7) & ~ 3; /* C++ constructor and destructor tables, properly ordered: */ __init_array_start = ABSOLUTE(.); - KEEP (*crtbegin.o(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*crtbegin.*(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) __init_array_end = ABSOLUTE(.); - KEEP (*crtbegin.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*crtbegin.*(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) /* C++ exception handlers table: */ diff --git a/components/esp32/phy_init_data.h b/components/esp32/phy_init_data.h index d09bbdd9c..9213020ca 100644 --- a/components/esp32/phy_init_data.h +++ b/components/esp32/phy_init_data.h @@ -12,7 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#pragma once +#ifndef PHY_INIT_DATA_H +#define PHY_INIT_DATA_H /* don't use #pragma once here, we compile this file sometimes */ #include "esp_phy_init.h" #include "sdkconfig.h" @@ -138,3 +139,5 @@ static const esp_phy_init_data_t phy_init_data= { { static const char phy_init_magic_post[] = PHY_INIT_MAGIC; +#endif /* PHY_INIT_DATA_H */ + diff --git a/components/esp_adc_cal/CMakeLists.txt b/components/esp_adc_cal/CMakeLists.txt new file mode 100644 index 000000000..fc21f1eca --- /dev/null +++ b/components/esp_adc_cal/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES) + +register_component() diff --git a/components/esp_http_client/CMakeLists.txt b/components/esp_http_client/CMakeLists.txt new file mode 100644 index 000000000..f95c657ab --- /dev/null +++ b/components/esp_http_client/CMakeLists.txt @@ -0,0 +1,8 @@ +set(COMPONENT_SRCDIRS "." "lib") +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_PRIV_INCLUDEDIRS "lib/include") + +set(COMPONENT_REQUIRES "nghttp") +set(COMPONENT_PRIV_REQUIRES "mbedtls" "lwip") + +register_component() diff --git a/components/esp_https_ota/CMakeLists.txt b/components/esp_https_ota/CMakeLists.txt new file mode 100644 index 000000000..bfc6c1205 --- /dev/null +++ b/components/esp_https_ota/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_ADD_INCLUDEDIRS include) +set(COMPONENT_SRCDIRS "src") + +set(COMPONENT_REQUIRES esp_http_client) +set(COMPONENT_PRIV_REQUIRES log app_update) + +register_component() diff --git a/components/esptool_py/CMakeLists.txt b/components/esptool_py/CMakeLists.txt new file mode 100644 index 000000000..690763934 --- /dev/null +++ b/components/esptool_py/CMakeLists.txt @@ -0,0 +1,14 @@ +register_config_only_component() + +# 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() + +configure_file( + "${CMAKE_CURRENT_LIST_DIR}/flasher_args.json.in" + "${CMAKE_BINARY_DIR}/flasher_args.json" + ) diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild index 84ca5d683..799b576a0 100644 --- a/components/esptool_py/Kconfig.projbuild +++ b/components/esptool_py/Kconfig.projbuild @@ -1,127 +1,135 @@ menu "Serial flasher config" config ESPTOOLPY_PORT - string "Default serial port" - default "/dev/ttyUSB0" - help - The serial port that's connected to the ESP chip. This can be overridden by setting the ESPPORT - environment variable. + string "Default serial port" + depends on !IDF_CMAKE + default "/dev/ttyUSB0" + help + The serial port that's connected to the ESP chip. This can be overridden by setting the ESPPORT + environment variable. + + This value is ignored when using the CMake-based build system or idf.py. choice ESPTOOLPY_BAUD - prompt "Default baud rate" - default ESPTOOLPY_BAUD_115200B - help - Default baud rate to use while communicating with the ESP chip. Can be overridden by - setting the ESPBAUD variable. + prompt "Default baud rate" + depends on !IDF_CMAKE + default ESPTOOLPY_BAUD_115200B + help + Default baud rate to use while communicating with the ESP chip. Can be overridden by + setting the ESPBAUD variable. + + This value is ignored when using the CMake-based build system or idf.py. config ESPTOOLPY_BAUD_115200B - bool "115200 baud" + bool "115200 baud" config ESPTOOLPY_BAUD_230400B - bool "230400 baud" + bool "230400 baud" config ESPTOOLPY_BAUD_921600B - bool "921600 baud" + bool "921600 baud" config ESPTOOLPY_BAUD_2MB - bool "2Mbaud" + bool "2Mbaud" config ESPTOOLPY_BAUD_OTHER bool "Other baud rate" endchoice config ESPTOOLPY_BAUD_OTHER_VAL - int "Other baud rate value" if ESPTOOLPY_BAUD_OTHER - default 115200 + int "Other baud rate value" if ESPTOOLPY_BAUD_OTHER + default 115200 config ESPTOOLPY_BAUD - int - default 115200 if ESPTOOLPY_BAUD_115200B - default 230400 if ESPTOOLPY_BAUD_230400B - default 921600 if ESPTOOLPY_BAUD_921600B - default 2000000 if ESPTOOLPY_BAUD_2MB - default ESPTOOLPY_BAUD_OTHER_VAL if ESPTOOLPY_BAUD_OTHER + int + depends on !IDF_CMAKE + default 115200 if ESPTOOLPY_BAUD_115200B + default 230400 if ESPTOOLPY_BAUD_230400B + default 921600 if ESPTOOLPY_BAUD_921600B + default 2000000 if ESPTOOLPY_BAUD_2MB + default ESPTOOLPY_BAUD_OTHER_VAL if ESPTOOLPY_BAUD_OTHER config ESPTOOLPY_COMPRESSED - bool "Use compressed upload" - default "y" - help - The flasher tool can send data compressed using zlib, letting the ROM on the ESP chip - decompress it on the fly before flashing it. For most payloads, this should result in a - speed increase. + bool "Use compressed upload" + depends on !IDF_CMAKE + default "y" + help + The flasher tool can send data compressed using zlib, letting the ROM on the ESP chip + decompress it on the fly before flashing it. For most payloads, this should result in a + speed increase. choice FLASHMODE - prompt "Flash SPI mode" - default FLASHMODE_DIO - help - Mode the flash chip is flashed in, as well as the default mode for the - binary to run in. + prompt "Flash SPI mode" + default FLASHMODE_DIO + help + Mode the flash chip is flashed in, as well as the default mode for the + binary to run in. config FLASHMODE_QIO - bool "QIO" + bool "QIO" config FLASHMODE_QOUT - bool "QOUT" + bool "QOUT" config FLASHMODE_DIO - bool "DIO" + bool "DIO" config FLASHMODE_DOUT - bool "DOUT" + bool "DOUT" endchoice # Note: we use esptool.py to flash bootloader in # dio mode for QIO/QOUT, bootloader then upgrades # itself to quad mode during initialisation config ESPTOOLPY_FLASHMODE - string - default "dio" if FLASHMODE_QIO - default "dio" if FLASHMODE_QOUT - default "dio" if FLASHMODE_DIO - default "dout" if FLASHMODE_DOUT + string + default "dio" if FLASHMODE_QIO + default "dio" if FLASHMODE_QOUT + default "dio" if FLASHMODE_DIO + default "dout" if FLASHMODE_DOUT choice ESPTOOLPY_FLASHFREQ - prompt "Flash SPI speed" - default ESPTOOLPY_FLASHFREQ_40M - help - The SPI flash frequency to be used. + prompt "Flash SPI speed" + default ESPTOOLPY_FLASHFREQ_40M + help + The SPI flash frequency to be used. config ESPTOOLPY_FLASHFREQ_80M - bool "80 MHz" + bool "80 MHz" config ESPTOOLPY_FLASHFREQ_40M - bool "40 MHz" + bool "40 MHz" config ESPTOOLPY_FLASHFREQ_26M - bool "26 MHz" + bool "26 MHz" config ESPTOOLPY_FLASHFREQ_20M - bool "20 MHz" + bool "20 MHz" endchoice config ESPTOOLPY_FLASHFREQ - string - default "80m" if ESPTOOLPY_FLASHFREQ_80M - default "40m" if ESPTOOLPY_FLASHFREQ_40M - default "26m" if ESPTOOLPY_FLASHFREQ_26M - default "20m" if ESPTOOLPY_FLASHFREQ_20M + string + default "80m" if ESPTOOLPY_FLASHFREQ_80M + default "40m" if ESPTOOLPY_FLASHFREQ_40M + default "26m" if ESPTOOLPY_FLASHFREQ_26M + default "20m" if ESPTOOLPY_FLASHFREQ_20M choice ESPTOOLPY_FLASHSIZE - prompt "Flash size" - default ESPTOOLPY_FLASHSIZE_2MB - help - SPI flash size, in megabytes + prompt "Flash size" + default ESPTOOLPY_FLASHSIZE_2MB + help + SPI flash size, in megabytes config ESPTOOLPY_FLASHSIZE_1MB - bool "1 MB" + bool "1 MB" config ESPTOOLPY_FLASHSIZE_2MB - bool "2 MB" + bool "2 MB" config ESPTOOLPY_FLASHSIZE_4MB - bool "4 MB" + bool "4 MB" config ESPTOOLPY_FLASHSIZE_8MB - bool "8 MB" + bool "8 MB" config ESPTOOLPY_FLASHSIZE_16MB - bool "16 MB" + bool "16 MB" endchoice config ESPTOOLPY_FLASHSIZE - string - default "1MB" if ESPTOOLPY_FLASHSIZE_1MB - default "2MB" if ESPTOOLPY_FLASHSIZE_2MB - default "4MB" if ESPTOOLPY_FLASHSIZE_4MB - default "8MB" if ESPTOOLPY_FLASHSIZE_8MB - default "16MB" if ESPTOOLPY_FLASHSIZE_16MB + string + default "1MB" if ESPTOOLPY_FLASHSIZE_1MB + default "2MB" if ESPTOOLPY_FLASHSIZE_2MB + default "4MB" if ESPTOOLPY_FLASHSIZE_4MB + default "8MB" if ESPTOOLPY_FLASHSIZE_8MB + default "16MB" if ESPTOOLPY_FLASHSIZE_16MB config ESPTOOLPY_FLASHSIZE_DETECT bool "Detect flash size when flashing bootloader" diff --git a/components/esptool_py/flash_app_args.in b/components/esptool_py/flash_app_args.in new file mode 100644 index 000000000..6d31ca4fe --- /dev/null +++ b/components/esptool_py/flash_app_args.in @@ -0,0 +1 @@ +${APP_PARTITION_OFFSET} ${PROJECT_NAME}.bin diff --git a/components/esptool_py/flash_bootloader_args.in b/components/esptool_py/flash_bootloader_args.in new file mode 100644 index 000000000..ac19a6d81 --- /dev/null +++ b/components/esptool_py/flash_bootloader_args.in @@ -0,0 +1,4 @@ +--flash_mode ${ESPFLASHMODE} +--flash_size ${ESPFLASHSIZE} +--flash_freq ${ESPFLASHFREQ} +0x1000 bootloader/bootloader.bin diff --git a/components/esptool_py/flash_partition_table_args.in b/components/esptool_py/flash_partition_table_args.in new file mode 100644 index 000000000..ccfc14d71 --- /dev/null +++ b/components/esptool_py/flash_partition_table_args.in @@ -0,0 +1 @@ +${PARTITION_TABLE_OFFSET} partition_table/partition-table.bin diff --git a/components/esptool_py/flash_project_args.in b/components/esptool_py/flash_project_args.in new file mode 100644 index 000000000..d3eb6f582 --- /dev/null +++ b/components/esptool_py/flash_project_args.in @@ -0,0 +1,7 @@ +--flash_mode ${ESPFLASHMODE} +--flash_size ${ESPFLASHSIZE} +--flash_freq ${ESPFLASHFREQ} +0x1000 bootloader/bootloader.bin +${PARTITION_TABLE_OFFSET} partition_table/partition-table.bin +${APP_PARTITION_OFFSET} ${PROJECT_NAME}.bin +${PHY_PARTITION_OFFSET} ${PHY_PARTITION_BIN_FILE} diff --git a/components/esptool_py/flasher_args.json.in b/components/esptool_py/flasher_args.json.in new file mode 100644 index 000000000..4ec3a8c24 --- /dev/null +++ b/components/esptool_py/flasher_args.json.in @@ -0,0 +1,17 @@ +{ + "write_flash_args" : [ "--flash_mode", "${ESPFLASHMODE}", + "--flash_size", "${ESPFLASHSIZE}", + "--flash_freq", "${ESPFLASHFREQ}" ], + "flash_files" : { + "0x1000" : "bootloader/bootloader.bin", + "${PARTITION_TABLE_OFFSET}" : "partition_table/partition-table.bin", + "${APP_PARTITION_OFFSET}" : "${PROJECT_NAME}.bin", + "${PHY_PARTITION_OFFSET}" : "${PHY_PARTITION_BIN_FILE}" + }, + "bootloader" : { "offset" : "0x1000", + "file" : "bootloader/bootloader.bin" }, + "app" : { "offset" : "${APP_PARTITION_OFFSET}", + "file" : "${PROJECT_NAME}.bin" }, + "partition_table" : { "offset" : "${PARTITION_TABLE_OFFSET}", + "file" : "partition_table/partition-table.bin" } +} diff --git a/components/esptool_py/project_include.cmake b/components/esptool_py/project_include.cmake new file mode 100644 index 000000000..31ce13d66 --- /dev/null +++ b/components/esptool_py/project_include.cmake @@ -0,0 +1,54 @@ +# Set some global esptool.py variables +# +# Many of these are read when generating flash_app_args & flash_project_args +set(ESPTOOLPY "${PYTHON}" "${CMAKE_CURRENT_LIST_DIR}/esptool/esptool.py" --chip esp32) +set(ESPSECUREPY "${PYTHON}" "${CMAKE_CURRENT_LIST_DIR}/esptool/espsecure.py") + +set(ESPFLASHMODE ${CONFIG_ESPTOOLPY_FLASHMODE}) +set(ESPFLASHFREQ ${CONFIG_ESPTOOLPY_FLASHFREQ}) +set(ESPFLASHSIZE ${CONFIG_ESPTOOLPY_FLASHSIZE}) + +set(ESPTOOLPY_SERIAL "${ESPTOOLPY}" --port "${ESPPORT}" --baud ${ESPBAUD}) + +set(ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS + --flash_mode ${ESPFLASHMODE} + --flash_freq ${ESPFLASHFREQ} + --flash_size ${ESPFLASHSIZE} + ) + +if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT) + # Set ESPFLASHSIZE to 'detect' *after* elf2image options are generated, + # as elf2image can't have 'detect' as an option... + set(ESPFLASHSIZE detect) +endif() + +# Set variables if the PHY data partition is in the flash +if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION) + set(PHY_PARTITION_OFFSET ${CONFIG_PHY_DATA_OFFSET}) + set(PHY_PARTITION_BIN_FILE "esp32/phy_init_data.bin") +endif() + +# +# Add 'app.bin' target - generates with elf2image +# +add_custom_command(OUTPUT "${PROJECT_NAME}.bin" + COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS} -o "${PROJECT_NAME}.bin" "${PROJECT_NAME}.elf" + DEPENDS ${PROJECT_NAME}.elf + VERBATIM + ) +add_custom_target(app ALL DEPENDS "${PROJECT_NAME}.bin") + +# +# Add 'flash' target - not all build systems can run this directly +# +function(esptool_py_custom_target target_name flasher_filename dependencies) + add_custom_target(${target_name} DEPENDS ${dependencies} + COMMAND ${ESPTOOLPY} -p ${CONFIG_ESPTOOLPY_PORT} -b ${CONFIG_ESPTOOLPY_BAUD} + write_flash @flash_${flasher_filename}_args + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) +endfunction() + +esptool_py_custom_target(flash project "app;partition_table;bootloader") +esptool_py_custom_target(app-flash app "app") +esptool_py_custom_target(bootloader-flash bootloader "bootloader") diff --git a/components/ethernet/CMakeLists.txt b/components/ethernet/CMakeLists.txt new file mode 100644 index 000000000..165d89fbe --- /dev/null +++ b/components/ethernet/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_SRCDIRS . eth_phy) +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES) +set(COMPONENT_PRIV_REQUIRES tcpip_adapter) + +register_component() diff --git a/components/ethernet/emac_main.c b/components/ethernet/emac_main.c index abdd50bef..f89c56952 100644 --- a/components/ethernet/emac_main.c +++ b/components/ethernet/emac_main.c @@ -275,7 +275,7 @@ static void emac_set_user_config_data(eth_config_t *config ) emac_config.emac_flow_ctrl_enable = config->flow_ctrl_enable; #else if(config->flow_ctrl_enable == true) { - ESP_LOGE(TAG, "eth flow ctrl init err!!! Please run make menuconfig and make sure DMA_RX_BUF_NUM > 9 ."); + ESP_LOGE(TAG, "eth flow ctrl init err!!! Please run menuconfig and make sure DMA_RX_BUF_NUM > 9 ."); } emac_config.emac_flow_ctrl_enable = false; #endif diff --git a/components/expat/CMakeLists.txt b/components/expat/CMakeLists.txt new file mode 100644 index 000000000..0241ae34f --- /dev/null +++ b/components/expat/CMakeLists.txt @@ -0,0 +1,18 @@ +set(COMPONENT_ADD_INCLUDEDIRS port/include include/expat) +set(COMPONENT_SRCDIRS library port) + +set(COMPONENT_REQUIRES) + +register_component() + +component_compile_definitions(HAVE_EXPAT_CONFIG_H) + +# patch around warnings in third-party files +set_source_files_properties( + library/xmlparse.c + PROPERTIES COMPILE_FLAGS + -Wno-unused-function + ) + +# Temporary suppress "fallthrough" warnings until they are fixed in expat repo +component_compile_options(-Wno-implicit-fallthrough) diff --git a/components/fatfs/CMakeLists.txt b/components/fatfs/CMakeLists.txt new file mode 100644 index 000000000..3d24c50bf --- /dev/null +++ b/components/fatfs/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS src) +set(COMPONENT_ADD_INCLUDEDIRS src) + +set(COMPONENT_REQUIRES wear_levelling sdmmc) + +register_component() diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt new file mode 100644 index 000000000..e0618d4a9 --- /dev/null +++ b/components/freertos/CMakeLists.txt @@ -0,0 +1,18 @@ +set(COMPONENT_ADD_INCLUDEDIRS include) +set(COMPONENT_PRIV_INCLUDEDIRS include/freertos) +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_REQUIRES) + +register_component() + +target_link_libraries(freertos "-Wl,--undefined=uxTopUsedPriority") + +set_source_files_properties( + tasks.c + event_groups.c + timers.c + queue.c + ringbuf.c + PROPERTIES COMPILE_DEFINITIONS + _ESP_FREERTOS_INTERNAL + ) diff --git a/components/heap/CMakeLists.txt b/components/heap/CMakeLists.txt new file mode 100644 index 000000000..9c4ccf16d --- /dev/null +++ b/components/heap/CMakeLists.txt @@ -0,0 +1,29 @@ +set(COMPONENT_SRCS heap_caps_init.c heap_caps.c multi_heap.c heap_trace.c) + +if(NOT CONFIG_HEAP_POISONING_DISABLED) + set(COMPONENT_SRCS ${COMPONENT_SRCS} multi_heap_poisoning.c) +endif() + +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES "") + +register_component() + +if(CONFIG_HEAP_TRACING) + set(WRAP_FUNCTIONS + calloc + malloc + free + realloc + heap_caps_malloc + heap_caps_free + heap_caps_realloc + heap_caps_malloc_default + heap_caps_realloc_default) + + foreach(wrap ${WRAP_FUNCTIONS}) + target_link_libraries(heap "-Wl,--wrap=${wrap}") + endforeach() + +endif() diff --git a/components/idf_test/CMakeLists.txt b/components/idf_test/CMakeLists.txt new file mode 100644 index 000000000..cf64054dd --- /dev/null +++ b/components/idf_test/CMakeLists.txt @@ -0,0 +1,3 @@ +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_REQUIRES) +register_component() diff --git a/components/jsmn/CMakeLists.txt b/components/jsmn/CMakeLists.txt new file mode 100644 index 000000000..7c19d9ccb --- /dev/null +++ b/components/jsmn/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS "src") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES "") + +register_component() diff --git a/components/json/CMakeLists.txt b/components/json/CMakeLists.txt new file mode 100644 index 000000000..0b8ba83d6 --- /dev/null +++ b/components/json/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS cJSON) +set(COMPONENT_ADD_INCLUDEDIRS cJSON) + +set(COMPONENT_REQUIRES "") + +register_component() diff --git a/components/libsodium/CMakeLists.txt b/components/libsodium/CMakeLists.txt new file mode 100644 index 000000000..0ad301662 --- /dev/null +++ b/components/libsodium/CMakeLists.txt @@ -0,0 +1,107 @@ +set(SRC libsodium/src/libsodium) + +set(COMPONENT_REQUIRES "mbedtls") + +set(COMPONENT_SRCDIRS + port + + # Derived from libsodium/src/libsodium/Makefile.am + # (ignoring the !MINIMAL set) + ${SRC}/crypto_aead/chacha20poly1305/sodium + ${SRC}/crypto_aead/xchacha20poly1305/sodium + ${SRC}/crypto_auth + ${SRC}/crypto_auth/hmacsha256 + ${SRC}/crypto_auth/hmacsha512 + ${SRC}/crypto_auth/hmacsha512256 + ${SRC}/crypto_box + ${SRC}/crypto_box/curve25519xsalsa20poly1305 + ${SRC}/crypto_core/curve25519/ref10 + ${SRC}/crypto_core/hchacha20 + ${SRC}/crypto_core/hsalsa20/ref2 + ${SRC}/crypto_core/hsalsa20 + ${SRC}/crypto_core/salsa/ref + ${SRC}/crypto_generichash + ${SRC}/crypto_generichash/blake2b + ${SRC}/crypto_generichash/blake2b/ref + ${SRC}/crypto_hash + ${SRC}/crypto_hash/sha256 + ${SRC}/crypto_hash/sha512 + ${SRC}/crypto_kdf/blake2b + ${SRC}/crypto_kdf + ${SRC}/crypto_kx + ${SRC}/crypto_onetimeauth + ${SRC}/crypto_onetimeauth/poly1305 + ${SRC}/crypto_onetimeauth/poly1305/donna + ${SRC}/crypto_pwhash/argon2 + ${SRC}/crypto_pwhash + ${SRC}/crypto_pwhash/scryptsalsa208sha256 + ${SRC}/crypto_pwhash/scryptsalsa208sha256/nosse + ${SRC}/crypto_scalarmult + ${SRC}/crypto_scalarmult/curve25519 + ${SRC}/crypto_scalarmult/curve25519/ref10 + ${SRC}/crypto_secretbox + ${SRC}/crypto_secretbox/xsalsa20poly1305 + ${SRC}/crypto_shorthash + ${SRC}/crypto_shorthash/siphash24 + ${SRC}/crypto_shorthash/siphash24/ref + ${SRC}/crypto_sign + ${SRC}/crypto_sign/ed25519 + ${SRC}/crypto_sign/ed25519/ref10 + ${SRC}/crypto_stream/chacha20 + ${SRC}/crypto_stream/chacha20/ref + ${SRC}/crypto_stream + ${SRC}/crypto_stream/salsa20 + ${SRC}/crypto_stream/salsa20/ref + ${SRC}/crypto_stream/xsalsa20 + ${SRC}/crypto_verify/sodium + ${SRC}/randombytes + ${SRC}/sodium + ) + +if(CONFIG_LIBSODIUM_USE_MBEDTLS_SHA) + set(COMPONENT_SRCDIRS ${COMPONENT_SRCDIRS} + port/crypto_hash_mbedtls + ) +else() + set(COMPONENT_SRCDIRS ${COMPONENT_SRCDIRS} + ${SRC}/crypto_hash/sha256/cp + ${SRC}/crypto_hash/sha512/cp + ) +endif() + +set(COMPONENT_ADD_INCLUDEDIRS ${SRC}/include port_include) +set(COMPONENT_PRIV_INCLUDEDIRS ${SRC}/include/sodium port_include/sodium port) + +register_component() + +component_compile_definitions( + CONFIGURED + NATIVE_LITTLE_ENDIAN + HAVE_WEAK_SYMBOLS + __STDC_LIMIT_MACROS + __STDC_CONSTANT_MACROS + ) + +component_compile_options(-Wno-unknown-pragmas) + +# patch around warnings in third-party files +set_source_files_properties( + ${SRC}/crypto_pwhash/argon2/argon2-fill-block-ref.c + ${SRC}/crypto_pwhash/argon2/pwhash_argon2i.c + ${SRC}/crypto_pwhash/argon2/argon2-core.c + ${SRC}/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c + PROPERTIES COMPILE_FLAGS + -Wno-type-limits + ) +set_source_files_properties( + ${SRC}/sodium/utils.c + PROPERTIES COMPILE_FLAGS + -Wno-unused-variable + ) + +# Temporary suppress "fallthrough" warnings until they are fixed in libsodium repo +set_source_files_properties( + ${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c + ${SRC}/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c + PROPERTIES COMPILE_FLAGS + -Wno-implicit-fallthrough) diff --git a/components/log/CMakeLists.txt b/components/log/CMakeLists.txt new file mode 100644 index 000000000..ad162fe1e --- /dev/null +++ b/components/log/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_REQUIRES) +register_component() diff --git a/components/lwip/CMakeLists.txt b/components/lwip/CMakeLists.txt new file mode 100644 index 000000000..2d362f288 --- /dev/null +++ b/components/lwip/CMakeLists.txt @@ -0,0 +1,41 @@ +set(COMPONENT_ADD_INCLUDEDIRS + include/lwip + include/lwip/port + include/lwip/posix + apps/ping + ) + +if(CONFIG_PPP_SUPPORT) + set(LWIP_PPP_DIRS netif/ppp/polarssl netif/ppp) +endif() + +set(COMPONENT_SRCDIRS + api + apps apps/sntp apps/ping + core core/ipv4 core/ipv6 + ${LWIP_PPP_DIRS} netif + port/freertos port/netif port/debug port) + +set(COMPONENT_REQUIRES vfs) +set(COMPONENT_PRIV_REQUIRES ethernet tcpip_adapter) + +register_component() + +component_compile_options(-Wno-address) + +# patch around warnings in third-party files +set_source_files_properties(api/tcpip.c + PROPERTIES COMPILE_FLAGS + -Wno-unused-variable + ) +set_source_files_properties(core/pbuf.c core/tcp_in.c + PROPERTIES COMPILE_FLAGS + -Wno-unused-but-set-variable + ) +set_source_files_properties(apps/dhcpserver.c + PROPERTIES COMPILE_FLAGS + "-Wno-unused-variable -Wno-unused-but-set-variable -Wno-type-limits" + ) +set_source_files_properties(netif/ppp/pppos.c + PROPERTIES COMPILE_FLAGS + -Wno-type-limits) diff --git a/components/mbedtls/CMakeLists.txt b/components/mbedtls/CMakeLists.txt new file mode 100644 index 000000000..ffac9fea8 --- /dev/null +++ b/components/mbedtls/CMakeLists.txt @@ -0,0 +1,12 @@ +set(COMPONENT_ADD_INCLUDEDIRS port/include mbedtls/include) +set(COMPONENT_SRCDIRS mbedtls/library port) + +set(COMPONENT_SRCEXCLUDE mbedtls/library/net_sockets.c) + +set(COMPONENT_REQUIRES lwip) + +register_component() + +target_compile_definitions(mbedtls PUBLIC + -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h" +) diff --git a/components/mdns/CMakeLists.txt b/components/mdns/CMakeLists.txt new file mode 100644 index 000000000..4ab664110 --- /dev/null +++ b/components/mdns/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_PRIV_INCLUDEDIRS "private_include") +set(COMPONENT_REQUIRES lwip mbedtls console tcpip_adapter) + +register_component() + diff --git a/components/micro-ecc/CMakeLists.txt b/components/micro-ecc/CMakeLists.txt new file mode 100644 index 000000000..24e0a9e6f --- /dev/null +++ b/components/micro-ecc/CMakeLists.txt @@ -0,0 +1,8 @@ +# only compile the micro-ecc/uECC.c source file +set(COMPONENT_SRCS micro-ecc/uECC.c) + +set(COMPONENT_ADD_INCLUDEDIRS micro-ecc) + +set(COMPONENT_REQUIRES) + +register_component() diff --git a/components/newlib/CMakeLists.txt b/components/newlib/CMakeLists.txt new file mode 100644 index 000000000..4bc0db3f9 --- /dev/null +++ b/components/newlib/CMakeLists.txt @@ -0,0 +1,23 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS platform_include include) + +if(CONFIG_SPIRAM_CACHE_WORKAROUND) + set(LIBC c-psram-workaround) + set(LIBM m-psram-workaround) +else() + + if(CONFIG_NEWLIB_NANO_FORMAT) + set(LIBC c_nano) + else() + set(LIBC c) + endif() + + set(LIBM m) +endif() + +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}) diff --git a/components/nghttp/CMakeLists.txt b/components/nghttp/CMakeLists.txt new file mode 100644 index 000000000..c7e4b754b --- /dev/null +++ b/components/nghttp/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_ADD_INCLUDEDIRS port/include nghttp2/lib/includes) +set(COMPONENT_SRCDIRS nghttp2/lib port) + +register_component() diff --git a/components/nvs_flash/CMakeLists.txt b/components/nvs_flash/CMakeLists.txt new file mode 100644 index 000000000..1fe5ecf26 --- /dev/null +++ b/components/nvs_flash/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS src) +set(COMPONENT_ADD_INCLUDEDIRS include) + +set(COMPONENT_REQUIRES spi_flash) + +register_component() diff --git a/components/openssl/CMakeLists.txt b/components/openssl/CMakeLists.txt new file mode 100644 index 000000000..84d02ffe8 --- /dev/null +++ b/components/openssl/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_ADD_INCLUDEDIRS include) +set(COMPONENT_PRIV_INCLUDEDIRS include/internal include/platform include/openssl) +set(COMPONENT_SRCDIRS library platform) + +set(COMPONENT_REQUIRES mbedtls) + +register_component() diff --git a/components/partition_table/CMakeLists.txt b/components/partition_table/CMakeLists.txt new file mode 100644 index 000000000..443a5ad6e --- /dev/null +++ b/components/partition_table/CMakeLists.txt @@ -0,0 +1,70 @@ +register_config_only_component() + +if(NOT BOOTLOADER_BUILD) + +set(partition_csv "${PARTITION_CSV_PATH}") + +if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + set(unsigned_partition_bin "partition-table-unsigned.bin") + set(final_partition_bin "partition-table.bin") + set(final_partition_target "sign_partition_table") +else() + set(unsigned_partition_bin "partition-table.bin") + set(final_partition_bin "partition-table.bin") + set(final_partition_target "build_partition_table") +endif() + +if(CONFIG_PARTITION_TABLE_MD5) + set(md5_opt --disable-md5sum) +endif() + +if(CONFIG_ESPTOOLPY_FLASHSIZE) + set(flashsize_opt --flash-size ${CONFIG_ESPTOOLPY_FLASHSIZE}) +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_csv} ${unsigned_partition_bin} + DEPENDS ${partition_csv} "${CMAKE_CURRENT_SOURCE_DIR}/gen_esp32part.py" + VERBATIM) + +# Add signing steps +if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES) + get_filename_component(secure_boot_signing_key + "${CONFIG_SECURE_BOOT_SIGNING_KEY}" + ABSOLUTE BASE_DIR "${PROJECT_PATH}") + + add_custom_command(OUTPUT "${final_partition_bin}" + COMMAND "${PYTHON}" "${ESPSECUREPY}" sign_data --keyfile "${secure_boot_signing_key}" + -o "${final_partition_bin}" "${unsigned_partition_bin}" + DEPENDS "${unsigned_partition_bin}" + VERBATIM) + +endif() + +if(EXISTS ${partition_csv}) + add_custom_target(partition_table ALL DEPENDS "${final_partition_bin}") +else() + # This is a bit of a hack: If the partition input CSV is not found, create a phony partition_table target that + # fails the build. Have it also touch CMakeCache.txt to cause a cmake run next time + # (to pick up a new CSV if one exists, etc.) + # + # This is because partition CSV is required at CMake runtime (to generate metadata files with flashing data, etc) but we can't + # fail the build if it is not found, because the "menuconfig" target may be required to fix the problem. CMAKE_CONFIGURE_DEPENDS + # only works for files which exist at CMake runtime. + add_custom_target(partition_table ALL + COMMAND ${CMAKE_COMMAND} -E echo "Partition table CSV ${partition_csv} does not exist. Either change partition table in menuconfig or create this input file." + COMMAND ${CMAKE_COMMAND} -E touch "${CMAKE_BINARY_DIR}/CMakeCache.txt" + COMMAND ${CMAKE_COMMAND} -P ${IDF_PATH}/tools/cmake/scripts/fail.cmake) +endif() + +add_dependencies(bootloader partition_table) +add_dependencies(app partition_table) + +# Use global properties ESPTOOL_WRITE_FLASH_ARGS to pass this info to build +# the list of esptool write arguments for flashing +set_property(GLOBAL APPEND_STRING PROPERTY + ESPTOOL_WRITE_FLASH_ARGS + "${PARTITION_TABLE_OFFSET} ${final_partition_bin} ") + +endif() diff --git a/components/partition_table/partitions_singleapp.csv b/components/partition_table/partitions_singleapp.csv index 26b8591aa..22cf97bac 100644 --- a/components/partition_table/partitions_singleapp.csv +++ b/components/partition_table/partitions_singleapp.csv @@ -1,5 +1,5 @@ # 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, +nvs, data, nvs, , 0x6000, +phy_init, data, phy, , 0x1000, +factory, app, factory, , 1M, diff --git a/components/partition_table/partitions_singleapp_coredump.csv b/components/partition_table/partitions_singleapp_coredump.csv index a9f12c0fd..8bcf89c20 100644 --- a/components/partition_table/partitions_singleapp_coredump.csv +++ b/components/partition_table/partitions_singleapp_coredump.csv @@ -1,6 +1,6 @@ # Name, Type, SubType, Offset, Size # 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 -coredump, data, coredump,, 64K +nvs, data, nvs, , 0x6000 +phy_init, data, phy, , 0x1000 +factory, app, factory, , 1M +coredump, data, coredump, , 64K diff --git a/components/partition_table/partitions_two_ota.csv b/components/partition_table/partitions_two_ota.csv index b33f114d1..6ff36afd7 100644 --- a/components/partition_table/partitions_two_ota.csv +++ b/components/partition_table/partitions_two_ota.csv @@ -1,8 +1,9 @@ # 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, 0x4000 -otadata, data, ota, 0xd000, 0x2000 -phy_init, data, phy, 0xf000, 0x1000 -factory, 0, 0, 0x10000, 1M -ota_0, 0, ota_0, , 1M -ota_1, 0, ota_1, , 1M +nvs, data, nvs, , 0x4000, +otadata, data, ota, , 0x2000, +phy_init, data, phy, , 0x1000, +factory, app, factory, , 1M, +ota_0, app, ota_0, , 1M, +ota_1, app, ota_1, , 1M, + diff --git a/components/partition_table/partitions_two_ota_coredump.csv b/components/partition_table/partitions_two_ota_coredump.csv index 64d70b0d8..3a2143690 100644 --- a/components/partition_table/partitions_two_ota_coredump.csv +++ b/components/partition_table/partitions_two_ota_coredump.csv @@ -1,9 +1,9 @@ # Name, Type, SubType, Offset, Size # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild -nvs, data, nvs, 0x9000, 0x4000 -otadata, data, ota, 0xd000, 0x2000 -phy_init, data, phy, 0xf000, 0x1000 -factory, 0, 0, 0x10000, 1M +nvs, data, nvs, , 0x4000 +otadata, data, ota, , 0x2000 +phy_init, data, phy, , 0x1000 +factory, 0, 0, , 1M coredump, data, coredump,, 64K ota_0, 0, ota_0, , 1M ota_1, 0, ota_1, , 1M diff --git a/components/partition_table/parttool.py b/components/partition_table/parttool.py index 8188dfe3d..145fb8d3c 100755 --- a/components/partition_table/parttool.py +++ b/components/partition_table/parttool.py @@ -49,6 +49,8 @@ def main(): parser.add_argument('--quiet', '-q', help="Don't print status messages to stderr", action='store_true') + parser.add_argument('--partition-table-offset', help='The offset of the partition table in flash. Only consulted if partition table is in CSV format.', type=str, default='0x8000') + search_type = parser.add_mutually_exclusive_group() search_type.add_argument('--partition-name', '-p', help='The name of the required partition', type=str, default=None) search_type.add_argument('--type', '-t', help='The type of the required partition', type=str, default=None) @@ -74,6 +76,8 @@ def main(): quiet = args.quiet + gen.offset_part_table = int(args.partition_table_offset, 0) + input = args.input.read() input_is_binary = input[0:2] == gen.PartitionDefinition.MAGIC_BYTES if input_is_binary: diff --git a/components/partition_table/project_include.cmake b/components/partition_table/project_include.cmake new file mode 100644 index 000000000..ff2464437 --- /dev/null +++ b/components/partition_table/project_include.cmake @@ -0,0 +1,54 @@ +if(NOT BOOTLOADER_BUILD) + +set(PARTITION_TABLE_OFFSET ${CONFIG_PARTITION_TABLE_OFFSET}) + +# Set PARTITION_CSV_PATH to the configured partition CSV file +# 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}") + + if(NOT EXISTS "${PARTITION_CSV_PATH}") + message(WARNING "Partition table CSV file ${PARTITION_CSV_PATH} not found. " + "Change custom partition CSV path in menuconfig.") + # Note: partition_table CMakeLists.txt contains some logic to create a dummy + # partition_table target in this case, see comments in that file. + endif() +else() + # Other .csv files are always in the component directory + get_filename_component(PARTITION_CSV_PATH "${COMPONENT_PATH}/${CONFIG_PARTITION_TABLE_FILENAME}" ABSOLUTE) + + if(NOT EXISTS "${PARTITION_CSV_PATH}") + message(FATAL_ERROR "Internal error, built-in ${PARTITION_CSV_PATH} not found.") + endif() +endif() + +# need to re-run CMake if the partition CSV changes, as the offsets/sizes of partitions may change +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${PARTITION_CSV_PATH}) + +# Parse the partition table to get variable partition offsets & sizes which must be known at CMake runtime +function(get_partition_info variable get_part_info_args) + separate_arguments(get_part_info_args) + execute_process(COMMAND ${PYTHON} + ${COMPONENT_PATH}/parttool.py -q + --partition-table-offset ${PARTITION_TABLE_OFFSET} + ${get_part_info_args} + ${PARTITION_CSV_PATH} + OUTPUT_VARIABLE result + RESULT_VARIABLE exit_code + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT ${exit_code} EQUAL 0) + # can't fail here as it would prevent the user from running 'menuconfig' again + message(WARNING "parttool.py execution failed, problem with partition CSV file (see above)") + endif() + set(${variable} ${result} PARENT_SCOPE) +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") +endif() + +get_partition_info(APP_PARTITION_OFFSET "--default-boot-partition --offset") + +endif() diff --git a/components/pthread/CMakeLists.txt b/components/pthread/CMakeLists.txt new file mode 100644 index 000000000..0b93e09ed --- /dev/null +++ b/components/pthread/CMakeLists.txt @@ -0,0 +1,8 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_REQUIRES) +register_component() + +if(CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK) + target_link_libraries(pthread "-Wl,--wrap=vPortCleanUpTCB") +endif() diff --git a/components/sdmmc/CMakeLists.txt b/components/sdmmc/CMakeLists.txt new file mode 100644 index 000000000..58b9aeb67 --- /dev/null +++ b/components/sdmmc/CMakeLists.txt @@ -0,0 +1,4 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_REQUIRES driver) +register_component() diff --git a/components/smartconfig_ack/CMakeLists.txt b/components/smartconfig_ack/CMakeLists.txt new file mode 100644 index 000000000..8b18007de --- /dev/null +++ b/components/smartconfig_ack/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_PRIV_REQUIRES lwip tcpip_adapter) + +register_component() diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt new file mode 100644 index 000000000..b4c088edd --- /dev/null +++ b/components/soc/CMakeLists.txt @@ -0,0 +1,9 @@ +set(SOC_NAME esp32) + +set(COMPONENT_SRCDIRS ${SOC_NAME}) +set(COMPONENT_ADD_INCLUDEDIRS ${SOC_NAME}/include include) + +set(COMPONENT_REQUIRES) + + +register_component() diff --git a/components/spi_flash/CMakeLists.txt b/components/spi_flash/CMakeLists.txt new file mode 100644 index 000000000..1eafba54d --- /dev/null +++ b/components/spi_flash/CMakeLists.txt @@ -0,0 +1,14 @@ +if(BOOTLOADER_BUILD) + # Bootloader needs SPIUnlock from this file, but doesn't + # need other parts of this component + set(COMPONENT_SRCS spi_flash_rom_patch.c) + set(COMPONENT_PRIV_REQUIRES bootloader_support) +else() + set(COMPONENT_SRCDIRS .) + set(COMPONENT_PRIV_REQUIRES bootloader_support app_update) +endif() + +set(COMPONENT_ADD_INCLUDEDIRS include) +set(COMPONENT_REQUIRES) + +register_component() diff --git a/components/spiffs/CMakeLists.txt b/components/spiffs/CMakeLists.txt new file mode 100644 index 000000000..54356cb0d --- /dev/null +++ b/components/spiffs/CMakeLists.txt @@ -0,0 +1,9 @@ +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_PRIV_INCLUDEDIRS "." "spiffs/src") +set(COMPONENT_SRCDIRS "." "spiffs/src") + +set(COMPONENT_REQUIRES spi_flash) +set(COMPONENT_PRIV_REQUIRES bootloader_support) + +register_component() + diff --git a/components/tcpip_adapter/CMakeLists.txt b/components/tcpip_adapter/CMakeLists.txt new file mode 100644 index 000000000..24deb2f24 --- /dev/null +++ b/components/tcpip_adapter/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES lwip) + +register_component() diff --git a/components/ulp/CMakeLists.txt b/components/ulp/CMakeLists.txt new file mode 100644 index 000000000..fc21f1eca --- /dev/null +++ b/components/ulp/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES) + +register_component() diff --git a/components/vfs/CMakeLists.txt b/components/vfs/CMakeLists.txt new file mode 100644 index 000000000..fc21f1eca --- /dev/null +++ b/components/vfs/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES) + +register_component() diff --git a/components/wear_levelling/CMakeLists.txt b/components/wear_levelling/CMakeLists.txt new file mode 100644 index 000000000..8b5db6231 --- /dev/null +++ b/components/wear_levelling/CMakeLists.txt @@ -0,0 +1,5 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") +set(COMPONENT_PRIV_INCLUDEDIRS private_include) +set(COMPONENT_REQUIRES spi_flash) +register_component() diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt new file mode 100644 index 000000000..2f63ff398 --- /dev/null +++ b/components/wpa_supplicant/CMakeLists.txt @@ -0,0 +1,25 @@ +set(COMPONENT_SRCDIRS src/crypto port src/fast_crypto src/wpa2/eap_peer src/wpa2/tls src/wpa2/utils src/wps) +set(COMPONENT_ADD_INCLUDEDIRS include port/include) + +set(COMPONENT_REQUIRES "") +set(COMPONENT_PRIV_REQUIRES mbedtls) + +register_component() + +component_compile_options(-Wno-strict-aliasing) +component_compile_definitions( + __ets__ + EMBEDDED_SUPP + IEEE8021X_EAPOL + EAP_PEER_METHOD + EAP_MSCHAPv2 + EAP_TTLS + EAP_TLS + EAP_PEAP + USE_WPA2_TASK + CONFIG_WPS2 + CONFIG_WPS_PIN + USE_WPS_TASK + ESPRESSIF_USE + ESP32_WORKAROUND + ) diff --git a/components/xtensa-debug-module/CMakeLists.txt b/components/xtensa-debug-module/CMakeLists.txt new file mode 100644 index 000000000..810d299d1 --- /dev/null +++ b/components/xtensa-debug-module/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS "include") + +set(COMPONENT_REQUIRES "") + +register_component() diff --git a/docs/_static/what-you-need-cmake.png b/docs/_static/what-you-need-cmake.png new file mode 100644 index 000000000..d088be085 Binary files /dev/null and b/docs/_static/what-you-need-cmake.png differ diff --git a/docs/conf_common.py b/docs/conf_common.py index 56a08806f..843943e2d 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -16,7 +16,7 @@ import sys, os import re -from subprocess import Popen, PIPE +import subprocess import shlex # Note: If extensions (or modules to document with autodoc) are in another directory, @@ -44,10 +44,21 @@ if os.system('python ../gen-dxd.py') != 0: raise RuntimeError('gen-dxd.py failed') # Generate 'kconfig.inc' file from components' Kconfig files +print("Generating kconfig.inc from kconfig contents") kconfig_inc_path = '{}/inc/kconfig.inc'.format(builddir) -if os.system('python ../gen-kconfig-doc.py > ' + kconfig_inc_path + '.in') != 0: - raise RuntimeError('gen-kconfig-doc.py failed') - +temp_sdkconfig_path = '{}/sdkconfig.tmp'.format(builddir) +kconfigs = subprocess.check_output(["find", "../../components", "-name", "Kconfig"]).decode() +kconfig_projbuilds = subprocess.check_output(["find", "../../components", "-name", "Kconfig.projbuild"]).decode() +confgen_args = ["python", + "../../tools/kconfig_new/confgen.py", + "--kconfig", "../../Kconfig", + "--config", temp_sdkconfig_path, + "--create-config-if-missing", + "--env", "COMPONENT_KCONFIGS={}".format(kconfigs), + "--env", "COMPONENT_KCONFIGS_PROJBUILD={}".format(kconfig_projbuilds), + "--output", "docs", kconfig_inc_path + '.in' +] +subprocess.check_call(confgen_args) copy_if_modified(kconfig_inc_path + '.in', kconfig_inc_path) # Generate 'esp_err_defs.inc' file with ESP_ERR_ error code definitions diff --git a/docs/en/api-guides/build-system-cmake.rst b/docs/en/api-guides/build-system-cmake.rst new file mode 100644 index 000000000..b7aae2dda --- /dev/null +++ b/docs/en/api-guides/build-system-cmake.rst @@ -0,0 +1,942 @@ +Build System (CMake) +******************** + +.. include:: ../cmake-warning.rst + +.. include:: ../cmake-pending-features.rst + +This document explains the implementation of the CMake-based ESP-IDF build system and the concept of "components". :doc:`Documentation for the GNU Make based build system ` is also available + +Read this document if you want to know how to organise and build a new ESP-IDF project or component using the CMake-based build system. + + +Overview +======== + +An ESP-IDF project can be seen as an amalgamation of a number of components. +For example, for a webserver that shows the current humidity, there could be: + +- The ESP32 base libraries (libc, ROM bindings, etc) +- The WiFi drivers +- A TCP/IP stack +- The FreeRTOS operating system +- A webserver +- A driver for the humidity sensor +- Main code tying it all together + +ESP-IDF makes these components explicit and configurable. To do that, +when a project is compiled, the build system will look up all the +components in the ESP-IDF directories, the project directories and +(optionally) in additional custom component directories. It then +allows the user to configure the ESP-IDF project using a a text-based +menu system to customize each component. After the components in the +project are configured, the build system will compile the project. + +Concepts +-------- + +- A "project" is a directory that contains all the files and configuration to build a single "app" (executable), as well as additional supporting elements such as a partition table, data/filesystem partitions, and a bootloader. + +- "Project configuration" is held in a single file called ``sdkconfig`` in the root directory of the project. This configuration file is modified via ``idf.py menuconfig`` to customise the configuration of the project. A single project contains exactly one project configuration. + +- An "app" is an executable which is built by ESP-IDF. A single project will usually build two apps - a "project app" (the main executable, ie your custom firmware) and a "bootloader app" (the initial bootloader program which launches the project app). + +- "components" are modular pieces of standalone code which are compiled into static libraries (.a files) and linked into an app. Some are provided by ESP-IDF itself, others may be sourced from other places. + +Some things are not part of the project: + +- "ESP-IDF" is not part of the project. Instead it is standalone, and linked to the project via the ``IDF_PATH`` environment variable which holds the path of the ``esp-idf`` directory. This allows the IDF framework to be decoupled from your project. + +- The toolchain for compilation is not part of the project. The toolchain should be installed in the system command line PATH. + +Using the Build System +====================== + +.. _idf.py: + +idf.py +------ + +The ``idf.py`` command line tool provides a front-end for easily managing your project builds. It manages the following tools: + +- CMake_, which configures the project to be built +- A command line build tool (either Ninja_ build or `GNU Make`) +- `esptool.py`_ for flashing ESP32. + +The :ref:`getting started guide ` contains a brief introduction to how to set up ``idf.py`` to configure, build, and flash projects. + +``idf.py`` should be run in an ESP-IDF "project" directory, ie one containing a ``CMakeLists.txt`` file. Older style projects with a Makefile will not work with ``idf.py``. + +Type ``idf.py --help`` for a full list of commands. Here are a summary of the most useful ones: + +- ``idf.py menuconfig`` runs the "menuconfig" tool to configure the project. +- ``idf.py build`` will build the project found in the current directory. This can involve multiple steps: + + - Create the build directory if needed. The sub-directory ``build`` is used to hold build output, although this can be changed with the ``-B`` option. + - Run CMake_ as necessary to configure the project and generate build files for the main build tool. + - Run the main build tool (Ninja_ or `GNU Make`). By default, the build tool is automatically detected but it can be explicitly set by passing the ``-G`` option to ``idf.py``. + + Building is incremental so if no source files or configuration has changed since the last build, nothing will be done. +- ``idf.py clean`` will "clean" the project by deleting build output files from the build directory, forcing a "full rebuild" the next time the project is built. Cleaning doesn't delete CMake configuration output and some other files. +- ``idf.py fullclean`` will delete the entire "build" directory contents. This includes all CMake configuration output. The next time the project is built, CMake will configure it from scratch. Note that this option recursively deletes *all* files in the build directory, so use with care. Project configuration is not deleted. +- ``idf.py reconfigure`` re-runs CMake_ even if it doesn't seem to need re-running. This isn't necessary during normal usage, but can be useful after adding/removing files from the source tree. +- ``idf.py flash`` will automatically build the project if necessary, and then flash it to an ESP32. The ``-p`` and ``-b`` options can be used to set serial port name and flasher baud rate, respectively. +- ``idf.py monitor`` will display serial output from the ESP32. The ``-p`` option can be used to set the serial port name. Type ``Ctrl-]`` to exit the monitor. See :doc:`/get-started/idf-monitor` for more details about using the monitor. + +Multiple ``idf.py`` commands can be combined into one. For example, ``idf.py -p COM4 clean flash monitor`` will clean the source tree, then build the project and flash it to the ESP32 before running the serial monitor. + +.. note:: The environment variables ``ESPPORT`` and ``ESPBAUD`` can be used to set default values for the ``-p`` and ``-b`` options, respectively. Providing these options on the command line overrides the default. + +Advanced Commands +^^^^^^^^^^^^^^^^^ + +- ``idf.py app``, ``idf.py bootloader``, ``idf.py partition_table`` can be used to build only the app, bootloader, or partition table from the project as applicable. +- There are matching commands ``idf.py app-flash``, etc. to flash only that single part of the project to the ESP32. +- ``idf.py -p PORT erase_flash`` will use esptool.py to erase the ESP32's entire flash chip. +- ``idf.py size`` prints some size information about the app. ``size-components`` and ``size-files`` are similar commands which print more detailed per-component or per-source-file information, respectively. + +The order of multiple ``idf.py`` commands on the same invocation is not important, they will automatically be executed in the correct order for everything to take effect (ie building before flashing, erasing before flashing, etc.). + +Using CMake Directly +-------------------- + +:ref:`idf.py` is a wrapper around CMake_ for convenience. However, you can also invoke CMake directly if you prefer. + +.. highlight:: bash + +When ``idf.py`` does something, it prints each command that it runs for easy reference. For example, the ``idf.py build`` command is the same as running these commands in a bash shell (or similar commands for Windows Command Prompt):: + + mkdir -p build + cd build + cmake .. -G Ninja # or 'Unix Makefiles' + ninja + +In the above list, the ``cmake`` command configures the project and generates build files for use with the final build tool. In this case the final build tool is Ninja_: running ``ninja`` actually builds the project. + +It's not necessary to run ``cmake`` more than once. After the first build, you only need to run ``ninja`` each time. ``ninja`` will automatically re-invoke ``cmake`` if the project needs reconfiguration. + +If using CMake with ``ninja`` or ``make``, there are also targets for more of the ``idf.py`` sub-commands - for example running ``make menuconfig`` or ``ninja menuconfig`` in the build directory will work the same as ``idf.py menuconfig``. + +.. note:: + If you're already familiar with CMake_, you may find the ESP-IDF CMake-based build system unusual because it wraps a lot of CMake's functionality to reduce boilerplate. See `writing pure CMake components`_ for some information about writing more "CMake style" components. + +Using CMake in an IDE +--------------------- + +You can also use an IDE with CMake integration. The IDE will want to know the path to the project's ``CMakeLists.txt`` file. IDEs with CMake integration often provide their own build tools (CMake calls these "generators") to build the source files as part of the IDE. + +When adding custom non-build steps like "flash" to the IDE, it is recommended to execute ``idf.py`` for these "special" commands. + +For more detailed information about integrating ESP-IDF with CMake into an IDE, see `Build System Metadata`_. + +.. setting-python-interpreter: + +Setting the Python Interpreter +------------------------------ + +Currently, ESP-IDF only works with Python 2.7. If you have a system where the default ``python`` interpreter is Python 3.x, this can lead to problems. + +If using ``idf.py``, running ``idf.py`` as ``python2 $IDF_PATH/tools/idf.py ...`` will work around this issue (``idf.py`` will tell other Python processes to use the same Python interpreter). You can set up a shell alias or another script to simplify the command. + +If using CMake directly, running ``cmake -D PYTHON=python2 ...`` will cause CMake to override the default Python interpreter. + +If using an IDE with CMake, setting the ``PYTHON`` value as a CMake cache override in the IDE UI will override the default Python interpreter. + +To manage the Python version more generally via the command line, check out the tools pyenv_ or virtualenv_. These let you change the default python version. + +.. _example-project-structure: + +Example Project +=============== + +.. highlight:: none + +An example project directory tree might look like this:: + + - myProject/ + - CMakeLists.txt + - sdkconfig + - components/ - component1/ - CMakeLists.txt + - Kconfig + - src1.c + - component2/ - CMakeLists.txt + - Kconfig + - src1.c + - include/ - component2.h + - main/ - src1.c + - src2.c + + - build/ + +This example "myProject" contains the following elements: + +- A top-level project CMakeLists.txt file. This is the primary file which CMake uses to learn how to build the project. The project CMakeLists.txt file sets the ``MAIN_SRCS`` variable which lists all of the source files in the "main" directory (part of this project's executable). It may set other project-wide CMake variables, as well. Then it includes the file :idf_file:`/tools/cmake/project.cmake` which + implements the rest of the build system. Finally, it sets the project name and defines the project. + +- "sdkconfig" project configuration file. This file is created/updated when ``idf.py menuconfig`` runs, and holds configuration for all of the components in the project (including ESP-IDF itself). The "sdkconfig" file may or may not be added to the source control system of the project. + +- Optional "components" directory contains components that are part of the project. A project does not have to contain custom components of this kind, but it can be useful for structuring reusable code or including third party components that aren't part of ESP-IDF. + +- "main" directory is a special "by convention" directory that contains source code for the project executable itself. These source files are listed in the project's CMakeLists file. You don't need to name this directory "main", but we recommend you follow this convention. If you have a lot of source files in your project, we recommend grouping most into components instead of putting them all in "main". + +- "build" directory is where build output is created. This directory is created by ``idf.py`` if it doesn't already exist. CMake configures the project and generates interim build files in this directory. Then, after the main build process is run, this directory will also contain interim object files and libraries as well as final binary output files. This directory is usually not added to source control or distributed with the project source code. + +Component directories each contain a component ``CMakeLists.txt`` file. This file contains variable definitions +to control the build process of the component, and its integration into the overall project. See `Component CMakeLists Files`_ for more details. + +Each component may also include a ``Kconfig`` file defining the `component configuration`_ options that can be set via ``menuconfig``. Some components may also include ``Kconfig.projbuild`` and ``project_include.cmake`` files, which are special files for `overriding parts of the project`_. + +Project CMakeLists File +======================= + +Each project has a single top-level ``CMakeLists.txt`` file that contains build settings for the entire project. By default, the project CMakeLists can be quite minimal. + +Minimal Example CMakeLists +-------------------------- + +.. highlight:: cmake + +Minimal project:: + + cmake_minimum_required(VERSION 3.5) + + set(MAIN_SRCS main/src1.c main/src2.c) + + include($ENV{IDF_PATH}/tools/cmake/project.cmake) + project(myProject) + + +.. _project-mandatory-parts: + +Mandatory Parts +--------------- + +The inclusion of these four lines, in the order shown above, is necessary for every project: + +- ``cmake_minimum_required(VERSION 3.5)`` tells CMake what version is required to build the project. ESP-IDF is designed to work with CMake 3.5 or newer. This line must be the first line in the CMakeLists.txt file. +- ``set(MAIN_SRCS xxx)`` sets a variable - ``MAIN_SRCS`` to be a list of the "main" source files in the project. Paths are relative to the CMakeLists. They don't specifically need to be under the "main" sub-directory, but this structure is encouraged. + + It is *strongly recommended not to add a lot of files to the MAIN_SRCS list*. If you have a lot of source files then it recommended to organise them functionally into individual components under the project "components" directory. This will make your project more maintainable, reusable, and easier to configure. Components are further explained below. + + ``MAIN_SRCS`` must name at least one source file (although that file doesn't need to necessarily include an ``app_main()`` function or anything else). +- ``include($ENV{IDF_PATH}/tools/cmake/project.cmake)`` pulls in the rest of the CMake functionality to configure the project, discover all the components, etc. +- ``project(myProject)`` creates the project itself, and specifies the project name. The project name is used for the final binary output files of the app - ie ``myProject.elf``, ``myProject.bin``. Only one project can be defined per CMakeLists file. + + +Optional Project Variables +-------------------------- + +These variables all have default values that can be overridden for custom behaviour. Look in :idf_file:`/tools/cmake/project.cmake` for all of the implementation details. + +- ``COMPONENT_DIRS``: Directories to search for components. Defaults to `${IDF_PATH}/components`, `${PROJECT_PATH}/components`, and ``EXTRA_COMPONENT_DIRS``. Override this variable if you don't want to search for components in these places. +- ``EXTRA_COMPONENT_DIRS``: Optional list of additional directories to search for components. Paths can be relative to the project directory, or absolute. +- ``COMPONENTS``: A list of component names to build into the project. Defaults to all components found in the ``COMPONENT_DIRS`` directories. Use this variable to "trim down" the project for faster build times. Note that any component which "requires" another component via ``COMPONENT_REQUIRES`` will automatically have it added to this list, so the ``COMPONENTS`` list can be very short. +- ``COMPONENT_REQUIRES_COMMON``: A list of components that every component requires. These components are automatically added to every component's ``COMPONENT_PRIV_REQUIRES`` list and also the project's ``COMPONENTS`` list. By default, this variable is set to the minimal set of core "system" components needed for any ESP-IDF project. Usually, you would not change this variable in your project. + +Any paths in these variables can be absolute paths, or set relative to the project directory. + +To set these variables, use the `cmake set command `_ ie ``set(VARIABLE "VALUE")``. The ``set()`` commands should be placed after the ``cmake_minimum(...)`` line but before the ``include(...)`` line. + +.. _component-directories-cmake: + +Component CMakeLists Files +========================== + +Each project contains one or more components. Components can be part of ESP-IDF, part of the project's own components directory, or added from custom component directories (:ref:`see above `). + +A component is any directory in the ``COMPONENT_DIRS`` list which contains a ``CMakeLists.txt`` file. + +Searching for Components +------------------------ + +The list of directories in ``COMPONENT_DIRS`` is searched for the project's components. Directories in this list can either be components themselves (ie they contain a `CMakeLists.txt` file), or they can be top-level directories whose sub-directories are components. + +When CMake runs to configure the project, it logs the components included in the build. This list can be useful for debugging the inclusion/exclusion of certain components. + +Multiple components with the same name +-------------------------------------- + +When ESP-IDF is collecting all the components to compile, it will do this in the order specified by ``COMPONENT_DIRS``; by default, this means ESP-IDF's internal components first, then the project's components, and finally any components set in ``EXTRA_COMPONENT_DIRS``. If two or more of these directories +contain component sub-directories with the same name, the component in the last place searched is used. This allows, for example, overriding ESP-IDF components +with a modified version by copying that component from the ESP-IDF components directory to the project components directory and then modifying it there. +If used in this way, the ESP-IDF directory itself can remain untouched. + +Minimal Component CMakeLists +---------------------------- + +.. highlight:: cmake + +The minimal component ``CMakeLists.txt`` file is as follows:: + + set(COMPONENT_SRCDIRS ".") + set(COMPONENT_ADD_INCLUDEDIRS "include") + register_component() + +- ``COMPONENT_SRCDIRS`` is a (space-separated) list of directories to search for source files. Source files (``*.c``, ``*.cpp``, ``*.cc``, ``*.S``) in these directories will be compiled into the component library. +- ``COMPONENT_ADD_INCLUDEDIRS`` is a (space-separated) list of directories to add to the global include search path for any component which requires this component, and also the main source files. +- ``register_component()`` is required to add the component (using the variables set above) to the build. A library with the name of the component will be built and linked into the final app. If this step is skipped (perhaps due to use of a CMake `if function `_ or similar), this component will not be part of the build. + +Directories are usually specified relative to the ``CMakeLists.txt`` file itself, although they can be absolute. + +See `example component CMakeLists`_ for more complete component ``CMakeLists.txt`` examples. + +.. _component variables: + +Preset Component Variables +-------------------------- + +The following component-specific variables are available for use inside component CMakeLists, but should not be modified: + +- ``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. + +The following variables are set at the project level, but available for use in component CMakeLists: + +- ``PROJECT_NAME``: Name of the project, as set in project Makefile +- ``PROJECT_PATH``: Absolute path of the project directory containing the project Makefile. Same as the ``CMAKE_SOURCE_DIR`` variable. +- ``COMPONENTS``: Names of all components that are included in this build, formatted as a semicolon-delimited CMake list. +- ``CONFIG_*``: Each value in the project configuration has a corresponding variable available in make. All names begin with ``CONFIG_``. :doc:`More information here `. +- ``IDF_VER``: Git version of ESP-IDF (produced by ``git describe``) + +If you modify any of these variables inside ``CMakeLists.txt`` then this will not prevent other components from building but it may make your component hard to build and/or debug. + +- ``COMPONENT_ADD_INCLUDEDIRS``: Paths, relative to the component directory, which will be added to the include search path for + all other components which require this one. If an include directory is only needed to compile this specific component, + add it to ``COMPONENT_PRIV_INCLUDEDIRS`` instead. +- ``COMPONENT_REQUIRES`` is a (space-separated) list of components that are required to include this project's header files into other components. If this component has a header file in a ``COMPONENT_ADD_INCLUDEDIRS`` directory that includes a header from another component, that component should be listed in ``COMPONENT_REQUIRES``. Requirements are recursive. + + The ``COMPONENT_REQUIRES`` list can be empty because some very common components (like newlib for libc, freertos for RTOS functions, etc) are always required by all components. This list is found in the project-level variable ``COMPONENT_REQUIRES_COMMON``. + + If a component only requires another component's headers to compile its source files (not for including this component's headers), then these components should be listed in ``COMPONENT_PRIV_REQUIRES`` instead. + + See `Component Requirements`_ for more details. + +Optional Component-Specific Variables +------------------------------------- + +The following variables can be set inside ``component.mk`` to control the build of that component: + +- ``COMPONENT_PRIV_INCLUDEDIRS``: Directory paths, must be relative to + the component directory, which will be added to the include search + path for this component's source files only. +- ``COMPONENT_PRIV_REQUIRES`` is a (space-separated) list of components that are required to either compile or link this component's source files. These components' header paths do not propagate to other components which require it, they are only used to compile this component's sources. See `Component Requirements`_ for more details. +- ``COMPONENT_SRCDIRS``: Directory paths, must be relative to the component directory, which will be searched for source files (``*.cpp``, + ``*.c``, ``*.S``). Set this to specify a list of directories which contain source files. +- ``COMPONENT_SRCS``: Paths to individual source files to compile. Setting this causes ``COMPONENT_SRCDIRS`` to be ignored. Setting this variable instead gives you finer grained control over which files are compiled. + If you don't set ``COMPONENT_SRCDIRS`` or ``COMPONENT_SRCS``, your component won't compile a library but it may still add include paths for use when compiling other components or the source files listed in ``MAIN_SRCS``. +- ``COMPONENT_SRCEXCLUDE``: Paths to source files to exclude from component. Can be set in conjunction with ``COMPONENT_SRCDIRS`` if there is a directory with a large number of source files to include in the component but one or more source files which should not be. Paths can be specified relative to the component directory or absolute. + +Controlling Component Compilation +--------------------------------- + +.. highlight:: cmake + +To pass compiler options when compiling source files belonging to a particular component, use the ``component_compile_options`` function:: + + component_compile_options(-Wno-unused-variable) + +This is a wrapper around the CMake `target_compile_options`_ command. + +To apply the compilation flags to a single source file, use the CMake `set_source_files_properties`_ command:: + + set_source_files_properties(mysrc.c + PROPERTIES COMPILE_FLAGS + -Wno-unused-variable + ) + +This can be useful if there is upstream code that emits warnings. + +When using these commands, place them after the ``register_component()`` line in the component CMakeLists file. + +.. _component-configuration-cmake: + +Component Configuration +======================= + +Each component can also have a ``Kconfig`` file, alongside ``CMakeLists.txt``. This contains +configuration settings to add to the configuration menu for this component. + +These settings are found under the "Component Settings" menu when menuconfig is run. + +To create a component Kconfig file, it is easiest to start with one of the Kconfig files distributed with ESP-IDF. + +For an example, see `Adding conditional configuration`_. + +Preprocessor Definitions +======================== + +The ESP-IDF build system adds the following C preprocessor definitions on the command line: + +- ``ESP_PLATFORM`` — Can be used to detect that build happens within ESP-IDF. +- ``IDF_VER`` — Defined to a git version string. E.g. ``v2.0`` for a tagged release or ``v1.0-275-g0efaa4f`` for an arbitrary commit. + +Component Requirements +====================== + +When compiling each component, the ESP-IDF build system recursively evaluates its components. + +Each component's source file is compiled with these include path directories: + +- The current component's ``COMPONENT_ADD_INCLUDEDIRS`` and ``COMPONENT_PRIV_INCLUDEDIRS``. +- The ``COMPONENT_ADD_INCLUDEDIRS`` set by all components in the current component's ``COMPONENT_REQUIRES`` and ``COMPONENT_PRIV_REQUIRES`` variables (ie all the current component's public and private dependencies). +- All of the ``COMPONENT_REQUIRES`` of those components, evaluated recursively (ie all public dependencies of this component's dependencies, recursively expanded). + +When writing a component +------------------------ + +- ``COMPONENT_REQUIRES`` should be set to all components whose header files are #included from the *public* header files of this component. +- ``COMPONENT_PRIV_REQUIRES`` should be set to all components whose header files are #included from *any source files* of this component, unless already listed in ``COMPONENT_REQUIRES``. Or any component which is required to be linked in order for this component to function correctly. +- ``COMPONENT_REQUIRES`` and/or ``COMPONENT_PRIV_REQUIRES`` should be set before calling ``register_component()``. +- The values of ``COMPONENT_REQUIRES`` and ``COMPONENT_PRIV_REQUIRES`` should not depend on any configuration choices (``CONFIG_xxx`` macros). This is because requirements are expanded before configuration is loaded. Other component variables (like include paths or source files) can depend on configuration choices. +- Not setting either or both ``REQUIRES`` variables is fine. If the component has no requirements except for the "common" components needed for RTOS, libc, etc (``COMPONENT_REQUIRES_COMMON``) then both variables can be empty or unset. + +When creating a project +----------------------- + +- By default, every component is included in the build. +- If you set the ``COMPONENTS`` variable to a minimal list of components used directly by your project, then the build will include: + - Components mentioned explicitly in ``COMPONENTS``. + - Those components' requirements (evaluated recursively). + - The "common" components that every component depends on. +- Setting ``COMPONENTS`` to the minimal list of required components can significantly reduce compile times. +- When compiling the project's source files (``MAIN_SRCS``), the public header directories (``COMPONENT_ADD_INCLUDEDIRS`` list) of all components included in the build are available. + +.. _component-requirements-implementation: + +Requirements in the build system implementation +----------------------------------------------- + +- Very early in the CMake configuration process, the script ``expand_requirements.cmake`` is run. This script does a partial evaluation of all component CMakeLists.txt files and builds a graph of component requirements (this graph may have cycles). The graph is used to generate a file ``component_depends.cmake`` in the build directory. +- The main CMake process then includes this file and uses it to determine the list of components to include in the build (internal ``BUILD_COMPONENTS`` variable). +- Configuration is then evaluated for the components included in the build. +- Each component is included in the build normally and the CMakeLists.txt file is evaluated again to add the component libraries to the build. + +Build Process Internals +======================= + +For full details about CMake_ and CMake commands, see the `CMake v3.5 documentation`_. + +project.cmake contents +---------------------- + +When included from a project CMakeLists file, the ``project.cmake`` file defines some utility modules and global variables and then sets ``IDF_PATH`` if it was not set in the system environment. + +It also defines an overridden custom version of the built-in CMake_ ``project`` function. This function is overridden to add all of the ESP-IDF specific project functionality. + +project function +---------------- + +The custom ``project()`` function performs the following steps: + +- Evaluates component dependencies and builds the ``BUILD_COMPONENTS`` list of components to include in the build (see :ref:`above`). +- Finds all components in the project (searching ``COMPONENT_DIRS`` and filtering by ``COMPONENTS`` if this is set). +- Loads the project configuration from the ``sdkconfig`` file and generates a ``sdkconfig.cmake`` file and a ``sdkconfig.h`` header. These define configuration values in CMake and C/C++, respectively. If the project configuration changes, cmake will automatically be re-run to re-generate these files and re-configure the project. +- Sets the `CMAKE_TOOLCHAIN_FILE`_ variable to the ESP-IDF toolchain file with the Xtensa ESP32 toolchain. +- Declare the actual cmake-level project by calling the `CMake project function `_. +- Load the git version. This includes some magic which will automatically re-run CMake if a new revision is checked out in git. See `File Globbing & Incremental Builds`_. +- Include ``project_include.cmake`` files from any components which have them. +- Add each component to the build. Each component CMakeLists file calls ``register_component``, calls the CMake `add_library `_ function to add a library and then adds source files, compile options, etc. +- Add the final app executable to the build. +- Go back and add inter-component dependencies between components (ie adding the public header directories of each component to each other component). + +Browse the :idf_file:`/tools/cmake/project.cmake` file and supporting functions in :idf_file:`/tools/cmake/idf_functions.cmake` for more details. + +Debugging CMake +--------------- + +Some tips for debugging the ESP-IDF CMake-based build system: + +- When CMake runs, it prints quite a lot of diagnostic information including lists of components and component paths. +- Running ``cmake -DDEBUG=1`` will produce more verbose diagnostic output from the IDF build system. +- Running ``cmake`` with the ``--trace`` or ``--trace-expand`` options will give a lot of information about control flow. See the `cmake command line documentation`_. + +.. _warn-undefined-variables-cmake: + +Warning On Undefined Variables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, ``idf.py`` passes the ``--warn-uninitialized`` flag to CMake_ so it will print a warning if an undefined variable is referenced in the build. This can be very useful to find buggy CMake files. + +If you don't want this behaviour, it can be disabled by passing ``--no-warnings`` to ``idf.py``. + +Overriding Parts of the Project +------------------------------- + +project_include.cmake +^^^^^^^^^^^^^^^^^^^^^ + +For components that have build requirements which must be evaluated before any component CMakeLists +files are evaluated, you can create a file called ``project_include.cmake`` in the +component directory. This CMake file is included when ``project.cmake`` is evaluating the entire project. + +``project_include.cmake`` files are used inside ESP-IDF, for defining project-wide build features such as ``esptool.py`` command line arguments and the ``bootloader`` "special app". + +Note that ``project_include.cmake`` isn't necessary for the most common component uses - such as adding include directories to the project, or ``LDFLAGS`` to the final linking step. These values can be customised via the ``CMakeLists.txt`` file itself. See `Optional Project Variables`_ for details. + +Take great care when setting variables or targets in a ``project_include.cmake`` file. As the values are included into the top-level project CMake pass, they can influence or break functionality across all components! + +KConfig.projbuild +^^^^^^^^^^^^^^^^^ + +This is an equivalent to ``project_include.cmake`` for :ref:`component-configuration-cmake` KConfig files. If you want to include +configuration options at the top-level of menuconfig, rather than inside the "Component Configuration" sub-menu, then these can be defined in the KConfig.projbuild file alongside the ``CMakeLists.txt`` file. + +Take care when adding configuration values in this file, as they will be included across the entire project configuration. Where possible, it's generally better to create a KConfig file for :ref:`component-configuration-cmake`. + + +Configuration-Only Components +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Special components which contain no source files, only ``Kconfig.projbuild`` and ``KConfig``, can have a one-line ``CMakeLists.txt`` file which calls the function ``register_config_only_component()``. This function will include the component in the project build, but no library will be built *and* no header files will be added to any include paths. + +If a CMakeLists.txt file doesn't call ``register_component()`` or ``register_config_only_component()``, it will be excluded from the project entirely. This may sometimes be desirable, depending on the project configuration. + +Example Component CMakeLists +============================ + +Because the build environment tries to set reasonable defaults that will work most +of the time, component ``CMakeLists.txt`` can be very small or even empty (see `Minimal Component CMakeLists`_). However, overriding `component variables`_ is usually required for some functionality. + +Here are some more advanced examples of component CMakeLists files. + +Adding conditional configuration +-------------------------------- + +The configuration system can be used to conditionally compile some files +depending on the options selected in the project configuration. + +.. highlight:: none + +``Kconfig``:: + + config FOO_ENABLE_BAR + bool "Enable the BAR feature." + help + This enables the BAR feature of the FOO component. + +``CMakeLists.txt``:: + + set(COMPONENT_SRCS "foo.c" "more_foo.c") + + if(CONFIG_FOO_ENABLE_BAR) + list(APPEND COMPONENT_SRCS "bar.c") + endif(CONFIG_FOO_ENABLE_BAR) + +This example makes use of the CMake `if function `_ and `list APPEND `_ function. + +This can also be used to select or stub out an implementation, as such: + +``Kconfig``:: + + config ENABLE_LCD_OUTPUT + bool "Enable LCD output." + help + Select this if your board has a LCD. + + config ENABLE_LCD_CONSOLE + bool "Output console text to LCD" + depends on ENABLE_LCD_OUTPUT + help + Select this to output debugging output to the lcd + + config ENABLE_LCD_PLOT + bool "Output temperature plots to LCD" + depends on ENABLE_LCD_OUTPUT + help + Select this to output temperature plots + +.. highlight:: cmake + +``CMakeLists.txt``:: + + if(CONFIG_ENABLE_LCD_OUTPUT) + set(COMPONENT_SRCS lcd-real.c lcd-spi.c) + else() + set(COMPONENT_SRCS lcd-dummy.c) + endif() + + # We need font if either console or plot is enabled + if(CONFIG_ENABLE_LCD_CONSOLE OR CONFIG_ENABLE_LCD_PLOT) + list(APPEND COMPONENT_SRCS "font.c") + endif() + + +Source Code Generation +---------------------- + +Some components will have a situation where a source file isn't +supplied with the component itself but has to be generated from +another file. Say our component has a header file that consists of the +converted binary data of a BMP file, converted using a hypothetical +tool called bmp2h. The header file is then included in as C source +file called graphics_lib.c:: + + add_custom_command(OUTPUT logo.h + COMMAND bmp2h -i ${COMPONENT_PATH}/logo.bmp -o log.h + DEPENDS ${COMPONENT_PATH}/logo.bmp + VERBATIM) + + add_custom_target(logo DEPENDS logo.h) + add_dependencies(${COMPONENT_NAME} logo) + + set_property(DIRECTORY "${COMPONENT_PATH}" APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES logo.h) + +This answer is adapted from the `CMake FAQ entry `_, which contains some other examples that will also work with ESP-IDF builds. + +In this example, logo.h will be generated in the +current directory (the build directory) while logo.bmp comes with the +component and resides under the component path. Because logo.h is a +generated file, it should be cleaned when the project is cleaned. For this reason +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 a a source file from another component included ``logo.h``, then ``add_dependencies`` would need to be called to add a dependency between +the two components, to ensure that the component source files were always compiled in the correct order. + +Embedding Binary Data +--------------------- + +Sometimes you have a file with some binary or text data that you'd like to make available to your component - but you don't want to reformat the file as C source. + +You can set a variable ``COMPONENT_EMBED_FILES`` in your component's CMakeLists, giving space-delimited names of the files to embed:: + + set(COMPONENT_EMBED_FILES server_root_cert.der) + +Or if the file is a string, you can use the variable ``COMPONENT_EMBED_TXTFILES``. This will embed the contents of the text file as a null-terminated string:: + + set(COMPONENT_EMBED_TXTFILES server_root_cert.pem) + +.. highlight:: c + +The file's contents will be added to the .rodata section in flash, and are available via symbol names as follows:: + + extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_root_cert_pem_start"); + extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_root_cert_pem_end"); + +The names are generated from the full name of the file, as given in ``COMPONENT_EMBED_FILES``. Characters /, ., etc. are replaced with underscores. The _binary prefix in the symbol name is added by objcopy and is the same for both text and binary files. + +.. highlight:: cmake + +To embed a file into a project, rather than a component, you can call the function ``target_add_binary_data`` like this:: + + target_add_binary_data(myproject.elf "main/data.bin" TEXT) + +Place this line after the ``project()`` line in your project CMakeLists.txt file. Replace ``myproject.elf`` with your project name. The final argument can be ``TEXT`` to embed a null-terminated string, or ``BINARY`` to embed the content as-is. + +For an example of using this technique, see :example:`protocols/https_request` - the certificate file contents are loaded from the text .pem file at compile time. + +.. _component-build-full-override: + +Fully Overriding The Component Build Process +-------------------------------------------- + +.. highlight:: cmake + +Obviously, there are cases where all these recipes are insufficient for a +certain component, for example when the component is basically a wrapper +around another third-party component not originally intended to be +compiled under this build system. In that case, it's possible to forego +the ESP-IDF build system entirely by using a CMake feature called ExternalProject_. Example component CMakeLists:: + + # External build process for quirc, runs in source dir and + # produces libquirc.a + externalproject_add(quirc_build + PREFIX ${COMPONENT_PATH} + SOURCE_DIR ${COMPONENT_PATH}/quirc + CONFIGURE_COMMAND "" + BUILD_IN_SOURCE 1 + BUILD_COMMAND make CC=${CMAKE_C_COMPILER} libquirc.a + INSTALL_COMMAND "" + ) + + # Add libquirc.a to the build process + # + add_library(quirc STATIC IMPORTED GLOBAL) + add_dependencies(quirc quirc_build) + + set_target_properties(quirc PROPERTIES IMPORTED_LOCATION + ${COMPONENT_PATH}/quirc/libquirc.a) + set_target_properties(quirc PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + ${COMPONENT_PATH}/quirc/lib) + + set_directory_properties( PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES + "${COMPONENT_PATH}/quirc/libquirc.a") + +(The above CMakeLists.txt can be used to create a component named ``quirc`` that builds the quirc_ project using its own Makefile.) + +- ``externalproject_add`` defines an external build system. + + - ``SOURCE_DIR``, ``CONFIGURE_COMMAND``, ``BUILD_COMMAND`` and ``INSTALL_COMMAND`` should always be set. ``CONFIGURE_COMMAND`` can be set to an empty string if the build system has no "configure" step. ``INSTALL_COMMAND`` will generally be empty for ESP-IDF builds. + - Setting ``BUILD_IN_SOURCE`` means the build directory is the same as the source directory. Otherwise you can set ``BUILD_DIR``. + - Consult the ExternalProject_ documentation for more details about ``externalproject_add()`` + +- The second set of commands adds a library target, which points to the "imported" library file built by the external system. Some properties need to be set in order to add include directories and tell CMake where this file is. +- Finally, the generated library is added to `ADDITIONAL_MAKE_CLEAN_FILES`_. This means ``make clean`` will delete this library. (Note that the other object files from the build won't be deleted.) + +.. _ADDITIONAL_MAKE_CLEAN_FILES_note: + +ExternalProject dependencies, clean builds +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +CMake has some unusual behaviour around external project builds: + +- `ADDITIONAL_MAKE_CLEAN_FILES`_ only works when "make" is used as the build system. If Ninja_ or an IDE build system is used, it won't delete these files when cleaning. +- However, the ExternalProject_ configure & build commands will *always* be re-run after a clean is run. +- Therefore, there are two alternative recommended ways to configure the external build command: + + 1. Have the external ``BUILD_COMMAND`` run a full clean compile of all sources. The build command will be run if any of the dependencies passed to ``externalproject_add`` with ``DEPENDS`` have changed, or if this is a clean build (ie any of ``idf.py clean``, ``ninja clean``, or ``make clean`` was run.) + 2. Have the external ``BUILD_COMMAND`` be an incremental build command. Pass the parameter ``BUILD_ALWAYS 1`` to ``externalproject_add``. This means the external project will be built each time a build is run, regardless of dependencies. This is only recommended if the external project has correct incremental build behaviour, and doesn't take too long to run. + +The best of these approaches for building an external project will depend on the project itself, its build system, and whether you anticipate needing to frequently recompile the project. + +.. _custom-sdkconfig-defaults-cmake: + +Custom sdkconfig defaults +========================= + +For example projects or other projects where you don't want to specify a full sdkconfig configuration, but you do want to override some key values from the ESP-IDF defaults, it is possible to create a file ``sdkconfig.defaults`` in the project directory. This file will be used when creating a new config from scratch, or when any new config value hasn't yet been set in the ``sdkconfig`` file. + +To override the name of this file, set the ``SDKCONFIG_DEFAULTS`` environment variable. + + +Flash arguments +=============== + +There are some scenarios that we want to flash the target board without IDF. For this case we want to save the built binaries, esptool.py and esptool write_flash arguments. It's simple to write a script to save binaries and esptool.py. + +After running a project build, the build directory contains binary output files (``.bin`` files) for the project and also the following flashing data files: + +- ``flash_project_args`` contains arguments to flash the entire project (app, bootloader, partition table, PHY data if this is configured). +- ``flash_app_args`` contains arguments to flash only the app. +- ``flash_bootloader_args`` contains arguments to flash only the bootloader. + +.. highlight:: bash + +You can pass any of these flasher argument files to ``esptool.py`` as follows:: + + python esptool.py --chip esp32 write_flash @build/flash_project_args + +Alternatively, it is possible to manually copy the parameters from the argument file and pass them on the command line. + +The build directory also contains a generated file ``flasher_args.json`` which contains project flash information, in JSON format. This file is used by ``idf.py`` and can also be used by other tools which need information about the project build. + +Building the Bootloader +======================= + +The bootloader is built by default as part of ``idf.py build``, or can be built standalone via ``idf.py bootloader``. + +The bootloader is a special "subproject" inside :idf:`/components/bootloader/subproject`. It has its own project CMakeLists.txt file and builds separate .ELF and .BIN files to the main project. However it shares its configuration and build directory with the main project. + +The subproject is inserted as an external project from the top-level project, by the file :idf_file:`/components/bootloader/project_include.cmake`. The main build process runs CMake for the subproject, which includes discovering components (a subset of the main components) and generating a bootloader-specific config (derived from the main ``sdkconfig``). + +Writing Pure CMake Components +============================= + +The ESP-IDF build system "wraps" CMake with the concept of "components", and helper functions to automatically integrate these components into a project build. + +However, underneath the concept of "components" is a full CMake build system. It is also possible to make a component which is pure CMake. + +.. highlight:: cmake + +Here is an example minimal "pure CMake" component CMakeLists file for a component named ``json``:: + + add_library(json STATIC + cJSON/cJSON.c + cJSON/cJSON_Utils.c) + + target_include_directories(json PUBLIC cJSON) + +- This is actually an equivalent declaration to the IDF ``json`` component :idf_file:`/components/json/CMakeLists.txt`. +- 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. + + +File Globbing & Incremental Builds +================================== + +.. highlight:: cmake + +The preferred way to include source files in an ESP-IDF component is to set ``COMPONENT_SRC_DIRS``:: + + set(COMPONENT_SRCDIRS library platform) + +The build system will automatically find (via "file globbing") all source files in this directory. Alternatively, files can be specified individually:: + + set(COMPONENT_SRCS library/a.c library/b.c platform/platform.c) + +CMake_ recommends always to name all files individually (ie ``COMPONENT_SRCS``). This is because CMake is automatically re-run whenever a CMakeLists file changes. If a new source file is added and file globbing is used, then CMake won't know to automatically re-run and this file won't be added to the build. + +The trade-off is acceptable when you're adding the file yourself, because you can trigger a clean build or run ``idf.py reconfigure`` to manually re-run CMake_. However, the problem gets harder when you share your project with others who may check out a new version using a source control tool like Git... + +For components which are part of ESP-IDF, we use a third party Git CMake integration module (:idf_file:`/tools/cmake/third_party/GetGitRevisionDescription.cmake`) which automatically re-runs CMake any time the repository commit changes. This means if you check out a new ESP-IDF version, CMake will automatically rerun. + +For project CMakeLists files, ``MAIN_SRCS`` is a list of source files. Therefore if a new file is added, CMakeLists will change and this triggers a re-run of CMake. (This is the approach which CMake_ recommends.) + +For project components (not part of ESP-IDF), there are a few different options: + +- If keeping your project file in Git, ESP-IDF will automatically track the Git revision and re-run CMake if the revision changes. +- If some components are kept in a third git repository (not the project repository or ESP-IDF repository), you can add a call to the ``git_describe`` function in a component CMakeLists file in order to automatically trigger re-runs of CMake when the Git revision changes. +- If not using Git, remember to manually run ``idf.py reconfigure`` whenever a source file may change. +- To avoid this problem entirely, use ``COMPONENT_SRCS`` to list all source files in project components. + +The best option will depend on your particular project and its users. + +Build System Metadata +===================== + +For integration into IDEs and other build systems, when CMake runs the build process generates a number of metadata files in the ``build/`` directory. To regenerate these files, run ``cmake`` or ``idf.py reconfigure`` (or any other ``idf.py`` build command). + +- ``compile_commands.json`` is a standard format JSON file which describes every source file which is compiled in the project. A CMake feature generates this file, and many IDEs know how to parse it. +- ``project_description.json`` contains some general information about the ESP-IDF project, configured paths, etc. +- ``flasher_args.json`` contains esptool.py arguments to flash the project's binary files. There are also ``flash_*_args`` files which can be used directly with esptool.py. See `Flash arguments`_. +- ``CMakeCache.txt`` is the CMake cache file which contains other information about the CMake process, toolchain, etc. +- ``config/sdkconfig.json`` is a JSON-formatted version of the project configuration values. +- ``config/kconfig_menus.json`` is a JSON-formatted version of the menus shown in menuconfig, for use in external IDE UIs. + +JSON Configuration Server +------------------------- + +.. highlight :: json + +A tool called ``confserver.py`` is provided to allow IDEs to easily integrate with the configuration system logic. ``confserver.py`` is designed to run in the background and interact with a calling process by reading and writing JSON over process stdin & stdout. + +You can run ``confserver.py`` from a project via ``idf.py confserver`` or ``ninja confserver``, or a similar target triggered from a different build generator. + +The config server outputs human-readable errors and warnings on stderr and JSON on stdout. On startup, it will output the full values of each configuration item in the system as a JSON dictionary, and the available ranges for values which are range constrained. The same information is contained in ``sdkconfig.json``:: + + {"version": 1, "values": { "ITEM": "value", "ITEM_2": 1024, "ITEM_3": false }, "ranges" : { "ITEM_2" : [ 0, 32768 ] } } + +Only visible configuration items are sent. Invisible/disabled items can be parsed from the static ``kconfig_menus.json`` file which also contains the menu structure and other metadata (descriptions, types, ranges, etc.) + +The Configuration Server will then wait for input from the client. The client passes a request to change one or more values, as a JSON object followed by a newline:: + + {"version": "1", "set": {"SOME_NAME": false, "OTHER_NAME": true } } + +The Configuration Server will parse this request, update the project ``sdkconfig`` file, and return a full list of changes:: + + {"version": 1, "values": {"SOME_NAME": false, "OTHER_NAME": true , "DEPENDS_ON_SOME_NAME": null}} + +Items which are now invisible/disabled will return value ``null``. Any item which is newly visible will return its newly visible current value. + +If the range of a config item changes, due to conditional range depending on another value, then this is also sent:: + + {"version": 1, "values": {"OTHER_NAME": true }, "ranges" : { "HAS_RANGE" : [ 3, 4 ] } } + +If invalid data is passed, an "error" field is present on the object:: + + {"version": 1, "values": {}, "error": ["The following config symbol(s) were not visible so were not updated: NOT_VISIBLE_ITEM"]} + +By default, no config changes are written to the sdkconfig file. Changes are held in memory until a "save" command is sent:: + + {"version": 1, "save": null } + +To reload the config values from a saved file, discarding any changes in memory, a "load" command can be sent:: + + {"version": 1, "load": null } + +The value for both "load" and "save" can be a new pathname, or "null" to load/save the previous pathname. + +The response to a "load" command is always the full set of config values and ranges, the same as when the server is initially started. + +Any combination of "load", "set", and "save" can be sent in a single command and commands are executed in that order. Therefore it's possible to load config from a file, set some config item values and then save to a file in a single command. + +.. note:: The configuration server does not automatically load any changes which are applied externally to the ``sdkconfig`` file. Send a "load" command or restart the server if the file is externally edited. + +.. note:: The configuration server does not re-run CMake to regenerate other build files or metadata files after ``sdkconfig`` is updated. This will happen automatically the next time ``CMake`` or ``idf.py`` is run. + +.. _gnu-make-to-cmake: + +Migrating from ESP-IDF GNU Make System +====================================== + +Some aspects of the CMake-based ESP-IDF build system are very similar to the older GNU Make-based system. For example, to adapt a ``component.mk`` file to ``CMakeLists.txt`` variables like ``COMPONENT_ADD_INCLUDEDIRS`` and ``COMPONENT_SRCDIRS`` can stay the same and the syntax only needs changing to CMake syntax. + +Automatic Conversion Tool +------------------------- + +.. highlight:: bash + +An automatic project conversion tool is available in :idf_file:`/tools/cmake/convert_to_cmake.py`. Run this command line tool with the path to a project like this:: + + $IDF_PATH/tools/cmake/convert_to_cmake.py /path/to/project_dir + +The project directory must contain a Makefile, and GNU Make (``make``) must be installed and available on the PATH. + +The tool will convert the project Makefile and any component ``component.mk`` files to their equivalent ``CMakeLists.txt`` files. + +It does so by running ``make`` to expand the ESP-IDF build system variables which are set by the build, and then producing equivalent CMakelists files to set the same variables. + +The conversion tool is not capable of dealing with complex Makefile logic or unusual targets. These will need to be converted by hand. + +'main' is no longer a component +------------------------------- + +In the GNU Make build system ``main`` is a component with a ``component.mk`` file like other components. + +Due to CMake requirements for building executables, ``main`` source files are now linked directly into the final binary. The source files in ``main`` must be listed in the ``MAIN_SRCS`` variable (see :ref:`project mandatory variables ` for more details). At least one source file has to be listed here (although it doesn't need to contain anything in particular). + +In general, it's better not to have too many source files in ``MAIN_SRCS``. If you find that you are adding many source files here, see if you can reorganize and group some into project components (see the :ref:`example project structure `, above). + +No Longer Available in CMake +---------------------------- + +Some features are significantly different or removed in the CMake-based system. The following variables no longer exist in the CMake-based build system: + +- ``COMPONENT_BUILD_DIR``: Use ``CMAKE_CURRENT_BINARY_DIR`` instead. +- ``COMPONENT_LIBRARY``: Defaulted to ``$(COMPONENT_NAME).a``, but the library name could be overriden by the component. The name of the component library can no longer be overriden by the component. +- ``CC``, ``LD``, ``AR``, ``OBJCOPY``: Full paths to each tool from the gcc xtensa cross-toolchain. Use ``CMAKE_C_COMPILER``, ``CMAKE_C_LINK_EXECUTABLE``, ``CMAKE_OBJCOPY``, etc instead. `Full list here `_. +- ``HOSTCC``, ``HOSTLD``, ``HOSTAR``: Full names of each tool from the host native toolchain. These are no longer provided, external projects should detect any required host toolchain manually. +- ``COMPONENT_ADD_LDFLAGS``: Used to override linker flags. Use the CMake `target_link_libraries`_ command instead. +- ``COMPONENT_ADD_LINKER_DEPS``: List of files that linking should depend on. `target_link_libraries`_ will usually infer these dependencies automatically. For linker scripts, use the provided custom CMake function ``target_linker_scripts``. +- ``COMPONENT_SUBMODULES``: No longer used, the build system will automatically enumerate all submodules in the ESP-IDF repository. +- ``COMPONENT_EXTRA_INCLUDES``: Used to be an alternative to ``COMPONENT_PRIV_INCLUDEDIRS`` for absolute paths. Use ``COMPONENT_PRIV_INCLUDEDIRS`` for all cases now (can be relative or absolute). +- ``COMPONENT_OBJS``: Previously, component sources could be specified as a list of object files. Now they can be specified as an list of source files via ``COMPONENT_SRCS``. +- ``COMPONENT_OBJEXCLUDE``: Has been replaced with ``COMPONENT_SRCEXCLUDE``. Specify source files (as absolute paths or relative to component directory), instead. +- ``COMPONENT_EXTRA_CLEAN``: Set property ``ADDITIONAL_MAKE_CLEAN_FILES`` instead but note :ref:`CMake has some restrictions around this functionality `. +- ``COMPONENT_OWNBUILDTARGET`` & ``COMPONENT_OWNCLEANTARGET``: Use CMake `ExternalProject`_ instead. See :ref:`component-build-full-override` for full details. +- ``COMPONENT_CONFIG_ONLY``: Call ``register_config_only_component()`` instead. See `Configuration-Only Components`_. +- ``CFLAGS``, ``CPPFLAGS``, ``CXXFLAGS``: Use equivalent CMake commands instead. See `Controlling Component Compilation`_. + + +No Default Values +----------------- + +The following variables no longer have default values: + +- ``COMPONENT_SRCDIRS`` +- ``COMPONENT_ADD_INCLUDEDIRS`` + +No Longer Necessary +------------------- + +It is no longer necessary to set ``COMPONENT_SRCDIRS`` if setting ``COMPONENT_SRCS`` (in fact, in the CMake-based system ``COMPONENT_SRCDIRS`` is ignored if ``COMPONENT_SRCS`` is set). + + +.. _esp-idf-template: https://github.com/espressif/esp-idf-template +.. _cmake: https://cmake.org +.. _ninja: https://ninja-build.org +.. _esptool.py: https://github.com/espressif/esptool/#readme +.. _CMake v3.5 documentation: https://cmake.org/cmake/help/v3.5/index.html +.. _cmake command line documentation: https://cmake.org/cmake/help/v3.5/manual/cmake.1.html#options +.. _cmake add_library: https://cmake.org/cmake/help/v3.5/command/project.html +.. _cmake if: https://cmake.org/cmake/help/v3.5/command/if.html +.. _cmake list: https://cmake.org/cmake/help/v3.5/command/list.html +.. _cmake project: https://cmake.org/cmake/help/v3.5/command/project.html +.. _cmake set: https://cmake.org/cmake/help/v3.5/command/set.html +.. _cmake string: https://cmake.org/cmake/help/v3.5/command/string.html +.. _cmake faq generated files: https://cmake.org/Wiki/CMake_FAQ#How_can_I_generate_a_source_file_during_the_build.3F +.. _ADDITIONAL_MAKE_CLEAN_FILES: https://cmake.org/cmake/help/v3.5/prop_dir/ADDITIONAL_MAKE_CLEAN_FILES.html +.. _ExternalProject: https://cmake.org/cmake/help/v3.5/module/ExternalProject.html +.. _cmake language variables: https://cmake.org/cmake/help/v3.5/manual/cmake-variables.7.html#variables-for-languages +.. _set_source_files_properties: https://cmake.org/cmake/help/v3.5/command/set_source_files_properties.html +.. _target_compile_options: https://cmake.org/cmake/help/v3.5/command/target_compile_options.html +.. _target_link_libraries: https://cmake.org/cmake/help/v3.5/command/target_link_libraries.html#command:target_link_libraries +.. _cmake_toolchain_file: https://cmake.org/cmake/help/v3.5/variable/CMAKE_TOOLCHAIN_FILE.html +.. _quirc: https://github.com/dlbeer/quirc +.. _pyenv: https://github.com/pyenv/pyenv#README +.. _virtualenv: https://virtualenv.pypa.io/en/stable/ + diff --git a/docs/en/api-guides/core_dump.rst b/docs/en/api-guides/core_dump.rst index 84eec8297..99821b8c9 100644 --- a/docs/en/api-guides/core_dump.rst +++ b/docs/en/api-guides/core_dump.rst @@ -83,6 +83,6 @@ Generic command syntax: * --gdb,-g GDB. Path to gdb to use for data retrieval. * --core,-c CORE. Path to core dump file to use (if skipped core dump will be read from flash). * --core-format,-t CORE_FORMAT. Specifies that file passed with "-c" is an ELF ("elf"), dumped raw binary ("raw") or base64-encoded ("b64") format. - * --off,-o OFF. Ofsset of coredump partition in flash (type "make partition_table" to see it). - * --save-core,-s SAVE_CORE. Save core to file. Othwerwise temporary core file will be deleted. Ignored with "-c". + * --off,-o OFF. Offset of coredump partition in flash (type `make partition_table` to see it). + * --save-core,-s SAVE_CORE. Save core to file. Otherwise temporary core file will be deleted. Ignored with "-c". * --print-mem,-m Print memory dump. Used only with "info_corefile". diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index e93b1b7bb..0a0f9c8e9 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -6,6 +6,7 @@ API Guides General Notes Build System + Build System (CMake) Error Handling Fatal Errors Deep Sleep Wake Stubs diff --git a/docs/en/api-guides/jtag-debugging/setup-openocd-windows.rst b/docs/en/api-guides/jtag-debugging/setup-openocd-windows.rst index 12e5560b0..e7d6f5dfa 100644 --- a/docs/en/api-guides/jtag-debugging/setup-openocd-windows.rst +++ b/docs/en/api-guides/jtag-debugging/setup-openocd-windows.rst @@ -7,7 +7,7 @@ Set up OpenOCD ============== -OpenOCD for Windows / MSYS2 is available for download from Github: +OpenOCD for Windows is available for download from Github: https://github.com/espressif/openocd-esp32/releases @@ -16,7 +16,7 @@ Download latest release archive with `win32` in its name, for example `openocd-e Extract the downloaded file in ``~/esp/`` directory. cd ~/esp - unzip /c/Users//Downloads/openocd-esp32-win32-.zip + unzip /c/Users//Downloads/openocd-esp32-win32-.zip Next Steps ========== diff --git a/docs/en/cmake-pending-features.rst b/docs/en/cmake-pending-features.rst new file mode 100644 index 000000000..1ea28a913 --- /dev/null +++ b/docs/en/cmake-pending-features.rst @@ -0,0 +1,10 @@ +.. important:: + The following features are not yet supported with the CMake-based build system: + + - Eclipse IDE Documentation + - Secure Boot + - Flash Encryption + - ULP toolchain. + + Support for these features will be available before CMake becomes the default build system. + diff --git a/docs/en/cmake-warning.rst b/docs/en/cmake-warning.rst new file mode 100644 index 000000000..3f97614f4 --- /dev/null +++ b/docs/en/cmake-warning.rst @@ -0,0 +1,4 @@ +.. note:: + This is documentation for the CMake-based build system which is currently in preview release. If you encounter any gaps or bugs, please report them in the `Issues `_ section of the ESP-IDF repository. + + The CMake-based build system will become the default build system in ESP-IDF V4.0. The existing GNU Make based build system will be deprecated in ESP-IDF V5.0. diff --git a/docs/en/contribute/style-guide.rst b/docs/en/contribute/style-guide.rst index bf0a2a018..cceacf2a1 100644 --- a/docs/en/contribute/style-guide.rst +++ b/docs/en/contribute/style-guide.rst @@ -170,6 +170,19 @@ To re-format a file, run:: tools/format.sh components/my_component/file.c +CMake Code Style +---------------- + +- Indent with four spaces. +- Maximum line length 120 characters. When splitting lines, try to + focus on readability where possible (for example, by pairing up + keyword/argument pairs on individual lines). +- Don't put anything in the optional parentheses after ``endforeach()``, ``endif()``, etc. +- Use lowercase (``with_underscores``) for command, function, and macro names. +- For locally scoped variables, use lowercase (``with_underscores``). +- For globally scoped variables, use uppercase (``WITH_UNDERSCORES``). +- Otherwise follow the defaults of the cmake-lint_ project. + Configuring the code style for a project using EditorConfig ----------------------------------------------------------- @@ -193,3 +206,4 @@ Language features To be written. +.. _cmake-lint: https://github.com/richq/cmake-lint diff --git a/docs/en/get-started-cmake/add-idf_path-to-profile.rst b/docs/en/get-started-cmake/add-idf_path-to-profile.rst new file mode 100644 index 000000000..a3b3a471e --- /dev/null +++ b/docs/en/get-started-cmake/add-idf_path-to-profile.rst @@ -0,0 +1,73 @@ +Add IDF_PATH & idf.py PATH to User Profile (CMake) +================================================== + +.. include:: ../cmake-warning.rst + +To use the CMake-based build system and the idf.py tool, two modifications need to be made to system environment variables: + +- ``IDF_PATH`` needs to be set to the path of the directory containing ESP-IDF. +- System ``PATH`` variable to include the directory containing the ``idf.py`` tool (part of ESP-IDF). + +To preserve setting of these variables between system restarts, add them to the user profile by following the instructions below. + +.. note:: If using an IDE, you can optionally set these environment variables in your IDE's project environment rather than from the command line as described below. + +.. note:: If you don't ever use the command line ``idf.py`` tool, but run cmake directly or via an IDE, then it is not necessary to set the ``PATH`` variable - only ``IDF_PATH``. However it can be useful to set both. + +.. note:: If you only ever use the command line ``idf.py`` tool, and never use cmake directly or via an IDE, then it is not necessary to set the ``IDF_PATH`` variable - ``idf.py`` will detect the directory it is contained within and set ``IDF_PATH`` appropriately if it is missing. + +.. _add-paths-to-profile-windows-cmake: + +Windows +------- + +To edit Environment Variables on Windows 10, search for "Edit Environment Variables" under the Start menu. + +On earlier Windows versions, open the System Control Panel then choose "Advanced" and look for the Environment Variables button. + +You can set these environment variables for all users, or only for the current user, depending on whether other users of your computer will be using ESP-IDF. + +- Click ``New...`` to add a new system variable named ``IDF_PATH``. Set the path to directory containing ESP-IDF, for example ``C:\Users\user-name\esp\esp-idf``. +- Locate the ``Path`` environment variable and double-click to edit it. Append the following to the end: ``;%IDF_PATH%\tools``. This will allow you to run ``idf.py`` and other tools from Windows Command Prompt. + +If you got here from section :ref:`get-started-setup-path-cmake`, while installing s/w for ESP32 development, then go back to section :ref:`get-started-start-project-cmake`. + + +.. _add-idf_path-to-profile-linux-macos-cmake: + +Linux and MacOS +--------------- + +Set up ``IDF_PATH`` and add ``idf.py`` to the PATH by adding the following two lines to your ``~/.profile`` file:: + + export IDF_PATH=~/esp/esp-idf + export PATH="$PATH:$IDF_PATH/tools" + +.. note:: + + ``~/.profile`` means a file named ``.profile`` in your user's home directory (which is abbreviated ``~`` in the shell). + +Log off and log in back to make this change effective. + +.. note:: + + Not all shells use ``.profile``. If you have ``/bin/bash`` and ``.bash_profile`` exists then update this file instead. For ``zsh``, update ``.zprofile``. Other shells may use other profile files (consult the shell's documentation). + +Run the following command to check if ``IDF_PATH`` is set:: + + printenv IDF_PATH + +The path previously entered in ``~/.profile`` file (or set manually) should be printed out. + +To verify idf.py is now on the ``PATH``, you can run the following:: + + which idf.py + +A path like ``${IDF_PATH}/tools/idf.py`` should be printed. + +If you do not like to have ``IDF_PATH`` or ``PATH`` modifications set, you can enter it manually in terminal window on each restart or logout:: + + export IDF_PATH=~/esp/esp-idf + export PATH="$PATH:$IDF_PATH/tools" + +If you got here from section :ref:`get-started-setup-path-cmake`, while installing s/w for ESP32 development, then go back to section :ref:`get-started-start-project-cmake`. diff --git a/docs/en/get-started-cmake/eclipse-setup.rst b/docs/en/get-started-cmake/eclipse-setup.rst new file mode 100644 index 000000000..ccc546f34 --- /dev/null +++ b/docs/en/get-started-cmake/eclipse-setup.rst @@ -0,0 +1,10 @@ +**************************************** +Build and Flash with Eclipse IDE (CMake) +**************************************** + +.. include:: ../cmake-warning.rst + +Documentation for Eclipse setup with CMake-based build system and Eclipse CDT is coming soon. + +.. _eclipse.org: https://www.eclipse.org/ + diff --git a/docs/en/get-started-cmake/establish-serial-connection.rst b/docs/en/get-started-cmake/establish-serial-connection.rst new file mode 100644 index 000000000..ca0e4dd2c --- /dev/null +++ b/docs/en/get-started-cmake/establish-serial-connection.rst @@ -0,0 +1,131 @@ +Establish Serial Connection with ESP32 (CMake) +============================================== + + +This section provides guidance how to establish serial connection between ESP32 and PC. + + +Connect ESP32 to PC +-------------------- + +Connect the ESP32 board to the PC using the USB cable. If device driver does not install automatically, identify USB to serial converter chip on your ESP32 board (or external converter dongle), search for drivers in internet and install them. + +Below are the links to drivers for ESP32 boards produced by Espressif: + +* ESP32-PICO-KIT and ESP32-DevKitC - `CP210x USB to UART Bridge VCP Drivers `_ + +* ESP32-WROVER-KIT and ESP32 Demo Board - `FTDI Virtual COM Port Drivers `_ + +Above drivers are primarily for reference. They should already be bundled with the operating system and installed automatically once one of listed boards is connected to the PC. + + +Check port on Windows +--------------------- + +Check the list of identified COM ports in the Windows Device Manager. Disconnect ESP32 and connect it back, to verify which port disappears from the list and then shows back again. + +Figures below show serial port for ESP32 DevKitC and ESP32 WROVER KIT + +.. figure:: ../../_static/esp32-devkitc-in-device-manager.png + :align: center + :alt: USB to UART bridge of ESP32-DevKitC in Windows Device Manager + :figclass: align-center + + USB to UART bridge of ESP32-DevKitC in Windows Device Manager + +.. figure:: ../../_static/esp32-wrover-kit-in-device-manager.png + :align: center + :alt: Two USB Serial Ports of ESP-WROVER-KIT in Windows Device Manager + :figclass: align-center + + Two USB Serial Ports of ESP-WROVER-KIT in Windows Device Manager + + +Check port on Linux and MacOS +----------------------------- + +To check the device name for the serial port of your ESP32 board (or external converter dongle), run this command two times, first with the board / dongle unplugged, then with plugged in. The port which appears the second time is the one you need: + +Linux :: + + ls /dev/tty* + +MacOS :: + + ls /dev/cu.* + + +.. note: MacOS users: if you don't see the serial port then check you have the USB/serial drivers installed as shown in the Getting Started guide for your particular development board. For MacOS High Sierra (10.13), you may also have to explicitly allow the drivers to load. Open System Preferences -> Security & Privacy -> General and check if there is a message shown here about "System Software from developer ..." where the developer name is Silicon Labs or FTDI. + +.. _linux-dialout-group-cmake: + +Adding user to ``dialout`` on Linux +----------------------------------- + +The currently logged user should have read and write access the serial port over USB. On most Linux distributions, this is done by adding the user to ``dialout`` group with the following command:: + + sudo usermod -a -G dialout $USER + +Make sure you re-login to enable read and write permissions for the serial port. + + +Verify serial connection +------------------------ + +Now verify that the serial connection is operational. You can do this using a serial terminal program. In this example we will use `PuTTY SSH Client `_ that is available for both Windows and Linux. You can use other serial program and set communication parameters like below. + +Run terminal, set identified serial port, baud rate = 115200, data bits = 8, stop bits = 1, and parity = N. Below are example screen shots of setting the port and such transmission parameters (in short described as 115200-8-1-N) on Windows and Linux. Remember to select exactly the same serial port you have identified in steps above. + +.. figure:: ../../_static/putty-settings-windows.png + :align: center + :alt: Setting Serial Communication in PuTTY on Windows + :figclass: align-center + + Setting Serial Communication in PuTTY on Windows + +.. figure:: ../../_static/putty-settings-linux.png + :align: center + :alt: Setting Serial Communication in PuTTY on Linux + :figclass: align-center + + Setting Serial Communication in PuTTY on Linux + + +Then open serial port in terminal and check, if you see any log printed out by ESP32. The log contents will depend on application loaded to ESP32. An example log by ESP32 is shown below. + +.. highlight:: none + +:: + + ets Jun 8 2016 00:22:57 + + rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + ets Jun 8 2016 00:22:57 + + rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + configsip: 0, SPIWP:0x00 + clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 + mode:DIO, clock div:2 + load:0x3fff0008,len:8 + load:0x3fff0010,len:3464 + load:0x40078000,len:7828 + load:0x40080000,len:252 + entry 0x40080034 + I (44) boot: ESP-IDF v2.0-rc1-401-gf9fba35 2nd stage bootloader + I (45) boot: compile time 18:48:10 + + ... + +If you see some legible log, it means serial connection is working and you are ready to proceed with installation and finally upload of application to ESP32. + +.. note:: + + For some serial port wiring configurations, the serial RTS & DTR pins need to be disabled in the terminal program before the ESP32 will boot and produce serial output. This depends on the hardware itself, most development boards (including all Espressif boards) *do not* have this issue. The issue is present if RTS & DTR are wired directly to the EN & GPIO0 pins. See the `esptool documentation`_ for more details. + +.. note:: + + Close serial terminal after verification that communication is working. In next step we are going to use another application to upload ESP32. This application will not be able to access serial port while it is open in terminal. + +If you got here from section :ref:`get-started-connect-cmake` when installing s/w for ESP32 development, then go back to section :ref:`get-started-configure-cmake`. + +.. _esptool documentation: https://github.com/espressif/esptool/wiki/ESP32-Boot-Mode-Selection#automatic-bootloader diff --git a/docs/en/get-started-cmake/get-started-devkitc-v2.rst b/docs/en/get-started-cmake/get-started-devkitc-v2.rst new file mode 100644 index 000000000..fd566387e --- /dev/null +++ b/docs/en/get-started-cmake/get-started-devkitc-v2.rst @@ -0,0 +1,80 @@ +ESP32-DevKitC V2 Getting Started Guide (CMake) +============================================== + +This user guide shows how to get started with ESP32-DevKitC development board. + + +What You Need +------------- + +* 1 × :ref:`ESP32-DevKitC V2 board ` +* 1 × USB A / micro USB B cable +* 1 × PC loaded with Windows, Linux or Mac OS + + +Overview +-------- + +ESP32-DevKitC is a small-sized ESP32-based development board produced by `Espressif `_. Most of the I/O pins are broken out to the pin headers on both sides for easy interfacing. Developers can connect these pins to peripherals as needed. Standard headers also make development easy and convenient when using a breadboard. + + +Functional Description +---------------------- + +The following list and figure below describe key components, interfaces and controls of ESP32-DevKitC board. + +ESP-WROOM-32 + Standard `ESP-WROOM-32 `_ module soldered to the ESP32-DevKitC board. +EN + Reset button: pressing this button resets the system. +Boot + Download button: holding down the **Boot** button and pressing the **EN** button initiates the firmware download mode. Then user can download firmware through the serial port. +USB + USB interface. It functions as the power supply for the board and the communication interface between PC and ESP-WROOM-32. +I/O + Most of the pins on the ESP-WROOM-32 are broken out to the pin headers on the board. Users can program ESP32 to enable multiple functions such as PWM, ADC, DAC, I2C, I2S, SPI, etc. + +.. _get-started-esp32-devkitc-v2-board-front-cmake: + +.. figure:: ../../_static/esp32-devkitc-v2-functional-overview.png + :align: center + :alt: ESP32-DevKitC V2 board layout + :figclass: align-center + + ESP32-DevKitC V2 board layout + + +Power Supply Options +-------------------- + +There following options are available to provide power supply to this board: + +1. Micro USB port, this is default power supply connection +2. 5V / GND header pins +3. 3V3 / GND header pins + +.. warning:: + + Above options are mutually exclusive, i.e. the power supply may be provided using only one of the above options. Attempt to power the board using more than one connection at a time may damage the board and/or the power supply source. + + +Start Application Development +------------------------------ + +Before powering up the ESP32-DevKitC, please make sure that the board has been received in good condition with no obvious signs of damage. + +To start development of applications, proceed to section :doc:`index`, that will walk you through the following steps: + +* :ref:`get-started-setup-toolchain-cmake` in your PC to develop applications for ESP32 in C language +* :ref:`get-started-connect-cmake` the module to the PC and verify if it is accessible +* :ref:`get-started-build-cmake` for an example application +* :ref:`get-started-flash-cmake` to run code on the ESP32 +* :ref:`get-started-build-monitor-cmake` instantly what the application is doing + + +Related Documents +----------------- + +* `ESP32-DevKitC schematic `_ (PDF) +* `ESP32 Datasheet `_ (PDF) +* `ESP-WROOM-32 Datasheet `_ (PDF) diff --git a/docs/en/get-started-cmake/get-started-devkitc.rst b/docs/en/get-started-cmake/get-started-devkitc.rst new file mode 100644 index 000000000..20b2d86f6 --- /dev/null +++ b/docs/en/get-started-cmake/get-started-devkitc.rst @@ -0,0 +1,114 @@ +ESP32-DevKitC V4 Getting Started Guide (CMake) +============================================== + +This user guide shows how to get started with ESP32-DevKitC V4 development board. For description of other versions of the ESP32-DevKitC check :doc:`../hw-reference/index`. + + +What You Need +------------- + +* 1 × :ref:`ESP32-DevKitC V4 board ` +* 1 × USB A / micro USB B cable +* 1 × PC loaded with Windows, Linux or Mac OS + + +Overview +-------- + +ESP32-DevKitC V4 is a small-sized ESP32-based development board produced by `Espressif `_. Most of the I/O pins are broken out to the pin headers on both sides for easy interfacing. Developers can connect these pins to peripherals as needed. Standard headers also make development easy and convenient when using a breadboard. + +The board comes in two versions, either with :ref:`esp-modules-and-boards-esp-wroom-32` or :ref:`esp-modules-and-boards-esp32-wrover` module soldered. + + +Functional Description +---------------------- + +The following list and figure below describe key components, interfaces and controls of ESP32-DevKitC V4 board. + +ESP-WROOM-32 + :ref:`esp-modules-and-boards-esp-wroom-32` module soldered to the ESP32-DevKitC V4 board. +ESP32-WROVER + Optionally :ref:`esp-modules-and-boards-esp32-wrover` module may be soldered instead of the ESP-WROOM-32. +USB-UART Bridge + A single chip USB-UART bridge provides up to 3 Mbps transfers rates. +Boot + Download button: holding down the **Boot** button and pressing the **EN** button initiates the firmware download mode. Then user can download firmware through the serial port. +Micro USB Port + USB interface. It functions as the power supply for the board and the communication interface between PC and the ESP module. +5V Power On LED + This LED lights when the USB or an external 5V power supply is applied to the board. For details see schematic in `Related Documents`_. +EN + Reset button: pressing this button resets the system. +I/O + Most of the pins on the ESP module are broken out to the pin headers on the board. Users can program ESP32 to enable multiple functions such as PWM, ADC, DAC, I2C, I2S, SPI, etc. + + .. note:: + + Some of broken out pins are used internally be the ESP32 module to communicate with SPI memory. They are grouped on one side of the board besides the USB connector and labeled D0, D1, D2, D3, CMD and CLK. In general these pins should be left unconnected or access to the SPI flash memory / SPI RAM may be disturbed. + + .. note:: + + GPIO16 and 17 are used internally by the ESP32-WROVER module. They are broken out and avialable for use only for boards that have the ESP-WROOM-32 module installed. + + +.. _get-started-esp32-devkitc-board-front-cmake: + +.. figure:: ../../_static/esp32-devkitc-functional-overview.jpg + :align: center + :alt: ESP32-DevKitC V4 with ESP-WROOM-32 module soldered + :figclass: align-center + + ESP32-DevKitC V4 with ESP-WROOM-32 module soldered + + +Power Supply Options +-------------------- + +There following options are available to provide power supply to this board: + +1. Micro USB port, this is default power supply connection +2. 5V / GND header pins +3. 3V3 / GND header pins + +.. warning:: + + Above options are mutually exclusive, i.e. the power supply may be provided using only one of the above options. Attempt to power the board using more than one connection at a time may damage the board and/or the power supply source. + + +Start Application Development +------------------------------ + +Before powering up the ESP32-DevKitC, please make sure that the board has been received in good condition with no obvious signs of damage. + +To start development of applications, proceed to section :doc:`index`, that will walk you through the following steps: + +* :ref:`get-started-setup-toolchain-cmake` in your PC to develop applications for ESP32 in C language +* :ref:`get-started-connect-cmake` the module to the PC and verify if it is accessible +* :ref:`get-started-build-cmake` for an example application +* :ref:`get-started-flash-cmake` to run code on the ESP32 +* :ref:`get-started-build-monitor-cmake` instantly what the application is doing + + +Board Dimensions +---------------- + +.. figure:: ../../_static/esp32-devkitc-dimensions-back.jpg + :align: center + :alt: ESP32 DevKitC board dimensions - back + :figclass: align-center + + ESP32 DevKitC board dimensions - back + + +Related Documents +----------------- + +* `ESP32-DevKitC V4 schematic `_ (PDF) +* `ESP32 Datasheet `_ (PDF) +* `ESP-WROOM-32 Datasheet `_ (PDF) +* `ESP32-WROVER Datasheet `_ (PDF) + +.. toctree:: + :hidden: + + get-started-devkitc-v2 diff --git a/docs/en/get-started-cmake/get-started-pico-kit-v3.rst b/docs/en/get-started-cmake/get-started-pico-kit-v3.rst new file mode 100644 index 000000000..3abd213d4 --- /dev/null +++ b/docs/en/get-started-cmake/get-started-pico-kit-v3.rst @@ -0,0 +1,67 @@ +ESP32-PICO-KIT V3 Getting Started Guide (CMake) +=============================================== + +This user guide shows how to get started with the ESP32-PICO-KIT V3 mini development board. For description of other versions of the ESP32-PICO-KIT check :doc:`../hw-reference/index`. + + +What You Need +------------- + +* 1 × ESP32-PICO-KIT V3 mini development board +* 1 × USB A / Micro USB B cable +* 1 × PC loaded with Windows, Linux or Mac OS + + +Overview +-------- + +ESP32-PICO-KIT V3 is a mini development board based on the ESP32-PICO-D4 SIP module produced by `Espressif `_. All the IO signals and system power on ESP32-PICO-D4 are led out through two standard 20 pin x 0.1" pitch headers on both sides for easy interfacing. The development board integrates a USB-UART Bridge circuit, allowing the developers to connect the development board to a PC's USB port for downloads and debugging. + + +Functional Description +---------------------- + +The following list and figure below describe key components, interfaces and controls of ESP32-PICO-KIT V3 board. + +ESP32-PICO-D4 + Standard ESP32-PICO-D4 module soldered to the ESP32-PICO-KIT V3 board. The complete system of the ESP32 chip has been integrated into the SIP module, requiring only external antenna with LC matching network, decoupling capacitors and pull-up resistors for EN signals to function properly. +USB-UART Bridge + A single chip USB-UART bridge provides up to 1 Mbps transfers rates. +I/O + All the pins on ESP32-PICO-D4 are broken out to the pin headers on the board. Users can program ESP32 to enable multiple functions such as PWM, ADC, DAC, I2C, I2S, SPI, etc. +Micro USB Port + USB interface. It functions as the power supply for the board and the communication interface between PC and ESP32-PICO-KIT V3. +EN Button + Reset button; pressing this button resets the system. +BOOT Button + Holding down the Boot button and pressing the EN button initiates the firmware download mode. Then user can download firmware through the serial port. + +.. figure:: ../../_static/esp32-pico-kit-v3-layout.jpg + :align: center + :alt: ESP32-PICO-KIT V3 board layout + :figclass: align-center + + ESP32-PICO-KIT V3 board layout + + +Start Application Development +------------------------------ + +Before powering up the ESP32-PICO-KIT V3, please make sure that the board has been received in good condition with no obvious signs of damage. + +To start development of applications, proceed to section :doc:`index`, that will walk you through the following steps: + +* :ref:`get-started-setup-toolchain-cmake` in your PC to develop applications for ESP32 in C language +* :ref:`get-started-connect-cmake` the module to the PC and verify if it is accessible +* :ref:`get-started-build-cmake` for an example application +* :ref:`get-started-flash-cmake` to run code on the ESP32 +* :ref:`get-started-build-monitor-cmake` instantly what the application is doing + + +Related Documents +----------------- + +* `ESP32-PICO-KIT V3 schematic `_ (PDF) +* `ESP32-PICO-D4 Datasheet `_ (PDF) +* :doc:`../hw-reference/index` + diff --git a/docs/en/get-started-cmake/get-started-pico-kit.rst b/docs/en/get-started-cmake/get-started-pico-kit.rst new file mode 100644 index 000000000..9d73f34cb --- /dev/null +++ b/docs/en/get-started-cmake/get-started-pico-kit.rst @@ -0,0 +1,213 @@ +ESP32-PICO-KIT V4 Getting Started Guide (CMake) +=============================================== + + +This user guide shows how to get started with the ESP32-PICO-KIT V4 mini development board. For description of other versions of the ESP32-PICO-KIT check :doc:`../hw-reference/index`. + + +What You Need +------------- + +* 1 × :ref:`ESP32-PICO-KIT V4 mini development board ` +* 1 × USB A / Micro USB B cable +* 1 × PC loaded with Windows, Linux or Mac OS + +If you like to start using this board right now, go directly to section `Start Application Development`_. + + +Overview +-------- + +ESP32-PICO-KIT V4 is a mini development board produced by `Espressif `_. At the core of this board is the ESP32-PICO-D4, a System-in-Package (SIP) module with complete Wi-Fi and Bluetooth functionalities. Comparing to other ESP32 chips, the ESP32-PICO-D4 integrates several peripheral components in one single package, that otherwise would need to be installed separately. This includes a 40 MHz crystal oscillator, 4 MB flash, filter capacitors and RF matching links in. This greatly reduces quantity and costs of additional components, subsequent assembly and testing cost, as well as overall product complexity. + +The development board integrates a USB-UART Bridge circuit, allowing the developers to connect the board to a PC's USB port for downloads and debugging. + +For easy interfacing, all the IO signals and system power on ESP32-PICO-D4 are led out through two rows of 20 x 0.1" pitch header pads on both sides of the development board. To make the ESP32-PICO-KIT V4 fit into mini breadboards, the header pads are populated with two rows of 17 pin headers. Remaining 2 x 3 pads grouped on each side of the board besides the antenna are not populated. The remaining 2 x 3 pin headers may be soldered later by the user. + +.. note:: + + The 2 x 3 pads not populated with pin headers are internally connected to the flash memory embedded in the ESP32-PICO-D4 SIP module. For more details see module's datasheet in `Related Documents`_. + +The board dimensions are 52 x 20.3 x 10 mm (2.1" x 0.8" x 0.4"), see section `Board Dimensions`_. An overview functional block diagram is shown below. + +.. figure:: ../../_static/esp32-pico-kit-v4-functional-block-diagram.png + :align: center + :alt: ESP32-PICO-KIT V4 functional block diagram + :figclass: align-center + + ESP32-PICO-KIT V4 functional block diagram + + +Functional Description +---------------------- + +The following list and figure below describe key components, interfaces and controls of ESP32-PICO-KIT V4 board. + +ESP32-PICO-D4 + Standard ESP32-PICO-D4 module soldered to the ESP32-PICO-KIT V4 board. The complete system of the ESP32 chip has been integrated into the SIP module, requiring only external antenna with LC matching network, decoupling capacitors and pull-up resistors for EN signals to function properly. +LDO + 5V-to-3.3V Low dropout voltage regulator (LDO). +USB-UART Bridge + A single chip USB-UART bridge provides up to 1 Mbps transfers rates. +Micro USB Port + USB interface. It functions as the power supply for the board and the communication interface between PC and ESP32-PICO-KIT V4. +5V Power On LED + This light emitting diode lits when the USB or an external 5V power supply is applied to the board. For details see schematic in `Related Documents`_. +I/O + All the pins on ESP32-PICO-D4 are broken out to the pin headers on the board. Users can program ESP32 to enable multiple functions such as PWM, ADC, DAC, I2C, I2S, SPI, etc. For details please see section `Pin Descriptions`_. +BOOT Button + Holding down the Boot button and pressing the EN button initiates the firmware download mode. Then user can download firmware through the serial port. +EN Button + Reset button; pressing this button resets the system. + +.. _get-started-pico-kit-v4-board-front-cmake: + +.. figure:: ../../_static/esp32-pico-kit-v4-layout.jpg + :align: center + :alt: ESP32-PICO-KIT V4 board layout + :figclass: align-center + + ESP32-PICO-KIT V4 board layout + + +Power Supply Options +-------------------- + +There following options are available to provide power supply to the ESP32-PICO-KIT V4: + +1. Micro USB port, this is default power supply connection +2. 5V / GND header pins +3. 3V3 / GND header pins + +.. warning:: + + Above options are mutually exclusive, i.e. the power supply may be provided using only one of the above options. Attempt to power the board using more than one connection at a time may damage the board and/or the power supply source. + + +Start Application Development +----------------------------- + +Before powering up the ESP32-PICO-KIT V4, please make sure that the board has been received in good condition with no obvious signs of damage. + +To start development of applications, proceed to section :doc:`index`, that will walk you through the following steps: + +* :ref:`get-started-setup-toolchain-cmake` in your PC to develop applications for ESP32 in C language +* :ref:`get-started-connect-cmake` the module to the PC and verify if it is accessible +* :ref:`get-started-build-cmake` for an example application +* :ref:`get-started-flash-cmake` to run code on the ESP32 +* :ref:`get-started-build-monitor-cmake` instantly what the application is doing + + +Pin Descriptions +---------------- + +The two tables below provide the **Name** and **Function** of I/O headers on both sides of the board, see :ref:`get-started-pico-kit-v4-board-front-cmake`. The pin numbering and header names are the same as on a schematic in `Related Documents`_. + + +Header J2 +""""""""" + +====== ================= ====== ====================================================== +No. Name Type Function +====== ================= ====== ====================================================== +1 FLASH_SD1 (FSD1) I/O | GPIO8, SD_DATA1, SPID, HS1_DATA1 :ref:`(1) ` , U2CTS +2 FLASH_SD3 (FSD3) I/O | GPIO7, SD_DATA0, SPIQ, HS1_DATA0 :ref:`(1) ` , U2RTS +3 FLASH_CLK (FCLK) I/O | GPIO6, SD_CLK, SPICLK, HS1_CLK :ref:`(1) ` , U1CTS +4 IO21 I/O | GPIO21, VSPIHD, EMAC_TX_EN +5 IO22 I/O | GPIO22, VSPIWP, U0RTS, EMAC_TXD1 +6 IO19 I/O | GPIO19, VSPIQ, U0CTS, EMAC_TXD0 +7 IO23 I/O | GPIO23, VSPID, HS1_STROBE +8 IO18 I/O | GPIO18, VSPICLK, HS1_DATA7 +9 IO5 I/O | GPIO5, VSPICS0, HS1_DATA6, EMAC_RX_CLK +10 IO10 I/O | GPIO10, SD_DATA3, SPIWP, HS1_DATA3, U1TXD +11 IO9 I/O | GPIO9, SD_DATA2, SPIHD, HS1_DATA2, U1RXD +12 RXD0 I/O | GPIO3, U0RXD :ref:`(4) ` , CLK_OUT2 +13 TXD0 I/O | GPIO1, U0TXD :ref:`(4) ` , CLK_OUT3, EMAC_RXD2 +14 IO35 I | ADC1_CH7, RTC_GPIO5 +15 IO34 I | ADC1_CH6, RTC_GPIO4 +16 IO38 I | GPIO38, ADC1_CH2, ADC_PRE_AMP :ref:`(2b) ` , RTC_GPIO2 +17 IO37 I | GPIO37, ADC_PRE_AMP :ref:`(2a) ` , ADC1_CH1, RTC_GPIO1 +18 EN I | CHIP_PU +19 GND P | Ground +20 VDD33 (3V3) P | 3.3V power supply +====== ================= ====== ====================================================== + + +Header J3 +""""""""" + +====== ================= ====== ====================================================== +No. Name Type Function +====== ================= ====== ====================================================== +1 FLASH_CS (FCS) I/O | GPIO16, HS1_DATA4 :ref:`(1) ` , U2RXD, EMAC_CLK_OUT +2 FLASH_SD0 (FSD0) I/O | GPIO17, HS1_DATA5 :ref:`(1) ` , U2TXD, EMAC_CLK_OUT_180 +3 FLASH_SD2 (FSD2) I/O | GPIO11, SD_CMD, SPICS0, HS1_CMD :ref:`(1) ` , U1RTS +4 SENSOR_VP (FSVP) I | GPIO36, ADC1_CH0, ADC_PRE_AMP :ref:`(2a) ` , RTC_GPIO0 +5 SENSOR_VN (FSVN) I | GPIO39, ADC1_CH3, ADC_PRE_AMP :ref:`(2b) ` , RTC_GPIO3 +6 IO25 I/O | GPIO25, DAC_1, ADC2_CH8, RTC_GPIO6, EMAC_RXD0 +7 IO26 I/O | GPIO26, DAC_2, ADC2_CH9, RTC_GPIO7, EMAC_RXD1 +8 IO32 I/O | 32K_XP :ref:`(3a) ` , ADC1_CH4, TOUCH9, RTC_GPIO9 +9 IO33 I/O | 32K_XN :ref:`(3b) ` , ADC1_CH5, TOUCH8, RTC_GPIO8 +10 IO27 I/O | GPIO27, ADC2_CH7, TOUCH7, RTC_GPIO17 + | EMAC_RX_DV +11 IO14 I/O | ADC2_CH6, TOUCH6, RTC_GPIO16, MTMS, HSPICLK, + | HS2_CLK, SD_CLK, EMAC_TXD2 +12 IO12 I/O | ADC2_CH5, TOUCH5, RTC_GPIO15, MTDI :ref:`(5) ` , HSPIQ, + | HS2_DATA2, SD_DATA2, EMAC_TXD3 +13 IO13 I/O | ADC2_CH4, TOUCH4, RTC_GPIO14, MTCK, HSPID, + | HS2_DATA3, SD_DATA3, EMAC_RX_ER +14 IO15 I/O | ADC2_CH3, TOUCH3, RTC_GPIO13, MTDO, HSPICS0 + | HS2_CMD, SD_CMD, EMAC_RXD3 +15 IO2 I/O | ADC2_CH2, TOUCH2, RTC_GPIO12, HSPIWP, + | HS2_DATA0, SD_DATA0 +16 IO4 I/O | ADC2_CH0, TOUCH0, RTC_GPIO10, HSPIHD, + | HS2_DATA1, SD_DATA1, EMAC_TX_ER +17 IO0 I/O | ADC2_CH1, TOUCH1, RTC_GPIO11, CLK_OUT1 + | EMAC_TX_CLK +18 VDD33 (3V3) P | 3.3V power supply +19 GND P | Ground +20 EXT_5V (5V) P | 5V power supply +====== ================= ====== ====================================================== + + +.. _get-started-pico-kit-v4-pin-notes-cmake: + +**Notes to** `Pin Descriptions`_ + + 1. This pin is connected to the flash pin of ESP32-PICO-D4. + 2. When used as ADC_PRE_AMP, connect 270 pF capacitors between: (a) SENSOR_VP and IO37, (b) SENSOR_VN and IO38. + 3. 32.768 kHz crystal oscillator: (a) input, (b) output. + 4. This pin is connected to the pin of the USB bridge chip on the board. + 5. The operating voltage of ESP32-PICO-KIT’s embedded SPI flash is 3.3V. Therefore, the strapping pin MTDI should hold bit ”0” during the module power-on reset. + + +Board Dimensions +---------------- + +.. figure:: ../../_static/esp32-pico-kit-v4-dimensions-back.jpg + :align: center + :alt: ESP32-PICO-KIT V4 dimensions - back + :figclass: align-center + + ESP32-PICO-KIT V4 dimensions - back + +.. figure:: ../../_static/esp32-pico-kit-v4-dimensions-side.jpg + :align: center + :alt: ESP32-PICO-KIT V4 dimensions - side + :figclass: align-center + + ESP32-PICO-KIT V4 dimensions - side + + +Related Documents +----------------- + +* `ESP32-PICO-KIT V4 schematic `_ (PDF) +* `ESP32-PICO-D4 Datasheet `_ (PDF) +* :doc:`../hw-reference/index` + + +.. toctree:: + :hidden: + + get-started-pico-kit-v3 diff --git a/docs/en/get-started-cmake/get-started-wrover-kit-v2.rst b/docs/en/get-started-cmake/get-started-wrover-kit-v2.rst new file mode 100644 index 000000000..c10325fb3 --- /dev/null +++ b/docs/en/get-started-cmake/get-started-wrover-kit-v2.rst @@ -0,0 +1,192 @@ +ESP-WROVER-KIT V2 Getting Started Guide (CMake) +=============================================== + +This user guide shows how to get started with ESP-WROVER-KIT V2 development board including description of its functionality and configuration options. For description of other versions of the ESP-WROVER-KIT check :doc:`../hw-reference/index`. + +If you like to start using this board right now, go directly to section :ref:`esp-wrover-kit-v2-start-development-cmake`. + + +What You Need +------------- + +* 1 × ESP-WROVER-KIT V2 board +* 1 x Micro USB 2.0 Cable, Type A to Micro B +* 1 × PC loaded with Windows, Linux or Mac OS + + +Overview +^^^^^^^^ + +The ESP-WROVER-KIT is a development board produced by `Espressif `_ built around ESP32. This board is compatible with ESP32 modules, including the ESP-WROOM-32 and ESP32-WROVER. The ESP-WROVER-KIT features support for an LCD and MicroSD card. The I/O pins have been broken out from the ESP32 module for easy extension. The board carries an advanced multi-protocol USB bridge (the FTDI FT2232HL), enabling developers to use JTAG directly to debug the ESP32 through the USB interface. The development board makes secondary development easy and cost-effective. + +.. note:: + + ESP-WROVER-KIT V2 integrates the ESP-WROOM-32 module by default. + + +Functionality Overview +^^^^^^^^^^^^^^^^^^^^^^ + +Block diagram below presents main components of ESP-WROVER-KIT and interconnections between components. + +.. figure:: ../../_static/esp32-wrover-kit-block-diagram.png + :align: center + :alt: ESP-WROVER-KIT block diagram + :figclass: align-center + + ESP-WROVER-KIT block diagram + + +Functional Description +^^^^^^^^^^^^^^^^^^^^^^ + +The following list and figures below describe key components, interfaces and controls of ESP-WROVER-KIT board. + +32.768 kHz + An external precision 32.768 kHz crystal oscillator provides the chip with a clock of low-power consumption during the Deep-sleep mode. +ESP32 Module + ESP-WROVER-KIT is compatible with both ESP-WROOM-32 and ESP32-WROVER. The ESP32-WROVER module features all the functions of ESP-WROOM-32 and integrates an external 32-MBit PSRAM for flexible extended storage and data processing capabilities. + + .. note:: + + GPIO16 and GPIO17 are used as the CS and clock signal for PSRAM. To ensure reliable performance, the two GPIOs are not broken out. + +CTS/RTS + Serial port flow control signals: the pins are not connected to the circuitry by default. To enable them, respective pins of JP14 must be shorted with jumpers. +UART + Serial port: the serial TX/RX signals on FT2232HL and ESP32 are broken out to the two sides of JP11. By default, the two signals are connected with jumpers. To use the ESP32 module serial interface only, the jumpers may be removed and the module can be connected to another external serial device. +SPI + SPI interface: the SPI interface connects to an external flash (PSRAM). To interface another SPI device, an extra CS signal is needed. If an ESP32-WROVER is being used, please note that the electrical level on the flash and SRAM is 1.8V. +JTAG + JTAG interface: the JTAG signals on FT2232HL and ESP32 are broken out to the two sides of JP8. By default, the two signals are disconnected. To enable JTAG, shorting jumpers are required on the signals. +FT2232 + FT2232 chip is a multi-protocol USB-to-serial bridge. The FT2232 chip features USB-to-UART and USB-to-JTAG functionalities. Users can control and program the FT2232 chip through the USB interface to establish communication with ESP32. + + The embedded FT2232 chip is one of the distinguishing features of the ESP-WROVER-KIT. It enhances users’ convenience in terms of application development and debugging. In addition, uses do not need to buy a JTAG debugger separately, which reduces the development cost, see `ESP-WROVER-KIT V2 schematic`_. +EN + Reset button: pressing this button resets the system. +Boot + Download button: holding down the **Boot** button and pressing the **EN** button initiates the firmware download mode. Then user can download firmware through the serial port. +USB + USB interface. It functions as the power supply for the board and the communication interface between PC and ESP32 module. +Power Select + Power supply selection interface: the ESP-WROVER-KIT can be powered through the USB interface or the 5V Input interface. The user can select the power supply with a jumper. More details can be found in section :ref:`esp-wrover-kit-v2-setup-options-cmake`, jumper header JP7. +Power Key + Power on/off button: toggling to the right powers the board on; toggling to the left powers the board off. +5V Input + The 5V power supply interface is used as a backup power supply in case of full-load operation. +LDO + NCP1117(1A). 5V-to-3.3V LDO. (There is an alternative pin-compatible LDO — LM317DCY, with an output current of up to 1.5A). NCP1117 can provide a maximum current of 1A. The LDO solutions are available with both fixed output voltage and variable output voltage. For details please refer to `ESP-WROVER-KIT V2 schematic`_. +Camera + Camera interface: a standard OV7670 camera module is supported. +RGB + Red, green and blue (RGB) light emitting diodes (LEDs), which may be controlled by pulse width modulation (PWM). +I/O + All the pins on the ESP32 module are led out to the pin headers on the ESPWROVER-KIT. Users can program ESP32 to enable multiple functions such as PWM, ADC, DAC, I2C, I2S, SPI, etc. + +Micro SD Card + Micro SD card slot for data storage: when ESP32 enters the download mode, GPIO2 cannot be held high. However, a pull-up resistor is required on GPIO2 to enable the Micro SD Card. By default, GPIO2 and the pull-up resistor R153 are disconnected. To enable the SD Card, use jumpers on JP1 as shown in section :ref:`esp-wrover-kit-v2-setup-options-cmake`. +LCD + ESP-WROVER-KIT supports mounting and interfacing a 3.2” SPI (standard 4-wire Serial Peripheral Interface) LCD, as shown on figure :ref:`esp-wrover-kit-v2-board-back-cmake`. + +.. figure:: ../../_static/esp-wrover-kit-v2-layout-front.png + :align: center + :alt: ESP-WROVER-KIT board layout - front + :figclass: align-center + + ESP-WROVER-KIT board layout - front + +.. _esp-wrover-kit-v2-board-back-cmake: + +.. figure:: ../../_static/esp-wrover-kit-v2-layout-back.png + :align: center + :alt: ESP-WROVER-KIT board layout - back + :figclass: align-center + + ESP-WROVER-KIT board layout - back + + +.. _esp-wrover-kit-v2-setup-options-cmake: + +Setup Options +^^^^^^^^^^^^^ + +There are five jumper headers available to set up the board functionality. Typical options to select from are listed in table below. + ++--------+----------------------+-------------------------------------------------+ +| Header | Jumper Setting | Description of Functionality | ++--------+----------------------+-------------------------------------------------+ +| JP1 | |jp1-sd_io2| | Enable pull up for the Micro SD Card | ++--------+----------------------+-------------------------------------------------+ +| JP1 | |jp1-both| | Assert GPIO2 low during each download | +| | | (by jumping it to GPIO0) | ++--------+----------------------+-------------------------------------------------+ +| JP7 | |jp7-ext_5v| | Power ESP-WROVER-KIT board from an external | +| | | power supply | ++--------+----------------------+-------------------------------------------------+ +| JP7 | |jp7-usb_5v| | Power ESP-WROVER-KIT board from an USB port | ++--------+----------------------+-------------------------------------------------+ +| JP8 | |jp8| | Enable JTAG functionality | ++--------+----------------------+-------------------------------------------------+ +| JP11 | |jp11-rx-tx| | Enable UART communication | ++--------+----------------------+-------------------------------------------------+ +| JP14 | |jp14| | Enable RTS/CTS flow control for serial | +| | | communication | ++--------+----------------------+-------------------------------------------------+ + + +.. _esp-wrover-kit-v2-start-development-cmake: + +Start Application Development +----------------------------- + +Before powering up the ESP-WROVER-KIT, please make sure that the board has been received in good condition with no obvious signs of damage. + + +Initial Setup +^^^^^^^^^^^^^ + +Select the source of power supply for the board by setting jumper JP7. The options are either USB port or an external power supply. For this application selection of USB port is sufficient. Enable UART communication by installing jumpers on JP11. Both selections are shown in table below. + ++----------------------+----------------------+ +| Power up | Enable UART | +| from USB port | communication | ++----------------------+----------------------+ +| |jp7-usb_5v| | |jp11-rx-tx| | ++----------------------+----------------------+ + +Do not install any other jumpers. + + +Now to Development +^^^^^^^^^^^^^^^^^^ + +To start development of applications for ESP32-DevKitC, proceed to section :doc:`index`, that will walk you through the following steps: + +* :ref:`get-started-setup-toolchain-cmake` in your PC to develop applications for ESP32 in C language +* :ref:`get-started-connect-cmake` the module to the PC and verify if it is accessible +* :ref:`get-started-build-cmake` for an example application +* :ref:`get-started-flash-cmake` to run code on the ESP32 +* :ref:`get-started-build-monitor-cmake` instantly what the application is doing + + +Related Documents +----------------- + +* `ESP-WROVER-KIT V2 schematic`_ (PDF) +* `ESP32 Datasheet `_ (PDF) +* `ESP-WROOM-32 Datasheet `_ (PDF) +* `ESP32-WROVER Datasheet `_ (PDF) +* :doc:`../api-guides/jtag-debugging/index` +* :doc:`../hw-reference/index` + + +.. |jp1-sd_io2| image:: ../../_static/wrover-jp1-sd_io2.png +.. |jp1-both| image:: ../../_static/wrover-jp1-both.png +.. |jp7-ext_5v| image:: ../../_static/wrover-jp7-ext_5v.png +.. |jp7-usb_5v| image:: ../../_static/wrover-jp7-usb_5v.png +.. |jp8| image:: ../../_static/wrover-jp8.png +.. |jp11-rx-tx| image:: ../../_static/wrover-jp11-tx-rx.png +.. |jp14| image:: ../../_static/wrover-jp14.png + +.. _ESP-WROVER-KIT V2 schematic: https://dl.espressif.com/dl/schematics/ESP-WROVER-KIT_SCH-2.pdf diff --git a/docs/en/get-started-cmake/get-started-wrover-kit.rst b/docs/en/get-started-cmake/get-started-wrover-kit.rst new file mode 100644 index 000000000..c99c62d36 --- /dev/null +++ b/docs/en/get-started-cmake/get-started-wrover-kit.rst @@ -0,0 +1,413 @@ +ESP-WROVER-KIT V3 Getting Started Guide (CMake) +=============================================== + +This user guide shows how to get started with ESP-WROVER-KIT V3 development board including description of its functionality and configuration options. For description of other versions of the ESP-WROVER-KIT check :doc:`../hw-reference/index`. + +If you like to start using this board right now, go directly to section :ref:`get-started-esp-wrover-kit-start-development-cmake`. + + +What You Need +------------- + +* 1 × :ref:`ESP-WROVER-KIT V3 board ` +* 1 x Micro USB 2.0 Cable, Type A to Micro B +* 1 × PC loaded with Windows, Linux or Mac OS + + +Overview +^^^^^^^^ + +The ESP-WROVER-KIT is a development board produced by `Espressif `_ built around ESP32. This board is compatible with ESP32 modules, including the ESP-WROOM-32 and ESP32-WROVER. The ESP-WROVER-KIT features support for an LCD and MicroSD card. The I/O pins have been broken out from the ESP32 module for easy extension. The board carries an advanced multi-protocol USB bridge (the FTDI FT2232HL), enabling developers to use JTAG directly to debug the ESP32 through the USB interface. The development board makes secondary development easy and cost-effective. + +.. note:: + + ESP-WROVER-KIT V3 integrates the ESP32-WROVER module by default. + + +Functionality Overview +^^^^^^^^^^^^^^^^^^^^^^ + +Block diagram below presents main components of ESP-WROVER-KIT and interconnections between components. + +.. figure:: ../../_static/esp32-wrover-kit-block-diagram.png + :align: center + :alt: ESP-WROVER-KIT block diagram + :figclass: align-center + + ESP-WROVER-KIT block diagram + + +Functional Description +^^^^^^^^^^^^^^^^^^^^^^ + +The following list and figures below describe key components, interfaces and controls of ESP-WROVER-KIT board. + +32.768 kHz + An external precision 32.768 kHz crystal oscillator provides the chip with a clock of low-power consumption during the Deep-sleep mode. +0R + A zero Ohm resistor intended as a placeholder for a current shunt. May be desoldered or replaced with a current shunt to facilitate measurement of current required by ESP32 module depending on power mode. +ESP32 Module + ESP-WROVER-KIT is compatible with both ESP-WROOM-32 and ESP32-WROVER. The ESP32-WROVER module features all the functions of ESP-WROOM-32 and integrates an external 32-MBit PSRAM for flexible extended storage and data processing capabilities. + + .. note:: + + GPIO16 and GPIO17 are used as the CS and clock signal for PSRAM. To ensure reliable performance, the two GPIOs are not broken out. + +FT2232 + The FT2232 chip is a multi-protocol USB-to-serial bridge. Users can control and program the FT2232 chip through the USB interface to establish communication with ESP32. The FT2232 chip also features USB-to-JTAG interface. USB-to-JTAG is available on channel A of FT2232, USB-to-serial on channel B. The embedded FT2232 chip is one of the distinguishing features of the ESPWROVER-KIT. It enhances users’ convenience in terms of application development and debugging. In addition, users do not need to buy a JTAG debugger separately, which reduces the development cost, see `ESP-WROVER-KIT V3 schematic`_. +UART + Serial port: the serial TX/RX signals on FT2232HL and ESP32 are broken out to the two sides of JP11. By default, the two signals are connected with jumpers. To use the ESP32 module serial interface only, the jumpers may be removed and the module can be connected to another external serial device. +SPI + SPI interface: the SPI interface connects to an external flash (PSRAM). To interface another SPI device, an extra CS signal is needed. The electrical level on the flash of this module is 1.8V. If an ESP-WROOM-32 is being used, please note that the electrical level on the flash of this module is 3.3V. +CTS/RTS + Serial port flow control signals: the pins are not connected to the circuitry by default. To enable them, respective pins of JP14 must be shorted with jumpers. +JTAG + JTAG interface: the JTAG signals on FT2232HL and ESP32 are broken out to the two sides of JP8. By default, the two signals are disconnected. To enable JTAG, shorting jumpers are required on the signals. +EN + Reset button: pressing this button resets the system. +Boot + Download button: holding down the **Boot** button and pressing the **EN** button initiates the firmware download mode. Then user can download firmware through the serial port. +USB + USB interface. It functions as the power supply for the board and the communication interface between PC and ESP32 module. +Power Select + Power supply selection interface: the ESP-WROVER-KIT can be powered through the USB interface or the 5V Input interface. The user can select the power supply with a jumper. More details can be found in section :ref:`get-started-esp-wrover-kit-setup-options-cmake`, jumper header JP7. +Power Key + Power on/off button: toggling to the right powers the board on; toggling to the left powers the board off. +5V Input + The 5V power supply interface is used as a backup power supply in case of full-load operation. +LDO + NCP1117(1A). 5V-to-3.3V LDO. (There is an alternative pin-compatible LDO — LM317DCY, with an output current of up to 1.5A). NCP1117 can provide a maximum current of 1A. The LDO solutions are available with both fixed output voltage and variable output voltage. For details please refer to `ESP-WROVER-KIT V3 schematic`_. +Camera + Camera interface: a standard OV7670 camera module is supported. +RGB + Red, green and blue (RGB) light emitting diodes (LEDs), which may be controlled by pulse width modulation (PWM). +I/O + All the pins on the ESP32 module are led out to the pin headers on the ESP-WROVER-KIT. Users can program ESP32 to enable multiple functions such as PWM, ADC, DAC, I2C, I2S, SPI, etc. +Micro SD Card + Micro SD card slot for data storage. +LCD + ESP-WROVER-KIT supports mounting and interfacing a 3.2” SPI (standard 4-wire Serial Peripheral Interface) LCD, as shown on figure :ref:`get-started-esp-wrover-kit-board-back-cmake`. + +.. _get-started-esp-wrover-kit-board-front-cmake: + +.. figure:: ../../_static/esp32-wrover-kit-layout-front.jpg + :align: center + :alt: ESP-WROVER-KIT board layout - front + :figclass: align-center + + ESP-WROVER-KIT board layout - front + +.. _get-started-esp-wrover-kit-board-back-cmake: + +.. figure:: ../../_static/esp32-wrover-kit-layout-back.jpg + :align: center + :alt: ESP-WROVER-KIT board layout - back + :figclass: align-center + + ESP-WROVER-KIT board layout - back + + +.. _get-started-esp-wrover-kit-setup-options-cmake: + +Setup Options +^^^^^^^^^^^^^ + +There are five jumper headers available to set up the board functionality. Typical options to select from are listed in table below. + ++--------+------------------+--------------------------------------------------+ +| Header | Jumper Setting | Description of Functionality | ++--------+------------------+--------------------------------------------------+ +| JP7 | |jp7-ext_5v| | Power ESP-WROVER-KIT board from an external | +| | | power supply | ++--------+------------------+--------------------------------------------------+ +| JP7 | |jp7-usb_5v| | Power ESP-WROVER-KIT board from an USB port | ++--------+------------------+--------------------------------------------------+ +| JP8 | |jp8| | Enable JTAG functionality | ++--------+------------------+--------------------------------------------------+ +| JP11 | |jp11-rx-tx| | Enable UART communication | ++--------+------------------+--------------------------------------------------+ +| JP14 | |jp14| | Enable RTS/CTS flow control for serial | +| | | communication | ++--------+------------------+--------------------------------------------------+ + + +Allocation of ESP32 Pins +^^^^^^^^^^^^^^^^^^^^^^^^ + +Several pins / terminals of ESP32 module are allocated to the on board hardware. Some of them, like GPIO0 or GPIO2, have multiple functions. If certain hardware is not installed, e.g. nothing is plugged in to the Camera / JP4 header, then selected GPIOs may be used for other purposes. + + +Main I/O Connector / JP1 +"""""""""""""""""""""""" + +The JP1 connector is shown in two columns in the middle under "I/O" headers. The two columns "Shared With" outside, describe where else on the board certain GPIO is used. + ++----------------------+------+------+----------------------+ +| Shared With | I/O | I/O | Shared With | ++======================+======+======+======================+ +| | 3.3V | GND | | ++----------------------+------+------+----------------------+ +| NC/XTAL | IO32 | IO33 | NC/XTAL | ++----------------------+------+------+----------------------+ +| JTAG, MicroSD | IO12 | IO13 | JTAG, MicroSD | ++----------------------+------+------+----------------------+ +| JTAG, MicroSD | IO14 | IO27 | Camera | ++----------------------+------+------+----------------------+ +| Camera | IO26 | IO25 | Camera, LCD | ++----------------------+------+------+----------------------+ +| Camera | IO35 | IO34 | Camera | ++----------------------+------+------+----------------------+ +| Camera | IO39 | IO36 | Camera | ++----------------------+------+------+----------------------+ +| JTAG | EN | IO23 | Camera, LCD | ++----------------------+------+------+----------------------+ +| Camera, LCD | IO22 | IO21 | Camera, LCD, MicroSD | ++----------------------+------+------+----------------------+ +| Camera, LCD | IO19 | IO18 | Camera, LCD | ++----------------------+------+------+----------------------+ +| Camera, LCD | IO5 | IO17 | PSRAM | ++----------------------+------+------+----------------------+ +| PSRAM | IO16 | IO4 | LED, Camera, MicroSD | ++----------------------+------+------+----------------------+ +| LED, Boot | IO0 | IO2 | LED, Camera, MicroSD | ++----------------------+------+------+----------------------+ +| JTAG, MicroSD | IO15 | 5V | | ++----------------------+------+------+----------------------+ + +Legend: + +* NC/XTAL - :ref:`32.768 kHz Oscillator ` +* JTAG - :ref:`JTAG / JP8 ` +* Boot - Boot button / SW2 +* Camera - :ref:`Camera / JP4 ` +* LED - :ref:`RGB LED ` +* MicroSD - :ref:`MicroSD Card / J4 ` +* LCD - :ref:`LCD / U5 ` +* PSRAM - ESP32-WROVER's PSRAM, if ESP32-WROVER is installed + + +.. _get-started-esp-wrover-kit-xtal-cmake: + +32.768 kHz Oscillator +""""""""""""""""""""" + ++---+-----------+ +| | ESP32 Pin | ++===+===========+ +| 1 | GPIO32 | ++---+-----------+ +| 2 | GPIO33 | ++---+-----------+ + +.. note:: + + As GPIO32 and GPIO33 are connected to the oscillator, to maintain signal integrity, they are not connected to JP1 I/O expansion connector. This allocation may be changed from oscillator to JP1 by desoldering 0R resistors from positions R11 / R23 and installing them in positions R12 / R24. + + +.. _get-started-esp-wrover-spi-flash-header-cmake: + +SPI Flash / JP13 +"""""""""""""""" + ++---+--------------+ +| | ESP32 Pin | ++===+==============+ +| 1 | CLK / GPIO6 | ++---+--------------+ +| 2 | SD0 / GPIO7 | ++---+--------------+ +| 3 | SD1 / GPIO8 | ++---+--------------+ +| 4 | SD2 / GPIO9 | ++---+--------------+ +| 5 | SD3 / GPIO10 | ++---+--------------+ +| 6 | CMD / GPIO11 | ++---+--------------+ + +.. important:: + + The module's flash bus is connected to the pin header JP13 through 0-Ohm resistors R140 ~ R145. If the flash frequency needs to operate at 80 MHz, to improve integrity of the bus signals, it is recommended to desolder resistors R140 ~ R145. At this point, the module's flash bus is disconnected with the pin header JP13. + + +.. _get-started-esp-wrover-jtag-header-cmake: + +JTAG / JP8 +"""""""""" + ++---+---------------+-------------+ +| | ESP32 Pin | JTAG Signal | ++===+===============+=============+ +| 1 | EN | TRST_N | ++---+---------------+-------------+ +| 2 | MTDO / GPIO15 | TDO | ++---+---------------+-------------+ +| 3 | MTDI / GPIO12 | TDI | ++---+---------------+-------------+ +| 4 | MTCK / GPIO13 | TCK | ++---+---------------+-------------+ +| 5 | MTMS / GPIO14 | TMS | ++---+---------------+-------------+ + + +.. _get-started-esp-wrover-camera-header-cmake: + +Camera / JP4 +"""""""""""" + ++----+--------------+----------------------+ +| | ESP32 Pin | Camera Signal | ++====+==============+======================+ +| 1 | GPIO27 | SCCB Clock | ++----+--------------+----------------------+ +| 2 | GPIO26 | SCCB Data | ++----+--------------+----------------------+ +| 3 | GPIO21 | System Clock | ++----+--------------+----------------------+ +| 4 | GPIO25 | Vertical Sync | ++----+--------------+----------------------+ +| 5 | GPIO23 | Horizontal Reference | ++----+--------------+----------------------+ +| 6 | GPIO22 | Pixel Clock | ++----+--------------+----------------------+ +| 7 | GPIO4 | Pixel Data Bit 0 | ++----+--------------+----------------------+ +| 8 | GPIO5 | Pixel Data Bit 1 | ++----+--------------+----------------------+ +| 9 | GPIO18 | Pixel Data Bit 2 | ++----+--------------+----------------------+ +| 10 | GPIO19 | Pixel Data Bit 3 | ++----+--------------+----------------------+ +| 11 | GPIO36 | Pixel Data Bit 4 | ++----+--------------+----------------------+ +| 11 | GPIO39 | Pixel Data Bit 5 | ++----+--------------+----------------------+ +| 11 | GPIO34 | Pixel Data Bit 6 | ++----+--------------+----------------------+ +| 11 | GPIO35 | Pixel Data Bit 7 | ++----+--------------+----------------------+ +| 11 | GPIO2 | Camera Reset | ++----+--------------+----------------------+ + + +.. _get-started-esp-wrover-rgb-led-connections-cmake: + +RGB LED +""""""" + ++---+-----------+---------+ +| | ESP32 Pin | RGB LED | ++===+===========+=========+ +| 1 | GPIO0 | Red | ++---+-----------+---------+ +| 2 | GPIO2 | Blue | ++---+-----------+---------+ +| 3 | GPIO4 | Green | ++---+-----------+---------+ + + +.. _get-started-esp-wrover-microsd-card-slot-cmake: + +MicroSD Card / J4 +""""""""""""""""" + ++---+---------------+----------------+ +| | ESP32 Pin | MicroSD Signal | ++===+===============+================+ +| 1 | MTDI / GPIO12 | DATA2 | ++---+---------------+----------------+ +| 2 | MTCK / GPIO13 | CD / DATA3 | ++---+---------------+----------------+ +| 3 | MTDO / GPIO15 | CMD | ++---+---------------+----------------+ +| 4 | MTMS / GPIO14 | CLK | ++---+---------------+----------------+ +| 5 | GPIO2 | DATA0 | ++---+---------------+----------------+ +| 6 | GPIO4 | DATA1 | ++---+---------------+----------------+ +| 7 | GPIO21 | CD | ++---+---------------+----------------+ + + +.. _get-started-esp-wrover-lcd-connector-cmake: + +LCD / U5 +"""""""" + ++---+-----------+------------+ +| | ESP32 Pin | LCD Signal | ++===+===========+============+ +| 1 | GPIO18 | RESET | ++---+-----------+------------+ +| 2 | GPIO19 | SCL | ++---+-----------+------------+ +| 3 | GPIO21 | D/C | ++---+-----------+------------+ +| 4 | GPIO22 | CS | ++---+-----------+------------+ +| 5 | GPIO23 | SDA | ++---+-----------+------------+ +| 6 | GPIO25 | SDO | ++---+-----------+------------+ +| 7 | GPIO5 | Backlight | ++---+-----------+------------+ + + +.. _get-started-esp-wrover-kit-start-development-cmake: + +Start Application Development +----------------------------- + +Before powering up the ESP-WROVER-KIT, please make sure that the board has been received in good condition with no obvious signs of damage. + + +Initial Setup +^^^^^^^^^^^^^ + +Select the source of power supply for the board by setting jumper JP7. The options are either USB port or an external power supply. For this application selection of USB port is sufficient. Enable UART communication by installing jumpers on JP11. Both selections are shown in table below. + ++----------------------+----------------------+ +| Power up | Enable UART | +| from USB port | communication | ++----------------------+----------------------+ +| |jp7-usb_5v| | |jp11-rx-tx| | ++----------------------+----------------------+ + +Do not install any other jumpers. + + +Now to Development +^^^^^^^^^^^^^^^^^^ + +To start development of applications for ESP-WROVER-KIT, proceed to section :doc:`index`, that will walk you through the following steps: + +* :ref:`get-started-setup-toolchain-cmake` in your PC to develop applications for ESP32 in C language +* :ref:`get-started-connect-cmake` the module to the PC and verify if it is accessible +* :ref:`get-started-build-cmake` for an example application +* :ref:`get-started-flash-cmake` to run code on the ESP32 +* :ref:`get-started-build-monitor-cmake` instantly what the application is doing + + +Related Documents +----------------- + +* `ESP-WROVER-KIT V3 schematic`_ (PDF) +* `ESP32 Datasheet `_ (PDF) +* `ESP32-WROVER Datasheet `_ (PDF) +* `ESP-WROOM-32 Datasheet `_ (PDF) +* :doc:`../api-guides/jtag-debugging/index` +* :doc:`../hw-reference/index` + +.. |jp7-ext_5v| image:: ../../_static/esp-wrover-kit-v3-jp7-ext_5v.png +.. |jp7-usb_5v| image:: ../../_static/esp-wrover-kit-v3-jp7-usb_5v.png +.. |jp8| image:: ../../_static/esp-wrover-kit-v3-jp8.png +.. |jp11-rx-tx| image:: ../../_static/esp-wrover-kit-v3-jp11-tx-rx.png +.. |jp14| image:: ../../_static/esp-wrover-kit-v3-jp14.png + +.. _ESP-WROVER-KIT V3 schematic: https://dl.espressif.com/dl/schematics/ESP-WROVER-KIT_SCH-3.pdf + +.. toctree:: + :hidden: + + get-started-wrover-kit-v2.rst diff --git a/docs/en/get-started-cmake/idf-monitor.rst b/docs/en/get-started-cmake/idf-monitor.rst new file mode 100644 index 000000000..b29667cdb --- /dev/null +++ b/docs/en/get-started-cmake/idf-monitor.rst @@ -0,0 +1,135 @@ +******************* +IDF Monitor (CMake) +******************* + + +The idf_monitor tool is a Python program which runs when the ``idf.py monitor`` target is invoked in IDF. + +It is mainly a serial terminal program which relays serial data to and from the target device's serial port, but it has some other IDF-specific features. + +Interacting With IDF Monitor +============================ + +- ``Ctrl-]`` will exit the monitor. +- ``Ctrl-T Ctrl-H`` will display a help menu with all other keyboard shortcuts. +- Any other key apart from ``Ctrl-]`` and ``Ctrl-T`` is sent through the serial port. + +Automatically Decoding Addresses +================================ + +Any time esp-idf prints a hexadecimal code address of the form ``0x4_______``, IDF Monitor will use addr2line_ to look up the source code location and function name. + +.. highlight:: none + +When an esp-idf app crashes and panics a register dump and backtrace such as this is produced:: + + Guru Meditation Error of type StoreProhibited occurred on core 0. Exception was unhandled. + Register dump: + PC : 0x400f360d PS : 0x00060330 A0 : 0x800dbf56 A1 : 0x3ffb7e00 + A2 : 0x3ffb136c A3 : 0x00000005 A4 : 0x00000000 A5 : 0x00000000 + A6 : 0x00000000 A7 : 0x00000080 A8 : 0x00000000 A9 : 0x3ffb7dd0 + A10 : 0x00000003 A11 : 0x00060f23 A12 : 0x00060f20 A13 : 0x3ffba6d0 + A14 : 0x00000047 A15 : 0x0000000f SAR : 0x00000019 EXCCAUSE: 0x0000001d + EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000 + + Backtrace: 0x400f360d:0x3ffb7e00 0x400dbf56:0x3ffb7e20 0x400dbf5e:0x3ffb7e40 0x400dbf82:0x3ffb7e60 0x400d071d:0x3ffb7e90 + +IDF Monitor will augment the dump:: + + Guru Meditation Error of type StoreProhibited occurred on core 0. Exception was unhandled. + Register dump: + PC : 0x400f360d PS : 0x00060330 A0 : 0x800dbf56 A1 : 0x3ffb7e00 + 0x400f360d: do_something_to_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:57 + (inlined by) inner_dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:52 + A2 : 0x3ffb136c A3 : 0x00000005 A4 : 0x00000000 A5 : 0x00000000 + A6 : 0x00000000 A7 : 0x00000080 A8 : 0x00000000 A9 : 0x3ffb7dd0 + A10 : 0x00000003 A11 : 0x00060f23 A12 : 0x00060f20 A13 : 0x3ffba6d0 + A14 : 0x00000047 A15 : 0x0000000f SAR : 0x00000019 EXCCAUSE: 0x0000001d + EXCVADDR: 0x00000000 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000 + + Backtrace: 0x400f360d:0x3ffb7e00 0x400dbf56:0x3ffb7e20 0x400dbf5e:0x3ffb7e40 0x400dbf82:0x3ffb7e60 0x400d071d:0x3ffb7e90 + 0x400f360d: do_something_to_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:57 + (inlined by) inner_dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:52 + 0x400dbf56: still_dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:47 + 0x400dbf5e: dont_crash at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:42 + 0x400dbf82: app_main at /home/gus/esp/32/idf/examples/get-started/hello_world/main/./hello_world_main.c:33 + 0x400d071d: main_task at /home/gus/esp/32/idf/components/esp32/./cpu_start.c:254 + +Behind the scenes, the command IDF Monitor runs to decode each address is:: + + xtensa-esp32-elf-addr2line -pfiaC -e build/PROJECT.elf ADDRESS + + +Launch GDB for GDBStub +====================== + +By default, if an esp-idf app crashes then the panic handler prints registers and a stack dump as shown above, and then resets. + +Optionally, the panic handler can be configured to run a serial "gdb stub" which can communicate with a gdb_ debugger program and allow memory to be read, variables and stack frames examined, etc. This is not as versatile as JTAG debugging, but no special hardware is required. + +To enable the gdbstub, run ``idf.py menuconfig`` and set :envvar:`CONFIG_ESP32_PANIC` option to ``Invoke GDBStub``. + +If this option is enabled and IDF Monitor sees the gdb stub has loaded, it will automatically pause serial monitoring and run GDB with the correct arguments. After GDB exits, the board will be reset via the RTS serial line (if this is connected.) + +Behind the scenes, the command IDF Monitor runs is:: + + xtensa-esp32-elf-gdb -ex "set serial baud BAUD" -ex "target remote PORT" -ex interrupt build/PROJECT.elf + + +Quick Compile and Flash +======================= + +The keyboard shortcut ``Ctrl-T Ctrl-F`` will pause idf_monitor, run the ``idf.py flash`` target, then resume idf_monitor. Any changed source files will be recompiled before re-flashing. + +The keyboard shortcut ``Ctrl-T Ctrl-A`` will pause idf-monitor, run the ``idf.py app-flash`` target, then resume idf_monitor. This is similar to ``idf.py flash``, but only the main app is compiled and reflashed. + + +Quick Reset +=========== + +The keyboard shortcut ``Ctrl-T Ctrl-R`` will reset the target board via the RTS line (if it is connected.) + + +Pause the Application +===================== + +The keyboard shortcut ``Ctrl-T Ctrl-P`` will reset the target into bootloader, so that the board will run nothing. This is +useful when you want to wait for another device to startup. Then shortcut ``Ctrl-T Ctrl-R`` can be used to restart the +application. + + +Toggle Output Display +===================== + +Sometimes you may want to stop new output printed to screen, to see the log before. The keyboard shortcut ``Ctrl-T Ctrl-Y`` will +toggle the display (discard all serial data when the display is off) so that you can stop to see the log, and revert +again quickly without quitting the monitor. + + +Simple Monitor +============== + +Earlier versions of ESP-IDF used the pySerial_ command line program miniterm_ as a serial console program. + +This program can still be run, via ``make simple_monitor``. + +IDF Monitor is based on miniterm and shares the same basic keyboard shortcuts. + +.. note:: This target only works in the GNU Make based build system, not the CMake-based build system preview. + +Known Issues with IDF Monitor +============================= + +Issues Observed on Windows +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- If you are using the supported Windows environment and receive the error "winpty: command not found" then run ``pacman -S winpty`` to fix. +- Arrow keys and some other special keys in gdb don't work, due to Windows Console limitations. +- Occasionally when "make" exits, it may stall for up to 30 seconds before idf_monitor resumes. +- Occasionally when "gdb" is run, it may stall for a short time before it begins communicating with the gdbstub. + + +.. _addr2line: https://sourceware.org/binutils/docs/binutils/addr2line.html +.. _gdb: https://sourceware.org/gdb/download/onlinedocs/ +.. _pySerial: https://github.com/pyserial/pyserial +.. _miniterm: https://pyserial.readthedocs.org/en/latest/tools.html#module-serial.tools.miniterm diff --git a/docs/en/get-started-cmake/index.rst b/docs/en/get-started-cmake/index.rst new file mode 100644 index 000000000..8b3318a40 --- /dev/null +++ b/docs/en/get-started-cmake/index.rst @@ -0,0 +1,464 @@ +******************* +Get Started (CMake) +******************* + +.. include:: ../cmake-warning.rst + +.. include:: ../cmake-pending-features.rst + +This document is intended to help users set up the software environment for development of applications using hardware based on the Espressif ESP32. Through a simple example we would like to illustrate how to use ESP-IDF (Espressif IoT Development Framework), including the menu based configuration, compiling the ESP-IDF and firmware download to ESP32 boards. + +Introduction +============ + +ESP32 integrates Wi-Fi (2.4 GHz band) and Bluetooth 4.2 solutions on a single chip, along with dual high performance cores, Ultra Low Power co-processor and several peripherals. Powered by 40 nm technology, ESP32 provides a robust, highly integrated platform to meet the continuous demands for efficient power usage, compact design, security, high performance, and reliability. + +Espressif provides the basic hardware and software resources that help application developers to build their ideas around the ESP32 series hardware. The software development framework by Espressif is intended for rapidly developing Internet-of-Things (IoT) applications, with Wi-Fi, Bluetooth, power management and several other system features. + + +What You Need +============= + +To develop applications for ESP32 you need: + +* **PC** loaded with either Windows, Linux or Mac operating system +* **Toolchain** to compile code for ESP32 +* **Build tools** CMake and Ninja to build a full **Application** for ESP32 +* **ESP-IDF** that essentially contains API for ESP32 and scripts to operate the **Toolchain** +* A text editor to write programs (**Projects**) in C, e.g. `Eclipse `_ +* The **ESP32** board itself and a **USB cable** to connect it to the **PC** + +.. figure:: ../../_static/what-you-need-cmake.png + :align: center + :alt: Development of applications for ESP32 + :figclass: align-center + + Development of applications for ESP32 + +Steps to set up Development Environment: + +1. Setup of **Toolchain** +2. Getting **ESP-IDF** from GitHub + +Once the development environment is set up, we will follow these steps to create an ESP-IDF application: + +1. Configuration of a **Project** and writing the code +2. Compilation of the **Project** and linking it to build an **Application** +3. Flashing (uploading) the compiled **Application** to **ESP32** over a USB/serial connection +4. Monitoring / debugging of the **Application** output via USB/serial + + +Development Board Guides +======================== + +If you have one of ESP32 development boards listed below, click on the link for hardware setup: + +.. toctree:: + :maxdepth: 1 + + ESP32 DevKitC + ESP-WROVER-KIT + ESP32-PICO-KIT + +If you have different board, move to sections below. + + +.. _get-started-setup-toolchain-cmake: + +Setup Toolchain +=============== + +The quickest way to start development with ESP32 is by installing a prebuilt toolchain. Pick up your OS below and follow provided instructions. + +.. toctree:: + :hidden: + + Windows + Linux + MacOS + ++-------------------+-------------------+-------------------+ +| |windows-logo| | |linux-logo| | |macos-logo| | ++-------------------+-------------------+-------------------+ +| `Windows`_ | `Linux`_ | `Mac OS`_ | ++-------------------+-------------------+-------------------+ + +.. |windows-logo| image:: ../../_static/windows-logo.png + :target: ../get-started-cmake/windows-setup.html + +.. |linux-logo| image:: ../../_static/linux-logo.png + :target: ../get-started-cmake/linux-setup.html + +.. |macos-logo| image:: ../../_static/macos-logo.png + :target: ../get-started-cmake/macos-setup.html + +.. _Windows: ../get-started-cmake/windows-setup.html +.. _Linux: ../get-started-cmake/linux-setup.html +.. _Mac OS: ../get-started-cmake/macos-setup.html + +.. note:: + + We are an using ``esp`` subdirectory in your user's home directory (``~/esp`` on Linux and MacOS, ``%userprofile%\esp`` on Windows) to install everything needed for ESP-IDF. You can use any different directory, but will need to adjust the respective commands. + +Depending on your experience and preferences, instead of using a prebuilt toolchain, you may want to customize your environment. To set up the system your own way go to section :ref:`get-started-customized-setup-cmake`. + +Once you are done with setting up the toolchain then go to section :ref:`get-started-get-esp-idf-cmake`. + +.. _get-started-get-esp-idf-cmake: + +Get ESP-IDF +=========== + +Besides the toolchain (that contains programs to compile and build the application), you also need ESP32 specific API / libraries. They are provided by Espressif in `ESP-IDF repository `_. To get it, open terminal, navigate to the directory you want to put ESP-IDF, and clone it using ``git clone`` command. + +Linux and MacOS +~~~~~~~~~~~~~~~ + +.. code-block:: bash + + mkdir -p ~/esp + cd ~/esp + git clone --branch feature/cmake --recursive https://github.com/espressif/esp-idf.git + +ESP-IDF will be downloaded into ``~/esp/esp-idf``. + + +Windows Command Prompt +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: batch + + mkdir %userprofile%\esp + cd %userprofile%\esp + git clone --branch feature/cmake --recursive https://github.com/espressif/esp-idf.git + +.. highlight:: bash +.. note:: + + Do not miss the ``--recursive`` option. If you have already cloned ESP-IDF without this option, run another command to get all the submodules:: + + cd esp-idf + git submodule update --init + +.. note:: + + The CMake-based build system preview uses a different Git branch to the default. This branch is ``feature/cmake``. If you missed the ``--branch`` option when cloning then you can switch branches on the command line:: + + cd esp-idf + git checkout feature/cmake + +.. _get-started-setup-path-cmake: + +Setup Environment Variables +=========================== + +ESP-IDF requires two environment variables to be set for normal operation: + +- ``IDF_PATH`` should be set to the path to the ESP-IDF root directory. +- ``PATH`` should include the path to the ``tools`` directory inside the same ``IDF_PATH`` directory. + +These two variables should be set up on your PC, otherwise projects will not build. + +Setting may be done manually, each time PC is restarted. Another option is to set them permanently in user profile. To do this, follow instructions specific to :ref:`Windows ` , :ref:`Linux and MacOS ` in section :doc:`add-idf_path-to-profile`. + +.. _get-started-start-project-cmake: + +Start a Project +=============== + +Now you are ready to prepare your application for ESP32. To start off quickly, we will use :example:`get-started/hello_world` project from :idf:`examples` directory in IDF. + +Copy :example:`get-started/hello_world` to ``~/esp`` directory: + +Linux and MacOS +~~~~~~~~~~~~~~~ + +.. code-block:: bash + + cd ~/esp + cp -r $IDF_PATH/examples/get-started/hello_world . + +Windows Command Prompt +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: batch + + cd %userprofile%\esp + xcopy /e /i %IDF_PATH%\examples\get-started\hello_world hello_world + +You can also find a range of example projects under the :idf:`examples` directory in ESP-IDF. These example project directories can be copied in the same way as presented above, to begin your own projects. + +It is also possible to build examples in-place, without copying them first. + +.. important:: + + The esp-idf build system does not support spaces in the path to either esp-idf or to projects. + +.. _get-started-connect-cmake: + +Connect +======= + +You are almost there. To be able to proceed further, connect ESP32 board to PC, check under what serial port the board is visible and verify if serial communication works. If you are not sure how to do it, check instructions in section :doc:`establish-serial-connection`. Note the port number, as it will be required in the next step. + +.. _get-started-configure-cmake: + +Configure +========= + +Naviagate to the directory of the ``hello_world`` application copy, and run the ``menuconfig`` project configuration utility: + +Linux and MacOS +~~~~~~~~~~~~~~~ + +.. code-block:: bash + + cd ~/esp/hello_world + idf.py menuconfig + +Windows Command Prompt +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: batch + + cd %userprofile%\esp\hello_world + idf.py menuconfig + +.. note:: If you get an error about ``idf.py`` not being found, check the ``tools`` directory is part of your Path as described above in :ref:`get-started-setup-path-cmake`. If there is no ``idf.py`` in the ``tools`` directory, check you have the correct branch for the CMake preview as shown under :ref:`get-started-get-esp-idf-cmake`. + +.. note:: Windows users, the Python 2.7 installer will try to configure Windows to associate files with a ``.py`` extension with Python 2. If a separate installed program (such as Visual Studio Python Tools) has created an association with a different version of Python, then running ``idf.py`` may not work (it opens the file in Visual Studio instead). You can either run ``C:\Python27\python idf.py`` each time instead, or change the association that Windows uses for ``.py`` files. + +.. note:: Linux users, if your default version of Python is 3.x then you may need to run ``python2 idf.py`` instead. + +If previous steps have been done correctly, the following menu will be displayed: + +.. figure:: ../../_static/project-configuration.png + :align: center + :alt: Project configuration - Home window + :figclass: align-center + + Project configuration - Home window + +Here are couple of tips on navigation and use of ``menuconfig``: + +* Use up & down arrow keys to navigate the menu. +* Use Enter key to go into a submenu, Escape key to go up a level or exit. +* Type ``?`` to see a help screen. Enter key exits the help screen. +* Use Space key, or ``Y`` and ``N`` keys to enable (Yes) and disable (No) configuration items with checkboxes "``[*]``" +* Pressing ``?`` while highlighting a configuration item displays help about that item. +* Type ``/`` to search the configuration items. + +.. _get-started-build-cmake: + +Build The Project +================= + +.. highlight:: bash + +Now you can build the project. Run:: + + idf.py build + +This command will compile the application and all the ESP-IDF components, generate bootloader, partition table, and application binaries. + +.. code-block:: none + + $ idf.py build + Running cmake in directory /path/to/hello_world/build + Executing "cmake -G Ninja --warn-uninitialized /path/to/hello_world"... + Warn about uninitialized values. + -- Found Git: /usr/bin/git (found version "2.17.0") + -- Building empty aws_iot component due to configuration + -- Component names: ... + -- Component paths: ... + + ... (more lines of build system output) + + [527/527] Generating hello-world.bin + esptool.py v2.3.1 + + Project build complete. To flash, run this command: + ../../../components/esptool_py/esptool/esptool.py -p (PORT) -b 921600 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x10000 build/hello-world.bin build 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin + or run 'idf.py -p PORT flash' + +If there are no errors, the build will finish by generating the firmware binary .bin file. + +.. _get-started-flash-cmake: + +Flash To A Device +================= + +Now you can flash the application to the ESP32 board. Run:: + + idf.py -p PORT flash + +Replace PORT with the name of your ESP32 board's serial port. On Windows, serial ports have names like ``COM1``. On MacOS, they start with ``/dev/cu.``. On Linux, they start with ``/dev/tty``. See :doc:`establish-serial-connection` for full details. + +This step will flash the binaries that you just built to your ESP32 board. + +.. note:: Running ``idf.py build`` before ``idf.py flash`` is not actually necessary, the flash step will automatically build the project if required before flashing. + +.. code-block:: none + + Running esptool.py in directory [...]/esp/hello_world + Executing "python [...]/esp-idf/components/esptool_py/esptool/esptool.py -b 460800 write_flash @flash_project_args"... + esptool.py -b 460800 write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 bootloader/bootloader.bin 0x8000 partition_table/partition-table.bin 0x10000 hello-world.bin + esptool.py v2.3.1 + Connecting.... + Detecting chip type... ESP32 + Chip is ESP32D0WDQ6 (revision 1) + Features: WiFi, BT, Dual Core + Uploading stub... + Running stub... + Stub running... + Changing baud rate to 460800 + Changed. + Configuring flash size... + Auto-detected Flash size: 4MB + Flash params set to 0x0220 + Compressed 22992 bytes to 13019... + Wrote 22992 bytes (13019 compressed) at 0x00001000 in 0.3 seconds (effective 558.9 kbit/s)... + Hash of data verified. + Compressed 3072 bytes to 82... + Wrote 3072 bytes (82 compressed) at 0x00008000 in 0.0 seconds (effective 5789.3 kbit/s)... + Hash of data verified. + Compressed 136672 bytes to 67544... + Wrote 136672 bytes (67544 compressed) at 0x00010000 in 1.9 seconds (effective 567.5 kbit/s)... + Hash of data verified. + + Leaving... + Hard resetting via RTS pin... + +If there are no issues, at the end of flash process, the module will be reset and “hello_world” application will be running there. + +.. (Not currently supported) If you'd like to use the Eclipse IDE instead of running ``idf.py``, check out the :doc:`Eclipse guide `. + + +.. _get-started-build-monitor-cmake: + +Monitor +======= + +To see if "hello_world" application is indeed running, type ``idf.py -p PORT monitor``. This command is launching :doc:`IDF Monitor ` application:: + + $ idf.py -p /dev/ttyUSB0 monitor + Running idf_monitor in directory [...]/esp/hello_world/build + Executing "python [...]/esp-idf/tools/idf_monitor.py -b 115200 [...]/esp/hello_world/build/hello-world.elf"... + --- idf_monitor on /dev/ttyUSB0 115200 --- + --- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H --- + ets Jun 8 2016 00:22:57 + + rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) + ets Jun 8 2016 00:22:57 + ... + +Several lines below, after start up and diagnostic log, you should see "Hello world!" printed out by the application. + +.. code-block:: none + + ... + Hello world! + Restarting in 10 seconds... + I (211) cpu_start: Starting scheduler on APP CPU. + Restarting in 9 seconds... + Restarting in 8 seconds... + Restarting in 7 seconds... + +To exit the monitor use shortcut ``Ctrl+]``. + +.. note:: + + If instead of the messages above, you see a random garbage similar to:: + + e���)(Xn@�y.!��(�PW+)��Hn9a؅/9�!�t5��P�~�k��e�ea�5�jA + ~zY��Y(1�,1�� e���)(Xn@�y.!Dr�zY(�jpi�|�+z5Ymvp + + or monitor fails shortly after upload, your board is likely using 26MHz crystal. Most development board designs use 40MHz and the ESP-IDF uses this default value. Exit the monitor, go back to the :ref:`menuconfig `, change :envvar:`CONFIG_ESP32_XTAL_FREQ_SEL` to 26MHz, then :ref:`build and flash ` the application again. This is found under ``idf.py menuconfig`` under Component config --> ESP32-specific --> Main XTAL frequency. + +.. note:: + + You can combine building, flashing and monitoring into one step as follows:: + + idf.py -p PORT flash monitor + +Check the section :doc:`IDF Monitor ` for handy shortcuts and more details on using the monitor. + +Check the section :ref:`idf.py` for a full reference of ``idf.py`` commands and options. + +That's all what you need to get started with ESP32! + +Now you are ready to try some other :idf:`examples`, or go right to developing your own applications. + + +Updating ESP-IDF +================ + +After some time of using ESP-IDF, you may want to update it to take advantage of new features or bug fixes. The simplest way to do so is by deleting existing ``esp-idf`` folder and cloning it again, exactly as when doing initial installation described in sections :ref:`get-started-get-esp-idf-cmake`. + +Another solution is to update only what has changed. This method is useful if you have a slow connection to GitHub. To do the update run the following commands: + +Linux and MacOS +~~~~~~~~~~~~~~~ + +.. code-block:: bash + + cd ~/esp/esp-idf + git pull + git submodule update --init --recursive + +Windows Command Prompt +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: batch + + cd %userprofile%\esp\esp-idf + git pull + git submodule update --init --recursive + +The ``git pull`` command is fetching and merging changes from ESP-IDF repository on GitHub. Then ``git submodule update --init --recursive`` is updating existing submodules or getting a fresh copy of new ones. On GitHub the submodules are represented as links to other repositories and require this additional command to get them onto your PC. + +.. highlight:: bash + +It is also possible to check out a specific release of ESP-IDF, e.g. `v2.1`. + +Linux and MacOS +~~~~~~~~~~~~~~~ + +.. code-block:: bash + + cd ~/esp + git clone https://github.com/espressif/esp-idf.git esp-idf-v2.1 + cd esp-idf-v2.1/ + git checkout v2.1 + git submodule update --init --recursive + + +Windows Command Prompt +~~~~~~~~~~~~~~~~~~~~~~ + +.. code-block:: batch + + cd %userprofile%\esp + git clone https://github.com/espressif/esp-idf.git esp-idf-v2.1 + cd esp-idf-v2.1/ + git checkout v2.1 + git submodule update --init --recursive + +After that remember to :doc:`add-idf_path-to-profile`, so the toolchain scripts know where to find the ESP-IDF in it's release specific location. + +.. note:: + + Different versions of ESP-IDF may have different setup or prerequisite requirements, or require different toolchain versions. If you experience any problems, carefully check the Getting Started documentation for the version you are switching to. + + +Related Documents +================= + +.. toctree:: + :maxdepth: 1 + + add-idf_path-to-profile + establish-serial-connection + eclipse-setup + idf-monitor + toolchain-setup-scratch diff --git a/docs/en/get-started-cmake/linux-setup-scratch.rst b/docs/en/get-started-cmake/linux-setup-scratch.rst new file mode 100644 index 000000000..e1d2205d8 --- /dev/null +++ b/docs/en/get-started-cmake/linux-setup-scratch.rst @@ -0,0 +1,73 @@ +****************************************** +Setup Linux Toolchain from Scratch (CMake) +****************************************** + +.. include:: ../cmake-warning.rst + +The following instructions are alternative to downloading binary toolchain from Espressif website. To quickly setup the binary toolchain, instead of compiling it yourself, backup and proceed to section :doc:`linux-setup`. + +Install Prerequisites +===================== + +To compile with ESP-IDF you need to get the following packages: + +- CentOS 7:: + + sudo yum install git wget ncurses-devel flex bison gperf python pyserial cmake ninja-build ccache + +- Ubuntu and Debian:: + + sudo apt-get install git wget libncurses-dev flex bison gperf python python-serial cmake ninja-build ccache + +- Arch:: + + sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial cmake ninja ccache + +.. note:: + CMake version 3.5 or newer is required for use with ESP-IDF. Older Linux distributions may require updating, enabling of a "backports" repository, or installing of a "cmake3" package rather than "cmake". + +Compile the Toolchain from Source +================================= + +- Install dependencies: + + - CentOS 7:: + + sudo yum install gawk gperf grep gettext ncurses-devel python python-devel automake bison flex texinfo help2man libtool make + + - Ubuntu pre-16.04:: + + sudo apt-get install gawk gperf grep gettext libncurses-dev python python-dev automake bison flex texinfo help2man libtool make + + - Ubuntu 16.04:: + + sudo apt-get install gawk gperf grep gettext python python-dev automake bison flex texinfo help2man libtool libtool-bin make + + - Debian 9:: + + sudo apt-get install gawk gperf grep gettext libncurses-dev python python-dev automake bison flex texinfo help2man libtool libtool-bin make + + - Arch:: + + TODO + +Download ``crosstool-NG`` and build it:: + + cd ~/esp + git clone -b xtensa-1.22.x https://github.com/espressif/crosstool-NG.git + cd crosstool-NG + ./bootstrap && ./configure --enable-local && make install + +Build the toolchain:: + + ./ct-ng xtensa-esp32-elf + ./ct-ng build + chmod -R u+w builds/xtensa-esp32-elf + +Toolchain will be built in ``~/esp/crosstool-NG/builds/xtensa-esp32-elf``. Follow :ref:`instructions for standard setup ` to add the toolchain to your ``PATH``. + + +Next Steps +========== + +To carry on with development environment setup, proceed to section :ref:`get-started-get-esp-idf-cmake`. diff --git a/docs/en/get-started-cmake/linux-setup.rst b/docs/en/get-started-cmake/linux-setup.rst new file mode 100644 index 000000000..8977a582b --- /dev/null +++ b/docs/en/get-started-cmake/linux-setup.rst @@ -0,0 +1,112 @@ +********************************************* +Standard Setup of Toolchain for Linux (CMake) +********************************************* + +.. include:: ../cmake-warning.rst + +Install Prerequisites +===================== + +To compile with ESP-IDF you need to get the following packages: + +- CentOS 7:: + + sudo yum install git wget ncurses-devel flex bison gperf python pyserial cmake ninja-build ccache + +- Ubuntu and Debian:: + + sudo apt-get install git wget libncurses-dev flex bison gperf python python-serial cmake ninja-build ccache + +- Arch:: + + sudo pacman -S --needed gcc git make ncurses flex bison gperf python2-pyserial cmake ninja ccache + +.. note:: + CMake version 3.5 or newer is required for use with ESP-IDF. Older Linux distributions may require updating, enabling of a "backports" repository, or installing of a "cmake3" package rather than "cmake". + +Toolchain Setup +=============== + +ESP32 toolchain for Linux is available for download from Espressif website: + +- for 64-bit Linux: + + https://dl.espressif.com/dl/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz + +- for 32-bit Linux: + + https://dl.espressif.com/dl/xtensa-esp32-elf-linux32-1.22.0-80-g6c4433a-5.2.0.tar.gz + +1. Download this file, then extract it in ``~/esp`` directory:: + + mkdir -p ~/esp + cd ~/esp + tar -xzf ~/Downloads/xtensa-esp32-elf-linux64-1.22.0-80-g6c4433a-5.2.0.tar.gz + +.. _setup-linux-toolchain-add-it-to-path-cmake: + +2. The toolchain will be extracted into ``~/esp/xtensa-esp32-elf/`` directory. + + To use it, you will need to update your ``PATH`` environment variable in ``~/.profile`` file. To make ``xtensa-esp32-elf`` available for all terminal sessions, add the following line to your ``~/.profile`` file:: + + export PATH="$PATH:$HOME/esp/xtensa-esp32-elf/bin" + + Alternatively, you may create an alias for the above command. This way you can get the toolchain only when you need it. To do this, add different line to your ``~/.profile`` file:: + + alias get_esp32='export PATH="$PATH:$HOME/esp/xtensa-esp32-elf/bin"' + + Then when you need the toolchain you can type ``get_esp32`` on the command line and the toolchain will be added to your ``PATH``. + + .. note:: + + If you have ``/bin/bash`` set as login shell, and both ``.bash_profile`` and ``.profile`` exist, then update ``.bash_profile`` instead. + +3. Log off and log in back to make the ``.profile`` changes effective. Run the following command to verify if ``PATH`` is correctly set:: + + printenv PATH + + You are looking for similar result containing toolchain's path at the end of displayed string:: + + $ printenv PATH + /home/user-name/bin:/home/user-name/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/user-name/esp/xtensa-esp32-elf/bin + + Instead of ``/home/user-name`` there should be a home path specific to your installation. + + +Permission issues /dev/ttyUSB0 +------------------------------ + +With some Linux distributions you may get the ``Failed to open port /dev/ttyUSB0`` error message when flashing the ESP32. :ref:`This can be solved by adding the current user to the dialout group`. + + +Arch Linux Users +---------------- + +To run the precompiled gdb (xtensa-esp32-elf-gdb) in Arch Linux requires ncurses 5, but Arch uses ncurses 6. + +Backwards compatibility libraries are available in AUR_ for native and lib32 configurations: + +- https://aur.archlinux.org/packages/ncurses5-compat-libs/ +- https://aur.archlinux.org/packages/lib32-ncurses5-compat-libs/ + +Before installing these packages you might need to add the author's public key to your keyring as described in the "Comments" section at the links above. + +Alternatively, use crosstool-NG to compile a gdb that links against ncurses 6. + + +Next Steps +========== + +To carry on with development environment setup, proceed to section :ref:`get-started-get-esp-idf-cmake`. + + +Related Documents +================= + +.. toctree:: + :maxdepth: 1 + + linux-setup-scratch + + +.. _AUR: https://wiki.archlinux.org/index.php/Arch_User_Repository diff --git a/docs/en/get-started-cmake/macos-setup-scratch.rst b/docs/en/get-started-cmake/macos-setup-scratch.rst new file mode 100644 index 000000000..ae6e8c43e --- /dev/null +++ b/docs/en/get-started-cmake/macos-setup-scratch.rst @@ -0,0 +1,83 @@ +*********************************************** +Setup Toolchain for Mac OS from Scratch (CMake) +*********************************************** + +.. include:: ../cmake-warning.rst + +Package Manager +=============== + +To set up the toolchain from scratch, rather than :doc:`downloading a pre-compiled toolchain`, you will need to install either the MacPorts_ or homebrew_ package manager. + +MacPorts needs a full XCode installation, while homebrew only needs XCode command line tools. + + .. _homebrew: https://brew.sh/ + .. _MacPorts: https://www.macports.org/install.php + +Install Prerequisites +===================== + +- install pip:: + + sudo easy_install pip + +- install pyserial:: + + sudo pip install pyserial + +- install CMake & Ninja build: + + - If you have HomeBrew, you can run:: + + brew install cmake ninja + + - If you have MacPorts, you can run:: + + sudo port install cmake ninja + +Compile the Toolchain from Source +================================= + +- Install dependencies: + + - with MacPorts:: + + sudo port install gsed gawk binutils gperf grep gettext wget libtool autoconf automake make + + - with homebrew:: + + brew install gnu-sed gawk binutils gperftools gettext wget help2man libtool autoconf automake make + +Create a case-sensitive filesystem image:: + + hdiutil create ~/esp/crosstool.dmg -volname "ctng" -size 10g -fs "Case-sensitive HFS+" + +Mount it:: + + hdiutil mount ~/esp/crosstool.dmg + +Create a symlink to your work directory:: + + cd ~/esp + ln -s /Volumes/ctng crosstool-NG + +Download ``crosstool-NG`` and build it:: + + cd ~/esp + git clone -b xtensa-1.22.x https://github.com/espressif/crosstool-NG.git + cd crosstool-NG + ./bootstrap && ./configure --enable-local && make install + +Build the toolchain:: + + ./ct-ng xtensa-esp32-elf + ./ct-ng build + chmod -R u+w builds/xtensa-esp32-elf + +Toolchain will be built in ``~/esp/crosstool-NG/builds/xtensa-esp32-elf``. Follow :ref:`instructions for standard setup ` to add the toolchain to your ``PATH``. + + +Next Steps +========== + +To carry on with development environment setup, proceed to section :ref:`get-started-get-esp-idf-cmake`. diff --git a/docs/en/get-started-cmake/macos-setup.rst b/docs/en/get-started-cmake/macos-setup.rst new file mode 100644 index 000000000..21a780c52 --- /dev/null +++ b/docs/en/get-started-cmake/macos-setup.rst @@ -0,0 +1,90 @@ +********************************************** +Standard Setup of Toolchain for Mac OS (CMake) +********************************************** + +.. include:: ../cmake-warning.rst + +Install Prerequisites +===================== + +ESP-IDF will use the version of Python installed by default on Mac OS. + +- install pip:: + + sudo easy_install pip + +- install pyserial:: + + sudo pip install pyserial + +- install CMake & Ninja build: + + - If you have HomeBrew_, you can run:: + + brew install cmake ninja + + - If you have MacPorts_, you can run:: + + sudo port install cmake ninja + + - Otherwise, consult the CMake_ and Ninja_ home pages for Mac OS installation downloads. + +- It is strongly recommended to also install ccache_ for faster builds. If you have HomeBrew_, this can be done via ``brew install ccache`` or ``sudo port install ccache`` on MacPorts_. + +.. note:: + If an error like this is shown during any step:: + + xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun + + Then you will need to install the XCode command line tools to continue. You can install these by running ``xcode-select --install``. + +Toolchain Setup +=============== + +ESP32 toolchain for macOS is available for download from Espressif website: + +https://dl.espressif.com/dl/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz + +Download this file, then extract it in ``~/esp`` directory:: + + mkdir -p ~/esp + cd ~/esp + tar -xzf ~/Downloads/xtensa-esp32-elf-osx-1.22.0-80-g6c4433a-5.2.0.tar.gz + +.. _setup-macos-toolchain-add-it-to-path-cmake: + +The toolchain will be extracted into ``~/esp/xtensa-esp32-elf/`` directory. + +To use it, you will need to update your ``PATH`` environment variable in ``~/.profile`` file. To make ``xtensa-esp32-elf`` available for all terminal sessions, add the following line to your ``~/.profile`` file:: + + export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin + +Alternatively, you may create an alias for the above command. This way you can get the toolchain only when you need it. To do this, add different line to your ``~/.profile`` file:: + + alias get_esp32="export PATH=$PATH:$HOME/esp/xtensa-esp32-elf/bin" + +Then when you need the toolchain you can type ``get_esp32`` on the command line and the toolchain will be added to your ``PATH``. + +Log off and log in back to make the ``.profile`` changes effective. Run the following command to verify if ``PATH`` is correctly set:: + + printenv PATH + + +Next Steps +========== + +To carry on with development environment setup, proceed to section :ref:`get-started-get-esp-idf-cmake`. + +Related Documents +================= + +.. toctree:: + :maxdepth: 1 + + macos-setup-scratch + +.. _cmake: https://cmake.org/ +.. _ninja: https://ninja-build.org/ +.. _ccache: https://ccache.samba.org/ +.. _homebrew: https://brew.sh/ +.. _MacPorts: https://www.macports.org/install.php diff --git a/docs/en/get-started-cmake/toolchain-setup-scratch.rst b/docs/en/get-started-cmake/toolchain-setup-scratch.rst new file mode 100644 index 000000000..b5e9f0fbd --- /dev/null +++ b/docs/en/get-started-cmake/toolchain-setup-scratch.rst @@ -0,0 +1,25 @@ +.. _get-started-customized-setup-cmake: + +************************************* +Customized Setup of Toolchain (CMake) +************************************* + +Instead of downloading binary toolchain from Espressif website (see :ref:`get-started-setup-toolchain-cmake`) you may build the toolchain yourself. + +If you can't think of a reason why you need to build it yourself, then probably it's better to stick with the binary version. However, here are some of the reasons why you might want to compile it from source: + +- if you want to customize toolchain build configuration +- if you want to use a different GCC version (such as 4.8.5) +- if you want to hack gcc or newlib or libstdc++ +- if you are curious and/or have time to spare +- if you don't trust binaries downloaded from the Internet + +In any case, here are the instructions to compile the toolchain yourself. + +.. toctree:: + :maxdepth: 1 + + windows-setup-scratch + linux-setup-scratch + macos-setup-scratch + diff --git a/docs/en/get-started-cmake/windows-setup-scratch.rst b/docs/en/get-started-cmake/windows-setup-scratch.rst new file mode 100644 index 000000000..d8381ae68 --- /dev/null +++ b/docs/en/get-started-cmake/windows-setup-scratch.rst @@ -0,0 +1,89 @@ +******************************************** +Setup Windows Toolchain from Scratch (CMake) +******************************************** + +.. include:: ../cmake-warning.rst + +This is a step-by-step alternative to running the :doc:`ESP-IDF Tools Installer ` for the CMake-based build system. Installing all of the tools by hand allows more control over the process, and also provides the information for advanced users to customize the install. + +To quickly setup the toolchain and other tools in standard way, using the ESP-IDF Tools installer, proceed to section :doc:`windows-setup`. + + +.. note:: + The GNU Make based build system requires the MSYS2_ Unix compatibility environment on Windows. The CMake-based build system does not require this environment. + +Tools +===== + +cmake +^^^^^ + +Download the latest stable release of CMake_ for Windows and run the installer. + +When the installer asks for Install Options, choose either "Add CMake to the system PATH for all users" or "Add CMake to the system PATH for the current user". + +Ninja build +^^^^^^^^^^^ + +.. note:: + Ninja currently only provides binaries for 64-bit Windows. It is possible to use CMake and ``idf.py`` with other build tools, such as mingw-make, on 32-bit windows. However this is currently undocumented. + +Download the ninja_ latest stable Windows release from the (`download page `_). + +The Ninja for Windows download is a .zip file containing a single ``ninja.exe`` file which needs to be unzipped to a directory which is then `added to your Path `_ (or you can choose a directory which is already on your Path). + + +Python 2.x +^^^^^^^^^^ + +Download the latest Python_ 2.7 for Windows installer, and run it. + +The "Customise" step of the Python installer gives a list of options. The last option is "Add python.exe to Path". Change this option to select "Will be installed". + +Once Python is installed, open a Windows Command Prompt from the Start menu and run the following command:: + + pip install pyserial + +MConf for IDF +^^^^^^^^^^^^^ + +Download the configuration tool mconf-idf from the `kconfig-frontends releases page `_. This is the ``mconf`` configuration tool with some minor customizations for ESP-IDF. + +This tool will also need to be unzipped to a directory which is then `added to your Path `_. + +Toolchain Setup +=============== + +Download the precompiled Windows toolchain from dl.espressif.com: + +https://dl.espressif.com/dl/xtensa-esp32-elf-win32-1.22.0-80-g6c4433a-5.2.0.zip + +Unzip the zip file to ``C:\Program Files`` (or some other location). The zip file contains a single directory ``xtensa-esp32-elf``. + +Next, the ``bin`` subdirectory of this directory must be `added to your Path `_. For example, the directory to add may be ``C:\Program Files\xtensa-esp32-elf\bin``. + +.. note:: + If you already have the MSYS2 environment (for use with the "GNU Make" build system) installed, you can skip the separate download and add the directory ``C:\msys32\opt\xtensa-esp32-elf\bin`` to the Path instead, as the toolchain is included in the MSYS2 environment. + + +.. _add-directory-windows-path-cmake: + +Adding Directory to Path +======================== + +To add any new directory to your Windows Path environment variable: + +Open the System control panel and navigate to the Environment Variables dialog. (On Windows 10, this is found under Advanced System Settings). + +Double-click the ``Path`` variable (either User or System Path, depending if you want other users to have this directory on their path.) Go to the end of the value, and append ``;``. + + +Next Steps +========== + +To carry on with development environment setup, proceed to section :ref:`get-started-get-esp-idf-cmake`. + +.. _ninja: https://ninja-build.org/ +.. _Python: https://www.python.org/downloads/windows/ +.. _MSYS2: https://msys2.github.io/ + diff --git a/docs/en/get-started-cmake/windows-setup.rst b/docs/en/get-started-cmake/windows-setup.rst new file mode 100644 index 000000000..c7393c8b9 --- /dev/null +++ b/docs/en/get-started-cmake/windows-setup.rst @@ -0,0 +1,71 @@ +*********************************************** +Standard Setup of Toolchain for Windows (CMake) +*********************************************** + +.. include:: ../cmake-warning.rst + +.. note:: + The CMake-based build system is only supported on 64-bit versions of Windows. + +Introduction +============ + +ESP-IDF requires some prerequisite tools to be installed so you can build firmware for the ESP32. The prerequisite tools include Git, a cross-compiler and the CMake build tool. We'll go over each one in this document. + +For this Getting Started we're going to use a command prompt, but after ESP-IDF is installed you can use :doc:`Eclipse ` or another graphical IDE with CMake support instead. + +.. note:: + The GNU Make based build system requires the MSYS2_ Unix compatibility environment on Windows. The CMake-based build system does not require this environment. + +ESP-IDF Tools Installer +======================= + +The easiest way to install ESP-IDF's prerequisites is to download the ESP-IDF Tools installer from this URL: + +https://dl.espressif.com/dl/esp-idf-tools-setup-1.1.exe + +The installer will automatically install the ESP32 Xtensa gcc toolchain, Ninja_ build tool, and a configuration tool called mconf-idf_. The installer can also download and run installers for CMake_ and Python_ 2.7 if these are not already installed on the computer. + +By default, the installer updates the Windows ``Path`` environment variable so all of these tools can be run from anywhere. If you disable this option, you will need to configure the environment where you are using ESP-IDF (terminal or chosen IDE) with the correct paths. + +Note that this installer is for the ESP-IDF Tools package, it doesn't include ESP-IDF itself. + +Installing Git +============== + +The ESP-IDF tools installer does not install Git. By default, the getting started guide assumes you will be using Git on the command line. You can download and install a command line Git for Windows (along with the "Git Bash" terminal) from `Git For Windows`_. + +If you prefer to use a different graphical Git client, then you can install one such as `Github Desktop`. You will need to translate the Git commands in the Getting Started guide for use with your chosen Git client. + +Using a Terminal +================ + +For the remaining Getting Started steps, we're going to use a terminal command prompt. It doesn't matter which command prompt you use: + +- You can use the built-in Windows Command Prompt, under the Start menu. All Windows command line instructions in this documentation are "batch" commands for use with the Windows Command Prompt. +- You can use the "Git Bash" terminal which is part of `Git for Windows`_. This uses the same "bash" command prompt syntax as is given for Mac OS or Linux. You can find it in the Start menu once installed. +- If you have MSYS2_ installed (maybe from a previous ESP-IDF version), then you can also use the MSYS terminal. + +Next Steps +========== + +To carry on with development environment setup, proceed to section :ref:`get-started-get-esp-idf-cmake`. + +Related Documents +================= + +For advanced users who want to customize the install process: + +.. toctree:: + :maxdepth: 1 + + windows-setup-scratch + + +.. _MSYS2: https://msys2.github.io/ +.. _cmake: https://cmake.org/download/ +.. _ninja: https://ninja-build.org/ +.. _Python: https://www.python.org/downloads/windows/ +.. _Git for Windows: https://gitforwindows.org/ +.. _mconf-idf: https://github.com/espressif/kconfig-frontends/releases/ +.. _Github Desktop: https://desktop.github.com/ diff --git a/docs/en/get-started/eclipse-setup-windows.rst b/docs/en/get-started/eclipse-setup-windows.rst index 8cefffcb3..9c6f89564 100644 --- a/docs/en/get-started/eclipse-setup-windows.rst +++ b/docs/en/get-started/eclipse-setup-windows.rst @@ -49,7 +49,7 @@ Project Properties * Click "Add..." and enter name ``BATCH_BUILD`` and value ``1``. - * Click "Add..." again, and enter name ``IDF_PATH``. The value should be the full path where ESP-IDF is installed. The IDF_PATH directory should be specified using forwards slashes not backslashes, ie *C:/Users/MyUser/Development/esp-idf*. + * Click "Add..." again, and enter name ``IDF_PATH``. The value should be the full path where ESP-IDF is installed. The IDF_PATH directory should be specified using forwards slashes not backslashes, ie *C:/Users/user-name/Development/esp-idf*. * Edit the PATH environment variable. Delete the existing value and replace it with ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin`` (If you installed msys32 to a different directory then you'll need to change these paths to match). diff --git a/docs/en/get-started/linux-setup.rst b/docs/en/get-started/linux-setup.rst index bc4102a85..bdc4467ce 100644 --- a/docs/en/get-started/linux-setup.rst +++ b/docs/en/get-started/linux-setup.rst @@ -3,7 +3,6 @@ Standard Setup of Toolchain for Linux ************************************* :link_to_translation:`zh_CN:[中文]` - Install Prerequisites ===================== diff --git a/docs/en/index.rst b/docs/en/index.rst index d7295b4fa..c1dbe708b 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -40,6 +40,7 @@ The documentation has different language versions (:link_to_translation:`en:Engl :hidden: Get Started + Get Started (CMake Preview) API Reference H/W Reference API Guides diff --git a/docs/gen-kconfig-doc.py b/docs/gen-kconfig-doc.py deleted file mode 100755 index ec4b2bb6f..000000000 --- a/docs/gen-kconfig-doc.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# gen-kconfig-doc.py — generate Sphinx .rst file from Kconfig files -# -# This script iterates over Kconfig and Kconfig.projbuild files in -# ESP-IDF component directories, and outputs documentation for these options -# as ReST markup. -# For each option in Kconfig file (e.g. 'FOO'), CONFIG_FOO link target is -# generated, allowing options to be referenced in other documents -# (using :envvar:`CONFIG_FOO`) -# -# This script uses kconfiglib library to do all the work of parsing Kconfig -# files: https://github.com/ulfalizer/Kconfiglib -# -# Copyright 2017 Espressif Systems (Shanghai) PTE LTD -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http:#www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import os -import kconfiglib - -# Indentation to be used in the generated file -INDENT = ' ' - -# Characters used when underlining section heading -HEADING_SYMBOLS = '#*=-^"+' - -# Keep the heading level in sync with api-reference/kconfig.rst -INITIAL_HEADING_LEVEL = 2 -MAX_HEADING_LEVEL = 5 -OPTION_HEADING_LEVEL = 6 - -def print_menu_contents(title, items, heading_level, breadcrumbs, genindex): - if not genindex: - if title: - print_section_heading(title, heading_level) - if heading_level == INITIAL_HEADING_LEVEL+1: - print_menu_contents(title, items, heading_level, breadcrumbs, True) - for entry in items: - if entry.is_menu(): - if len(breadcrumbs) > 0: - new_breadcrumbs = breadcrumbs + ' > ' + entry.get_title() - else: - new_breadcrumbs = entry.get_title() - - print_menu_contents(entry.get_title(), entry.get_items(), - min(heading_level + 1, MAX_HEADING_LEVEL), - new_breadcrumbs, genindex) - elif genindex: - print_item(entry, breadcrumbs) - elif entry.is_choice(): - print_choice(entry, breadcrumbs) - else: - if len(entry.get_prompts()) == 0: - # Skip entries which can never be visible - continue - # Currently this does not handle 'menuconfig' entires in any special way, - # as Kconfglib offers no way of recognizing them automatically. - print_option(entry, breadcrumbs) - # Trailing newline after every option - print - -def print_choice(choice, breadcrumbs): - print_option(choice, breadcrumbs) - print - print '%sAvailable options' % INDENT - for opt in choice.get_symbols(): - # Format available options as a list - print '%s- %s' % (INDENT * 2, opt.name) - -def print_section_heading(title, heading_level): - print title - print HEADING_SYMBOLS[heading_level] * len(title) - print - -def print_option(opt, breadcrumbs): - # add link target so we can use :envvar:`CONFIG_FOO` - print '.. envvar:: CONFIG_%s' % opt.name - print - if len(opt.prompts) > 0: - print '%s%s' % (INDENT, opt.prompts[0][0]) - print - if opt.get_help() is not None: - # Help text normally contains newlines, but spaces at the beginning of - # each line are stripped by kconfiglib. We need to re-indent the text - # to produce valid ReST. - print '%s%s' % (INDENT, opt.get_help().replace('\n', '\n%s' % INDENT)) - print '%sFound in\n%s' % (INDENT, INDENT * 2 + breadcrumbs) - print - -def print_item(opt, breadcrumbs): - print '- :envvar:`CONFIG_%s`' % opt.name - print - -def process_kconfig_file(kconfig_file, heading_level, breadcrumbs): - if os.path.exists(kconfig_file): - cfg = kconfiglib.Config(kconfig_file, print_warnings=True) - print_menu_contents(None, cfg.get_top_level_items(), heading_level, breadcrumbs, False) - -def print_all_components(): - heading_level = INITIAL_HEADING_LEVEL - # Currently this works only for IDF components. - # TODO: figure out if this can be re-used for documenting applications? - components_path = os.path.join(os.path.curdir, '../..', 'components') - for component_name in os.listdir(components_path): - if component_name.startswith('.'): - continue # skip system thumbnail folders - - kconfig_file_path = os.path.join(components_path, component_name, 'Kconfig') - - process_kconfig_file(kconfig_file_path, heading_level, 'Component config') - process_kconfig_file(kconfig_file_path + '.projbuild', heading_level, '') - - kconfig_file_path = os.path.join(os.path.curdir, '../..', 'Kconfig.compiler') - process_kconfig_file(kconfig_file_path, heading_level, '') - -if __name__ == '__main__': - print_all_components() diff --git a/docs/zh_CN/api-guides/build-system-cmake.rst b/docs/zh_CN/api-guides/build-system-cmake.rst new file mode 100644 index 000000000..d70290e6e --- /dev/null +++ b/docs/zh_CN/api-guides/build-system-cmake.rst @@ -0,0 +1 @@ +.. include:: ../../en/api-guides/build-system-cmake.rst diff --git a/docs/zh_CN/api-guides/index.rst b/docs/zh_CN/api-guides/index.rst index acfcca62e..0a0f9c8e9 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -6,6 +6,7 @@ API Guides General Notes Build System + Build System (CMake) Error Handling Fatal Errors Deep Sleep Wake Stubs @@ -26,4 +27,4 @@ API Guides WiFi Driver Mesh Stack BluFi - External SPI-connected RAM \ No newline at end of file + External SPI-connected RAM diff --git a/docs/zh_CN/cmake-pending-features.rst b/docs/zh_CN/cmake-pending-features.rst new file mode 100644 index 000000000..6a45fbef9 --- /dev/null +++ b/docs/zh_CN/cmake-pending-features.rst @@ -0,0 +1 @@ +.. include:: /../en/cmake-pending-features.rst diff --git a/docs/zh_CN/cmake-warning.rst b/docs/zh_CN/cmake-warning.rst new file mode 100644 index 000000000..09479207f --- /dev/null +++ b/docs/zh_CN/cmake-warning.rst @@ -0,0 +1 @@ +.. include:: /../en/cmake-warning.rst diff --git a/docs/zh_CN/get-started-cmake/add-idf_path-to-profile.rst b/docs/zh_CN/get-started-cmake/add-idf_path-to-profile.rst new file mode 100644 index 000000000..2aacd4a4e --- /dev/null +++ b/docs/zh_CN/get-started-cmake/add-idf_path-to-profile.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/add-idf_path-to-profile.rst diff --git a/docs/zh_CN/get-started-cmake/eclipse-setup.rst b/docs/zh_CN/get-started-cmake/eclipse-setup.rst new file mode 100644 index 000000000..b7fd85471 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/eclipse-setup.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/eclipse-setup.rst diff --git a/docs/zh_CN/get-started-cmake/establish-serial-connection.rst b/docs/zh_CN/get-started-cmake/establish-serial-connection.rst new file mode 100644 index 000000000..29f14b710 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/establish-serial-connection.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/establish-serial-connection.rst diff --git a/docs/zh_CN/get-started-cmake/get-started-devkitc-v2.rst b/docs/zh_CN/get-started-cmake/get-started-devkitc-v2.rst new file mode 100644 index 000000000..155d0a53c --- /dev/null +++ b/docs/zh_CN/get-started-cmake/get-started-devkitc-v2.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/get-started-devkitc-v2.rst diff --git a/docs/zh_CN/get-started-cmake/get-started-devkitc.rst b/docs/zh_CN/get-started-cmake/get-started-devkitc.rst new file mode 100644 index 000000000..922a1445b --- /dev/null +++ b/docs/zh_CN/get-started-cmake/get-started-devkitc.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/get-started-devkitc.rst diff --git a/docs/zh_CN/get-started-cmake/get-started-pico-kit-v3.rst b/docs/zh_CN/get-started-cmake/get-started-pico-kit-v3.rst new file mode 100644 index 000000000..5cb327a30 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/get-started-pico-kit-v3.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/get-started-pico-kit-v3.rst diff --git a/docs/zh_CN/get-started-cmake/get-started-pico-kit.rst b/docs/zh_CN/get-started-cmake/get-started-pico-kit.rst new file mode 100644 index 000000000..d409f1d16 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/get-started-pico-kit.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/get-started-pico-kit.rst diff --git a/docs/zh_CN/get-started-cmake/get-started-wrover-kit-v2.rst b/docs/zh_CN/get-started-cmake/get-started-wrover-kit-v2.rst new file mode 100644 index 000000000..a742059bd --- /dev/null +++ b/docs/zh_CN/get-started-cmake/get-started-wrover-kit-v2.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/get-started-wrover-kit-v2.rst diff --git a/docs/zh_CN/get-started-cmake/get-started-wrover-kit.rst b/docs/zh_CN/get-started-cmake/get-started-wrover-kit.rst new file mode 100644 index 000000000..23227d7d5 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/get-started-wrover-kit.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/get-started-wrover-kit.rst diff --git a/docs/zh_CN/get-started-cmake/idf-monitor.rst b/docs/zh_CN/get-started-cmake/idf-monitor.rst new file mode 100644 index 000000000..05b457188 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/idf-monitor.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/idf-monitor.rst diff --git a/docs/zh_CN/get-started-cmake/index.rst b/docs/zh_CN/get-started-cmake/index.rst new file mode 100644 index 000000000..5c49b60a4 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/index.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/index.rst diff --git a/docs/zh_CN/get-started-cmake/linux-setup-scratch.rst b/docs/zh_CN/get-started-cmake/linux-setup-scratch.rst new file mode 100644 index 000000000..1bc3dfab7 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/linux-setup-scratch.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/linux-setup-scratch.rst diff --git a/docs/zh_CN/get-started-cmake/linux-setup.rst b/docs/zh_CN/get-started-cmake/linux-setup.rst new file mode 100644 index 000000000..048417a90 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/linux-setup.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/linux-setup.rst diff --git a/docs/zh_CN/get-started-cmake/macos-setup-scratch.rst b/docs/zh_CN/get-started-cmake/macos-setup-scratch.rst new file mode 100644 index 000000000..82b866534 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/macos-setup-scratch.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/macos-setup-scratch.rst diff --git a/docs/zh_CN/get-started-cmake/macos-setup.rst b/docs/zh_CN/get-started-cmake/macos-setup.rst new file mode 100644 index 000000000..e1bf5a2f6 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/macos-setup.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/macos-setup.rst diff --git a/docs/zh_CN/get-started-cmake/toolchain-setup-scratch.rst b/docs/zh_CN/get-started-cmake/toolchain-setup-scratch.rst new file mode 100644 index 000000000..2bad626c9 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/toolchain-setup-scratch.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/toolchain-setup-scratch.rst diff --git a/docs/zh_CN/get-started-cmake/windows-setup-scratch.rst b/docs/zh_CN/get-started-cmake/windows-setup-scratch.rst new file mode 100644 index 000000000..6ec60d320 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/windows-setup-scratch.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/windows-setup-scratch.rst diff --git a/docs/zh_CN/get-started-cmake/windows-setup.rst b/docs/zh_CN/get-started-cmake/windows-setup.rst new file mode 100644 index 000000000..b03ce8af0 --- /dev/null +++ b/docs/zh_CN/get-started-cmake/windows-setup.rst @@ -0,0 +1 @@ +.. include:: ../../en/get-started-cmake/windows-setup.rst diff --git a/docs/zh_CN/get-started/eclipse-setup-windows.rst b/docs/zh_CN/get-started/eclipse-setup-windows.rst index 6b9de3696..c8497dc64 100644 --- a/docs/zh_CN/get-started/eclipse-setup-windows.rst +++ b/docs/zh_CN/get-started/eclipse-setup-windows.rst @@ -50,7 +50,7 @@ Windows 平台上的 Eclipse 配置 * 选择 “Add...”,并在对应位置输入 ``BATCH_BUILD`` 和 ``1``。 - * 再次点击 “Add...”,输入名称 ``IDF_PATH``,并填写 ESP-IDF 的完整安装路径。``IDF_PATH`` 目录路径应使用正斜杠,而非反斜线,例如 ``C:/Users/MyUser/Development/esp-idf``。 + * 再次点击 “Add...”,输入名称 ``IDF_PATH``,并填写 ESP-IDF 的完整安装路径。``IDF_PATH`` 目录路径应使用正斜杠,而非反斜线,例如 ``C:/Users/user-name/Development/esp-idf``。 * 选择 PATH 环境变量,删除默认值,并将其替换为 ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin`` (如果您已经将 msys32 安装到其他目​​录,这里请自行调整)。 diff --git a/docs/zh_CN/get-started/index.rst b/docs/zh_CN/get-started/index.rst index 6e38dbdfc..043569da5 100644 --- a/docs/zh_CN/get-started/index.rst +++ b/docs/zh_CN/get-started/index.rst @@ -3,6 +3,8 @@ *********** :link_to_translation:`en:[English]` +.. important:: 对不起,CMake-based Build System Preview 还没有中文翻译。 + 本文档旨在指导用户创建 ESP32 的软件环境。本文将通过一个简单的例子来说明如何使用 ESP-IDF (Espressif IoT Development Framework),包括配置、编译、下载固件到开发板等步骤。 .. include:: /_build/inc/version-note.inc diff --git a/docs/zh_CN/get-started/linux-setup.rst b/docs/zh_CN/get-started/linux-setup.rst index 8c5c0cf6b..7c7c20227 100644 --- a/docs/zh_CN/get-started/linux-setup.rst +++ b/docs/zh_CN/get-started/linux-setup.rst @@ -3,6 +3,8 @@ Linux 平台工具链的标准设置 ***************************** :link_to_translation:`en:[English]` +.. important:: 对不起,CMake-based Build System Preview 还没有中文翻译。 + 安装前提 ===================== diff --git a/docs/zh_CN/get-started/macos-setup.rst b/docs/zh_CN/get-started/macos-setup.rst index 18c325303..5b6951e87 100644 --- a/docs/zh_CN/get-started/macos-setup.rst +++ b/docs/zh_CN/get-started/macos-setup.rst @@ -3,6 +3,8 @@ ************************************** :link_to_translation:`en:[English]` +.. important:: 对不起,CMake-based Build System Preview 还没有中文翻译。 + 安装准备 ================ diff --git a/docs/zh_CN/get-started/windows-setup.rst b/docs/zh_CN/get-started/windows-setup.rst index 8482b5d9c..25edb9d15 100644 --- a/docs/zh_CN/get-started/windows-setup.rst +++ b/docs/zh_CN/get-started/windows-setup.rst @@ -3,6 +3,8 @@ Windows 平台工具链的标准设置 *************************************** :link_to_translation:`en:[English]` +.. important:: 对不起,CMake-based Build System Preview 还没有中文翻译。 + 引言 ============ @@ -54,8 +56,6 @@ https://dl.espressif.com/dl/esp32_win32_msys2_environment_and_toolchain-20180110 你可以在系统上拥有独立的不同的 MSYS2 环境,前提是在不同的目录中。 -或者,:ref:`你也可以更新现有的环境而不是下载新环境 `,但是这样更复杂。 - 相关文档 ================= diff --git a/docs/zh_CN/index.rst b/docs/zh_CN/index.rst index 4b8afb435..2b8a7b374 100644 --- a/docs/zh_CN/index.rst +++ b/docs/zh_CN/index.rst @@ -40,6 +40,7 @@ ESP-IDF 编程指南 :hidden: 快速入门 + 快速入门 (CMake 预览版本) API 参考 H/W 参考 API 指南 diff --git a/examples/bluetooth/a2dp_gatts_coex/CMakeLists.txt b/examples/bluetooth/a2dp_gatts_coex/CMakeLists.txt new file mode 100644 index 000000000..3243515f3 --- /dev/null +++ b/examples/bluetooth/a2dp_gatts_coex/CMakeLists.txt @@ -0,0 +1,12 @@ +# 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) + +set(MAIN_SRCS + main/bt_app_av.c + main/bt_app_core.c + main/main.c + ) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(bt_ble_coex) diff --git a/examples/bluetooth/a2dp_gatts_coex/sdkconfig.defaults b/examples/bluetooth/a2dp_gatts_coex/sdkconfig.defaults index 07275e1e7..8c4616123 100644 --- a/examples/bluetooth/a2dp_gatts_coex/sdkconfig.defaults +++ b/examples/bluetooth/a2dp_gatts_coex/sdkconfig.defaults @@ -2,29 +2,29 @@ # Classic BT is enabled and BT_DRAM_RELEASE is disabled CONFIG_BT_ENABLED=y CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y -CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1= +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1=n CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y -CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= +CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4=n CONFIG_BLUEDROID_ENABLED=y CONFIG_BLUEDROID_PINNED_TO_CORE_0=y -CONFIG_BLUEDROID_PINNED_TO_CORE_1= +CONFIG_BLUEDROID_PINNED_TO_CORE_1=n CONFIG_BLUEDROID_PINNED_TO_CORE=0 CONFIG_BTC_TASK_STACK_SIZE=3072 -CONFIG_BLUEDROID_MEM_DEBUG= +CONFIG_BLUEDROID_MEM_DEBUG=n CONFIG_CLASSIC_BT_ENABLED=y CONFIG_A2DP_ENABLE=y CONFIG_A2DP_SINK_ENABLE=y -CONFIG_A2DP_SRC_ENABLE= +CONFIG_A2DP_SRC_ENABLE=n CONFIG_A2DP_SINK_TASK_STACK_SIZE=2048 -CONFIG_BT_SPP_ENABLED= +CONFIG_BT_SPP_ENABLED=n CONFIG_GATTS_ENABLE=y -CONFIG_GATTC_ENABLE= -CONFIG_BLE_SMP_ENABLE= +CONFIG_GATTC_ENABLE=n +CONFIG_BLE_SMP_ENABLE=n CONFIG_BLE_ENABLE_SRVCHG_REG=y -CONFIG_BT_STACK_NO_LOG= +CONFIG_BT_STACK_NO_LOG=n CONFIG_BT_ACL_CONNECTIONS=4 -CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST= -CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY= +CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=n +CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=n CONFIG_SMP_ENABLE=y CONFIG_BT_RESERVE_DRAM=0x10000 diff --git a/examples/bluetooth/a2dp_sink/CMakeLists.txt b/examples/bluetooth/a2dp_sink/CMakeLists.txt new file mode 100644 index 000000000..4d14857a0 --- /dev/null +++ b/examples/bluetooth/a2dp_sink/CMakeLists.txt @@ -0,0 +1,12 @@ +# 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) + +set(MAIN_SRCS + main/bt_app_av.c + main/bt_app_core.c + main/main.c + ) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(a2dp_sink) diff --git a/examples/bluetooth/a2dp_sink/sdkconfig.defaults b/examples/bluetooth/a2dp_sink/sdkconfig.defaults index 82779f66e..9769836c2 100644 --- a/examples/bluetooth/a2dp_sink/sdkconfig.defaults +++ b/examples/bluetooth/a2dp_sink/sdkconfig.defaults @@ -4,7 +4,7 @@ CONFIG_BT_ENABLED=y CONFIG_BLUEDROID_ENABLED=y CONFIG_CLASSIC_BT_ENABLED=y CONFIG_A2DP_ENABLE=y -CONFIG_BT_SPP_ENABLED= -CONFIG_GATTS_ENABLE= -CONFIG_GATTC_ENABLE= -CONFIG_BLE_SMP_ENABLE= +CONFIG_BT_SPP_ENABLED=n +CONFIG_GATTS_ENABLE=n +CONFIG_GATTC_ENABLE=n +CONFIG_BLE_SMP_ENABLE=n diff --git a/examples/bluetooth/a2dp_source/CMakeLists.txt b/examples/bluetooth/a2dp_source/CMakeLists.txt new file mode 100644 index 000000000..1b4c44799 --- /dev/null +++ b/examples/bluetooth/a2dp_source/CMakeLists.txt @@ -0,0 +1,11 @@ +# 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) + +set(MAIN_SRCS + main/bt_app_core.c + main/main.c + ) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(a2dp_source) diff --git a/examples/bluetooth/a2dp_source/sdkconfig.defaults b/examples/bluetooth/a2dp_source/sdkconfig.defaults index 6625f76f4..38b09494b 100644 --- a/examples/bluetooth/a2dp_source/sdkconfig.defaults +++ b/examples/bluetooth/a2dp_source/sdkconfig.defaults @@ -4,7 +4,7 @@ CONFIG_BT_ENABLED=y CONFIG_BLUEDROID_ENABLED=y CONFIG_CLASSIC_BT_ENABLED=y CONFIG_A2DP_ENABLE=y -CONFIG_BT_SPP_ENABLED= -CONFIG_GATTS_ENABLE= -CONFIG_GATTC_ENABLE= -CONFIG_BLE_SMP_ENABLE= +CONFIG_BT_SPP_ENABLED=n +CONFIG_GATTS_ENABLE=n +CONFIG_GATTC_ENABLE=n +CONFIG_BLE_SMP_ENABLE=n diff --git a/examples/bluetooth/ble_adv/CMakeLists.txt b/examples/bluetooth/ble_adv/CMakeLists.txt new file mode 100644 index 000000000..04715a858 --- /dev/null +++ b/examples/bluetooth/ble_adv/CMakeLists.txt @@ -0,0 +1,10 @@ +# 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) + +set(MAIN_SRCS + main/app_bt.c + ) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ble_adv) diff --git a/examples/bluetooth/ble_eddystone/CMakeLists.txt b/examples/bluetooth/ble_eddystone/CMakeLists.txt new file mode 100644 index 000000000..05d77c7c6 --- /dev/null +++ b/examples/bluetooth/ble_eddystone/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/esp_eddystone_api.c main/esp_eddystone_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ble_eddystone_demo) diff --git a/examples/bluetooth/ble_hid_device_demo/CMakeLists.txt b/examples/bluetooth/ble_hid_device_demo/CMakeLists.txt new file mode 100644 index 000000000..9cacc3489 --- /dev/null +++ b/examples/bluetooth/ble_hid_device_demo/CMakeLists.txt @@ -0,0 +1,11 @@ +# The following four 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) + +set(MAIN_SRCS main/ble_hidd_demo_main.c + main/hid_dev.c + main/hid_device_le_prf.c + main/esp_hidd_prf_api.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(hidd_demos) diff --git a/examples/bluetooth/ble_ibeacon/CMakeLists.txt b/examples/bluetooth/ble_ibeacon/CMakeLists.txt new file mode 100644 index 000000000..5eb1d7363 --- /dev/null +++ b/examples/bluetooth/ble_ibeacon/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/ibeacon_demo.c main/esp_ibeacon_api.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ble_ibeacon_demo) diff --git a/examples/bluetooth/ble_spp_client/CMakeLists.txt b/examples/bluetooth/ble_spp_client/CMakeLists.txt new file mode 100644 index 000000000..93abbbfb3 --- /dev/null +++ b/examples/bluetooth/ble_spp_client/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/spp_client_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(spp_client_demo) diff --git a/examples/bluetooth/ble_spp_server/CMakeLists.txt b/examples/bluetooth/ble_spp_server/CMakeLists.txt new file mode 100644 index 000000000..c0508f801 --- /dev/null +++ b/examples/bluetooth/ble_spp_server/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/ble_spp_server_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ble_spp_server_demo) diff --git a/examples/bluetooth/ble_throughput/throughput_client/CMakeLists.txt b/examples/bluetooth/ble_throughput/throughput_client/CMakeLists.txt new file mode 100644 index 000000000..c557a916e --- /dev/null +++ b/examples/bluetooth/ble_throughput/throughput_client/CMakeLists.txt @@ -0,0 +1,10 @@ +# 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) + +set(MAIN_SRCS + main/example_ble_client_throughput.c + ) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(throughput_client_demo) diff --git a/examples/bluetooth/ble_throughput/throughput_server/CMakeLists.txt b/examples/bluetooth/ble_throughput/throughput_server/CMakeLists.txt new file mode 100644 index 000000000..8d3bd0cbb --- /dev/null +++ b/examples/bluetooth/ble_throughput/throughput_server/CMakeLists.txt @@ -0,0 +1,10 @@ +# 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) + +set(MAIN_SRCS + main/example_ble_server_throughput.c + ) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(throughput_server_demo) diff --git a/examples/bluetooth/blufi/CMakeLists.txt b/examples/bluetooth/blufi/CMakeLists.txt new file mode 100644 index 000000000..e016e161a --- /dev/null +++ b/examples/bluetooth/blufi/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/blufi_security.c main/blufi_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(blufi_demo) diff --git a/examples/bluetooth/blufi/sdkconfig.defaults b/examples/bluetooth/blufi/sdkconfig.defaults index a0d1d3652..2d73b0662 100644 --- a/examples/bluetooth/blufi/sdkconfig.defaults +++ b/examples/bluetooth/blufi/sdkconfig.defaults @@ -6,24 +6,24 @@ # CONFIG_BT_ENABLED=y CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y -CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1= +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1=n CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y -CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4= +CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4=n CONFIG_BLUEDROID_ENABLED=y CONFIG_BLUEDROID_PINNED_TO_CORE_0=y -CONFIG_BLUEDROID_PINNED_TO_CORE_1= +CONFIG_BLUEDROID_PINNED_TO_CORE_1=n CONFIG_BLUEDROID_PINNED_TO_CORE=0 CONFIG_BTC_TASK_STACK_SIZE=3072 -CONFIG_BLUEDROID_MEM_DEBUG= -CONFIG_CLASSIC_BT_ENABLED= +CONFIG_BLUEDROID_MEM_DEBUG=n +CONFIG_CLASSIC_BT_ENABLED=n CONFIG_GATTS_ENABLE=y -CONFIG_GATTC_ENABLE= -CONFIG_BLE_SMP_ENABLE= +CONFIG_GATTC_ENABLE=n +CONFIG_BLE_SMP_ENABLE=n CONFIG_BLE_ENABLE_SRVCHG_REG=y -CONFIG_BT_STACK_NO_LOG= +CONFIG_BT_STACK_NO_LOG=n CONFIG_BT_ACL_CONNECTIONS=4 -CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST= -CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY= -CONFIG_SMP_ENABLE= +CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST=n +CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY=n +CONFIG_SMP_ENABLE=n CONFIG_BT_RESERVE_DRAM=0x10000 diff --git a/examples/bluetooth/bt_discovery/CMakeLists.txt b/examples/bluetooth/bt_discovery/CMakeLists.txt new file mode 100644 index 000000000..b79d221bd --- /dev/null +++ b/examples/bluetooth/bt_discovery/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/bt_discovery.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(bt_discovery) diff --git a/examples/bluetooth/bt_discovery/sdkconfig.defaults b/examples/bluetooth/bt_discovery/sdkconfig.defaults index ab028190f..793fe05c2 100644 --- a/examples/bluetooth/bt_discovery/sdkconfig.defaults +++ b/examples/bluetooth/bt_discovery/sdkconfig.defaults @@ -2,7 +2,7 @@ # Classic BT is enabled and BT_DRAM_RELEASE is disabled CONFIG_BT_ENABLED=y CONFIG_CLASSIC_BT_ENABLED=y -CONFIG_A2DP_ENABLE= -CONFIG_GATTS_ENABLE= -CONFIG_GATTC_ENABLE= -CONFIG_BLE_SMP_ENABLE= +CONFIG_A2DP_ENABLE=n +CONFIG_GATTS_ENABLE=n +CONFIG_GATTC_ENABLE=n +CONFIG_BLE_SMP_ENABLE=n diff --git a/examples/bluetooth/bt_spp_acceptor/CMakeLists.txt b/examples/bluetooth/bt_spp_acceptor/CMakeLists.txt new file mode 100644 index 000000000..5ed97b387 --- /dev/null +++ b/examples/bluetooth/bt_spp_acceptor/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/example_spp_acceptor_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(bt_spp_acceptor_demo) diff --git a/examples/bluetooth/bt_spp_initiator/CMakeLists.txt b/examples/bluetooth/bt_spp_initiator/CMakeLists.txt new file mode 100644 index 000000000..fc8eb551b --- /dev/null +++ b/examples/bluetooth/bt_spp_initiator/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/example_spp_initiator_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(bt_spp_initiator_demo) diff --git a/examples/bluetooth/bt_spp_vfs_acceptor/CMakeLists.txt b/examples/bluetooth/bt_spp_vfs_acceptor/CMakeLists.txt new file mode 100644 index 000000000..b37ab5f68 --- /dev/null +++ b/examples/bluetooth/bt_spp_vfs_acceptor/CMakeLists.txt @@ -0,0 +1,10 @@ +# The following four 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) + +set(MAIN_SRCS + main/example_spp_vfs_acceptor_demo.c + main/spp_task.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(bt_spp_vfs_acceptor_demo) diff --git a/examples/bluetooth/bt_spp_vfs_initiator/CMakeLists.txt b/examples/bluetooth/bt_spp_vfs_initiator/CMakeLists.txt new file mode 100644 index 000000000..94c7b230d --- /dev/null +++ b/examples/bluetooth/bt_spp_vfs_initiator/CMakeLists.txt @@ -0,0 +1,10 @@ +# The following four 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) + +set(MAIN_SRCS + main/example_spp_vfs_initiator_demo.c + main/spp_task.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(bt_spp_vfs_initiator_demo) diff --git a/examples/bluetooth/controller_hci_uart/CMakeLists.txt b/examples/bluetooth/controller_hci_uart/CMakeLists.txt new file mode 100644 index 000000000..0c7fcbdd9 --- /dev/null +++ b/examples/bluetooth/controller_hci_uart/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/controller_hci_uart_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(controller_hci_uart) diff --git a/examples/bluetooth/gatt_client/CMakeLists.txt b/examples/bluetooth/gatt_client/CMakeLists.txt new file mode 100644 index 000000000..5e41444ab --- /dev/null +++ b/examples/bluetooth/gatt_client/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/gattc_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(gatt_client_demo) diff --git a/examples/bluetooth/gatt_security_client/CMakeLists.txt b/examples/bluetooth/gatt_security_client/CMakeLists.txt new file mode 100644 index 000000000..787f0b763 --- /dev/null +++ b/examples/bluetooth/gatt_security_client/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/example_ble_sec_gattc_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(sec_gattc_demo) diff --git a/examples/bluetooth/gatt_security_server/CMakeLists.txt b/examples/bluetooth/gatt_security_server/CMakeLists.txt new file mode 100644 index 000000000..d232d02b3 --- /dev/null +++ b/examples/bluetooth/gatt_security_server/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/example_ble_sec_gatts_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(sec_gatts_demo) diff --git a/examples/bluetooth/gatt_server/CMakeLists.txt b/examples/bluetooth/gatt_server/CMakeLists.txt new file mode 100644 index 000000000..74a0560be --- /dev/null +++ b/examples/bluetooth/gatt_server/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/gatts_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(gatt_server_demos) diff --git a/examples/bluetooth/gatt_server_service_table/CMakeLists.txt b/examples/bluetooth/gatt_server_service_table/CMakeLists.txt new file mode 100644 index 000000000..2f5653065 --- /dev/null +++ b/examples/bluetooth/gatt_server_service_table/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/gatts_table_creat_demo.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(gatt_server_service_table_demo) diff --git a/examples/bluetooth/gattc_multi_connect/CMakeLists.txt b/examples/bluetooth/gattc_multi_connect/CMakeLists.txt new file mode 100644 index 000000000..73566a731 --- /dev/null +++ b/examples/bluetooth/gattc_multi_connect/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/gattc_multi_connect.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(gatt_multi_connect) diff --git a/examples/ethernet/ethernet/CMakeLists.txt b/examples/ethernet/ethernet/CMakeLists.txt new file mode 100644 index 000000000..0b4d20f08 --- /dev/null +++ b/examples/ethernet/ethernet/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/ethernet_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ethernet_demo) diff --git a/examples/get-started/blink/CMakeLists.txt b/examples/get-started/blink/CMakeLists.txt new file mode 100644 index 000000000..56450928b --- /dev/null +++ b/examples/get-started/blink/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following five 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) + +set(MAIN_SRCS main/blink.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(blink) diff --git a/examples/get-started/hello_world/CMakeLists.txt b/examples/get-started/hello_world/CMakeLists.txt new file mode 100644 index 000000000..1d4853e77 --- /dev/null +++ b/examples/get-started/hello_world/CMakeLists.txt @@ -0,0 +1,8 @@ +# 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) + +set(MAIN_SRCS main/hello_world_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(hello-world) diff --git a/examples/get-started/hello_world/partitions.csv b/examples/get-started/hello_world/partitions.csv new file mode 100644 index 000000000..22cf97bac --- /dev/null +++ b/examples/get-started/hello_world/partitions.csv @@ -0,0 +1,5 @@ +# 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, , 0x6000, +phy_init, data, phy, , 0x1000, +factory, app, factory, , 1M, diff --git a/examples/mesh/internal_communication/CMakeLists.txt b/examples/mesh/internal_communication/CMakeLists.txt new file mode 100644 index 000000000..485f63621 --- /dev/null +++ b/examples/mesh/internal_communication/CMakeLists.txt @@ -0,0 +1,11 @@ +# The following five 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) + +set(MAIN_SRCS main/mesh_light.c main/mesh_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(internal_transceiver) + +include_directories(main/include) + diff --git a/examples/mesh/manual_networking/CMakeLists.txt b/examples/mesh/manual_networking/CMakeLists.txt new file mode 100644 index 000000000..485f63621 --- /dev/null +++ b/examples/mesh/manual_networking/CMakeLists.txt @@ -0,0 +1,11 @@ +# The following five 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) + +set(MAIN_SRCS main/mesh_light.c main/mesh_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(internal_transceiver) + +include_directories(main/include) + diff --git a/examples/peripherals/adc/CMakeLists.txt b/examples/peripherals/adc/CMakeLists.txt new file mode 100644 index 000000000..2232b277c --- /dev/null +++ b/examples/peripherals/adc/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/adc1_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(adc) diff --git a/examples/peripherals/adc2/CMakeLists.txt b/examples/peripherals/adc2/CMakeLists.txt new file mode 100644 index 000000000..650e3100a --- /dev/null +++ b/examples/peripherals/adc2/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/adc2_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(adc2) diff --git a/examples/peripherals/gpio/CMakeLists.txt b/examples/peripherals/gpio/CMakeLists.txt new file mode 100644 index 000000000..82873edc4 --- /dev/null +++ b/examples/peripherals/gpio/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/gpio_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(gpio) diff --git a/examples/peripherals/i2c/CMakeLists.txt b/examples/peripherals/i2c/CMakeLists.txt new file mode 100644 index 000000000..048d75fb3 --- /dev/null +++ b/examples/peripherals/i2c/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/i2c_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(i2c) diff --git a/examples/peripherals/i2s/CMakeLists.txt b/examples/peripherals/i2s/CMakeLists.txt new file mode 100644 index 000000000..6520061d4 --- /dev/null +++ b/examples/peripherals/i2s/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/i2s_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(esp32-i2s-driver-example) diff --git a/examples/peripherals/i2s_adc_dac/CMakeLists.txt b/examples/peripherals/i2s_adc_dac/CMakeLists.txt new file mode 100644 index 000000000..8e7fe3c07 --- /dev/null +++ b/examples/peripherals/i2s_adc_dac/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/app_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(i2s-adc-dac) diff --git a/examples/peripherals/ledc/CMakeLists.txt b/examples/peripherals/ledc/CMakeLists.txt new file mode 100644 index 000000000..c0c15b6f9 --- /dev/null +++ b/examples/peripherals/ledc/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/ledc_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(ledc) diff --git a/examples/peripherals/mcpwm/mcpwm_basic_config/CMakeLists.txt b/examples/peripherals/mcpwm/mcpwm_basic_config/CMakeLists.txt new file mode 100644 index 000000000..a3ee8315f --- /dev/null +++ b/examples/peripherals/mcpwm/mcpwm_basic_config/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/mcpwm_basic_config_example.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mcpwm_basic_config) diff --git a/examples/peripherals/mcpwm/mcpwm_bldc_control/CMakeLists.txt b/examples/peripherals/mcpwm/mcpwm_bldc_control/CMakeLists.txt new file mode 100644 index 000000000..ed09e85b2 --- /dev/null +++ b/examples/peripherals/mcpwm/mcpwm_bldc_control/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/mcpwm_bldc_control_hall_sensor_example.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mcpwm_bldc_control_hall_sensor) diff --git a/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/CMakeLists.txt b/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/CMakeLists.txt new file mode 100644 index 000000000..4076c2839 --- /dev/null +++ b/examples/peripherals/mcpwm/mcpwm_brushed_dc_control/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/mcpwm_brushed_dc_control_example.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mcpwm_brushed_dc_control) diff --git a/examples/peripherals/mcpwm/mcpwm_servo_control/CMakeLists.txt b/examples/peripherals/mcpwm/mcpwm_servo_control/CMakeLists.txt new file mode 100644 index 000000000..fc3fab809 --- /dev/null +++ b/examples/peripherals/mcpwm/mcpwm_servo_control/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/mcpwm_servo_control_example.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mcpwm_servo_control) diff --git a/examples/peripherals/pcnt/CMakeLists.txt b/examples/peripherals/pcnt/CMakeLists.txt new file mode 100644 index 000000000..2a7c8f40e --- /dev/null +++ b/examples/peripherals/pcnt/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/pcnt_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(pcnt) diff --git a/examples/peripherals/rmt_nec_tx_rx/CMakeLists.txt b/examples/peripherals/rmt_nec_tx_rx/CMakeLists.txt new file mode 100644 index 000000000..468032294 --- /dev/null +++ b/examples/peripherals/rmt_nec_tx_rx/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/infrared_nec_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(infrared_nec) diff --git a/examples/peripherals/rmt_tx/CMakeLists.txt b/examples/peripherals/rmt_tx/CMakeLists.txt new file mode 100644 index 000000000..7aa64fedb --- /dev/null +++ b/examples/peripherals/rmt_tx/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/rmt_tx_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(rmt_tx) diff --git a/examples/peripherals/sigmadelta/CMakeLists.txt b/examples/peripherals/sigmadelta/CMakeLists.txt new file mode 100644 index 000000000..3f4df2cfc --- /dev/null +++ b/examples/peripherals/sigmadelta/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/sigmadelta_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(sigmadelta) diff --git a/examples/peripherals/spi_master/CMakeLists.txt b/examples/peripherals/spi_master/CMakeLists.txt new file mode 100644 index 000000000..d27864187 --- /dev/null +++ b/examples/peripherals/spi_master/CMakeLists.txt @@ -0,0 +1,17 @@ +# The following four 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) + +set(MAIN_SRCS + main/spi_master_example_main.c + main/pretty_effect.c + main/decode_image.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(spi_master) + +# Embed the image into the final binary +# +# (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.) +target_add_binary_data(spi_master.elf + "main/image.jpg" BINARY) diff --git a/examples/peripherals/spi_slave/receiver/CMakeLists.txt b/examples/peripherals/spi_slave/receiver/CMakeLists.txt new file mode 100644 index 000000000..21c05d9e6 --- /dev/null +++ b/examples/peripherals/spi_slave/receiver/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/app_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(spi-slave-receiver) diff --git a/examples/peripherals/spi_slave/sender/CMakeLists.txt b/examples/peripherals/spi_slave/sender/CMakeLists.txt new file mode 100644 index 000000000..0c95698e9 --- /dev/null +++ b/examples/peripherals/spi_slave/sender/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/app_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(spi-slave-sender) diff --git a/examples/peripherals/timer_group/CMakeLists.txt b/examples/peripherals/timer_group/CMakeLists.txt new file mode 100644 index 000000000..7f851e164 --- /dev/null +++ b/examples/peripherals/timer_group/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/timer_group_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(timer_group) diff --git a/examples/peripherals/touch_pad_interrupt/CMakeLists.txt b/examples/peripherals/touch_pad_interrupt/CMakeLists.txt new file mode 100644 index 000000000..efdecaba1 --- /dev/null +++ b/examples/peripherals/touch_pad_interrupt/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/tp_interrupt_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(touch_pad_interrupt) diff --git a/examples/peripherals/touch_pad_read/CMakeLists.txt b/examples/peripherals/touch_pad_read/CMakeLists.txt new file mode 100644 index 000000000..f246a1ad5 --- /dev/null +++ b/examples/peripherals/touch_pad_read/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/tp_read_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(touch_pad_read) diff --git a/examples/peripherals/uart_async_rxtxtasks/CMakeLists.txt b/examples/peripherals/uart_async_rxtxtasks/CMakeLists.txt new file mode 100644 index 000000000..4ab23a834 --- /dev/null +++ b/examples/peripherals/uart_async_rxtxtasks/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/uart_async_rxtxtasks_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(uart_async_rxtxtasks) diff --git a/examples/peripherals/uart_echo/CMakeLists.txt b/examples/peripherals/uart_echo/CMakeLists.txt new file mode 100644 index 000000000..b7ab8a582 --- /dev/null +++ b/examples/peripherals/uart_echo/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/uart_echo_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(uart_echo) diff --git a/examples/peripherals/uart_events/CMakeLists.txt b/examples/peripherals/uart_events/CMakeLists.txt new file mode 100644 index 000000000..464886f25 --- /dev/null +++ b/examples/peripherals/uart_events/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/uart_events_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(uart_events) diff --git a/examples/peripherals/uart_select/CMakeLists.txt b/examples/peripherals/uart_select/CMakeLists.txt new file mode 100644 index 000000000..c761f9d60 --- /dev/null +++ b/examples/peripherals/uart_select/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/uart_select_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(uart_select) diff --git a/examples/protocols/aws_iot/subscribe_publish/CMakeLists.txt b/examples/protocols/aws_iot/subscribe_publish/CMakeLists.txt new file mode 100644 index 000000000..c7cfd88f4 --- /dev/null +++ b/examples/protocols/aws_iot/subscribe_publish/CMakeLists.txt @@ -0,0 +1,13 @@ +# The following four 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) + +set(MAIN_SRCS main/subscribe_publish_sample.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(subscribe_publish) + +# Embed the certificate data directly in the built binary +target_add_binary_data(subscribe_publish.elf main/certs/aws-root-ca.pem TEXT) +target_add_binary_data(subscribe_publish.elf main/certs/certificate.pem.crt TEXT) +target_add_binary_data(subscribe_publish.elf main/certs/private.pem.key TEXT) diff --git a/examples/protocols/aws_iot/thing_shadow/CMakeLists.txt b/examples/protocols/aws_iot/thing_shadow/CMakeLists.txt new file mode 100644 index 000000000..37d5d9a9c --- /dev/null +++ b/examples/protocols/aws_iot/thing_shadow/CMakeLists.txt @@ -0,0 +1,13 @@ +# The following four 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) + +set(MAIN_SRCS main/thing_shadow_sample.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(thing_shadow) + +# Embed the certificate data directly in the built binary +target_add_binary_data(thing_shadow.elf main/certs/aws-root-ca.pem TEXT) +target_add_binary_data(thing_shadow.elf main/certs/certificate.pem.crt TEXT) +target_add_binary_data(thing_shadow.elf main/certs/private.pem.key TEXT) diff --git a/examples/protocols/coap_client/CMakeLists.txt b/examples/protocols/coap_client/CMakeLists.txt new file mode 100644 index 000000000..43378b8b6 --- /dev/null +++ b/examples/protocols/coap_client/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/coap_client_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(coap_client) diff --git a/examples/protocols/coap_server/CMakeLists.txt b/examples/protocols/coap_server/CMakeLists.txt new file mode 100644 index 000000000..8495b8578 --- /dev/null +++ b/examples/protocols/coap_server/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/coap_server_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(coap_server) diff --git a/examples/protocols/esp_http_client/CMakeLists.txt b/examples/protocols/esp_http_client/CMakeLists.txt new file mode 100644 index 000000000..5241b97bd --- /dev/null +++ b/examples/protocols/esp_http_client/CMakeLists.txt @@ -0,0 +1,14 @@ +# The following five 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) + +set(MAIN_SRCS main/esp_http_client_example.c main/app_wifi.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(esp-http-client-example) + +# Embed the server root certificate into the final binary +# +# (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.) +target_add_binary_data(esp-http-client-example.elf + "main/howsmyssl_com_root_cert.pem" TEXT) diff --git a/examples/protocols/http2_request/CMakeLists.txt b/examples/protocols/http2_request/CMakeLists.txt new file mode 100644 index 000000000..b49128d5e --- /dev/null +++ b/examples/protocols/http2_request/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/http2_request_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(http2-request) diff --git a/examples/protocols/http2_request/components/sh2lib/CMakeLists.txt b/examples/protocols/http2_request/components/sh2lib/CMakeLists.txt new file mode 100644 index 000000000..6d19bf48b --- /dev/null +++ b/examples/protocols/http2_request/components/sh2lib/CMakeLists.txt @@ -0,0 +1,8 @@ +set(COMPONENT_ADD_INCLUDEDIRS .) + +set(COMPONENT_SRCDIRS .) + +set(COMPONENT_REQUIRES nghttp) +set(COMPONENT_PRIV_REQUIRES lwip esp-tls) + +register_component() diff --git a/examples/protocols/http_request/CMakeLists.txt b/examples/protocols/http_request/CMakeLists.txt new file mode 100644 index 000000000..a8f1470b9 --- /dev/null +++ b/examples/protocols/http_request/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/http_request_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(http-request) diff --git a/examples/protocols/https_mbedtls/CMakeLists.txt b/examples/protocols/https_mbedtls/CMakeLists.txt new file mode 100644 index 000000000..b564db2fa --- /dev/null +++ b/examples/protocols/https_mbedtls/CMakeLists.txt @@ -0,0 +1,14 @@ +# The following five 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) + +set(MAIN_SRCS main/https_mbedtls_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(https-mbedtls) + +# Embed the server root certificate into the final binary +# +# (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.) +target_add_binary_data(https-mbedtls.elf + "main/server_root_cert.pem" TEXT) diff --git a/examples/protocols/https_request/CMakeLists.txt b/examples/protocols/https_request/CMakeLists.txt new file mode 100644 index 000000000..22118c45c --- /dev/null +++ b/examples/protocols/https_request/CMakeLists.txt @@ -0,0 +1,14 @@ +# The following five 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) + +set(MAIN_SRCS main/https_request_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(https_request) + +# Embed the server root certificate into the final binary +# +# (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.) +target_add_binary_data(https_request.elf + "main/server_root_cert.pem" TEXT) diff --git a/examples/protocols/mdns/CMakeLists.txt b/examples/protocols/mdns/CMakeLists.txt new file mode 100644 index 000000000..57c5e9a2e --- /dev/null +++ b/examples/protocols/mdns/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/mdns_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mdns-test) diff --git a/examples/protocols/openssl_client/CMakeLists.txt b/examples/protocols/openssl_client/CMakeLists.txt new file mode 100644 index 000000000..0fc241ddf --- /dev/null +++ b/examples/protocols/openssl_client/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/openssl_client_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(openssl_client) diff --git a/examples/protocols/openssl_server/CMakeLists.txt b/examples/protocols/openssl_server/CMakeLists.txt new file mode 100644 index 000000000..dba98fc68 --- /dev/null +++ b/examples/protocols/openssl_server/CMakeLists.txt @@ -0,0 +1,12 @@ +# The following four 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) + +set(MAIN_SRCS main/openssl_server_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(openssl_server) + +# Embed the certificate & key data directly in the built binary +target_add_binary_data(openssl_server.elf main/cacert.pem TEXT) +target_add_binary_data(openssl_server.elf main/prvtkey.pem TEXT) diff --git a/examples/protocols/pppos_client/CMakeLists.txt b/examples/protocols/pppos_client/CMakeLists.txt new file mode 100644 index 000000000..c9378d72f --- /dev/null +++ b/examples/protocols/pppos_client/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/pppos_client_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(pppos_client) diff --git a/examples/protocols/sntp/CMakeLists.txt b/examples/protocols/sntp/CMakeLists.txt new file mode 100644 index 000000000..d083f8fe1 --- /dev/null +++ b/examples/protocols/sntp/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/sntp_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(sntp) diff --git a/examples/protocols/udp_multicast/CMakeLists.txt b/examples/protocols/udp_multicast/CMakeLists.txt new file mode 100644 index 000000000..998524292 --- /dev/null +++ b/examples/protocols/udp_multicast/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/udp_multicast_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(udp-multicast) diff --git a/examples/storage/nvs_rw_blob/CMakeLists.txt b/examples/storage/nvs_rw_blob/CMakeLists.txt new file mode 100644 index 000000000..1dd6023f3 --- /dev/null +++ b/examples/storage/nvs_rw_blob/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/nvs_blob_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(nvs-rw-blob) diff --git a/examples/storage/nvs_rw_value/CMakeLists.txt b/examples/storage/nvs_rw_value/CMakeLists.txt new file mode 100644 index 000000000..971a306ef --- /dev/null +++ b/examples/storage/nvs_rw_value/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/nvs_value_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(nvs-rw-value) diff --git a/examples/storage/sd_card/CMakeLists.txt b/examples/storage/sd_card/CMakeLists.txt new file mode 100644 index 000000000..ab4bcf2fa --- /dev/null +++ b/examples/storage/sd_card/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/sd_card_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(sd_card) diff --git a/examples/storage/spiffs/CMakeLists.txt b/examples/storage/spiffs/CMakeLists.txt new file mode 100644 index 000000000..0356e25bf --- /dev/null +++ b/examples/storage/spiffs/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/spiffs_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(spiffs) diff --git a/examples/storage/wear_levelling/CMakeLists.txt b/examples/storage/wear_levelling/CMakeLists.txt new file mode 100644 index 000000000..bd35e0843 --- /dev/null +++ b/examples/storage/wear_levelling/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/wear_levelling_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wear_levelling_example) diff --git a/examples/system/app_trace_to_host/CMakeLists.txt b/examples/system/app_trace_to_host/CMakeLists.txt new file mode 100644 index 000000000..f26a0fdb6 --- /dev/null +++ b/examples/system/app_trace_to_host/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/app_trace_to_host_test.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(app_trace_to_host_test) diff --git a/examples/system/base_mac_address/CMakeLists.txt b/examples/system/base_mac_address/CMakeLists.txt new file mode 100644 index 000000000..984dbb978 --- /dev/null +++ b/examples/system/base_mac_address/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/base_mac_address_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(base_mac_address) diff --git a/examples/system/console/CMakeLists.txt b/examples/system/console/CMakeLists.txt new file mode 100644 index 000000000..416fc704a --- /dev/null +++ b/examples/system/console/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/cmd_wifi.c main/console_example_main.c main/cmd_system.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(console) diff --git a/examples/system/deep_sleep/CMakeLists.txt b/examples/system/deep_sleep/CMakeLists.txt new file mode 100644 index 000000000..cf3d195aa --- /dev/null +++ b/examples/system/deep_sleep/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/deep_sleep_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(deep_sleep) diff --git a/examples/system/esp_timer/CMakeLists.txt b/examples/system/esp_timer/CMakeLists.txt new file mode 100644 index 000000000..5165f3d2a --- /dev/null +++ b/examples/system/esp_timer/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/esp_timer_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(esp_timer_example) diff --git a/examples/system/gcov/CMakeLists.txt b/examples/system/gcov/CMakeLists.txt new file mode 100644 index 000000000..b1cb9fd77 --- /dev/null +++ b/examples/system/gcov/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/gcov_example_func.c main/gcov_example.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(gcov_example) diff --git a/examples/system/ota/native_ota_example/CMakeLists.txt b/examples/system/ota/native_ota_example/CMakeLists.txt new file mode 100644 index 000000000..c4aa4d0d4 --- /dev/null +++ b/examples/system/ota/native_ota_example/CMakeLists.txt @@ -0,0 +1,14 @@ +# The following four 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) + +set(MAIN_SRCS main/native_ota_example.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(native_ota) + +# Embed the server root certificate into the final binary +# +# (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.) +target_add_binary_data(native_ota.elf + "../server_certs/ca_cert.pem" TEXT) diff --git a/examples/system/ota/simple_ota_example/CMakeLists.txt b/examples/system/ota/simple_ota_example/CMakeLists.txt new file mode 100644 index 000000000..f15e70874 --- /dev/null +++ b/examples/system/ota/simple_ota_example/CMakeLists.txt @@ -0,0 +1,14 @@ +# The following four 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) + +set(MAIN_SRCS main/simple_ota_example.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(simple_ota) + +# Embed the server root certificate into the final binary +# +# (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.) +target_add_binary_data(simple_ota.elf + "../server_certs/ca_cert.pem" TEXT) diff --git a/examples/system/select/CMakeLists.txt b/examples/system/select/CMakeLists.txt new file mode 100644 index 000000000..3175ceeb0 --- /dev/null +++ b/examples/system/select/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/select_example.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(select) diff --git a/examples/system/task_watchdog/CMakeLists.txt b/examples/system/task_watchdog/CMakeLists.txt new file mode 100644 index 000000000..e0f24b03f --- /dev/null +++ b/examples/system/task_watchdog/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/task_watchdog_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(task_watchdog) diff --git a/examples/wifi/espnow/CMakeLists.txt b/examples/wifi/espnow/CMakeLists.txt new file mode 100644 index 000000000..446cf5ccf --- /dev/null +++ b/examples/wifi/espnow/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/espnow_example_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(espnow_example) diff --git a/examples/wifi/iperf/CMakeLists.txt b/examples/wifi/iperf/CMakeLists.txt new file mode 100644 index 000000000..7463023e9 --- /dev/null +++ b/examples/wifi/iperf/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/cmd_wifi.c main/main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(iperf) diff --git a/examples/wifi/iperf/components/CMakeLists.txt b/examples/wifi/iperf/components/CMakeLists.txt new file mode 100644 index 000000000..352403c41 --- /dev/null +++ b/examples/wifi/iperf/components/CMakeLists.txt @@ -0,0 +1,7 @@ +set(COMPONENT_ADD_INCLUDEDIRS .) + +set(COMPONENT_SRCDIRS .) + +set(COMPONENT_PRIV_REQUIRES lwip) + +register_component() diff --git a/examples/wifi/iperf/sdkconfig.defaults b/examples/wifi/iperf/sdkconfig.defaults index 613b73f3f..f084e4a67 100644 --- a/examples/wifi/iperf/sdkconfig.defaults +++ b/examples/wifi/iperf/sdkconfig.defaults @@ -12,18 +12,18 @@ CONFIG_ESP32_WIFI_TX_BA_WIN=32 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y CONFIG_ESP32_WIFI_RX_BA_WIN=32 -CONFIG_FREERTOS_UNICORE= +CONFIG_FREERTOS_UNICORE=n CONFIG_FREERTOS_HZ=1000 -CONFIG_INT_WDT= -CONFIG_TASK_WDT= +CONFIG_INT_WDT=n +CONFIG_TASK_WDT=n CONFIG_TCP_SND_BUF_DEFAULT=65535 CONFIG_TCP_WND_DEFAULT=65535 CONFIG_TCP_RECVMBOX_SIZE=64 CONFIG_UDP_RECVMBOX_SIZE=64 CONFIG_TCPIP_RECVMBOX_SIZE=64 -CONFIG_LWIP_ETHARP_TRUST_IP_MAC= +CONFIG_LWIP_ETHARP_TRUST_IP_MAC=n CONFIG_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHFREQ_40M=y diff --git a/examples/wifi/power_save/CMakeLists.txt b/examples/wifi/power_save/CMakeLists.txt new file mode 100644 index 000000000..65cc2011d --- /dev/null +++ b/examples/wifi/power_save/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/power_save.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(power_save) diff --git a/examples/wifi/scan/CMakeLists.txt b/examples/wifi/scan/CMakeLists.txt new file mode 100644 index 000000000..9de12341a --- /dev/null +++ b/examples/wifi/scan/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/scan.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(scan) diff --git a/examples/wifi/simple_wifi/CMakeLists.txt b/examples/wifi/simple_wifi/CMakeLists.txt new file mode 100644 index 000000000..57158b16b --- /dev/null +++ b/examples/wifi/simple_wifi/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following five 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) + +set(MAIN_SRCS main/simple_wifi.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(simple_wifi) diff --git a/examples/wifi/smart_config/CMakeLists.txt b/examples/wifi/smart_config/CMakeLists.txt new file mode 100644 index 000000000..ae0b88ee6 --- /dev/null +++ b/examples/wifi/smart_config/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/smartconfig_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(smart_config) diff --git a/examples/wifi/wpa2_enterprise/CMakeLists.txt b/examples/wifi/wpa2_enterprise/CMakeLists.txt new file mode 100644 index 000000000..a489894e3 --- /dev/null +++ b/examples/wifi/wpa2_enterprise/CMakeLists.txt @@ -0,0 +1,17 @@ + +# (Automatically converted from project Makefile by convert_to_cmake.py.) + +# The following four 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) + +set(MAIN_SRCS main/wpa2_enterprise_main.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wpa2-enterprise) + +# Embed CA, certificate & key directly into binary +target_add_binary_data(wpa2-enterprise.elf main/wpa2_ca.pem TEXT) +target_add_binary_data(wpa2-enterprise.elf main/wpa2_client.crt TEXT) +target_add_binary_data(wpa2-enterprise.elf main/wpa2_client.key TEXT) + diff --git a/examples/wifi/wps/CMakeLists.txt b/examples/wifi/wps/CMakeLists.txt new file mode 100644 index 000000000..fd23de9aa --- /dev/null +++ b/examples/wifi/wps/CMakeLists.txt @@ -0,0 +1,8 @@ +# The following four 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) + +set(MAIN_SRCS main/wps.c) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(wps_example) diff --git a/make/project_config.mk b/make/project_config.mk index 8f0006c79..50cf139e6 100644 --- a/make/project_config.mk +++ b/make/project_config.mk @@ -15,11 +15,11 @@ SDKCONFIG ?= $(PROJECT_PATH)/sdkconfig # overrides (usually used for esp-idf examples) SDKCONFIG_DEFAULTS ?= $(PROJECT_PATH)/sdkconfig.defaults -# Workaround to run make parallel (-j). mconf and conf cannot be made simultaneously -$(KCONFIG_TOOL_DIR)/mconf: $(KCONFIG_TOOL_DIR)/conf +# Workaround to run make parallel (-j). mconf-idf and conf-idf cannot be made simultaneously +$(KCONFIG_TOOL_DIR)/mconf-idf: $(KCONFIG_TOOL_DIR)/conf-idf # reset MAKEFLAGS as the menuconfig makefile uses implicit compile rules -$(KCONFIG_TOOL_DIR)/mconf $(KCONFIG_TOOL_DIR)/conf: $(wildcard $(KCONFIG_TOOL_DIR)/*.c) +$(KCONFIG_TOOL_DIR)/mconf-idf $(KCONFIG_TOOL_DIR)/conf-idf: $(wildcard $(KCONFIG_TOOL_DIR)/*.c) MAKEFLAGS="" CC=$(HOSTCC) LD=$(HOSTLD) \ $(MAKE) -C $(KCONFIG_TOOL_DIR) @@ -36,13 +36,14 @@ $(SDKCONFIG): defconfig endif endif -# macro for the commands to run kconfig tools conf or mconf. +# macro for the commands to run kconfig tools conf-idf or mconf-idf. # $1 is the name (& args) of the conf tool to run define RunConf mkdir -p $(BUILD_DIR_BASE)/include/config cd $(BUILD_DIR_BASE); KCONFIG_AUTOHEADER=$(abspath $(BUILD_DIR_BASE)/include/sdkconfig.h) \ COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" KCONFIG_CONFIG=$(SDKCONFIG) \ COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \ + IDF_CMAKE=n \ $(KCONFIG_TOOL_DIR)/$1 $(IDF_PATH)/Kconfig endef @@ -58,7 +59,7 @@ ifndef MAKE_RESTARTS # depend on any prerequisite that may cause a make restart as part of # the prerequisite's own recipe. -menuconfig: $(KCONFIG_TOOL_DIR)/mconf +menuconfig: $(KCONFIG_TOOL_DIR)/mconf-idf $(summary) MENUCONFIG ifdef BATCH_BUILD @echo "Can't run interactive configuration inside non-interactive build process." @@ -67,25 +68,25 @@ ifdef BATCH_BUILD @echo "See esp-idf documentation for more details." @exit 1 else - $(call RunConf,mconf) + $(call RunConf,mconf-idf) endif # defconfig creates a default config, based on SDKCONFIG_DEFAULTS if present -defconfig: $(KCONFIG_TOOL_DIR)/conf +defconfig: $(KCONFIG_TOOL_DIR)/conf-idf $(summary) DEFCONFIG ifneq ("$(wildcard $(SDKCONFIG_DEFAULTS))","") cat $(SDKCONFIG_DEFAULTS) >> $(SDKCONFIG) # append defaults to sdkconfig, will override existing values endif - $(call RunConf,conf --olddefconfig) + $(call RunConf,conf-idf --olddefconfig) # if neither defconfig or menuconfig are requested, use the GENCONFIG rule to # ensure generated config files are up to date -$(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h: $(KCONFIG_TOOL_DIR)/conf $(SDKCONFIG) $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD) | $(call prereq_if_explicit,defconfig) $(call prereq_if_explicit,menuconfig) +$(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h: $(KCONFIG_TOOL_DIR)/conf-idf $(SDKCONFIG) $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD) | $(call prereq_if_explicit,defconfig) $(call prereq_if_explicit,menuconfig) $(summary) GENCONFIG ifdef BATCH_BUILD # can't prompt for new config values like on terminal - $(call RunConf,conf --olddefconfig) + $(call RunConf,conf-idf --olddefconfig) endif - $(call RunConf,conf --silentoldconfig) + $(call RunConf,conf-idf --silentoldconfig) touch $(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h # ensure newer than sdkconfig else # "$(MAKE_RESTARTS)" != "" diff --git a/tools/ci/build_examples_cmake.sh b/tools/ci/build_examples_cmake.sh new file mode 100755 index 000000000..e4f728cbd --- /dev/null +++ b/tools/ci/build_examples_cmake.sh @@ -0,0 +1,173 @@ +#!/bin/bash +# +# Build all examples from the examples directory, out of tree to +# ensure they can run when copied to a new directory. +# +# Runs as part of CI process. +# +# Assumes PWD is an out-of-tree build directory, and will copy examples +# to individual subdirectories, one by one. +# +# +# Without arguments it just builds all examples +# +# With one argument it builds part of the examples. This is a useful for +# parallel execution in CI. +# must look like this: +# _ +# It scans .gitlab-ci.yaml to count number of jobs which have name "_" +# It scans the filesystem to count all examples +# Based on this, it decides to run qa set of examples. +# + +# ----------------------------------------------------------------------------- +# Safety settings (see https://gist.github.com/ilg-ul/383869cbb01f61a51c4d). + +if [[ ! -z ${DEBUG_SHELL} ]] +then + set -x # Activate the expand mode if DEBUG is anything but empty. +fi + +set -o errexit # Exit if command failed. +set -o pipefail # Exit if pipe failed. + +# Remove the initial space and instead use '\n'. +IFS=$'\n\t' + +export PATH="$IDF_PATH/tools:$PATH" # for idf.py + +# ----------------------------------------------------------------------------- + +die() { + echo "${1:-"Unknown Error"}" 1>&2 + exit 1 +} + +[ -z ${IDF_PATH} ] && die "IDF_PATH is not set" +[ -z ${LOG_PATH} ] && die "LOG_PATH is not set" +[ -d ${LOG_PATH} ] || mkdir -p ${LOG_PATH} + +set -o nounset # Exit if variable not set. + +echo "build_examples running in ${PWD}" + +# only 0 or 1 arguments +[ $# -le 1 ] || die "Have to run as $(basename $0) []" + +export BATCH_BUILD=1 +export V=0 # only build verbose if there's an error + +shopt -s lastpipe # Workaround for Bash to use variables in loops (http://mywiki.wooledge.org/BashFAQ/024) + +RESULT=0 +FAILED_EXAMPLES="" +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 CMakeLists.txt | grep -v "/components/" | sort ) + +if [ $# -eq 0 ] +then + START_NUM=0 + END_NUM=999 +else + JOB_NAME=$1 + + # parse text prefix at the beginning of string 'some_your_text_NUM' + # (will be 'some_your_text' without last '_') + JOB_PATTERN=$( echo ${JOB_NAME} | sed -n -r 's/^(.*)_[0-9]+$/\1/p' ) + [ -z ${JOB_PATTERN} ] && die "JOB_PATTERN is bad" + + # parse number 'NUM' at the end of string 'some_your_text_NUM' + JOB_NUM=$( echo ${JOB_NAME} | sed -n -r 's/^.*_([0-9]+)$/\1/p' ) + [ -z ${JOB_NUM} ] && die "JOB_NUM is bad" + + # count number of the jobs + NUM_OF_JOBS=$( grep -c -E "^${JOB_PATTERN}_[0-9]+:$" "${IDF_PATH}/.gitlab-ci.yml" ) + [ -z ${NUM_OF_JOBS} ] && die "NUM_OF_JOBS is bad" + + # count number of examples + NUM_OF_EXAMPLES=$(echo ${EXAMPLE_PATHS} | wc -l ) + [ -z ${NUM_OF_EXAMPLES} ] && die "NUM_OF_EXAMPLES is bad" + + # separate intervals + #57 / 5 == 12 + NUM_OF_EX_PER_JOB=$(( (${NUM_OF_EXAMPLES} + ${NUM_OF_JOBS} - 1) / ${NUM_OF_JOBS} )) + [ -z ${NUM_OF_EX_PER_JOB} ] && die "NUM_OF_EX_PER_JOB is bad" + + # ex.: [0; 12); [12; 24); [24; 36); [36; 48); [48; 60) + START_NUM=$(( ${JOB_NUM} * ${NUM_OF_EX_PER_JOB} )) + [ -z ${START_NUM} ] && die "START_NUM is bad" + + END_NUM=$(( (${JOB_NUM} + 1) * ${NUM_OF_EX_PER_JOB} )) + [ -z ${END_NUM} ] && die "END_NUM is bad" +fi + +build_example () { + local ID=$1 + shift + local CMAKELISTS=$1 + shift + + local EXAMPLE_DIR=$(dirname "${CMAKELISTS}") + local EXAMPLE_NAME=$(basename "${EXAMPLE_DIR}") + + echo "Building ${EXAMPLE_NAME} as ${ID}..." + mkdir -p "example_builds/${ID}" + cp -r "${EXAMPLE_DIR}" "example_builds/${ID}" + pushd "example_builds/${ID}/${EXAMPLE_NAME}" + # be stricter in the CI build than the default IDF settings + export EXTRA_CFLAGS="-Werror -Werror=deprecated-declarations" + export EXTRA_CXXFLAGS=${EXTRA_CFLAGS} + + # build non-verbose first + local BUILDLOG=${LOG_PATH}/ex_${ID}_log.txt + touch ${BUILDLOG} + + idf.py fullclean >>${BUILDLOG} 2>&1 && + idf.py build >>${BUILDLOG} 2>&1 && + cp build/flash_project_args build/download.config || # backwards compatible download.config filename + { + RESULT=$?; FAILED_EXAMPLES+=" ${EXAMPLE_NAME}" ; + } + + cat ${BUILDLOG} + popd + + grep -i "error\|warning" "${BUILDLOG}" 2>&1 | grep -v "error.c.obj" >> "${LOG_SUSPECTED}" || : +} + +EXAMPLE_NUM=0 + +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} ] - $EXAMPLE_PATH" + + build_example "${EXAMPLE_NUM}" "${EXAMPLE_PATH}" + + EXAMPLE_NUM=$(( $EXAMPLE_NUM + 1 )) +done + +# show warnings +echo -e "\nFound issues:" + +# Ignore the next messages: +# "error.o" or "-Werror" in compiler's command line +# "reassigning to symbol" or "changes choice state" in sdkconfig +sort -u "${LOG_SUSPECTED}" | \ +grep -v "library/error.o\|\ -Werror\|reassigning to symbol\|changes choice state" \ + && RESULT=$RESULT_ISSUES \ + || echo -e "\tNone" + +[ -z ${FAILED_EXAMPLES} ] || echo -e "\nThere are errors in the next examples: $FAILED_EXAMPLES" +[ $RESULT -eq 0 ] || echo -e "\nFix all warnings and errors above to pass the test!" + +echo -e "\nReturn code = $RESULT" + +exit $RESULT diff --git a/tools/ci/check_examples_cmake_make.sh b/tools/ci/check_examples_cmake_make.sh new file mode 100755 index 000000000..2f2d84413 --- /dev/null +++ b/tools/ci/check_examples_cmake_make.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# 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/") +MAKE_EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name Makefile ) + +# temporary: ignore ULP examples as no ULP toolchain support +CMAKE_EXAMPLE_PATHS=$( echo "$CMAKE_EXAMPLE_PATHS" | grep -v "/system/ulp") +MAKE_EXAMPLE_PATHS=$( echo "$MAKE_EXAMPLE_PATHS" | grep -v "/system/ulp") + +CMAKE_EXAMPLE_PATHS="$(/usr/bin/dirname $CMAKE_EXAMPLE_PATHS | sort -n)" +MAKE_EXAMPLE_PATHS="$(/usr/bin/dirname $MAKE_EXAMPLE_PATHS | sort -n)" + +MISMATCH=$(comm -3 <(echo "$MAKE_EXAMPLE_PATHS") <(echo "$CMAKE_EXAMPLE_PATHS")) + +if [ -n "$MISMATCH" ]; then + echo "Some examples are not in both CMake and GNU Make:" + echo "$MISMATCH" + exit 1 +fi + +echo "Example lists match" +exit 0 diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt index a55639cd3..0cf23a8f7 100644 --- a/tools/ci/executable-list.txt +++ b/tools/ci/executable-list.txt @@ -34,3 +34,13 @@ tools/kconfig/streamline_config.pl tools/kconfig/conf tools/kconfig/mconf tools/windows/eclipse_make.sh +tools/ci/build_examples_cmake.sh +tools/ci/test_build_system_cmake.sh +tools/ci/check_examples_cmake_make.sh +tools/cmake/convert_to_cmake.py +tools/cmake/run_cmake_lint.sh +tools/idf.py +tools/kconfig_new/confgen.py +tools/kconfig_new/confserver.py +tools/kconfig_new/test/test_confserver.py +tools/windows/tool_setup/build_installer.sh diff --git a/tools/ci/test_build_system.sh b/tools/ci/test_build_system.sh index e5ae4ea9f..efc3703b1 100755 --- a/tools/ci/test_build_system.sh +++ b/tools/ci/test_build_system.sh @@ -43,7 +43,11 @@ function run_tests() print_status "Cloning template from ${ESP_IDF_TEMPLATE_GIT}..." git clone ${ESP_IDF_TEMPLATE_GIT} template cd template - git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..." + if [ -z $CHECKOUT_REF_SCRIPT ]; then + git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..." + else + $CHECKOUT_REF_SCRIPT esp-idf-template + fi print_status "Updating template config..." make defconfig || exit $? diff --git a/tools/ci/test_build_system_cmake.sh b/tools/ci/test_build_system_cmake.sh new file mode 100755 index 000000000..de400fcb7 --- /dev/null +++ b/tools/ci/test_build_system_cmake.sh @@ -0,0 +1,317 @@ +#!/bin/bash +# +# Test the build system for basic consistency (Cmake/idf.py version) +# +# A bash script that tests some likely build failure scenarios in a row +# +# Assumes PWD is an out-of-tree build directory, and will create a +# subdirectory inside it to run build tests in. +# +# Environment variables: +# IDF_PATH - must be set +# ESP_IDF_TEMPLATE_GIT - Can override git clone source for template app. Otherwise github. +# NOCLEANUP - Set to '1' if you want the script to leave its temporary directory when done, for post-mortem. +# +# +# Internals: +# * The tests run in sequence & the system keeps track of all failures to print at the end. +# * BUILD directory is set to default BUILD_DIR_BASE +# * The "print_status" function both prints a status line to the log and keeps track of which test is running. +# * Calling the "failure" function prints a failure message to the log and also adds to the list of failures to print at the end. +# * The function "assert_built" tests for a file relative to the BUILD directory. +# * The function "take_build_snapshot" can be paired with the functions "assert_rebuilt" and "assert_not_rebuilt" to compare file timestamps and verify if they were rebuilt or not since the snapshot was taken. +# +# To add a new test case, add it to the end of the run_tests function. Note that not all test cases do comprehensive cleanup +# (although very invasive ones like appending CRLFs to all files take a copy of the esp-idf tree), however the clean_build_dir +# function can be used to force-delete all files from the build output directory. + +# Set up some variables +# +# override ESP_IDF_TEMPLATE_GIT to point to a local dir if you're testing and want fast iterations +[ -z ${ESP_IDF_TEMPLATE_GIT} ] && ESP_IDF_TEMPLATE_GIT=https://github.com/espressif/esp-idf-template.git + +# uncomment next line to produce a lot more debug output +#export V=1 + +export PATH="$IDF_PATH/tools:$PATH" # for idf.py + +function run_tests() +{ + FAILURES= + STATUS="Starting" + print_status "Checking prerequisites" + [ -z ${IDF_PATH} ] && echo "IDF_PATH is not set. Need path to esp-idf installation." && exit 2 + + print_status "Cloning template from ${ESP_IDF_TEMPLATE_GIT}..." + git clone ${ESP_IDF_TEMPLATE_GIT} template + cd template + if [ -z $CHECKOUT_REF_SCRIPT ]; then + git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..." + else + $CHECKOUT_REF_SCRIPT esp-idf-template + fi + + print_status "Try to clean fresh directory..." + idf.py fullclean || exit $? + + # all relative to the build directory + BOOTLOADER_BINS="bootloader/bootloader.elf bootloader/bootloader.bin" + APP_BINS="app-template.elf app-template.bin" + PARTITION_BIN="partition_table/partition-table.bin" + + print_status "Initial clean build" + # if build fails here, everything fails + idf.py build || exit $? + + # check all the expected build artifacts from the clean build + assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN} + + print_status "Updating component source file rebuilds component" + # touch a file & do a build + 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} + + 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/CMakeFiles/bootloader.elf.dir/main/bootloader_start.c.obj + assert_not_rebuilt ${APP_BINS} ${PARTITION_BIN} + + print_status "Partition CSV file rebuilds partitions" + take_build_snapshot + touch ${IDF_PATH}/components/partition_table/partitions_singleapp.csv + idf.py build || failure "Failed to build partition table" + assert_rebuilt ${PARTITION_BIN} + assert_not_rebuilt app-template.bin app-template.elf ${BOOTLOADER_BINS} + + print_status "Partial build doesn't compile anything by default" + take_build_snapshot + # verify no build files are refreshed by a partial make + ALL_BUILD_FILES=$(find ${BUILD} -type f | sed "s@${BUILD}/@@" | grep -v '^.') + idf.py build || failure "Partial build failed" + assert_not_rebuilt ${ALL_BUILD_FILES} + + print_status "Moving BUILD_DIR_BASE out of tree" + clean_build_dir + OUTOFTREE_BUILD=${TESTDIR}/alt_build + idf.py -B "${OUTOFTREE_BUILD}" build || failure "Failed to build with out-of-tree build dir" + NEW_BUILD_FILES=$(find ${OUTOFREE_BUILD} -type f) + if [ -z "${NEW_BUILD_FILES}" ]; then + failure "No files found in new build directory!" + fi + DEFAULT_BUILD_FILES=$(find ${BUILD} -mindepth 1) + if [ -n "${DEFAULT_BUILD_FILES}" ]; then + failure "Some files were incorrectly put into the default build directory: ${DEFAULT_BUILD_FILES}" + fi + + print_status "BUILD_DIR_BASE inside default build directory" + clean_build_dir + idf.py -B "build/subdirectory" build || failure "Failed to build with build dir as subdir" + NEW_BUILD_FILES=$(find ${BUILD}/subdirectory -type f) + if [ -z "${NEW_BUILD_FILES}" ]; then + failure "No files found in new build directory!" + fi + + print_status "Can still clean build if all text files are CRLFs" + clean_build_dir + find . -path .git -prune -exec unix2dos {} \; # CRLFify template dir + # make a copy of esp-idf and CRLFify it + CRLF_ESPIDF=${TESTDIR}/esp-idf-crlf + mkdir -p ${CRLF_ESPIDF} + cp -r ${IDF_PATH}/* ${CRLF_ESPIDF} + # don't CRLFify executable files, as Linux will fail to execute them + find ${CRLF_ESPIDF} -name .git -prune -name build -prune -type f ! -perm 755 -exec unix2dos {} \; + IDF_PATH=${CRLF_ESPIDF} idf.py build || failure "Failed to build with CRLFs in source" + # do the same checks we do for the clean build + assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN} + + print_status "Updating rom ld file should re-link app and bootloader" + clean_build_dir + idf.py build + take_build_snapshot + sleep 1 # ninja may ignore if the timestamp delta is too low + cp ${IDF_PATH}/components/esp32/ld/esp32.rom.ld . + echo "/* (Build test comment) */" >> ${IDF_PATH}/components/esp32/ld/esp32.rom.ld + tail ${IDF_PATH}/components/esp32/ld/esp32.rom.ld + idf.py build || failure "Failed to rebuild with modified linker script" + assert_rebuilt ${APP_BINS} ${BOOTLOADER_BINS} + mv esp32.rom.ld ${IDF_PATH}/components/esp32/ld/ + + print_status "Updating app-only ld file should only re-link app" + take_build_snapshot + cp ${IDF_PATH}/components/esp32/ld/esp32.common.ld . + sleep 1 # ninja may ignore if the timestamp delta is too low + echo "/* (Build test comment) */" >> ${IDF_PATH}/components/esp32/ld/esp32.common.ld + idf.py build || failure "Failed to rebuild with modified linker script" + assert_rebuilt ${APP_BINS} + assert_not_rebuilt ${BOOTLOADER_BINS} + mv esp32.common.ld ${IDF_PATH}/components/esp32/ld/ + + print_status "sdkconfig update triggers full recompile" + clean_build_dir + idf.py build + take_build_snapshot + # need to actually change config, or cmake is too smart to rebuild + sed -i s/CONFIG_FREERTOS_UNICORE=/CONFIG_FREERTOS_UNICORE=y/ sdkconfig + idf.py build + # check the sdkconfig.h file was rebuilt + 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 + + print_status "Updating project CMakeLists.txt triggers full recompile" + clean_build_dir + idf.py build + take_build_snapshot + # Need to actually change the build config, or CMake won't do anything + cp CMakeLists.txt CMakeLists.bak + sed -i 's/^project(/add_compile_options("-DUSELESS_MACRO_DOES_NOTHING=1")\nproject\(/' CMakeLists.txt + 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 + + print_status "Can build with Ninja (no idf.py)" + clean_build_dir + (cd build && cmake -G Ninja .. && ninja) || failure "Ninja build failed" + assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN} + + print_status "Can build with GNU Make (no idf.py)" + clean_build_dir + mkdir build + (cd build && cmake -G "Unix Makefiles" .. && make) || failure "Make build failed" + assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN} + + print_status "Can build with IDF_PATH set via cmake cache not environment" + clean_build_dir + cp CMakeLists.txt CMakeLists.bak + sed -i 's/ENV{IDF_PATH}/{IDF_PATH}/' CMakeLists.txt + export IDF_PATH_BACKUP="$IDF_PATH" + (unset IDF_PATH && + cd build && + cmake -G Ninja .. -DIDF_PATH=${IDF_PATH_BACKUP} && + ninja) || failure "Ninja build failed" + mv CMakeLists.bak CMakeLists.txt + assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN} + + print_status "Can build with IDF_PATH unset and inferred by build system" + clean_build_dir + cp CMakeLists.txt CMakeLists.bak + sed -i "s%\$ENV{IDF_PATH}%${IDF_PATH}%" CMakeLists.txt # expand to a hardcoded path + (unset IDF_PATH && cd build && + cmake -G Ninja .. && ninja) || failure "Ninja build failed" + mv CMakeLists.bak CMakeLists.txt + assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN} + + print_status "All tests completed" + if [ -n "${FAILURES}" ]; then + echo "Some failures were detected:" + echo -e "${FAILURES}" + exit 1 + else + echo "Build tests passed." + fi +} + +function print_status() +{ + echo "******** $1" + STATUS="$1" +} + +function failure() +{ + echo "!!!!!!!!!!!!!!!!!!!" + echo "FAILURE: $1" + echo "!!!!!!!!!!!!!!!!!!!" + FAILURES="${FAILURES}${STATUS} :: $1\n" +} + +TESTDIR=${PWD}/build_system_tests_$$ +mkdir -p ${TESTDIR} +# set NOCLEANUP=1 if you want to keep the test directory around +# for post-mortem debugging +[ -z ${NOCLEANUP} ] && trap "rm -rf ${TESTDIR}" EXIT KILL + +SNAPSHOT=${TESTDIR}/snapshot +BUILD=${TESTDIR}/template/build + + +# copy all the build output to a snapshot directory +function take_build_snapshot() +{ + rm -rf ${SNAPSHOT} + cp -ap ${TESTDIR}/template/build ${SNAPSHOT} +} + +# verify that all the arguments are present in the build output directory +function assert_built() +{ + until [ -z "$1" ]; do + if [ ! -f "${BUILD}/$1" ]; then + failure "File $1 should be in the build output directory" + fi + shift + done +} + +# Test if a file has been rebuilt. +function file_was_rebuilt() +{ + # can't use [ a -ot b ] here as -ot only gives second resolution + # but stat -c %y seems to be microsecond at least for tmpfs, ext4.. + if [ "$(stat -c %y ${SNAPSHOT}/$1)" != "$(stat -c %y ${BUILD}/$1)" ]; then + return 0 + else + return 1 + fi +} + +# verify all the arguments passed in were rebuilt relative to the snapshot +function assert_rebuilt() +{ + until [ -z "$1" ]; do + assert_built "$1" + if [ ! -f "${SNAPSHOT}/$1" ]; then + failure "File $1 should be in original build snapshot" + fi + if ! file_was_rebuilt "$1"; then + failure "File $1 should have been rebuilt" + fi + shift + done +} + +# verify all the arguments are in the build directory & snapshot, +# but were not rebuilt +function assert_not_rebuilt() +{ + until [ -z "$1" ]; do + assert_built "$1" + if [ ! -f "${SNAPSHOT}/$1" ]; then + failure "File $1 should be in snapshot build directory" + fi + if file_was_rebuilt "$1"; then + failure "File $1 should not have been rebuilt" + fi + shift + done +} + +# do a "clean" that doesn't depend on idf.py +function clean_build_dir() +{ + rm -rf --preserve-root ${BUILD}/* ${BUILD}/.* +} + +cd ${TESTDIR} +run_tests diff --git a/tools/cmake/components.cmake b/tools/cmake/components.cmake new file mode 100644 index 000000000..0056a3b4a --- /dev/null +++ b/tools/cmake/components.cmake @@ -0,0 +1,177 @@ +# Given a list of components in 'component_paths', filter only paths to the components +# mentioned in 'components' and return as a list in 'result_paths' +function(components_get_paths component_paths components result_paths) + set(result "") + foreach(path ${component_paths}) + get_filename_component(name "${path}" NAME) + if("${name}" IN_LIST components) + list(APPEND result "${name}") + endif() + endforeach() + set("${result_path}" "${result}" PARENT_SCOPE) +endfunction() + +# Add a component to the build, using the COMPONENT variables defined +# in the parent +# +function(register_component) + get_filename_component(component_dir ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) + get_filename_component(component ${component_dir} NAME) + + spaces2list(COMPONENT_SRCDIRS) + spaces2list(COMPONENT_ADD_INCLUDEDIRS) + spaces2list(COMPONENT_SRCEXCLUDE) + + # Add to COMPONENT_SRCS by globbing in COMPONENT_SRCDIRS + if(NOT COMPONENT_SRCS) + foreach(dir ${COMPONENT_SRCDIRS}) + get_filename_component(abs_dir ${dir} ABSOLUTE BASE_DIR ${component_dir}) + if(NOT IS_DIRECTORY ${abs_dir}) + message(FATAL_ERROR "${CMAKE_CURRENT_LIST_FILE}: COMPONENT_SRCDIRS entry '${dir}' does not exist") + endif() + + file(GLOB matches "${abs_dir}/*.c" "${abs_dir}/*.cpp" "${abs_dir}/*.S") + if(matches) + list(SORT matches) + set(COMPONENT_SRCS "${COMPONENT_SRCS};${matches}") + else() + message(FATAL_ERROR "${CMAKE_CURRENT_LIST_FILE}: COMPONENT_SRCDIRS entry '${dir}' has no source files") + endif() + endforeach() + endif() + + # Remove COMPONENT_SRCEXCLUDE matches + foreach(exclude ${COMPONENT_SRCEXCLUDE}) + get_filename_component(exclude "${exclude}" ABSOLUTE ${component_dir}) + foreach(src ${COMPONENT_SRCS}) + get_filename_component(abs_src "${src}" ABSOLUTE ${component_dir}) + if("${exclude}" STREQUAL "${abs_src}") # compare as canonical paths + list(REMOVE_ITEM COMPONENT_SRCS "${src}") + endif() + endforeach() + endforeach() + + # add as a PUBLIC library (if there are source files) or INTERFACE (if header only) + if(COMPONENT_SRCS OR embed_binaries) + add_library(${component} STATIC ${COMPONENT_SRCS}) + set(include_type PUBLIC) + else() + add_library(${component} INTERFACE) # header-only component + set(include_type INTERFACE) + endif() + + # binaries to embed directly in library + spaces2list(COMPONENT_EMBED_FILES) + spaces2list(COMPONENT_EMBED_TXTFILES) + foreach(embed_data ${COMPONENT_EMBED_FILES} ${COMPONENT_EMBED_TXTFILES}) + if(embed_data IN_LIST COMPONENT_EMBED_TXTFILES) + set(embed_type "TEXT") + else() + set(embed_type "BINARY") + endif() + target_add_binary_data("${component}" "${embed_data}" "${embed_type}") + endforeach() + + # add component public includes + foreach(include_dir ${COMPONENT_ADD_INCLUDEDIRS}) + get_filename_component(abs_dir ${include_dir} ABSOLUTE BASE_DIR ${component_dir}) + if(NOT IS_DIRECTORY ${abs_dir}) + message(FATAL_ERROR "${CMAKE_CURRENT_LIST_FILE}: " + "COMPONENT_ADD_INCLUDEDIRS entry '${include_dir}' not found") + endif() + target_include_directories(${component} ${include_type} ${abs_dir}) + endforeach() + + # add component private includes + foreach(include_dir ${COMPONENT_PRIV_INCLUDEDIRS}) + if(${include_type} STREQUAL INTERFACE) + message(FATAL_ERROR "${CMAKE_CURRENT_LIST_FILE} " + "sets no component source files but sets COMPONENT_PRIV_INCLUDEDIRS") + endif() + + get_filename_component(abs_dir ${include_dir} ABSOLUTE BASE_DIR ${component_dir}) + if(NOT IS_DIRECTORY ${abs_dir}) + message(FATAL_ERROR "${CMAKE_CURRENT_LIST_FILE}: " + "COMPONENT_PRIV_INCLUDEDIRS entry '${include_dir}' does not exist") + endif() + target_include_directories(${component} PRIVATE ${abs_dir}) + endforeach() +endfunction() + +function(register_config_only_component) + get_filename_component(component_dir ${CMAKE_CURRENT_LIST_FILE} DIRECTORY) + get_filename_component(component ${component_dir} NAME) + + # No-op for now... +endfunction() + +function(add_component_dependencies target dep dep_type) + get_target_property(target_type ${target} TYPE) + get_target_property(target_imported ${target} IMPORTED) + + if(${target_type} STREQUAL STATIC_LIBRARY OR ${target_type} STREQUAL EXECUTABLE) + if(TARGET ${dep}) + # Add all compile options exported by dep into target + target_include_directories(${target} ${dep_type} + $) + target_compile_definitions(${target} ${dep_type} + $) + target_compile_options(${target} ${dep_type} + $) + endif() + 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) + set(COMPONENT_LIBRARIES "${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}") + +endfunction() diff --git a/tools/cmake/convert_to_cmake.py b/tools/cmake/convert_to_cmake.py new file mode 100755 index 000000000..82e697171 --- /dev/null +++ b/tools/cmake/convert_to_cmake.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python +# +# Command line tool to convert simple ESP-IDF Makefile & component.mk files to +# CMakeLists.txt files +# +import argparse +import subprocess +import re +import os.path +import glob +import sys + +debug = False + +def get_make_variables(path, makefile="Makefile", expected_failure=False, variables={}): + """ + Given the path to a Makefile of some kind, return a dictionary of all variables defined in this Makefile + + Uses 'make' to parse the Makefile syntax, so we don't have to! + + Overrides IDF_PATH= to avoid recursively evaluating the entire project Makefile structure. + """ + variable_setters = [ ("%s=%s" % (k,v)) for (k,v) in variables.items() ] + + cmdline = ["make", "-rpn", "-C", path, "-f", makefile ] + variable_setters + if debug: + print("Running %s..." % (" ".join(cmdline))) + + p = subprocess.Popen(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + (output, stderr) = p.communicate("\n") + + if (not expected_failure) and p.returncode != 0: + raise RuntimeError("Unexpected make failure, result %d" % p.returncode) + + if debug: + print("Make stdout:") + print(output) + print("Make stderr:") + print(stderr) + + next_is_makefile = False # is the next line a makefile variable? + result = {} + BUILT_IN_VARS = set(["MAKEFILE_LIST", "SHELL", "CURDIR", "MAKEFLAGS"]) + + for line in output.decode().split("\n"): + if line.startswith("# makefile"): # this line appears before any variable defined in the makefile itself + next_is_makefile = True + elif next_is_makefile: + next_is_makefile = False + m = re.match(r"(?P[^ ]+) :?= (?P.+)", line) + if m is not None: + if not m.group("var") in BUILT_IN_VARS: + result[m.group("var")] = m.group("val").strip() + + return result + +def get_component_variables(project_path, component_path): + make_vars = get_make_variables(component_path, + os.path.join(os.environ["IDF_PATH"], + "make", + "component_wrapper.mk"), + expected_failure=True, + variables = { + "COMPONENT_MAKEFILE" : os.path.join(component_path, "component.mk"), + "COMPONENT_NAME" : os.path.basename(component_path), + "PROJECT_PATH": project_path, + }) + + if "COMPONENT_OBJS" in make_vars: # component.mk specifies list of object files + # Convert to sources + def find_src(obj): + obj = os.path.splitext(obj)[0] + for ext in [ "c", "cpp", "S" ]: + if os.path.exists(os.path.join(component_path, obj) + "." + ext): + return obj + "." + ext + print("WARNING: Can't find source file for component %s COMPONENT_OBJS %s" % (component_path, obj)) + return None + + srcs = [] + for obj in make_vars["COMPONENT_OBJS"].split(" "): + src = find_src(obj) + if src is not None: + srcs.append(src) + make_vars["COMPONENT_SRCS"] = " ".join(srcs) + else: # Use COMPONENT_SRCDIRS + make_vars["COMPONENT_SRCDIRS"] = make_vars.get("COMPONENT_SRCDIRS", ".") + + make_vars["COMPONENT_ADD_INCLUDEDIRS"] = make_vars.get("COMPONENT_ADD_INCLUDEDIRS", "include") + + return make_vars + + +def convert_project(project_path): + if not os.path.exists(project_path): + raise RuntimeError("Project directory '%s' not found" % project_path) + if not os.path.exists(os.path.join(project_path, "Makefile")): + raise RuntimeError("Directory '%s' doesn't contain a project Makefile" % project_path) + + project_cmakelists = os.path.join(project_path, "CMakeLists.txt") + if os.path.exists(project_cmakelists): + raise RuntimeError("This project already has a CMakeLists.txt file") + + project_vars = get_make_variables(project_path, expected_failure=True) + if not "PROJECT_NAME" in project_vars: + raise RuntimeError("PROJECT_NAME does not appear to be defined in IDF project Makefile at %s" % project_path) + + component_paths = project_vars["COMPONENT_PATHS"].split(" ") + + # "main" component is made special in cmake, so extract it from the component_paths list + try: + main_component_path = [ p for p in component_paths if os.path.basename(p) == "main" ][0] + if debug: + print("Found main component %s" % main_component_path) + main_vars = get_component_variables(project_path, main_component_path) + except IndexError: + print("WARNING: Project has no 'main' component, but CMake-based system requires at least one file in MAIN_SRCS...") + main_vars = { "COMPONENT_SRCS" : ""} # dummy for MAIN_SRCS + + # Remove main component from list of components we're converting to cmake + component_paths = [ p for p in component_paths if os.path.basename(p) != "main" ] + + # Convert components as needed + for p in component_paths: + convert_component(project_path, p) + + # Look up project variables before we start writing the file, so nothing + # is created if there is an error + + main_srcs = main_vars["COMPONENT_SRCS"].split(" ") + # convert from component-relative to absolute paths + main_srcs = [ os.path.normpath(os.path.join(main_component_path, m)) for m in main_srcs ] + # convert to make relative to the project directory + main_srcs = [ os.path.relpath(m, project_path) for m in main_srcs ] + + project_name = project_vars["PROJECT_NAME"] + + # Generate the project CMakeLists.txt file + with open(project_cmakelists, "w") as f: + f.write(""" +# (Automatically converted from project Makefile by convert_to_cmake.py.) + +# The following four 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) + +""") + f.write("set(MAIN_SRCS %s)\n" % " ".join(main_srcs)) + f.write(""" +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +""") + f.write("project(%s)\n" % project_name) + + print("Converted project %s" % project_cmakelists) + +def convert_component(project_path, component_path): + if debug: + print("Converting %s..." % (component_path)) + cmakelists_path = os.path.join(component_path, "CMakeLists.txt") + if os.path.exists(cmakelists_path): + print("Skipping already-converted component %s..." % cmakelists_path) + return + v = get_component_variables(project_path, component_path) + + # Look up all the variables before we start writing the file, so it's not + # created if there's an erro + component_srcs = v.get("COMPONENT_SRCS", None) + component_srcdirs = None + if component_srcs is not None: + # see if we should be using COMPONENT_SRCS or COMPONENT_SRCDIRS, if COMPONENT_SRCS is everything in SRCDIRS + component_allsrcs = [] + for d in v.get("COMPONENT_SRCDIRS", "").split(" "): + component_allsrcs += glob.glob(os.path.normpath(os.path.join(component_path, d, "*.[cS]"))) + component_allsrcs += glob.glob(os.path.normpath(os.path.join(component_path, d, "*.cpp"))) + abs_component_srcs = [os.path.normpath(os.path.join(component_path, p)) for p in component_srcs.split(" ")] + if set(component_allsrcs) == set(abs_component_srcs): + component_srcdirs = v.get("COMPONENT_SRCDIRS") + + component_add_includedirs = v["COMPONENT_ADD_INCLUDEDIRS"] + cflags = v.get("CFLAGS", None) + + with open(cmakelists_path, "w") as f: + f.write("set(COMPONENT_ADD_INCLUDEDIRS %s)\n\n" % component_add_includedirs) + + f.write("# Edit following two lines to set component requirements (see docs)\n") + f.write("set(COMPONENT_REQUIRES "")\n") + f.write("set(COMPONENT_PRIV_REQUIRES "")\n\n") + + if component_srcdirs is not None: + f.write("set(COMPONENT_SRCDIRS %s)\n\n" % component_srcdirs) + f.write("register_component()\n") + elif component_srcs is not None: + f.write("set(COMPONENT_SRCS %s)\n\n" % component_srcs) + f.write("register_component()\n") + else: + f.write("register_config_only_component()\n") + if cflags is not None: + f.write("component_compile_options(%s)\n" % cflags) + + print("Converted %s" % cmakelists_path) + + +def main(): + global debug + + parser = argparse.ArgumentParser(description='convert_to_cmake.py - ESP-IDF Project Makefile to CMakeLists.txt converter', prog='convert_to_cmake') + + parser.add_argument('--debug', help='Display debugging output', + action='store_true') + + parser.add_argument('project', help='Path to project to convert (defaults to CWD)', default=os.getcwd(), metavar='project path', nargs='?') + + args = parser.parse_args() + debug = args.debug + print("Converting %s..." % args.project) + convert_project(args.project) + + +if __name__ == "__main__": + main() diff --git a/tools/cmake/crosstool_version_check.cmake b/tools/cmake/crosstool_version_check.cmake new file mode 100644 index 000000000..d572a82a7 --- /dev/null +++ b/tools/cmake/crosstool_version_check.cmake @@ -0,0 +1,32 @@ +# Function to check the toolchain used the expected version +# of crosstool, and warn otherwise + +set(ctng_version_warning "Check Getting Started documentation or proceed at own risk.") + +function(gcc_version_check expected_gcc_version) + if(NOT "${CMAKE_C_COMPILER_VERSION}" STREQUAL "${expected_gcc_version}") + message(WARNING "Xtensa toolchain ${CMAKE_C_COMPILER} version ${CMAKE_C_COMPILER_VERSION} " + "is not the supported version ${expected_gcc_version}. ${ctng_version_warning}") + endif() +endfunction() + +function(crosstool_version_check expected_ctng_version) + execute_process( + COMMAND ${CMAKE_C_COMPILER} -v + ERROR_VARIABLE toolchain_stderr + OUTPUT_QUIET) + + string(REGEX MATCH "crosstool-ng-[0-9a-g\\.-]+" ctng_version "${toolchain_stderr}") + string(REPLACE "crosstool-ng-" "" ctng_version "${ctng_version}") + # We use FIND to match version instead of STREQUAL because some toolchains are built + # with longer git hash strings than others. This will match any version which starts with + # the expected version string. + string(FIND "${ctng_version}" "${expected_ctng_version}" found_expected_version) + if(NOT ctng_version) + message(WARNING "Xtensa toolchain ${CMAKE_C_COMPILER} does not appear to be built with crosstool-ng. " + "${ctng_version_warning}") + elseif(found_expected_version EQUAL -1) + message(WARNING "Xtensa toolchain ${CMAKE_C_COMPILER} crosstool-ng version ${ctng_version} " + "doesn't match supported version ${expected_ctng_version}. ${ctng_version_warning}") + endif() +endfunction() diff --git a/tools/cmake/git_submodules.cmake b/tools/cmake/git_submodules.cmake new file mode 100644 index 000000000..09098b24a --- /dev/null +++ b/tools/cmake/git_submodules.cmake @@ -0,0 +1,61 @@ +find_package(Git) + +if(NOT GIT_FOUND) + message(WARNING "Git executable was not found. Git submodule checks will not be executed. " + "If you have any build issues at all, start by adding git executable to the PATH and " + "rerun cmake to not see this warning again.") + + function(git_submodule_check root_path) + # no-op + endfunction() +else() + + function(git_submodule_check root_path) + + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule status + WORKING_DIRECTORY ${root_path} + OUTPUT_VARIABLE submodule_status + ) + + # git submodule status output not guaranteed to be stable, + # may need to check GIT_VERSION_STRING and do some fiddling in the + # future... + + lines2list(submodule_status) + + foreach(line ${submodule_status}) + string(REGEX MATCH "(.)[0-9a-f]+ ([^\( ]+) ?" _ignored "${line}") + set(status "${CMAKE_MATCH_1}") + set(submodule_path "${CMAKE_MATCH_2}") + + if("${status}" STREQUAL "-") # missing submodule + message(STATUS "Initialising new submodule ${submodule_path}...") + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive ${submodule_path} + WORKING_DIRECTORY ${root_path} + RESULT_VARIABLE git_result + ) + if(git_result) + message(FATAL_ERROR "Git submodule init failed for ${submodule_path}") + endif() + + elseif(NOT "${status}" STREQUAL " ") + message(WARNING "Git submodule ${submodule_path} is out of date. " + "Run 'git submodule update --init --recursive' to fix.") + endif() + + # Force a re-run of cmake if the submodule's .git file changes or is changed (ie accidental deinit) + get_filename_component(submodule_abs_path ${submodule_path} ABSOLUTE BASE_DIR ${root_path}) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${submodule_abs_path}/.git) + # same if the HEAD file in the submodule's directory changes (ie commit changes). + # This will at least print the 'out of date' warning + set(submodule_head "${root_path}/.git/modules/${submodule_path}/HEAD") + if(EXISTS "${submodule_head}") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${submodule_head}) + endif() + + endforeach() + endfunction() + +endif() diff --git a/tools/cmake/idf_functions.cmake b/tools/cmake/idf_functions.cmake new file mode 100644 index 000000000..b8c0f221d --- /dev/null +++ b/tools/cmake/idf_functions.cmake @@ -0,0 +1,202 @@ +# Some IDF-specific functions and functions + +include(crosstool_version_check) + +# +# Set some variables used by rest of the build +# +# 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 "") + + # Commmon components, required by every component in the build + # + set_default(COMPONENT_REQUIRES_COMMON "cxx esp32 newlib freertos heap log soc") + + # PROJECT_PATH has the path to the IDF project (top-level cmake directory) + # + # (cmake calls this CMAKE_SOURCE_DIR, keeping old name for compatibility.) + set(PROJECT_PATH "${CMAKE_SOURCE_DIR}") + + # Note: Unlike older build system, "main" is no longer a component. See build docs for details. + set_default(COMPONENT_DIRS "${PROJECT_PATH}/components ${EXTRA_COMPONENT_DIRS} ${IDF_PATH}/components") + spaces2list(COMPONENT_DIRS) + + spaces2list(COMPONENTS) + + # Tell cmake to drop executables in the top-level build dir + set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}") + + # path to idf.py tool + set(IDFTOOL ${PYTHON} "${IDF_PATH}/tools/idf.py") +endmacro() + +# Add all the IDF global compiler & preprocessor options +# (applied to all components). Some are config-dependent +# +# 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) + else() + add_compile_options(-Og) + endif() + + add_c_compile_options(-std=gnu99) + + add_cxx_compile_options(-std=gnu++11 -fno-rtti) + + if(CONFIG_CXX_EXCEPTIONS) + add_cxx_compile_options(-fexceptions) + else() + add_cxx_compile_options(-fno-exceptions) + endif() + + # Default compiler configuration + add_compile_options(-ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -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 + ) + + # Stack protection + if(NOT BOOTLOADER_BUILD) + if(CONFIG_STACK_CHECK_NORM) + add_compile_options(-fstack-protector) + elseif(CONFIG_STACK_CHECK_STRONG) + add_compile_options(-fstack-protector-strong) + elseif(CONFIG_STACK_CHECK_ALL) + add_compile_options(-fstack-protector-all) + endif() + endif() + + if(CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED) + add_definitions(-DNDEBUG) + 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() + +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() + + # Check toolchain is configured properly in cmake + if(NOT ( ${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${CMAKE_C_COMPILER} MATCHES xtensa)) + message(FATAL_ERROR "Internal error, toolchain has not been set correctly by project " + "(or an invalid CMakeCache.txt file has been generated somehow)") + endif() + + # + # Warn if the toolchain version doesn't match + # + # TODO: make these platform-specific for diff toolchains + gcc_version_check("5.2.0") + crosstool_version_check("1.22.0-80-g6c4433a") + +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) + + spaces2list(MAIN_SRCS) + add_executable(${exe_target} "${MAIN_SRCS}") + + 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 +# +# Set global IDF_VER to the git revision of ESP-IDF. +# +# Running git_describe() here automatically triggers rebuilds +# if the ESP-IDF git version changes +function(idf_get_git_revision) + git_describe(IDF_VER "${IDF_PATH}") + add_definitions(-DIDF_VER=\"${IDF_VER}\") + git_submodule_check("${IDF_PATH}") + set(IDF_VER ${IDF_VER} PARENT_SCOPE) +endfunction() diff --git a/tools/cmake/kconfig.cmake b/tools/cmake/kconfig.cmake new file mode 100644 index 000000000..040103575 --- /dev/null +++ b/tools/cmake/kconfig.cmake @@ -0,0 +1,166 @@ +include(ExternalProject) + +macro(kconfig_set_variables) + set(CONFIG_DIR ${CMAKE_BINARY_DIR}/config) + set_default(SDKCONFIG ${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 + find_program(WINPTY winpty) + 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}") + set(kconfigs) + set(kconfigs_projbuild) + + # Find Kconfig and Kconfig.projbuild for each component as applicable + # if any of these change, cmake should rerun + foreach(dir ${BUILD_COMPONENT_PATHS} "${CMAKE_SOURCE_DIR}/main") + file(GLOB kconfig "${dir}/Kconfig") + if(kconfig) + set(kconfigs "${kconfigs} ${kconfig}") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${kconfig}) + endif() + file(GLOB kconfig ${dir}/Kconfig.projbuild) + if(kconfig) + set(kconfigs_projbuild "${kconfigs_projbuild} ${kconfig}") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${kconfig}) + endif() + endforeach() + + if(EXISTS ${SDKCONFIG_DEFAULTS}) + set(defaults_arg --defaults "${SDKCONFIG_DEFAULTS}") + endif() + + # Set these in the parent scope, so that they can be written to project_description.json + set(kconfigs "${kconfigs}") + set(COMPONENT_KCONFIGS "${kconfigs}" PARENT_SCOPE) + set(COMPONENT_KCONFIGS_PROJBUILD "${kconfigs_projbuild}" PARENT_SCOPE) + + set(confgen_basecommand + ${PYTHON} ${IDF_PATH}/tools/kconfig_new/confgen.py + --kconfig ${ROOT_KCONFIG} + --config ${SDKCONFIG} + ${defaults_arg} + --create-config-if-missing + --env "COMPONENT_KCONFIGS=${kconfigs}" + --env "COMPONENT_KCONFIGS_PROJBUILD=${kconfigs_projbuild}" + --env "IDF_CMAKE=y") + + # Generate the menuconfig target (uses C-based mconf-idf tool, either prebuilt or via mconf-idf target above) + add_custom_target(menuconfig + ${menuconfig_depends} + # create any missing config file, with defaults if necessary + COMMAND ${confgen_basecommand} --output config ${SDKCONFIG} + COMMAND ${CMAKE_COMMAND} -E env + "COMPONENT_KCONFIGS=${kconfigs}" + "COMPONENT_KCONFIGS_PROJBUILD=${kconfigs_projbuild}" + "IDF_CMAKE=y" + "KCONFIG_CONFIG=${SDKCONFIG}" + ${MCONF} ${ROOT_KCONFIG} + VERBATIM + USES_TERMINAL) + + # Custom target to run confserver.py from the build tool + add_custom_target(confserver + COMMAND ${CMAKE_COMMAND} -E env + "COMPONENT_KCONFIGS=${kconfigs}" + "COMPONENT_KCONFIGS_PROJBUILD=${kconfigs_projbuild}" + ${IDF_PATH}/tools/kconfig_new/confserver.py --kconfig ${IDF_PATH}/Kconfig --config ${SDKCONFIG} + VERBATIM + USES_TERMINAL) + + # Generate configuration output via confgen.py + # makes sdkconfig.h and skdconfig.cmake + # + # This happens during the cmake run not during the build + execute_process(COMMAND ${confgen_basecommand} + --output header ${SDKCONFIG_HEADER} + --output cmake ${SDKCONFIG_CMAKE} + --output json ${SDKCONFIG_JSON} + --output json_menus ${KCONFIG_JSON_MENUS} + RESULT_VARIABLE config_result) + if(config_result) + message(FATAL_ERROR "Failed to run confgen.py (${confgen_basecommand}). Error ${config_result}") + endif() + + # When sdkconfig file changes in the future, trigger a cmake run + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${SDKCONFIG}") + + # Ditto if either of the generated files are missing/modified (this is a bit irritating as it means + # you can't edit these manually without them being regenerated, but I don't know of a better way...) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${SDKCONFIG_HEADER}") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${SDKCONFIG_CMAKE}") + + # Or if the config generation tool changes + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${IDF_PATH}/tools/kconfig_new/confgen.py") + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${IDF_PATH}/tools/kconfig_new/kconfiglib.py") + + set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY + ADDITIONAL_MAKE_CLEAN_FILES + "${SDKCONFIG_HEADER}" "${SDKCONFIG_CMAKE}") + +endfunction() diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake new file mode 100644 index 000000000..e914ac1da --- /dev/null +++ b/tools/cmake/project.cmake @@ -0,0 +1,145 @@ +# Designed to be included from an IDF app's CMakeLists.txt file +# +cmake_minimum_required(VERSION 3.5) + +# 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 + # can infer it relative to tools/cmake directory if it's not set. + get_filename_component(IDF_PATH "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE) +endif() +file(TO_CMAKE_PATH "${IDF_PATH}" IDF_PATH) +set(ENV{IDF_PATH} ${IDF_PATH}) + + +# +# 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(kconfig) +include(git_submodules) +include(idf_functions) + +set_default(PYTHON "python") + +# 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) + # Set global variables used by rest of the build + idf_set_global_variables() + + # Establish dependencies for components in the build + # (this happens before we even generate config...) + if(COMPONENTS) + # Make sure if an explicit list of COMPONENTS is given, it contains the "common" component requirements + # (otherwise, if COMPONENTS is empty then all components will be included in the build.) + set(COMPONENTS "${COMPONENTS} ${COMPONENT_REQUIRES_COMMON}") + endif() + execute_process(COMMAND "${CMAKE_COMMAND}" + -D "COMPONENTS=${COMPONENTS}" + -D "DEPENDENCIES_FILE=${CMAKE_BINARY_DIR}/component_depends.cmake" + -D "COMPONENT_DIRS=${COMPONENT_DIRS}" + -D "BOOTLOADER_BUILD=${BOOTLOADER_BUILD}" + -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: + # 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}") + + kconfig_set_variables() + + kconfig_process_config() + + # Include sdkconfig.cmake so rest of the build knows the configuration + include(${SDKCONFIG_CMAKE}) + + # Now the configuration is loaded, set the toolchain appropriately + # + # TODO: support more toolchains than just ESP32 + set(CMAKE_TOOLCHAIN_FILE $ENV{IDF_PATH}/tools/cmake/toolchain-esp32.cmake) + + # Declare the actual cmake-level project + _project(${name} ASM C CXX) + + # generate compile_commands.json (needs to come after project) + set(CMAKE_EXPORT_COMPILE_COMMANDS 1) + + # Verify the environment is configured correctly + idf_verify_environment() + + # Add some idf-wide definitions + idf_set_global_compiler_options() + + # 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}") + + # 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) + add_subdirectory(${COMPONENT_PATH} ${COMPONENT_NAME}) + endforeach() + unset(COMPONENT_NAME) + unset(COMPONENT_PATH) + + # + # Add the app executable to the build (has name of PROJECT.elf) + # + idf_add_executable() + + # 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() + +endmacro() diff --git a/tools/cmake/project_description.json.in b/tools/cmake/project_description.json.in new file mode 100644 index 000000000..878dce3b3 --- /dev/null +++ b/tools/cmake/project_description.json.in @@ -0,0 +1,18 @@ +{ + "project_name": "${PROJECT_NAME}", + "project_path": "${PROJECT_PATH}", + "build_dir": "${CMAKE_BINARY_DIR}", + "config_file": "${SDKCONFIG}", + "config_defaults": "${SDKCONFIG_DEFAULTS}", + "app_elf": "${PROJECT_NAME}.elf", + "app_bin": "${PROJECT_NAME}.bin", + "git_revision": "${IDF_VER}", + "phy_data_partition": "${CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION}", + "monitor_baud" : "${CONFIG_MONITOR_BAUD}", + "config_environment" : { + "COMPONENT_KCONFIGS" : "${COMPONENT_KCONFIGS}", + "COMPONENT_KCONFIGS_PROJBUILD" : "${COMPONENT_KCONFIGS_PROJBUILD}" + }, + "build_components" : ${build_components_json}, + "build_component_paths" : ${build_component_paths_json} +} diff --git a/tools/cmake/run_cmake_lint.sh b/tools/cmake/run_cmake_lint.sh new file mode 100755 index 000000000..a21bc1168 --- /dev/null +++ b/tools/cmake/run_cmake_lint.sh @@ -0,0 +1,25 @@ +#!/bin/bash +# +# Run cmakelint on all cmake files in IDF_PATH (except third party) +# +# cmakelint: https://github.com/richq/cmake-lint +# +# NOTE: This script makes use of features in (currently unreleased) +# cmakelint >1.4. Install directly from github as follows: +# +# pip install https://github.com/richq/cmake-lint/archive/058c6c0ed2536.zip +# + +if [ -z "${IDF_PATH}" ]; then + echo "IDF_PATH variable needs to be set" + exit 3 +fi + +cd "$IDF_PATH" + +# Only list the "main" IDF repo, don't check any files in submodules (which may contain +# third party CMakeLists.txt) + git ls-tree --full-tree --name-only -r HEAD | grep -v "/third_party/" | grep "^CMakeLists.txt$\|\.cmake$" \ + | xargs cmakelint --linelength=120 --spaces=4 + + diff --git a/tools/cmake/scripts/data_file_embed_asm.cmake b/tools/cmake/scripts/data_file_embed_asm.cmake new file mode 100644 index 000000000..291f9fea2 --- /dev/null +++ b/tools/cmake/scripts/data_file_embed_asm.cmake @@ -0,0 +1,83 @@ +# +# Convert a file (text or binary) into an assembler source file suitable +# for gcc. Designed to replicate 'objcopy' with more predictable +# naming, and supports appending a null byte for embedding text as +# a string. +# +# Designed to be run as a script with "cmake -P" +# +# Set variables DATA_FILE, SOURCE_FILE, FILE_TYPE when running this. +# +# If FILE_TYPE is set to TEXT, a null byte is appended to DATA_FILE's contents +# before SOURCE_FILE is created. +# +# If FILE_TYPE is unset (or any other value), DATA_FILE is copied +# verbatim into SOURCE_FILE. +# +# +if(NOT DATA_FILE) + message(FATAL_ERROR "DATA_FILE for converting must be specified") +endif() + +if(NOT SOURCE_FILE) + message(FATAL_ERROR "SOURCE_FILE destination must be specified") +endif() + +file(READ "${DATA_FILE}" data HEX) + +string(LENGTH "${data}" data_len) +math(EXPR data_len "${data_len} / 2") # 2 hex bytes per byte + +if(FILE_TYPE STREQUAL "TEXT") + set(data "${data}00") # null-byte termination +endif() + +## Convert string of raw hex bytes to lines of hex bytes as gcc .byte expressions +string(REGEX REPLACE "................................" ".byte \\0\n" data "${data}") # 16 bytes per line +string(REGEX REPLACE "[^\n]+$" ".byte \\0\n" data "${data}") # last line +string(REGEX REPLACE "[0-9a-f][0-9a-f]" "0x\\0, " data "${data}") # hex formatted C bytes +string(REGEX REPLACE ", \n" "\n" data "${data}") # trim the last comma + +## Come up with C-friendly symbol name based on source file +get_filename_component(source_filename "${DATA_FILE}" NAME) +string(MAKE_C_IDENTIFIER "${source_filename}" varname) + +function(append str) + file(APPEND "${SOURCE_FILE}" "${str}") +endfunction() + +function(append_line str) + append("${str}\n") +endfunction() + +function(append_identifier symbol) +append_line("\n.global ${symbol}") +append("${symbol}:") +if(${ARGC} GREATER 1) # optional comment + append(" /* ${ARGV1} */") +endif() +append("\n") +endfunction() + +file(WRITE "${SOURCE_FILE}" "/*") +append_line(" * Data converted from ${DATA_FILE}") +if(FILE_TYPE STREQUAL "TEXT") + append_line(" * (null byte appended)") +endif() +append_line(" */") + +append_line(".data") +append_line(".section .rodata.embedded") +append_identifier("${varname}") +append_identifier("_binary_${varname}_start" "for objcopy compatibility") +append("${data}") + +append_identifier("_binary_${varname}_end" "for objcopy compatibility") + +append_line("") +if(FILE_TYPE STREQUAL "TEXT") + append_identifier("${varname}_length" "not including null byte") +else() + append_identifier("${varname}_length") +endif() +append_line(".word ${data_len}") diff --git a/tools/cmake/scripts/expand_requirements.cmake b/tools/cmake/scripts/expand_requirements.cmake new file mode 100644 index 000000000..a825a7647 --- /dev/null +++ b/tools/cmake/scripts/expand_requirements.cmake @@ -0,0 +1,222 @@ +# expand_requires.cmake is a utility cmake script to expand component requirements early in the build, +# before the components are ready to be included. +# +# Parameters: +# - COMPONENTS = Space-separated list of initial components to include in the build. +# Can be empty, in which case all components are in the build. +# - DEPENDENCIES_FILE = Path of generated cmake file which will contain the expanded dependencies for these +# components. +# - COMPONENT_DIRS = List of paths to search for all components. +# - DEBUG = Set -DDEBUG=1 to debug component lists in the build. +# +# If successful, DEPENDENCIES_FILE can be expanded to set BUILD_COMPONENTS & BUILD_COMPONENT_PATHS with all +# components required for the build, and the get_component_requirements() function to return each component's +# recursively expanded requirements. +# +# TODO: Error out if a component requirement is missing +cmake_minimum_required(VERSION 3.5) +include("${IDF_PATH}/tools/cmake/utilities.cmake") + +if(NOT DEPENDENCIES_FILE) + message(FATAL_ERROR "DEPENDENCIES_FILE must be set.") +endif() + +if(NOT COMPONENT_DIRS) + message(FATAL_ERROR "COMPONENT_DIRS variable must be set") +endif() +spaces2list(COMPONENT_DIRS) + +function(debug message) + if(DEBUG) + message(STATUS "${message}") + endif() +endfunction() + +# Dummy register_component used to save requirements variables as global properties, for later expansion +# +# (expand_component_requirements() includes the component CMakeLists.txt, which then sets its component variables, +# calls this dummy macro, and immediately exits again.) +macro(register_component) + spaces2list(COMPONENT_REQUIRES) + set_property(GLOBAL PROPERTY "${COMPONENT}_REQUIRES" "${COMPONENT_REQUIRES}") + spaces2list(COMPONENT_PRIV_REQUIRES) + set_property(GLOBAL PROPERTY "${COMPONENT}_PRIV_REQUIRES" "${COMPONENT_PRIV_REQUIRES}") + + # This is tricky: we override register_component() so it returns out of the component CMakeLists.txt + # (as we're declaring it as a macro not a function, so it doesn't have its own scope.) + # + # This means no targets are defined, and the component expansion ends early. + return() +endmacro() + +macro(register_config_only_component) + register_component() +endmacro() + +# Given a component name (find_name) and a list of component paths (component_paths), +# return the path to the component in 'variable' +# +# Fatal error is printed if the component is not found. +function(find_component_path find_name component_paths variable) + foreach(path ${component_paths}) + get_filename_component(name "${path}" NAME) + if("${name}" STREQUAL "${find_name}") + set("${variable}" "${path}" PARENT_SCOPE) + return() + endif() + endforeach() + # TODO: find a way to print the dependency chain that lead to this not-found component + message(WARNING "Required component ${find_name} is not found in any of the provided COMPONENT_DIRS") +endfunction() + +# components_find_all: Search 'component_dirs' for components and return them +# as a list of names in 'component_names' and a list of full paths in +# 'component_paths' +# +# component_paths contains only unique component names. Directories +# earlier in the component_dirs list take precedence. +function(components_find_all component_dirs component_paths component_names) + # component_dirs entries can be files or lists of files + set(paths "") + set(names "") + + # start by expanding the component_dirs list with all subdirectories + foreach(dir ${component_dirs}) + # Iterate any subdirectories for values + file(GLOB subdirs LIST_DIRECTORIES true "${dir}/*") + foreach(subdir ${subdirs}) + set(component_dirs "${component_dirs};${subdir}") + endforeach() + endforeach() + + # Look for a component in each component_dirs entry + foreach(dir ${component_dirs}) + debug("Looking for CMakeLists.txt in ${dir}") + file(GLOB component "${dir}/CMakeLists.txt") + if(component) + debug("CMakeLists.txt file ${component}") + get_filename_component(component "${component}" DIRECTORY) + get_filename_component(name "${component}" NAME) + if(NOT name IN_LIST names) + set(names "${names};${name}") + set(paths "${paths};${component}") + endif() + + else() # no CMakeLists.txt file + # test for legacy component.mk and warn + file(GLOB legacy_component "${dir}/component.mk") + if(legacy_component) + get_filename_component(legacy_component "${legacy_component}" DIRECTORY) + message(WARNING "Component ${legacy_component} contains old-style component.mk but no CMakeLists.txt. " + "Component will be skipped.") + endif() + endif() + + endforeach() + + set(${component_paths} ${paths} PARENT_SCOPE) + set(${component_names} ${names} PARENT_SCOPE) +endfunction() + +# expand_component_requirements: Recursively expand a component's requirements, +# setting global properties BUILD_COMPONENTS & BUILD_COMPONENT_PATHS and +# also invoking the components to call register_component() above, +# which will add per-component global properties with dependencies, etc. +function(expand_component_requirements component) + get_property(build_components GLOBAL PROPERTY BUILD_COMPONENTS) + if(${component} IN_LIST build_components) + return() # already added this component + endif() + + find_component_path("${component}" "${ALL_COMPONENT_PATHS}" component_path) + debug("Expanding dependencies of ${component} @ ${component_path}") + if(NOT component_path) + set_property(GLOBAL APPEND PROPERTY COMPONENTS_NOT_FOUND ${component}) + return() + endif() + + # include the component CMakeLists.txt to expand its properties + # into the global cache (via register_component(), above) + unset(COMPONENT_REQUIRES) + unset(COMPONENT_PRIV_REQUIRES) + set(COMPONENT ${component}) + include(${component_path}/CMakeLists.txt) + + set_property(GLOBAL APPEND PROPERTY BUILD_COMPONENT_PATHS ${component_path}) + set_property(GLOBAL APPEND PROPERTY BUILD_COMPONENTS ${component}) + + get_property(requires GLOBAL PROPERTY "${component}_REQUIRES") + get_property(requires_priv GLOBAL PROPERTY "${component}_PRIV_REQUIRES") + foreach(req ${requires} ${requires_priv}) + expand_component_requirements(${req}) + endforeach() +endfunction() + + +# Main functionality goes here + +# Find every available component in COMPONENT_DIRS, save as ALL_COMPONENT_PATHS and ALL_COMPONENTS +components_find_all("${COMPONENT_DIRS}" ALL_COMPONENT_PATHS ALL_COMPONENTS) + +if(NOT COMPONENTS) + set(COMPONENTS "${ALL_COMPONENTS}") +endif() +spaces2list(COMPONENTS) + +debug("ALL_COMPONENT_PATHS ${ALL_COMPONENT_PATHS}") +debug("ALL_COMPONENTS ${ALL_COMPONENTS}") + +set_property(GLOBAL PROPERTY BUILD_COMPONENTS "") +set_property(GLOBAL PROPERTY BUILD_COMPONENT_PATHS "") +set_property(GLOBAL PROPERTY COMPONENTS_NOT_FOUND "") + +foreach(component ${COMPONENTS}) + debug("Expanding initial component ${component}") + expand_component_requirements(${component}) +endforeach() + +get_property(build_components GLOBAL PROPERTY BUILD_COMPONENTS) +get_property(build_component_paths GLOBAL PROPERTY BUILD_COMPONENT_PATHS) +get_property(not_found GLOBAL PROPERTY COMPONENTS_NOT_FOUND) + +debug("components in build: ${build_components}") +debug("components in build: ${build_component_paths}") +debug("components not found: ${not_found}") + +function(line contents) + file(APPEND "${DEPENDENCIES_FILE}.tmp" "${contents}\n") +endfunction() + +file(WRITE "${DEPENDENCIES_FILE}.tmp" "# Component requirements generated by expand_requirements.cmake\n\n") +line("set(BUILD_COMPONENTS ${build_components})") +line("set(BUILD_COMPONENT_PATHS ${build_component_paths})") +line("") + +line("# get_component_requirements: Generated function to read the dependencies of a given component.") +line("#") +line("# Parameters:") +line("# - component: Name of component") +line("# - var_requires: output variable name. Set to recursively expanded COMPONENT_REQUIRES ") +line("# for this component.") +line("# - var_private_requires: output variable name. Set to recursively expanded COMPONENT_PRIV_REQUIRES ") +line("# for this component.") +line("#") +line("# Throws a fatal error if 'componeont' is not found (indicates a build system problem).") +line("#") +line("function(get_component_requirements component var_requires var_private_requires)") +foreach(build_component ${build_components}) + get_property(reqs GLOBAL PROPERTY "${build_component}_REQUIRES") + get_property(private_reqs GLOBAL PROPERTY "${build_component}_PRIV_REQUIRES") + line(" if(\"\$\{component}\" STREQUAL \"${build_component}\")") + line(" set(\${var_requires} \"${reqs}\" PARENT_SCOPE)") + line(" set(\${var_private_requires} \"${private_reqs}\" PARENT_SCOPE)") + line(" return()") + line(" endif()") +endforeach() + +line(" message(FATAL_ERROR \"Component not found: \${component}\")") +line("endfunction()") + +# only replace DEPENDENCIES_FILE if it has changed (prevents ninja/make build loops.) +execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${DEPENDENCIES_FILE}.tmp" "${DEPENDENCIES_FILE}") +execute_process(COMMAND ${CMAKE_COMMAND} -E remove "${DEPENDENCIES_FILE}.tmp") diff --git a/tools/cmake/scripts/fail.cmake b/tools/cmake/scripts/fail.cmake new file mode 100644 index 000000000..5ceddb3ca --- /dev/null +++ b/tools/cmake/scripts/fail.cmake @@ -0,0 +1,4 @@ +# 'cmake -E' doesn't have a way to fail outright, so run this script +# with 'cmake -P' to fail a build. +message(FATAL_ERROR "Failing the build (see errors on lines above)") + diff --git a/tools/cmake/third_party/GetGitRevisionDescription.cmake b/tools/cmake/third_party/GetGitRevisionDescription.cmake new file mode 100644 index 000000000..6c711bbd4 --- /dev/null +++ b/tools/cmake/third_party/GetGitRevisionDescription.cmake @@ -0,0 +1,133 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ ...]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# +# Updated 2018 Espressif Systems to add _repo_dir argument +# to get revision of other repositories + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +function(get_git_head_revision _refspecvar _hashvar _repo_dir) + set(GIT_PARENT_DIR "${_repo_dir}") + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories + set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") + get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) + if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) + # We have reached the root directory, we are not in git + set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) + return() + endif() + set(GIT_DIR "${GIT_PARENT_DIR}/.git") + endwhile() + # check if this is a submodule + if(NOT IS_DIRECTORY ${GIT_DIR}) + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule}) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE) + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${GIT_DIR}/HEAD") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" + @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) + set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) +endfunction() + +function(git_describe _var _repo_dir) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash "${_repo_dir}") + if(NOT GIT_FOUND) + set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process(COMMAND + "${GIT_EXECUTABLE}" + describe + ${hash} + ${ARGN} + WORKING_DIRECTORY + "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE + res + OUTPUT_VARIABLE + out + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} "${out}" PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var _repo_dir) + git_describe(out "${_repo_dir}" --exact-match ${ARGN}) + set(${_var} "${out}" PARENT_SCOPE) +endfunction() diff --git a/tools/cmake/third_party/GetGitRevisionDescription.cmake.in b/tools/cmake/third_party/GetGitRevisionDescription.cmake.in new file mode 100644 index 000000000..6d8b708ef --- /dev/null +++ b/tools/cmake/third_party/GetGitRevisionDescription.cmake.in @@ -0,0 +1,41 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright Iowa State University 2009-2010. +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/tools/cmake/toolchain-esp32.cmake b/tools/cmake/toolchain-esp32.cmake new file mode 100644 index 000000000..c23fa4cbc --- /dev/null +++ b/tools/cmake/toolchain-esp32.cmake @@ -0,0 +1,7 @@ +set(CMAKE_SYSTEM_NAME Generic) + +set(CMAKE_C_COMPILER xtensa-esp32-elf-gcc) +set(CMAKE_CXX_COMPILER xtensa-esp32-elf-g++) +set(CMAKE_ASM_COMPILER xtensa-esp32-elf-gcc) + +set(CMAKE_EXE_LINKER_FLAGS "-nostdlib" CACHE STRING "Linker Base Flags") diff --git a/tools/cmake/utilities.cmake b/tools/cmake/utilities.cmake new file mode 100644 index 000000000..e1c682c89 --- /dev/null +++ b/tools/cmake/utilities.cmake @@ -0,0 +1,181 @@ +# set_default +# +# Define a variable to a default value if otherwise unset. +# +# Priority for new value is: +# - Existing cmake value (ie set with cmake -D, or already set in CMakeLists) +# - Value of any non-empty environment variable of the same name +# - Default value as provided to function +# +function(set_default variable default_value) + if(NOT ${variable}) + if(DEFINED ENV{${variable}} AND NOT "$ENV{${variable}}" STREQUAL "") + set(${variable} $ENV{${variable}} PARENT_SCOPE) + else() + set(${variable} ${default_value} PARENT_SCOPE) + endif() + endif() +endfunction() + +# spaces2list +# +# Take a variable whose value was space-delimited values, convert to a cmake +# list (semicolon-delimited) +# +# Note: if using this for directories, keeps the issue in place that +# directories can't contain spaces... +# +# TODO: look at cmake separate_arguments, which is quote-aware +function(spaces2list variable_name) + string(REPLACE " " ";" tmp "${${variable_name}}") + set("${variable_name}" "${tmp}" PARENT_SCOPE) +endfunction() + + +# lines2list +# +# Take a variable with multiple lines of output in it, convert it +# to a cmake list (semicolon-delimited), one line per item +# +function(lines2list variable_name) + string(REGEX REPLACE "\r?\n" ";" tmp "${${variable_name}}") + string(REGEX REPLACE ";;" ";" tmp "${tmp}") + set("${variable_name}" "${tmp}" PARENT_SCOPE) +endfunction() + + +# move_if_different +# +# If 'source' has different md5sum to 'destination' (or destination +# does not exist, move it across. +# +# If 'source' has the same md5sum as 'destination', delete 'source'. +# +# Avoids timestamp updates for re-generated files where content hasn't +# changed. +function(move_if_different source destination) + set(do_copy 1) + file(GLOB dest_exists ${destination}) + if(dest_exists) + file(MD5 ${source} source_md5) + file(MD5 ${destination} dest_md5) + if(source_md5 STREQUAL dest_md5) + set(do_copy "") + endif() + endif() + + if(do_copy) + message("Moving ${source} -> ${destination}") + file(RENAME ${source} ${destination}) + else() + message("Not moving ${source} -> ${destination}") + file(REMOVE ${source}) + endif() + +endfunction() + + +# add_compile_options variant for C++ code only +# +# This adds global options, set target properties for +# component-specific flags +function(add_cxx_compile_options) + foreach(option ${ARGV}) + # note: the Visual Studio Generator doesn't support this... + add_compile_options($<$:${option}>) + endforeach() +endfunction() + +# add_compile_options variant for C code only +# +# This adds global options, set target properties for +# component-specific flags +function(add_c_compile_options) + foreach(option ${ARGV}) + # note: the Visual Studio Generator doesn't support this... + add_compile_options($<$:${option}>) + endforeach() +endfunction() + + +# target_add_binary_data adds binary data into the built target, +# by converting it to a generated source file which is then compiled +# to a binary object as part of the build +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") + + add_custom_command(OUTPUT "${embed_srcfile}" + COMMAND "${CMAKE_COMMAND}" + -D "DATA_FILE=${embed_file}" + -D "SOURCE_FILE=${embed_srcfile}" + -D "FILE_TYPE=${embed_type}" + -P "${IDF_PATH}/tools/cmake/scripts/data_file_embed_asm.cmake" + MAIN_DEPENDENCY "${embed_file}" + DEPENDENCIES "${IDF_PATH}/tools/cmake/scripts/data_file_embed_asm.cmake" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") + + set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${embed_srcfile}") + + target_sources("${target}" PRIVATE "${embed_srcfile}") +endfunction() + +macro(include_if_exists path) + if(EXISTS "${path}") + include("${path}") + endif() +endmacro() + +# Append a single line to the file specified +# The line ending is determined by the host OS +function(file_append_line file line) + if(DEFINED ENV{MSYSTEM} OR CMAKE_HOST_WIN32) + set(line_ending "\r\n") + else() # unix + set(line_ending "\n") + endif() + file(READ ${file} existing) + string(FIND ${existing} ${line_ending} last_newline REVERSE) + string(LENGTH ${existing} length) + math(EXPR length "${length}-1") + if(NOT length EQUAL last_newline) # file doesn't end with a newline + file(APPEND "${file}" "${line_ending}") + endif() + file(APPEND "${file}" "${line}${line_ending}") +endfunction() + +# Add one or more linker scripts to the target, including a link-time dependency +# +# Automatically adds a -L search path for the containing directory (if found), +# and then adds -T with the filename only. This allows INCLUDE directives to be +# used to include other linker scripts in the same directory. +function(target_linker_script target) + foreach(scriptfile ${ARGN}) + get_filename_component(abs_script "${scriptfile}" ABSOLUTE) + message(STATUS "Adding linker script ${abs_script}") + + get_filename_component(search_dir "${abs_script}" DIRECTORY) + get_filename_component(scriptname "${abs_script}" NAME) + + get_target_property(link_libraries "${target}" LINK_LIBRARIES) + list(FIND "${link_libraries}" "-L ${search_dir}" found_search_dir) + if(found_search_dir EQUAL "-1") # not already added as a search path + target_link_libraries("${target}" "-L ${search_dir}") + endif() + + target_link_libraries("${target}" "-T ${scriptname}") + + # Note: In ESP-IDF, most targets are libraries and libary LINK_DEPENDS don't propagate to + # executable(s) the library is linked to. This is done manually in components.cmake. + set_property(TARGET "${target}" APPEND PROPERTY LINK_DEPENDS "${abs_script}") + endforeach() +endfunction() + +# Convert a CMake list to a JSON list and store it in a variable +function(make_json_list list variable) + string(REPLACE ";" "\", \"" result "[ \"${list}\" ]") + set("${variable}" "${result}" PARENT_SCOPE) +endfunction() diff --git a/tools/idf.py b/tools/idf.py new file mode 100755 index 000000000..bb55ff59e --- /dev/null +++ b/tools/idf.py @@ -0,0 +1,461 @@ +#!/usr/bin/env python +# +# 'idf.py' is a top-level config/build command line tool for ESP-IDF +# +# You don't have to use idf.py, you can use cmake directly +# (or use cmake in an IDE) +# +# +# +# Copyright 2018 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import sys +import argparse +import os +import os.path +import subprocess +import multiprocessing +import re +import shutil +import json + +class FatalError(RuntimeError): + """ + Wrapper class for runtime errors that aren't caused by bugs in idf.py or the build proces.s + """ + pass + +# Use this Python interpreter for any subprocesses we launch +PYTHON=sys.executable + +# note: os.environ changes don't automatically propagate to child processes, +# you have to pass env=os.environ explicitly anywhere that we create a process +os.environ["PYTHON"]=sys.executable + +# Make flavors, across the various kinds of Windows environments & POSIX... +if "MSYSTEM" in os.environ: # MSYS + MAKE_CMD = "make" + MAKE_GENERATOR = "MSYS Makefiles" +elif os.name == 'nt': # other Windows + MAKE_CMD = "mingw32-make" + MAKE_GENERATOR = "MinGW Makefiles" +else: + MAKE_CMD = "make" + MAKE_GENERATOR = "Unix Makefiles" + +GENERATORS = [ + # ('generator name', 'build command line', 'version command line', 'verbose flag') + ("Ninja", [ "ninja" ], [ "ninja", "--version" ], "-v"), + (MAKE_GENERATOR, [ MAKE_CMD, "-j", str(multiprocessing.cpu_count()+2) ], [ "make", "--version" ], "VERBOSE=1"), + ] +GENERATOR_CMDS = dict( (a[0], a[1]) for a in GENERATORS ) +GENERATOR_VERBOSE = dict( (a[0], a[3]) for a in GENERATORS ) + +def _run_tool(tool_name, args, cwd): + def quote_arg(arg): + " Quote 'arg' if necessary " + if " " in arg and not (arg.startswith('"') or arg.startswith("'")): + return "'" + arg + "'" + return arg + display_args = " ".join(quote_arg(arg) for arg in args) + print("Running %s in directory %s" % (tool_name, quote_arg(cwd))) + print('Executing "%s"...' % display_args) + try: + # Note: we explicitly pass in os.environ here, as we may have set IDF_PATH there during startup + subprocess.check_call(args, env=os.environ, cwd=cwd) + except subprocess.CalledProcessError as e: + raise FatalError("%s failed with exit code %d" % (tool_name, e.returncode)) + + +def check_environment(): + """ + Verify the environment contains the top-level tools we need to operate + + (cmake will check a lot of other things) + """ + if not executable_exists(["cmake", "--version"]): + raise FatalError("'cmake' must be available on the PATH to use idf.py") + # find the directory idf.py is in, then the parent directory of this, and assume this is IDF_PATH + detected_idf_path = os.path.realpath(os.path.join(os.path.dirname(__file__), "..")) + if "IDF_PATH" in os.environ: + set_idf_path = os.path.realpath(os.environ["IDF_PATH"]) + if set_idf_path != detected_idf_path: + print("WARNING: IDF_PATH environment variable is set to %s but idf.py path indicates IDF directory %s. Using the environment variable directory, but results may be unexpected..." + % (set_idf_path, detected_idf_path)) + else: + print("Setting IDF_PATH environment variable: %s" % detected_idf_path) + os.environ["IDF_PATH"] = detected_idf_path + +def executable_exists(args): + try: + subprocess.check_output(args) + return True + except: + return False + +def detect_cmake_generator(): + """ + Find the default cmake generator, if none was specified. Raises an exception if no valid generator is found. + """ + for (generator, _, version_check, _) in GENERATORS: + if executable_exists(version_check): + return generator + raise FatalError("To use idf.py, either the 'ninja' or 'GNU make' build tool must be available in the PATH") + +def _ensure_build_directory(args, always_run_cmake=False): + """Check the build directory exists and that cmake has been run there. + + If this isn't the case, create the build directory (if necessary) and + do an initial cmake run to configure it. + + This function will also check args.generator parameter. If the parameter is incompatible with + the build directory, an error is raised. If the parameter is None, this function will set it to + an auto-detected default generator or to the value already configured in the build directory. + """ + project_dir = args.project_dir + # Verify the project directory + if not os.path.isdir(project_dir): + if not os.path.exists(project_dir): + raise FatalError("Project directory %s does not exist") + else: + raise FatalError("%s must be a project directory") + if not os.path.exists(os.path.join(project_dir, "CMakeLists.txt")): + raise FatalError("CMakeLists.txt not found in project directory %s" % project_dir) + + # Verify/create the build directory + build_dir = args.build_dir + if not os.path.isdir(build_dir): + os.mkdir(build_dir) + cache_path = os.path.join(build_dir, "CMakeCache.txt") + if not os.path.exists(cache_path) or always_run_cmake: + if args.generator is None: + args.generator = detect_cmake_generator() + try: + cmake_args = ["cmake", "-G", args.generator] + if not args.no_warnings: + cmake_args += [ "--warn-uninitialized" ] + if args.no_ccache: + cmake_args += [ "-DCCACHE_DISABLE=1" ] + cmake_args += [ project_dir] + _run_tool("cmake", cmake_args, cwd=args.build_dir) + except: + # don't allow partially valid CMakeCache.txt files, + # to keep the "should I run cmake?" logic simple + if os.path.exists(cache_path): + os.remove(cache_path) + raise + + # Learn some things from the CMakeCache.txt file in the build directory + cache = parse_cmakecache(cache_path) + try: + generator = cache["CMAKE_GENERATOR"] + except KeyError: + generator = detect_cmake_generator() + if args.generator is None: + args.generator = generator # reuse the previously configured generator, if none was given + if generator != args.generator: + raise FatalError("Build is configured for generator '%s' not '%s'. Run 'idf.py fullclean' to start again." + % (generator, args.generator)) + + try: + home_dir = cache["CMAKE_HOME_DIRECTORY"] + if os.path.normcase(os.path.realpath(home_dir)) != os.path.normcase(os.path.realpath(project_dir)): + raise FatalError("Build directory '%s' configured for project '%s' not '%s'. Run 'idf.py fullclean' to start again." + % (build_dir, os.path.realpath(home_dir), os.path.realpath(project_dir))) + except KeyError: + pass # if cmake failed part way, CMAKE_HOME_DIRECTORY may not be set yet + + +def parse_cmakecache(path): + """ + Parse the CMakeCache file at 'path'. + + Returns a dict of name:value. + + CMakeCache entries also each have a "type", but this is currently ignored. + """ + result = {} + with open(path) as f: + for line in f: + # cmake cache lines look like: CMAKE_CXX_FLAGS_DEBUG:STRING=-g + # groups are name, type, value + m = re.match(r"^([^#/:=]+):([^:=]+)=(.+)\n$", line) + if m: + result[m.group(1)] = m.group(3) + return result + +def build_target(target_name, args): + """ + Execute the target build system to build target 'target_name' + + Calls _ensure_build_directory() which will run cmake to generate a build + directory (with the specified generator) as needed. + """ + _ensure_build_directory(args) + generator_cmd = GENERATOR_CMDS[args.generator] + if not args.no_ccache: + # Setting CCACHE_BASEDIR & CCACHE_NO_HASHDIR ensures that project paths aren't stored in the ccache entries + # (this means ccache hits can be shared between different projects. It may mean that some debug information + # will point to files in another project, if these files are perfect duplicates of each other.) + # + # It would be nicer to set these from cmake, but there's no cross-platform way to set build-time environment + #os.environ["CCACHE_BASEDIR"] = args.build_dir + #os.environ["CCACHE_NO_HASHDIR"] = "1" + pass + if args.verbose: + generator_cmd += [ GENERATOR_VERBOSE[args.generator] ] + + _run_tool(generator_cmd[0], generator_cmd + [target_name], args.build_dir) + + +def _get_esptool_args(args): + esptool_path = os.path.join(os.environ["IDF_PATH"], "components/esptool_py/esptool/esptool.py") + result = [ PYTHON, esptool_path ] + if args.port is not None: + result += [ "-p", args.port ] + result += [ "-b", str(args.baud) ] + return result + +def flash(action, args): + """ + Run esptool to flash the entire project, from an argfile generated by the build system + """ + flasher_args_path = { # action -> name of flasher args file generated by build system + "bootloader-flash": "flash_bootloader_args", + "partition_table-flash": "flash_partition_table_args", + "app-flash": "flash_app_args", + "flash": "flash_project_args", + }[action] + esptool_args = _get_esptool_args(args) + esptool_args += [ "write_flash", "@"+flasher_args_path ] + _run_tool("esptool.py", esptool_args, args.build_dir) + + +def erase_flash(action, args): + esptool_args = _get_esptool_args(args) + esptool_args += [ "erase_flash" ] + _run_tool("esptool.py", esptool_args, args.build_dir) + + +def monitor(action, args): + """ + Run idf_monitor.py to watch build output + """ + desc_path = os.path.join(args.build_dir, "project_description.json") + if not os.path.exists(desc_path): + _ensure_build_directory(args) + with open(desc_path, "r") as f: + project_desc = json.load(f) + + elf_file = os.path.join(args.build_dir, project_desc["app_elf"]) + if not os.path.exists(elf_file): + raise FatalError("ELF file '%s' not found. You need to build & flash the project before running 'monitor', and the binary on the device must match the one in the build directory exactly. Try 'idf.py flash monitor'." % elf_file) + idf_monitor = os.path.join(os.environ["IDF_PATH"], "tools/idf_monitor.py") + monitor_args = [PYTHON, idf_monitor ] + if args.port is not None: + monitor_args += [ "-p", args.port ] + monitor_args += [ "-b", project_desc["monitor_baud"] ] + monitor_args += [ elf_file ] + + idf_py = [ PYTHON ] + get_commandline_options() # commands to re-run idf.py + monitor_args += [ "-m", " ".join("'%s'" % a for a in idf_py) ] + + if "MSYSTEM" is os.environ: + monitor_args = [ "winpty" ] + monitor_args + _run_tool("idf_monitor", monitor_args, args.project_dir) + + +def clean(action, args): + if not os.path.isdir(args.build_dir): + print("Build directory '%s' not found. Nothing to clean." % args.build_dir) + return + build_target("clean", args) + +def reconfigure(action, args): + _ensure_build_directory(args, True) + +def fullclean(action, args): + build_dir = args.build_dir + if not os.path.isdir(build_dir): + print("Build directory '%s' not found. Nothing to clean." % build_dir) + return + if len(os.listdir(build_dir)) == 0: + print("Build directory '%s' is empty. Nothing to clean." % build_dir) + return + + if not os.path.exists(os.path.join(build_dir, "CMakeCache.txt")): + raise FatalError("Directory '%s' doesn't seem to be a CMake build directory. Refusing to automatically delete files in this directory. Delete the directory manually to 'clean' it." % build_dir) + red_flags = [ "CMakeLists.txt", ".git", ".svn" ] + for red in red_flags: + red = os.path.join(build_dir, red) + if os.path.exists(red): + raise FatalError("Refusing to automatically delete files in directory containing '%s'. Delete files manually if you're sure." % red) + # OK, delete everything in the build directory... + for f in os.listdir(build_dir): # TODO: once we are Python 3 only, this can be os.scandir() + f = os.path.join(build_dir, f) + if os.path.isdir(f): + shutil.rmtree(f) + else: + os.remove(f) + +def print_closing_message(args): + # print a closing message of some kind + # + + if "flash" in str(args.actions): + print("Done") + return + + # Otherwise, if we built any binaries print a message about + # how to flash them + def print_flashing_message(title, key): + print("\n%s build complete. To flash, run this command:" % title) + + with open(os.path.join(args.build_dir, "flasher_args.json")) as f: + flasher_args = json.load(f) + + def flasher_path(f): + return os.path.relpath(os.path.join(args.build_dir, f)) + + if key != "project": # flashing a single item + cmd = "" + if key == "bootloader": # bootloader needs --flash-mode, etc to be passed in + cmd = " ".join(flasher_args["write_flash_args"]) + " " + + cmd += flasher_args[key]["offset"] + " " + cmd += flasher_path(flasher_args[key]["file"]) + else: # flashing the whole project + cmd = " ".join(flasher_args["write_flash_args"]) + " " + flash_items = sorted((o,f) for (o,f) in flasher_args["flash_files"].items() if len(o) > 0) + for o,f in flash_items: + cmd += o + " " + flasher_path(f) + " " + + print("%s -p %s -b %s write_flash %s" % ( + os.path.relpath("%s/components/esptool_py/esptool/esptool.py" % os.environ["IDF_PATH"]), + args.port or "(PORT)", + args.baud, + cmd.strip())) + print("or run 'idf.py -p %s %s'" % (args.port or "(PORT)", key + "-flash" if key != "project" else "flash",)) + + if "all" in args.actions or "build" in args.actions: + print_flashing_message("Project", "project") + else: + if "app" in args.actions: + print_flashing_message("App", "app") + if "partition_table" in args.actions: + print_flashing_message("Partition Table", "partition_table") + if "bootloader" in args.actions: + print_flashing_message("Bootloader", "bootloader") + +ACTIONS = { + # action name : ( function (or alias), dependencies, order-only dependencies ) + "all" : ( build_target, [], [ "reconfigure", "menuconfig", "clean", "fullclean" ] ), + "build": ( "all", [], [] ), # build is same as 'all' target + "clean": ( clean, [], [ "fullclean" ] ), + "fullclean": ( fullclean, [], [] ), + "reconfigure": ( reconfigure, [], [ "menuconfig" ] ), + "menuconfig": ( build_target, [], [] ), + "confserver": ( build_target, [], [] ), + "size": ( build_target, [ "app" ], [] ), + "size-components": ( build_target, [ "app" ], [] ), + "size-files": ( build_target, [ "app" ], [] ), + "bootloader": ( build_target, [], [] ), + "bootloader-clean": ( build_target, [], [] ), + "bootloader-flash": ( flash, [ "bootloader" ], [ "erase_flash"] ), + "app": ( build_target, [], [ "clean", "fullclean", "reconfigure" ] ), + "app-flash": ( flash, [ "app" ], [ "erase_flash"]), + "partition_table": ( build_target, [], [ "reconfigure" ] ), + "partition_table-flash": ( flash, [ "partition_table" ], [ "erase_flash" ]), + "flash": ( flash, [ "all" ], [ "erase_flash" ] ), + "erase_flash": ( erase_flash, [], []), + "monitor": ( monitor, [], [ "flash", "partition_table-flash", "bootloader-flash", "app-flash" ]), +} + + +def get_commandline_options(): + """ Return all the command line options up to but not including the action """ + result = [] + for a in sys.argv: + if a in ACTIONS.keys(): + break + else: + result.append(a) + return result + +def main(): + if sys.version_info[0] != 2 or sys.version_info[1] != 7: + raise FatalError("ESP-IDF currently only supports Python 2.7, and this is Python %d.%d.%d. Search for 'Setting the Python Interpreter' in the ESP-IDF docs for some tips to handle this." % sys.version_info[:3]) + + parser = argparse.ArgumentParser(description='ESP-IDF build management tool') + parser.add_argument('-p', '--port', help="Serial port", + default=os.environ.get('ESPPORT', None)) + parser.add_argument('-b', '--baud', help="Baud rate", + default=os.environ.get('ESPBAUD', 460800)) + parser.add_argument('-C', '--project-dir', help="Project directory", default=os.getcwd()) + parser.add_argument('-B', '--build-dir', help="Build directory", default=None) + parser.add_argument('-G', '--generator', help="Cmake generator", choices=GENERATOR_CMDS.keys()) + parser.add_argument('-n', '--no-warnings', help="Disable Cmake warnings", action="store_true") + parser.add_argument('-v', '--verbose', help="Verbose build output", action="store_true") + parser.add_argument('--no-ccache', help="Disable ccache. Otherwise, if ccache is available on the PATH then it will be used for faster builds.", action="store_true") + parser.add_argument('actions', help="Actions (build targets or other operations)", nargs='+', + choices=ACTIONS.keys()) + + args = parser.parse_args() + + check_environment() + + # Advanced parameter checks + if args.build_dir is not None and os.path.realpath(args.project_dir) == os.path.realpath(args.build_dir): + raise FatalError("Setting the build directory to the project directory is not supported. Suggest dropping --build-dir option, the default is a 'build' subdirectory inside the project directory.") + if args.build_dir is None: + args.build_dir = os.path.join(args.project_dir, "build") + args.build_dir = os.path.realpath(args.build_dir) + + completed_actions = set() + def execute_action(action, remaining_actions): + ( function, dependencies, order_dependencies ) = ACTIONS[action] + # very simple dependency management, build a set of completed actions and make sure + # all dependencies are in it + for dep in dependencies: + if not dep in completed_actions: + execute_action(dep, remaining_actions) + for dep in order_dependencies: + if dep in remaining_actions and not dep in completed_actions: + execute_action(dep, remaining_actions) + + if action in completed_actions: + pass # we've already done this, don't do it twice... + elif function in ACTIONS: # alias of another action + execute_action(function, remaining_actions) + else: + function(action, args) + + completed_actions.add(action) + + actions = list(args.actions) + while len(actions) > 0: + execute_action(actions[0], actions[1:]) + actions.pop(0) + + print_closing_message(args) + +if __name__ == "__main__": + try: + main() + except FatalError as e: + print(e) + sys.exit(2) + + diff --git a/tools/idf_monitor.py b/tools/idf_monitor.py index 9bb0712a4..4dabe2123 100755 --- a/tools/idf_monitor.py +++ b/tools/idf_monitor.py @@ -3,8 +3,8 @@ # esp-idf serial output monitor tool. Does some helpful things: # - Looks up hex addresses in ELF file with addr2line # - Reset ESP32 via serial RTS line (Ctrl-T Ctrl-R) -# - Run "make flash" (Ctrl-T Ctrl-F) -# - Run "make app-flash" (Ctrl-T Ctrl-A) +# - Run "make (or idf.py) flash" (Ctrl-T Ctrl-F) +# - Run "make (or idf.py) app-flash" (Ctrl-T Ctrl-A) # - If gdbstub output is detected, gdb is automatically loaded # # Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD @@ -37,6 +37,7 @@ try: import queue except ImportError: import Queue as queue +import shlex import time import sys import serial @@ -297,7 +298,10 @@ class Monitor(object): self.console_reader = ConsoleReader(self.console, self.event_queue) self.serial_reader = SerialReader(self.serial, self.event_queue) self.elf_file = elf_file - self.make = make + if not os.path.exists(make): + self.make = shlex.split(make) # allow for possibility the "make" arg is a list of arguments (for idf.py) + else: + self.make = make self.toolchain_prefix = toolchain_prefix self.menu_key = CTRL_T self.exit_key = CTRL_RBRACKET @@ -459,19 +463,18 @@ class Monitor(object): --- {menu:7} Send the menu character itself to remote --- {exit:7} Send the exit character itself to remote --- {reset:7} Reset target board via RTS line ---- {make:7} Run 'make flash' to build & flash ---- {appmake:7} Run 'make app-flash to build & flash app +--- {makecmd:7} Build & flash project +--- {appmake:7} Build & flash app only --- {output:7} Toggle output display --- {pause:7} Reset target into bootloader to pause app via RTS line """.format(version=__version__, exit=key_description(self.exit_key), menu=key_description(self.menu_key), reset=key_description(CTRL_R), - make=key_description(CTRL_F), + makecmd=key_description(CTRL_F), appmake=key_description(CTRL_A), output=key_description(CTRL_Y), - pause=key_description(CTRL_P), - ) + pause=key_description(CTRL_P) ) def __enter__(self): """ Use 'with self' to temporarily disable monitoring behaviour """ @@ -489,12 +492,12 @@ class Monitor(object): red_print(""" --- {} --- Press {} to exit monitor. ---- Press {} to run 'make flash'. ---- Press {} to run 'make app-flash'. +--- Press {} to build & flash project. +--- Press {} to build & flash app. --- Press any other key to resume monitor (resets target).""".format(reason, key_description(self.exit_key), key_description(CTRL_F), - key_description(CTRL_A))) + key_description(CTRL_A) )) k = CTRL_T # ignore CTRL-T here, so people can muscle-memory Ctrl-T Ctrl-F, etc. while k == CTRL_T: k = self.console.getkey() @@ -508,9 +511,12 @@ class Monitor(object): def run_make(self, target): with self: - yellow_print("Running make %s..." % target) - p = subprocess.Popen([self.make, - target ]) + if isinstance(self.make, list): + popen_args = self.make + [ target ] + else: + popen_args = [ self.make, target ] + yellow_print("Running %s..." % " ".join(popen_args)) + p = subprocess.Popen(popen_args) try: p.wait() except KeyboardInterrupt: diff --git a/tools/idf_size.py b/tools/idf_size.py index 1893082ff..d207906b2 100755 --- a/tools/idf_size.py +++ b/tools/idf_size.py @@ -82,7 +82,6 @@ def load_sections(map_file): is a dict with details about this section, including a "sources" key which holds a list of source file line information for each symbol linked into the section. """ scan_to_header(map_file, "Linker script and memory map") - scan_to_header(map_file, "END GROUP") sections = {} section = None sym_backup = None @@ -102,16 +101,25 @@ def load_sections(map_file): # source file line, ie # 0x0000000040080400 0xa4 /home/gus/esp/32/idf/examples/get-started/hello_world/build/esp32/libesp32.a(cpu_start.o) - RE_SOURCE_LINE = r"\s*(?P\S*).* +0x(?P
[\da-f]+) +0x(?P[\da-f]+) (?P.+\.a)\((?P.+\.o)\)" + RE_SOURCE_LINE = r"\s*(?P\S*).* +0x(?P
[\da-f]+) +0x(?P[\da-f]+) (?P.+\.a)\((?P.+\.ob?j?)\)" m = re.match(RE_SOURCE_LINE, line, re.M) - if section is not None and m is not None: # input source file details + if not m: + # cmake build system links some object files directly, not part of any archive + RE_SOURCE_LINE = r"\s*(?P\S*).* +0x(?P
[\da-f]+) +0x(?P[\da-f]+) (?P.+\.ob?j?)" + m = re.match(RE_SOURCE_LINE, line) + if section is not None and m is not None: # input source file details=ma,e sym_name = m.group("sym_name") if len(m.group("sym_name")) > 0 else sym_backup + try: + archive = m.group("archive") + except IndexError: + archive = "(exe)" + source = { "size" : int(m.group("size"), 16), "address" : int(m.group("address"), 16), - "archive" : os.path.basename(m.group("archive")), - "object_file" : m.group("object_file"), + "archive" : os.path.basename(archive), + "object_file" : os.path.basename(m.group("object_file")), "sym_name" : sym_name, } source["file"] = "%s:%s" % (source["archive"], source["object_file"]) diff --git a/tools/kconfig/.gitignore b/tools/kconfig/.gitignore index 1950c8cb1..641b9e576 100644 --- a/tools/kconfig/.gitignore +++ b/tools/kconfig/.gitignore @@ -16,7 +16,9 @@ gconf.glade.h # configuration programs # conf +conf-idf mconf +mconf-idf nconf qconf gconf diff --git a/tools/kconfig/Makefile b/tools/kconfig/Makefile index 2454e47af..c8f8ba014 100644 --- a/tools/kconfig/Makefile +++ b/tools/kconfig/Makefile @@ -2,6 +2,10 @@ # Kernel configuration targets # These targets are used from top-level makefile +# SRCDIR is kconfig source dir, allows for out-of-tree builds +# if building in tree, SRCDIR==build dir +SRCDIR := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) + PHONY += xconfig gconfig menuconfig config silentoldconfig \ localmodconfig localyesconfig clean @@ -39,7 +43,7 @@ endif endif # MING32 endif # MSYSTEM -default: mconf conf +default: mconf-idf conf-idf xconfig: qconf $< $(silent) $(Kconfig) @@ -47,41 +51,41 @@ xconfig: qconf gconfig: gconf $< $(silent) $(Kconfig) -menuconfig: mconf +menuconfig: mconf-idf $< $(silent) $(Kconfig) -config: conf +config: conf-idf $< $(silent) --oldaskconfig $(Kconfig) nconfig: nconf $< $(silent) $(Kconfig) -silentoldconfig: conf +silentoldconfig: conf-idf mkdir -p include/config include/generated $< $(silent) --$@ $(Kconfig) -localyesconfig localmodconfig: streamline_config.pl conf +localyesconfig localmodconfig: streamline_config.pl conf-idf mkdir -p include/config include/generated perl $< --$@ . $(Kconfig) > .tmp.config if [ -f .config ]; then \ cmp -s .tmp.config .config || \ (mv -f .config .config.old.1; \ mv -f .tmp.config .config; \ - conf $(silent) --silentoldconfig $(Kconfig); \ + conf-idf $(silent) --silentoldconfig $(Kconfig); \ mv -f .config.old.1 .config.old) \ else \ mv -f .tmp.config .config; \ - conf $(silent) --silentoldconfig $(Kconfig); \ + conf-idf $(silent) --silentoldconfig $(Kconfig); \ fi rm -f .tmp.config -# These targets map 1:1 to the commandline options of 'conf' +# These targets map 1:1 to the commandline options of 'conf-idf' simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \ alldefconfig randconfig listnewconfig olddefconfig PHONY += $(simple-targets) -$(simple-targets): conf +$(simple-targets): conf-idf $< $(silent) --$@ $(Kconfig) PHONY += oldnoconfig savedefconfig defconfig @@ -91,10 +95,10 @@ PHONY += oldnoconfig savedefconfig defconfig # counter-intuitive name. oldnoconfig: olddefconfig -savedefconfig: conf +savedefconfig: conf-idf $< $(silent) --$@=defconfig $(Kconfig) -defconfig: conf +defconfig: conf-idf ifeq ($(KBUILD_DEFCONFIG),) $< $(silent) --defconfig $(Kconfig) else @@ -107,12 +111,12 @@ else endif endif -%_defconfig: conf +%_defconfig: conf-idf $< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig) configfiles=$(wildcard $(srctree)/kernel/configs/$@ $(srctree)/arch/$(SRCARCH)/configs/$@) -%.config: conf +%.config: conf-idf $(if $(call configfiles),, $(error No configuration exists for this target on this architecture)) $(CONFIG_SHELL) $(srctree)/scripts/kconfig/merge_config.sh -m .config $(configfiles) +yes "" | $(MAKE) -f $(srctree)/Makefile oldconfig @@ -156,19 +160,28 @@ help: @echo ' tinyconfig - Configure the tiniest possible kernel' # lxdialog stuff -check-lxdialog := lxdialog/check-lxdialog.sh +check-lxdialog := $(SRCDIR)/lxdialog/check-lxdialog.sh # Use recursively expanded variables so we do not call gcc unless # we really need to do so. (Do not call gcc as part of make mrproper) CFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \ -DLOCALE -MD +%.o: $(SRCDIR)/%.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ + +lxdialog/%.o: $(SRCDIR)/lxdialog/%.c + $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ + +%.o: %.c + $(CC) -I $(SRCDIR) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ + # =========================================================================== # Shared Makefile for the various kconfig executables: -# conf: Used for defconfig, oldconfig and related targets +# conf-idf: Used for defconfig, oldconfig and related targets # nconf: Used for the nconfig target. # Utilizes ncurses -# mconf: Used for the menuconfig target +# mconf-idf: Used for the menuconfig target # Utilizes the lxdialog package # qconf: Used for the xconfig target # Based on Qt which needs to be installed to compile it @@ -187,21 +200,25 @@ qconf-cxxobjs := qconf.o qconf-objs := zconf.tab.o gconf-objs := gconf.o zconf.tab.o -hostprogs-y := conf nconf mconf kxgettext qconf gconf +hostprogs-y := conf-idf nconf mconf-idf kxgettext qconf gconf all-objs := $(conf-objs) $(mconf-objs) $(lxdialog) all-deps := $(all-objs:.o=.d) clean-files := qconf.moc .tmp_qtcheck .tmp_gtkcheck clean-files += zconf.tab.c zconf.lex.c zconf.hash.c gconf.glade.h -clean-files += $(all-objs) $(all-deps) conf mconf +clean-files += $(all-objs) $(all-deps) conf-idf mconf-idf conf mconf +# (note: cleans both mconf & conf (old names) and conf-idf & mconf-idf (new names)) # Check that we have the required ncurses stuff installed for lxdialog (menuconfig) PHONY += dochecklxdialog $(addprefix ,$(lxdialog)): dochecklxdialog -dochecklxdialog: +dochecklxdialog: lxdialog $(CONFIG_SHELL) $(check-lxdialog) -check $(CC) $(CFLAGS) $(LOADLIBES_mconf) +lxdialog: + mkdir -p lxdialog + always := dochecklxdialog # Add environment specific flags @@ -308,23 +325,23 @@ gconf.glade.h: gconf.glade gconf.glade -mconf: $(mconf-objs) +mconf-idf: lxdialog $(mconf-objs) $(CC) -o $@ $(mconf-objs) $(LOADLIBES_mconf) -conf: $(conf-objs) +conf-idf: $(conf-objs) $(CC) -o $@ $(conf-objs) $(LOADLIBES_conf) zconf.tab.c: zconf.lex.c -zconf.lex.c: zconf.l - flex -L -P zconf -o zconf.lex.c zconf.l +zconf.lex.c: $(SRCDIR)/zconf.l + flex -L -P zconf -o zconf.lex.c $< -zconf.hash.c: zconf.gperf +zconf.hash.c: $(SRCDIR)/zconf.gperf # strip CRs on Windows systems where gperf will otherwise barf on them - sed -E "s/\\x0D$$//" zconf.gperf | gperf -t --output-file zconf.hash.c -a -C -E -g -k '1,3,$$' -p -t + sed -E "s/\\x0D$$//" $< | gperf -t --output-file zconf.hash.c -a -C -E -g -k '1,3,$$' -p -t -zconf.tab.c: zconf.y - bison -t -l -p zconf -o zconf.tab.c zconf.y +zconf.tab.c: $(SRCDIR)/zconf.y + bison -t -l -p zconf -o zconf.tab.c $< clean: rm -f $(clean-files) diff --git a/tools/kconfig/mconf.c b/tools/kconfig/mconf.c index 315ce2c7c..75fe11635 100644 --- a/tools/kconfig/mconf.c +++ b/tools/kconfig/mconf.c @@ -980,11 +980,17 @@ static int handle_exit(void) } /* fall through */ case -1: - if (!silent) + if (!silent) { + const char *is_cmake = getenv("IDF_CMAKE"); + const char *build_msg; + if (is_cmake && is_cmake[0] == 'y') + build_msg = _("Ready to use CMake (or 'idf.py build') to build the project."); + else + build_msg = _("Execute 'make' to start the build or try 'make help'."); printf(_("\n\n" - "*** End of the configuration.\n" - "*** Execute 'make' to start the build or try 'make help'." - "\n\n")); + "*** End of the configuration.\n" + "*** %s\n\n"), build_msg); + } res = 0; break; default: diff --git a/tools/kconfig_new/confgen.py b/tools/kconfig_new/confgen.py new file mode 100755 index 000000000..416c28d88 --- /dev/null +++ b/tools/kconfig_new/confgen.py @@ -0,0 +1,295 @@ +#!/usr/bin/env python +# +# Command line tool to take in ESP-IDF sdkconfig files with project +# settings and output data in multiple formats (update config, generate +# header file, generate .cmake include file, documentation, etc). +# +# Used internally by the ESP-IDF build system. But designed to be +# non-IDF-specific. +# +# Copyright 2018 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import argparse +import sys +import os +import os.path +import tempfile +import json + +import gen_kconfig_doc +import kconfiglib +import pprint + +__version__ = "0.1" + +if not "IDF_CMAKE" in os.environ: + os.environ["IDF_CMAKE"] = "" + +def main(): + parser = argparse.ArgumentParser(description='confgen.py v%s - Config Generation Tool' % __version__, prog=os.path.basename(sys.argv[0])) + + parser.add_argument('--config', + help='Project configuration settings', + nargs='?', + default=None) + + parser.add_argument('--defaults', + help='Optional project defaults file, used if --config file doesn\'t exist', + nargs='?', + default=None) + + parser.add_argument('--create-config-if-missing', + help='If set, a new config file will be saved if the old one is not found', + action='store_true') + + parser.add_argument('--kconfig', + help='KConfig file with config item definitions', + required=True) + + parser.add_argument('--output', nargs=2, action='append', + help='Write output file (format and output filename)', + metavar=('FORMAT', 'FILENAME'), + default=[]) + + parser.add_argument('--env', action='append', default=[], + help='Environment to set when evaluating the config file', metavar='NAME=VAL') + + args = parser.parse_args() + + for fmt, filename in args.output: + if not fmt in OUTPUT_FORMATS.keys(): + print("Format '%s' not recognised. Known formats: %s" % (fmt, OUTPUT_FORMATS.keys())) + sys.exit(1) + + try: + args.env = [ (name,value) for (name,value) in ( e.split("=",1) for e in args.env) ] + except ValueError: + print("--env arguments must each contain =. To unset an environment variable, use 'ENV='") + sys.exit(1) + + for name, value in args.env: + os.environ[name] = value + + config = kconfiglib.Kconfig(args.kconfig) + + if args.defaults is not None: + # always load defaults first, so any items which are not defined in that config + # will have the default defined in the defaults file + if not os.path.exists(args.defaults): + raise RuntimeError("Defaults file not found: %s" % args.defaults) + config.load_config(args.defaults) + + if args.config is not None: + if os.path.exists(args.config): + config.load_config(args.config) + elif args.create_config_if_missing: + print("Creating config file %s..." % args.config) + config.write_config(args.config) + elif args.default is None: + raise RuntimeError("Config file not found: %s" % args.config) + + for output_type, filename in args.output: + temp_file = tempfile.mktemp(prefix="confgen_tmp") + try: + output_function = OUTPUT_FORMATS[output_type] + output_function(config, temp_file) + update_if_changed(temp_file, filename) + finally: + try: + os.remove(temp_file) + except OSError: + pass + + +def write_config(config, filename): + CONFIG_HEADING = """# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# +""" + config.write_config(filename, header=CONFIG_HEADING) + +def write_header(config, filename): + CONFIG_HEADING = """/* + * Automatically generated file. DO NOT EDIT. + * Espressif IoT Development Framework (ESP-IDF) Configuration Header + */ +#pragma once +""" + config.write_autoconf(filename, header=CONFIG_HEADING) + +def write_cmake(config, filename): + with open(filename, "w") as f: + write = f.write + prefix = config.config_prefix + + write("""# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) Configuration cmake include file +# +""") + def write_node(node): + sym = node.item + if not isinstance(sym, kconfiglib.Symbol): + return + + # Note: str_value calculates _write_to_conf, due to + # internal magic in kconfiglib... + val = sym.str_value + if sym._write_to_conf: + if sym.orig_type in (kconfiglib.BOOL, kconfiglib.TRISTATE) and val == "n": + val = "" # write unset values as empty variables + write("set({}{} \"{}\")\n".format( + prefix, sym.name, val)) + config.walk_menu(write_node) + +def get_json_values(config): + config_dict = {} + def write_node(node): + sym = node.item + if not isinstance(sym, kconfiglib.Symbol): + return + + val = sym.str_value # this calculates _write_to_conf, due to kconfiglib magic + if sym._write_to_conf: + if sym.type in [ kconfiglib.BOOL, kconfiglib.TRISTATE ]: + val = (val != "n") + elif sym.type == kconfiglib.HEX: + val = int(val, 16) + elif sym.type == kconfiglib.INT: + val = int(val) + config_dict[sym.name] = val + config.walk_menu(write_node) + return config_dict + +def write_json(config, filename): + config_dict = get_json_values(config) + with open(filename, "w") as f: + json.dump(config_dict, f, indent=4, sort_keys=True) + +def write_json_menus(config, filename): + result = [] # root level items + node_lookup = {} # lookup from MenuNode to an item in result + + def write_node(node): + try: + json_parent = node_lookup[node.parent]["children"] + except KeyError: + assert not node.parent in node_lookup # if fails, we have a parent node with no "children" entity (ie a bug) + json_parent = result # root level node + + # node.kconfig.y means node has no dependency, + if node.dep is node.kconfig.y: + depends = None + else: + depends = kconfiglib.expr_str(node.dep) + + try: + is_menuconfig = node.is_menuconfig + except AttributeError: + is_menuconfig = False + + new_json = None + if node.item == kconfiglib.MENU or is_menuconfig: + new_json = { "type" : "menu", + "title" : node.prompt[0], + "depends_on": depends, + "children": [] + } + if is_menuconfig: + sym = node.item + new_json["name"] = sym.name + new_json["help"] = node.help + new_json["is_menuconfig"] = is_menuconfig + greatest_range = None + if len(sym.ranges) > 0: + # Note: Evaluating the condition using kconfiglib's expr_value + # should have one result different from value 0 ("n"). + for min_range, max_range, cond_expr in sym.ranges: + if kconfiglib.expr_value(cond_expr) != "n": + greatest_range = [min_range, max_range] + new_json["range"] = greatest_range + + elif isinstance(node.item, kconfiglib.Symbol): + sym = node.item + greatest_range = None + if len(sym.ranges) > 0: + # Note: Evaluating the condition using kconfiglib's expr_value + # should have one result different from value 0 ("n"). + for min_range, max_range, cond_expr in sym.ranges: + if kconfiglib.expr_value(cond_expr) != "n": + greatest_range = [int(min_range.str_value), int(max_range.str_value)] + + new_json = { + "type" : kconfiglib.TYPE_TO_STR[sym.type], + "name" : sym.name, + "title": node.prompt[0] if node.prompt else None, + "depends_on" : depends, + "help": node.help, + "range" : greatest_range, + "children": [], + } + elif isinstance(node.item, kconfiglib.Choice): + choice = node.item + new_json = { + "type": "choice", + "title": node.prompt[0], + "name": choice.name, + "depends_on" : depends, + "help": node.help, + "children": [] + } + + if new_json: + json_parent.append(new_json) + node_lookup[node] = new_json + + config.walk_menu(write_node) + with open(filename, "w") as f: + f.write(json.dumps(result, sort_keys=True, indent=4)) + +def update_if_changed(source, destination): + with open(source, "r") as f: + source_contents = f.read() + if os.path.exists(destination): + with open(destination, "r") as f: + dest_contents = f.read() + if source_contents == dest_contents: + return # nothing to update + + with open(destination, "w") as f: + f.write(source_contents) + + +OUTPUT_FORMATS = { + "config" : write_config, + "header" : write_header, + "cmake" : write_cmake, + "docs" : gen_kconfig_doc.write_docs, + "json" : write_json, + "json_menus" : write_json_menus, + } + +class FatalError(RuntimeError): + """ + Class for runtime errors (not caused by bugs but by user input). + """ + pass + +if __name__ == '__main__': + try: + main() + except FatalError as e: + print("A fatal error occurred: %s" % e) + sys.exit(2) diff --git a/tools/kconfig_new/confserver.py b/tools/kconfig_new/confserver.py new file mode 100755 index 000000000..cf63a598d --- /dev/null +++ b/tools/kconfig_new/confserver.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python +# +# Long-running server process uses stdin & stdout to communicate JSON +# with a caller +# +from __future__ import print_function +import argparse +import json +import kconfiglib +import os +import sys +import confgen +from confgen import FatalError, __version__ + +def main(): + parser = argparse.ArgumentParser(description='confserver.py v%s - Config Generation Tool' % __version__, prog=os.path.basename(sys.argv[0])) + + parser.add_argument('--config', + help='Project configuration settings', + required=True) + + parser.add_argument('--kconfig', + help='KConfig file with config item definitions', + required=True) + + parser.add_argument('--env', action='append', default=[], + help='Environment to set when evaluating the config file', metavar='NAME=VAL') + + args = parser.parse_args() + + try: + args.env = [ (name,value) for (name,value) in ( e.split("=",1) for e in args.env) ] + except ValueError: + print("--env arguments must each contain =. To unset an environment variable, use 'ENV='") + sys.exit(1) + + for name, value in args.env: + os.environ[name] = value + + print("Server running, waiting for requests on stdin...", file=sys.stderr) + run_server(args.kconfig, args.config) + + +def run_server(kconfig, sdkconfig): + config = kconfiglib.Kconfig(kconfig) + config.load_config(sdkconfig) + + config_dict = confgen.get_json_values(config) + ranges_dict = get_ranges(config) + json.dump({"version": 1, "values" : config_dict, "ranges" : ranges_dict}, sys.stdout) + print("\n") + + while True: + line = sys.stdin.readline() + if not line: + break + req = json.loads(line) + before = confgen.get_json_values(config) + before_ranges = get_ranges(config) + + if "load" in req: # if we're loading a different sdkconfig, response should have all items in it + before = {} + before_ranges = {} + + # if no new filename is supplied, use existing sdkconfig path, otherwise update the path + if req["load"] is None: + req["load"] = sdkconfig + else: + sdkconfig = req["load"] + + if "save" in req: + if req["save"] is None: + req["save"] = sdkconfig + else: + sdkconfig = req["save"] + + error = handle_request(config, req) + + after = confgen.get_json_values(config) + after_ranges = get_ranges(config) + + values_diff = diff(before, after) + ranges_diff = diff(before_ranges, after_ranges) + response = {"version" : 1, "values" : values_diff, "ranges" : ranges_diff} + if error: + for e in error: + print("Error: %s" % e, file=sys.stderr) + response["error"] = error + json.dump(response, sys.stdout) + print("\n") + + +def handle_request(config, req): + if not "version" in req: + return [ "All requests must have a 'version'" ] + if int(req["version"]) != 1: + return [ "Only version 1 requests supported" ] + + error = [] + + if "load" in req: + print("Loading config from %s..." % req["load"], file=sys.stderr) + try: + config.load_config(req["load"]) + except Exception as e: + error += [ "Failed to load from %s: %s" % (req["load"], e) ] + + if "set" in req: + handle_set(config, error, req["set"]) + + if "save" in req: + try: + print("Saving config to %s..." % req["save"], file=sys.stderr) + confgen.write_config(config, req["save"]) + except Exception as e: + error += [ "Failed to save to %s: %s" % (req["save"], e) ] + + return error + +def handle_set(config, error, to_set): + missing = [ k for k in to_set if not k in config.syms ] + if missing: + error.append("The following config symbol(s) were not found: %s" % (", ".join(missing))) + # replace name keys with the full config symbol for each key: + to_set = dict((config.syms[k],v) for (k,v) in to_set.items() if not k in missing) + + # Work through the list of values to set, noting that + # some may not be immediately applicable (maybe they depend + # on another value which is being set). Therefore, defer + # knowing if any value is unsettable until then end + + while len(to_set): + set_pass = [ (k,v) for (k,v) in to_set.items() if k.visibility ] + if not set_pass: + break # no visible keys left + for (sym,val) in set_pass: + if sym.type in (kconfiglib.BOOL, kconfiglib.TRISTATE): + if val == True: + sym.set_value(2) + elif val == False: + sym.set_value(0) + else: + error.append("Boolean symbol %s only accepts true/false values" % sym.name) + else: + sym.set_value(str(val)) + print("Set %s" % sym.name) + del to_set[sym] + + if len(to_set): + error.append("The following config symbol(s) were not visible so were not updated: %s" % (", ".join(s.name for s in to_set))) + + + +def diff(before, after): + """ + Return a dictionary with the difference between 'before' and 'after' (either with the new value if changed, + or None as the value if a key in 'before' is missing in 'after' + """ + diff = dict((k,v) for (k,v) in after.items() if before.get(k, None) != v) + hidden = dict((k,None) for k in before if k not in after) + diff.update(hidden) + return diff + + +def get_ranges(config): + ranges_dict = {} + def handle_node(node): + sym = node.item + if not isinstance(sym, kconfiglib.Symbol): + return + active_range = sym.active_range + if active_range[0] is not None: + ranges_dict[sym.name] = active_range + + config.walk_menu(handle_node) + return ranges_dict + + +if __name__ == '__main__': + try: + main() + except FatalError as e: + print("A fatal error occurred: %s" % e, file=sys.stderr) + sys.exit(2) + diff --git a/tools/kconfig_new/gen_kconfig_doc.py b/tools/kconfig_new/gen_kconfig_doc.py new file mode 100644 index 000000000..83a91f359 --- /dev/null +++ b/tools/kconfig_new/gen_kconfig_doc.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# gen_kconfig_doc - confgen.py support for generating ReST markup documentation +# +# For each option in the loaded Kconfig (e.g. 'FOO'), CONFIG_FOO link target is +# generated, allowing options to be referenced in other documents +# (using :ref:`CONFIG_FOO`) +# +# Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http:#www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import os +import kconfiglib + +# Indentation to be used in the generated file +INDENT = ' ' + +# Characters used when underlining section heading +HEADING_SYMBOLS = '*=-^#' + +# Keep the heading level in sync with api-reference/kconfig.rst +INITIAL_HEADING_LEVEL = 2 +MAX_HEADING_LEVEL = len(HEADING_SYMBOLS)-1 + +def write_docs(config, filename): + """ Note: writing .rst documentation ignores the current value + of any items. ie the --config option can be ignored. + (However at time of writing it still needs to be set to something...) """ + with open(filename, "w") as f: + config.walk_menu(lambda node: write_menu_item(f, node)) + + +def get_breadcrumbs(node): + # this is a bit wasteful as it recalculates each time, but still... + result = [] + node = node.parent + while node.parent: + if node_is_menu(node) and node.prompt: + result = [ node.prompt[0] ] + result + node = node.parent + return " > ".join(result) + +def get_heading_level(node): + # bit wasteful also + result = INITIAL_HEADING_LEVEL + node = node.parent + while node.parent: + # Test for 'Component config' is a hack so component config doesn't bury all + # the components under it in the hierarchy + if node_is_menu(node) and node.prompt[0] != "Component config": + result += 1 + if result == MAX_HEADING_LEVEL: + return MAX_HEADING_LEVEL + node = node.parent + return result + +def format_rest_text(text, indent): + # Format an indented text block for use with ReST + text = indent + text.replace('\n', '\n' + indent) + # Escape some characters which are inline formatting in ReST + text = text.replace("*", "\\*") + text = text.replace("_", "\\_") + text += '\n' + return text + +def node_is_menu(node): + try: + return node.item == kconfiglib.MENU or node.is_menuconfig + except AttributeError: + return False # not all MenuNodes have is_menuconfig for some reason + +def should_print_preview_links(node): + """ + Return True if we should print the preview links. For each menu, + the menu with the preview links is the top menu which contains + actual configuration items. + """ + child = node.list + while child: + if not node_is_menu(child) and child.prompt: + # we have a non-menu child, so return true if we don't have + # a parent which already returned true + return node.parent is None or not should_print_preview_links(node.parent) + child = child.next + return False + +def write_menu_item(f, node): + if not node.prompt: + return # Don't do anything for invisible menu items + + if isinstance(node.parent.item, kconfiglib.Choice): + return # Skip choice nodes, they are handled as part of the parent (see below) + + try: + name = node.item.name + except AttributeError: + name = None + + is_menu = node_is_menu(node) + + ## Heading + if name: + f.write('.. envvar:: CONFIG_%s\n\n' % name) + + # menus get a proper heading + if is_menu: + title = node.prompt[0] + f.write('%s\n' % title) + f.write(HEADING_SYMBOLS[get_heading_level(node)] * len(title)) + f.write('\n\n') + if should_print_preview_links(node): + # print preview links to all items in this menu + # for the first menu which contains at least one non-menu item + # (ie per component, or per top-level KConfig.projbuild menu) + def print_previews(parent): + child = parent.list + while child: + if not node_is_menu(child): + f.write('- :envvar:`CONFIG_%s`\n' % child.item.name) + if child.list and not isinstance(child.item, kconfiglib.Choice): + print_previews(child) + child = child.next + print_previews(node) + f.write('\n\n') + + if name: + f.write('%s%s\n\n' % (INDENT, node.prompt[0])) + + try: + if node.help: + # Help text normally contains newlines, but spaces at the beginning of + # each line are stripped by kconfiglib. We need to re-indent the text + # to produce valid ReST. + f.write(format_rest_text(node.help, INDENT)) + except AttributeError: + pass # No help + + if node.parent is not None and not is_menu: + f.write('%sFound in\n%s%s\n\n' % (INDENT, INDENT * 2, + get_breadcrumbs(node))) + + if isinstance(node.item, kconfiglib.Choice): + f.write('%sAvailable options:\n' % INDENT) + choice_node = node.list + while choice_node: + # Format available options as a list + f.write('%s- %-20s (`CONFIG_%s`)\n' % (INDENT * 2, choice_node.prompt[0], choice_node.item.name)) + if choice_node.help: + HELP_INDENT = INDENT * 2 + fmt_help = format_rest_text(choice_node.help, ' ' + HELP_INDENT) + f.write('%s \n%s\n' % (HELP_INDENT, fmt_help)) + choice_node = choice_node.next + + f.write('\n\n') + +if __name__ == '__main__': + print("Run this via 'confgen.py --output doc FILENAME'") + diff --git a/tools/kconfig_new/kconfiglib.py b/tools/kconfig_new/kconfiglib.py new file mode 100644 index 000000000..929f30d4d --- /dev/null +++ b/tools/kconfig_new/kconfiglib.py @@ -0,0 +1,4329 @@ +# Copyright (c) 2011-2017, Ulf Magnusson +# Modifications (c) 2018 Espressif Systems +# SPDX-License-Identifier: ISC +# +# ******* IMPORTANT ********** +# +# This is kconfiglib 2.1.0 with some modifications to match the behaviour +# of the ESP-IDF kconfig: +# +# - 'source' nows uses wordexp(3) behaviour to allow source-ing multiple +# files at once, and to expand environment variables directly in the source +# command (without them having to be set as properties in the Kconfig file) +# +# - Added walk_menu() function and refactored to use this internally. +# +# - BOOL & TRISTATE items are allowed to have blank values in .config +# (equivalent to n, this is backwards compatibility with old IDF conf.c) +# +""" +Overview +======== + +Kconfiglib is a Python 2/3 library for scripting and extracting information +from Kconfig configuration systems. It can be used for the following, among +other things: + + - Programmatically get and set symbol values + + allnoconfig.py and allyesconfig.py examples are provided, automatically + verified to produce identical output to the standard 'make allnoconfig' and + 'make allyesconfig'. + + - Read and write .config files + + The generated .config files are character-for-character identical to what + the C implementation would generate (except for the header comment). The + test suite relies on this, as it compares the generated files. + + - Inspect symbols + + Printing a symbol gives output which could be fed back into a Kconfig parser + to redefine it***. The printing function (__str__()) is implemented with + public APIs, meaning you can fetch just whatever information you need as + well. + + A helpful __repr__() is implemented on all objects too, also implemented + with public APIs. + + ***Choice symbols get their parent choice as a dependency, which shows up as + e.g. 'prompt "choice symbol" if ' when printing the symbol. This + could easily be worked around if 100% reparsable output is needed. + + - Inspect expressions + + Expressions use a simple tuple-based format that can be processed manually + if needed. Expression printing and evaluation functions are provided, + implemented with public APIs. + + - Inspect the menu tree + + The underlying menu tree is exposed, including submenus created implicitly + from symbols depending on preceding symbols. This can be used e.g. to + implement menuconfig-like functionality. See the menuconfig.py example. + + +Here are some other features: + + - Single-file implementation + + The entire library is contained in this file. + + - Runs unmodified under both Python 2 and Python 3 + + The code mostly uses basic Python features and has no third-party + dependencies. The most advanced things used are probably @property and + __slots__. + + - Robust and highly compatible with the standard Kconfig C tools + + The test suite automatically compares output from Kconfiglib and the C tools + by diffing the generated .config files for the real kernel Kconfig and + defconfig files, for all ARCHes. + + This currently involves comparing the output for 36 ARCHes and 498 defconfig + files (or over 18000 ARCH/defconfig combinations in "obsessive" test suite + mode). All tests are expected to pass. + + - Not horribly slow despite being a pure Python implementation + + The allyesconfig.py example currently runs in about 1.6 seconds on a Core i7 + 2600K (with a warm file cache), where half a second is overhead from 'make + scriptconfig' (see below). + + For long-running jobs, PyPy gives a big performance boost. CPython is faster + for short-running jobs as PyPy needs some time to warm up. + + - Internals that (mostly) mirror the C implementation + + While being simpler to understand. + + +Using Kconfiglib on the Linux kernel with the Makefile targets +============================================================== + +For the Linux kernel, a handy interface is provided by the +scripts/kconfig/Makefile patch. Apply it with either 'git am' or the 'patch' +utility: + + $ wget -qO- https://raw.githubusercontent.com/ulfalizer/Kconfiglib/master/makefile.patch | git am + $ wget -qO- https://raw.githubusercontent.com/ulfalizer/Kconfiglib/master/makefile.patch | patch -p1 + +Warning: Not passing -p1 to patch will cause the wrong file to be patched. + +Please tell me if the patch does not apply. It should be trivial to apply +manually, as it's just a block of text that needs to be inserted near the other +*conf: targets in scripts/kconfig/Makefile. + +If you do not wish to install Kconfiglib via pip, the Makefile patch is set up +so that you can also just clone Kconfiglib into the kernel root: + + $ git clone git://github.com/ulfalizer/Kconfiglib.git + $ git am Kconfiglib/makefile.patch (or 'patch -p1 < Kconfiglib/makefile.patch') + +Warning: The directory name Kconfiglib/ is significant in this case, because +it's added to PYTHONPATH by the new targets in makefile.patch. + +Look further down for a motivation for the Makefile patch and for instructions +on how you can use Kconfiglib without it. + +The Makefile patch adds the following targets: + + +make [ARCH=] iscriptconfig +-------------------------------- + +This target gives an interactive Python prompt where a Kconfig instance has +been preloaded and is available in 'kconf'. To change the Python interpreter +used, pass PYTHONCMD= to make. The default is "python". + +To get a feel for the API, try evaluating and printing the symbols in +kconf.defined_syms, and explore the MenuNode menu tree starting at +kconf.top_node by following 'next' and 'list' pointers. + +The item contained in a menu node is found in MenuNode.item (note that this can +be one of the constants MENU and COMMENT), and all symbols and choices have a +'nodes' attribute containing their menu nodes (usually only one). Printing a +menu node will print its item, in Kconfig format. + +If you want to look up a symbol by name, use the kconf.syms dictionary. + + +make scriptconfig SCRIPT=