[PATCH] scripts: merge_config.sh: support include directives in fragments

Julien Stephan jstephan at baylibre.com
Thu Mar 19 17:14:05 CET 2026


Many defconfig files rely on include directives to factor out common
configuration. When running "make some_board_defconfig", these files are
preprocessed and the includes are resolved automatically. However,
merge_config.sh script currently does not handle include directives in
configuration fragments.

Add a preprocessing step to resolve include directives in all fragments
before merging them.

By default, the include search path consists of:
  - the current working directory
  - the fragment's directory
  - the default U-Boot configs/ directory

This ensures that existing defconfig files work out of the box. Additional
include directories can be specified using the -I option:

  ./scripts/kconfig/merge_config.sh -I <additional include dir>  configs/some_board_defconfig frag1.cfg frag2.cfg

Signed-off-by: Julien Stephan <jstephan at baylibre.com>
---
 scripts/kconfig/merge_config.sh | 56 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 51 insertions(+), 5 deletions(-)

diff --git a/scripts/kconfig/merge_config.sh b/scripts/kconfig/merge_config.sh
index 0ef90649964..a78cfa5da02 100755
--- a/scripts/kconfig/merge_config.sh
+++ b/scripts/kconfig/merge_config.sh
@@ -21,7 +21,7 @@
 #  See the GNU General Public License for more details.
 
 clean_up() {
-	rm -f $TMP_FILE
+	rm -f $TMP_FILE $TMP_PREPROCESSED
 	exit
 }
 trap clean_up HUP INT TERM
@@ -33,6 +33,7 @@ usage() {
 	echo "  -n    use allnoconfig instead of alldefconfig"
 	echo "  -r    list redundant entries when merging fragments"
 	echo "  -O    dir to put generated output files.  Consider setting \$KCONFIG_CONFIG instead."
+	echo "  -I    include dir to search for includes. Defaults to pwd, u-boot configs and directory containing the fragment."
 	echo
 	echo "Used prefix: '$CONFIG_PREFIX'. You can redefine it with \$CONFIG_ environment variable."
 }
@@ -42,6 +43,7 @@ ALLTARGET=alldefconfig
 WARNREDUN=false
 OUTPUT=.
 CONFIG_PREFIX=${CONFIG_-CONFIG_}
+INCLUDE_DIR="-I $(pwd) -I $(pwd)/configs"
 
 while true; do
 	case $1 in
@@ -74,6 +76,16 @@ while true; do
 		shift 2
 		continue
 		;;
+	"-I")
+		if [ -d $2 ];then
+			INCLUDE_DIR="$INCLUDE_DIR -I $2"
+		else
+			echo "include directory $2 does not exist" 1>&2
+			exit 1
+		fi
+		shift 2
+		continue
+		;;
 	*)
 		break
 		;;
@@ -106,9 +118,39 @@ SED_CONFIG_EXP1="s/^\(${CONFIG_PREFIX}[a-zA-Z0-9_]*\)=.*/\1/p"
 SED_CONFIG_EXP2="s/^# \(${CONFIG_PREFIX}[a-zA-Z0-9_]*\) is not set$/\1/p"
 
 TMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
+TMP_PREPROCESSED=$(mktemp ./.tmp.config.preprocessed.XXXXXXXXXX)
+
+# Function to preprocess config file with cpp to expand #include directives
+preprocess_config() {
+	local input_file="$1"
+	local output_file="$2"
+
+	# Get the directory of the input file for include path
+	local include_dir=$(dirname "$input_file")
+
+	# Use cpp to preprocess the file, similar to how "make board_defconfig"
+	# does (./scripts/kconfig/Makefile):
+	#
+	#   %_defconfig: $(obj)/conf
+        #      $(Q)$(CPP) -nostdinc -P -I $(srctree) -undef -x assembler-with-cpp $(srctree)/arch/$(SRCARCH)/configs/$@ -o generated_defconfig
+        #      $(Q)sed -i -e 's/^[[:space:]]//' generated_defconfig
+
+	cpp -nostdinc -P -undef -x assembler-with-cpp \
+		-I "$include_dir" $INCLUDE_DIR  \
+		"$input_file" -o "$output_file"
+
+	if [ $? -ne 0 ]; then
+		# If cpp fails, fall back to just copying the file
+		echo "Warning: C preprocessor failed for $input_file, using file as-is" >&2
+		cp "$input_file" "$output_file"
+	else
+		# Clean up any leading spaces that cpp might have added
+		sed -i 's/^[[:space:]]//' "$output_file"
+	fi
+}
 
 echo "Using $INITFILE as base"
-cat $INITFILE > $TMP_FILE
+preprocess_config "$INITFILE" "$TMP_FILE"
 
 # Merge files, printing warnings on overridden values
 for MERGE_FILE in $MERGE_LIST ; do
@@ -117,12 +159,16 @@ for MERGE_FILE in $MERGE_LIST ; do
 		echo "The merge file '$MERGE_FILE' does not exist.  Exit." >&2
 		exit 1
 	fi
-	CFG_LIST=$(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $MERGE_FILE)
+
+	# Preprocess the fragment to expand includes
+	preprocess_config "$MERGE_FILE" "$TMP_PREPROCESSED"
+
+	CFG_LIST=$(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $TMP_PREPROCESSED)
 
 	for CFG in $CFG_LIST ; do
 		grep -q -w $CFG $TMP_FILE || continue
 		PREV_VAL=$(grep -w $CFG $TMP_FILE)
-		NEW_VAL=$(grep -w $CFG $MERGE_FILE)
+		NEW_VAL=$(grep -w $CFG $TMP_PREPROCESSED)
 		if [ "x$PREV_VAL" != "x$NEW_VAL" ] ; then
 			echo Value of $CFG is redefined by fragment $MERGE_FILE:
 			echo Previous  value: $PREV_VAL
@@ -133,7 +179,7 @@ for MERGE_FILE in $MERGE_LIST ; do
 		fi
 		sed -i "/$CFG[ =]/d" $TMP_FILE
 	done
-	cat $MERGE_FILE >> $TMP_FILE
+	cat $TMP_PREPROCESSED >> $TMP_FILE
 done
 
 if [ "$RUNMAKE" = "false" ]; then

---
base-commit: 142c805d470cd02470146d6d70aa9c522d4da16c
change-id: 20260319-merge_configs-support-include-directive-e3dd24314011

Best regards,
-- 
Julien Stephan <jstephan at baylibre.com>



More information about the U-Boot mailing list