ESP32 官方文档(二)构建系统

构建系统

本文档解释了Espressif物联网开发框架构建系统和“组件”的概念。

如果您想知道如何组织新的 ESP-IDF 项目,请阅读本文档。

我们建议使用 esp-idf-template 项目作为项目的起点。

使用构建系统

esp-idf README 文件包含有关如何使用构建系统构建项目的说明。

概要

一个 ESP-IDF 项目可以看作是多个组件的组合。例如,对于显示当前湿度的网络服务器,可能有:

  • ESP32 基础库(libc,rom 绑定等)
  • WiFi 驱动
  • TCP / IP 协议堆栈
  • FreeRTOS 操作系统
  • 网络服务器
  • 湿度传感器的驱动器
  • 调用它们的主程序

ESP-IDF 使这些组件更清晰并且具有可配置性。为此,在编译项目时,构建环境将查找ESP-IDF目录,项目目录和(可选)其他自定义组件目录中的所有组件。之后,它允许用户使用基于文本的菜单系统配置 ESP-IDF 项目,以自定义每个组件。在配置完项目中的组件之后,构建程序将编译项目。

概念

  • “项目”是一个目录,其中包含构建单个“app”(可执行文件)的所有文件和配置,以及其他支持输出,如分区表,数据/文件系统分区和引导加载程序。
  • “项目配置”保存在项目根目录中名为 sdkconfig 的单个文件中。通过 make menuconfig 修改此配置文件以自定义项目的配置。单个项目只包含一个项目配置。
  • “app”是由 esp-idf 构建的可执行文件。单个项目通常会构建两个应用程序 - 一个“项目应用程序”(主要可执行文件,即您的自定义固件)和一个“引导程序应用程序”(启动项目应用程序的初始引导程序)。
  • “组件”是独立代码的模块化部分,它们被编译成静态库(.a文件)并链接到应用程序。有些是由 esp-idf 本身提供的,有些则可能来自其他地方。

有些东西不是项目的一部分:

  • “ESP-IDF”不是该项目的一部分。相反,它是独立的,并通过 IDF_PATH 环境变量链接到项目,该变量保存 esp-idf 目录的路径。这允许 IDF 框架与您的项目分离。
  • 用于编译的工具链不是项目的一部分。工具链应安装在系统命令行 PATH 中,或者工具链的路径设置为项目配置中编译器前缀的一部分。

示例项目

示例项目目录结构可能如下所示:

 - myProject/
             - Makefile
             - sdkconfig
             - components/ - component1/ - component.mk
                                         - Kconfig
                                         - src1.c
                           - component2/ - component.mk
                                         - Kconfig
                                         - src1.c
                                         - include/ - component2.h
             - main/       - src1.c
                           - src2.c
                           - component.mk

             - build/

此示例“myProject”包含以下元素:

  • 顶级项目 Makefile 。此 Makefile 设置PROJECT_NAME变量,并(可选)定义其他项目范围的 make 变量。它包括核心 $(IDF_PATH)/make/project.mk makefile,它实现了 ESP-IDF 构建系统的其余部分。
  • “sdkconfig” 项目配置文件。当“make menuconfig”运行时,将创建/更新此文件,并保存项目中所有组件的配置(包括esp-idf本身)。“sdkconfig”文件可能会也可能不会添加到项目的源代码管理系统中。
  • 可选的“components”目录包含属于项目一部分的组件。项目不必包含此类自定义组件,但它可用于构造可重用代码或包括不属于 ESP-IDF 的第三方组件。
  • “main”目录是一个特殊的“伪组件”,它包含项目本身的源代码。“main”是默认名称,Makefile 变量COMPONENT_DIRS包含此组件,但您可以修改此变量(或设置EXTRA_COMPONENT_DIRS)以查找其他位置的组件。
  • “build”目录是项目构建输出的位置。运行make进程后,该目录被创建,并包含临时目标文件和库以及最终的二进制输出文件。此目录通常不会添加到源代码管理中,也不会随项目源代码一起分发。

组件目录包含一个组件 makefile 文件- component.mk。这可能包含变量定义,以控制组件的构建过程,以及它与整个项目的集成。有关更多详细信息,请参阅组件Makefile

