Prechádzať zdrojové kódy

Merge branch 'feature/prebuilt_binary_example_v4.0' into 'release/v4.0'

Import prebuilt binary (v4.0)

See merge request espressif/esp-idf!7208
Angus Gratton 6 rokov pred
rodič
commit
beb73456ee

+ 22 - 0
docs/en/api-guides/build-system.rst

@@ -1020,6 +1020,28 @@ Espressif's fork of `mbedtls <https://github.com/ARMmbed/mbedtls>`_. See its :co
 
 The CMake variable ``ESP_PLATFORM`` is set to 1 whenever the ESP-IDF build system is being used. Tests such as ``if (ESP_PLATFORM)`` can be used in generic CMake code if special IDF-specific logic is required.
 
+Using Prebuilt Libraries with Components
+========================================
+
+.. highlight:: cmake
+
+The ESP-IDF build system provides a utility function ``add_prebuilt_library`` for users to be able to easily import and use
+prebuilt libraries::
+
+  add_prebuilt_library(target_name lib_path [REQUIRES req1 req2 ...] [PRIV_REQUIRES req1 req2 ...])
+
+where:
+
+- ``target_name``- name that can be used to reference the imported library, such as when linking to other targets
+- ``lib_path``- path to prebuilt library; may be an absolute or relative path to the component directory
+
+Optional arguments ``REQUIRES`` and ``PRIV_REQUIRES`` specify dependency on other components. These have the same meaning as the arguments for ``idf_component_register``. 
+
+Take note that the prebuilt library must have been compiled for the same target as the consuming project. Configuration relevant to the prebuilt
+library must also match. If not paid attention to, these two factors may contribute to subtle bugs in the app.
+
+For an example, take a look at :example:`build_system/cmake/import_prebuilt`.
+
 
 Using ESP-IDF in Custom CMake Projects
 ======================================

+ 6 - 0
examples/build_system/cmake/import_prebuilt/CMakeLists.txt

@@ -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_prebuilt)

+ 37 - 0
examples/build_system/cmake/import_prebuilt/README.md

