From 62390fddc753e04aa12655d073572f9c39af3874 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 28 Nov 2014 16:49:46 -0600 Subject: Add "make change" target to build the big toybox binary as a bunch of little ones (in the "change" subdirectory), and tweak scripts/make.sh to avoid redundant work when rebuilding. --- scripts/make.sh | 200 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 120 insertions(+), 80 deletions(-) (limited to 'scripts') diff --git a/scripts/make.sh b/scripts/make.sh index dab5206..2274d68 100755 --- a/scripts/make.sh +++ b/scripts/make.sh @@ -15,13 +15,95 @@ source ./configure CPUS=$((($(echo /sys/devices/system/cpu/cpu[0-9]* | wc -w)*3)/2)) # Respond to V= by echoing command lines as well as running them +DOTPROG= do_loudly() { - [ ! -z "$V" ] && echo "$@" + [ ! -z "$V" ] && echo "$@" || echo -n "$DOTPROG" "$@" } +# Is anything under directory $2 newer than file $1 +isnewer() +{ + [ ! -z "$(find "$2" -newer "$1" 2>/dev/null || echo yes)" ] +} + +echo "Generate headers from toys/*/*.c..." + mkdir -p generated + +if isnewer generated/Config.in toys +then + echo "Extract configuration information from toys/*.c files..." + scripts/genconfig.sh +fi + +# Create a list of all the commands toybox can provide. Note that the first +# entry is out of order on purpose (the toybox multiplexer command must be the +# first element of the array). The rest must be sorted in alphabetical order +# for fast binary search. + +if isnewer generated/newtoys.h toys +then + echo -n "generated/newtoys.h " + + echo "USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT))" > generated/newtoys.h + sed -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \ + | sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -k 1,1 \ + | sed 's/[^ ]* //' >> generated/newtoys.h && + sed -n -e 's/.*(NEWTOY(\([^,]*\), *\(\("[^"]*"[^,]*\)*\),.*/#define OPTSTR_\1\t\2/p' \ + generated/newtoys.h > generated/oldtoys.h || exit 1 +fi + +[ ! -z "$V" ] && echo "Which C files to build..." + +# Extract a list of toys/*/*.c files to compile from the data in $KCONFIG_CONFIG +TOYFILES="$(egrep -l "TOY[(]($(sed -n 's/^CONFIG_\([^=]*\)=.*/\1/p' "$KCONFIG_CONFIG" | xargs | tr ' [A-Z]' '|[a-z]'))[ ,]" toys/*/*.c)" +BUILD="$(echo ${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE)" +FILES="$(echo lib/*.c main.c $TOYFILES)" + +genbuildsh() +{ + # Write a canned build line for use on crippled build machines. + + echo "#!/bin/sh" + echo + echo "BUILD=\"$BUILD\"" + echo + echo "FILES=\"$FILES\"" + echo + echo "LINK=\"$LINK\"" + echo + echo + echo '$BUILD $FILES $LINK' +} + +if ! cmp -s <(genbuildsh | head -n 3) \ + <(head -n 3 generated/build.sh 2>/dev/null) +then + echo -n "Library probe" + + # We trust --as-needed to remove each library if we don't use any symbols + # out of it, this loop is because the compiler has no way to ignore a library + # that doesn't exist, so we have to detect and skip nonexistent libraries + # for it. + + > generated/optlibs.dat + for i in util crypt m resolv + do + echo "int main(int argc, char *argv[]) {return 0;}" | \ + ${CROSS_COMPILE}${CC} $CFLAGS -xc - -o /dev/null -Wl,--as-needed -l$i > /dev/null 2>/dev/null && + echo -l$i >> generated/optlibs.dat + echo -n . + done + echo +fi + +# LINK needs optlibs.dat, above + +LINK="$(echo $LDOPTIMIZE -o toybox_unstripped -Wl,--as-needed $(cat generated/optlibs.dat))" +genbuildsh > generated/build.sh && chmod +x generated/build.sh || exit 1 + echo "Make generated/config.h from $KCONFIG_CONFIG." # This long and roundabout sed invocation is to make old versions of sed happy. @@ -48,27 +130,10 @@ sed -n \ -e 's/.*/#define USE_&(...) __VA_ARGS__/p' \ $KCONFIG_CONFIG > generated/config.h || exit 1 - -echo "Extract configuration information from toys/*.c files..." -scripts/genconfig.sh - -echo "Generate headers from toys/*/*.c..." - -# Create a list of all the commands toybox can provide. Note that the first -# entry is out of order on purpose (the toybox multiplexer command must be the -# first element of the array). The rest must be sorted in alphabetical order -# for fast binary search. - -echo -n "generated/newtoys.h " - -echo "USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT))" > generated/newtoys.h -sed -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \ - | sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -k 1,1 \ - | sed 's/[^ ]* //' >> generated/newtoys.h -sed -n -e 's/.*(NEWTOY(\([^,]*\), *\(\("[^"]*"[^,]*\)*\),.*/#define OPTSTR_\1\t\2/p' \ - generated/newtoys.h > generated/oldtoys.h - -do_loudly $HOSTCC scripts/mkflags.c -o generated/mkflags || exit 1 +if [ generated/mkflags -ot scripts/mkflags.c ] +then + do_loudly $HOSTCC scripts/mkflags.c -o generated/mkflags || exit 1 +fi echo -n "generated/flags.h " @@ -126,80 +191,55 @@ function getglobals() done } -echo -n "generated/globals.h " - -GLOBSTRUCT="$(getglobals)" -( - echo "$GLOBSTRUCT" - echo - echo "extern union global_union {" - echo "$GLOBSTRUCT" | sed -n 's/struct \(.*\)_data {/ struct \1_data \1;/p' - echo "} this;" -) > generated/globals.h +if isnewer generated/globals.h toys +then + echo -n "generated/globals.h " + GLOBSTRUCT="$(getglobals)" + ( + echo "$GLOBSTRUCT" + echo + echo "extern union global_union {" + echo "$GLOBSTRUCT" | \ + sed -n 's/struct \(.*\)_data {/ struct \1_data \1;/p' + echo "} this;" + ) > generated/globals.h +fi echo "generated/help.h" -do_loudly $HOSTCC scripts/config2help.c -I . lib/xwrap.c lib/llist.c lib/lib.c \ - -o generated/config2help && \ +if [ generated/config2help -ot scripts/config2help.c ] +then + do_loudly $HOSTCC scripts/config2help.c -I . lib/xwrap.c lib/llist.c \ + lib/lib.c -o generated/config2help || exit 1 +fi generated/config2help Config.in $KCONFIG_CONFIG > generated/help.h || exit 1 -echo -n "Library probe" - -# We trust --as-needed to remove each library if we don't use any symbols -# out of it, this loop is because the compiler has no way to ignore a library -# that doesn't exist, so we have to detect and skip nonexistent libraries -# for it. - -> generated/optlibs.dat -for i in util crypt m resolv -do - echo "int main(int argc, char *argv[]) {return 0;}" | \ - ${CROSS_COMPILE}${CC} $CFLAGS -xc - -o /dev/null -Wl,--as-needed -l$i > /dev/null 2>/dev/null && - echo -l$i >> generated/optlibs.dat - echo -n . -done -echo +[ ! -z "$NOBUILD" ] && exit 0 echo -n "Compile toybox" [ ! -z "$V" ] && echo - -# Extract a list of toys/*/*.c files to compile from the data in $KCONFIG_CONFIG - -TOYFILES="$(egrep -l "TOY[(]($(sed -n 's/^CONFIG_\([^=]*\)=.*/\1/p' "$KCONFIG_CONFIG" | xargs | tr ' [A-Z]' '|[a-z]'))[ ,]" toys/*/*.c)" - -do_loudly() -{ - [ ! -z "$V" ] && echo "$@" || echo -n . - "$@" -} - -BUILD="$(echo ${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE)" -FILES="$(echo lib/*.c main.c $TOYFILES)" -LINK="$(echo $LDOPTIMIZE -o toybox_unstripped -Wl,--as-needed $(cat generated/optlibs.dat))" +DOTPROG=. # This is a parallel version of: do_loudly $BUILD $FILES $LINK || exit 1 -# Write a canned build line for use on crippled build machines. -( - echo "#!/bin/sh" - echo - echo "BUILD=\"$BUILD\"" - echo - echo "LINK=\"$LINK\"" - echo - echo "FILES=\"$FILES\"" - echo - echo '$BUILD $FILES $LINK' -) > generated/build.sh && chmod +x generated/build.sh || echo 1 - -rm -rf generated/obj && mkdir -p generated/obj || exit 1 +X="$(ls -1t generated/obj/* 2>/dev/null | tail -n 1)" +if [ ! -e "$X" ] || [ ! -z "$(find toys -name "*.h" -newer "$X")" ] +then + rm -rf generated/obj && mkdir -p generated/obj || exit 1 +else + rm -f generated/obj/{main,lib_help}.o || exit 1 +fi PENDING= +LFILES= for i in $FILES do # build each generated/obj/*.o file in parallel X=${i/lib\//lib_} X=${X##*/} - do_loudly $BUILD -c $i -o generated/obj/${X%%.c}.o & + OUT="generated/obj/${X%%.c}.o" + LFILES="$LFILES $OUT" + [ "$OUT" -nt "$i" ] && continue + do_loudly $BUILD -c $i -o $OUT & # ratelimit to $CPUS many parallel jobs, detecting errors @@ -220,7 +260,7 @@ do wait $i || exit 1 done -do_loudly $BUILD generated/obj/*.o $LINK || exit 1 +do_loudly $BUILD $LFILES $LINK || exit 1 do_loudly ${CROSS_COMPILE}${STRIP} toybox_unstripped -o toybox || exit 1 # gcc 4.4's strip command is buggy, and doesn't set the executable bit on # its output the way SUSv4 suggests it do so. -- cgit v1.2.3