application | ||
build | ||
external | ||
hal | ||
middleware | ||
output_files/libs/test_tools | ||
test | ||
tools | ||
utils | ||
.clang-format | ||
.gitignore | ||
CMakeLists.txt | ||
Doxyfile | ||
LICENSE | ||
Makefile | ||
merge.sh | ||
README.md |
1. 一个嵌入式软件架构的示例
1.1. 概述
从嵌入式软件角度来描述软件架构开发方法。
欢迎在仓库里面提issue交流学习。
1.2. 嵌入式软件架构基本要素
pie
title 嵌入式软件开发
"源码构建" : 10
"架构设计" : 30
"代码调试/版本测试" : 10
"代码动态测试" : 20
"代码静态检测" : 5
"代码自动格式化" : 5
"平台适配" : 10
"设计文档" : 5
"工具使用" : 5
本仓库从上述全方面来部署一个嵌入式软件开发项目。各部分环环相扣不分彼此,组成一个完整的健康的敏捷的可持续的嵌入式开发体系。
1.2.1. 源码构建
源码构建是一个嵌入式软件项目的开始,属于嵌入式软件开发的最基础要素,他决定了开发者使用何种方式何种工具来部署 / 编译项目源码。源码构建方案设计会直接影响到开发效率。
源码构建的工具很多,嵌入式开发中常见的有Makefile / CMake / Scons / GN等,例如:国内比较热门的开源项目鸿蒙系统,使用GN作为构建工具。由于历史原因,Makefile是相对古老的源码构建工具,大部分开源项目使用的都是Makefile,随着发展,部分开源项目开始增加使用CMake构建脚本,此时开源项目同时支持Makefile和CMake两种构建方案。构建工具的选择没有好坏之分,大部分后开发的工具都会针对性解决前者的一些缺陷,往往后来者会有更多的优点。本仓库自研部分使用的是CMake工具进行源码构建。
一个CMakeList.txt脚本示例
通俗来讲,CMakeList.txt脚本就是告诉编译器,从哪里搜索头文件 / 把哪些源代码编译 / 从哪里找到哪些链接库 /输出什么文件到哪个目录。
include(${CMAKE_SOURCE_DIR_IPCSDK}/build/global_config.cmake) // 一个配置文件
set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) // 设置可执行文件的输出目录
set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) // 设置库的输出目录
include_directories( // 编译时搜索头文件路径
./src
./include
${UTILS_SOURCE_PATH}/StatusCode/include
${UTILS_SOURCE_PATH}/Log/include
)
#use link_directories when need to link any other library.
#link_directories( // 链接时链接库的搜索路径
#)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
aux_source_directory(./src SRC_FILES) // 设置需要编译的源码文件
set(TARGET_NAME StatusCode)
add_library(${TARGET_NAME} STATIC ${SRC_FILES}) // 生成一个静态库
target_link_libraries(${TARGET_NAME} Log) // 设置前述静态库的库依赖关系
if ("${CLANG_TIDY_SUPPORT}" MATCHES "true") // 静态代码检测
add_custom_target(
StatusCode_code_check
COMMAND ${CLANG_TIDY_EXE}
-checks='${CLANG_TIDY_CHECKS}'
--header-filter=.*
--system-headers=false
${SRC_FILES}
${CLANG_TIDY_CONFIG}
-p ${CMAKE_SOURCE_DIR_IPCSDK}/cmake-shell-linux
WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/StatusCode
)
add_custom_command(
TARGET ${TARGET_NAME}
# TARGET ${ABSTRACT_TARGET}
PRE_BUILD
COMMAND make StatusCode_code_check
WORKING_DIRECTORY ${PROJECT_ROOT_PATH}/cmake-shell-linux/
)
endif()
1.2.1.1. 源码构建当中的工具使用
1.2.1.1.1. 代码静态检测(编码规范)
在编译的时候,使用clang-tidy工具针对性选择对自研部分的代码进行静态检测。 示例:
add_custom_target(
SharedData_code_check
COMMAND ${CLANG_TIDY_EXE}
-checks='${CLANG_TIDY_CHECKS}'
--header-filter=.*
--system-headers=false
${SRC_FILES}
${CLANG_TIDY_CONFIG}
-p ${CMAKE_SOURCE_DIR_IPCSDK}/cmake-shell
WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/SharedData
)
1.2.1.1.2. 代码格式化
在编译的时候,使用clang-format工具针对性选择对自研部分的代码进行自动格式化,实现编码格式的客观绝对统一。 示例:
add_custom_target(
SharedData_code_format
COMMAND ${CLANG_FORMAT_EXE}
-style=file
-i ${SRC_FILES} ${HEADER_FILES}
WORKING_DIRECTORY ${UTILS_SOURCE_PATH}/SharedData
)
1.2.2. 架构设计
抛开产品业务不进行描述,代码部署主要使用分层模块化的代码结构,结合面向对象的多态设计模式进行代码开发,使得业务代码在部署时具备灵活多变的特性,进一步提高代码的复用性,最终实现产品业务软件层面的敏捷迭代。