@@ -0,0 +1,37 @@
+# Import Prebuilt Library Example
+
+This example illustrates how to import a prebuilt static library in the ESP-IDF build system.
+
+## Example Flow
+
+Users need to first build the project in the [prebuilt](prebuilt) subdirectory:
+
+```
+cd prebuilt
+idf.py build
+```
+
+This builds a component named [prebuilt](prebuilt/components/prebuilt), which has private dependency on ESP-IDF components `spi_flash`, `log` and `app_update` (see [its CMakeLists.txt](prebuilt/components/prebuilt/CMakeLists.txt)). Once built, the archive file `libprebuilt.a`, along with the header file `prebuilt.h`, is automatically copied to the [`main` component](main) of this example project. 
+
+The [`main` component's CMakeLists.txt](main/CMakeLists.txt) demonstrates how to import `libprebuilt.a` and link it to `main` so that the definitions inside can be used. 
+It also demonstrates how to specify the same dependencies the original component had so as to properly resolve symbols used inside the prebuilt library.
+
+Users can then return to this directory and build the main example:
+
+```
+cd ..
+idf.py build
+```
+
+
+### Output
+
+The example simply outputs the current running partition.
+
+```
+I (319) prebuilt: The running partition is 'factory'!
+```
+
+---
+
+There is a discussion on importing prebuilt libraries in the programming guide under `API Guides` -> `Build System` -> `Using Prebuilt Libraries with Components`

+ 12 - 0
examples/build_system/cmake/import_prebuilt/main/CMakeLists.txt

@@ -0,0 +1,12 @@
+idf_component_register(SRCS "main.c"
+                    INCLUDE_DIRS ".")
+
+# Import the library, specifying a target name and the library path.
+# The private dependencies of the library is also specified.
+add_prebuilt_library(prebuilt "libprebuilt.a"
+             PRIV_REQUIRES spi_flash app_update log)
+
+# `main` calls a function from the library, so link it to `main`
+target_link_libraries(${COMPONENT_LIB} PRIVATE prebuilt)
+
+

+ 17 - 0
examples/build_system/cmake/import_prebuilt/main/main.c

@@ -0,0 +1,17 @@
+/* Import Prebuilt Library 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 the prebuilt library's header file so as to be able 
+// to reference `prebuilt_func` here.
+#include "prebuilt.h"
+
+void app_main(void)
+{
+    prebuilt_func();
+}

+ 6 - 0
examples/build_system/cmake/import_prebuilt/main/project_include.cmake

@@ -0,0 +1,6 @@
+# For users checking this example, ignore the following code. This is so that
+# the prebuilt project is built automatically in ESP-IDF CI.
+if("$ENV{CI}")
+    execute_process(COMMAND ${IDFTOOL} build
+                    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/prebuilt)
+endif()

+ 8 - 0
examples/build_system/cmake/import_prebuilt/prebuilt/CMakeLists.txt

@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.5)
+
+# Since we're only interested in the prebuilt library, trim
+# the build
+set(COMPONENTS prebuilt main esptool_py)
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+
+project(prebuilt C)

+ 10 - 0
examples/build_system/cmake/import_prebuilt/prebuilt/components/prebuilt/CMakeLists.txt

@@ -0,0 +1,10 @@
+idf_component_register(SRCS prebuilt.c
+                       INCLUDE_DIRS "."
+                       PRIV_REQUIRES app_update spi_flash log)
+
+# After build, copy the archive file and header file to parent example directory's main component
+add_custom_command(TARGET ${COMPONENT_LIB}
+                  POST_BUILD
+                  COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${COMPONENT_LIB}> ${CMAKE_SOURCE_DIR}/../main
+                  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/prebuilt.h ${CMAKE_SOURCE_DIR}/../main
+                  COMMENT "Copying built archive file and header to parent example directory...")

+ 21 - 0
examples/build_system/cmake/import_prebuilt/prebuilt/components/prebuilt/prebuilt.c

@@ -0,0 +1,21 @@
+/* Import Prebuilt Library 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 "esp_ota_ops.h"
+#include "esp_partition.h"
+#include "esp_log.h"
+
+const char *TAG = "prebuilt";
+
+void prebuilt_func(void)
+{
+    const esp_partition_t* running_partition = esp_ota_get_running_partition();
+    ESP_LOGI(TAG, "The running partition is '%s'!", running_partition->label);
+}
+
+

+ 11 - 0
examples/build_system/cmake/import_prebuilt/prebuilt/components/prebuilt/prebuilt.h

@@ -0,0 +1,11 @@
+/* Import Prebuilt Library 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.
+*/
+#pragma once
+
+void prebuilt_func(void);

+ 2 - 0
examples/build_system/cmake/import_prebuilt/prebuilt/main/CMakeLists.txt

@@ -0,0 +1,2 @@
+idf_component_register(SRCS "main.c"
+                    INCLUDE_DIRS "")

+ 6 - 0
examples/build_system/cmake/import_prebuilt/prebuilt/main/main.c

@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+void app_main(void)
+{
+    printf("Hello World!\n");
+}

+ 23 - 0
tools/cmake/utilities.cmake

@@ -258,3 +258,26 @@ function(add_c_compile_options)
         add_compile_options($<$<COMPILE_LANGUAGE:C>:${option}>)
     endforeach()
 endfunction()
+
+
+function(add_prebuilt_library target_name lib_path)
+    cmake_parse_arguments(_ "" "" "REQUIRES;PRIV_REQUIRES" ${ARGN})
+
+    get_filename_component(lib_path "${lib_path}"
+                ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
+
+    add_library(${target_name} STATIC IMPORTED)
+    set_property(TARGET ${target_name} PROPERTY IMPORTED_LOCATION ${lib_path})
+
+    foreach(req ${__REQUIRES})
+        idf_component_get_property(req_lib "${req}" COMPONENT_LIB)
+        set_property(TARGET ${target_name} APPEND PROPERTY LINK_LIBRARIES "${req_lib}")
+        set_property(TARGET ${target_name} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${req_lib}")
+    endforeach()
+
+    foreach(req ${__PRIV_REQUIRES})
+        idf_component_get_property(req_lib "${req}" COMPONENT_LIB)
+        set_property(TARGET ${target_name} APPEND PROPERTY LINK_LIBRARIES "${req_lib}")
+        set_property(TARGET ${target_name} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "$<LINK_ONLY:${req_lib}>")
+    endforeach()
+endfunction()