| # Copyright 2025 The Pigweed Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| # use this file except in compliance with the License. You may obtain a copy of |
| # the License at |
| # |
| # https://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations under |
| # the License. |
| """Generates Kconfig files that source necessary Kconfig files from Zephyr. |
| |
| This is the equivalent of the CMake function 'kconfig_gen' in |
| cmake/modules/hwm_v2.cmake |
| |
| The following files are generated in '<KCONFIG_BINARY_DIR>/soc' |
| - Kconfig.defconfig: Contains references to SoC defconfig files for Zephyr |
| integration. |
| - Kconfig: Contains references to regular SoC Kconfig files for Zephyr |
| integration. |
| - Kconfig.soc: Contains references to generic SoC Kconfig files. |
| - Kconfig.sysbuild: Contains references to SoC sysbuild Kconfig files. |
| |
| The following file is generated in '<KCONFIG_BINARY_DIR>/arch' |
| - Kconfig: Contains references to regular arch Kconfig files for Zephyr |
| integration. |
| |
| The following files are generated in '<KCONFIG_BINARY_DIR>/boards' |
| - Kconfig: Contains references to regular board Kconfig files for Zephyr |
| integration. |
| - Kconfig.defconfig: Contains references to board defconfig files for Zephyr |
| integration. |
| - Kconfig.<board>: Contains references to generic board Kconfig files. |
| - Kconfig.sysbuild: Contains references to board sysbuild Kconfig files. |
| """ |
| |
| import argparse |
| import os |
| from pathlib import Path |
| |
| |
| def find_arch_source_directories(arch_roots): |
| """Finds all directories containing a valid arch definition. |
| |
| Args: |
| arch_roots (list[Path]): A list of root directories to search for archs. |
| |
| Returns: |
| list[str]: A list of directory paths corresponding to an architecture. |
| """ |
| result = [] |
| # The 'arch' directory has a flat structure with child directories |
| # corresponding to architectures. |
| for arch_root in arch_roots: |
| for arch_dir in (Path(arch_root) / 'arch').iterdir(): |
| result.append(str(arch_dir)) |
| return result |
| |
| |
| def find_soc_source_directories(soc_roots): |
| """Finds all directories containing a valid SoC definition. |
| |
| Args: |
| soc_roots (list[Path]): A list of root directories to search for SoCs. |
| |
| Returns: |
| list[str]: A list of directory paths corresponding to a SoC. |
| """ |
| # Find all soc.yml files in the given roots. Each yaml file should |
| # correspond to one SoC with Kconfig. |
| yml_files = [] |
| for root in soc_roots: |
| yml_files.extend(sorted((root / 'soc').rglob('soc.yml'))) |
| |
| result = [] |
| for soc_yml in yml_files: |
| if soc_yml.is_file(): |
| result.append(soc_yml.parent) |
| return result |
| |
| |
| def find_subdirectory(root_directory, subdirectory_name): |
| """Searches for a subdirectory within a given root directory. |
| |
| Args: |
| root_directory (str): The path to the directory where the search starts. |
| subdirectory_name (str): The name of the subdirectory to find. |
| |
| Returns: |
| str: The full path to the first matching subdirectory found, or None if |
| not found. |
| """ |
| if not os.path.isdir(root_directory): |
| print(f"Error: Root directory '{root_directory}' not found.") |
| return None |
| |
| for dirpath, dirnames, filenames in os.walk(root_directory): |
| if subdirectory_name in dirnames: |
| return os.path.join(dirpath, subdirectory_name) |
| |
| return None |
| |
| |
| def kconfig_gen(bin_dir, file, dirs, comment): |
| """Generates Kconfig snippets that point to SoC-specific and board-specific Kconfig files. |
| |
| Args: |
| bin_dir (str): The suffix of the path to hold the generated snippet. |
| file (str): The filename for the generated snippet. |
| dirs (list[str]): List of directories to search for Kconfig files to |
| include. |
| comment (str): Comment to add to the top of the generated snippet. |
| """ |
| kconfig_header = f'# Load {comment} descriptions.\n' |
| kconfig_file = os.environ['KCONFIG_BINARY_DIR'] + f'/{bin_dir}/{file}' |
| |
| kconfig_binary_dir = Path(os.environ['KCONFIG_BINARY_DIR'] + f'/{bin_dir}') |
| try: |
| kconfig_binary_dir.mkdir(parents=True, exist_ok=True) |
| except OSError as e: |
| print(f"Error creating directory '{kconfig_binary_dir}': {e}") |
| return |
| |
| with open(kconfig_file, 'w') as f: |
| f.write(kconfig_header + '\n') |
| for entry in dirs: |
| kconfig_file_path = Path(entry) / file |
| if kconfig_file_path.exists(): |
| f.write('osource "' + str(kconfig_file_path) + '"\n') |
| |
| |
| if __name__ == '__main__': |
| parser = argparse.ArgumentParser( |
| description='Script to generate Kconfig include files for Zephyr' |
| ) |
| parser.add_argument( |
| '--arch-root', |
| type=Path, |
| dest='arch_roots', |
| nargs='+', |
| help='Directory containing an arch subdirectory', |
| required=True, |
| ) |
| parser.add_argument( |
| '--soc-root', |
| type=Path, |
| dest='soc_roots', |
| nargs='+', |
| help='Directory containing a soc subdirectory', |
| required=True, |
| ) |
| args = parser.parse_args() |
| |
| arch_source_dirs = find_arch_source_directories(args.arch_roots) |
| soc_source_dirs = find_soc_source_directories(args.soc_roots) |
| |
| board = os.environ['BOARD'] |
| # Here we use our own simple search function instead of calling Zephyr's |
| # list_board.py because we are only interested in one board. |
| # TODO(pwbug.dev/434212597): Use list_board.py to support out-of-tree board |
| # directories. |
| board_dir = find_subdirectory(os.environ['srctree'], board) |
| |
| kconfig_gen('arch', 'Kconfig', arch_source_dirs, 'Zephyr Arch Kconfig') |
| kconfig_gen( |
| 'soc', |
| 'Kconfig.defconfig', |
| soc_source_dirs, |
| 'Zephyr SoC defconfig', |
| ) |
| kconfig_gen('soc', 'Kconfig', soc_source_dirs, 'Zephyr SoC Kconfig') |
| kconfig_gen('soc', 'Kconfig.soc', soc_source_dirs, 'SoC Kconfig') |
| kconfig_gen( |
| 'soc', |
| 'Kconfig.sysbuild', |
| soc_source_dirs, |
| 'Sysbuild SoC Kconfig', |
| ) |
| kconfig_gen( |
| 'boards', 'Kconfig.defconfig', [board_dir], 'Zephyr board defconfig' |
| ) |
| kconfig_gen('boards', f'Kconfig.{board}', [board_dir], 'board Kconfig') |
| kconfig_gen('boards', 'Kconfig', [board_dir], 'Zephyr board Kconfig') |
| kconfig_gen( |
| 'boards', 'Kconfig.sysbuild', [board_dir], 'Sysbuild board Kconfig' |
| ) |