mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(cmakev2): Added import_lib_direct example for cmakev2
This commit adds a new example at examples/build_system/cmakev2/features/import_lib_direct to demonstrate the cmakev2 ability to integrate with external CMake projects easily.
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
# This example demonstrates a cmakev2 capability of importing an external
|
||||
# C library via FetchContent, built by its own CMake, and linked directly
|
||||
# to an IDF component without any IDF component wrapper for the library.
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmakev2/idf.cmake)
|
||||
|
||||
project(import_lib_direct C CXX ASM)
|
||||
|
||||
idf_project_default()
|
||||
@@ -0,0 +1,61 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
# Import External C Library Directly (cmakev2)
|
||||
|
||||
This example demonstrates importing an external C library that is a pure CMake project. It is downloaded at configure time, built by its own CMake, and linked directly to the IDF app without wrapping it as an IDF component.
|
||||
|
||||
## Overview
|
||||
|
||||
In Build System v1, integrating third-party CMake libraries required wrapping them as IDF components (see the `import_lib` example). With cmakev2, CMake's `FetchContent` module can be used to fetch and build an external CMake library (lwjson) and link the library to an IDF component using `target_link_libraries`.
|
||||
|
||||
This example uses [lwjson](https://github.com/MaJerle/lwjson), a lightweight JSON parser for embedded systems.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
import_lib_direct/
|
||||
├── CMakeLists.txt # Initialize the IDF project
|
||||
├── README.md
|
||||
└── main/
|
||||
├── CMakeLists.txt # FetchContent for lwjson, register component, link
|
||||
└── main.c # Uses lwjson API
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. The **main component's CMakeLists.txt** uses `FetchContent_Declare()` and `FetchContent_MakeAvailable()` to download and build lwjson at configure time. The fetched sources land in `./build/_deps/`.
|
||||
|
||||
2. After registering the main omponent with `idf_component_register`, it links the fetched library:
|
||||
```cmake
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC lwjson)
|
||||
```
|
||||
|
||||
3. **main.c** uses the lwjson API (`lwjson_init`, `lwjson_parse`, `lwjson_find`, etc.) to parse a sample JSON string and print device name, cores, features, and specs.
|
||||
|
||||
## How to Use
|
||||
|
||||
Build and flash the example:
|
||||
|
||||
```bash
|
||||
idf.py set-target <target>
|
||||
idf.py build
|
||||
idf.py flash monitor
|
||||
```
|
||||
|
||||
## Expected Output
|
||||
|
||||
```
|
||||
I (275) import_lib_direct: lwjson library imported directly (downloaded, built, linked) without IDF component wrapper
|
||||
I (275) import_lib_direct: Parsing JSON string...
|
||||
I (285) import_lib_direct: Device name: ESP32
|
||||
I (285) import_lib_direct: Number of cores: 2
|
||||
I (285) import_lib_direct: Features:
|
||||
I (295) import_lib_direct: - WiFi
|
||||
I (295) import_lib_direct: - Bluetooth
|
||||
I (295) import_lib_direct: - GPIO
|
||||
I (305) import_lib_direct: Specifications:
|
||||
I (305) import_lib_direct: Flash: 4MB
|
||||
I (305) import_lib_direct: RAM: 520KB
|
||||
I (315) import_lib_direct: Example complete!
|
||||
```
|
||||
@@ -0,0 +1,15 @@
|
||||
# Fetch the external lwjson library at configure time.
|
||||
include(FetchContent)
|
||||
fetchcontent_declare(
|
||||
lwjson
|
||||
GIT_REPOSITORY https://github.com/MaJerle/lwjson.git
|
||||
GIT_TAG v1.8.1
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
fetchcontent_makeavailable(lwjson)
|
||||
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
# Link the fetched lwjson library to this component
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC lwjson)
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* This example demonstrates importing an external C library (lwjson)
|
||||
* via FetchContent, built by its own CMake, and linked directly to this IDF component
|
||||
* without any IDF component wrapper.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "lwjson/lwjson.h"
|
||||
|
||||
static const char *TAG = "import_lib_direct";
|
||||
|
||||
#define LWJSON_TOKENS 64
|
||||
|
||||
/* Sample JSON string to parse */
|
||||
static const char *sample_json =
|
||||
"{"
|
||||
" \"name\": \"ESP32\","
|
||||
" \"cores\": 2,"
|
||||
" \"features\": [\"WiFi\", \"Bluetooth\", \"GPIO\"],"
|
||||
" \"specs\": {"
|
||||
" \"flash\": \"4MB\","
|
||||
" \"ram\": \"520KB\""
|
||||
" }"
|
||||
"}";
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "lwjson library imported directly (downloaded, built, linked) without IDF component wrapper");
|
||||
|
||||
static lwjson_token_t tokens[LWJSON_TOKENS];
|
||||
lwjson_t lwobj;
|
||||
|
||||
if (lwjson_init(&lwobj, tokens, LWJSON_TOKENS) != lwjsonOK) {
|
||||
ESP_LOGE(TAG, "lwjson_init failed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (lwjson_parse(&lwobj, sample_json) != lwjsonOK) {
|
||||
ESP_LOGE(TAG, "lwjson_parse failed");
|
||||
lwjson_free(&lwobj);
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Parsing JSON string...");
|
||||
|
||||
const lwjson_token_t *name_t = lwjson_find(&lwobj, "name");
|
||||
if (name_t != NULL) {
|
||||
size_t len;
|
||||
const char *s = lwjson_get_val_string(name_t, &len);
|
||||
if (s != NULL) {
|
||||
ESP_LOGI(TAG, "Device name: %.*s", (int)len, s);
|
||||
}
|
||||
}
|
||||
|
||||
const lwjson_token_t *cores_t = lwjson_find(&lwobj, "cores");
|
||||
if (cores_t != NULL && cores_t->type == LWJSON_TYPE_NUM_INT) {
|
||||
ESP_LOGI(TAG, "Number of cores: %lld", (long long)lwjson_get_val_int(cores_t));
|
||||
}
|
||||
|
||||
const lwjson_token_t *features_t = lwjson_find(&lwobj, "features");
|
||||
if (features_t != NULL && features_t->type == LWJSON_TYPE_ARRAY) {
|
||||
ESP_LOGI(TAG, "Features:");
|
||||
const lwjson_token_t *child = lwjson_get_first_child(features_t);
|
||||
while (child != NULL) {
|
||||
if (child->type == LWJSON_TYPE_STRING) {
|
||||
size_t len;
|
||||
const char *s = lwjson_get_val_string(child, &len);
|
||||
if (s != NULL) {
|
||||
ESP_LOGI(TAG, " - %.*s", (int)len, s);
|
||||
}
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
}
|
||||
|
||||
const lwjson_token_t *flash_t = lwjson_find(&lwobj, "specs.flash");
|
||||
const lwjson_token_t *ram_t = lwjson_find(&lwobj, "specs.ram");
|
||||
if (flash_t != NULL || ram_t != NULL) {
|
||||
ESP_LOGI(TAG, "Specifications:");
|
||||
if (flash_t != NULL) {
|
||||
size_t len;
|
||||
const char *s = lwjson_get_val_string(flash_t, &len);
|
||||
if (s != NULL) {
|
||||
ESP_LOGI(TAG, " Flash: %.*s", (int)len, s);
|
||||
}
|
||||
}
|
||||
if (ram_t != NULL) {
|
||||
size_t len;
|
||||
const char *s = lwjson_get_val_string(ram_t, &len);
|
||||
if (s != NULL) {
|
||||
ESP_LOGI(TAG, " RAM: %.*s", (int)len, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lwjson_free(&lwobj);
|
||||
|
||||
ESP_LOGI(TAG, "Example complete!");
|
||||
}
|
||||
Reference in New Issue
Block a user