每个组件还可以包括一个 Kconfig 文件,用于定义可以通过项目配置设置的组件配置选项。某些组件还可能包含 Kconfig.projbuildMakefile.projbuild 文件,这些文件是用于覆盖项目部分的特殊文件。

项目Makefile

每个项目都有一个 Makefile,其中包含整个项目的构建配置。默认情况下,项目 Makefile 可以非常小。

最小示例Makefile

PROJECT_NAME := myProject

include $(IDF_PATH)/make/project.mk

强制项目变量

  • PROJECT_NAME:项目名称。二进制输出文件将使用此名称 - 即 myProject.bin,myProject.elf。

可选的项目变量

这些变量都具有可以为自定义行为覆盖的默认值。查看 make/project.mk以获取所有实现细节。

  • PROJECT_PATH:顶级项目目录。默认为包含Makefile的目录。许多其他项目变量都基于此变量。项目路径不能包含空格。
  • BUILD_DIR_BASE:所有对象/库/二进制文件的构建目录。默认为$(PROJECT_PATH)/build
  • COMPONENT_DIRS:搜索组件的目录。默认为$(IDF_PATH)/components$(PROJECT_PATH)/components$(PROJECT_PATH)/mainEXTRA_COMPONENT_DIRS。如果您不想在这些位置搜索组件,请覆盖此变量。
  • EXTRA_COMPONENT_DIRS:搜索组件的其他目录的可选列表。
  • COMPONENTS:要构建到项目中的组件名称列表。默认为COMPONENT_DIRS目录中的所有组件。
  • EXCLUDE_COMPONENTS:在构建过程中要排除的组件名称的可选列表。请注意,这会减少构建时间,但不会减少二进制大小。

这些 Makefile 变量中的任何路径都应该是绝对路径。您可以使用$(PROJECT_PATH)/ xxx$(IDF_PATH)/ xxx转换相对路径,或使用 Make 函数$(abspath xxx)

这些变量应该在 Makefile 中包含$(IDF_PATH)/make/project.mk的行之前设置。

组件Makefile

每个项目都包含一个或多个组件,这些组件可以是 esp-idf 的一部分,也可以从其他组件目录添加。

组件是包含 component.mk 文件的任何目录。

搜索组件

搜索COMPONENT_DIRS中的目录列表以查找项目的组件。此列表中的目录可以是组件本身(即它们包含 component.mk 文件),也可以是子目录为组件的顶级目录。

运行make list-components目标会转储许多这些变量,并可以帮助调试组件目录的发现。

具有相同名称的多个组件

当 esp-idf 收集要编译的所有组件时,它将按照COMPONENT_DIRS指定的顺序执行此操作; 默认情况下,这意味着首先是 idf 组件,第二个是项目组件,最后是EXTRA_COMPONENT_DIRS中的组件。如果这些目录中的两个或多个包含具有相同名称的组件子目录,则使用搜索的最后一个位置中的组件。例如,这允许通过简单地将组件从 esp-idf 组件目录复制到项目组件树然后在那里修改它来覆盖具有修改版本的 esp-idf 组件。如果以这种方式使用,esp-idf 目录本身可以保持不变。

最小组件Makefile

最小的component.mk文件是一个空文件(!)。如果文件为空,则设置默认组件行为:

  • 与makefile相同的目录中的所有源文件(*.c*.cpp*.cc*.S)将被编译到组件库中
  • 子目录“include”将被添加到所有其他组件的全局包含搜索路径中。
  • 组件库将链接到项目应用程序中。

有关更完整的示例组件 makefile,请参阅示例组件 makefile。

请注意,空component.mk文件(调用默认组件构建行为)和没有component.mk文件(这意味着不会发生默认组件构建行为)之间存在差异。组件可能没有component.mk文件,如果它只包含影响项目配置或构建过程的其他文件。

预设组件变量

以下特定于组件的变量可在component.mk中使用,但不应修改:

  • COMPONENT_PATH:组件目录。计算包含component.mk的目录的绝对路径。组件路径不能包含空格。
  • COMPONENT_NAME:组件的名称。默认为组件目录的名称。
  • COMPONENT_BUILD_DIR:组件构建目录。计算$(BUILD_DIR_BASE)中要构建此组件源文件的目录的绝对路径。每次构建组件时,这也是当前工作目录,因此make目标等中的相对路径将相对于此目录。
  • COMPONENT_LIBRARY:将为此组件构建的静态库文件的名称(相对于组件构建目录)。默认为$(COMPONENT_NAME).a

以下变量在项目级别设置,但导出以在组件构建中使用:

  • PROJECT_NAME:项目名称,在项目Makefile中设置
  • PROJECT_PATH:包含项目 Makefile 的项目目录的绝对路径。
  • COMPONENTS:此构建中包含的所有组件的名称。
  • CONFIG_ *:项目配置中的每个值都有一个 make 中可用的对应变量。所有名称都以 CONFIG_ 开头。
  • CCLDAROBJCOPY:gcc xtensa交叉工具链中每个工具的完整路径。
  • HOSTCCHOSTLDHOSTAR:来自主机本机工具链的每个工具的全名。
  • IDF_VER:ESP-IDF 版本,使用git命令git describe$(IDF_PATH)/ version.txt文件(如果存在)中检索。这里推荐的格式是指定主要IDF发布版本的单行,例如用于标记版本的v2.0或用于任意提交的v2.0-275-g0efaa4f。应用程序可以通过调用esp_get_idf_version()来使用它。

如果您修改component.mk中的任何这些变量,那么这不会阻止构建其他组件,但它可能使您的组件难以构建和/或调试。

可选项目范围的组件变量

可以在component.mk中设置以下变量来控制整个项目中的构建设置:

  • COMPONENT_ADD_INCLUDEDIRS:相对于组件目录的路径,将添加到项目中所有组件的包含搜索路径。如果未被覆盖,则默认include。如果仅需要编译此特定组件的include目录,请将其添加到COMPONENT_PRIV_INCLUDEDIRS
  • COMPONENT_ADD_LDFLAGS:为LDFLAGS添加链接器参数以用于应用程序可执行文件。默认为-l$(COMPONENT_NAME)。如果将预编译库添加到此目录,请将它们添加为绝对路径 -e$(COMPONENT_PATH)/libwhatever.a
  • COMPONENT_DEPENDS:应在此组件之前编译的组件名称的可选列表。这对于链接时依赖性不是必需的,因为所有组件包含目录始终可用。如果一个组件生成一个包含文件,然后您想要包含在另一个组件中,则这是必要的。大多数组件不需要设置此变量。

以下变量仅适用于属于esp-idf本身的组件:

  • COMPONENT_SUBMODULES:组件使用的git子模块路径(相对于COMPONENT_PATH)的可选列表。这些将由构建过程检查(并在必要时初始化)。如果组件位于IDF_PATH目录之外,则忽略此变量。

可选特定的组件变量

可以在component.mk中设置以下变量来控制该组件的构建:

  • COMPONENT_PRIV_INCLUDEDIRS:目录路径必须相对于组件目录,该组件目录将仅添加到此组件源文件的包含搜索路径中。
  • COMPONENT_EXTRA_INCLUDES:编译组件源文件时使用的任何额外包含路径。这些将以’-I’为前缀,并按原样传递给编译器。与COMPONENT_PRIV_INCLUDEDIRS变量类似,但这些路径不会相对于组件目录进行扩展。
  • COMPONENT_SRCDIRS:目录路径,必须相对于组件目录,将搜索源文件(* .cpp* .c* .S)。默认为’。’,即组件目录本身。覆盖它以指定包含源文件的不同目录列表。
  • COMPONENT_OBJS:要编译的对象文件。默认值是COMPONENT_SRCDIRS中找到的每个源文件的 a.o 文件。覆盖此列表允许您排除COMPONENT_SRCDIRS中的源文件,否则将被编译。请参阅指定源文件
  • COMPONENT_EXTRA_CLEAN:相对于组件构建目录的路径,使用component.mk文件中的自定义make规则生成的任何文件,以及作为make clean的一部分需要删除的文件。有关示例,请参阅源代码生成
  • COMPONENT_OWNBUILDTARGETCOMPONENT_OWNCLEANTARGET:这些目标允许您完全覆盖组件的默认构建行为。有关详细信息,请参阅完全覆盖组件 Makefile
  • COMPONENT_CONFIG_ONLY:如果设置,则此标志指示组件根本不生成任何内置输出(即未构建COMPONENT_LIBRARY),并忽略大多数其他组件变量。此标志用于 IDF 内部组件,其中仅包含 KConfig.projbuild 和/或 Makefile.projbuild 文件以配置项目,但没有源文件。
  • CFLAGS:标志传递给C编译器。根据项目设置定义一组默认CFLAGS。可以通过CFLAGS + =进行组件特定的添加。也可以(尽管不推荐)完全覆盖该组件的变量。
  • CPPFLAGS:传递给C预处理器的标志(用于.c,.cpp和.S文件)。根据项目设置定义一组默认的CPPFLAGS。可以通过CPPFLAGS + =进行组件特定的添加。也可以(尽管不推荐)完全覆盖该组件的变量。
  • CXXFLAGS:传递给C ++编译器的标志。根据项目设置定义一组默认的CXXFLAGS。可以通过CXXFLAGS + =进行组件特定的添加。也可以(尽管不推荐)完全覆盖该组件的变量。

