xref: /OK3568_Linux_fs/buildroot/build/merge_config.sh (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun#!/bin/bash
2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0
3*4882a593Smuzhiyun#
4*4882a593Smuzhiyun#  merge_config.sh - Takes a list of config fragment values, and merges
5*4882a593Smuzhiyun#  them one by one. Provides warnings on overridden values, and specified
6*4882a593Smuzhiyun#  values that did not make it to the resulting .config file (due to missed
7*4882a593Smuzhiyun#  dependencies or config symbol removal).
8*4882a593Smuzhiyun#
9*4882a593Smuzhiyun#  Portions reused from kconf_check and generate_cfg:
10*4882a593Smuzhiyun#  http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/kconf_check
11*4882a593Smuzhiyun#  http://git.yoctoproject.org/cgit/cgit.cgi/yocto-kernel-tools/tree/tools/generate_cfg
12*4882a593Smuzhiyun#
13*4882a593Smuzhiyun#  Copyright (c) 2009-2010 Wind River Systems, Inc.
14*4882a593Smuzhiyun#  Copyright 2011 Linaro
15*4882a593Smuzhiyun#
16*4882a593Smuzhiyun#  Based on buildroot(2022.08.x)/support/kconfig/merge_config.sh
17*4882a593Smuzhiyun#  Copyright (c) 2022 Jeffy Chen <jeffy.chen@rock-chips.com>
18*4882a593Smuzhiyun#
19*4882a593Smuzhiyun#  This program is free software; you can redistribute it and/or modify
20*4882a593Smuzhiyun#  it under the terms of the GNU General Public License version 2 as
21*4882a593Smuzhiyun#  published by the Free Software Foundation.
22*4882a593Smuzhiyun#
23*4882a593Smuzhiyun#  This program is distributed in the hope that it will be useful,
24*4882a593Smuzhiyun#  but WITHOUT ANY WARRANTY; without even the implied warranty of
25*4882a593Smuzhiyun#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26*4882a593Smuzhiyun#  See the GNU General Public License for more details.
27*4882a593Smuzhiyun
28*4882a593Smuzhiyunset -e
29*4882a593Smuzhiyun
30*4882a593Smuzhiyunclean_up() {
31*4882a593Smuzhiyun	rm -f $TMP_FILE
32*4882a593Smuzhiyun	rm -f $TMP_MERGE_FILE
33*4882a593Smuzhiyun}
34*4882a593Smuzhiyun
35*4882a593Smuzhiyunusage() {
36*4882a593Smuzhiyun	echo "Usage: $0 [OPTIONS] [CONFIG [...]]"
37*4882a593Smuzhiyun	echo "  -h    display this help text"
38*4882a593Smuzhiyun	echo "  -m    only merge the fragments, do not execute the make command"
39*4882a593Smuzhiyun	echo "  -n    use allnoconfig instead of alldefconfig"
40*4882a593Smuzhiyun	echo "  -r    list redundant entries when merging fragments"
41*4882a593Smuzhiyun	echo "  -O    dir to put generated output files.  Consider setting \$KCONFIG_CONFIG instead."
42*4882a593Smuzhiyun}
43*4882a593Smuzhiyun
44*4882a593SmuzhiyunRUNMAKE=true
45*4882a593SmuzhiyunALLTARGET=alldefconfig
46*4882a593SmuzhiyunWARNREDUN=false
47*4882a593SmuzhiyunOUTPUT=.
48*4882a593Smuzhiyun
49*4882a593Smuzhiyunwhile true; do
50*4882a593Smuzhiyun	case $1 in
51*4882a593Smuzhiyun	"-n")
52*4882a593Smuzhiyun		ALLTARGET=allnoconfig
53*4882a593Smuzhiyun		shift
54*4882a593Smuzhiyun		continue
55*4882a593Smuzhiyun		;;
56*4882a593Smuzhiyun	"-m")
57*4882a593Smuzhiyun		RUNMAKE=false
58*4882a593Smuzhiyun		shift
59*4882a593Smuzhiyun		continue
60*4882a593Smuzhiyun		;;
61*4882a593Smuzhiyun	"-h")
62*4882a593Smuzhiyun		usage
63*4882a593Smuzhiyun		exit
64*4882a593Smuzhiyun		;;
65*4882a593Smuzhiyun	"-r")
66*4882a593Smuzhiyun		WARNREDUN=true
67*4882a593Smuzhiyun		shift
68*4882a593Smuzhiyun		continue
69*4882a593Smuzhiyun		;;
70*4882a593Smuzhiyun	"-O")
71*4882a593Smuzhiyun		if [ -d $2 ];then
72*4882a593Smuzhiyun			OUTPUT=$(echo $2 | sed 's/\/*$//')
73*4882a593Smuzhiyun		else
74*4882a593Smuzhiyun			echo "output directory $2 does not exist" 1>&2
75*4882a593Smuzhiyun			exit 1
76*4882a593Smuzhiyun		fi
77*4882a593Smuzhiyun		shift 2
78*4882a593Smuzhiyun		continue
79*4882a593Smuzhiyun		;;
80*4882a593Smuzhiyun	*)
81*4882a593Smuzhiyun		break
82*4882a593Smuzhiyun		;;
83*4882a593Smuzhiyun	esac
84*4882a593Smuzhiyundone
85*4882a593Smuzhiyun
86*4882a593Smuzhiyunif [ "$#" -lt 1 ] ; then
87*4882a593Smuzhiyun	usage
88*4882a593Smuzhiyun	exit
89*4882a593Smuzhiyunfi
90*4882a593Smuzhiyun
91*4882a593Smuzhiyunif [ -z "$KCONFIG_CONFIG" ]; then
92*4882a593Smuzhiyun	if [ "$OUTPUT" != . ]; then
93*4882a593Smuzhiyun		KCONFIG_CONFIG=$(readlink -m -- "$OUTPUT/.config")
94*4882a593Smuzhiyun	else
95*4882a593Smuzhiyun		KCONFIG_CONFIG=.config
96*4882a593Smuzhiyun	fi
97*4882a593Smuzhiyunfi
98*4882a593Smuzhiyun
99*4882a593SmuzhiyunINITFILE=$1
100*4882a593Smuzhiyunshift;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyunif [ ! -r "$INITFILE" ]; then
103*4882a593Smuzhiyun	echo "The base file '$INITFILE' does not exist.  Exit." >&2
104*4882a593Smuzhiyun	exit 1
105*4882a593Smuzhiyunfi
106*4882a593Smuzhiyun
107*4882a593SmuzhiyunMERGE_LIST=$*
108*4882a593SmuzhiyunSED_CONFIG_EXP1="s/^\([a-zA-Z0-9_]*\)+\{0,1\}=.*/\1/p"
109*4882a593SmuzhiyunSED_CONFIG_EXP2="s/^# \([a-zA-Z0-9_]*\) is not set$/\1/p"
110*4882a593SmuzhiyunSED_CONFIG_EXP3="s/^# \([a-zA-Z0-9_]*\) is reset to default$/\1/p"
111*4882a593Smuzhiyun
112*4882a593SmuzhiyunSED_CLEAR_EXP1="s/^\([a-zA-Z0-9_]*\)+=/\1=/" # Append
113*4882a593SmuzhiyunSED_CLEAR_EXP2="/^# \([a-zA-Z0-9_]*\) is reset to default$/d" # Reset
114*4882a593Smuzhiyun
115*4882a593SmuzhiyunTMP_FILE=$(mktemp ./.tmp.config.XXXXXXXXXX)
116*4882a593SmuzhiyunTMP_MERGE_FILE=$(mktemp ./.merge_tmp.config.XXXXXXXXXX)
117*4882a593Smuzhiyun
118*4882a593Smuzhiyunecho "Using $INITFILE as base"
119*4882a593Smuzhiyun
120*4882a593Smuzhiyuntrap clean_up EXIT
121*4882a593Smuzhiyun
122*4882a593Smuzhiyuncat $INITFILE | sed -e "$SED_CLEAR_EXP1" -e "$SED_CLEAR_EXP2" >> $TMP_FILE
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun# Merge files, printing warnings on overridden values
125*4882a593Smuzhiyunfor MERGE_FILE in $MERGE_LIST ; do
126*4882a593Smuzhiyun	echo "Merging $MERGE_FILE"
127*4882a593Smuzhiyun	if [ ! -r "$MERGE_FILE" ]; then
128*4882a593Smuzhiyun		echo "The merge file '$MERGE_FILE' does not exist.  Exit." >&2
129*4882a593Smuzhiyun		exit 1
130*4882a593Smuzhiyun	fi
131*4882a593Smuzhiyun	CFG_LIST=$(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" \
132*4882a593Smuzhiyun		-e "$SED_CONFIG_EXP3" $MERGE_FILE)
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun	cat $MERGE_FILE > $TMP_MERGE_FILE
135*4882a593Smuzhiyun	for CFG in $CFG_LIST ; do
136*4882a593Smuzhiyun		grep -q -w $CFG $TMP_FILE || continue
137*4882a593Smuzhiyun		PREV_VAL=$(grep -w $CFG $TMP_FILE)
138*4882a593Smuzhiyun		ORIG_NEW_VAL=$(grep -w $CFG $TMP_MERGE_FILE)
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun		if [ "$ORIG_NEW_VAL" = "# $CFG is reset to default" ]; then
141*4882a593Smuzhiyun			# Reset
142*4882a593Smuzhiyun			NEW_VAL=
143*4882a593Smuzhiyun		elif [ "${ORIG_NEW_VAL%=*}" = "$CFG+" ]; then
144*4882a593Smuzhiyun			# Append
145*4882a593Smuzhiyun			if echo "$PREV_VAL" | grep -q "^#"; then
146*4882a593Smuzhiyun				# Replace
147*4882a593Smuzhiyun				NEW_VAL=${ORIG_NEW_VAL/+=/=}
148*4882a593Smuzhiyun			else
149*4882a593Smuzhiyun				ORIG_NEW_STR=$(echo "$ORIG_NEW_VAL" | \
150*4882a593Smuzhiyun					sed "s/^.*=\"\(.*\)\"/\1/")
151*4882a593Smuzhiyun				PREV_STR=$(echo "$PREV_VAL" | \
152*4882a593Smuzhiyun					sed "s/^.*=\"\(.*\)\"/\1/")
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun				NEW_STR=
155*4882a593Smuzhiyun				for s in $ORIG_NEW_STR; do
156*4882a593Smuzhiyun					echo "$PREV_STR" | xargs -n 1 | \
157*4882a593Smuzhiyun						grep "^$s$" >/dev/null || \
158*4882a593Smuzhiyun						NEW_STR="$NEW_STR $s"
159*4882a593Smuzhiyun				done
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun				if [ -z "$NEW_STR" ]; then
162*4882a593Smuzhiyun					# Skip
163*4882a593Smuzhiyun					NEW_VAL="$PREV_VAL"
164*4882a593Smuzhiyun				else
165*4882a593Smuzhiyun					# Append string value
166*4882a593Smuzhiyun					NEW_VAL="${PREV_VAL%\"} ${NEW_STR# }\""
167*4882a593Smuzhiyun				fi
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun				# Update fragment
170*4882a593Smuzhiyun				sed -i "s#\<$CFG\>.*#$NEW_VAL#" $TMP_MERGE_FILE
171*4882a593Smuzhiyun			fi
172*4882a593Smuzhiyun		else
173*4882a593Smuzhiyun			# Normal replace
174*4882a593Smuzhiyun			NEW_VAL=$ORIG_NEW_VAL
175*4882a593Smuzhiyun		fi
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun		if [ "$PREV_VAL" != "$NEW_VAL" ] ; then
178*4882a593Smuzhiyun			echo "Value of $CFG is redefined by $MERGE_FILE:"
179*4882a593Smuzhiyun			echo -e "Previous value:\t$PREV_VAL"
180*4882a593Smuzhiyun			if [ "$NEW_VAL" != "$ORIG_NEW_VAL" ]; then
181*4882a593Smuzhiyun				echo -e "Modify value:\t$ORIG_NEW_VAL"
182*4882a593Smuzhiyun			fi
183*4882a593Smuzhiyun			echo -e "New value:\t$NEW_VAL"
184*4882a593Smuzhiyun			echo
185*4882a593Smuzhiyun		elif [ "$WARNREDUN" = "true" ]; then
186*4882a593Smuzhiyun			echo "Value of $CFG is redundant by $MERGE_FILE:"
187*4882a593Smuzhiyun		fi
188*4882a593Smuzhiyun		sed -i "/\<$CFG[ =]/d" $TMP_FILE
189*4882a593Smuzhiyun	done
190*4882a593Smuzhiyun	cat $TMP_MERGE_FILE | sed -e "$SED_CLEAR_EXP1" \
191*4882a593Smuzhiyun		-e "$SED_CLEAR_EXP2" >> $TMP_FILE
192*4882a593Smuzhiyundone
193*4882a593Smuzhiyun
194*4882a593Smuzhiyunif [ "$RUNMAKE" = "false" ]; then
195*4882a593Smuzhiyun	cp -T -- "$TMP_FILE" "$KCONFIG_CONFIG"
196*4882a593Smuzhiyun	echo "#"
197*4882a593Smuzhiyun	echo "# merged configuration written to $KCONFIG_CONFIG (needs make)"
198*4882a593Smuzhiyun	echo "#"
199*4882a593Smuzhiyun	exit
200*4882a593Smuzhiyunfi
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun# If we have an output dir, setup the O= argument, otherwise leave
203*4882a593Smuzhiyun# it blank, since O=. will create an unnecessary ./source softlink
204*4882a593SmuzhiyunOUTPUT_ARG=""
205*4882a593Smuzhiyunif [ "$OUTPUT" != "." ] ; then
206*4882a593Smuzhiyun	OUTPUT_ARG="O=$OUTPUT"
207*4882a593Smuzhiyunfi
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun# Use the merged file as the starting point for:
211*4882a593Smuzhiyun# alldefconfig: Fills in any missing symbols with Kconfig default
212*4882a593Smuzhiyun# allnoconfig: Fills in any missing symbols with # CONFIG_* is not set
213*4882a593Smuzhiyunmake KCONFIG_ALLCONFIG=$TMP_FILE $OUTPUT_ARG $ALLTARGET
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun# Check all specified config values took (might have missed-dependency issues)
217*4882a593Smuzhiyunfor CFG in $(sed -n -e "$SED_CONFIG_EXP1" -e "$SED_CONFIG_EXP2" $TMP_FILE); do
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun	REQUESTED_VAL=$(grep -w -e "$CFG" $TMP_FILE)
220*4882a593Smuzhiyun	ACTUAL_VAL=$(grep -w -e "$CFG" "$KCONFIG_CONFIG" || true)
221*4882a593Smuzhiyun	if [ "$REQUESTED_VAL" != "$ACTUAL_VAL" ] ; then
222*4882a593Smuzhiyun		echo "Value requested for $CFG not in final .config"
223*4882a593Smuzhiyun		echo "Requested value:  $REQUESTED_VAL"
224*4882a593Smuzhiyun		echo "Actual value:     $ACTUAL_VAL"
225*4882a593Smuzhiyun		echo ""
226*4882a593Smuzhiyun	fi
227*4882a593Smuzhiyundone
228