1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
#!/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())
|