1""" 2Utility script to migrate Zephyr-based projects to normative POSIX Kconfig options. 3 4This script should be used for migrating from versions of Zephyr older than v3.7.0 to Zephyr 5version v3.7.0 or later. 6 7Usage:: 8 9 python $ZEPHYR_BASE/scripts/utils/migrate_posix_kconfigs.py -r root_path 10 11The utility will process c, cpp, h, hpp, rst, conf, CMakeLists.txt, 12yml, yaml and Kconfig files. 13 14 15Copyright (c) 2022 Nordic Semiconductor ASA 16Copyright (c) 2024 Tenstorrent AI ULC 17SPDX-License-Identifier: Apache-2.0 18""" 19 20import argparse 21import re 22import sys 23from pathlib import Path 24 25ZEPHYR_BASE = Path(__file__).parents[2] 26 27FILE_PATTERNS = ( 28 r".+\.c", r".+\.cpp", r".+\.hpp", r".+\.h", r".+\.rst", r".+\.conf", 29 r".+\.yml", r".+\.yaml", r"CMakeLists.txt", r"Kconfig(\..+)?" 30) 31 32REPLACEMENTS = { 33 "EVENTFD_MAX": "ZVFS_EVENTFD_MAX", 34 "FNMATCH": "POSIX_C_LIB_EXT", 35 "GETENTROPY": "POSIX_C_LIB_EXT", 36 "GETOPT": "POSIX_C_LIB_EXT", 37 "MAX_PTHREAD_COUNT": "POSIX_THREAD_THREADS_MAX", 38 "MAX_PTHREAD_KEY_COUNT": "POSIX_THREAD_KEYS_MAX", 39 "MAX_TIMER_COUNT": "POSIX_TIMER_MAX", 40 "MSG_COUNT_MAX": "POSIX_MQ_OPEN_MAX", 41 "POSIX_CLOCK": "POSIX_TIMERS", 42 "POSIX_CONFSTR": "POSIX_SINGLE_PROCESS", 43 "POSIX_ENV": "POSIX_SINGLE_PROCESS", 44 "POSIX_FS": "POSIX_FILE_SYSTEM", 45 "POSIX_LIMITS_RTSIG_MAX": "POSIX_RTSIG_MAX", 46 "POSIX_MAX_FDS": "ZVFS_OPEN_MAX", 47 "POSIX_MAX_OPEN_FILES": "ZVFS_OPEN_MAX", 48 "POSIX_MQUEUE": "POSIX_MESSAGE_PASSING", 49 "POSIX_PUTMSG": "XOPEN_STREAMS", 50 "POSIX_SIGNAL": "POSIX_SIGNALS", 51 "POSIX_SYSCONF": "POSIX_SINGLE_PROCESS", 52 "POSIX_SYSLOG": "XSI_SYSTEM_LOGGING", 53 "POSIX_UNAME": "POSIX_SINGLE_PROCESS", 54 "PTHREAD": "POSIX_THREADS", 55 "PTHREAD_BARRIER": "POSIX_BARRIERS", 56 "PTHREAD_COND": "POSIX_THREADS", 57 "PTHREAD_IPC": "POSIX_THREADS", 58 "PTHREAD_KEY": "POSIX_THREADS", 59 "PTHREAD_MUTEX": "POSIX_THREADS", 60 "PTHREAD_RWLOCK": "POSIX_READER_WRITER_LOCKS", 61 "PTHREAD_SPINLOCK": "POSIX_SPIN_LOCKS", 62 "TIMER": "POSIX_TIMERS", 63 "TIMER_DELAYTIMER_MAX": "POSIX_DELAYTIMER_MAX", 64 "SEM_NAMELEN_MAX": "POSIX_SEM_NAME_MAX", 65 "SEM_VALUE_MAX": "POSIX_SEM_VALUE_MAX", 66} 67 68MESSAGES = { 69 "POSIX_CLOCK": 70 "POSIX_CLOCK is a one-to-many replacement. If this simple substitution is not " 71 "sufficient, it's best to try a combination of POSIX_CLOCK_SELECTION, POSIX_CPUTIME, " 72 "POSIX_MONOTONIC_CLOCK, POSIX_TIMERS, and POSIX_TIMEOUTS.", 73 "POSIX_MAX_FDS": 74 "A read-only version of this symbol is POSIX_OPEN_MAX, which is of course, the standard " 75 "symbol. ZVFS_OPEN_MAX may be set by the user. Consider using POSIX_MAX_FDS if the " 76 "use-case is read-only.", 77} 78 79 80def process_file(path): 81 modified = False 82 output = [] 83 84 try: 85 with open(path) as f: 86 lines = f.readlines() 87 88 for line in lines: 89 longest = "" 90 length = 0 91 for m in REPLACEMENTS: 92 if re.match(".*" + m + ".*", line) and len(m) > length: 93 length = len(m) 94 longest = m 95 96 if length != 0: 97 modified = True 98 line = line.replace(longest, REPLACEMENTS[longest]) 99 msg = MESSAGES.get(longest) 100 if msg: 101 print( 102 f"Notice: {longest} -> {REPLACEMENTS[longest]}: {msg}") 103 104 output.append(line) 105 106 if modified is False: 107 return 108 109 with open(path, "w") as f: 110 f.writelines(output) 111 112 except UnicodeDecodeError: 113 print(f"Unable to read lines from {path}", file=sys.stderr) 114 except Exception as e: 115 print(f"Failed with exception {e}", e) 116 117 118def process_tree(project): 119 for p in project.glob("**/*"): 120 for fp in FILE_PATTERNS: 121 cfp = re.compile(".+/" + fp + "$") 122 if re.match(cfp, str(p)) is not None: 123 process_file(p) 124 125 126if __name__ == "__main__": 127 parser = argparse.ArgumentParser(allow_abbrev=False) 128 parser.add_argument( 129 "-r", 130 "--root", 131 type=Path, 132 required=True, 133 help="Zephyr-based project path") 134 args = parser.parse_args() 135 136 process_tree(args.root) 137