导入第三方库概述

可以在应用程序的目录之外生成库代码,但重要的是应用程序和库代码都面向相同的应用程序二进制接口 (ABI)。在大多数体系结构上,都有控制ABI目标的编译器标志,因此库和应用程序具有某些共同的编译器标志非常重要。
为了更轻松地集成第三方组件,Zephyr构建系统定义了CMake函数,使应用程序构建脚本能够访问zephyr编译器选项。这些函数在cmake/extensions.cmake中记录和定义,并遵循zephyr_get_<type>_<format>命名约定。
以下变量通常需要导出到第三方生成系统:

  • 编译标志CMAKE_C_COMPILER
  • 链接标志CMAKE_AR
  • 体系架构ARCH
  • 板子信息BOARD
  • 标识Zephyr内核版本

示例

目录结构

  1. |--++ external_lib
  2. |--++ mylib
  3. |--++ include
  4. |-- mylib.h
  5. |--++ src
  6. |-- mylib.c
  7. |-- Makefile
  8. |--++ src
  9. |-- main.c
  10. |-- CMakeLists.txt
  11. |-- README.rst
  12. |-- prj.conf
  13. |-- sample.yaml

CmakeLists.txt的编写

  1. # SPDX-License-Identifier: Apache-2.0
  2. # 指定cmake的最低运行版本
  3. cmake_minimum_required(VERSION 3.20.0)
  4. # 查找zephyr
  5. find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
  6. # 定义项目名称
  7. project(external_lib)
  8. # 添加应用程序的源文件
  9. target_sources(app PRIVATE src/main.c)
  10. # 获取zephyr编译C代码的系统的头文件路径
  11. zephyr_get_include_directories_for_lang_as_string(C includes)
  12. # 获取zephyr编译C代码系统的头文件系统路径
  13. zephyr_get_system_include_directories_for_lang_as_string(C system_includes)
  14. # 获取zephyr编译C代码的外部定义
  15. zephyr_get_compile_definitions_for_lang_as_string(C definitions)
  16. # 获取zephyr编译C代码的编译标志
  17. zephyr_get_compile_options_for_lang_as_string(C options)
  18. # 设置编译第三方库时的标志
  19. set(external_project_cflags
  20. "${includes} ${definitions} ${options} ${system_includes}"
  21. )
  22. # 包含外部项目模块
  23. include(ExternalProject)
  24. # 设置需要编译外部库的源码目录
  25. set(mylib_src_dir ${CMAKE_CURRENT_SOURCE_DIR}/mylib)
  26. # 设置需要编译外部库的头文件目录
  27. set(mylib_build_dir ${CMAKE_CURRENT_BINARY_DIR}/mylib)
  28. # 设置生成的库的存放目录
  29. set(MYLIB_LIB_DIR ${mylib_build_dir}/lib)
  30. # 设置库的头文件路径
  31. set(MYLIB_INCLUDE_DIR ${mylib_src_dir}/include)
  32. # 判定camke使用的的生成器,然后设置生成库时采用的生成器一致
  33. if(CMAKE_GENERATOR STREQUAL "Unix Makefiles")
  34. # https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html
  35. set(submake "$(MAKE)")
  36. else() # Obviously no MAKEFLAGS. Let's hope a "make" can be found somewhere.
  37. set(submake "make")
  38. endif()
  39. # 设置生成库时需要的信息
  40. ExternalProject_Add(
  41. mylib_project # 一个自定义的目标
  42. PREFIX ${mylib_build_dir} # 库的根目录
  43. SOURCE_DIR ${mylib_src_dir} # 库的源码目录
  44. BINARY_DIR ${mylib_src_dir} # 库的二进制根目录
  45. CONFIGURE_COMMAND "" # 库的配置命令
  46. BUILD_COMMAND # 库的编译命令
  47. ${submake} # 库使用的生成器
  48. PREFIX=${mylib_build_dir} # 库编译时的根目录
  49. CC=${CMAKE_C_COMPILER} # 库编译时采用的C标志
  50. AR=${CMAKE_AR} # 库连接时采用的C连接标志
  51. CFLAGS=${external_project_cflags} # 库编译时采用的外部标志
  52. INSTALL_COMMAND "" # 库的安装指令
  53. BUILD_BYPRODUCTS ${MYLIB_LIB_DIR}/libmylib.a # 编译之后存放的文件
  54. )
  55. # 创建一个我们的应用程序可以链接的包装器CMake库
  56. add_library(mylib_lib STATIC IMPORTED GLOBAL)
  57. # mylib_lib目标依赖于mylib_project的目标执行
  58. add_dependencies(
  59. mylib_lib
  60. mylib_project
  61. )
  62. # 设置mylib_lib的IMPORTED_LOCATION属性为生成的静态库
  63. set_target_properties(mylib_lib PROPERTIES IMPORTED_LOCATION ${MYLIB_LIB_DIR}/libmylib.a)
  64. # 设置mylib_lib的INTERFACE_INCLUDE_DIRECTORIES属性为头文件路径
  65. set_target_properties(mylib_lib PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${MYLIB_INCLUDE_DIR})
  66. # 连接生成的库到应用程序
  67. target_link_libraries(app PUBLIC mylib_lib)