From 84db063a5581356edf3ed60e5a7ca9f6ce6e21f6 Mon Sep 17 00:00:00 2001 From: FBEZ Date: Thu, 14 Aug 2025 11:57:27 +0200 Subject: [PATCH] Added porting library as esp-idf component article, moved folder, implemented review --- .../featured.webp | Bin 0 -> 33168 bytes .../img/new_project.webp | Bin 0 -> 18448 bytes .../index.md | 289 ++++++++++++++++++ 3 files changed, 289 insertions(+) create mode 100644 content/blog/2025/10/porting-external-library-as-component/featured.webp create mode 100644 content/blog/2025/10/porting-external-library-as-component/img/new_project.webp create mode 100644 content/blog/2025/10/porting-external-library-as-component/index.md diff --git a/content/blog/2025/10/porting-external-library-as-component/featured.webp b/content/blog/2025/10/porting-external-library-as-component/featured.webp new file mode 100644 index 0000000000000000000000000000000000000000..48500d28deb7a3af4eb8d05d0f80da88d7251950 GIT binary patch literal 33168 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 MsxWv+oYU5*01PUsi~s-t literal 0 HcmV?d00001 diff --git a/content/blog/2025/10/porting-external-library-as-component/img/new_project.webp b/content/blog/2025/10/porting-external-library-as-component/img/new_project.webp new file mode 100644 index 0000000000000000000000000000000000000000..b1692cb777ca274b85659db135b4b93d23a8b629 GIT binary patch literal 18448 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 literal 0 HcmV?d00001 diff --git a/content/blog/2025/10/porting-external-library-as-component/index.md b/content/blog/2025/10/porting-external-library-as-component/index.md new file mode 100644 index 000000000..d521d1b71 --- /dev/null +++ b/content/blog/2025/10/porting-external-library-as-component/index.md @@ -0,0 +1,289 @@ +--- +title: "Porting a library to an ESP-IDF component" +date: "2025-10-20" +summary: "This article shows how to port an external library into an ESP-IDF project by converting it into a reusable component. Using tinyexpr as an example, it covers obtaining the source code, creating a new project, building a component, configuring the build system, and testing on hardware." +authors: + - "francesco-bez" +tags: ["esp32c3", "component","porting"] +--- + +## Introduction + +When developing with [ESP-IDF](https://github.com/espressif/esp-idf), you may eventually need functionality that isn’t provided by its built-in components. In many cases, the solution is an open-source library from GitHub or another repository. However, these external libraries are not always structured for ESP-IDF, and simply copying their source files into your project can lead to messy integrations, difficult updates, and code that’s hard to reuse or share. + +A cleaner and more maintainable approach is to wrap the external library into a **reusable ESP-IDF component**. Components integrate naturally with the ESP-IDF build system, can be reused across multiple projects, and make sharing and maintaining code much easier. They also help keep your project organized and scalable over time. + +In this article, we’ll demonstrate this approach by porting the [tinyexpr](https://github.com/codeplea/tinyexpr?tab=readme-ov-file#tinyexpr) library into a fully functional ESP-IDF component, ready for reuse in future applications. +To keep things simple, we’ll start by manually adding the library’s source and header files into a new component structure. In a future article, we’ll extend this setup by adding the library as a git submodule, making it easier to stay synchronized with the upstream repository as new features or bug fixes are released. + +We’ll be using an **ESP32-C3-DevKitM-1** board and the **ESP-IDF Extension for VS Code**, though the same steps apply to other boards and SoCs. + +## Prepare to create a component + +To keep things straightforward, we will work with a self-contained library that does not rely on specific peripherals. A good example of such a library is _tinyexpr_, which we will use throughout this article. + +Integrating an external library as an ESP-IDF component involves several steps: + +1. Obtain library code +2. Set up a test project in ESP-IDF +3. Test the component +4. Solve compatibility issues + +These are the steps we will follow in the rest of the article. + +## Obtain library code + +The tinyexpr code is available on GitHub: + +{{< github repo="codeplea/tinyexpr" >}} + +We can clone the repository to inspect the files: + +```bash +git clone https://github.com/codeplea/tinyexpr.git +``` + +Although the repository contains several source files, the library itself consists of just two key files, as noted in the `README`: + +* `tinyexpr.h` +* `tinyexpr.c` + +There are also several examples in the repo, showing how to use the library. The simplest one is `example.c`, so it's a good idea to use it to test our component. + +## Set up a test project in ESP-IDF + +To work on the porting, we need to +1. Create a new project +2. Create a new component + +### Create a new project + +To keep things simple and organized, we will start with a basic project using a template app. You can follow one of the two approaches below: + +{{< tabs groupId="devtool" >}} + {{% tab name="ESP-IDF Extension for VS Code New Project" %}} + +* In VS Code command palette enter: `> ESP-IDF: New Project` + +You will be presented with a screen like Fig.1. +{{< figure +default=true +src="img/new_project.webp" +height=500 +caption="Fig.1 - Choosing the project settings" + >}} + +If you're using the ESP32-C3-DevKitM, fill the fields as follows: +* Project name: `esp_tinyexpr_test` +* Choose ESP-IDF Target: `esp32c3` +* Choose ESP-IDF Board: `ESP32-C3 chip (via builtin USB-JTAG)` +* Choose serial port: (e.g. `COM25` or `/dev/tty.usbserial-11133`) + +Feel free to change the settings according to your platform. + +* Click on `Choose Template` and select `template_app` +* Open the project with VS Code + +You should now have the following project structure: +```bash +. +├── CMakeLists.txt +├── main +│   ├── CMakeLists.txt +│   └── main.c +└── README.md +``` + + + {{% /tab %}} + {{% tab name="Clone basic example" %}} +* Download the basic example code found on [this github repo](https://github.com/FBEZ-docs-and-templates/devrel-tutorials-code/tree/main/tutorial-basic-project). +* Open the project with VSCode +* `> ESP-IDF: Set Espressif Device target` +* `> ESP-IDF: Select Port to Use` + + {{% /tab %}} +{{< /tabs >}} + + +### Create a new component + +Next, we will create a new component named `my_tinyexpr` to hold the `tinyexpr` files. + +* Select `> ESP-IDF: Create New ESP-IDF Component` + + * Name it `my_tinyexpr` + +Your project structure now looks like this. + +```bash +. +├── CMakeLists.txt +├── components +│ └── my_tinyexpr +│ ├── CMakeLists.txt +│ ├── include +│ │ └── my_tinyexpr.h +│ └── my_tinyexpr.c +├── main +│ ├── CMakeLists.txt +│ └── main.c +├── README.md +├── sdkconfig +└── sdkconfig.old +``` + +* Replace `my_tinyexpr.c` with the downloaded `tinyexpr.c` +* Replace `my_tinyexpr.h` with the downloaded `tinyexpr.h` + +Since the filenames differ from the default, update the component's `CMakeLists.txt` to register the correct source file: + +```txt +idf_component_register(SRCS "tinyexpr.c" + INCLUDE_DIRS "include") +``` + +{{< alert icon="circle-info" cardColor="#b3e0f2" iconColor="#04a5e5">}} +The build system automatically includes all files in the `include` directory, so no additional configuration is needed to locate `tinyexpr.h`. +{{< /alert >}} + +Now that we’ve created the new component, it’s time to test it. + +## Test the component + +To test the component we need to +1. Inform the build system about the new component +2. Include the header file +3. Call the function of the library + +### Inform the build system about the new component + +In the `CMakeLists.txt` of the `__main__` component, add `REQUIRES "my_tinyexpr"` to let the build system know about the new component: + +```txt +idf_component_register(SRCS "main.c" + REQUIRES "my_tinyexpr" + INCLUDE_DIRS ".") +``` + +This ensures that the build system includes `my_tinyexpr` when compiling your project. + + +### Include the header file + +In your main file, include the header from the `tinyexpr` library: + +```c +#include "tinyexpr.h" +``` + + +{{< alert icon="lightbulb" iconColor="#179299" cardColor="#9cccce">}} +In general, a component’s header file does not need to match its name, and this applies broadly across ESP-IDF projects. +{{< /alert >}} + +### Call a function of the library + +In the tinyexpr repository, there is an `example.c` file that demonstrates how to use the library. + +* Copy the relevant portions of `example.c` into your `main.c` file. + +Your `app_main` function should now look like this: + +```c +#include +#include "tinyexpr.h" + +void app_main(void) +{ + const char *c = "sqrt(5^2+7^2+11^2+(8-2)^2)"; + double r = te_interp(c, 0); + printf("The expression:\n\t%s\nevaluates to:\n\t%f\n", c, r); +} +``` + +Next, build, flash, and monitor the project: + +* `ESP-IDF: Build, Flash and Start a Monitor on Your Device` + +And we got and error! + +```console +In file included from /tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c:43: +/tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c: In function 'next_token': +/tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c:255:32: error: array subscript has type 'char' [-Werror=char-subscripts] + 255 | if (isalpha(s->next[0])) { + | ~~~~~~~^~~ +/tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c:258:39: error: array subscript has type 'char' [-Werror=char-subscripts] + 258 | while (isalpha(s->next[0]) || isdigit(s->next[0]) || (s->next[0] == '_')) s->next++; + | ~~~~~~~^~~ +/tutorial-porting-tinyexpr/components/my_tinyexpr/tinyexpr.c:258:62: error: array subscript has type 'char' [-Werror=char-subscripts] + 258 | while (isalpha(s->next[0]) || isdigit(s->next[0]) || (s->next[0] == '_')) s->next++; + | ~~~~~~~^~~ +cc1: some warnings being treated as errors +ninja: build stopped: subcommand failed. +``` + +There is a compatibility issue. Although the library you found is written in C and appears to work, compiler settings or library dependencies could still cause problems. Let’s investigate what is preventing the compilation. + +## Solve compatibility issues + +The error is in the following code. + +```c +if (isalpha(s->next[0])) { ... } +while (isalpha(s->next[0]) || isdigit(s->next[0]) || (s->next[0] == '_')) s->next++; +``` + +It happens because a `char` is directly passed to `isalpha()` and `isdigit()`. On many platforms, `char` is signed, and these functions expect an `int` in the range of `unsigned char` (or `EOF`). Passing a signed `char` can trigger warnings or undefined behavior. + +ESP-IDF uses very strict compilation flags and treats all warnings as errors (`-Werror`), which is why these warnings stop the build. + +So we have two options, changing the code or changing the compilation flag. + +{{< alert iconColor="#df8e1d" cardColor="#edcea3">}} +Modifying the code of an external library is not recommended, as it makes it harder to keep your version synchronized with the official release and to apply future updates or bug fixes. +{{< /alert >}} + + +### Changing the code + +A fast way to fix it is to cast the character to `unsigned char`: + +```c +if (isalpha((unsigned char)s->next[0])) { ... } + +while (isalpha((unsigned char)s->next[0]) || + isdigit((unsigned char)s->next[0]) || + (s->next[0] == '_')) s->next++; +``` + +Now we can build, flash, and monitor the project again. + +* `ESP-IDF: Build, Flash and Start a Monitor on Your Device` + +And we get the expected output. + +```console +The expression: + sqrt(5^2+7^2+11^2+(8-2)^2) +evaluates to: + 15.198684 +``` + +### Changing the compilation flag + +Alternatively, the issue can be resolved by adjusting the compilation flags instead of modifying the source code. Since the error originates from `-Werror=char-subscripts`, we can suppress it by adding the following line to the `CMakeLists.txt` file of your component: + +```cmake +target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-char-subscripts) +``` + +This approach is often preferable when working with external libraries, as it allows you to keep the original source code intact. It also makes it easier to manage updates: if the library is included as a git submodule, any future improvements or security fixes can be applied by simply updating the submodule, without the need to reapply code changes. + + +Now that we’ve covered the basics of creating a component and resolving common compatibility issues, the next article will build on this foundation. You’ll see how to import a component as a git submodule, integrate it into multiple projects, and share it with the community. This workflow not only helps keep your code organized and maintainable but also ensures that updates and improvements can be easily propagated across projects without modifying the original source. + +## Conclusion + +In this article, we demonstrated how to take an existing open source library and integrate it into an ESP-IDF project as a reusable component. We located the tinyexpr library, created a new ESP-IDF project, built a dedicated component for the library, resolved compatibility details, and verified its functionality on an ESP32-C3-DevkitM-1 board. By packaging the library as a component rather than copying source files directly, we ensured cleaner integration, easier maintenance, and effortless reuse in future projects.