【无标题】

发布时间:2024年01月23日

BAT脚本获取Keil软件源文件中版本信息

背景:

项目中遇到需要将代码中定义的软件版本号通过Keil编译,生成包含版本信息的可执行文件(.bin、.hex)文件,通常做法利用Keil编译器在编译结束后可调用bat脚本,因此考虑编写可执行脚本。

实现方法:

1 代码中定义版本宏信息

#define SOFTWARE_VERSION  "1.0.1"

在这里插入图片描述

bat脚本从含有版本信息源文件中识别关键字,获取版本字符串,参考资料:KEIL 开发者的福音,这下不用再到处找输出文件了,还能定制文件名,一切都自动搞定!
参考代码:gitee仓库

2、代码中通过ASCII常量数组存储版本信息

const uint8_T SoftVersion[8] = {83, 87, 86, 58, 49, 46, 48, 49};

基于第1中情况,需要在脚本中识别存储版本信息字符串,并获取数组中的内容,再将十进制ASCII码转换为字符,脚本实现如下:

@echo off
@REM AUTHOR: Kunn
@REM VERSION: V1.0.0

setlocal enabledelayedexpansion

@REM 请根据实际情况修改以下变量,注意如果使用相对路径,需要以KEIL的工程文件路径为基准,而非本脚本所在路径

@REM KEIL 设置中的输出文件名(Keil中Output设置)
set EXEC_NAME=Name of Executable
@REM KEIL 设置中的输出文件路径
set OBJ_PATH=.\Objects
@REM 输出文件路径
set OUTPUT_PATH=.\Output
@REM 包含版本字符串文件的路径
set VERSION_FILE_PATH=E:\QAES_CODE\BCU_Kunn\Config\ProjectConfig.c
@REM fromelf.exe 的路径(KEIL安装目录)
set FROMELF_PATH=D:\Keil_v5\ARM\ARMCC\bin
@REM 版本字符串的格式
REM set VERSION_PATTERN="#define SOFTWARE_VERSION"
set VERSION_PATTERN= "const uint8_T SoftwreVersion"

@REM 获取日期【这里的日期格式为 YYYY-MM-HH hh:mm:ss,不同时区或配置下格式可能不同,请自行调整】
set YEAR=%DATE:~2,2%
set MONTH=%DATE:~5,2%
set DAY=%DATE:~8,2%
set HOUR=%TIME:~0,2%
set MINUTE=%TIME:~3,2%
set SECOND=%TIME:~6,2%
set CURRENT_DATE=%YEAR%%MONTH%%DAY%_%HOUR%%MINUTE%%SECOND%
@REM echo "Current date: %CURRENT_DATE%"

set "targetArrayName=SoftwreVersion"
:: 查找包含数组定义的行,并提取数组内容
for /f "usebackq tokens=*" %%a in (`findstr "%targetArrayName%" %VERSION_FILE_PATH%`) do (
    set "arrayDefinition=%%a"
)

:: 从数组定义中提取数组内容
for /f "tokens=2 delims={}" %%b in ("!arrayDefinition!") do (
    set "arrayContent=%%b"
	echo %%b
)
REM pause

:: 使用certutil将十进制数组转换为文本
for %%c in (%arrayContent%) do (
    set /a "char=%%c"
	CALL :CONV_ASCII_TO_CHAR %%c
)

GOTO :END

:CONV_ASCII_TO_CHAR
REM make conversion from ASCII value to character.
REM CHARA_SET: This is a set of characters
SET CHARA_SET= ^^^!^"#$^%%^&'()*+,-./0123456789^:;^^^<=^^^>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^^^_`abcdefghijklmnopqrstuvwxyz{^|}~
REM BASE: Base character ' '(SP), others character ASCII offset calculation will base on it.
SET BASE=0x20

SET /A OFFSET=%1-BASE
IF %OFFSET% GEQ 0 IF %OFFSET% LSS 96 (
    SET "CHAR=!CHARA_SET:~%OFFSET%,1!"
    REM ECHO Converted Character: !CHAR!
	set "result=!result!!CHAR!"
) ELSE (
    GOTO :BUILDWITHERROR
)
GOTO :EOF

:END
:BUILDWITHERROR


:: 输出结果
echo Software Version: %result%


REM REM endlocal
REM pause

REM set output_file_name=%EXEC_NAME%

if not exist %OUTPUT_PATH% mkdir %OUTPUT_PATH%
echo "Clean old files..."
for /f "delims=" %%A in ('dir /b %OUTPUT_PATH%') do del %OUTPUT_PATH%\%%A"

REM set output_file_name=%output_file_name%_V%result%_%CURRENT_DATE%
REM set output_file_name=%output_file_name%-%result%
set output_file_name=%result%

@REM GET BIN
echo "Output bin file: %OUTPUT_PATH%\%output_file_name%.bin"
%FROMELF_PATH%\fromelf --bin %OBJ_PATH%\%EXEC_NAME%.axf --output %OUTPUT_PATH%\%output_file_name%.bin

@REM GET HEX
echo "Output hex file: %OUTPUT_PATH%\%output_file_name%.hex"
copy %OBJ_PATH%\%EXEC_NAME%.hex %OUTPUT_PATH%\%output_file_name%.hex

pause
exit

2.1 实现方法上需要在BAT脚本中实现对ASCII码转字符,常用set /a "chr"的方式,实际运用可能 /a未能正确输出字符:
@echo off
setlocal enabledelayedexpansion

:: ASCII码
set "asciiCode=67"

:: 使用set /a将ASCII码转换为字符
set /a "char=!asciiCode!"

:: 输出结果
echo Converted Character: !char!

endlocal

2.2 定义子函数方式实现,定义CONV_ASCII_TO_CHAR ,通过CALL回调方式完成转换:
:: 使用certutil将十进制数组转换为文本
for %%c in (%arrayContent%) do (
    set /a "char=%%c"
	CALL :CONV_ASCII_TO_CHAR %%c
)

GOTO :END

:CONV_ASCII_TO_CHAR
REM make conversion from ASCII value to character.
REM CHARA_SET: This is a set of characters
SET CHARA_SET= ^^^!^"#$^%%^&'()*+,-./0123456789^:;^^^<=^^^>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^^^^_`abcdefghijklmnopqrstuvwxyz{^|}~
REM BASE: Base character ' '(SP), others character ASCII offset calculation will base on it.
SET BASE=0x20

SET /A OFFSET=%1-BASE
IF %OFFSET% GEQ 0 IF %OFFSET% LSS 96 (
    SET "CHAR=!CHARA_SET:~%OFFSET%,1!"
    REM ECHO Converted Character: !CHAR!
	set "result=!result!!CHAR!"
) ELSE (
    GOTO :BUILDWITHERROR
)
GOTO :EOF

:END
:BUILDWITHERROR

实现关键:ASCII码转字符串类似查表的方式,计算ASCII码到0x20差值,然后在字符串中取响应位置字符。

文章来源:https://blog.csdn.net/weixin_42367960/article/details/135774890
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。