Skip to content

Commit

Permalink
pio: add build-and-copy, more configuration options for version
Browse files Browse the repository at this point in the history
Multiple ways to specify version string through environment variables:
- `ESPURNA_BUILD_FULL_VERSION` to set full version string
By default it is empty, and the version is combined using the values specified below
- `ESPURNA_BUILD_VERSION` to modify the first part of the version string (1.15.0-dev)
By default, uses espurna/config/version.h APP_VERSION value
- `ESPURNA_BUILD_REVISION` to specify revision part of the version string
For example 12345678, which is expanded as either .git12345678 or -git12345678
(depending on whether the version string contains hyphen)
By default, use git to retrieve the first 8 characters of the current HEAD SHA value
- `ESPURNA_BUILD_VERSION_SUFFIX` to specify build metadata part of the string
For example nightly20210607, which is added to the full version as 1.15.0-dev+nightly20210607
Empty by defauld

Adds -t build-and-copy which uses the values above to copy firmware.bin, configurable with:
- `ESPURNA_BUILD_NAME` to set the suffix of the filename.
By default, uses the $PIOENV (aka the string after the env: in the .ini file)
- `ESPURNA_BUILD_DESTINATION` to specify where to copy the .bin files
By default, uses $PROJECT_DIR

Resulting file is stored at:
${ESPURNA_BUILD_DESTINATION}/${ESPURNA_BUILD_FULL_VERSION}/espurna-${ESPURNA_BUILD_FULL_VERSION}-${ESPURNA_BUILD_NAME}.bin

In addition, modify generate_release_sh.py to use the new environment variables.
  • Loading branch information
mcspr committed Jun 7, 2021
1 parent c945c23 commit 4c33cac
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 124 deletions.
14 changes: 14 additions & 0 deletions code/espurna/config/version.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,22 @@

#pragma once

#ifndef APP_NAME
#define APP_NAME "ESPURNA"
#endif

#ifndef APP_VERSION
#define APP_VERSION "1.15.0-dev"
#endif

#ifndef APP_AUTHOR
#define APP_AUTHOR "xose.perez@gmail.com"
#endif

#ifndef APP_WEBSITE
#define APP_WEBSITE "http://tinkerman.cat"
#endif

#ifndef CFG_VERSION
#define CFG_VERSION 6
#endif
9 changes: 1 addition & 8 deletions code/espurna/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,7 @@ const String& getCoreRevision() {
}

const char* getVersion() {
static const char version[] {
#if defined(APP_REVISION)
APP_VERSION APP_REVISION
#else
APP_VERSION
#endif
};

static const char version[] = APP_VERSION;
return version;
}

Expand Down
21 changes: 12 additions & 9 deletions code/scripts/espurna_utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
#
# ldscripts, lwip patching, updated postmortem flags and git support
# Copyright (C) 2019 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
# Copyright (C) 2019-2021 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand All @@ -19,21 +19,24 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from .build import firmware_destination, app_add_target_build_and_copy
from .checks import check_cppcheck, check_printsize
from .flags import app_inject_flags
from .float_support import remove_float_support
from .ldscripts import ldscripts_inject_libpath
from .postmortem import dummy_ets_printf
from .git import app_inject_revision
from .release import copy_release
from .flags import app_inject_flags
from .version import app_inject_version, app_full_version_for_env

__all__ = [
"app_add_target_build_and_copy",
"app_full_version_for_env",
"app_inject_flags",
"app_inject_version",
"app_version",
"check_cppcheck",
"check_printsize",
"remove_float_support",
"ldscripts_inject_libpath",
"dummy_ets_printf",
"app_inject_revision",
"app_inject_flags",
"copy_release",
"firmware_destination",
"ldscripts_inject_libpath",
"remove_float_support",
]
64 changes: 64 additions & 0 deletions code/scripts/espurna_utils/build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import atexit
import os
import shutil
import tempfile
import functools

from .display import print_warning
from .version import app_full_version_for_env


def try_remove(path):
try:
os.remove(path)
except: # pylint: disable=bare-except
print_warning("Please manually remove the file `{}`".format(path))


