查看原文
其他

项目配置与编译自动化

嵌入式系统 嵌入式系统 2023-06-07

嵌入式设备公司的一个产品线不可能只出一款产品,必定会有各种客制化功能以适应不同场景,在基础版上衍生出多个版本。对软件来说,最佳方案是同一套代码进行不同的配置,编译出适配不同机型的软件,通用bug一处解决则全部机型的都可以修复,当然一旦出事也是一起遭殃。

一套软件适配多个项目,在代码中必然有项目宏,在不同的项目宏下,有不同的功能配置和默认参数。代码实现时尽量使用功能宏,实在无法兼容的则提取项目特有的,单独一个文件实现,每个项目互不影响,要实现编译自动化,还需要脚本配合。

如有甲乙丙3个项目,在ABC 三个标准功能上进行客制化,形式如下:

基线版本={A+B+C}
甲={A1+B1+C1}
乙={A2+B2+C2}
丙={A3+B3+C3}

如果差异很小,在宏文件分别定义甲乙丙3个项目,每个项目下有3个子功能宏表示不同的小功能。

项目=甲/乙/丙三选一
#if 甲
A1+B1+C1
#elif 乙
A2+B2+C2
#elif 丙
A3+B3+C3
#endif

源码是同一套,编译脚本支持传入参数指定项目名,这样执行不同的脚本,编译出不同的项目软件。如果差异很大,单纯的功能宏已经无法区分,假如甲乙丙三个项目分别提取主要差异,在A.c、B.c、C.c中实现客制化的ABC功能,则对编译.c文件路径进行修改,在加编译路径时加项目宏

 SRC+=./xx/xx/{项目名}/A.c
 SRC+=./xx/xx/{项目名}/B.c
 SRC+=./xx/xx/{项目名}/C.c 

每个项目分别实现自身功能,但是在编译时统一文件名,添加编译路径时根据不同的项目,从三个同名文件中选择一个进行编译。

如果项目特殊,比如驱动配置或者非.c编译文件,则可以使用拷贝机制,在进入正式编译前,拷贝该项目对应的文件到指定位置,然后再编译。如甲乙丙有3个端口配置文件夹。

./端口配置 (最终编译的只有这个文件夹)
./端口配置_甲
./端口配置_乙
./端口配置_丙

开始编译前,使用脚本复制对应项目的配置文件夹,如编译丙项目,则将“端口配置_丙”覆盖到“端口配置”,再进行后续编译。

对于简单的参数差异,尽量都合并在同一个.h,不需要脚本,直接编码如下在 .param.h文件

 #if 甲
 #include “param_甲.h”
 #elif 乙
 #include “param_乙.h”
 #elif 丙
 #include “param_丙.h”
 #endif


如果操作再骚点,.c文件也可以使用#include。

实现了项目配置,脚本怎么操作呢?需要结合编译环境,如果是windows,一般使用.bat批处理,如果是linux环境则使用shell脚本,有些特殊的项目编译使用perl脚本。不管是什么环境,最终需要实现的功能都一样。识别输入的项目名参数,用它去匹配不同的脚本动作,进行复制或者设定编译路径。以windows下的bat文件为例,可以参考如下框架。

::编译指令::mk [project] or mk@echo off
:STARTif not "1%~1%"=="1" goto check1::无项目名参数:select_projectECHO.ECHO *******************************************************ECHO 1. project_AECHO 2. project_BECHO 3. project_CECHO *******************************************************set /p userInput=选择项目序号(Q退出): if /i "%userInput%"=="1" goto select_project_Aif /i "%userInput%"=="2" goto select_project_Bif /i "%userInput%"=="3" goto select_project_Cif /i "%userInput%"=="Q" goto ENDecho 你究竟要编译哪个项目?goto :select_project:check1if "1%~2%"=="1" goto check2echo 只能输入一个项目名参数 goto :select_project:check2::echo %~dp0::判断输入的项目名if /i "%1%"=="project_A" goto select_project_Aif /i "%1%"=="project_B" goto select_project_Bif /i "%1%"=="project_C" goto select_project_Cecho 项目名不存在,请重新选择goto select_project:select_project_error_log set mtk_project=HENIT2503D_11C IF EXIST .\build\%mtk_project%\err.log DEL .\build\%mtk_project%\err.log /q findstr /S Error: .\build\%mtk_project%\bootloader.log >>.\build\%mtk_project%\err.log findstr /S Error: .\build\%mtk_project%\bootloader_ext.log >>.\build\%mtk_project%\err.log findstr /S Error: .\build\%mtk_project%\log\*.log >>.\build\%mtk_project%\err.log findstr /S Error: .\build\%mtk_project%\MT6261.log >>.\build\%mtk_project%\err.log ECHO. >> .\build\%mtk_project%\err.log .\build\%mtk_project%\err.log goto end::根据项目配置参数 xxx=xxx表示按实际添加变量:select_project_A set project=A set xxx=aaa goto CompileCopy:select_project_B set project=B set xxx=bbb goto CompileCopy:select_project_C set project=C set xxx=ccc goto CompileCopy
:CompileCopy::按实际需求复制项目客制化文件::自由扩展::编译goto END:paramErrorecho 输入参数错误无法执行 goto END:ENDping -n 1 127.0.0.1>nul::echo mk执行结束
先使用txt记事本编辑,再重命名修改后缀为bat即可双击运行。

编译完成后,将生成的有效的bin文件复制到特定文件夹,这样发布软件就不需逐个复制文件。流程是如此,实际项目中可能是几个方式混合使用,但思路一致,就是让编译器从多个并列项目代码中,选择一份进行编译;一套软件匹配多个项目,减少维护工作量。




您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存