scripts: Dynamically add driver subsystems to subsystems list
This change extends the parse_syscalls.py script to scan for a __subsystem sentinal added to driver api declarations. It thens generates a list that is passed into gen_kobject_list.py to extend the subsystems list. This allows subsystems to be declared in the code instead of a separate python list and provides a mechanism for defining out-of-tree subsystems. Signed-off-by: Corey Wharton <coreyw7@fb.com>
This commit is contained in:
parent
bedd4e01fd
commit
ccd15df510
5 changed files with 90 additions and 33 deletions
|
@ -5,7 +5,7 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
Script to scan Zephyr include directories and emit system call metadata
|
||||
Script to scan Zephyr include directories and emit system call and subsystem metadata
|
||||
|
||||
System calls require a great deal of boilerplate code in order to implement
|
||||
completely. This script is the first step in the build system's process of
|
||||
|
@ -26,7 +26,7 @@ import argparse
|
|||
import os
|
||||
import json
|
||||
|
||||
api_regex = re.compile(r'''
|
||||
syscall_regex = re.compile(r'''
|
||||
__syscall\s+ # __syscall attribute, must be first
|
||||
([^(]+) # type and name of system call (split later)
|
||||
[(] # Function opening parenthesis
|
||||
|
@ -34,9 +34,16 @@ __syscall\s+ # __syscall attribute, must be first
|
|||
[)] # Closing parenthesis
|
||||
''', re.MULTILINE | re.VERBOSE)
|
||||
|
||||
subsys_regex = re.compile(r'''
|
||||
__subsystem\s+ # __subsystem attribute, must be first
|
||||
struct\s+ # struct keyword is next
|
||||
([^{]+) # name of subsystem
|
||||
[{] # Open curly bracket
|
||||
''', re.MULTILINE | re.VERBOSE)
|
||||
|
||||
def analyze_headers(multiple_directories):
|
||||
ret = []
|
||||
syscall_ret = []
|
||||
subsys_ret = []
|
||||
|
||||
for base_path in multiple_directories:
|
||||
for root, dirs, files in os.walk(base_path, topdown=True):
|
||||
|
@ -44,23 +51,41 @@ def analyze_headers(multiple_directories):
|
|||
files.sort()
|
||||
for fn in files:
|
||||
|
||||
# toolchain/common.h has the definition of __syscall which we
|
||||
# toolchain/common.h has the definitions of __syscall and __subsystem which we
|
||||
# don't want to trip over
|
||||
path = os.path.join(root, fn)
|
||||
if not fn.endswith(".h") or path.endswith(os.path.join(os.sep, 'toolchain', 'common.h')):
|
||||
continue
|
||||
|
||||
with open(path, "r", encoding="utf-8") as fp:
|
||||
try:
|
||||
result = [(mo.groups(), fn)
|
||||
for mo in api_regex.finditer(fp.read())]
|
||||
except Exception:
|
||||
sys.stderr.write("While parsing %s\n" % fn)
|
||||
raise
|
||||
contents = fp.read()
|
||||
|
||||
ret.extend(result)
|
||||
try:
|
||||
syscall_result = [(mo.groups(), fn)
|
||||
for mo in syscall_regex.finditer(contents)]
|
||||
subsys_result = [mo.groups()[0].strip()
|
||||
for mo in subsys_regex.finditer(contents)]
|
||||
except Exception:
|
||||
sys.stderr.write("While parsing %s\n" % fn)
|
||||
raise
|
||||
|
||||
return ret
|
||||
syscall_ret.extend(syscall_result)
|
||||
subsys_ret.extend(subsys_result)
|
||||
|
||||
return syscall_ret, subsys_ret
|
||||
|
||||
|
||||
def update_file_if_changed(path, new):
|
||||
if os.path.exists(path):
|
||||
with open(path, 'r') as fp:
|
||||
old = fp.read()
|
||||
|
||||
if new != old:
|
||||
with open(path, 'w') as fp:
|
||||
fp.write(new)
|
||||
else:
|
||||
with open(path, 'w') as fp:
|
||||
fp.write(new)
|
||||
|
||||
|
||||
def parse_args():
|
||||
|
@ -76,34 +101,33 @@ def parse_args():
|
|||
parser.add_argument(
|
||||
"-j", "--json-file", required=True,
|
||||
help="Write system call prototype information as json to file")
|
||||
parser.add_argument(
|
||||
"-s", "--subsystem-file", required=True,
|
||||
help="Write subsystem name information as json to file")
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
def main():
|
||||
parse_args()
|
||||
|
||||
syscalls = analyze_headers(args.include)
|
||||
syscalls, subsys = analyze_headers(args.include)
|
||||
|
||||
# Only write json files if they don't exist or have changes since
|
||||
# they will force and incremental rebuild.
|
||||
|
||||
syscalls_in_json = json.dumps(
|
||||
syscalls,
|
||||
indent=4,
|
||||
sort_keys=True
|
||||
)
|
||||
update_file_if_changed(args.json_file, syscalls_in_json)
|
||||
|
||||
# Check if the file already exists, and if there are no changes,
|
||||
# don't touch it since that will force an incremental rebuild
|
||||
path = args.json_file
|
||||
new = syscalls_in_json
|
||||
if os.path.exists(path):
|
||||
with open(path, 'r') as fp:
|
||||
old = fp.read()
|
||||
|
||||
if new != old:
|
||||
with open(path, 'w') as fp:
|
||||
fp.write(new)
|
||||
else:
|
||||
with open(path, 'w') as fp:
|
||||
fp.write(new)
|
||||
subsys_in_json = json.dumps(
|
||||
subsys,
|
||||
indent=4,
|
||||
sort_keys=True
|
||||
)
|
||||
update_file_if_changed(args.subsystem_file, subsys_in_json)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue