Zephyr has encapsulated a lot of functionality in its build system around CMake, primarily through a series of macros and functions that simplify the declaration of libraries and modules, the addition of source files, the setting of include directories, and linking operations. Below are detailed explanations of some key points:
1.zephyr_library() Macro
lFunction
This macro essentially wraps the CMake add_library() command, but it automatically applies specific settings of the Zephyr build system, such as adding standard compilation options, defining macros, and setting target properties, allowing the generated static library to seamlessly integrate into Zephyr applications.
lUsage Example
In a module’s CMakeLists.txt, you can declare a library like this:
zephyr_library() zephyr_library_sources( src/foo.c src/bar.c ) zephyr_library_include_directories(include)
|
This not only adds the source code files to the library but also automatically adds the include directory to the compiler’s search path.
2.Conditional Compilation and Encapsulation
lConditionally Adding Source Files
Zephyr provides macros like zephyr_library_sources_ifdef() that can conditionally add source files to the library based on the value of Kconfig options. For example:
zephyr_library_sources_ifdef(CONFIG_FEATURE_X src/feature_x.c) |
Only when CONFIG_FEATURE_X is enabled in Kconfig will feature_x.c be compiled in.
lEncapsulating Include Directories
Similar to adding source files, zephyr_include_directories() and its conditional versions ensure the correct setup of header file directories while remaining consistent with the overall configuration of Zephyr.
3.Module and Global Library Management
lAutomatically Added to Global List
Libraries declared using zephyr_library() are typically automatically added to the global library list (e.g., ZEPHYR_LIBS), so that during subsequent linking stages, Zephyr will link these libraries with the main application. This mechanism hides the complexity of manually managing library dependencies.
lInterface Library Encapsulation
In addition to static libraries, Zephyr also encapsulates the concept of interface libraries (e.g., zephyr_interface_library()), allowing certain modules to expose interfaces without directly participating in compilation, thus enabling more flexible management of inter-module dependencies.
4.Using Static Library Files
Using static library files in Zephyr is primarily accomplished by modifying the CMake configuration files. Below is a common method:
Importing the library in CMakeLists.txt. Add the following configuration in your project root directory (or the application’s CMakeLists.txt file) to import this static library:
# Declare an IMPORTED type static library target add_library(foo STATIC IMPORTED)
# Set the path to the library file, be sure to modify according to the actual path set_target_properties(foo PROPERTIES IMPORTED_LOCATION “${CMAKE_CURRENT_LIST_DIR}/foo.a” )
# Link the static library to the application target_link_libraries(app PRIVATE foo)
# If there are additional include directories, they can also be set target_include_directories(app PRIVATE ${CMAKE_CURRENT_LIST_DIR} ) |
After adding the imported CMake directory to the project, the code directory can be hidden. At this point, the static library contains all the files from the code, but any functions that need to be exposed to the outside must be written in the header file.
|—lib |—-|—CMakeLists.txt |—-|—foo.h |—-|—foo.a |
When calling functions from the static library in other C files, include:
#include “foo.h“ |