build implementation
Design ideas
ARMINO construction is mainly designed with object-oriented thinking, and the key points to understand:
Second scan of CMakeLists.txt, there is a chance to do some special processing during dependency expansion
Dependency expansion is performed before building to simplify the writing of dependencies
projects/components is derived from cmake’s projects/target, overriding default values by setting specific variables before the function call, and by setting specific properties after the function call
Allow projects/components to be hooked before, during, and after core script execution
Provide packaged APIs to handle more than 90% of the vast majority of scenarios, only a few special scenarios require complex cmake script processing
build script
The listing file for the ARMINO build system is located in /tools/build_tools/cmake.The modules that implement the core functions of the build system are as follows
build.cmake - build related functions, i.e. build initialization, retrieving/setting build properties, build processing.
component.cmake - Component related functions, such as adding components, retrieving/setting component properties, registering components.
kconfig.cmake - Generate configuration files (sdkconfig, sdkconfig.h, sdkconfig.cmake, etc.) from Kconfig files.
target.cmake - sets the build target and toolchain files.
utilities.cmake - other help commands.
In addition to these files, there are two important CMake scripts in /tools/build_tools/cmake:
armino.cmake - sets build parameters and imports the core modules listed above.
project.cmake - imports
armino.cmakeand provides a customproject()command that handles all the heavy lifting of building the executable. Included in the top-level CMakeLists.txt of a standard ARMINO project
The other files in /tools/build_tools/cmake are support files or third-party scripts for the build process.
build process
The build process can be roughly divided into four stages: initialization, Generate-component-list, component-handling and Finish.
initialization
This phase sets the necessary parameters for the build.
- After importing
armino.cmakeintoproject.cmake, the following steps are performed:
Set
ARMINO_PATHin an environment variable or infer a relative path from theproject.cmakepath contained in the top-level CMakeLists.txt.Add /tools/build_tools/cmake to
CMAKE_MODULE_PATHand import core modules and various helper/3rd party scripts.Set build tools/executables like default Python interpreter.
Set global build parameters, i.e. compile options, compile definitions, include directories for all components.
Add components from components and middleware to the build.
- The initial part of the custom
project()command performs the following steps:
Set
ARMINO_TARGETin an environment variable or CMake cache and setCMAKE_TOOLCHAIN_FILEto use accordingly.Add components from
EXTRA_COMPONENTS_DIRSto the buildPrepare parameters for calling command
armino_build_process()from variables such asCOMPONENTS/EXCLUDE_COMPONENTS、SDKCONFIG、SDKCONFIG_DEFAULTSetc. phase.
armino_build_process() command marks the end of this.
Generate component list
This phase builds a list of components that need to be processed during the build process, and is done in the first half of
armino_build_process().
Find public and private dependencies for each component. Create a subprocess to execute each component’s CMakeLists.txt in script mode. The values of the
armino_component_registerREQUIRES and PRIV_REQUIRES parameters are returned to the parent process. This is the component dependency extension (or early extension). In this step define the variable CMAKE_BUILD_EARLY_EXPANSION.Recursively import individual components based on public and private dependencies.
Note
Each CMakeLists.txt in the component will be executed twice,the first time occurs in the _<generate component list> stage, the purpose is to expand the component dependencies with armino_component_register(), At this point Kconfig is not loaded, so it is not possible to determine whether a component should be loaded or not by the CONFIG_XXX values in Kconfig.
If it is necessary to add component dependencies to the CPU during the generation of the component list stage, the following method can be referred to:
armino_build_get_property(target ARMINO_SOC)
if ("${target}" STREQUAL "bk7239")
list(APPEND depenency_component)
endif()
component handling
This stage handles components in the build and is the second half of
armino_build_process().
Load the project configuration from the sdkconfig file and generate the sdkconfig.cmake and sdkconfig.h header files. These two files define configuration variables/macros that can be accessed from build scripts and C/C++ source/header files, respectively.
Import project_include.cmake for each component.
Add each component as a subdirectory, processing its CMakeLists.txt. The component CMakeLists.txt calls the registration command
armino_component_registerto add source files, import directories, create component libraries, link dependencies, etc.
Finish
This stage is the remaining step of
armino_build_process().
Create an executable and link it into the component library.
Generate project metadata files such as project_description.json and display relevant information such as the built project.
The execution steps of the compilation process are saved in the
buildninjafile corresponding to the project SOC in the build directory. If you need to view the specific compilation tree, you can check thearminofolder in the same directory, which stores the.c.objand. afiles during the compilation process.
Please refer to /tools/build_tools/cmake/project.cmake for more information.