要将编译标志应用于单个源文件,可以将变量覆盖添加为目标,即:

apps / dhcpserver.o:CFLAGS + = -Wno-unused-variable

组件配置

每个组件也可以与 component.mk 一起使用 Kconfig 文件。其中包含要添加到此组件的“make menuconfig”的配置设置。

运行 menuconfig 时,可在“组件设置”菜单下找到这些设置。

要创建组件 KConfig 文件,最简单的方法是使用 esp-id f分发的一个 KConfig 文件。

有关示例,请参阅添加条件配置

预处理器定义

ESP-IDF构建系统在命令行上添加以下C预处理器定义:

  • ESP_PLATFORM - 可用于检测在ESP-IDF内发生的构建。
  • IDF_VER - ESP-IDF版本,有关详细信息,请参阅预设组件变量

构建过程内部

顶级:Project Makefile

  • “make”始终从项目目录和项目makefile运行,通常名为Makefile。
  • 项目makefile设置PROJECT_NAME,并可选择自定义其他可选项目变量
  • 项目makefile包含$(IDF_PATH)/make/project.mk,其中包含项目级的Make逻辑。
  • project.mk填写默认的项目级make变量,并包含项目配置中的make变量。如果生成的包含项目配置的makefile已过期,则会重新生成(通过project_config.mk中的目标),然后make进程从顶部重新开始。
  • project.mk根据默认组件目录或可选项目变量中设置的自定义组件列表构建要构建的组件列表。
  • 每个组件都可以设置一些可选的项目范围的组件变量。这些包含在名为component_project_vars.mk的生成的makefile中 - 每个组件有一个。这些生成的makefile包含在project.mk中。如果有任何缺失或过时,它们将被重新生成(通过对组件makefile的递归调用),然后make进程从顶部重新开始。
  • 组件中的Makefile.projbuild文件包含在make进程中,以添加额外的目标或配置。
  • 默认情况下,项目makefile还为每个组件生成顶级构建和清理目标,并设置app和clean目标以调用所有这些子目标。
  • 为了编译每个组件,对组件makefile执行递归make。

为了更好地理解项目构建过程,请通读project.mk文件本身。

第二级:组件Makefile

  • 每次调用组件makefile都是通过$(IDF_PATH)/make/component_wrapper.mk包装器makefile进行的。
  • 此组件包装器包含所有组件Makefile.componentbuild文件,使这些文件中的任何配方,变量等可用于每个组件。
  • 调用component_wrapper.mk时将当前目录设置为组件构建目录,并将COMPONENT_MAKEFILE变量设置为component.mk的绝对路径。
  • component_wrapper.mk为所有组件变量设置默认值,然后包括可以覆盖或修改这些变量的component.mk文件。
  • 如果未定义COMPONENT_OWNBUILDTARGETCOMPONENT_OWNCLEANTARGET,则会为组件的源文件和必备组件COMPONENT_LIBRARY静态库文件创建缺省构建和清除目标。
  • component_project_vars.mk文件在component_wrapper.mk中有自己的目标,如果由于组件makefile或项目配置的更改而需要重建此文件,则从project.mk进行评估。

