The xCDL Build Process
Work in progress.
This chapter describes the whole build process.
Configuration consequences
Some xCDL properties describe the consequences of manipulating configuration options. There are two main types of consequences.
- Typically enabling a configuration option results in one or more
#definelines in a configuration header file, and properties that affect this includeheaderFile,customDefine, andvalueFormat. - Enabling a configuration option can also affect the build process,
primarily determining which files are used in the build. Properties
related to the build process include
sourceFiles.
Build systems
Part of the overall design of the xCDL component framework is that it
can interact with different build systems and also might run the build
internally. The most obvious of these is GNU make: the component
framework can generate one or more makefiles, and the user can then
build the various packages simply by invoking make.
A more modern solution is to generate build.ninja files, for the
Ninja build system. Another choice is
to interact with CMake and meson.
However it should also be possible to use xCDL components in other
environments too: the component framework can be queried about what is
involved in building a given configuration, and this information can
then be fed into the desired build system. Component authors should be
aware of this possibility. Most packages will not be affected because
the sourceFiles property can be used to provide the list of
source files in a portable manner. However, some build systems might
need further specific details, which will probably require further
properties be added.
Build tree generation
Before anything can be built, it is necessary to create an xCDL
configuration. This is expected to be done via a configuration
(graphical) tool and the result is a cdlConfigurations object in the
xcdl-configurations.json file. This object remembers all user choices entered
during configuration, like manually enabling/disabling objects and
entering values for data objects. Each build configuration has its own
cdlConfigurations object.
An xCDL build actually involves several separate folders.
- The source for the build is the component repository, and for application developers this should be considered a read-only resource.
- The build tree is where all intermediate files, especially object files, and the final artefacts are created.
The primary goal of the xCDL framework is to generate binary executable files for various target platforms.
Future version may be enhanced to also generate libraries; in this case the build will create an install folder where all public header files and configuration files are located.
Following a successful build it is possible to take just the output artefact and use it: none of the files in the component repository or the build tree are needed for that. The build tree will be needed again only if the user changes the source code or the configuration.
By default the configuration file and the build tree reside in the project folder. However this is not a requirement, all folders can be anywhere in the file system.
In the build folder there will be at least one generated file with the project specific #define lines.
Details of header file generation are given below.
The component framework does not define the structure of the build tree, and this may vary between build systems. It can be assumed that each package in the configuration will have its own folder in the build tree, and that this folder will be used for storing the package's object files and as the current folder for any build steps for that package. This avoids problems when custom build steps from different packages generate intermediate files which happen to have the same name.
The build tree is created and the headers are generated in a single
separate workflow step (via xcdl setup); after this multiple build
steps can be performed in the build tree; between them the application
source code can be changed, but not the configuration.
If the configuration needs updates (like enabling/disabling or changing configuration options values), the build tree must be regenerated from scratch.
Configuration Header File Generation
Configuration options can affect a build in two main ways. First,
enabling an xCDL component can result in various files being added to the
built, thus providing functionality to the resulting artefacts.
However this mechanism can only operate at a rather coarse grain,
at the level of entire source files. Hence the component framework also
generates configuration header files containing mainly C preprocessor
#define directives. Package source code can then #include the
appropriate header files and use #if, #ifdef and #ifndef
directives to adapt accordingly. In this way configuration options can
be used to enable or disable entire functions within a source file or
just a single line, whichever is appropriate.
The configuration header files end up in a folder in the build tree,
usually generated. It is up to the component authors
how many files are
generated, and how definitions are split between components.
The header files are generated when creating the build tree, which needs to happen after every change to the configuration.
The component framework processes each package in the configuration one
at a time. The exact order in which the packages are processed is not
defined, so the order in which #define's will end up in the headers
may vary. However for any given configuration the order should remain
consistent until packages are added to or removed from the system. This
avoids unnecessary changes to the global header file and hence
unnecessary rebuilds of the packages and of application code because of
header file dependency handling.
Within a given package the various components, options and interfaces
will be processed in the order in which they were defined in the
corresponding xCDL files. Typically the data in the configuration
headers consists only of a sequence of #define's so the order in
which these are generated is irrelevant. It should be noted that
re-parenting an object below some other package has no effect on which
header file will contain the corresponding #define: the preprocessor
directives will always end up in the header file for the package that
defines the object.
There are several properties which affect the process of generating
header files: headerFile, customDefineand valueFormat.
The headerFile property can only occur in the body of a
cdlPackage or cdlComponents object and specifies the path of the
header file where the configuration data is written, for example:
{
"cdlPackage": {
"name": "hal.arm",
"display": "Arm architecture",
"headerFile": "include/os/hal/hal-arm-generated.h"
}
}
Given such a headerFile property, the component framework will use the file include/os/hal/hal-arm-generated.h for the package's configuration data.
Building Test Cases
TBD
Credits
The initial content of this page was based on Chapter 4. The Build Process of The eCos Component Writer's Guide, by Bart Veer and John Dallaway, published in 2001.
Also: