PythonExtra/py/makeversionhdr.py

149 lines
5.0 KiB
Python

"""
Generate header file with macros defining MicroPython version info.
This script works with Python 2.6, 2.7, 3.3 and 3.4.
"""
from __future__ import print_function
import argparse
import sys
import os
import datetime
import subprocess
# The MicroPython repository tags a release commit as "vX.Y.Z", and the commit
# immediately following as "vX.(Y+1).Z-preview".
# This function will return:
# "vX.Y.Z" -- building at the release commit
# "vX.Y.Z-preview" -- building at the first commit in the next cycle
# "vX.Y.Z-preview.N.gHASH" -- building at any subsequent commit in the cycle
# "vX.Y.Z-preview.N.gHASH.dirty" -- building at any subsequent commit in the cycle
# with local changes
def get_version_info_from_git(repo_path):
# Python 2.6 doesn't have check_output, so check for that
try:
subprocess.check_output
subprocess.check_call
except AttributeError:
return None
# Note: git describe doesn't work if no tag is available
try:
git_tag = subprocess.check_output(
["git", "describe", "--tags", "--dirty", "--always", "--match", "v[1-9].*"],
cwd=repo_path,
stderr=subprocess.STDOUT,
universal_newlines=True,
).strip()
# Turn git-describe's output into semver compatible (dot-separated
# identifiers inside the prerelease field).
git_tag = git_tag.split("-", 1)
if len(git_tag) == 1:
return git_tag[0]
else:
return git_tag[0] + "-" + git_tag[1].replace("-", ".")
except subprocess.CalledProcessError:
return None
except OSError:
return None
# When building from a source tarball (or any situation where the git repo
# isn't available), this function will use the info in mpconfig.h as a
# fallback. The release commit sets MICROPY_VERSION_PRERELEASE to 0, and the
# commit immediately following increments MICROPY_VERSION_MINOR and sets
# MICROPY_VERSION_PRERELEASE back to 1.
# This function will return:
# "vX.Y.Z" -- building at the release commit
# "vX.Y.Z-preview" -- building at any other commit
def get_version_info_from_mpconfig(repo_path):
print(
"makeversionhdr.py: Warning: No git repo or tag info available, falling back to mpconfig.h version info.",
file=sys.stderr,
)
with open(os.path.join(repo_path, "py", "mpconfig.h")) as f:
for line in f:
if line.startswith("#define MICROPY_VERSION_MAJOR "):
ver_major = int(line.strip().split()[2])
elif line.startswith("#define MICROPY_VERSION_MINOR "):
ver_minor = int(line.strip().split()[2])
elif line.startswith("#define MICROPY_VERSION_MICRO "):
ver_micro = int(line.strip().split()[2])
elif line.startswith("#define MICROPY_VERSION_PRERELEASE "):
ver_prerelease = int(line.strip().split()[2])
git_tag = "v%d.%d.%d%s" % (
ver_major,
ver_minor,
ver_micro,
"-preview" if ver_prerelease else "",
)
return git_tag
return None
def make_version_header(repo_path, filename):
git_tag = None
if "MICROPY_GIT_TAG" in os.environ:
git_tag = os.environ["MICROPY_GIT_TAG"]
if git_tag is None:
git_tag = get_version_info_from_git(repo_path)
if git_tag is None:
git_tag = get_version_info_from_mpconfig(repo_path)
if not git_tag:
print("makeversionhdr.py: Error: No version information available.")
sys.exit(1)
build_date = datetime.date.today()
if "SOURCE_DATE_EPOCH" in os.environ:
build_date = datetime.datetime.utcfromtimestamp(
int(os.environ["SOURCE_DATE_EPOCH"])
).date()
# Generate the file with the git and version info
file_data = """\
// This file was generated by py/makeversionhdr.py
#define MICROPY_GIT_TAG "%s"
#define MICROPY_BUILD_DATE "%s"
""" % (
git_tag,
build_date.strftime("%Y-%m-%d"),
)
# Check if the file contents changed from last time
write_file = True
if os.path.isfile(filename):
with open(filename, "r") as f:
existing_data = f.read()
if existing_data == file_data:
write_file = False
# Only write the file if we need to
if write_file:
print("GEN %s" % filename)
with open(filename, "w") as f:
f.write(file_data)
def main():
parser = argparse.ArgumentParser()
# makeversionheader.py lives in repo/py, so default repo_path to the
# parent of sys.argv[0]'s directory.
parser.add_argument(
"-r",
"--repo-path",
default=os.path.join(os.path.dirname(sys.argv[0]), ".."),
help="path to MicroPython Git repo to query for version",
)
parser.add_argument("dest", nargs=1, help="output file path")
args = parser.parse_args()
make_version_header(args.repo_path, args.dest[0])
if __name__ == "__main__":
main()