导入第三方库概述
可以在应用程序的目录之外生成库代码,但重要的是应用程序和库代码都面向相同的应用程序二进制接口 (ABI)
。在大多数体系结构上,都有控制ABI
目标的编译器标志
,因此库和应用程序具有某些共同的编译器标志非常重要。
为了更轻松地集成第三方组件,Zephyr构建系统
定义了CMake函数
,使应用程序构建脚本
能够访问zephyr编译器选项
。这些函数在cmake/extensions.cmake
中记录和定义,并遵循zephyr_get_<type>_<format>
命名约定。
以下变量通常需要导出到第三方生成系统:
- 编译标志
CMAKE_C_COMPILER
- 链接标志
CMAKE_AR
- 体系架构
ARCH
- 板子信息
BOARD
- 标识
Zephyr
内核版本
示例
目录结构
|--++ external_lib
|--++ mylib
|--++ include
|-- mylib.h
|--++ src
|-- mylib.c
|-- Makefile
|--++ src
|-- main.c
|-- CMakeLists.txt
|-- README.rst
|-- prj.conf
|-- sample.yaml
CmakeLists.txt的编写
# SPDX-License-Identifier: Apache-2.0
# 指定cmake的最低运行版本
cmake_minimum_required(VERSION 3.20.0)
# 查找zephyr
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
# 定义项目名称
project(external_lib)
# 添加应用程序的源文件
target_sources(app PRIVATE src/main.c)
# 获取zephyr编译C代码的系统的头文件路径
zephyr_get_include_directories_for_lang_as_string(C includes)
# 获取zephyr编译C代码系统的头文件系统路径
zephyr_get_system_include_directories_for_lang_as_string(C system_includes)
# 获取zephyr编译C代码的外部定义
zephyr_get_compile_definitions_for_lang_as_string(C definitions)
# 获取zephyr编译C代码的编译标志
zephyr_get_compile_options_for_lang_as_string(C options)
# 设置编译第三方库时的标志
set(external_project_cflags
"${includes} ${definitions} ${options} ${system_includes}"
)
# 包含外部项目模块
include(ExternalProject)
# 设置需要编译外部库的源码目录
set(mylib_src_dir ${CMAKE_CURRENT_SOURCE_DIR}/mylib)
# 设置需要编译外部库的头文件目录
set(mylib_build_dir ${CMAKE_CURRENT_BINARY_DIR}/mylib)
# 设置生成的库的存放目录
set(MYLIB_LIB_DIR ${mylib_build_dir}/lib)
# 设置库的头文件路径
set(MYLIB_INCLUDE_DIR ${mylib_src_dir}/include)
# 判定camke使用的的生成器,然后设置生成库时采用的生成器一致
if(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
# https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html
set(submake "$(MAKE)")
else() # Obviously no MAKEFLAGS. Let's hope a "make" can be found somewhere.
set(submake "make")
endif()
# 设置生成库时需要的信息
ExternalProject_Add(
mylib_project # 一个自定义的目标
PREFIX ${mylib_build_dir} # 库的根目录
SOURCE_DIR ${mylib_src_dir} # 库的源码目录
BINARY_DIR ${mylib_src_dir} # 库的二进制根目录
CONFIGURE_COMMAND "" # 库的配置命令
BUILD_COMMAND # 库的编译命令
${submake} # 库使用的生成器
PREFIX=${mylib_build_dir} # 库编译时的根目录
CC=${CMAKE_C_COMPILER} # 库编译时采用的C标志
AR=${CMAKE_AR} # 库连接时采用的C连接标志
CFLAGS=${external_project_cflags} # 库编译时采用的外部标志
INSTALL_COMMAND "" # 库的安装指令
BUILD_BYPRODUCTS ${MYLIB_LIB_DIR}/libmylib.a # 编译之后存放的文件
)
# 创建一个我们的应用程序可以链接的包装器CMake库
add_library(mylib_lib STATIC IMPORTED GLOBAL)
# mylib_lib目标依赖于mylib_project的目标执行
add_dependencies(
mylib_lib
mylib_project
)
# 设置mylib_lib的IMPORTED_LOCATION属性为生成的静态库
set_target_properties(mylib_lib PROPERTIES IMPORTED_LOCATION ${MYLIB_LIB_DIR}/libmylib.a)
# 设置mylib_lib的INTERFACE_INCLUDE_DIRECTORIES属性为头文件路径
set_target_properties(mylib_lib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${MYLIB_INCLUDE_DIR})
# 连接生成的库到应用程序
target_link_libraries(app PUBLIC mylib_lib)