]> granicus.if.org Git - esp-idf/commitdiff
examples: generic cmake support examples
authorRenz Christian Bagaporo <renz@espressif.com>
Sun, 11 Nov 2018 07:36:24 +0000 (15:36 +0800)
committerRenz Christian Bagaporo <renz@espressif.com>
Tue, 27 Nov 2018 05:59:26 +0000 (13:59 +0800)
17 files changed:
.gitmodules
examples/README.md
examples/build_system/cmake/idf_as_lib/CMakeLists.txt [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/README.md [new file with mode: 0644]
examples/build_system/cmake/idf_as_lib/build.sh [new file with mode: 0755]
examples/build_system/cmake/idf_as_lib/main.c [new file with mode: 0644]
examples/build_system/cmake/import_lib/CMakeLists.txt [new file with mode: 0644]
examples/build_system/cmake/import_lib/README.md [new file with mode: 0644]
examples/build_system/cmake/import_lib/main/CMakeLists.txt [new file with mode: 0644]
examples/build_system/cmake/import_lib/main/lib/tinyxml2 [new submodule]
examples/build_system/cmake/import_lib/main/main.cpp [new file with mode: 0644]
examples/build_system/cmake/import_lib/main/sample.xml [new file with mode: 0644]
examples/build_system/cmake/import_lib/partitions_example.csv [new file with mode: 0644]
examples/build_system/cmake/import_lib/sdkconfig.defaults [new file with mode: 0644]
examples/get-started/hello_world/CMakeLists.txt
examples/system/ota/native_ota_example/main/CMakeLists.txt
examples/system/ota/simple_ota_example/main/CMakeLists.txt

index eb60d7eaa5f2d86704ff321e59e93ab070ed041f..a9489d8a1a1952b00a6af8fc927e3f54a5326f69 100644 (file)
 [submodule "components/protobuf-c/protobuf-c"]
        path = components/protobuf-c/protobuf-c
        url = https://github.com/protobuf-c/protobuf-c
+
 [submodule "components/unity/unity"]
        path = components/unity/unity
        url = https://github.com/ThrowTheSwitch/Unity
+
+[submodule "examples/build_system/cmake/import_lib/main/lib/tinyxml2"]
+       path = examples/build_system/cmake/import_lib/main/lib/tinyxml2
+       url = https://github.com/leethomason/tinyxml2
index b164fc30fb535d41f3c4042076f8f8d3e901523f..62e0b73bd574976ba2d286af68f87c3ceb82f812 100644 (file)
@@ -15,6 +15,7 @@ The examples are grouped into subdirectories by category. Each category director
 * `storage` contains examples showing data storage methods using SPI flash or external storage like the SD/MMC interface.
 * `system` contains examples which demonstrate some internal chip features, or debugging & development tools.
 * `wifi` contains examples of advanced Wi-Fi features. (For network protocol examples, see `protocols` instead.)
+* `build_system` contains examples of build system features
 
 # Using Examples
 
diff --git a/examples/build_system/cmake/idf_as_lib/CMakeLists.txt b/examples/build_system/cmake/idf_as_lib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ba0176f
--- /dev/null
@@ -0,0 +1,24 @@
+cmake_minimum_required(VERSION 3.5)
+project(idf_as_lib C)
+
+# The source file main.c contains app_main() definition
+add_executable(${CMAKE_PROJECT_NAME}.elf main.c)
+
+# Provides idf_import_components() and idf_link_components()
+include($ENV{IDF_PATH}/tools/cmake/idf_functions.cmake)
+
+# Create artifacts used for flashing the project to target chip
+set(IDF_BUILD_ARTIFACTS ON)
+set(IDF_PROJECT_EXECUTABLE ${CMAKE_PROJECT_NAME}.elf)
+set(IDF_BUILD_ARTIFACTS_DIR ${CMAKE_BINARY_DIR})
+
+# Trim down components included in the build. Although freertos and spi_flash are the ones needed by the application
+# itself, the bootloader and esptool_py components are also needed in order to create the artifacts to be used
+# for flashing to the target chip
+set(IDF_COMPONENTS freertos spi_flash bootloader esptool_py)
+
+# Wraps add_subdirectory() to create library targets for components, and then return them using the specified variable
+idf_import_components(components $ENV{IDF_PATH} esp-idf)
+
+# Wraps target_link_libraries() to link processed components by idf_import_components to target
+idf_link_components(${CMAKE_PROJECT_NAME}.elf "${components}")
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/README.md b/examples/build_system/cmake/idf_as_lib/README.md
new file mode 100644 (file)
index 0000000..19506a8
--- /dev/null
@@ -0,0 +1,69 @@
+# Using ESP-IDF in Custom CMake Projects
+
+This example illustrates using ESP-IDF components as libraries in custom CMake projects. This builds
+an equivalent application to the `hello_world` example under `examples/get-started/hello_world`.
+
+## Example Flow
+
+Users looking at this example should focus on the [top-level CMakeLists.txt file](./CMakeLists.txt). This builds an
+application that can run on targets without relying on the typical ESP-IDF application template. The application itself
+follows a similar code flow to the aforementioned `hello_world` example.
+
+### Output
+
+```
+Hello world!
+This is ESP32 chip with 2 CPU cores, WiFi/BT/BLE, silicon revision 0, 4MB external flash
+Restarting in 10 seconds...
+Restarting in 9 seconds...
+Restarting in 8 seconds...
+Restarting in 7 seconds...
+Restarting in 6 seconds...
+Restarting in 5 seconds...
+Restarting in 4 seconds...
+Restarting in 3 seconds...
+Restarting in 2 seconds...
+Restarting in 1 seconds...
+Restarting in 0 seconds...
+```
+
+## Building this Example
+
+To build this example, run the following commands from this directory:
+
+```bash
+# Create a build directory, and change location to that directory.
+mkdir build; cd build
+# Invoke CMake, specifying the top-level CMakeLists.txt directory and toolchain file to use. This will generate
+# the build system files.
+cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DIDF_TARGET=esp32
+# Build using the generated build system files.
+cmake --build .
+```
+
+Or, execute `build.sh` script, which contains the same commands mentioned above.
+
+## Flashing and Running this Example
+
+To flash this example, we will have to invoke `esptool.py` and `idf_monitor.py` manually. While still in the build directory:
+
+### Flashing to target
+
+```bash
+# Write project binaries to flash.
+esptool.py --port /dev/ttyUSB0 write_flash @flash_project_args
+```
+
+### Running on target
+
+```bash
+# Monitor the output of the flashed firmware.
+idf_monitor.py --port /dev/ttyUSB0 idf_as_lib.elf
+```
+
+Of course, you should replace the specified ports in the commands specified above to the proper one where your device
+is connected.
+
+---
+
+There is a discussion on using ESP-IDF in custom CMake projects in the programming guide under `API Guides` -> `Build System (CMake)` -> `Using ESP-IDF in Custom CMake Projects`
diff --git a/examples/build_system/cmake/idf_as_lib/build.sh b/examples/build_system/cmake/idf_as_lib/build.sh
new file mode 100755 (executable)
index 0000000..23de02c
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/bash
+#
+# Build this example, which does not use that standard IDF app template. See README.md for
+# more information about the build and how to run this example on the target once built.
+
+mkdir build; cd build
+cmake .. -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32.cmake -DIDF_TARGET=esp32
+cmake --build .
\ No newline at end of file
diff --git a/examples/build_system/cmake/idf_as_lib/main.c b/examples/build_system/cmake/idf_as_lib/main.c
new file mode 100644 (file)
index 0000000..59f0aa0
--- /dev/null
@@ -0,0 +1,39 @@
+/* Hello World Example
+
+   This example code is in the Public Domain (or CC0 licensed, at your option.)
+
+   Unless required by applicable law or agreed to in writing, this
+   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+   CONDITIONS OF ANY KIND, either express or implied.
+*/
+#include <stdio.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_system.h"
+#include "esp_spi_flash.h"
+
+void app_main()
+{
+    printf("Hello world!\n");
+
+    /* Print chip information */
+    esp_chip_info_t chip_info;
+    esp_chip_info(&chip_info);
+    printf("This is ESP32 chip with %d CPU cores, WiFi%s%s, ",
+            chip_info.cores,
+            (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
+            (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
+
+    printf("silicon revision %d, ", chip_info.revision);
+
+    printf("%dMB %s flash\n", spi_flash_get_chip_size() / (1024 * 1024),
+            (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
+
+    for (int i = 10; i >= 0; i--) {
+        printf("Restarting in %d seconds...\n", i);
+        vTaskDelay(1000 / portTICK_PERIOD_MS);
+    }
+    printf("Restarting now.\n");
+    fflush(stdout);
+    esp_restart();
+}
diff --git a/examples/build_system/cmake/import_lib/CMakeLists.txt b/examples/build_system/cmake/import_lib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e145bd4
--- /dev/null
@@ -0,0 +1,6 @@
+# The following lines of boilerplate have to be in your project's
+# CMakeLists in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(import_cmake_lib)
diff --git a/examples/build_system/cmake/import_lib/README.md b/examples/build_system/cmake/import_lib/README.md
new file mode 100644 (file)
index 0000000..e24090a
--- /dev/null
@@ -0,0 +1,36 @@
+# Import Third-Party CMake Library Example
+
+This example demonstrates how to import third-party CMake libraries.
+
+## Example Flow
+
+[tinyxml2](https://github.com/leethomason/tinyxml2) is a 
+a small C++ XML parser. It is imported, without modification, for use in the project's `main` component (see the `main` component's [CMakeLists.txt](main/CMakeLists.txt)). To demonstrate the library being used, a sample XML is embedded into the project.
+This sample XML is then read and parsed later on using `tinyxml2`.
+
+### Output
+
+```
+I (317) example: Setting up...
+I (317) example: Copying sample XML to filesystem...
+I (647) example: Reading XML file
+I (657) example: Read XML data:
+<?xml version="1.0" encoding="UTF-8"?>
+<note>
+    <to>Tove</to>
+    <from>Jani</from>
+    <heading>Reminder</heading>
+    <body>Don't forget me this weekend!</body>
+</note>
+
+I (667) example: Parsed XML data:
+
+To: Tove
+From: Jani
+Heading: Reminder
+Body: Don't forget me this weekend!
+I (677) example: Example end
+```
+---
+
+There is a discussion on importing third-party CMake libraries in the programming guide under `API Guides` -> `Build System (CMake)` -> `Using Third-Party CMake Projects with Components`
diff --git a/examples/build_system/cmake/import_lib/main/CMakeLists.txt b/examples/build_system/cmake/import_lib/main/CMakeLists.txt
new file mode 100644 (file)
index 0000000..92d44e3
--- /dev/null
@@ -0,0 +1,21 @@
+set(COMPONENT_SRCS "main.cpp")
+set(COMPONENT_ADD_INCLUDEDIRS ".")
+
+set(COMPONENT_EMBED_TXTFILES "sample.xml")
+
+register_component()
+
+# Build static library, do not build test executables
+option(BUILD_SHARED_LIBS OFF)
+option(BUILD_TESTING OFF)
+
+# Import tinyxml2 targets 
+add_subdirectory(lib/tinyxml2)
+
+# Propagate compile settings to tinyxml2
+target_include_directories(tinyxml2 PRIVATE ${IDF_INCLUDE_DIRECTORIES})
+target_compile_options(tinyxml2 PRIVATE "${IDF_COMPILE_OPTIONS}")
+target_compile_options(tinyxml2 PRIVATE "${IDF_CXX_COMPILE_OPTIONS}")
+
+# Link tinyxml2 to main component
+target_link_libraries(${COMPONENT_TARGET} tinyxml2)
diff --git a/examples/build_system/cmake/import_lib/main/lib/tinyxml2 b/examples/build_system/cmake/import_lib/main/lib/tinyxml2
new file mode 160000 (submodule)
index 0000000..7e8e249
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit 7e8e249990ec491ec15990cf95b6d871a66cf64a
diff --git a/examples/build_system/cmake/import_lib/main/main.cpp b/examples/build_system/cmake/import_lib/main/main.cpp
new file mode 100644 (file)
index 0000000..6df76dc
--- /dev/null
@@ -0,0 +1,72 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/unistd.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_vfs_fat.h"
+#include "lib/tinyxml2/tinyxml2.h"
+
+using namespace tinyxml2;
+
+static const char *TAG = "example";
+
+// Handle of the wear levelling library instance
+static wl_handle_t s_wl_handle = WL_INVALID_HANDLE;
+
+// Mount path for the partition
+const char *base_path = "/spiflash";
+
+extern "C" void app_main(void)
+{
+    // Do example setup
+    ESP_LOGI(TAG, "Setting up...");
+    esp_vfs_fat_mount_config_t mount_config;
+    mount_config.max_files = 4;
+    mount_config.format_if_mount_failed = true;
+    mount_config.allocation_unit_size = CONFIG_WL_SECTOR_SIZE;
+
+    esp_err_t err = esp_vfs_fat_spiflash_mount(base_path, "storage", &mount_config, &s_wl_handle);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(err));
+        return;
+    }
+
+    // The sample XML is embedded binary data. Create a file first containing the embedded
+    // so it can be accessed.
+    ESP_LOGI(TAG, "Copying sample XML to filesystem...");
+
+    extern const char data_start[] asm("_binary_sample_xml_start");
+    extern const char data_end[]   asm("_binary_sample_xml_end");
+    FILE *f = fopen("/spiflash/sample.xml", "wb");
+
+    if (f == NULL) {
+        ESP_LOGE(TAG, "Failed to open file for writing");
+        return;
+    }
+    fwrite(data_start, sizeof(char), data_end - data_start + 1, f);
+    fclose(f);
+
+    // Now that the file is created, load it using tinyxml2 and parse
+    ESP_LOGI(TAG, "Reading XML file");
+
+    XMLDocument data;
+    data.LoadFile("/spiflash/sample.xml");
+
+    XMLPrinter printer;
+    data.Print(&printer);
+
+    ESP_LOGI(TAG, "Read XML data:\n%s", printer.CStr());
+
+    const char* to_data = data.FirstChildElement("note")->FirstChildElement("to")->GetText();
+    const char* from_data = data.FirstChildElement("note")->FirstChildElement("from")->GetText();
+    const char* heading_data = data.FirstChildElement("note")->FirstChildElement("heading")->GetText();
+    const char* body_data = data.FirstChildElement("note")->FirstChildElement("body")->GetText();
+
+    ESP_LOGI(TAG, "Parsed XML data:\n\nTo: %s\nFrom: %s\nHeading: %s\nBody: %s",
+                to_data, from_data, heading_data, body_data);
+
+    ESP_LOGI(TAG, "Example end");
+}
\ No newline at end of file
diff --git a/examples/build_system/cmake/import_lib/main/sample.xml b/examples/build_system/cmake/import_lib/main/sample.xml
new file mode 100644 (file)
index 0000000..fa0c0a5
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<note>
+  <to>Tove</to>
+  <from>Jani</from>
+  <heading>Reminder</heading>
+  <body>Don't forget me this weekend!</body>
+</note>
\ No newline at end of file
diff --git a/examples/build_system/cmake/import_lib/partitions_example.csv b/examples/build_system/cmake/import_lib/partitions_example.csv
new file mode 100644 (file)
index 0000000..3e95433
--- /dev/null
@@ -0,0 +1,6 @@
+# Name,   Type, SubType, Offset,  Size, Flags
+# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
+nvs,      data, nvs,     0x9000,  0x6000,
+phy_init, data, phy,     0xf000,  0x1000,
+factory,  app,  factory, 0x10000, 1M,
+storage,  data, fat,  ,        528K, 
diff --git a/examples/build_system/cmake/import_lib/sdkconfig.defaults b/examples/build_system/cmake/import_lib/sdkconfig.defaults
new file mode 100644 (file)
index 0000000..f30f322
--- /dev/null
@@ -0,0 +1,5 @@
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_example.csv"
+CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000
+CONFIG_PARTITION_TABLE_FILENAME="partitions_example.csv"
+CONFIG_APP_OFFSET=0x10000
index 8a022b8486b73a856a8a6b4a505a3e64894afbb1..519e5a1d7bcc27516dcf7faf99361908ca960950 100644 (file)
@@ -3,4 +3,4 @@
 cmake_minimum_required(VERSION 3.5)
 
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
-project(hello-world)
+project(hello-world)
\ No newline at end of file
index a700e0b3b4edb6f455101e07d98b3c027546589c..fa4644e4556f88c7634dd0f89a9e4d228d7cc4a7 100644 (file)
@@ -2,6 +2,6 @@ set(COMPONENT_SRCS "native_ota_example.c")
 set(COMPONENT_ADD_INCLUDEDIRS ".")
 
 # Embed the server root certificate into the final binary
-set(COMPONENT_EMBED_TXTFILES ${PROJECT_PATH}/server_certs/ca_cert.pem)
+set(COMPONENT_EMBED_TXTFILES ${IDF_PROJECT_PATH}/server_certs/ca_cert.pem)
 
 register_component()
index 8adb69a8f7f137fc59cf9120f704d76fcdd5b1bf..98a7208f86a2a79f9c06f0bd473a1e189a121373 100644 (file)
@@ -3,6 +3,6 @@ set(COMPONENT_ADD_INCLUDEDIRS ".")
 
 
 # Embed the server root certificate into the final binary
-set(COMPONENT_EMBED_TXTFILES ${PROJECT_PATH}/server_certs/ca_cert.pem)
+set(COMPONENT_EMBED_TXTFILES ${IDF_PROJECT_PATH}/server_certs/ca_cert.pem)
 
 register_component()