| """ |
| 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) |