Trouble with Custom Firmware Naming

Sure, and welcome to the community!

As @maxgerhardt said below, getting something from a header file is sub-optimal. I ended up getting the name from the Git environment. You need to include the following in your platformio.ini file:

build_flags = !python tools\git_rev.py
extra_scripts = pre:python tools\name_firmware.py

This assumes you will create a .\tools directory in your project of course. Create two files in your ./tools directory.

tools\git_rev.py:

import subprocess

# Get Git project name
projcmd = "git rev-parse --show-toplevel"
project = subprocess.check_output(projcmd, shell=True).decode().strip()
project = project.split("/")
project = project[len(project)-1]

# Get 0.0.0 version from latest Git tag
tagcmd = "git describe --tags --abbrev=0"
version = subprocess.check_output(tagcmd, shell=True).decode().strip()

# Get latest commit short from Git
revcmd = "git log --pretty=format:'%h' -n 1"
commit = subprocess.check_output(revcmd, shell=True).decode().strip()

# Get branch name from Git
branchcmd = "git rev-parse --abbrev-ref HEAD"
branch = subprocess.check_output(branchcmd, shell=True).decode().strip()

# Make all available for use in the macros
print("-DPIO_SRC_NAM={0}".format(project))
print("-DPIO_SRC_TAG={0}".format(version))
print("-DPIO_SRC_REV={0}".format(commit))
print("-DPIO_SRC_BRH={0}".format(branch))

This script will run before your code compiles and create defines in your environment for:

  • PIO_SRC_NAM - The name of your project according to Git
  • PIO_SRC_TAG - Your current Git tag
  • PIO_SRC_REV - Your current commit has (short)
  • PIO_SRC_BRH - Yout current Git branch

(Incidentally, these can be used in your code, that’s extra credit I’ll leave to you.)

And tools\name_firmware.py:

import subprocess
Import("env")

my_flags = env.ParseFlags(env['BUILD_FLAGS'])
defines = {k: v for (k, v) in my_flags.get("CPPDEFINES")}

env.Replace(PROGNAME="%s-%s-%s-%s-%s" % (
    defines.get("PIO_SRC_NAM"),
    str(env["BOARD"]),
    defines.get("PIO_SRC_TAG"),
    defines.get("PIO_SRC_REV"),
    defines.get("PIO_SRC_BRH")))

This will give you a firmware name similar to: myproject-d1_mini-1.0.0-5ba5cd3-master.bin where myproject is from PIO_SRC_NAM, d1_mini is from the board definition in your platformio.ini file, 1.0.01 is from PIO_SRC_TAG, 5ba5cd3 is from PIO_SRC_REV, and master is from PIO_SRC_BRH.

From that description, you should be able to handle darned near everything you’d want to do.

If you really want to get something from a header file, this is a sample of the python in the tools\name_firmware.py`:

# Parse out defined shield from Config.h
shields = []
linenum = 0
define = "#define BREWPI_STATIC_CONFIG".lower()
with open (str(env["PROJECTSRC_DIR"]) + '\Config.h', 'rt') as config:
    for line in config:
        linenum += 1
        if line.lower().startswith(define):
            shields.append(line.rstrip('\n'))
for variant in shields:
    shield = variant.split(" ")[-1].split("_")[-1].lower()

In this case shield will contain the define argument from a line like this in src/Config.h:

#define BREWPI_STATIC_CONFIG BREWPI_SHIELD_I2C

The shield = variant.split(" ")[-1].split("_")[-1].lower() logic splits out by the underscores and gives me i2c as the value of shield.