]> granicus.if.org Git - esp-idf/commitdiff
examples: update idf_as_lib example to use new api
authorRenz Christian Bagaporo <renz@espressif.com>
Sun, 24 Mar 2019 02:14:49 +0000 (10:14 +0800)
committerRenz Christian Bagaporo <renz@espressif.com>
Tue, 14 May 2019 10:01:14 +0000 (18:01 +0800)
24 files changed:
components/bootloader_support/CMakeLists.txt
components/esp32/CMakeLists.txt
components/esptool_py/CMakeLists.txt
components/spi_flash/CMakeLists.txt
examples/build_system/cmake/idf_as_lib/CMakeLists.txt
examples/build_system/cmake/idf_as_lib/README.md
examples/build_system/cmake/idf_as_lib/build-esp32.sh [new file with mode: 0755]
examples/build_system/cmake/idf_as_lib/build.sh
examples/build_system/cmake/idf_as_lib/run-esp32.sh [new file with mode: 0755]
examples/build_system/cmake/idf_as_lib/run.sh [new file with mode: 0755]
examples/build_system/cmake/idf_as_lib/stubs/esp32/CMakeLists.txt [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/esp32/cpu_start.c [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/esp32/esp_system.h [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/esp32/flash_ops.c [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/esp32/system_api.c [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/freertos/CMakeLists.txt [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/freertos/freertos/FreeRTOS.h [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/freertos/freertos/task.h [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/freertos/task.c [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/spi_flash/CMakeLists.txt [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/stubs/spi_flash/esp_spi_flash.h [new file with mode: 0644]
tools/ci/build_examples_cmake.sh
tools/ci/executable-list.txt
tools/ci/test_build_system_cmake.sh

index dc0e0be7fd63d6010e08594bc3445d763f0b0d10..526ad92a111cf99e17a32d6514f2a4ecffb8194e 100644 (file)
@@ -55,8 +55,8 @@ else()
                                "src/idf/secure_boot_signatures.c")
     set(COMPONENT_ADD_INCLUDEDIRS "include")
     set(COMPONENT_PRIV_INCLUDEDIRS "include_bootloader")
-    set(COMPONENT_REQUIRES soc) #unfortunately the header directly uses SOC registers
-    set(COMPONENT_PRIV_REQUIRES spi_flash mbedtls efuse)
+    set(COMPONENT_REQUIRES mbedtls soc) #unfortunately the header directly uses SOC registers
+    set(COMPONENT_PRIV_REQUIRES spi_flash efuse)
 endif()
 
 register_component()
\ No newline at end of file
index c9fe3f59a8fc6793a364d31a7e83ebbe4728a4aa..c8816fc388cf07b33a19390435562cec299dab36 100644 (file)
@@ -34,13 +34,13 @@ else()
                    "task_wdt.c")
     set(COMPONENT_ADD_INCLUDEDIRS "include")
 
-    set(COMPONENT_REQUIRES driver esp_event efuse soc) #unfortunately rom/uart uses SOC registers directly
+    set(COMPONENT_REQUIRES app_update driver esp_event efuse pthread soc) #unfortunately rom/uart uses SOC registers directly
 
     # driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t
     # app_update is added here because cpu_start.c uses esp_ota_get_app_description() function.
     set(COMPONENT_PRIV_REQUIRES
         app_trace app_update bootloader_support log mbedtls nvs_flash
-        pthread smartconfig_ack spi_flash vfs wpa_supplicant espcoredump esp_common esp_wifi)
+        smartconfig_ack spi_flash vfs wpa_supplicant espcoredump esp_common esp_wifi)
 
     set(COMPONENT_ADD_LDFRAGMENTS linker.lf ld/esp32_fragments.lf)
 
index d20de8b245982d5b5abe509996acbf3c8f9ba8da..09764ccf05e5117c78e0b3bbcfb4c558ce478feb 100644 (file)
@@ -1,4 +1,5 @@
-register_config_only_component()
+set(COMPONENT_PRIV_REQUIRES bootloader)
+register_component()
 
 string(REPLACE ";" " " ESPTOOLPY_FLASH_PROJECT_OPTIONS "${ESPTOOLPY_ELF2IMAGE_FLASH_OPTIONS}")
 set(ESPTOOLPY_FLASH_PROJECT_OPTIONS
index be290e7c321aef46dba5847a8c4d66b5c9a7bd42..db8fceee0e045838570634f3e48d6b2c461beb71 100644 (file)
@@ -9,7 +9,8 @@ else()
                    "flash_ops.c"
                    "partition.c"
                    "spi_flash_rom_patch.c")
-    set(COMPONENT_PRIV_REQUIRES bootloader_support app_update soc)
+    set(COMPONENT_REQUIRES app_update)
+    set(COMPONENT_PRIV_REQUIRES bootloader_support soc)
 endif()
 
 set(COMPONENT_ADD_INCLUDEDIRS include)
index ba0176f1d7cd5061a11091c3031866d228e10266..b035e11b525a5bc0cc6b1cab99898dc1743bf42c 100644 (file)
@@ -1,24 +1,38 @@
 cmake_minimum_required(VERSION 3.5)
 project(idf_as_lib C)
 
-# The source file main.c contains app_main() definition
-add_executable(${CMAKE_PROJECT_NAME}.elf main.c)
+if("${TARGET}" STREQUAL "esp32")
+    # Include for ESP-IDF build system functions
+    include($ENV{IDF_PATH}/tools/cmake/idf.cmake)
+    # Create idf::esp32 and idf::freertos static libraries
+    idf_build_process(esp32
+                    # try and trim the build; additional components
+                    # will be included as needed based on dependency tree
+                    #
+                    # although esptool_py does not generate static library,
+                    # processing the component is needed for flashing related
+                    # targets and file generation
+                    COMPONENTS esp32 freertos esptool_py
+                    SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig
+                    BUILD_DIR ${CMAKE_BINARY_DIR})
+else()
+    # Create stubs for esp32 and freertos, stub::esp32 and stub::freertos
+    add_subdirectory(stubs/esp32)
+    add_subdirectory(stubs/freertos)
+    add_subdirectory(stubs/spi_flash)
+endif()
 
-# Provides idf_import_components() and idf_link_components()
-include($ENV{IDF_PATH}/tools/cmake/idf_functions.cmake)
+set(elf_file ${CMAKE_PROJECT_NAME}.elf)
+add_executable(${elf_file} main.c)
 
-# Create artifacts used for flashing the project to target chip
-set(IDF_BUILD_ARTIFACTS ON)
-set(IDF_PROJECT_EXECUTABLE ${CMAKE_PROJECT_NAME}.elf)
-set(IDF_BUILD_ARTIFACTS_DIR ${CMAKE_BINARY_DIR})
+# Link the static libraries to the executable
+if("${TARGET}" STREQUAL "esp32")
+    target_link_libraries(${elf_file} idf::esp32 idf::freertos idf::spi_flash)
+    # Attach additional targets to the executable file for flashing,
+    # linker script generation, partition_table generation, etc.
+    idf_build_executable(${elf_file})
+else()
+    target_link_libraries(${elf_file} stub::esp32 stub::freertos stub::spi_flash)
+endif()
 
-# Trim down components included in the build. Although freertos and spi_flash are the ones needed by the application
-# itself, the bootloader and esptool_py components are also needed in order to create the artifacts to be used
-# for flashing to the target chip
-set(IDF_COMPONENTS freertos spi_flash bootloader esptool_py)
-
-# Wraps add_subdirectory() to create library targets for components, and then return them using the specified variable
-idf_import_components(components $ENV{IDF_PATH} esp-idf)
-
-# Wraps target_link_libraries() to link processed components by idf_import_components to target
-idf_link_components(${CMAKE_PROJECT_NAME}.elf "${components}")
\ No newline at end of file
+set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
\ No newline at end of file
index 19506a8fac1fa0f3f9a632237e7f03c2793158a5..eda7ac0b4d819e83d2304a04bf368cd17b15c4f0 100644 (file)
@@ -1,13 +1,17 @@
 # Using ESP-IDF in Custom CMake Projects
 
-This example illustrates using ESP-IDF components as libraries in custom CMake projects. This builds
-an equivalent application to the `hello_world` example under `examples/get-started/hello_world`.
+This example illustrates using ESP-IDF components as libraries in custom CMake projects. The application
+in this example can run on either host or on an ESP32, and the appropriate libraries are linked
+to the executable depending on which target is specified. If the target is an ESP32, the libraries
+created from ESP-IDF components are linked. On the other hand, stub libraries are linked if example
+is meant to be run on the host to simulate the same application behavior.
+
+The application in this example is equivalent to the `hello_world` example under `examples/get-started/hello_world`.
 
 ## Example Flow
 
 Users looking at this example should focus on the [top-level CMakeLists.txt file](./CMakeLists.txt). This builds an
-application that can run on targets without relying on the typical ESP-IDF application template. The application itself
-follows a similar code flow to the aforementioned `hello_world` example.
+application that can run on the target without relying on the typical ESP-IDF application template.
 
 ### Output
 
@@ -29,41 +33,38 @@ Restarting in 0 seconds...
 
 ## Building this Example
 
-To build this example, run the following commands from this directory:
+To build this example, the user can either run [build-esp32.sh](./build-esp32.sh) to build for the ESP32
+or run [build.sh](./build.sh) to build for the host:
 
 ```bash
-# Create a build directory, and change location to that directory.
-mkdir build; cd build
-# Invoke CMake, specifying the top-level CMakeLists.txt directory and toolchain file to use. This will generate
-# the build system files.
-cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DIDF_TARGET=esp32
-# Build using the generated build system files.
-cmake --build .
+# Builds the example for ESP32
+./build-esp32.sh
 ```
 
-Or, execute `build.sh` script, which contains the same commands mentioned above.
+or
 
-## Flashing and Running this Example
+```bash
+# Builds the example to run on host
+./build.sh
+```
 
-To flash this example, we will have to invoke `esptool.py` and `idf_monitor.py` manually. While still in the build directory:
+## Flashing and Running this Example
 
-### Flashing to target
+To flash and run the example, users can run either  [run-esp32.sh](./run-esp32.sh) or [run.sh](./run.sh) depending
+on what the example was built for. In the case of ``run-esp32.sh``, the port needs to be specified:
 
 ```bash
-# Write project binaries to flash.
-esptool.py --port /dev/ttyUSB0 write_flash @flash_project_args
+# Run the example on device connected to /dev/ttyUSB1
+./run-esp32.sh /dev/ttyUSB1
 ```
 
-### Running on target
+or
 
 ```bash
-# Monitor the output of the flashed firmware.
-idf_monitor.py --port /dev/ttyUSB0 idf_as_lib.elf
+# Run the example on the host
+./run.sh
 ```
 
-Of course, you should replace the specified ports in the commands specified above to the proper one where your device
-is connected.
-
 ---
 
 There is a discussion on using ESP-IDF in custom CMake projects in the programming guide under `API Guides` -> `Build System (CMake)` -> `Using ESP-IDF in Custom CMake Projects`
diff --git a/examples/build_system/cmake/idf_as_lib/build-esp32.sh b/examples/build_system/cmake/idf_as_lib/build-esp32.sh
new file mode 100755 (executable)
index 0000000..a313c6c
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+rm -rf build && mkdir build && cd build
+cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DTARGET=esp32 -GNinja
+cmake --build .
\ No newline at end of file
index 23de02c8361f37bab89e9623b544d7a0ef22b8f1..85ffed78953cac2bf331fbdfb5377ef49c85c889 100755 (executable)
@@ -1,8 +1,4 @@
 #!/bin/bash
-#
-# Build this example, which does not use that standard IDF app template. See README.md for
-# more information about the build and how to run this example on the target once built.
-
-mkdir build; cd build
-cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DIDF_TARGET=esp32
+rm -rf build && mkdir build && cd build
+cmake .. 
 cmake --build .
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/run-esp32.sh b/examples/build_system/cmake/idf_as_lib/run-esp32.sh
new file mode 100755 (executable)
index 0000000..ab1677a
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+cd build
+python $IDF_PATH/components/esptool_py/esptool/esptool.py -p $1 write_flash @flash_project_args
+python $IDF_PATH/tools/idf_monitor.py -p $1 idf_as_lib.elf
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/run.sh b/examples/build_system/cmake/idf_as_lib/run.sh
new file mode 100755 (executable)
index 0000000..30186ca
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+cd build
+./idf_as_lib.elf
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/esp32/CMakeLists.txt b/examples/build_system/cmake/idf_as_lib/stubs/esp32/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e8d2da0
--- /dev/null
@@ -0,0 +1,6 @@
+add_library(stub_esp32 STATIC system_api.c flash_ops.c cpu_start.c)
+target_include_directories(stub_esp32 PUBLIC .)
+add_library(stub::esp32 ALIAS stub_esp32)
+
+target_link_libraries(stub_esp32 "-u app_main")
+target_link_libraries(stub_esp32 stub::spi_flash)
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/esp32/cpu_start.c b/examples/build_system/cmake/idf_as_lib/stubs/esp32/cpu_start.c
new file mode 100644 (file)
index 0000000..44eedcb
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdbool.h>
+#include <setjmp.h>
+
+extern void app_main();
+jmp_buf buf;
+
+int main()
+{
+    setjmp(buf);
+    app_main();
+}
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/esp32/esp_system.h b/examples/build_system/cmake/idf_as_lib/stubs/esp32/esp_system.h
new file mode 100644 (file)
index 0000000..3bee3f7
--- /dev/null
@@ -0,0 +1,15 @@
+#pragma once
+#include <stdint.h>
+
+#define CHIP_FEATURE_EMB_FLASH  (1UL << 0)
+#define CHIP_FEATURE_BT         (1UL << 4)
+#define CHIP_FEATURE_BLE        (1UL << 5)
+
+typedef struct {
+    uint32_t features;       //!< bit mask of CHIP_FEATURE_x feature flags
+    uint8_t cores;           //!< number of CPU cores
+    uint8_t revision;        //!< chip revision number
+} esp_chip_info_t;
+
+void esp_restart(void);
+void esp_chip_info(esp_chip_info_t* out_info);
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/esp32/flash_ops.c b/examples/build_system/cmake/idf_as_lib/stubs/esp32/flash_ops.c
new file mode 100644 (file)
index 0000000..175e84b
--- /dev/null
@@ -0,0 +1,6 @@
+#include "esp_spi_flash.h"
+
+int spi_flash_get_chip_size()
+{
+    return (1024 * 1024 * 1024);
+}
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/esp32/system_api.c b/examples/build_system/cmake/idf_as_lib/stubs/esp32/system_api.c
new file mode 100644 (file)
index 0000000..8a83c75
--- /dev/null
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <setjmp.h>
+#include "esp_system.h"
+
+extern jmp_buf buf;
+
+void esp_restart(void) 
+{
+    printf("\n");
+    sleep(1); // pause for dramatic effect
+    longjmp(buf, 0);
+}
+
+void esp_chip_info(esp_chip_info_t* out_info)
+{
+    out_info->cores = 8;
+    out_info->features = (uint32_t) -1;
+}
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/freertos/CMakeLists.txt b/examples/build_system/cmake/idf_as_lib/stubs/freertos/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5a96eb3
--- /dev/null
@@ -0,0 +1,3 @@
+add_library(stub_freertos STATIC task.c)
+target_include_directories(stub_freertos PUBLIC .)
+add_library(stub::freertos ALIAS stub_freertos)
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/freertos/freertos/FreeRTOS.h b/examples/build_system/cmake/idf_as_lib/stubs/freertos/freertos/FreeRTOS.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/freertos/freertos/task.h b/examples/build_system/cmake/idf_as_lib/stubs/freertos/freertos/task.h
new file mode 100644 (file)
index 0000000..6962f70
--- /dev/null
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <stdint.h>
+
+#define portTICK_PERIOD_MS  1000
+
+void vTaskDelay( const uint32_t xTicksToDelay );
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/freertos/task.c b/examples/build_system/cmake/idf_as_lib/stubs/freertos/task.c
new file mode 100644 (file)
index 0000000..5a752ec
--- /dev/null
@@ -0,0 +1,7 @@
+#include <unistd.h>
+#include "freertos/task.h"
+
+void vTaskDelay( const uint32_t xTicksToDelay )
+{
+    sleep(xTicksToDelay);
+}
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/spi_flash/CMakeLists.txt b/examples/build_system/cmake/idf_as_lib/stubs/spi_flash/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1f2d357
--- /dev/null
@@ -0,0 +1,3 @@
+add_library(stub_spi_flash INTERFACE)
+target_include_directories(stub_spi_flash INTERFACE .)
+add_library(stub::spi_flash ALIAS stub_spi_flash)
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/stubs/spi_flash/esp_spi_flash.h b/examples/build_system/cmake/idf_as_lib/stubs/spi_flash/esp_spi_flash.h
new file mode 100644 (file)
index 0000000..544f361
--- /dev/null
@@ -0,0 +1,5 @@
+#pragma once
+
+#include <stddef.h>
+
+int spi_flash_get_chip_size();
\ No newline at end of file
index a392c56cd550d1a823fcfb34062809746e4b9fc3..e19d255c1491f41f3db14bec0f49315437e336f3 100755 (executable)
@@ -66,7 +66,7 @@ LOG_SUSPECTED=${LOG_PATH}/common_log.txt
 touch ${LOG_SUSPECTED}
 SDKCONFIG_DEFAULTS_CI=sdkconfig.ci
 
-EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name CMakeLists.txt | grep -v "/components/" | grep -v "/common_components/" | grep -v "/main/" | sort )
+EXAMPLE_PATHS=$( find ${IDF_PATH}/examples/ -type f -name CMakeLists.txt | grep -v "/components/" | grep -v "/common_components/" | grep -v "/main/" | grep -v "/idf_as_lib/stubs/" | sort )
 
 if [ $# -eq 0 ]
 then
@@ -142,7 +142,7 @@ build_example () {
             idf.py build >>${BUILDLOG} 2>&1
         else
             rm -rf build &&
-            ./build.sh >>${BUILDLOG} 2>&1
+            ./build-esp32.sh >>${BUILDLOG} 2>&1
         fi ||
         {
             RESULT=$?; FAILED_EXAMPLES+=" ${EXAMPLE_NAME}" ;
index 707861073c513593cc60d07050de03f18eb85141..14071ab2eb16c425e941f865aead6a84842a2a9c 100644 (file)
@@ -73,7 +73,10 @@ components/espcoredump/test/test_espcoredump.sh
 tools/ldgen/ldgen.py
 tools/ldgen/test/test_fragments.py
 tools/ldgen/test/test_generation.py
+examples/build_system/cmake/idf_as_lib/build-esp32.sh
 examples/build_system/cmake/idf_as_lib/build.sh
+examples/build_system/cmake/idf_as_lib/run-esp32.sh
+examples/build_system/cmake/idf_as_lib/run.sh
 examples/storage/parttool/parttool_example.py
 examples/system/ota/otatool/otatool_example.py
 tools/check_kconfigs.py
index 016b50d03094bb6b8958c649ad6aa1d4088274db..7474eb8d985bdfd360fbbd6625fcdad112247e54 100755 (executable)
@@ -342,6 +342,7 @@ function run_tests()
     rm sdkconfig.defaults;
 
     print_status "Building a project with CMake library imported and PSRAM workaround, all files compile with workaround"
+    # Test for libraries compiled within ESP-IDF
     rm -rf build
     echo "CONFIG_SPIRAM_SUPPORT=y" >> sdkconfig.defaults
     echo "CONFIG_SPIRAM_CACHE_WORKAROUND=y" >> sdkconfig.defaults
@@ -349,7 +350,16 @@ function run_tests()
     idf.py -C $IDF_PATH/examples/build_system/cmake/import_lib -B `pwd`/build reconfigure -D SDKCONFIG_DEFAULTS="`pwd`/sdkconfig.defaults"
     grep -q '"command"' build/compile_commands.json || failure "compile_commands.json missing or has no no 'commands' in it"
     (grep '"command"' build/compile_commands.json | grep -v mfix-esp32-psram-cache-issue) && failure "All commands in compile_commands.json should use PSRAM cache workaround"
-    rm sdkconfig.defaults
+    rm -r sdkconfig.defaults build
+    # Test for external libraries in custom CMake projects with ESP-IDF components linked
+    mkdir build && touch build/sdkconfig
+    echo "CONFIG_SPIRAM_SUPPORT=y" >> build/sdkconfig
+    echo "CONFIG_SPIRAM_CACHE_WORKAROUND=y" >> build/sdkconfig
+    # note: we just need to run cmake
+    (cd build && cmake $IDF_PATH/examples/build_system/cmake/idf_as_lib -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DTARGET=esp32)
+    grep -q '"command"' build/compile_commands.json || failure "compile_commands.json missing or has no no 'commands' in it"
+    (grep '"command"' build/compile_commands.json | grep -v mfix-esp32-psram-cache-issue) && failure "All commands in compile_commands.json should use PSRAM cache workaround"
+    rm -r build
 
     print_status "Make sure a full build never runs '/usr/bin/env python' or similar"
     OLDPATH="$PATH"