为了更好地理解组件制作过程,请读取component_wrapper.mk文件和esp-idf中包含的一些component.mk文件。

以非交互方式运行

在不希望交互式提示的情况下运行make时(例如:在IDE或自动构建系统中)将BATCH_BUILD = 1附加到make参数(或将其设置为环境变量)。

设置BATCH_BUILD意味着以下内容:

  • 详细输出(与V = 1相同,见下文)。如果您不想要详细输出,还要设置V = 0
  • 如果项目配置缺少新配置项(来自新组件或esp-idf更新),则项目使用默认值,而不是提示用户输入每个项目。
  • 如果构建系统需要调用menuconfig,则会打印错误并且构建失败。

调试Make Process

调试esp-idf构建系统的一些技巧:
- 将V = 1附加到make参数(或将其设置为环境变量)将使make回显所有已执行的命令,以及为子make输入的每个目录。
- 运行make -w将导致make在为子make输入时回显每个目录 - 与V = 1相同但不回显所有命令。
- 运行make --trace(可能除了上述参数之一)将打印出构建时的每个目标,以及导致它构建的依赖项。
- 运行make -p会打印每个makefile中每个生成的目标的(非常详细的)摘要。

有关更多调试技巧和一般制作信息,请参阅GNU制作手册。

警告未定义的变量

默认情况下,如果引用了未定义的变量(如$(DOES_NOT_EXIST)),构建过程将打印警告。这对于查找变量名称中的错误非常有用。

如果您不想要此行为,可以在SDK工具配置下的menuconfig顶级菜单中禁用它。

请注意,如果在Makefile中使用ifdefifndef,则此选项不会触发警告。

覆盖项目的部分内容

Makefile.projbuild

对于具有必须在顶级项目make pass中进行求值的构建要求的组件,可以在组件目录中创建名为Makefile.projbuild的文件。在评估project.mk时包含此makefile。

例如,如果您的组件需要为整个项目添加CFLAGS(不仅仅是为了自己的源文件),那么您可以在Makefile.projbuild中设置CFLAGS + =

Makefile.projbuild文件在esp-idf中大量使用,用于定义项目范围的构建功能,例如esptool.py命令行参数和bootloader“特殊应用程序”。

请注意,Makefile.projbuild对于最常见的组件使用不是必需的 - 例如向项目添加include目录,或者将LDFLAGS添加到最终链接步骤。可以通过component.mk文件本身自定义这些值。有关详细信息,请参阅可选的项目范围组件变量

在此文件中设置变量或目标时要小心。由于这些值包含在顶级项目makefile中,因此它们可以影响或破坏所有组件的功能!

KConfig.projbuild

这相当于Makefile.projbuild的组件配置KConfig文件。如果要在menuconfig的顶层包含配置选项,而不是在“组件配置”子菜单中,则可以在component.mk文件旁边的KConfig.projbuild文件中定义这些选项。

在此文件中添加配置值时要小心,因为它们将包含在整个项目配置中。在可能的情况下,通常最好为组件配置创建KConfig文件。

Makefile.componentbuild

对于例如组件 包括从其他文件生成源文件的工具,必须能够将配方,宏或变量定义添加到每个组件的组件构建过程中。这是通过在组件目录中包含Makefile.componentbuild来完成的。在包含组件的component.mk之前,此文件包含在component_wrapper.mk中。与Makefile.projbuild一样,请注意这些文件:因为它们包含在每个组件构建中,所以只有在编译完全不同的组件时才会出现Makefile.componentbuild错误。

仅配置组件

一些不包含源文件的特殊组件,只有Kconfig.projbuildMakefile.projbuild,可以在component.mk文件中设置标志COMPONENT_CONFIG_ONLY。如果设置了此标志,则忽略大多数其他组件变量,并且不会为组件运行构建步骤。

示例组件Makefile

因为构建环境试图设置大多数时间都能工作的合理默认值,所以component.mk可能非常小甚至是空的(请参阅Minimal Component Makefile)。但是,某些功能通常需要覆盖组件变量。

