uhd/host/utils/update_fbs.py
Martin Braun 0d273bfe0c tests: fbs test: Fix issues around missing git
- update_fbs.py would use git directly, instead of the requested git
  executable
- There are other corner cases for the git executable detection, which
  are now all captured under a more general exception type

Credit to Christopher Friedt for pointing out the original issue.
2020-08-25 07:10:53 -05:00

158 lines
5.1 KiB
Python
Executable file

#!/usr/bin/env python3
#
# Copyright 2020 Ettus Research, a National Instruments Brand
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
"""
Utility to update the .fbs files in UHD, or to verify them.
"""
import os
import glob
import argparse
import pathlib
import re
import shutil
import subprocess
import sys
CAL_SUBDIR = ('include', 'uhd', 'cal')
def find_executable(name, hint=None):
"""
Find an executable file. See documentation of which
for platform depended behaviour.
"""
result = shutil.which(name, path=hint)
print("Found {} executable: {}".format(name, result))
return result
def find_uhd_source_path(hint=None):
"""
Find UHD path
"""
if hint:
cal_subdir = os.path.join(hint, *CAL_SUBDIR)
if os.path.isdir(cal_subdir):
return hint
hint = os.path.join(hint, 'host')
if os.path.isdir(cal_subdir):
return hint
raise RuntimeError(
"Invalid UHD source path: {} (does not have subdir: {})"
.format(hint, os.path.join(*CAL_SUBDIR)))
# If there's no hint, we try our own path as a hint:
return find_uhd_source_path(str(pathlib.Path(__file__).parent.absolute().parent))
def parse_args():
""" Parse args and return args object """
parser = argparse.ArgumentParser(
description="Update or verify FlatBuffer files in UHD",
)
parser.add_argument(
'--flatc-path',
help="Path to flatc executable. Will attempt to find the executable if "
"not provided.")
parser.add_argument(
'--git-path',
help="Path to git executable. Will attempt to find the executable if "
"not provided.")
parser.add_argument(
'--uhd-path',
help="Path to UHD repository. Will use the repository this file is in "
"if not provided.")
parser.add_argument(
"-V", "--verify", action='store_true',
help="If set, will only check if the files are up-to-date, and return "
"non-zero if they are not.")
return parser.parse_args()
def get_schema_files(uhd_path=None):
"""
Returns a list of flatbuffers schema files (using glob) in uhd_path
"""
try:
cal_path = os.path.join(find_uhd_source_path(uhd_path), *CAL_SUBDIR)
cal_path = os.path.abspath(cal_path)
except RuntimeError as ex:
print("ERROR: {}".format(str(ex)))
return False
print("Checking UHD cal data in: {}".format(cal_path))
os.chdir(cal_path)
return glob.glob("*.fbs")
def get_hash(git_exe, file):
"""
return the latest git hash of file. Returns None if git does not return 0.
"""
try:
# git command to extract the hash of the last commit
git_cmd = (git_exe, "log", "-1", "--oneline", "--pretty='%h'")
result = subprocess.check_output(git_cmd + (file,), stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as error:
print("Failed to read hash from {} ({})".format(file, error.output))
result = None
return result
def verify(git_exe, uhd_path=None):
"""
Make sure that the .fbs files are all up to date w.r.t. their generated
files. Because the content of the generated headers differ between the
versions of flatbuffers we cannot compare generated files with files
in repo.
Instead the git hashes of the schema and the generated headers files
are compared. This will detect changes to the .fbs that are not
accompanied by a change of the header. It also detects manual
changes to the generated header files.
"""
if not git_exe:
print("Cannot verify schema files (no git found), assuming pass")
return True
try:
subprocess.check_output((git_exe, "status"), stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
print("Cannot verify schema files (not a git repo), assuming pass")
return True
try:
result = True
for file in get_schema_files(uhd_path):
print(file, end="...")
fbs_hash = get_hash(git_exe, file)
hpp_hash = get_hash(git_exe,
re.sub(r'\.fbs$', '_generated.h', file))
if fbs_hash and hpp_hash:
# we have a valid hash for both files
if fbs_hash == hpp_hash:
print("OK")
else:
print("ERROR git hashes of schema {} and header {} differ."
.format(fbs_hash, hpp_hash))
result = False
return result
except BaseException as ex:
print("ERROR: " + str(ex))
return False
def generate(flatc_exe, uhd_path=None):
"""
Generate header files from schema
"""
files = get_schema_files(uhd_path)
subprocess.check_call([flatc_exe, '--cpp'] + files)
return True
def main():
""" Go, go, go! """
args = parse_args()
if args.verify:
git_exe = find_executable("git", hint=args.git_path)
return verify(git_exe, uhd_path=args.uhd_path)
flatc_exe = find_executable("flatc", hint=args.flatc_path)
return generate(flatc_exe, uhd_path=args.uhd_path)
if __name__ == "__main__":
sys.exit(not main())