doc: build overview: Improve diagram, fix errors/stale info, misc.

Diagram and text improvements:

 - Redraw the configuration phase diagram to better reflect the actual
   logic. Remove some misleading arrows, like from devicetree.h to
   Kconfig. Kconfig uses the devicetree scripts directly.

 - After the old devicetree scripts were removed in commit c8c35f76ab
   ("scripts: dts: Remove deprecated extract_dts_includes.py script"),
   the dtc compiler is only run to catch any high-level warnings and
   errors from it. The output is unused.

   Update the diagram and descriptions to explain how dtc is used.

 - Mention kconfigfunctions.py and explain better how devicetree and
   Kconfig interact

 - Clarify that 'cpp' is the C preprocessor. People often confuse it
   with C++.

 - Fix a typo'd devicetree_fixups.h in the text

 - Use the :file: role for files instead of italic text

 - Add links to the devicetree and Kconfig sections of the manual, and
   use the :zephyr_file: role to turn more files into direct links

 - Make the text generic re. Make vs. Ninja

 - Lots of other minor tweaks and clarifications

Signed-off-by: Ulf Magnusson <Ulf.Magnusson@nordicsemi.no>
This commit is contained in:
Ulf Magnusson 2020-01-21 17:09:58 +01:00 committed by Anas Nashif
commit dbed9027ba
2 changed files with 60 additions and 34 deletions

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Before After
Before After

View file

@ -3,10 +3,8 @@
Build Overview
##############
The Zephyr build process can be divided into two main phases: a
configuration phase (driven by *CMake*) and a build phase (driven by
*Make* or *Ninja*). We will describe the build phase using *Make* as
example.
The Zephyr build process can be divided into two main phases: a configuration
phase (driven by CMake) and a build phase (driven by Make or Ninja).
Configuration Phase
@ -21,43 +19,71 @@ specifying a source application directory and a board target.
:figclass: align-center
:width: 80%
*CMake* begins by processing the *CMakeLists.txt* file in the application
directory, which refers to the *CMakeLists.txt* file in the Zephyr
top-level directory, which in turn refers to *CMakeLists.txt* files
throughout the build tree (directly and indirectly). Its primary
output is a set of Makefiles to drive the build process, but *CMake*
scripts do some build processing of their own:
CMake begins by processing the :file:`CMakeLists.txt` file in the application
directory, which refers to the :file:`CMakeLists.txt` file in the Zephyr
top-level directory, which in turn refers to :file:`CMakeLists.txt` files
throughout the build tree (directly and indirectly). Its primary output is a
set of Makefiles or Ninja files to drive the build process, but the CMake
scripts also do some processing of their own:
Device tree
Using *cpp*, device-tree specifications (*.dts/.dtsi* files) are
collected from the targets architecture, SoC, board, and
application directories and compiled with *dtc*. Then the build
tool (scripts/dts) convert this into *.h* files for later
consumption.
Devicetree
:file:`*.dts` (*devicetree source*) and :file:`*.dtsi` (*devicetree source
include*) files are collected from the target's architecture, SoC, board,
and application directories.
Device tree fixup
Files named *dts_fixup.h* from the targets architecture, SoC,
board, and application directories are concatenated into a single
*dts_fixup.h*. Its purpose is to normalize constants output in the
previous step so they have the names expected by the source files
in the build phase.
:file:`*.dtsi` files are included by :file:`*.dts` files via the C
preprocessor (often abbreviated *cpp*, which should not be confused with
C++). The C preprocessor is also used to merge in any devicetree
:file:`*.overlay` files, and to expand macros in :file:`*.dts`,
:file:`*.dtsi`, and :file:`*.overlay` files.
The preprocessed devicetree sources (stored in :file:`*.dts.pre.tmp`) are
parsed by :zephyr_file:`gen_defines.py <scripts/dts/gen_defines.py>` to
generate a :file:`devicetree_unfixed.h` header with preprocessor macros.
The ``dtc`` devicetree compiler also gets run on the preprocessed devicetree
sources to catch any extra warnings and errors generated by it. The output
from ``dtc`` is unused otherwise.
The above is just a brief overview. For more information on devicetree, see
:ref:`the devicetree section of the manual <device-tree>`.
Devicetree fixups
Files named :file:`dts_fixup.h` from the targets architecture, SoC, board,
and application directories are concatenated into a single
:file:`devicetree_fixups.h` file. :file:`dts_fixup.h` files are used to
rename generated macros to names expected by the source code.
Source code accesses preprocessor macros generated from devicetree by
including the :zephyr_file:`devicetree.h <include/devicetree.h>` header,
which includes :file:`devicetree_unfixed.h` and :file:`devicetree_fixups.h`.
Kconfig
The build tool reads the *Kconfig* files for the target
architecture, the target SoC, the target board, the target
application, as well as *Kconfig* files associated with subsystems
throughout the source tree. It incorporates the device tree outputs
to allow configurations to make use of that data. It ensures the
desired configuration is consistent, outputs *autoconf.h* for the
build phase.
:file:`Kconfig` files define available configuration options for for the
target architecture, SoC, board, and application, as well as dependencies
between options.
Kconfig configurations are stored in *configuration files*. The initial
configuration is generated by merging configuration fragments from the board
and application (e.g. :file:`prj.conf`).
The output from Kconfig is an :file:`autoconf.h` header with preprocessor
assignments, and a :file:`.config` file that acts both as a saved
configuration and as configuration output (used by CMake).
Information from devicetree is available to Kconfig, through the functions
defined in :zephyr_file:`kconfigfunctions.py
<scripts/kconfig/kconfigfunctions.py>`.
See :ref:`the Kconfig section of the manual <kconfig>` for more information.
Build Phase
***********
The build phase begins when the user invokes *make*. Its ultimate
output is a complete Zephyr application in a format suitable for
loading/flashing on the desired target board (*zephyr.elf*,
*zephyr.hex*, etc.) The build phase can be broken down, conceptually,
The build phase begins when the user invokes ``make`` or ``ninja``. Its
ultimate output is a complete Zephyr application in a format suitable for
loading/flashing on the desired target board (:file:`zephyr.elf`,
:file:`zephyr.hex`, etc.) The build phase can be broken down, conceptually,
into four stages: the pre-build, first-pass binary, final binary, and
post-processing.