以下是component.mk makefile的一些更高级的示例:

添加源文件目录

默认情况下,将忽略子目录。如果您的项目在子目录而不是组件的根目录中有源文件,那么您可以通过设置COMPONENT_SRCDIRS告诉构建系统:

COMPONENT_SRCDIRS:= src1 src2

这将编译src1 /和src2 /子目录中的所有源文件。

指定源文件

标准component.mk逻辑将源目录中的所有.S和.c文件添加为无条件编译的源。通过将COMPONENT_OBJS变量手动设置为需要生成的对象的名称,可以绕过该逻辑并对要编译的对象进行硬编码:

COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o
COMPONENT_SRCDIRS := . thing anotherthing

请注意,还必须设置COMPONENT_SRCDIRS

添加条件配置

配置系统可用于有条件地编译某些文件,具体取决于make menuconfig中选择的选项。为此,ESP-IDF具有compile_only_if和compile_only_if_not宏:

Kconfig:

config FOO_ENABLE_BAR
    bool "Enable the BAR feature."
    help
        This enables the BAR feature of the FOO component.

component.mk:

$(call compile_only_if,$(CONFIG_FOO_ENABLE_BAR),bar.o)

从示例中可以看出,compile_only_if宏将条件和目标文件列表作为参数。如果条件为真(在这种情况下:如果在menuconfig中启用了BAR功能),将始终编译目标文件(在本例中为bar.o)。相反的情况也是如此:如果条件不成立,bar.o将永远不会被编译。compile_only_if_not执行相反的操作:如果条件为false则编译,如果条件为true则不编译。

这也可用于选择或删除实现,如下所示:
Kconfig

config ENABLE_LCD_OUTPUT
    bool "Enable LCD output."
    help
        Select this if your board has a LCD.

config ENABLE_LCD_CONSOLE
    bool "Output console text to LCD"
    depends on ENABLE_LCD_OUTPUT
    help
        Select this to output debugging output to the lcd

config ENABLE_LCD_PLOT
    bool "Output temperature plots to LCD"
    depends on ENABLE_LCD_OUTPUT
    help
        Select this to output temperature plots

component.mk:

# If LCD is enabled, compile interface to it, otherwise compile dummy interface
$(call compile_only_if,$(CONFIG_ENABLE_LCD_OUTPUT),lcd-real.o lcd-spi.o)
$(call compile_only_if_not,$(CONFIG_ENABLE_LCD_OUTPUT),lcd-dummy.o)

#We need font if either console or plot is enabled
$(call compile_only_if,$(or $(CONFIG_ENABLE_LCD_CONSOLE),$(CONFIG_ENABLE_LCD_PLOT)), font.o)

请注意使用Make’或’功能来包含字体文件。其他替换函数,如’and’以及’if’也适用于此处。也可以使用不来自menuconfig的变量:ESP-IDF 使用默认的构建配置来判断一个空的变量或只包含空格为false,而其中包含任何非空格的变量为true。

(注意:本文档的旧版本建议有条件地将目标文件名添加到COMPONENT_OBJS。虽然这仍然可行,但只有当组件的所有目标文件都明确命名时才会起作用,并且不会通过make clear中的取消选择的目标文件通过。)

源代码生成

某些组件将出现源文件未随组件本身提供但必须从另一个文件生成的情况。假设我们的组件有一个头文件,该文件由BMP文件的转换后的二进制数据组成,使用名为bmp2h的假设工具进行转换。然后将头文件包含在名为graphics_lib.c的C源文件中:

COMPONENT_EXTRA_CLEAN := logo.h

graphics_lib.o: logo.h

logo.h: $(COMPONENT_PATH)/logo.bmp
    bmp2h -i $^ -o $@

在此示例中,将在当前目录(构建目录)中生成graphics_lib.ologo.h,而logo.bmp随组件一起提供并位于组件路径下。因为logo.h是一个生成的文件,所以当调用make clean时需要清理它,这就是为什么它被添加到COMPONENT_EXTRA_CLEAN变量中。

Cosmetic Improvements

