From 8b77783d62a213c22ba016c70d2eb354a50e5367 Mon Sep 17 00:00:00 2001 From: Chris Osborn Date: Tue, 15 Oct 2024 08:28:55 -0700 Subject: [PATCH] Add debug_version.py to put commit ID into FN_VERSION_FULL during build without altering include/version.h --- .gitignore | 3 + create-platformio-ini.py | 5 +- debug_version.py | 128 +++++++++++++++++++++++++++++++++++++++ include/version.h | 5 ++ 4 files changed, 139 insertions(+), 2 deletions(-) create mode 100755 debug_version.py diff --git a/.gitignore b/.gitignore index bb7d1bb8b..9a0b74671 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ data/webui/device_specific/BUILD_ATARI/fnconfig.ini # ignore any releases downloaded via fujinet_firware_uploader fujinet_releases/* +*~ +*.orig +*.rej diff --git a/create-platformio-ini.py b/create-platformio-ini.py index b0f02b1c7..c473865d7 100644 --- a/create-platformio-ini.py +++ b/create-platformio-ini.py @@ -18,6 +18,7 @@ def create_local_ini(board_name, local_file_name): config.set('fujinet', 'build_board', board_name) with open(local_file_name, 'w') as configfile: config.write(configfile) + configfile.write("[env]\n;build_flags += !python3 debug_version.py\n") print(f"{local_file_name} file created with build_board = {board_name}") def merge_ini_files(base_file, local_file, output_file): @@ -120,7 +121,7 @@ def main(): parser.add_argument("-l", "--local-file", metavar="local_file", help="Use specified local_file instead of platformio.local.ini") parser.add_argument("-o", "--output-file", metavar="output_file", help="write to output_file instead of default platformio-generated.ini") parser.add_argument("-f", "--add-files", metavar="add_files", action="append", help="include additional ini file changes, can be specified multiple times") - + args = parser.parse_args() local_file = "platformio.local.ini" output_file = "platformio-generated.ini" @@ -144,4 +145,4 @@ def main(): print(f"Merged INI file created as '{output_file}'.") if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/debug_version.py b/debug_version.py new file mode 100755 index 000000000..55f4bc7b8 --- /dev/null +++ b/debug_version.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 +# +# Created by FozzTexx + +import argparse +import subprocess +import os, sys +import re +import shlex +from datetime import datetime +from pathlib import Path + +VERSION_H = "include/version.h" +PLATFORMS = "build-platforms" +MACRO_PATTERN = r"^\s*#define\s+(.*?)\s+(.*?)\s*(?://.*|/\*[\s\S]*?\*/)?$" + +def build_argparser(): + parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument("--update_version_h", action="store_true", + help="update include/version.h with current commit information") + return parser + +def run_command(cmd): + return subprocess.check_output(cmd, universal_newlines=True).strip() + +def get_repo_base(): + return run_command(["git", "rev-parse", "--show-toplevel"]) + +def is_fujinet_repo(base): + if os.path.exists(os.path.join(base, VERSION_H)) \ + and os.path.isdir(os.path.join(base, PLATFORMS)): + return True + return False + +def get_commit_version(): + return run_command(["git", "describe", "--always", "HEAD"]) + +def get_modified_files(): + files = run_command(["git", "diff", "--name-only"]).split("\n") + files = [f for f in files if f] + return files + +def load_version_macros(path): + txt = [line for line in open(path)] + macros = {} + for line in txt: + m = re.match(MACRO_PATTERN, line) + if m: + name = m.group(1) + if '(' in name: + continue + value = m.group(2) + if not value: + value = None + macros[name] = value + return macros + +def main(): + base = get_repo_base() + if not is_fujinet_repo(base): + print("Not in FujiNet firmware repo") + return 0 + + args = build_argparser().parse_args() + # FIXME - don't allow update_version_h unless on the actual tag? + + version_h_path = os.path.join(base, VERSION_H) + version = get_commit_version() + modified = get_modified_files() + commit_id_long = run_command(["git", "rev-parse", "HEAD"]) + + mtime = int(run_command(["git", "show", "--no-patch", "--format=%ct", "HEAD"])) + for path in modified: + if os.path.exists(path): + mt = os.path.getmtime(path) + if not mtime or mt > mtime: + mtime = mt + + macros = { + 'FN_VERSION_BUILD': commit_id_long, + } + cur_macros = load_version_macros(version_h_path) + ver_major = int(cur_macros['FN_VERSION_MAJOR']) + ver_minor = int(cur_macros['FN_VERSION_MINOR']) + + m = re.match(r"^v([0-9]+)[.]([0-9]+)[.]([0-9]+)-([0-9]+)-g(.*)", version) + if m: + ver_major = macros['FN_VERSION_MAJOR'] = int(m.group(1)) + ver_minor = macros['FN_VERSION_MINOR'] = int(m.group(2)) + version = f"v{m.group(1)}.{m.group(2)}-{m.group(5)}" + else: + m = re.match(r"^([a-z0-9]{8})$", version) + if m: + version = f"v{ver_major}.{ver_minor}-{version}" + + if modified: + version += "*" + macros['FN_VERSION_FULL'] = version + macros['FN_VERSION_DATE'] = datetime.fromtimestamp(mtime).strftime("%Y-%m-%d %H:%M:%S") + + new_macros = cur_macros.copy() + new_macros.update(macros) + + if new_macros != cur_macros: + for key in macros: + if isinstance(macros[key], str): + macros[key] = f'"{macros[key]}"' + + cur_macros.update(macros) + macro_defs = [] + for key in cur_macros: + value = cur_macros[key] + mdef = f"-D{key}" + if value is not None: + mdef += f"={value}" + macro_defs.append(shlex.quote(mdef)) + + # FIXME - if args.update_version_h then update, don't print + macro_defs = " ".join(macro_defs) + print(macro_defs) + #Path(version_h_path).touch() + + return + +if __name__ == "__main__": + exit(main() or 0) +elif __name__ == "SCons.Script": + print("Running as build script") diff --git a/include/version.h b/include/version.h index e57ce2b91..629257994 100644 --- a/include/version.h +++ b/include/version.h @@ -7,6 +7,9 @@ as needed. */ +#ifndef _VERSION_H +#define _VERSION_H + #define FN_VERSION_MAJOR 1 #define FN_VERSION_MINOR 4 @@ -15,3 +18,5 @@ #define FN_VERSION_DATE "2024-08-07 20:49:13" #define FN_VERSION_FULL "v1.4" + +#endif /* _VERSION_H */