# emulate .ino concatenation to speed up compilation times
def merge_cpp(sources, output):
with tempfile.TemporaryFile() as tmp:
tmp.write(b"// !!! Automatically generated file; DO NOT EDIT !!! \n")
tmp.write(b'#include "espurna.h"\n')
for source in sources:
src_include = '#include "{}"\n'.format(source)
tmp.write(src_include.encode("utf-8"))

tmp.seek(0)

with open(output, "wb") as fobj:
shutil.copyfileobj(tmp, fobj)
atexit.register(try_remove, output)


def firmware_prefix(env):
return "espurna-{}".format(app_full_version_for_env(env))


# generate an common name for the current build
def firmware_filename(env):
suffix = "{}.bin".format(env["ESPURNA_BUILD_NAME"] or env["PIOENV"])
return "-".join([firmware_prefix(env), suffix])


def firmware_destination(env):
destdir = env["ESPURNA_BUILD_DESTINATION"] or env["PROJECT_DIR"]
subdir = os.path.join(destdir, firmware_prefix(env))

return os.path.join(subdir, firmware_filename(env))


def app_add_target_build_and_copy(env):
from SCons.Script import Copy

copy_dest = firmware_destination(env)
copy = env.Command(
copy_dest, "${BUILD_DIR}/${PROGNAME}.bin", Copy("$TARGET", "$SOURCE")
)
env.AddTarget(
"build-and-copy",
copy_dest,
actions=None, # command invocation already handles this
title="Build firmware.bin and store a copy",
description="Build and store firmware.bin as $ESPURNA_BUILD_DESTINATION/espurna-<version>-$ESPURNA_BUILD_NAME.bin (default destination is $PROJECT_DIR)",
)
24 changes: 0 additions & 24 deletions code/scripts/espurna_utils/git.py

This file was deleted.

49 changes: 0 additions & 49 deletions code/scripts/espurna_utils/release.py

This file was deleted.

89 changes: 89 additions & 0 deletions code/scripts/espurna_utils/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import os
import functools
import subprocess

from .display import print_warning


try:
cached = functools.cache
except AttributeError:
cached = functools.lru_cache(None)


@cached
def app_revision():
def git(*args):
cmd = ["git"]
cmd.extend(args)
proc = subprocess.Popen(
cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True
)
return proc.stdout.readlines()[0].strip()

revision = None
try:
revision = git("rev-parse", "--short=8", "HEAD")
except subprocess.CalledProcessError:
pass
except FileNotFoundError:
pass

return revision


@cached
def app_version(version_h):
version = None
with open(version_h, "r") as f:
for line in f:
if "define" in line and "APP_VERSION" in line:
version = line.split(" ")[-1]
version = version.strip().replace('"', "")
break

return version


def app_version_for_env(env):
return env.get("ESPURNA_BUILD_VERSION") or app_version(
os.path.join(env.get("PROJECT_DIR"), "espurna/config/version.h")
)


def app_revision_for_env(env):
return env.get("ESPURNA_BUILD_REVISION") or app_revision()


def app_suffix_for_env(env):
return env.get("ESPURNA_BUILD_VERSION_SUFFIX", "")


def app_combined_version(env):
version = app_version_for_env(env)
if not version:
raise ValueError("Version string cannot be empty")

revision = app_revision_for_env(env)
if revision:
# handle both 1.2.3-dev.git... and 1.2.3-git...
# and avoid 1.2.3.git... that cannot be parsed by the semantic_version module
middle = ".git" if "-" in version else "-git"
version = middle.join([version, revision])

suffix = app_suffix_for_env(env)
if suffix:
version = "+".join([version, suffix])

return version


def app_full_version_for_env(env):
return env.get("ESPURNA_BUILD_FULL_VERSION") or app_combined_version(env)


def app_inject_version(env):
def inject_string(env, flag, value):
env.Append(CPPDEFINES=[(flag, '\\"{}\\"'.format(value))])

inject_string(env, "APP_VERSION", app_full_version_for_env(env))
Loading

0 comments on commit 4c33cac

Please sign in to comment.