因为logo.h是一个生成的文件,所以当调用make clean时需要清理它,这就是为什么它被添加到COMPONENT_EXTRA_CLEAN变量中。

将logo.h添加到graphics_lib.o依赖项会导致在编译graphics_lib.c之前生成它。

如果另一个组件中的源文件包含logo.h,则必须将此组件的名称添加到另一个组件的COMPONENT_DEPENDS列表中,以确保组件按顺序构建。

嵌入二进制数据

有时您有一个文件包含您希望组件可用的二进制或文本数据 - 但您不希望将文件重新格式化为C源。

您可以在component.mk中设置变量COMPONENT_EMBED_FILES,以这种方式给出要嵌入的文件的名称:

COMPONENT_EMBED_FILES:= server_root_cert.der

或者,如果文件是字符串,则可以使用变量COMPONENT_EMBED_TXTFILES。这将把文本文件的内容嵌入为以null结尾的字符串:

COMPONENT_EMBED_TXTFILES:= server_root_cert.pem

文件的内容将被添加到flash中的.rodata部分,并通过符号名称提供,如下所示:

extern const uint8_t server_root_cert_pem_start [] asm(“_ binary_server_root_cert_pem_start”);
extern const uint8_t server_root_cert_pem_end [] asm(“_ binary_server_root_cert_pem_end”);

名称是根据文件的全名生成的,如COMPONENT_EMBED_FILES中所示。字符/,等等用下划线代替。符号名称中的_binary前缀由objcopy添加,对于文本和二进制文件都是相同的。

有关使用此技术的示例,请参阅protocols/https_request-证书文件内容在编译时从文本.pem文件加载。

完全覆盖组件Makefile

显然,在某些情况下,所有这些不足以满足某个组件,例如,当组件基本上是另一个第三方组件的包装器时,该第三方组件最初不打算在此构建系统下编译。在这种情况下,可以通过设置COMPONENT_OWNBUILDTARGET和可能的COMPONENT_OWNCLEANTARGET并在component.mk目标中定义名为buildclean的自己的目标来完全放弃esp-idf构建系统。构建目标可以执行任何操作,只要它为项目生成过程创建$(COMPONENT_LIBRARY)以链接到应用程序二进制文件。

(实际上,即使这不是必需的-如果重写COMPONENT_ADD_LDFLAGS变量,则组件可以指示链接器链接其他二进制文件。)

自定义sdkconfig默认值

例如,您不希望指定完整sdkconfig配置的项目或其他项目,但您确实希望覆盖esp-idf默认值中的某些键值,则可以在项目目录中创建文件sdkconfig.defaults。运行make defconfig或从头创建新配置时将使用此文件。

要覆盖此文件的名称,请设置SDKCONFIG_DEFAULTS环境变量。

保存flash参数

在某些情况下,我们希望在没有IDF的情况下烧写目标板。对于这种情况,我们希望保存构建的二进制文件,esptool.py和esptool write_flash参数。编写脚本以保存二进制文件和esptool.py很简单。我们可以使用命令make print_flash_cmd,它会打印flash参数:

--flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader / bootloader.bin 0x10000 example_app.bin 0x8000 partition_table_unit_test_app.bin

然后使用flash参数作为esptool write_flash参数的arguemnts:

python esptool.py --chip esp32 --port / dev / ttyUSB0 --baud 921600 - before default_reset - after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 bootloader / bootloader.bin 0x10000 example_app .bin 0x8000 partition_table_unit_test_app.bin

构建Bootloader

引导程序默认构建为“make all”的一部分,或者可以通过“make bootloader-clean”独立构建。还有“make bootloader-list-components”来查看引导加载程序构建中包含的组件。

IDF组件/bootloader中的组件是特殊的,因为第二阶段引导加载程序是主项目的单独.ELF和.BIN文件。但是,它与主项目共享其配置和构建目录。

这是通过在components/bootloader/subproject下添加子项目来完成的。这个子项目有自己的Makefile,但它希望通过components/bootloader/Makefile.projectbuild文件中的一些粘合剂从项目自己的Makefile中调用。有关详细信息,请参阅这些文件

猜你喜欢

转载自blog.csdn.net/qq_27114397/article/details/81152448