VS 基于git工程编译版本自动添加版本号
目录
概要
实现方案
概要
最近在用visual Studio 开发MFC项目时,需要在release版本编译后的exe文件自动追加版本信息。
由于我们用的git工程管理,即需要基于最新的git 提交来打版本。
比如: MFCApplication_V1.0.2_9.exe
由于git 提交信息是hash 记录,不便于看出不同版本时间先后顺序。这里不使用commit 记录。
换个思路,可用最新的commit count 计数来区分版本。但这个是个纯数字。
如果用tag,可以写成任意样式,是个不错的思路。所以决定采用tag自加方式。
但是如果每笔commit 都打tag,感觉有点滥用tag了。故采用在正式出release版本编译时才让tag自加。
实现方案
获取下一个要打的tag 信息。
下面是一个根据当前tag 生成下一tag的脚本:get_next_tag.bat
REM 配置后可支持中文
chcp 65001
@echo off
::开启后以便让变量即时生效
setlocal enabledelayedexpansion
set OUTPUT_FILE=build_tag_info.txt
:: --------------------------------
:: 获取当前提交的 tag(如果有)
:: 场景:
:: 1.从未打过tag;
:: 2. 当前提交不带tag;
:: 3. 当前提交就带tag 含反复编译情况。
:: :: --------------------------------
for /f "delims=" %%i in ('git tag --points-at HEAD') do (
set COMMIT_TAG=%%i
)
if "!COMMIT_TAG!"=="" (
echo "head has no tag"
) else (
echo "Current has tag, not need to increase"
set NEXT_TAG=%COMMIT_TAG%
REM @pause
goto save_info
)
:: 获取最后一个 tag, 命令用'""' 包含,防止不能识别=
for /f "delims=" %%i in ('"git describe --tags --abbrev=0"') do set LAST_TAG=%%i
:: 去掉前缀V(如果有)
echo LAST_TAG=!LAST_TAG!
if "!LAST_TAG!"=="" (
set MAJOR=1
set MINOR=0
set PATCH=0
) else (
set TAG_CLEAN=%LAST_TAG:V=%
echo "cur tag: !TAG_CLEAN! .need new tag: "
:: 拆分为主版本.次版本.补丁
for /f "tokens=1,2,3 delims=." %%a in ("!TAG_CLEAN!") do (
set MAJOR=%%a
set MINOR=%%b
set PATCH=%%c
)
echo "before PATCH=!PATCH!"
:: 如果 PATCH 为空,则设为 0
if "!MAJOR!"=="" set MAJOR=1
if "!MINOR!"=="" set MINOR=0
if "!PATCH!"=="" set PATCH=0
echo "PATCH=!PATCH!"
:: 补丁号 +1
set /a PATCH+=1
)
echo MAJOR=!MAJOR!
echo MINOR=!MINOR!
echo PATCH=!PATCH!
:: 组合新的 tag
set NEW_TAG=V!MAJOR!.!MINOR!.!PATCH!
:: 打印输出
echo LAST_TAG=%LAST_TAG%
set NEXT_TAG=!NEW_TAG!
:: 提交tag
git tag !NEXT_TAG!
git push origin --tags
:: 输出调试信息
:save_info
echo NEXT_TAG=!NEXT_TAG!
REM echo BUILD_TIME=%BUILD_TIME%
:: 保存到文件, ">"左边不要加空格,避免生成文件含空格
echo !NEXT_TAG!> "%OUTPUT_FILE%"
:: get git count
for /f "delims=" %%i in ('git rev-list --count HEAD') do set GIT_COUNT=%%i
echo GIT_COUNT: !GIT_COUNT!
echo !GIT_COUNT!>> "%OUTPUT_FILE%"
endlocal
copy_files.bat
编译后,自动追加tag信息,并把要拷贝的文件拷贝到output目录下。
REM 配置后可支持中文
chcp 65001
@echo off
setlocal enabledelayedexpansion
set "TargetPath=%~1"
set "ProjectDir=%~2"
set "TargetName=%~3"
set "TargetExt=%~4"
echo "TargetPath=%TargetPath%"
echo "ProjectDir=%ProjectDir%"
echo "TargetName=%TargetName%"
echo "TargetExt=%TargetExt%"
set GIT_RECORD_FILE=%ProjectDir%build_tag_info.txt
set /p BUILD_TAG=<"%GIT_RECORD_FILE%"
echo BUILD_TAG=%BUILD_TAG%
::读取第二行count计数
for /f "usebackq delims=" %%A in ("%GIT_RECORD_FILE%") do (
set /a LINE_NUM+=1
if !LINE_NUM! EQU 2 (
set "SECOND_LINE=%%A"
goto :findCount
)
)
:findCount
SET GIT_COUNT=!SECOND_LINE!
echo "SECOND_LINE: !SECOND_LINE!"
echo "GIT_COUNT=!SECOND_LINE!"
set "NEW_NAME=%TargetName%_!BUILD_TAG!_!SECOND_LINE!%TargetExt%"
::copy 前先删除之前的目标文件,此时不能删除!TargetPath!代表的文件
set TARGET_ABS_PATH=!TargetPath!\..\!NEW_NAME!
echo ".............................Renaming to !TARGET_ABS_PATH!"
for %%f in (!TargetPath!\..\!TargetName!*.exe) do (
REM 检查文件名是否不等于 !TargetName!.exe
if /i not "%%f"=="!TargetPath!\..\!TargetName!.exe" (
echo will delete %%f
del "%%f"
)
)
REM 保存当前路径到环境变量
set PREV_PATH=%CD%
cd ..
if exist .\output\!TargetName!*.exe (del /S /Q output\!TargetName!*.exe) else (md output\ )
echo "...................start copy"
echo TargetPath=!TargetPath!
echo "NEW_NAME=!NEW_NAME!"
::需要重命名,不要使用xcopy
copy !TargetPath! output\!NEW_NAME! /Y
::copy other files to Debug\Release 便于调试
xcopy Config.ini !TargetPath!\.. /D /Y
::copy other files to output
xcopy Config.ini output\ /D /Y
xcopy README.md output\ /D /Y
cd /D %PREV_PATH%
del !GIT_RECORD_FILE!
endlocal
最后在项目属性中——生成事件——生成后事件,为Release版本配置:
call "$(ProjectDir)get_next_tag.bat"
call "$(ProjectDir)copy_files.bat" "$(TargetPath)" $(ProjectDir) "$(TargetName)" $(TargetExt)
大家可根据自己实际情况自行修改。