forked from espressif/esp-idf
docs: Rewrite build system docs to address new system, plus general editing
Fixes TW#8017
This commit is contained in:
@@ -8,262 +8,368 @@ Read this document if you want to know how to organise a new ESP-IDF project.
|
|||||||
|
|
||||||
We recommend using the esp-idf-template_ project as a starting point for your project.
|
We recommend using the esp-idf-template_ project as a starting point for your project.
|
||||||
|
|
||||||
|
Using the Build System
|
||||||
|
======================
|
||||||
|
|
||||||
|
The esp-idf README file contains a description of how to use the build system to build your project.
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
========
|
========
|
||||||
|
|
||||||
An ESP-IDF project can be seen as an almagation of a number of components.
|
An ESP-IDF project can be seen as an amalgamation of a number of components.
|
||||||
For example, for a webserver that shows the current humidity, we would
|
For example, for a webserver that shows the current humidity, there could be:
|
||||||
have:
|
|
||||||
|
|
||||||
- The ESP32 base libraries (libc, rom bindings etc)
|
- The ESP32 base libraries (libc, rom bindings etc)
|
||||||
- The WiFi drivers
|
- The WiFi drivers
|
||||||
- A TCP/IP stack
|
- A TCP/IP stack
|
||||||
- The FreeRTOS operating system
|
- The FreeRTOS operating system
|
||||||
- A webserver
|
- A webserver
|
||||||
- A driver for an humidity sensor
|
- A driver for the humidity sensor
|
||||||
- Main code tying it all together
|
- Main code tying it all together
|
||||||
|
|
||||||
ESP-IDF makes these components explicit and configurable. To do that, when a project
|
ESP-IDF makes these components explicit and configurable. To do that,
|
||||||
is compiled, the build environment will look up all the components in the
|
when a project is compiled, the build environment will look up all the
|
||||||
ESP-IDF directories, the project directories and optionally custom other component
|
components in the ESP-IDF directories, the project directories and
|
||||||
directories. It then allows the user to configure compile-time options using
|
(optionally) in additional custom component directories. It then
|
||||||
a friendly text-based menu system to customize the ESP-IDF as well as other components
|
allows the user to configure the ESP-IDF project using a a text-based
|
||||||
to the requirements of the project. After the components are customized, the
|
menu system to customize each component. After the components in the
|
||||||
build process will compile everything into an output file, which can then be uploaded
|
project are configured, the build process will compile the project.
|
||||||
into a board in a way that can also be defined by components.
|
|
||||||
|
|
||||||
A project in this sense is defined as a directory under which all the files required
|
Concepts
|
||||||
to build it live, excluding the ESP-IDF files and the toolchain. A simple project
|
--------
|
||||||
tree might look like this::
|
|
||||||
|
|
||||||
- myProject/ - build/
|
- A "project" is a directory that contains all the files and configuration to build a single "app" (executable), as well as additional supporting output such as a partition table, data/filesystem partitions, and a bootloader.
|
||||||
|
|
||||||
|
- "Project configuration" is held in a single file called sdkconfig in the root directory of the project. This configuration file is modified via ``make menuconfig`` to customise the configuration of the project. A single project contains exactly one project configuration.
|
||||||
|
|
||||||
|
- An "app" is an executable which is built by esp-idf. A single project will usually build two apps - a "project app" (the main executable, ie your custom firmware) and a "bootloader app" (the initial bootloader program which launches the project app).
|
||||||
|
|
||||||
|
- "components" are modular pieces of standalone code which are compiled into static libraries (.a files) and linked into an app. Some are provided by esp-idf itself, others may be sourced from other places.
|
||||||
|
|
||||||
|
Some things are not part of the project:
|
||||||
|
|
||||||
|
- "ESP-IDF" is not part of the project. Instead it is standalone, and linked to the project via the ``IDF_PATH`` environment variable which holds the path of the ``esp-idf`` directory. This allows the IDF framework to be decoupled from your project.
|
||||||
|
|
||||||
|
- The toolchain for compilation is not part of the project. The toolchain should be installed in the system command line PATH, or the path to the toolchain can be set as part of the compiler prefix in the project configuration.
|
||||||
|
|
||||||
|
|
||||||
|
Example Project
|
||||||
|
---------------
|
||||||
|
|
||||||
|
An example project directory tree might look like this::
|
||||||
|
- myProject/
|
||||||
|
- Makefile
|
||||||
|
- sdkconfig
|
||||||
- components/ - component1/ - component.mk
|
- components/ - component1/ - component.mk
|
||||||
- Kconfig
|
- Kconfig
|
||||||
- src1.c
|
- src1.c
|
||||||
- component2/ - component.mk
|
- component2/ - component.mk
|
||||||
- Kconfig
|
- Kconfig
|
||||||
- src1.c
|
- src1.c
|
||||||
|
- include/
|
||||||
|
- component2.h
|
||||||
- main/ - src1.c
|
- main/ - src1.c
|
||||||
- src2.c
|
- src2.c
|
||||||
- Makefile
|
- component.mk
|
||||||
|
- build/
|
||||||
|
|
||||||
As we can see, a project consists of a components/ subdirectory containing its
|
This example "myProject" contains the following elements:
|
||||||
components as well as one or more directories containing the project-specific
|
|
||||||
sources; by default a single directory called 'main' is assumed. The project
|
|
||||||
directory will also have a Makefile where the projects name as well as optionally
|
|
||||||
other options are defined. After compilation, the project directory will contain
|
|
||||||
a 'build'-directory containing all of the objects, libraries and other generated
|
|
||||||
files as well as the final binary.
|
|
||||||
|
|
||||||
Components also have a custom makefile - ``component.mk``. This contains various definititions
|
- A top-level project Makefile. This Makefile set the ``PROJECT_NAME`` variable and (optionally) defines
|
||||||
influencing the build process of the component as well as the project it's used
|
other project-wide make variables. It includes the core ``$(IDF_PATH)/make/project.mk`` makefile which
|
||||||
in. Components may also include a Kconfig file defining the compile-time options that are
|
implements the rest of the ESP-IDF build system.
|
||||||
settable by means of the menu system.
|
|
||||||
|
|
||||||
Project Makefile variables that can be set by the programmer::
|
- "sdkconfig" project configuration file. This file is created/updated when "make menuconfig" runs, and holds configuration for all of the components in the project (including esp-idf itself). The "sdkconfig" file may or may not be added to the source control system of the project.
|
||||||
|
|
||||||
PROJECT_NAME: Mandatory. Name for the project
|
- Optional "components" directory contains components that are part of the project. A project does not have to contain custom components of this kind, but it can be useful for structuring reusable code or including third party components that aren't part of ESP-IDF.
|
||||||
BUILD_DIR_BASE: Set the directory where all objects/libraries/binaries end up in.
|
|
||||||
Defaults to $(PROJECT_PATH)/build
|
|
||||||
COMPONENT_DIRS: Search path for components. Defaults to the component/ directories
|
|
||||||
in the ESP-IDF path and the project path.
|
|
||||||
COMPONENTS: A list of component names. Defaults to all the component found in the
|
|
||||||
COMPONENT_DIRS directory
|
|
||||||
EXTRA_COMPONENT_DIRS: Defaults to unset. Use this to add directories to the default
|
|
||||||
COMPONENT_DIRS.
|
|
||||||
SRCDIRS: Directories under the project dir containing project-specific sources.
|
|
||||||
Defaults to 'main'. These are treated as 'lite' components: they do not have
|
|
||||||
include directories that are passed to the compilation pass of all components and
|
|
||||||
they do not have a Kconfig option.
|
|
||||||
|
|
||||||
Component-specific component.mk variables that can be set by the programmer::
|
- "main" directory is a special "pseudo-component" that contains source code for the project itself. "main" is a default name, the Makefile variable ``SRCDIRS`` defaults to this but can be set to look for pseudo-components in other directories.
|
||||||
|
|
||||||
COMPONENT_ADD_INCLUDEDIRS: Relative path to include directories to be added to
|
- "build" directory is where build output is created. After the make process is run, this directory will contain interim object files and libraries as well as final binary output files. This directory is usually not added to source control or distributed with the project source code.
|
||||||
the entire project. If an include directory is only needed to compile this
|
|
||||||
specific component, don't add it here.
|
Component directories contain a component makefile - ``component.mk``. This may contain variable definitions
|
||||||
COMPONENT_PRIV_INCLUDEDIRS: Relative path to include directories that are only used
|
to control the build process of the component, and its integration into the overall project. See `Component Makefiles` for more details.
|
||||||
when compiling this specific component.
|
|
||||||
COMPONENT_DEPENDS: Names of any components that need to be compiled before this component.
|
Each component may also include a ``Kconfig`` file defining the `component configuration` options that can be set via the project configuration. Some components may also include ``Kconfig.projbuild`` and ``Makefile.projbuild`` files, which are special files for `overriding parts of the project`.
|
||||||
COMPONENT_ADD_LDFLAGS: LD flags to add for the entire project. Defaults to -l$(COMPONENT_NAME).
|
|
||||||
Add libraries etc in the current directory as $(abspath libwhatever.a)
|
Project Makefiles
|
||||||
COMPONENT_EXTRA_INCLUDES: Any extra include paths used when compiling the component's
|
-----------------
|
||||||
source files. These will be prefixed with '-I' and passed to the compiler.
|
|
||||||
Similar to COMPONENT_PRIV_INCLUDEDIRS, but these paths are passed as-is instead of
|
Each project has a single Makefile that contains build settings for the entire project. By default, the project Makefile can be quite minimal.
|
||||||
|
|
||||||
|
Minimal Example Makefile
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
::
|
||||||
|
PROJECT_NAME := myProject
|
||||||
|
|
||||||
|
include $(IDF_PATH)/make/project.mk
|
||||||
|
|
||||||
|
|
||||||
|
Mandatory Project Variables
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
- ``PROJECT_NAME``: Name of the project. Binary output files will use this name - ie myProject.bin, myProject.elf.
|
||||||
|
|
||||||
|
Optional Project Variables
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
These variables all have default values that can be overridden for custom behaviour. Look in ``make/project.mk`` for all of the implementation details.
|
||||||
|
|
||||||
|
- ``PROJECT_PATH``: Top-level project directory. Defaults to the directory containing the Makefile. Many other project variables are based on this variable. The project path cannot contain spaces.
|
||||||
|
- ``BUILD_DIR_BASE``: The build directory for all objects/libraries/binaries. Defaults to ``$(PROJECT_PATH)/build``.
|
||||||
|
- ``COMPONENT_DIRS``: Directories to search for components. Defaults to `$(IDF_PATH)/components`, `$(PROJECT_PATH)/components` and ``EXTRA_COMPONENT_DIRS``. Override this variable if you don't want to search for components in the esp-idf & project ``components`` directories.
|
||||||
|
- ``EXTRA_COMPONENT_DIRS``: Optional list of additional directories to search for components. Components themselves are in sub-directories of these directories, this is a top-level directory containing the component directories.
|
||||||
|
- ``COMPONENTS``: A list of component names to build into the project. Defaults to all components found in the COMPONENT_DIRS directories.
|
||||||
|
- ``SRCDIRS``: Directories under the main project directory which contain project-specific "pseudo-components". Defaults to 'main'. The difference between specifying a directory here and specifying it under ``EXTRA_COMPONENT_DIRS`` is that a directory in ``SRCDIRS`` is a component itself (contains a file "component.mk"), whereas a directory in ``EXTRA_COMPONENT_DIRS`` contains component directories which contain a file "component.mk". See the `Example Project` for a concrete case of this.
|
||||||
|
|
||||||
|
|
||||||
|
Component Makefiles
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Each project contains one or more components, which can either be part of esp-idf or added from other component directories.
|
||||||
|
|
||||||
|
A component is any sub-directory that contains a `component.mk` file.[#f1]_.
|
||||||
|
|
||||||
|
Minimal Component Makefile
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The minimal ``component.mk`` file is an empty file(!). If the file is empty, the default component behaviour is set:
|
||||||
|
- All source files in the same directory as the makefile (*.c, *.cpp, *.S) will be compiled into the component library
|
||||||
|
- A sub-directory "include" will be added to the global include search path for all other components.
|
||||||
|
- The component library will be linked into the project app.
|
||||||
|
|
||||||
|
See `example component makefiles` for more complete component makefile examples.
|
||||||
|
|
||||||
|
Note that there is a different between an empty ``component.mk`` file (which invokes default component build behaviour) and no ``component.mk`` file (which means no default component build behaviour will occur.) It is possible for a component to have no `component.mk` file, if it only contains other files which influence the project configuration or build process.
|
||||||
|
|
||||||
|
.. component variables:
|
||||||
|
|
||||||
|
Preset Component Variables
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The following component-specific variables are available for use inside ``component.mk``, but should not be modified:
|
||||||
|
|
||||||
|
- ``COMPONENT_PATH``: The component directory. Evaluates to the absolute path of the directory containing ``component.mk``. The component path cannot contain spaces.
|
||||||
|
- ``COMPONENT_NAME``: Name of the component. Defaults to the name of the component directory.
|
||||||
|
- ``COMPONENT_BUILD_DIR``: The component build directory. Evaluates to the absolute path of a directory inside `$(BUILD_DIR_BASE)` where this component's source files are to be built. This is also the Current Working Directory any time the component is being built, so relative paths in make targets, etc. will be relative to this directory.
|
||||||
|
- ``COMPONENT_LIBRARY``: Name of the static library file (relative to the component build directory) that will be built for this component. Defaults to ``$(COMPONENT_NAME).a``.
|
||||||
|
|
||||||
|
The following variables are set at the project level, but exported for use in the component build:
|
||||||
|
|
||||||
|
- ``PROJECT_NAME``: Name of the project, as set in project Makefile
|
||||||
|
- ``PROJECT_PATH``: Absolute path of the project directory containing the project Makefile.
|
||||||
|
- ``COMPONENTS``: Name of all components that are included in this build.
|
||||||
|
- ``CONFIG_*``: Each value in the project configuration has a corresponding variable available in make. All names begin with ``CONFIG_``.
|
||||||
|
- ``CC``, ``LD``, ``AR``, ``OBJCOPY``: Full paths to each tool from the gcc xtensa cross-toolchain.
|
||||||
|
- ``HOSTCC``, ``HOSTLD``, ``HOSTAR``: Full names of each tool from the host native toolchain.
|
||||||
|
|
||||||
|
If you modify any of these variables inside ``component.mk`` then this will not prevent other components from building but it may make your component hard to build and/or debug.
|
||||||
|
|
||||||
|
Optional Project-Wide Component Variables
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The following variables can be set inside ``component.mk`` to control build settings across the entire project:
|
||||||
|
|
||||||
|
- ``COMPONENT_ADD_INCLUDEDIRS``: Paths, relative to the component
|
||||||
|
directory, which will be added to the include search path for
|
||||||
|
all components in the project. Defaults to ``include`` if not overridden. If an include directory is only needed to compile
|
||||||
|
this specific component, add it to ``COMPONENT_PRIV_INCLUDEDIRS`` instead.
|
||||||
|
- ``COMPONENT_ADD_LDFLAGS``: Add linker arguments to the LDFLAGS for
|
||||||
|
the app executable. Defaults to ``-l$(COMPONENT_NAME)``. If
|
||||||
|
adding pre-compiled libraries to this directory, add them as
|
||||||
|
absolute paths - ie $(COMPONENT_PATH)/libwhatever.a
|
||||||
|
- ``COMPONENT_DEPENDS``: Optional list of component names that should
|
||||||
|
be compiled before this component. This is not necessary for
|
||||||
|
link-time dependencies, because all component include directories
|
||||||
|
are available at all times. It is necessary if one component
|
||||||
|
generates an include file which you then want to include in another
|
||||||
|
component. Most components do not need to set this variable.
|
||||||
|
|
||||||
|
|
||||||
|
Optional Component-Specific Variables
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The following variables can be set inside ``component.mk`` to control the build of that component:
|
||||||
|
|
||||||
|
- ``COMPONENT_PRIV_INCLUDEDIRS``: Directory paths, must be relative to
|
||||||
|
the component directory, which will be added to the include search
|
||||||
|
path for this component's source files only.
|
||||||
|
- ``COMPONENT_EXTRA_INCLUDES``: Any extra include paths used when
|
||||||
|
compiling the component's source files. These will be prefixed with
|
||||||
|
'-I' and passed as-is to the compiler. Similar to the
|
||||||
|
``COMPONENT_PRIV_INCLUDEDIRS`` variable, except these paths are not
|
||||||
expanded relative to the component directory.
|
expanded relative to the component directory.
|
||||||
COMPONENT_SRCDIRS: Relative directories to look in for sources. Defaults to '.', the current
|
- ``COMPONENT_SRCDIRS``: Directory paths, must be relative to the
|
||||||
directory (the root of the component) only. Use this to specify any subdirectories. Note
|
component directory, which will be searched for source files (*.cpp,
|
||||||
that specifying this overwrites the default action of compiling everything in the
|
*.c, *.S). Defaults to '.', ie the component directory
|
||||||
components root dir; to keep this behaviour please also add '.' as a directory in this
|
itself. Override this to specify a different list of directories
|
||||||
list.
|
which contain source files.
|
||||||
COMPONENT_OBJS: Object files to compile. Defaults to the .o variants of all .c and .S files
|
- ``COMPONENT_OBJS``: Object files to compile. Default value is a .o
|
||||||
that are found in COMPONENT_SRCDIRS.
|
file for each source file that is found in ``COMPONENT_SRCDIRS``.
|
||||||
COMPONENT_EXTRA_CLEAN: Files that are generated using rules in the components Makefile
|
Overriding this list allows you to exclude source files in
|
||||||
that also need to be cleaned
|
``COMPONENT_SRCDIRS`` that would otherwise be compiled. See
|
||||||
COMPONENT_BUILDRECIPE: Recipe to build the component. Optional. Defaults to building all
|
`Specifying source files`
|
||||||
COMPONENT_OBJS and linking them into lib(componentname).a
|
- ``COMPONENT_EXTRA_CLEAN``: Paths, relative to the component build
|
||||||
COMPONENT_CLEANRECIPE: Recipe to clean the component. Optional. Defaults to removing
|
directory, of any files that are generated using custom make rules
|
||||||
all built objects and libraries.
|
in the component.mk file and which need to be removed as part of
|
||||||
COMPONENT_BUILD_DIR: Equals the cwd of the component build, which is the build dir
|
``make clean``. See `Source Code Generation` for an example.
|
||||||
of the component (where all the .o etc files should be created).
|
- ``COMPONENT_OWNBUILDTARGET`` & `COMPONENT_OWNCLEANTARGET`: These
|
||||||
|
targets allow you to fully override the default build behaviour for
|
||||||
|
the component. See `Fully Overriding The Component Makefile` for
|
||||||
|
more details.
|
||||||
|
- ``CFLAGS``: Flags passed to the C compiler. A default set of
|
||||||
|
``CFLAGS`` is defined based on project settings. Component-specific
|
||||||
|
additions can be made via ``CFLAGS +=``. It is also possible
|
||||||
|
(although not recommended) to override this variable completely for
|
||||||
|
a component.
|
||||||
|
- ``CPPFLAGS``: Flags passed to the C preprocessor (used for .c, .cpp
|
||||||
|
and .S files). A default set of ``CPPFLAGS`` is defined based on
|
||||||
|
project settings. Component-specific additions can be made via
|
||||||
|
``CPPFLAGS +=``. It is also possible (although not recommended) to
|
||||||
|
override this variable completely for a component.
|
||||||
|
- ``CXXFLAGS``: Flags passed to the C++ compiler. A default set of
|
||||||
|
``CXXFLAGS`` is defined based on project
|
||||||
|
settings. Component-specific additions can be made via ``CXXFLAGS
|
||||||
|
+=``. It is also possible (although not recommended) to override
|
||||||
|
this variable completely for a component.
|
||||||
|
|
||||||
These variables are already set early on in the Makefile and the values in it will
|
Component Configuration
|
||||||
be usable in component or project Makefiles::
|
-----------------------
|
||||||
|
|
||||||
CC, LD, AR, OBJCOPY: Xtensa gcc tools
|
Each component can also have a Kconfig file, alongside ``component.mk``. This contains contains
|
||||||
HOSTCC, HOSTLD etc: Host gcc tools
|
configuration settings to add to the "make menuconfig" for this component.
|
||||||
LDFLAGS, CFLAGS: Set to usable values as defined in ESP-IDF Makefile
|
|
||||||
PROJECT_NAME: Name of the project, as set in project makefile
|
|
||||||
PROJECT_PATH: Path to the root of the project folder
|
|
||||||
COMPONENTS: Name of the components to be included
|
|
||||||
CONFIG_*: All values set by 'make menuconfig' have corresponding Makefile variables.
|
|
||||||
|
|
||||||
Inside your component's component.mk makefile, you can override or add to these variables
|
These settings are found under the "Component Settings" menu when menuconfig is run.
|
||||||
as necessary. The changes are isolated from other components (see Makefile.projbuild below
|
|
||||||
if you want to share these changes with all other components.)
|
|
||||||
|
|
||||||
For components, there also are these defines::
|
To create a component KConfig file, it is easiest to start with one of the KConfig files distributed with esp-idf.
|
||||||
|
|
||||||
COMPONENT_PATH: Absolute path to the root of the source tree of the component we're
|
For an example, see `Adding conditional configuration`.
|
||||||
compiling
|
|
||||||
COMPONENT_LIBRARY: The full path to the static library the components compilation pass
|
|
||||||
is supposed to generate
|
|
||||||
|
|
||||||
Make Process
|
Build Process Internals
|
||||||
------------
|
-----------------------
|
||||||
|
|
||||||
The Make process is always invoked from the project directory by the
|
Top Level: Project Makefile
|
||||||
user; invoking it anywhere else gives an error. This is what happens if
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
we build a binary:
|
|
||||||
|
|
||||||
The Makefile first determines how it was included. It figures out
|
- "make" is always run from the project directory and the project makefile, typically named Makefile.
|
||||||
various paths as well as the components available to it. It will also
|
- The project makefile sets ``PROJECT_NAME`` and optionally customises other `optional project variables`
|
||||||
collect the ldflags and includes that the components specify they need.
|
- The project makefile includes ``$(IDF_PATH)/make/project.mk`` which contains the project-level Make logic.
|
||||||
It does this by running a dummy make on the components with a "get_variable"
|
- ``project.mk`` fills in default project-level make variables and includes make variables from the project configuration. If the generated makefile containing project configuration is out of date, then it is regenerated (via targets in ``project_config.mk``) and then the make process restarts from the top.
|
||||||
target that will output these values.
|
- ``project.mk`` builds a list of components to build, based on the default component directories or a custom list of components set in `optional project variables`.
|
||||||
|
- Each component can set some `optional project-wide component variables`. These are included via generated makefiles named ``component_project_vars.mk`` - there is one per component. These generated makefiles are included into ``project.mk``. If any are missing or out of date, they are regenerated (via a recursive make call to the component makefile) and then the make process restarts from the top.
|
||||||
|
- `Makefile.projbuild` files from components are included into the make process, to add extra targets or configuration.
|
||||||
|
- By default, the project makefile also generates top-level build & clean targets for each component and sets up `app` and `clean` targets to invoke all of these sub-targets.
|
||||||
|
- In order to compile each component, a recursive make is performed for the component makefile.
|
||||||
|
|
||||||
The Makefile will then create targets to build the lib*.a libraries of
|
To better understand the project make process, have a read through the ``project.mk`` file itself.
|
||||||
all components and make the elf target depend on this. The main Makefile
|
|
||||||
invokes Make on the componen.mk of each components inside a sub-mke: this way
|
|
||||||
the components have full freedom to do whatever is necessary to build
|
|
||||||
the library without influencing other components. By default, the
|
|
||||||
component.mk includes the utility makefile $(IDF_PATH)/make/component_common.mk.
|
|
||||||
This provides default targets and configurations that will work
|
|
||||||
out-of-the-box for most projects.
|
|
||||||
|
|
||||||
KConfig
|
Second Level: Component Makefiles
|
||||||
-------
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Each component can also have a Kconfig file, alongside the component.mk, that contains
|
- Each call to a component makefile goes via the ``$(IDF_PATH)/make/component_wrapper.mk`` wrapper makefile.
|
||||||
details to add to "menuconfig" for this component.
|
- The ``component_wrapper.mk`` is called with the current directory set to the component build directory, and the ``COMPONENT_MAKEFILE`` variable is set to the absolute path to ``component.mk``.
|
||||||
|
- ``component_wrapper.mk`` sets default values for all `component variables`, then includes the `component.mk` file which can override or modify these.
|
||||||
|
- If ``COMPONENT_OWNBUILDTARGET`` and ``COMPONENT_OWNCLEANTARGET`` are not defined, default build and clean targets are created for the component's source files and the prerequisite ``COMPONENT_LIBRARY`` static library file.
|
||||||
|
- The ``component_project_vars.mk`` file has its own target in ``component_wrapper.mk``, which is evaluated from ``project.mk`` if this file needs to be rebuilt due to changes in the component makefile or the project configuration.
|
||||||
|
|
||||||
|
To better understand the component make process, have a read through the ``component_wrapper.mk`` file and some of the ``component.mk`` files included with esp-idf.
|
||||||
|
|
||||||
|
Overriding Parts of the Project
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
Makefile.projbuild
|
Makefile.projbuild
|
||||||
------------------
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
For components that have parts that need to be evaluated in the top-level
|
For components that have build requirements that must be evaluated in the top-level
|
||||||
project context, you can create a file called Makefile.projbuild in the
|
project make pass, you can create a file called ``Makefile.projbuild`` in the
|
||||||
component root directory. These files is included into the project's
|
component directory. This makefile is included when ``project.mk`` is evaluated.
|
||||||
top-level Makefile.
|
|
||||||
|
|
||||||
For example, if your component needs to add to CFLAGS for the entire
|
For example, if your component needs to add to CFLAGS for the entire
|
||||||
project (not just for its own source files) then you can set
|
project (not just for its own source files) then you can set
|
||||||
``CFLAGS +=`` in Makefile.projbuild. Note that this isn't necessary for
|
``CFLAGS +=`` in Makefile.projbuild.
|
||||||
adding include directories to the project, you can set
|
|
||||||
``COMPONENT_ADD_INCLUDEDIRS`` (see above) in the component.mk.
|
|
||||||
|
|
||||||
|
``Makefile.projbuild`` files are used heavily inside esp-idf, for defining project-wide build features such as ``esptool.py`` command line arguments and the ``bootloader`` "special app".
|
||||||
|
|
||||||
|
Note that ``Makefile.projbuild`` isn't necessary for the most common component uses - such as adding include directories to the project, or LDFLAGS to the final linking step. These values can be customised via the ``component.mk`` file itself. See `Optional Project-Wide Component Variables` for details.
|
||||||
|
|
||||||
|
Take care when setting variables or targets in this file. As the values are included into the top-level project makefile pass, they can influence or break functionality across all components!
|
||||||
|
|
||||||
KConfig.projbuild
|
KConfig.projbuild
|
||||||
-----------------
|
^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
There's an equivalent to Makefile.projbuild for KConfig: if you want to include
|
This is an equivalent to `Makefile.projbuild` for `component configuration` KConfig files. If you want to include
|
||||||
options at the top-level, not inside the 'components' submenu then create a Kconfig.projbuild and
|
configuration options at the top-level of menuconfig, rather than inside the "Component Configuration" sub-menu, then these can be defined in the KConfig.projbuild file alongside the ``component.mk`` file.
|
||||||
it will be included in the main menu of menuconfig.
|
|
||||||
|
|
||||||
Take good care when (re)defining stuff here: because it's included with all the other
|
Take care when adding configuration values in this file, as they will be included across the entire project configuration. Where possible, it's generally better to create a KConfig file for `component configuration`.
|
||||||
.projbuild files, it's possible to overwrite variables or re-declare targets defined in
|
|
||||||
the ESP-IDF makefile/Kconfig and other .projbuild files. It's generally better to just
|
|
||||||
create a KConfig file, if you can.
|
|
||||||
|
|
||||||
|
|
||||||
Writing Component Makefiles
|
Example Component Makefiles
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
A component consists of a directory which doubles as the name for the
|
Because the build environment tries to set reasonable defaults that will work most
|
||||||
component: a component named 'httpd' lives in a directory called 'httpd'
|
of the time, component.mk can be very small or even empty (see `Minimal Component Makefile`). However, overriding `component variables` is usually required for some functionality.
|
||||||
Because components usually live under the project directory (although
|
|
||||||
they can also reside in an other folder), the path to this may be
|
|
||||||
something like /home/myuser/projects/myprojects/components/httpd .
|
|
||||||
|
|
||||||
Components can have any name (unique to the project) but the name
|
Here are some more advanced examples of ``component.mk`` makefiles:
|
||||||
cannot contain spaces (esp-idf does not support spaces in paths).
|
|
||||||
|
|
||||||
One of the things that most components will have is a component.mk makefile,
|
|
||||||
containing instructions on how to build the component. Because the
|
|
||||||
build environment tries to set reasonable defaults that will work most
|
|
||||||
of the time, component.mk can be very small.
|
|
||||||
|
|
||||||
Simplest component.mk
|
|
||||||
=====================
|
|
||||||
|
|
||||||
At the minimum, component.mk will just include the ESP-IDF component "common" makefile,
|
|
||||||
which adds common component functionality::
|
|
||||||
|
|
||||||
include $(IDF_PATH)/make/component_common.mk
|
|
||||||
|
|
||||||
This will take all the .c and .S files in the component root and compile
|
|
||||||
them into object files, finally linking them into a library.
|
|
||||||
|
|
||||||
|
|
||||||
Adding source directories
|
Adding source directories
|
||||||
=========================
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
By default, subdirectories are ignored. If your project has sources in subdirectories
|
By default, sub-directories are ignored. If your project has sources in sub-directories
|
||||||
instead of in the root of the component then you can tell that to the build
|
instead of in the root of the component then you can tell that to the build
|
||||||
system by setting COMPONENT_SRCDIRS::
|
system by setting ``COMPONENT_SRCDIRS``::
|
||||||
|
|
||||||
COMPONENT_SRCDIRS := src1 src2
|
COMPONENT_SRCDIRS := src1 src2
|
||||||
include $(IDF_PATH)/make/component_common.mk
|
|
||||||
|
|
||||||
This will compile all source files in the src1/ and src2/ subdirectories
|
This will compile all source files in the src1/ and src2/ sub-directories
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
Specifying source files
|
Specifying source files
|
||||||
=======================
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The standard component.mk logic adds all .S and .c files in the source
|
The standard component.mk logic adds all .S and .c files in the source
|
||||||
directories as sources to be compiled unconditionally. It is possible
|
directories as sources to be compiled unconditionally. It is possible
|
||||||
to circumvent that logic and hardcode the objects to be compiled by
|
to circumvent that logic and hard-code the objects to be compiled by
|
||||||
manually setting the COMPONENT_OBJS variable to the name of the
|
manually setting the ``COMPONENT_OBJS`` variable to the name of the
|
||||||
objects that need to be generated::
|
objects that need to be generated::
|
||||||
|
|
||||||
COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o
|
COMPONENT_OBJS := file1.o file2.o thing/filea.o thing/fileb.o anotherthing/main.o
|
||||||
include $(IDF_PATH)/make/component_common.mk
|
COMPONENT_SRCDIRS := . thing anotherthing
|
||||||
|
|
||||||
|
Note that ``COMPONENT_SRCDIRS`` must be set as well.
|
||||||
|
|
||||||
Adding conditional configuration
|
Adding conditional configuration
|
||||||
================================
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The configuration system can be used to conditionally compile some files
|
The configuration system can be used to conditionally compile some files
|
||||||
dependending on the options selected in ``make menuconfig``:
|
depending on the options selected in ``make menuconfig``:
|
||||||
|
|
||||||
Kconfig::
|
``Kconfig``::
|
||||||
config FOO_ENABLE_BAR
|
config FOO_ENABLE_BAR
|
||||||
bool "Enable the BAR feature."
|
bool "Enable the BAR feature."
|
||||||
help
|
help
|
||||||
This enables the BAR feature of the FOO component.
|
This enables the BAR feature of the FOO component.
|
||||||
|
|
||||||
Makefile::
|
``component.mk``::
|
||||||
COMPONENT_OBJS := foo_a.o foo_b.o $(if $(CONFIG_FOO_ENABLE_BAR),foo_bar.o foo_bar_interface.o)
|
COMPONENT_OBJS := foo_a.o foo_b.o
|
||||||
include $(IDF_PATH)/make/component_common.mk
|
|
||||||
|
ifdef CONFIG_FOO_BAR
|
||||||
|
COMPONENT_OBJS += foo_bar.o foo_bar_interface.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
See the `GNU Make Manual` for conditional syntax that can be used use in makefiles.
|
||||||
|
|
||||||
|
|
||||||
Source Code Generation
|
Source Code Generation
|
||||||
======================
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
Some components will have a situation where a source file isn't supplied
|
Some components will have a situation where a source file isn't
|
||||||
with the component itself but has to be generated from another file. Say
|
supplied with the component itself but has to be generated from
|
||||||
our component has a header file that consists of the converted binary
|
another file. Say our component has a header file that consists of the
|
||||||
data of a BMP file, converted using a hypothetical tool called bmp2h. The
|
converted binary data of a BMP file, converted using a hypothetical
|
||||||
header file is then included in as C source file called graphics_lib.c::
|
tool called bmp2h. The header file is then included in as C source
|
||||||
|
file called graphics_lib.c::
|
||||||
|
|
||||||
COMPONENT_EXTRA_CLEAN := logo.h
|
COMPONENT_EXTRA_CLEAN := logo.h
|
||||||
|
|
||||||
@@ -272,16 +378,25 @@ header file is then included in as C source file called graphics_lib.c::
|
|||||||
logo.h: $(COMPONENT_PATH)/logo.bmp
|
logo.h: $(COMPONENT_PATH)/logo.bmp
|
||||||
bmp2h -i $^ -o $@
|
bmp2h -i $^ -o $@
|
||||||
|
|
||||||
include $(IDF_PATH)/make/component_common.mk
|
|
||||||
|
|
||||||
In this example, graphics_lib.o and logo.h will be generated in the
|
In this example, graphics_lib.o and logo.h will be generated in the
|
||||||
current directory (the build directory) while logo.bmp comes with the
|
component build directory, whereas logo.bmp resides in the component
|
||||||
component and resides under the component path. Because logo.h is a
|
source directory.
|
||||||
generated file, it needs to be cleaned when make clean is called which
|
|
||||||
why it is added to the COMPONENT_EXTRA_CLEAN variable.
|
Because logo.h is a generated file, it needs to be cleaned when make
|
||||||
|
clean is called which why it is added to the COMPONENT_EXTRA_CLEAN
|
||||||
|
variable.
|
||||||
|
|
||||||
|
Adding logo.h to the ``graphics_lib.o`` dependencies causes it to be
|
||||||
|
generated before ``graphics_lib.c`` is compiled.
|
||||||
|
|
||||||
|
If a a source file in another component included ``logo.h``, then this
|
||||||
|
component's name would have to be added to the other component's
|
||||||
|
``COMPONENT_DEPENDS`` list to ensure that the components were built
|
||||||
|
in-order.
|
||||||
|
|
||||||
Cosmetic Improvements
|
Cosmetic Improvements
|
||||||
=====================
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
The above example will work just fine, but there's one last cosmetic
|
The above example will work just fine, but there's one last cosmetic
|
||||||
improvement that can be done. The make system tries to make the make
|
improvement that can be done. The make system tries to make the make
|
||||||
@@ -298,7 +413,6 @@ make process::
|
|||||||
$(summary) BMP2H $@
|
$(summary) BMP2H $@
|
||||||
$(Q) bmp2h -i $^ -o $@
|
$(Q) bmp2h -i $^ -o $@
|
||||||
|
|
||||||
include $(IDF_PATH)/make/component_common.mk
|
|
||||||
|
|
||||||
Fully Overriding The Component Makefile
|
Fully Overriding The Component Makefile
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
@@ -307,12 +421,15 @@ Obviously, there are cases where all these recipes are insufficient for a
|
|||||||
certain component, for example when the component is basically a wrapper
|
certain component, for example when the component is basically a wrapper
|
||||||
around another third-party component not originally intended to be
|
around another third-party component not originally intended to be
|
||||||
compiled under this build system. In that case, it's possible to forego
|
compiled under this build system. In that case, it's possible to forego
|
||||||
the build system entirely by setting COMPONENT_OWNBUILDTARGET and
|
the esp-idf build system entirely by setting COMPONENT_OWNBUILDTARGET and
|
||||||
possibly COMPONENT_OWNCLEANTARGET and defining your own build- and clean
|
possibly COMPONENT_OWNCLEANTARGET and defining your own targets named ``build`` and ``clean`` in ``component.mk``
|
||||||
target. The build target can do anything as long as it creates
|
target. The build target can do anything as long as it creates
|
||||||
$(COMPONENT_LIBRARY) for the main file to link into the project binary,
|
$(COMPONENT_LIBRARY) for the project make process to link into the app binary.
|
||||||
and even that is not necessary: if the COMPONENT_ADD_LDFLAGS variable
|
|
||||||
is set, the component can instruct the linker to do anything else as well.
|
(Actually, even this is not strictly necessary - if the COMPONENT_ADD_LDFLAGS variable
|
||||||
|
is set then the component can instruct the linker to link other binaries instead.)
|
||||||
|
|
||||||
|
|
||||||
.. _esp-idf-template: https://github.com/espressif/esp-idf-template
|
.. _esp-idf-template: https://github.com/espressif/esp-idf-template
|
||||||
|
.. _GNU Make Manual: https://www.gnu.org/software/make/manual/make.html
|
||||||
|
.. _[_f1]: Actually, some components in esp-idf are "pure configuration" components that don't have a component.mk file, only a Makefile.projbuild and/or Kconfig.projbuild file. However, these components are unusual and most components have a component.mk file.
|
||||||
|
Reference in New Issue
Block a user