【问题标题】:Auto increment build number using PlatformIO使用 PlatformIO 自动增加内部版本号
【发布时间】:2019-07-07 16:09:56
【问题描述】:

我有几个用于家庭自动化的微控制器项目。我的每个节点都有一个在代码中手动设置的版本号。这个版本号是在节点启动的时候报告的,用来通知我运行的是哪个代码。

在对代码进行一些更改后,有时会忘记更改版本号。所以必须找到一个自动的解决方案。

我对解决方案有一些想法:

  1. 创建文件(version.h):#define BUILDNO xxx
  2. 将其包含在相关的 c 代码中
  3. 每次构建前自动增加 xxx

可以实现吗?或者有没有其他类似结果的解决方案?

【问题讨论】:

  • 请帮帮我!这个问题有什么问题?很多反对票..
  • 这似乎是一个好问题,恕我直言。至少它向人们介绍了 PlatformIO 的自定义脚本。 (至少对我有用!)

标签: build arduino microcontroller platformio


【解决方案1】:

我根据我的问题的答案进行了一些研究。 PlatformIO 可以在编译前运行自定义脚本。以下是生成内部版本号并将其包含到项目代码中的过程:

  1. 在项目文件夹中创建 Python 脚本:buildscript_versioning.py
FILENAME_BUILDNO = 'versioning'
FILENAME_VERSION_H = 'include/version.h'
version = 'v0.1.'

import datetime

build_no = 0
try:
    with open(FILENAME_BUILDNO) as f:
        build_no = int(f.readline()) + 1
except:
    print('Starting build number from 1..')
    build_no = 1
with open(FILENAME_BUILDNO, 'w+') as f:
    f.write(str(build_no))
    print('Build number: {}'.format(build_no))

hf = """
#ifndef BUILD_NUMBER
  #define BUILD_NUMBER "{}"
#endif
#ifndef VERSION
  #define VERSION "{} - {}"
#endif
#ifndef VERSION_SHORT
  #define VERSION_SHORT "{}"
#endif
""".format(build_no, version+str(build_no), datetime.datetime.now(), version+str(build_no))
with open(FILENAME_VERSION_H, 'w+') as f:
    f.write(hf)
  1. platformio.ini 中添加一行:
    extra_scripts = 
        pre:buildscript_versioning.py

构建您的项目将运行该脚本。将创建 2 个文件:

  • 版本控制:一个简单的文本文件,用于存储最后的内部版本号

  • include/version.h:要包含的头文件

现在您可以将此行添加到您的 C 代码中:

#include <version.h>

我在这里创建了一个带有一些文档的 gitlab 存储库:https://gitlab.com/pvojnisek/buildnumber-for-platformio/tree/master 欢迎提供更多想法!

【讨论】:

  • 根据platformio docs,如果脚本应该在构建之前执行,则需要在脚本名称前加上“pre:”,否则默认为“post:”如果没有字首。示例:extra_scripts = \n pre:pre_extra_script.py \n post:post_extra_script1.py \n
  • 抱歉代码格式错误,我看不到如何在评论中格式化多行代码。您是否还找到了一种方法来(重新)相应地命名文件,以便在文件名中使用正确的版本号上传文件?即firmware_0.1.2.bin
  • @EthanArnold 感谢您的评论! pre 和 post 前缀很有用。我认为 pre: 在这种情况下是最好的解决方案。我也会更新答案和 gitlab 项目。
  • @EthanArnold 您是否设法重命名了 bin 文件?它可以在 python 脚本中轻松完成。只需使用以下几行:import osos.rename(firmware.bin,f'firmware_{VERSION}.bin')
  • 虽然这绝对可行,但使用字符数组而不是预处理器定义可能会更好。如果预处理器定义发生变化,PIO 必须重新编译编译单元中的所有文件(所有库等)。使用字符数组允许 PIO 仅重新编译包含 version.h 文件的项目源文件。 ?
【解决方案2】:

我用git describe 和PlatformIO 的advanced scripting 解决了这个问题。

首先,我使用它的项目严重依赖 git 标签进行版本控制。在我看来,在多个地方手动跟踪版本号是一件很痛苦的事情,应该都是基于 git 标签。这使得 CI 等变得非常简单,因为我永远不会忘记在某个文件中更新版本,它只需要引用 git 标签(github/gitlab 上的正则表达式保护标签也有帮助)。

使用git describe,我们可以将提交描述注入到PIO构建中。

这是一个例子:

platformio.ini

