Cmake: add defconfig preprocess capability in Cmake build environment(recursively expand #include)

Add:
    cmake/nuttx_process_config.cmake
    tools/process_config.py

    Update nuttx/CMakeLists.txt to call process_config defined ini
    nuttx_process_config.cmake to process defconfig before actually using it
This commit is contained in:
wangchengdong 2025-08-25 12:03:17 +08:00 committed by Xiang Xiao
parent e87c43b798
commit be36d42da5
3 changed files with 169 additions and 0 deletions

View file

@ -158,6 +158,22 @@ if(NOT EXISTS "${NUTTX_DEFCONFIG}")
message(FATAL_ERROR "No config file found at ${NUTTX_DEFCONFIG}")
endif()
# Process initial defconfig ###################################################
# Process initial defconfig to recursively expand #include in it
include(nuttx_process_config)
get_filename_component(NUTTX_DEFCONFIG_DIR "${NUTTX_DEFCONFIG}" DIRECTORY)
process_config(
${CMAKE_BINARY_DIR}/.defconfig.processed
${NUTTX_DEFCONFIG}
INCLUDE_PATHS
${NUTTX_DEFCONFIG_DIR}/../../common/configs
${NUTTX_DEFCONFIG_DIR}/../common
${NUTTX_DEFCONFIG_DIR}
${NUTTX_DIR}/../apps
${NUTTX_DIR}/../nuttx-apps)
set(NUTTX_DEFCONFIG ${CMAKE_BINARY_DIR}/.defconfig.processed)
# Generate initial .config ###################################################
# This is needed right before any other configure step so that we can source
# Kconfig variables into CMake variables

View file

@ -0,0 +1,48 @@
# ##############################################################################
# cmake/nuttx_process_config.cmake
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
# license agreements. See the NOTICE file distributed with this work for
# additional information regarding copyright ownership. The ASF licenses this
# file to you 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
#
# http://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.
#
# ##############################################################################
function(process_config OUTPUT INPUT)
set(options)
set(oneValueArgs)
set(multiValueArgs INCLUDE_PATHS)
cmake_parse_arguments(PARSE_ARGV 2 PROCESS_INCLUDES "${options}"
"${oneValueArgs}" "${multiValueArgs}")
find_package(Python3 REQUIRED COMPONENTS Interpreter)
set(include_args "")
foreach(path IN LISTS PROCESS_INCLUDES_INCLUDE_PATHS)
list(APPEND include_args "${path}")
endforeach()
message(STATUS "Processing includes: ${INPUT} → ${OUTPUT}")
execute_process(
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/tools/process_config.py
${OUTPUT} ${INPUT} ${include_args}
RESULT_VARIABLE result
OUTPUT_VARIABLE out
ERROR_VARIABLE err)
if(NOT result EQUAL 0)
message(FATAL_ERROR "Failed to process includes:\n${err}")
endif()
endfunction()

105
tools/process_config.py Normal file
View file

@ -0,0 +1,105 @@
#!/usr/bin/env python3
# tools/process_config.py
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you 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
#
# http://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.
#
import re
import sys
from pathlib import Path
def expand_file(input_path, include_paths, processed=None):
"""
Recursively expand the file, returning its contents in order as a list of lines.
"""
if processed is None:
processed = set()
input_path = Path(input_path).resolve()
if input_path in processed:
return [] # Already processed, avoid duplicate includes
processed.add(input_path)
expanded_lines = []
with input_path.open("r", encoding="utf-8") as f:
lines = f.readlines()
for line in lines:
line_strip = line.strip()
match = re.match(r'#include\s*[<"]([^">]+)[">]', line_strip)
if match:
include_file = match.group(1)
found = False
# Check the current directory first
direct_path = input_path.parent / include_file
if direct_path.exists():
expanded_lines.extend(
expand_file(direct_path, include_paths, processed)
)
found = True
else:
# Then check in the include paths
for path in include_paths:
candidate = Path(path) / include_file
if candidate.exists():
expanded_lines.extend(
expand_file(candidate, include_paths, processed)
)
found = True
break
if not found:
print(
f'ERROR: Cannot find "{include_file}" from {input_path}',
file=sys.stderr,
)
sys.exit(1)
else:
expanded_lines.append(line)
expanded_lines.append("\n") # Keep separation between files
return expanded_lines
def process_file(output_path, input_path, include_paths):
lines = expand_file(input_path, include_paths)
with open(output_path, "w", encoding="utf-8") as out:
out.writelines(lines)
if __name__ == "__main__":
if len(sys.argv) < 3:
print(
"Usage: process_includes.py <output_file> <input_file> [include_paths...]",
file=sys.stderr,
)
sys.exit(1)
output_file = Path(sys.argv[1])
input_file = sys.argv[2]
include_dirs = sys.argv[3:]
if output_file.exists():
output_file.unlink()
process_file(output_file, input_file, include_dirs)