zephyr/scripts/utils/migrate_posix_kconfigs.py

138 lines
4.2 KiB
Python

"""
Utility script to migrate Zephyr-based projects to normative POSIX Kconfig options.
This script should be used for migrating from versions of Zephyr older than v3.7.0 to Zephyr
version v3.7.0 or later.
Usage::
python $ZEPHYR_BASE/scripts/utils/migrate_posix_kconfigs.py -r root_path
The utility will process c, cpp, h, hpp, rst, conf, CMakeLists.txt,
yml, yaml and Kconfig files.
Copyright (c) 2022 Nordic Semiconductor ASA
Copyright (c) 2024 Tenstorrent AI ULC
SPDX-License-Identifier: Apache-2.0
"""
import argparse
from pathlib import Path
import re
import sys
ZEPHYR_BASE = Path(__file__).parents[2]
FILE_PATTERNS = (
r".+\.c", r".+\.cpp", r".+\.hpp", r".+\.h", r".+\.rst", r".+\.conf",
r".+\.yml", r".+\.yaml", r"CMakeLists.txt", r"Kconfig(\..+)?"
)
REPLACEMENTS = {
"EVENTFD_MAX": "ZVFS_EVENTFD_MAX",
"FNMATCH": "POSIX_C_LIB_EXT",
"GETENTROPY": "POSIX_C_LIB_EXT",
"GETOPT": "POSIX_C_LIB_EXT",
"MAX_PTHREAD_COUNT": "POSIX_THREAD_THREADS_MAX",
"MAX_PTHREAD_KEY_COUNT": "POSIX_THREAD_KEYS_MAX",
"MAX_TIMER_COUNT": "POSIX_TIMER_MAX",
"MSG_COUNT_MAX": "POSIX_MQ_OPEN_MAX",
"POSIX_CLOCK": "POSIX_TIMERS",
"POSIX_CONFSTR": "POSIX_SINGLE_PROCESS",
"POSIX_ENV": "POSIX_SINGLE_PROCESS",
"POSIX_FS": "POSIX_FILE_SYSTEM",
"POSIX_LIMITS_RTSIG_MAX": "POSIX_RTSIG_MAX",
"POSIX_MAX_FDS": "ZVFS_OPEN_MAX",
"POSIX_MAX_OPEN_FILES": "ZVFS_OPEN_MAX",
"POSIX_MQUEUE": "POSIX_MESSAGE_PASSING",
"POSIX_PUTMSG": "XOPEN_STREAMS",
"POSIX_SIGNAL": "POSIX_SIGNALS",
"POSIX_SYSCONF": "POSIX_SINGLE_PROCESS",
"POSIX_SYSLOG": "XSI_SYSTEM_LOGGING",
"POSIX_UNAME": "POSIX_SINGLE_PROCESS",
"PTHREAD": "POSIX_THREADS",
"PTHREAD_BARRIER": "POSIX_BARRIERS",
"PTHREAD_COND": "POSIX_THREADS",
"PTHREAD_IPC": "POSIX_THREADS",
"PTHREAD_KEY": "POSIX_THREADS",
"PTHREAD_MUTEX": "POSIX_THREADS",
"PTHREAD_RWLOCK": "POSIX_READER_WRITER_LOCKS",
"PTHREAD_SPINLOCK": "POSIX_SPIN_LOCKS",
"TIMER": "POSIX_TIMERS",
"TIMER_DELAYTIMER_MAX": "POSIX_DELAYTIMER_MAX",
"SEM_NAMELEN_MAX": "POSIX_SEM_NAME_MAX",
"SEM_VALUE_MAX": "POSIX_SEM_VALUE_MAX",
}
MESSAGES = {
"POSIX_CLOCK":
"POSIX_CLOCK is a one-to-many replacement. If this simple substitution is not "
"sufficient, it's best to try a combination of POSIX_CLOCK_SELECTION, POSIX_CPUTIME, "
"POSIX_MONOTONIC_CLOCK, POSIX_TIMERS, and POSIX_TIMEOUTS.",
"POSIX_MAX_FDS":
"A read-only version of this symbol is POSIX_OPEN_MAX, which is of course, the standard "
"symbol. ZVFS_OPEN_MAX may be set by the user. Consider using POSIX_MAX_FDS if the "
"use-case is read-only.",
}
def process_file(path):
modified = False
output = []
try:
with open(path) as f:
lines = f.readlines()
for line in lines:
longest = ""
length = 0
for m in REPLACEMENTS:
if re.match(".*" + m + ".*", line) and len(m) > length:
length = len(m)
longest = m
if length != 0:
modified = True
line = line.replace(longest, REPLACEMENTS[longest])
msg = MESSAGES.get(longest)
if msg:
print(
f"Notice: {longest} -> {REPLACEMENTS[longest]}: {msg}")
output.append(line)
if modified is False:
return
with open(path, "w") as f:
f.writelines(output)
except UnicodeDecodeError:
print(f"Unable to read lines from {path}", file=sys.stderr)
except Exception as e:
print(f"Failed with exception {e}", e)
def process_tree(project):
for p in project.glob("**/*"):
for fp in FILE_PATTERNS:
cfp = re.compile(".+/" + fp + "$")
if re.match(cfp, str(p)) is not None:
process_file(p)
if __name__ == "__main__":
parser = argparse.ArgumentParser(allow_abbrev=False)
parser.add_argument(
"-r",
"--root",
type=Path,
required=True,
help="Zephyr-based project path")
args = parser.parse_args()
process_tree(args.root)