Files
GenerateMcuProgramVersion/McuVersionGen.py
2025-05-06 21:36:49 +08:00

155 lines
6.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import re
import subprocess
import os
import sys
import datetime
import io
import locale
system_encoding = locale.getpreferredencoding(False)
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding=system_encoding)
# 语义化版本 https://semver.org/lang/zh-CN/spec/v2.0.0.html
default_major_version = 0 # 主版本号
defalut_minor_version = 1 # 次版本号
defalut_revision_version = 0 # 修订版本号
defalut_pre_release_version = "" # 预发行版本号
def get_version_from_file(path):
"""从项目根目录的version.txt文件中读取版本信息"""
version_file = os.path.join(path, "version.txt")
# 默认版本号
versions = {
"major_version": default_major_version,
"minor_version": defalut_minor_version,
"revision_version": defalut_revision_version,
"pre_release_version": defalut_pre_release_version
}
# 检查文件是否存在
if not os.path.exists(version_file):
# 创建默认version.txt文件
try:
with open(version_file, 'w', encoding='utf-8') as f:
f.write(f"major_version={versions['major_version']}\n")
f.write(f"minor_version={versions['minor_version']}\n")
f.write(f"revision_version={versions['revision_version']}\n")
f.write(
f"pre_release_version={versions['pre_release_version']}\n")
print(f"已在项目根目录创建默认的version.txt文件")
except Exception as e:
print(f"创建version.txt文件失败: {str(e)}")
return versions
# 读取version.txt文件
try:
with open(version_file, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if '=' in line:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip()
if key in versions:
# 处理整数类型的版本号
if key != "pre_release_version":
try:
versions[key] = int(value)
except ValueError:
raise ValueError(
f"版本号解析错误: {key}必须是整数,当前值为'{value}'")
else:
versions[key] = value
except Exception as e:
raise Exception(f"解析version.txt文件失败: {str(e)}")
return versions
def generate_version_file(name, path, file_version, file_build_time):
if not os.path.exists(f"{path}/Core/App/AutoGen/"):
os.makedirs(f"{path}/Core/App/AutoGen/", exist_ok=True)
with open(f"{path}/Core/App/AutoGen/autogen_version.c", "w", encoding="utf-8") as f:
f.write("// 这个文件是自动生成的\n")
f.write("// 对它作任何修改都将在编译前由程序自动覆盖\n")
f.write("// 不需要修改这个文件的内容\n")
f.write("\n")
f.write(f'const char *g_name = "{name}";\n')
f.write(f'const char *g_version = "{file_version}";\n')
f.write(f'const char *g_buildTime = "{file_build_time}";\n')
def generate_version(path):
# 从version.txt获取版本信息
try:
versions = get_version_from_file(path)
major_version = versions["major_version"]
minor_version = versions["minor_version"]
revision_version = versions["revision_version"]
pre_release_version = versions["pre_release_version"]
except Exception as e:
print(f"错误: {str(e)}")
sys.exit(-1)
generated_version = f"{major_version}.{minor_version}.{revision_version}"
git_commit_id = ""
# 检查是否在Git仓库中
git_process = subprocess.run(
["git", "rev-parse"], capture_output=True, text=True, cwd=path)
if git_process.returncode == 0:
# 检查是否有未提交的更改
commit_process = subprocess.run(
["git", "status", "-s"], capture_output=True, text=True, cwd=path)
if commit_process.stdout != "":
# 有未提交的更改获取当前commit id并加*
process = subprocess.run(
["git", "rev-parse", "--short", "HEAD"], capture_output=True, text=True, cwd=path)
git_commit_id = process.stdout.strip() + "*"
else:
# 没有未提交的更改直接获取当前commit id
process = subprocess.run(["git", "rev-parse", "--short=8", "HEAD"], capture_output=True, text=True,
cwd=path)
git_commit_id = process.stdout.strip()
# 根据 pre_release_version 和 git_commit_id 更新版本号
if pre_release_version and git_commit_id:
generated_version += f"-{pre_release_version}+{git_commit_id}"
elif pre_release_version:
generated_version += f"-{pre_release_version}"
elif git_commit_id:
generated_version += f"+{git_commit_id}"
# https://regex101.com/r/Ly7O1x/3/
semver_regex = (
r"^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*["
r"a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>["
r"0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*|\*|.*\*))?$")
if not re.match(semver_regex, generated_version):
print(f"生成的版本号 {generated_version} 不符合语义化版本规范")
return generated_version
if __name__ == "__main__":
try:
name = sys.argv[1] if len(sys.argv) > 1 else 'McuProgram'
project_directory = sys.argv[2] if len(sys.argv) > 2 else '.'
if not os.path.isdir(project_directory):
raise Exception("Invalid project directory")
version = generate_version(project_directory)
build_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
generate_version_file(
name, project_directory, version, build_time)
print(f"Program name: {name}")
print(f"Version: {version}")
print(f"Build time: {build_time}")
sys.exit(0)
except Exception as e:
print(e)
sys.exit(-1)