blob: 281516dc2039855a403cd8af6f723b93f5140bd2 [file] [log] [blame]
# 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'
)