Messages in this thread | | | Date | Wed, 17 Sep 2008 01:55:26 +0200 | From | Takashi Iwai <> | Subject | diet-kconfig: a script to trim unneeded kconfigs |
| |
Hi,
a topic that just came up in kernel summit is a script to remove unneeded kernel configs automatically to reduce the compile time. Incidentally, I already wrote such a script during the last SUSE hack week a couple of weeks ago, so I'd like to share here, hopefully to give an idea for further improvements.
The script checks the currently loaded modules and trims other CONFIG_XXX=m simply, and tries make oldconfig, and writes out the resultant .config in the current directory after some checks. You can specify the config file via option, as default, it reads from /proc/config.gz.
The script is VERY hackish. I should have begun with perl or whatever better script language, but I chose bash and co. So, don't expect much code quality. I'm no script guy after all :)
Takashi ---
#!/bin/sh
# this magic makes grep and co a lot faster export LANG=C
kroot= subarch=$(uname -i) oldconfig=/proc/config.gz localversion= modulelist= optimize_smp= optimize_memory= outputfile=
usage () { cat <<EOF diet-kconfig -- Trim down kernel configs of unused modules Usage: diet-kconfig [-options] Create a kernel config file based on the running system option: -r ROOT Specifies the linux-kernel root, default: current dir -a ARCH Architecture (e.g. i386), default: running arch -c FILE Old config file, default: /proc/config.gz) -o FILE Output config file, default: kernel/.config -l LIST Module list, default: read lsmod -v VER Specifies the local version string, default: as is the original -s Optimize SMP -m Optimize memory model (for i386) -h This help EOF exit 1 }
while getopts r:a:c:o:l:v:pmh opt; do case "$opt" in r) kroot="$OPTARG" ;; a) subarch="$OPTARG" ;; c) oldconfig="$OPTARG" if [ ! -f "$oldconfig" ]; then echo "Cannot find old config $oldconfig" exit 1 fi ;; o) outputfile="$OPTARG" ;; l) modulelist="$OPTARG" if [ ! -f "$modulelist" ]; then echo "Cannot find module list file modulelist" exit 1 fi ;; v) localversion="-$OPTARG" ;; s) optimize_smp=y ;; m) optimize_memory=y ;; h) usage ;; *) echo "Invalid option $opt" usage ;; esac done
if [ -z "$kroot" ]; then kdir=. else kdir="$kroot" fi if [ ! -d "$kdir" -o ! -f "$kdir"/Makefile -o ! -f "$kdir"/MAINTAINERS ]; then echo "Invalid kernel root directory $kdir" exit 1 fi
case $subarch in i?86|x86_64) arch=x86;; *) arch=$subarch;; esac
tmpd=$(mktemp -q -d /tmp/dietkconf.XXXXXX)
cleanup () { rm -rf $tmpd exit 1 } trap cleanup 0
curdir=$(pwd)
test -n "$kroot" && cd $kroot
# create a list of Makefile's find arch/$arch block crypto drivers fs ipc kernel lib mm net security sound virt \ -name 'Makefile' | xargs cat >> $tmpd/makefiles
# find configs to create the given module find_kconfig () { module=$1 modregex=$(echo $1 | sed -e's/_/[_-]/g')
grep -E '^[[:space:]]*obj-\$\([A-Za-z0-9_]*\)[[:space:]]*[+:]=.*[[:space:]]'"$modregex"'\.o' $tmpd/makefiles | \ sed -e's/^.*://g' -e's/^[[:space:]]*obj-\$(\(.*\)).*$/\1/g' }
# set config no kconfig_no () { sed -i -e's/^\('$1'\)=.*/# \1 is not set/' $tmpd/kconfig }
# set config yes kconfig_yes () { sed -i -e's/# '$1' .*/'$1'=y/' $tmpd/kconfig }
# only previously selected modules with XXX marks kconfig_mod () { sed -i -e's/# '$1' XXX/'$1'=m/' $tmpd/kconfig }
get_old_config () { case "$oldconfig" in *.gz) zcat $oldconfig ;; *) cat $oldconfig esac }
list_modules () { if [ -n "$modulelist" ]; then awk '{if ($1 != "Module") {print $1}}' < $modulelist else lsmod | awk '{if ($1 != "Module") {print $1}}' fi }
# copy the original kconfigs; reset all modules, but remember they were # enabled by marking XXX get_old_config | sed -e's/^\(CONFIG.*\)=m/# \1 XXX/g' > $tmpd/kconfig
# optimize some stuff (if given) if [ "$optimize_smp" = "y" ]; then cpus=$(cat /proc/cpuinfo | grep -q -c 'processor[[:space:]]*:') if [ "$cpus" = 1 ]; then kconfig_no CONFIG_SMP else kconfig_yes CONFIG_SMP fi fi if [ "$subarch" = "i386" ]; then if [ "$optimize_memory" = "y" ]; then mem=$(free | grep 'Mem:' | awk '{print $2}') if [ $mem -gt 4194304 ]; then kconfig_yes CONFIG_HIGHMEM64G kconfig_no CONFIG_HIGHMEM4G kconfig_no CONFIG_NOHIGHMEM kconfig_yes CONFIG_X86_PAE elif [ $mem -gt 1048576 ]; then kconfig_no CONFIG_HIGHMEM64G kconfig_yes CONFIG_HIGHMEM4G kconfig_no CONFIG_NOHIGHMEM kconfig_no CONFIG_X86_PAE else kconfig_no CONFIG_HIGHMEM64G kconfig_no CONFIG_HIGHMEM4G kconfig_yes CONFIG_NOHIGHMEM kconfig_no CONFIG_X86_PAE fi fi fi
# rewrite the local version if [ -n "$localversion" ]; then sed -i -e's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION="'$localversion'"/' $tmpd/kconfig fi # find kconfig for each module rm -f $noconfigs $okconfigs list_modules | while read m; do echo -n "Checking module $m..." cfgs=$(find_kconfig $m) if [ -z "$cfgs" ]; then echo -n "N/A" echo $m >> $tmpd/conf-no else echo -n "$m" >> $tmpd/conf-ok for c in $cfgs; do echo -n " $c" echo -n " $c" >> $tmpd/conf-ok kconfig_mod $c done echo >> $tmpd/conf-ok fi echo done
# if the previously =m doesn't enable any modules, it's a virtual one, which # we should keep =m for c in $(grep '^#.*XXX$' $tmpd/kconfig | sed -e's/^#.*\(CONFIG.*\) XXX/\1/g'); do grep -q 'obj-\$('$c').*=.*\.o' $tmpd/makefiles || kconfig_mod $c done
# replace XXX to standard sed -i -e's/^\(#.*\) XXX/\1 is not set/g' $tmpd/kconfig
# reconfigure echo "Reconfiguring via make silentconfig" cd $curdir cp $tmpd/kconfig .config
if [ -n "$kroot" ]; then make_args="-C $kroot O=$curdir" else make_args= fi make $make_args silentoldconfig ARCH=$arch
if [ -n "$outputfile" ]; then echo "Copying the result to $outputfile" cp .config $outputfile fi
echo echo "*** FINISHED ***" echo if [ -s $tmpd/conf-no ]; then echo "Modules not configured:" cat $tmpd/conf-no fi
if [ -s $tmpd/conf-ok ]; then while read m cfgs; do found= for c in $cfgs; do if grep -q $c=m .config; then found=y break fi done if [ -z "$found" ]; then echo "Not enabled: module $m with config $cfgs" fi done < $tmpd/conf-ok fi
exit 0
| |