[env:my_env]
platform = teensy
board = teensy40
framework = arduino
extra_scripts = 
    pre:auto_firmware_version.py

auto_firmware_version.py

import subprocess

Import("env")

def get_firmware_specifier_build_flag():    
    ret = subprocess.run(["git", "describe"], stdout=subprocess.PIPE, text=True) #Uses only annotated tags
    #ret = subprocess.run(["git", "describe", "--tags"], stdout=subprocess.PIPE, text=True) #Uses any tags
    build_version = ret.stdout.strip()
    build_flag = "-D AUTO_VERSION=\\\"" + build_version + "\\\""
    print ("Firmware Revision: " + build_version)
    return (build_flag)

env.Append(
    BUILD_FLAGS=[get_firmware_specifier_build_flag()]
)

main.cpp

#include <Arduino.h>

void setup(){
    serial.begin(115200);
    serial.print("Firmware Version: ");
    serial.println(AUTO_VERSION);   // Use the preprocessor directive

   // OR //

   char firmware_char_array[] = AUTO_VERSION;
   serial.println(firmware_char_array, sizeof(firmware_char_array));
}

void loop(){
    // Loop
}

使用此配置,您可以将固件版本作为字符串文字获取。你可以随心所欲地使用它,因为它是在预处理器而不是编译器中处理的。


例如,这将打印提交与之对齐的标签:

v1.2.3

或者,如果提交时没有标签,则与最新标签的关系:

v1.2.3-13-gabc1234
└────┤ └┤  └─────┴─ Short commit Hash (not the g)
     │  └─ Distance from tag
     └─ Latest Tag in Git

您可以在 python 脚本中随意自定义此字符串,例如:

build_version = "My_Project_Firmware-" + ret.stdout.strip() + "-" + env['PIOENV'].upper()

会产生:

My_Project_Firmware-v1.2.3-13-gabc1234-MY_ENV

我使用env['PIOENV'] 来区分不同的构建环境,如果您有常规构建和调试构建,这很有用。


大部分是platformIO论坛帖子的副本:

https://community.platformio.org/t/how-to-build-got-revision-into-binary-for-version-output/15380/5?u=awbmilne

【讨论】:

  • 感谢您的描述。我认为这个解决方案可以在大多数情况下使用。
  • 希望 ? Python 脚本可用于创建几乎任何所需的字符串。您甚至可以只使用时间戳作为递增值。这么多选择!
【解决方案3】:

在使用 C 或 C++ (Arduino) 时,您必须依赖预构建程序。您必须添加一个预构建程序,该程序使用简单的更新文件:

#define VERSION "1.0.0"

您的自动增量程序需要将当前版本存储在某处(最好在version.h 中,这样它就不会不同步)并在编译时读取、增量和存储它。

您可以使用来自vurdalakov 的解决方案,或cplusadd.blogspot.com 上使用Makefiles 的解决方案。

【讨论】:

  • 感谢您对这个问题的贡献。这非常有用。它给了我一些从哪里开始的想法。由于 PlatformIO 是多平台的,我将链接代码迁移到 Python,它可以在平台上完美运行。我在下面发布了最终解决方案。
【解决方案4】:

对于我的用例,我确实 NOT 一定需要一个总是加一的增量数字,但是任何类型的升序数字都可以,因此使用 timeticks 是对我来说很好。

在你的 platformio.ini 中:

[common]
firmware_version = '"0.1.0+${UNIX_TIME}"'

[env:release]
build_flags =
    -D FIRMWARE_VERSION=${common.firmware_version}

这将为您提供以下格式的宏定义:

#define FIRMWARE_VERSION "0.1.0+1615469592"

【讨论】:

    【解决方案5】:

    我喜欢你解决问题的方法。但是基于源代码的版本号不是更有用吗? PlatformIO 有一个关于动态构建变量的部分,其中有一个从 git 源版本中提取哈希的示例 https://docs.platformio.org/en/latest/projectconf/section_env_build.html#id4(向下滚动到动态构建变量部分)

    【讨论】:

    • 感谢您的建议。我很喜欢。这里的目标是生成一个增量 ID。它与日期一起是独一无二的。 HEAD 的 id 是另一回事。这取决于当前的分支。如果您在开发期间更改分支,则必须手动设置它(我个人为每个错误和功能打开单独的分支)。其他解决方案可能是使用$UNIX_TIME 标志。
    猜你喜欢
    • 1970-01-01
    • 2011-08-21
    • 2011-03-06
    • 1970-01-01
    • 2010-11-27
    • 1970-01-01
    • 2016-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多