diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/change.sh | 10 | ||||
-rwxr-xr-x | scripts/genconfig.sh | 91 | ||||
-rwxr-xr-x | scripts/git-static-index.sh | 28 | ||||
-rw-r--r-- | scripts/help.txt | 3 | ||||
-rwxr-xr-x | scripts/install.sh | 9 | ||||
-rwxr-xr-x | scripts/make.sh | 247 | ||||
-rwxr-xr-x | scripts/mcm-buildall.sh | 13 | ||||
-rw-r--r-- | scripts/mkflags.c | 34 | ||||
-rwxr-xr-x | scripts/mkroot.sh | 293 | ||||
-rwxr-xr-x | scripts/mkstatus.py | 2 | ||||
-rw-r--r-- | scripts/portability.sh | 22 | ||||
-rwxr-xr-x | scripts/record-commands | 42 | ||||
-rwxr-xr-x | scripts/root/dropbear | 58 | ||||
-rwxr-xr-x | scripts/root/plumbing | 45 | ||||
-rw-r--r-- | scripts/runtest.sh | 224 | ||||
-rwxr-xr-x | scripts/single.sh | 10 | ||||
-rwxr-xr-x | scripts/test.sh | 20 |
17 files changed, 311 insertions, 840 deletions
diff --git a/scripts/change.sh b/scripts/change.sh index 74889aa7..dda5ee14 100755 --- a/scripts/change.sh +++ b/scripts/change.sh @@ -9,15 +9,11 @@ ${HOSTCC:-cc} -I . scripts/install.c -o "$UNSTRIPPED"/instlist && export PREFIX=${PREFIX:-change/} && mkdir -p "$PREFIX" || exit 1 -# Build all the commands standalone except: - -# sh - shell builtins like "cd" and "exit" need the multiplexer -# help - needs to know what other commands are enabled (use command --help) - -for i in $("$UNSTRIPPED"/instlist | egrep -vw "sh|help") +# Build all the commands standalone +for i in $("$UNSTRIPPED"/instlist) do echo -n " $i" && - scripts/single.sh $i > /dev/null 2>$PREFIX/${i}.bad && + scripts/single.sh $i &>$PREFIX/${i}.bad && rm $PREFIX/${i}.bad || echo -n '*' done echo diff --git a/scripts/genconfig.sh b/scripts/genconfig.sh index 034aa376..52a9c259 100755 --- a/scripts/genconfig.sh +++ b/scripts/genconfig.sh @@ -1,7 +1,7 @@ #!/bin/bash # This has to be a separate file from scripts/make.sh so it can be called -# before menuconfig. (It's called again from scripts/make.sh just to be sure.) +# before menuconfig. (It's called again from scripts/make.sh just to be sure.) source scripts/portability.sh @@ -18,55 +18,11 @@ probesymbol() { probecc "${@:2}" 2>/dev/null && DEFAULT=y || DEFAULT=n rm a.out 2>/dev/null - echo -e "config $1\n\tbool" || exit 1 - echo -e "\tdefault $DEFAULT\n" || exit 1 + echo -e "config $1\n\tbool\n\tdefault $DEFAULT\n" || exit 1 } probeconfig() { - # Probe for container support on target - probesymbol TOYBOX_CONTAINER << EOF - #include <stdio.h> - #include <sys/syscall.h> - #include <linux/sched.h> - int x=CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET; - - int main(int argc, char *argv[]){printf("%d", x+SYS_unshare+ SYS_setns);} -EOF - - probesymbol TOYBOX_FIFREEZE -c << EOF - #include <linux/fs.h> - #ifndef FIFREEZE - #error nope - #endif -EOF - - # Work around some uClibc limitations - probesymbol TOYBOX_ICONV -c << EOF - #include "iconv.h" -EOF - - # Android and some other platforms miss utmpx - probesymbol TOYBOX_UTMPX -c << EOF - #include <utmpx.h> - #ifndef BOOT_TIME - #error nope - #endif - int main(int argc, char *argv[]) { - struct utmpx *a; - if (0 != (a = getutxent())) return 0; - return 1; - } -EOF - - # Android is missing shadow.h - probesymbol TOYBOX_SHADOW -c << EOF - #include <shadow.h> - int main(int argc, char *argv[]) { - struct spwd *a = getspnam("root"); return 0; - } -EOF - # Some commands are android-specific probesymbol TOYBOX_ON_ANDROID -c << EOF #ifndef __ANDROID__ @@ -74,45 +30,12 @@ EOF #endif EOF - probesymbol TOYBOX_ANDROID_SCHEDPOLICY << EOF - #include <processgroup/sched_policy.h> - - int main(int argc,char *argv[]) { get_sched_policy_name(0); } -EOF - # nommu support probesymbol TOYBOX_FORK << EOF #include <unistd.h> int main(int argc, char *argv[]) { return fork(); } EOF echo -e '\tdepends on !TOYBOX_FORCE_NOMMU' - - probesymbol TOYBOX_PRLIMIT << EOF - #include <sys/types.h> - #include <sys/time.h> - #include <sys/resource.h> - int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, - struct rlimit *old_limit); - int main(int argc, char *argv[]) { prlimit(0, 0, 0, 0); } -EOF - - probesymbol TOYBOX_GETRANDOM << EOF - #include <sys/random.h> - int main(void) { char buf[100]; getrandom(buf, 100, 0); } -EOF - - # glibc requires #define GNU to get the wrapper for this Linux system call, - # so just use syscall(). - probesymbol TOYBOX_COPYFILERANGE << EOF - #include <sys/syscall.h> - #include <unistd.h> - int main(void) { syscall(__NR_copy_file_range, 0, 0, 1, 0, 123, 0); } -EOF - probesymbol TOYBOX_HASTIMERS << EOF - #include <signal.h> - #include <time.h> - int main(void) {void *x=0;timer_create(CLOCK_MONOTONIC,x,x);} -EOF } genconfig() @@ -150,8 +73,7 @@ toys() $SED -En 's/([^:]*):.*(OLD|NEW)TOY\( *([a-zA-Z][^,]*) *,.*/\1:\3/p' } -WORKING= -PENDING= +WORKING= PENDING= EXAMPLE= toys toys/*/*.c | ( while IFS=":" read FILE NAME do @@ -160,12 +82,13 @@ do [ "$NAME" == sh ] && FILE="toys/*/*.c" echo -e "$NAME: $FILE *.[ch] lib/*.[ch]\n\tscripts/single.sh $NAME\n" echo -e "test_$NAME:\n\tscripts/test.sh $NAME\n" - [ "${FILE/pending//}" != "$FILE" ] && - PENDING="$PENDING $NAME" || + [ "${FILE/example//}" != "$FILE" ] && EXAMPLE="$EXAMPLE $NAME" || + [ "${FILE/pending//}" != "$FILE" ] && PENDING="$PENDING $NAME" || WORKING="$WORKING $NAME" done && echo -e "clean::\n\t@rm -f $WORKING $PENDING" && echo -e "list:\n\t@echo $(echo $WORKING | tr ' ' '\n' | sort | xargs)" && -echo -e "list_pending:\n\t@echo $(echo $PENDING | tr ' ' '\n' | sort | xargs)" && +echo -e "list_example:\n\t@echo $(echo $EXAMPLE | tr ' ' '\n' | sort | xargs)"&& +echo -e "list_pending:\n\t@echo $(echo $PENDING | tr ' ' '\n' | sort | xargs)"&& echo -e ".PHONY: $WORKING $PENDING" | $SED 's/ \([^ ]\)/ test_\1/g' ) > .singlemake diff --git a/scripts/git-static-index.sh b/scripts/git-static-index.sh new file mode 100755 index 00000000..fb9ac4e5 --- /dev/null +++ b/scripts/git-static-index.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Create very basic index.html and commit links for a static git archive + +mkdir -p commit +git log --pretty=%H | while read i +do + [ -e commit/$i ] && break + git format-patch -1 --stdout $i > commit/$i + ln -sf $i commit/${i::12} +done + +echo '<html><body><font face=monospace><table border=1 cellpadding=2>' +echo '<tr valign=top><td>commit</td><td>author</td><td>date</td><td>description</td></tr>' +git log --pretty='%H%n%an<%ae>%n%ad%n%s' --date=format:'%r<br />%d-%m-%Y' | while read HASH +do + HASH="${HASH::12}" + read AUTHOR + AUTHOR1="${AUTHOR/<*/}" + AUTHOR1="${AUTHOR1::17}" + AUTHOR2="<${AUTHOR/*</}" + AUTHOR2="${AUTHOR2::20}" + read DATE + DATE="${DATE/ / }" + read DESC + echo "<tr valign=top><td><a href=commit/$HASH>$HASH</a></td><td>$AUTHOR1<br />$AUTHOR2</td><td>$DATE</td><td>$DESC</td></tr>" +done +echo "</table></body></html>" diff --git a/scripts/help.txt b/scripts/help.txt index d369e47a..feca0a8d 100644 --- a/scripts/help.txt +++ b/scripts/help.txt @@ -1,6 +1,7 @@ toybox - Build toybox. COMMANDNAME - Build individual toybox command as a standalone binary. list - List COMMANDNAMEs you can build standalone. + list_example - List example commands (often used by the test suite) list_pending - List unfinished COMMANDNAMEs out of toys/pending. change - Build each command standalone under change/. baseline - Create toybox_old for use by bloatcheck. @@ -22,6 +23,6 @@ LINUX= build kernel from this source, configured for qemu run_root - boot toyroot under qemu, I.E. cd root/$CROSS && ./qemu-*.sh -example: make defconfig toybox install CFLAGS="--static" CROSS_COMPILE=armv5l- +example: make defconfig toybox install LDFLAGS="--static" CROSS_COMPILE=armv5l- or : make root run_root CROSS=sh4 LINUX=~/linux diff --git a/scripts/install.sh b/scripts/install.sh index 842ff9b0..38d9dcec 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -31,7 +31,6 @@ done echo "Compile instlist..." -NOBUILD=1 scripts/make.sh $DEBUG $HOSTCC -I . scripts/install.c -o "$UNSTRIPPED"/instlist || exit 1 COMMANDS="$("$UNSTRIPPED"/instlist $LONG_PATH)" @@ -106,11 +105,9 @@ done # The following are commands toybox should provide, but doesn't yet. # For now symlink the host version. This list must go away by 1.0. -PENDING="dd diff expr git tr vi wget bash sh xzcat bc ar gzip ftpd less awk unxz bison flex make nm" - -# "gcc" can go away if the kernel guys merge my patch: -# http://lkml.iu.edu/hypermail/linux/kernel/2202.0/01505.html -TOOLCHAIN="as cc ld gcc objdump" +PENDING="expr git tr bash sh gzip awk bison flex make" +TOOLCHAIN="as cc ld objdump" +TOOLCHAIN+="bc gcc" # both patched out but not in vanilla yet # Tools needed to build packages for i in $TOOLCHAIN $PENDING $HOST_EXTRA diff --git a/scripts/make.sh b/scripts/make.sh index b7bb6930..9de74192 100755 --- a/scripts/make.sh +++ b/scripts/make.sh @@ -1,83 +1,105 @@ #!/bin/bash # Grab default values for $CFLAGS and such. - set -o pipefail source scripts/portability.sh -# Default to running one more parallel cc instance than we have processors -: ${CPUS:=$(($(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null)+1))} +# Shell functions called by the build + +DASHN=-n +true & wait -n 2>/dev/null || { wait; unset DASHN; } +ratelimit() +{ + if [ "$#" -eq 0 ] + then + [ -z "$DASHN" ] && PIDS="$PIDS$! " + [ $((++COUNT)) -lt $CPUS ] && return 0 + fi + ((--COUNT)) + if [ -n "$DASHN" ] + then + wait -n + DONE=$(($DONE+$?)) + else + # MacOS uses an ancient version of bash which hasn't got "wait -n", and + # wait without arguments always returns 0 instead of process exit code. + # This keeps $CPUS less busy when jobs finish out of order. + wait ${PIDS%% *} + DONE=$(($DONE+$?)) + PIDS=${PIDS#* } + fi + + return $DONE +} # Respond to V= by echoing command lines as well as running them -DOTPROG= do_loudly() { - [ ! -z "$V" ] && echo "$@" || echo -n "$DOTPROG" + { [ -n "$V" ] && echo "$@" || echo -n "$DOTPROG" ; } >&2 "$@" } -# Is anything under directory $2 newer than file $1 +# Is anything under directory $2 newer than generated/$1 (or does it not exist)? isnewer() { - CHECK="$1" - shift - [ ! -z "$(find "$@" -newer "$CHECK" 2>/dev/null || echo yes)" ] + [ -e "$GENDIR/$1" ] && [ -z "$(find "${@:2}" -newer "$GENDIR/$1")" ] && + return 1 + echo -n "${DIDNEWER:-$GENDIR/{}$1" + DIDNEWER=, } -echo "Generate headers from toys/*/*.c..." - -mkdir -p "$UNSTRIPPED" - -if isnewer "$GENDIR"/Config.in toys || isnewer "$GENDIR"/Config.in Config.in -then - echo "Extract configuration information from toys/*.c files..." - scripts/genconfig.sh -fi +# Build a tool that runs on the host +hostcomp() +{ + if [ ! -f "$UNSTRIPPED"/$1 ] || [ "$UNSTRIPPED"/$1 -ot scripts/$1.c ] + then + do_loudly $HOSTCC scripts/$1.c -o "$UNSTRIPPED"/$1 || exit 1 + 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. +# Set/record build environment information +compflags() +{ + [ -z "$VERSION" ] && [ -d ".git" ] && [ -n "$(which git 2>/dev/null)" ] && + VERSION="-DTOYBOX_VERSION=\"$(git describe --tags --abbrev=12 2>/dev/null)\"" -if isnewer "$GENDIR"/newtoys.h toys -then - echo -n "$GENDIR/newtoys.h " + # VERSION and LIBRARIES volatile, changing either does not require a rebuild + echo '#!/bin/sh' + echo + echo "VERSION='$VERSION'" + echo "LIBRARIES='$(xargs 2>/dev/null < "$GENDIR/optlibs.dat")'" + echo "BUILD='${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE '\"\$VERSION\"" + echo "LINK='$LDOPTIMIZE $LDFLAGS '\"\$LIBRARIES\"" + echo "PATH='$PATH'" + echo "# Built from $KCONFIG_CONFIG" + echo +} - echo "USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT|TOYFLAG_NOHELP))" \ - > "$GENDIR"/newtoys.h - $SED -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \ - | $SED 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -s -k 1,1 \ - | $SED 's/[^ ]* //' >> "$GENDIR"/newtoys.h - [ $? -ne 0 ] && exit 1 -fi +# Make sure rm -rf isn't gonna go funny +B="$(readlink -f "$PWD")/" A="$(readlink -f "$GENDIR")" A="${A%/}"/ +[ "$A" == "${B::${#A}}" ] && + { echo "\$GENDIR=$GENDIR cannot include \$PWD=$PWD"; exit 1; } +unset A B DOTPROG DIDNEWER -[ ! -z "$V" ] && echo "Which C files to build..." +# Force full rebuild if our compiler/linker options changed +cmp -s <(compflags|sed '5,8!d') <($SED '5,8!d' "$GENDIR"/build.sh 2>/dev/null)|| + rm -rf "$GENDIR"/* # Keep symlink, delete contents +mkdir -p "$UNSTRIPPED" "$(dirname $OUTNAME)" || exit 1 # Extract a list of toys/*/*.c files to compile from the data in $KCONFIG_CONFIG # (First command names, then filenames with relevant {NEW,OLD}TOY() macro.) -[ -d ".git" ] && [ ! -z "$(which git 2>/dev/null)" ] && - GITHASH="-DTOYBOX_VERSION=\"$(git describe --tags --abbrev=12 2>/dev/null)\"" +[ -n "$V" ] && echo -e "\nWhich C files to build..." TOYFILES="$($SED -n 's/^CONFIG_\([^=]*\)=.*/\1/p' "$KCONFIG_CONFIG" | xargs | tr ' [A-Z]' '|[a-z]')" TOYFILES="main.c $(egrep -l "TOY[(]($TOYFILES)[ ,]" toys/*/*.c | xargs)" -BUILD="$(echo ${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE $GITHASH)" if [ "${TOYFILES/pending//}" != "$TOYFILES" ] then echo -e "\n\033[1;31mwarning: using unfinished code from toys/pending\033[0m" fi -genbuildsh() -{ - # Write a canned build line for use on crippled build machines. - - LLINK="$(echo $LDOPTIMIZE $LDFLAGS $(cat "$GENDIR"/optlibs.dat))" - echo -e "#!/bin/sh\n\nPATH='$PATH'\nBUILD='$BUILD'\nLINK='$LLINK'\n" - echo -e "\$BUILD lib/*.c $TOYFILES \$LINK -o $OUTNAME" -} - -if ! cmp -s <(genbuildsh 2>/dev/null | head -n 5) \ - <(head -n 5 "$GENDIR"/build.sh 2>/dev/null | $SED '5s/ -o .*//') +# Probe library list if our compiler/linker options changed +if [ ! -e "$GENDIR"/optlibs.dat ] then echo -n "Library probe" @@ -85,25 +107,53 @@ then # compiler has no way to ignore a library that doesn't exist, so detect # and skip nonexistent libraries for it. - > "$GENDIR"/optlibs.dat + > "$GENDIR"/optlibs.new + [ -z "$V" ] && X=/dev/null || X=/dev/stderr for i in util crypt m resolv selinux smack attr crypto z log iconv tls ssl do - echo "int main(int argc, char *argv[]) {return 0;}" | \ - ${CROSS_COMPILE}${CC} $CFLAGS $LDFLAGS -xc - -o "$GENDIR"/libprobe -l$i > /dev/null 2>/dev/null && - echo -l$i >> "$GENDIR"/optlibs.dat - echo -n . + do_loudly ${CROSS_COMPILE}${CC} $CFLAGS $LDFLAGS -xc - -l$i >>$X 2>&1 \ + -o "$UNSTRIPPED"/libprobe <<<"int main(int argc,char*argv[]){return 0;}"&& + do_loudly echo -n ' '-l$i >> "$GENDIR"/optlibs.new done - rm -f "$GENDIR"/libprobe + unset X + rm -f "$UNSTRIPPED"/libprobe + mv "$GENDIR"/optlibs.{new,dat} || exit 1 echo fi -genbuildsh > "$GENDIR"/build.sh && chmod +x "$GENDIR"/build.sh || exit 1 +# Write build variables (and set them locally), then append build invocation. +compflags > "$GENDIR"/build.sh && source "$GENDIR/build.sh" && + echo -e "\$BUILD lib/*.c $TOYFILES \$LINK -o $OUTNAME" >> "$GENDIR"/build.sh&& + chmod +x "$GENDIR"/build.sh || exit 1 -#TODO: "make $SED && make" doesn't regenerate config.h because diff .config -if true #isnewer "$GENDIR"/config.h "$KCONFIG_CONFIG" +if isnewer Config.in toys || isnewer Config.in Config.in then - echo "Make $GENDIR/config.h from $KCONFIG_CONFIG." + scripts/genconfig.sh +fi + +# Does .config need dependency recalculation because toolchain changed? +A="$($SED -n '/^config .*$/h;s/default \(.\)/\1/;T;H;g;s/config \([^\n]*\)[^yn]*\(.\)/\1=\2/p' "$GENDIR"/Config.probed | sort)" +B="$(egrep "^CONFIG_($(echo "$A" | sed 's/=[yn]//' | xargs | tr ' ' '|'))=" "$KCONFIG_CONFIG" | $SED 's/^CONFIG_//' | sort)" +A="$(echo "$A" | grep -v =n)" +[ "$A" != "$B" ] && + { echo -e "\nWarning: Config.probed changed, run 'make oldconfig'" >&2; } +unset A B + +# Create a list of all the commands toybox can provide. +if isnewer newtoys.h toys +then + # The multiplexer is the first element in the array + echo "USE_TOYBOX(NEWTOY(toybox, 0, TOYFLAG_STAYROOT|TOYFLAG_NOHELP))" \ + > "$GENDIR"/newtoys.h + # Sort rest by name for binary search (copy name to front, sort, remove copy) + $SED -n 's/^\(USE_[^(]*(.*TOY(\)\([^,]*\)\(,.*\)/\2 \1\2\3/p' toys/*/*.c \ + | sort -s -k 1,1 | $SED 's/[^ ]* //' >> "$GENDIR"/newtoys.h + [ $? -ne 0 ] && exit 1 +fi +#TODO: "make $SED && make" doesn't regenerate config.h because diff .config +if true #isnewer config.h "$KCONFIG_CONFIG" +then # This long and roundabout sed invocation is to make old versions of sed # happy. New ones have '\n' so can replace one line with two without all # the branches and tedious mucking about with hyperspace. @@ -130,20 +180,14 @@ then $KCONFIG_CONFIG > "$GENDIR"/config.h || exit 1 fi -if [ ! -f "$GENDIR"/mkflags ] || [ "$GENDIR"/mkflags -ot scripts/mkflags.c ] -then - do_loudly $HOSTCC scripts/mkflags.c -o "$UNSTRIPPED"/mkflags || exit 1 -fi - # Process config.h and newtoys.h to generate FLAG_x macros. Note we must # always #define the relevant macro, even when it's disabled, because we # allow multiple NEWTOY() in the same C file. (When disabled the FLAG is 0, # so flags&0 becomes a constant 0 allowing dead code elimination.) -if isnewer "$GENDIR"/flags.h toys "$KCONFIG_CONFIG" +hostcomp mkflags +if isnewer flags.h toys "$KCONFIG_CONFIG" then - echo -n "$GENDIR/flags.h " - # Parse files through C preprocessor twice, once to get flags for current # .config and once to get flags for allyesconfig for I in A B @@ -187,18 +231,16 @@ function getglobals() { for i in toys/*/*.c do - # alas basename -s isn't in posix yet. - NAME="$(echo $i | $SED 's@.*/\(.*\)\.c@\1@')" + NAME=${i##*/} NAME=${NAME%\.c} DATA="$($SED -n -e '/^GLOBALS(/,/^)/b got;b;:got' \ -e 's/^GLOBALS(/_data {/' \ -e 's/^)/};/' -e 'p' $i)" - [ ! -z "$DATA" ] && echo -e "// $i\n\nstruct $NAME$DATA\n" + [ -n "$DATA" ] && echo -e "// $i\n\nstruct $NAME$DATA\n" done } -if isnewer "$GENDIR"/globals.h toys +if isnewer globals.h toys then - echo -n "$GENDIR/globals.h " GLOBSTRUCT="$(getglobals)" ( echo "$GLOBSTRUCT" @@ -210,53 +252,40 @@ then ) > "$GENDIR"/globals.h fi -if [ ! -f "$UNSTRIPPED"/mktags ] || [ "$UNSTRIPPED"/mktags -ot scripts/mktags.c ] -then - do_loudly $HOSTCC scripts/mktags.c -o "$UNSTRIPPED"/mktags || exit 1 -fi - -if isnewer "$GENDIR"/tags.h toys +hostcomp mktags +if isnewer tags.h toys then - echo -n "$GENDIR/tags.h " - $SED -n '/TAGGED_ARRAY(/,/^)/{s/.*TAGGED_ARRAY[(]\([^,]*\),/\1/;p}' \ toys/*/*.c lib/*.c | "$UNSTRIPPED"/mktags > "$GENDIR"/tags.h fi -if [ ! -f "$UNSTRIPPED"/config2help ] || [ "$UNSTRIPPED"/config2help -ot scripts/config2help.c ] +hostcomp config2help +if isnewer help.h "$GENDIR"/Config.in then - do_loudly $HOSTCC scripts/config2help.c -o "$UNSTRIPPED"/config2help || exit 1 -fi -if isnewer "$GENDIR"/help.h "$GENDIR"/Config.in -then - echo "$GENDIR/help.h" "$UNSTRIPPED"/config2help Config.in $KCONFIG_CONFIG > "$GENDIR"/help.h || exit 1 fi +[ -z "$DIDNEWER" ] || echo } -[ ! -z "$NOBUILD" ] && exit 0 +[ -n "$NOBUILD" ] && exit 0 -echo -n "Compile $OUTNAME" -[ ! -z "$V" ] && echo +echo "Compile $OUTNAME" DOTPROG=. -# This is a parallel version of: do_loudly $BUILD $FILES $LLINK || exit 1 +# This is a parallel version of: do_loudly $BUILD lib/*.c $TOYFILES $LINK -# Any headers newer than the oldest generated/obj file? +# Build all if oldest generated/obj file isn't newer than all header files. X="$(ls -1t "$GENDIR"/obj/* 2>/dev/null | tail -n 1)" -# TODO: redo this -if [ ! -e "$X" ] || [ ! -z "$(find toys -name "*.h" -newer "$X")" ] +if [ ! -e "$X" ] || [ -n "$(find toys -name "*.h" -newer "$X")" ] then rm -rf "$GENDIR"/obj && mkdir -p "$GENDIR"/obj || exit 1 else + # always redo toy_list[] and help_data[] rm -f "$GENDIR"/obj/main.o || exit 1 fi # build each generated/obj/*.o file in parallel -unset PENDING LNKFILES CLICK -DONE=0 -COUNT=0 - +PENDING= LNKFILES= CLICK= DONE=0 COUNT=0 for i in lib/*.c click $TOYFILES do [ "$i" == click ] && CLICK=1 && continue @@ -266,30 +295,25 @@ do OUT="$GENDIR/obj/${X%%.c}.o" LNKFILES="$LNKFILES $OUT" - # Library files don't need to be rebuilt if older than .config. - # ($TOYFILES contents can depend on CONFIG symbols, lib/*.c never should.) - + # Library files don't get rebuilt if older than .config, but commands do. [ "$OUT" -nt "$i" ] && [ -z "$CLICK" -o "$OUT" -nt "$KCONFIG_CONFIG" ] && continue do_loudly $BUILD -c $i -o $OUT & - # ratelimit to $CPUS many parallel jobs, detecting errors - [ $((++COUNT)) -ge $CPUS ] && { wait $DASHN; DONE=$?; : $((--COUNT)); } - [ $DONE -ne 0 ] && break + ratelimit || break done -# wait for all background jobs, detecting errors -while [ $((COUNT--)) -gt 0 ] +# wait for all background jobs, detecting errors +while [ "$COUNT" -gt 0 ] do - wait $DASHN; - DONE=$((DONE+$?)) + ratelimit done done [ $DONE -ne 0 ] && exit 1 UNSTRIPPED="$UNSTRIPPED/${OUTNAME/*\//}" -do_loudly $BUILD $LNKFILES $LLINK -o "$UNSTRIPPED" || exit 1 -if [ ! -z "$NOSTRIP" ] || +do_loudly $BUILD $LNKFILES $LINK -o "$UNSTRIPPED" || exit 1 +if [ -n "$NOSTRIP" ] || ! do_loudly ${CROSS_COMPILE}${STRIP} "$UNSTRIPPED" -o "$OUTNAME" then [ -z "$NOSTRIP" ] && echo "strip failed, using unstripped" @@ -297,10 +321,9 @@ then cp "$UNSTRIPPED" "$OUTNAME" || exit 1 fi -# 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. While we're at it, make sure -# we don't have the "w" bit set so things like bzip2's "cp -f" install don't -# overwrite our binary through the symlink. +# Remove write bit set so buggy installs (like bzip's) don't overwrite the +# multiplexer binary via truncate-and-write through a symlink. do_loudly chmod 555 "$OUTNAME" || exit 1 -echo +# Ensure make wrapper sees success return code +[ -z "$V" ] && echo >&2 || true diff --git a/scripts/mcm-buildall.sh b/scripts/mcm-buildall.sh index cac41372..11a10136 100755 --- a/scripts/mcm-buildall.sh +++ b/scripts/mcm-buildall.sh @@ -91,7 +91,11 @@ make_toolchain() # Prevent cross compiler reusing dynamically linked host build files for # $BOOTSTRAP arch - [ -z "$TYPE" ] && make clean + [ -z "$TYPE" ] && { + [ -e musl-git-master ] && mv musl-git-master keep-this-dir + make clean + [ -e keep-this-dir ] && mv keep-this-dir musl-git-master + } if [ "$TYPE" == native ] then @@ -138,13 +142,6 @@ fix_nommu() PP=patches/musl-"$(sed -n 's/MUSL_VER[ \t]*=[ \t]*//p' Makefile)" mkdir -p "$PP" && cat > "$PP"/0001-nommu.patch << 'EOF' ---- a/include/features.h -+++ b/include/features.h -@@ -3,2 +3,4 @@ - -+#define __MUSL__ 1 -+ - #if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) --- a/src/legacy/daemon.c +++ b/src/legacy/daemon.c @@ -17,3 +17,3 @@ diff --git a/scripts/mkflags.c b/scripts/mkflags.c index 6560db50..79cf1656 100644 --- a/scripts/mkflags.c +++ b/scripts/mkflags.c @@ -1,5 +1,5 @@ -// Take three word input lines on stdin and produce flag #defines to stdout. -// The three words on each input lnie are command name, option string with +// Read three word input lines from stdin and produce flag #defines to stdout. +// The three words on each input line are command name, option string with // current config, option string from allyesconfig. The three are space // separated and the last two are in double quotes. @@ -14,9 +14,8 @@ #include <ctype.h> struct flag { - struct flag *next; + struct flag *next, *lopt; char *command; - struct flag *lopt; }; int chrtype(char c) @@ -38,7 +37,7 @@ int chrtype(char c) char *mark_gaps(char *flags, char *all) { char *n, *new, c; - int bare = 2; + int bare = 1; // Shell feeds in " " for blank args, leading space not meaningful. while (isspace(*flags)) flags++; @@ -50,7 +49,6 @@ char *mark_gaps(char *flags, char *all) if (*all == '(') { int len = 0; - if (bare) bare = 1; while (all[len]) if (all[len++] == ')') break; if (strncmp(flags, all, len)) { // bare longopts need their own skip placeholders @@ -95,6 +93,10 @@ struct flag *digest(char *string) if (*string == '(') { struct flag *new = calloc(sizeof(struct flag), 1); + if (string[1]==')') { + fprintf(stderr, "empty () longopt in '%s'", err); + exit(1); + } new->command = ++string; // Attach longopt to previous short opt, if any. @@ -131,6 +133,10 @@ struct flag *digest(char *string) } else { struct flag *new = calloc(sizeof(struct flag), 1); + if (string[0]=='~' && string[1]!='(') { + fprintf(stderr, "~ without (longopt) in '%s'", err); + exit(1); + } new->command = string++; new->next = list; list = new; @@ -164,9 +170,8 @@ int main(int argc, char *argv[]) // See "intentionally crappy", above. if (!(out = outbuf)) return 1; - printf("#undef FORCED_FLAG\n#undef FORCED_FLAGLL\n" - "#ifdef FORCE_FLAGS\n#define FORCED_FLAG 1\n#define FORCED_FLAGLL 1ULL\n" - "#else\n#define FORCED_FLAG 0\n#define FORCED_FLAGLL 0LL\n#endif\n\n"); + printf("#undef FORCED_FLAG\n#ifdef FORCE_FLAGS\n#define FORCED_FLAG 1LL\n" + "#else\n#define FORCED_FLAG 0LL\n#endif\n\n"); for (;;) { struct flag *flist, *aflist, *offlist; @@ -208,7 +213,8 @@ int main(int argc, char *argv[]) while (offlist) { char *s = (char []){0, 0, 0, 0}; - if (!offlist->command) s = offlist->lopt->command; + if (!offlist->command || *offlist->command=='~') + s = offlist->lopt->command; else { *s = *offlist->command; if (127 < (unsigned char)*s) sprintf(s, "X%02X", 127&*s); @@ -223,11 +229,11 @@ int main(int argc, char *argv[]) out += strlen(out); while (aflist) { - char *llstr = bit>30 ? "LL" : "", *s = (char []){0, 0, 0, 0}; + char *s = (char []){0, 0, 0, 0}; int enabled = 0; // Output flag macro for bare longopts - if (!aflist->command) { + if (!aflist->command || *aflist->command=='~') { s = aflist->lopt->command; if (flist && flist->lopt && !strcmp(flist->lopt->command, aflist->lopt->command)) enabled++; @@ -238,8 +244,8 @@ int main(int argc, char *argv[]) if (flist && flist->command && *aflist->command == *flist->command) enabled++; } - out += sprintf(out, "#define FLAG_%s (%s%s<<%d)\n", - s, enabled ? "1" : "FORCED_FLAG", llstr, bit++); + out += sprintf(out, "#define FLAG_%s (%s<<%d)\n", + s, enabled ? "1LL" : "FORCED_FLAG", bit++); aflist = aflist->next; if (enabled) flist = flist->next; } diff --git a/scripts/mkroot.sh b/scripts/mkroot.sh index c099bec7..2ac634bc 100755 --- a/scripts/mkroot.sh +++ b/scripts/mkroot.sh @@ -1,292 +1 @@ -#!/bin/bash - -# ------------------------------ Part 1: Setup ------------------------------- - -# Clear environment variables by restarting script w/bare minimum passed through -[ -z "$NOCLEAR" ] && exec env -i NOCLEAR=1 HOME="$HOME" PATH="$PATH" \ - LINUX="$LINUX" CROSS="$CROSS" CROSS_COMPILE="$CROSS_COMPILE" "$0" "$@" - -# assign command line NAME=VALUE args to env vars, the rest are packages -for i in "$@"; do - [ "${i/=/}" != "$i" ] && export "$i" || { [ "$i" != -- ] && PKG="$PKG $i"; } -done - -# Set default directory locations (overrideable from command line) -: ${LOG:=${BUILD:=${TOP:=$PWD/root}/build}/log} ${AIRLOCK:=$BUILD/airlock} -: ${CCC:=$PWD/ccc} ${PKGDIR:=$PWD/scripts/root} - -# useful functions -announce() { echo -e "\033]2;$CROSS $*\007\n=== $*"; } -die() { echo "$@" >&2; exit 1; } - -# ----- Are we cross compiling (via CROSS_COMPILE= or CROSS=) - -if [ -n "$CROSS_COMPILE" ]; then - CROSS_COMPILE="$(realpath -s "$CROSS_COMPILE")" # airlock needs absolute path - [ -z "$CROSS" ] && CROSS=${CROSS_COMPILE/*\//} CROSS=${CROSS/-*/} - -elif [ -n "$CROSS" ]; then # CROSS=all/allnonstop/$ARCH else list known $ARCHes - [ ! -d "$CCC" ] && die "No ccc symlink to compiler directory." - TARGETS="$(ls "$CCC" | sed -n 's/-.*//p' | sort -u)" - - if [ "${CROSS::3}" == all ]; then # loop calling ourselves for each target - for i in $TARGETS; do - "$0" "$@" CROSS=$i || [ "$CROSS" == allnonstop ] || exit 1 - done; exit - - else # Find matching cross compiler under ccc/ else list available targets - CROSS_COMPILE="$(echo "$CCC/$CROSS"-*cross/bin/"$CROSS"*-cc)" # wildcard - [ ! -e "$CROSS_COMPILE" ] && echo $TARGETS && exit # list available targets - CROSS_COMPILE="${CROSS_COMPILE%cc}" # trim to prefix for cc/ld/as/nm/strip - fi -fi - -# Verify selected compiler works -${CROSS_COMPILE}cc --static -xc - -o /dev/null <<< "int main(void){return 0;}"|| - die "${CROSS_COMPILE}cc can't create static binaries" - -# When not cross compiling set CROSS=host. Create per-target output directory -: ${CROSS:=host} ${OUTPUT:=$TOP/$CROSS} - -# ----- Create hermetic build environment - -if [ -z "$NOAIRLOCK"] && [ -n "$CROSS_COMPILE" ]; then - # When cross compiling set host $PATH to binaries with known behavior by - # - building a host toybox later builds use as their command line - # - cherry-picking specific commands from old path via symlink - if [ ! -e "$AIRLOCK/toybox" ]; then - announce "airlock" && - PREFIX="$AIRLOCK" KCONFIG_CONFIG=.singleconfig_airlock CROSS_COMPILE= \ - make clean defconfig toybox install_airlock && # see scripts/install.sh - rm .singleconfig_airlock || exit 1 - fi - export PATH="$AIRLOCK" -fi - -# Create per-target work directories -MYBUILD="$BUILD/${CROSS}-tmp" && rm -rf "$MYBUILD" && -mkdir -p "$MYBUILD" "$OUTPUT" "$LOG" || exit 1 -[ -z "$ROOT" ] && ROOT="$OUTPUT/fs" && rm -rf "$ROOT" - -# ----- log build output - -# Install command line recording wrapper, logs all commands run from $PATH -if [ -z "$NOLOGPATH" ]; then - # Move cross compiler into $PATH so calls to it get logged - [ -n "$CROSS_COMPILE" ] && PATH="${CROSS_COMPILE%/*}:$PATH" && - CROSS_COMPILE=${CROSS_COMPILE##*/} - export WRAPDIR="$BUILD/record-commands" LOGPATH="$LOG/$CROSS-commands.txt" - rm -rf "$WRAPDIR" "$LOGPATH" generated/obj && - WRAPDIR="$WRAPDIR" CROSS_COMPILE= NOSTRIP=1 source scripts/record-commands || - exit 1 -fi - -# Start logging stdout/stderr -rm -f "$LOG/$CROSS".{n,y} || exit 1 -[ -z "$NOLOG" ] && exec > >(tee "$LOG/$CROSS.n") 2>&1 -echo "Building for $CROSS" - -# ---------------------- Part 2: Create root filesystem ----------------------- - -# ----- Create new root filesystem's directory layout. - -# FHS wants boot media opt srv usr/{local,share}, stuff under /var... -mkdir -p "$ROOT"/{dev,etc/rc,home,mnt,proc,root,sys,tmp/run,usr/{bin,sbin,lib},var} && -chmod a+rwxt "$ROOT"/tmp && ln -s usr/{bin,sbin,lib} tmp/run "$ROOT" || exit 1 - -# Write init script. Runs as pid 1 from initramfs to set up and hand off system. -cat > "$ROOT"/init << 'EOF' && -#!/bin/sh - -export HOME=/home PATH=/bin:/sbin - -if ! mountpoint -q dev; then - mount -t devtmpfs dev dev - [ $$ -eq 1 ] && exec 0<>/dev/console 1>&0 2>&1 - for i in ,fd /0,stdin /1,stdout /2,stderr - do ln -sf /proc/self/fd${i/,*/} dev/${i/*,/}; done - mkdir dev/shm - chmod +t /dev/shm -fi -mountpoint -q dev/pts || { mkdir dev/pts && mount -t devpts dev/pts dev/pts; } -mountpoint -q proc || mount -t proc proc proc -mountpoint -q sys || mount -t sysfs sys sys -echo 0 99999 > /proc/sys/net/ipv4/ping_group_range - -if [ $$ -eq 1 ]; then # Setup networking for QEMU (needs /proc) - ifconfig lo 127.0.0.1 - ifconfig eth0 10.0.2.15 - route add default gw 10.0.2.2 - [ "$(date +%s)" -lt 1000 ] && timeout 2 sntp -sq 10.0.2.2 # Ask host - [ "$(date +%s)" -lt 10000000 ] && sntp -sq time.google.com - - # Run package scripts (if any) - for i in $(ls -1 /etc/rc 2>/dev/null | sort); do . /etc/rc/"$i"; done - - [ -z "$CONSOLE" ] && CONSOLE="$(</sys/class/tty/console/active)" - [ -z "$HANDOFF" ] && HANDOFF=/bin/sh && echo -e '\e[?7hType exit when done.' - echo 3 > /proc/sys/kernel/printk - exec oneit -c /dev/"${CONSOLE:-console}" $HANDOFF -else # for chroot - /bin/sh - umount /dev/pts /dev /sys /proc -fi -EOF -chmod +x "$ROOT"/init && - -# Google's nameserver, passwd+group with special (root/nobody) accounts + guest -echo "nameserver 8.8.8.8" > "$ROOT"/etc/resolv.conf && -cat > "$ROOT"/etc/passwd << 'EOF' && -root:x:0:0:root:/root:/bin/sh -guest:x:500:500:guest:/home/guest:/bin/sh -nobody:x:65534:65534:nobody:/proc/self:/dev/null -EOF -echo -e 'root:x:0:\nguest:x:500:\nnobody:x:65534:' > "$ROOT"/etc/group || exit 1 - -# Build static toybox with existing .config if there is one, else defconfig+sh -announce toybox -[ ! -z "$PENDING" ] && rm -f .config -[ -e .config ] && CONF=silentoldconfig || unset CONF -for i in $PENDING sh route wget; do XX="$XX"$'\n'CONFIG_${i^^?}=y; done -LDFLAGS=--static PREFIX="$ROOT" make clean \ - ${CONF:-defconfig KCONFIG_ALLCONFIG=<(echo "$XX")} toybox install || exit 1 - -# Build any packages listed on command line -for i in ${PKG:+plumbing $PKG}; do - announce "$i"; PATH="$PKGDIR:$PATH" source $i || die $i -done - -# ------------------ Part 3: Build + package bootable system ------------------ - -# ----- Build kernel for target - -if [ -z "$LINUX" ] || [ ! -d "$LINUX/kernel" ]; then - echo 'No $LINUX directory, kernel build skipped.' -else - # Which architecture are we building a kernel for? - LINUX="$(realpath "$LINUX")" - [ -z "$TARGET" ] && - { [ "$CROSS" == host ] && TARGET="$(uname -m)" || TARGET="$CROSS"; } - - # Target-specific info in an (alphabetical order) if/else staircase - # Each target needs board config, serial console, RTC, ethernet, block device. - - if [ "$TARGET" == armv5l ]; then - # This could use the same VIRT board as armv7, but let's demonstrate a - # different one requiring a separate device tree binary. - QEMU="arm -M versatilepb -net nic,model=rtl8139 -net user" - KARCH=arm KARGS=ttyAMA0 VMLINUX=arch/arm/boot/zImage - KCONF=CPU_ARM926T,MMU,VFP,ARM_THUMB,AEABI,ARCH_VERSATILE,ATAGS,DEPRECATED_PARAM_STRUCT,ARM_ATAG_DTB_COMPAT,ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND,SERIAL_AMBA_PL011,SERIAL_AMBA_PL011_CONSOLE,RTC_CLASS,RTC_DRV_PL031,RTC_HCTOSYS,PCI,PCI_VERSATILE,BLK_DEV_SD,SCSI,SCSI_LOWLEVEL,SCSI_SYM53C8XX_2,SCSI_SYM53C8XX_MMIO,NET_VENDOR_REALTEK,8139CP - KERNEL_CONFIG="CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0" - DTB=arch/arm/boot/dts/versatile-pb.dtb - elif [ "$TARGET" == armv7l ] || [ "$TARGET" == aarch64 ]; then - if [ "$TARGET" == aarch64 ]; then - QEMU="aarch64 -M virt -cpu cortex-a57" - KARCH=arm64 VMLINUX=arch/arm64/boot/Image - else - QEMU="arm -M virt" KARCH=arm VMLINUX=arch/arm/boot/zImage - fi - KARGS=ttyAMA0 - KCONF=MMU,ARCH_MULTI_V7,ARCH_VIRT,SOC_DRA7XX,ARCH_OMAP2PLUS_TYPICAL,ARCH_ALPINE,ARM_THUMB,VDSO,CPU_IDLE,ARM_CPUIDLE,KERNEL_MODE_NEON,SERIAL_AMBA_PL011,SERIAL_AMBA_PL011_CONSOLE,RTC_CLASS,RTC_HCTOSYS,RTC_DRV_PL031,NET_CORE,VIRTIO_MENU,VIRTIO_NET,PCI,PCI_HOST_GENERIC,VIRTIO_BLK,VIRTIO_PCI,VIRTIO_MMIO,ATA,ATA_SFF,ATA_BMDMA,ATA_PIIX,PATA_PLATFORM,PATA_OF_PLATFORM,ATA_GENERIC,CONFIG_ARM_LPAE - elif [ "$TARGET" == hexagon ]; then - QEMU="hexagon -M comet" KARGS=ttyS0 VMLINUX=vmlinux - KARCH="hexagon LLVM_IAS=1" KCONF=SPI,SPI_BITBANG,IOMMU_SUPPORT - elif [ "$TARGET" == i486 ] || [ "$TARGET" == i686 ] || - [ "$TARGET" == x86_64 ] || [ "$TARGET" == x32 ]; then - if [ "$TARGET" == i486 ]; then - QEMU="i386 -cpu 486 -global fw_cfg.dma_enabled=false" KCONF=M486 - elif [ "$TARGET" == i686 ]; then - QEMU="i386 -cpu pentium3" KCONF=MPENTIUMII - else - QEMU=x86_64 KCONF=64BIT - [ "$TARGET" == x32 ] && KCONF=X86_X32 - fi - KARCH=x86 KARGS=ttyS0 VMLINUX=arch/x86/boot/bzImage - KCONF=$KCONF,UNWINDER_FRAME_POINTER,PCI,BLK_DEV_SD,ATA,ATA_SFF,ATA_BMDMA,ATA_PIIX,NET_VENDOR_INTEL,E1000,SERIAL_8250,SERIAL_8250_CONSOLE,RTC_CLASS - elif [ "$TARGET" == m68k ]; then - QEMU="m68k -M q800" KARCH=m68k KARGS=ttyS0 VMLINUX=vmlinux - KCONF=MMU,M68040,M68KFPU_EMU,MAC,SCSI_MAC_ESP,MACINTOSH_DRIVERS,ADB,ADB_MACII,NET_CORE,NET_VENDOR_NATSEMI,MACSONIC,SERIAL_PMACZILOG,SERIAL_PMACZILOG_TTYS,SERIAL_PMACZILOG_CONSOLE - elif [ "$TARGET" == mips ] || [ "$TARGET" == mipsel ]; then - QEMU="mips -M malta" KARCH=mips KARGS=ttyS0 VMLINUX=vmlinux - KCONF=MIPS_MALTA,CPU_MIPS32_R2,SERIAL_8250,SERIAL_8250_CONSOLE,PCI,BLK_DEV_SD,ATA,ATA_SFF,ATA_BMDMA,ATA_PIIX,NET_VENDOR_AMD,PCNET32,POWER_RESET,POWER_RESET_SYSCON - [ "$TARGET" == mipsel ] && KCONF=$KCONF,CPU_LITTLE_ENDIAN && - QEMU="mipsel -M malta" - elif [ "$TARGET" == powerpc ]; then - KARCH=powerpc QEMU="ppc -M g3beige" KARGS=ttyS0 VMLINUX=vmlinux - KCONF=ALTIVEC,PPC_PMAC,PPC_OF_BOOT_TRAMPOLINE,IDE,IDE_GD,IDE_GD_ATA,BLK_DEV_IDE_PMAC,BLK_DEV_IDE_PMAC_ATA100FIRST,MACINTOSH_DRIVERS,ADB,ADB_CUDA,NET_VENDOR_NATSEMI,NET_VENDOR_8390,NE2K_PCI,SERIO,SERIAL_PMACZILOG,SERIAL_PMACZILOG_TTYS,SERIAL_PMACZILOG_CONSOLE,BOOTX_TEXT - elif [ "$TARGET" == powerpc64le ]; then - KARCH=powerpc QEMU="ppc64 -M pseries -vga none" KARGS=hvc0 - VMLINUX=vmlinux - KCONF=PPC64,PPC_PSERIES,CPU_LITTLE_ENDIAN,PPC_OF_BOOT_TRAMPOLINE,BLK_DEV_SD,SCSI_LOWLEVEL,SCSI_IBMVSCSI,ATA,NET_VENDOR_IBM,IBMVETH,HVC_CONSOLE,PPC_TRANSACTIONAL_MEM,PPC_DISABLE_WERROR,SECTION_MISMATCH_WARN_ONLY - elif [ "$TARGET" = s390x ]; then - QEMU="s390x" KARCH=s390 VMLINUX=arch/s390/boot/bzImage - KCONF=MARCH_Z900,PACK_STACK,NET_CORE,VIRTIO_NET,VIRTIO_BLK,SCLP_TTY,SCLP_CONSOLE,SCLP_VT220_TTY,SCLP_VT220_CONSOLE,S390_GUEST - elif [ "$TARGET" == sh2eb ]; then - BUILTIN=1 KARCH=sh VMLINUX=vmlinux - KERNEL_CONFIG=$'CONFIG_MEMORY_START=0x10000000\nCONFIG_CMDLINE="console=ttyUL0 earlycon"' - KCONF=CPU_SUBTYPE_J2,CPU_BIG_ENDIAN,SH_JCORE_SOC,SMP,BINFMT_ELF_FDPIC,JCORE_EMAC,SERIAL_UARTLITE,SERIAL_UARTLITE_CONSOLE,HZ_100,CMDLINE_OVERWRITE,SPI,SPI_JCORE,MMC,PWRSEQ_SIMPLE,MMC_BLOCK,MMC_SPI - elif [ "$TARGET" == sh4 ]; then - QEMU="sh4 -M r2d -serial null -serial mon:stdio" KARCH=sh - KARGS="ttySC1 noiotrap" VMLINUX=arch/sh/boot/zImage - KERNEL_CONFIG="CONFIG_MEMORY_START=0x0c000000" - KCONF=CPU_SUBTYPE_SH7751R,MMU,VSYSCALL,SH_FPU,SH_RTS7751R2D,RTS7751R2D_PLUS,SERIAL_SH_SCI,SERIAL_SH_SCI_CONSOLE,PCI,NET_VENDOR_REALTEK,8139CP,PCI,BLK_DEV_SD,ATA,ATA_SFF,ATA_BMDMA,PATA_PLATFORM,BINFMT_ELF_FDPIC,BINFMT_FLAT -#see also SPI SPI_SH_SCI MFD_SM501 RTC_CLASS RTC_DRV_R9701 RTC_DRV_SH RTC_HCTOSYS - else die "Unknown \$TARGET $TARGET" - fi - - # Write the qemu launch script - if [ -n "$QEMU" ]; then - [ -z "$BUILTIN" ] && INITRD="-initrd ${CROSS}root.cpio.gz" - { echo qemu-system-"$QEMU" '"$@"' $QEMU_MORE -nographic -no-reboot -m 256 \ - -kernel $(basename $VMLINUX) $INITRD ${DTB:+-dtb "$(basename "$DTB")"} \ - "-append \"panic=1 HOST=$TARGET console=$KARGS \$KARGS\"" && - echo "echo -e '\\e[?7h'" - } > "$OUTPUT/qemu-$TARGET.sh" && - chmod +x "$OUTPUT/qemu-$TARGET.sh" || exit 1 - fi - - announce "linux-$KARCH" - pushd "$LINUX" && make distclean && popd && - cp -sfR "$LINUX" "$MYBUILD/linux" && pushd "$MYBUILD/linux" && - sed -is '/select HAVE_STACK_VALIDATION/d' arch/x86/Kconfig && # Fix x86-64 - sed -is 's/depends on !SMP/& || !MMU/' mm/Kconfig && # Fix sh2eb - - # Write miniconfig - { echo "# make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG=$TARGET.miniconf" - echo -e "# make ARCH=$KARCH -j \$(nproc)\n# boot $VMLINUX\n\n" - echo "# CONFIG_EMBEDDED is not set" - - # Expand list of =y symbols, first generic then architecture-specific - for i in BINFMT_ELF,BINFMT_SCRIPT,NO_HZ,HIGH_RES_TIMERS,BLK_DEV,BLK_DEV_INITRD,RD_GZIP,BLK_DEV_LOOP,EXT4_FS,EXT4_USE_FOR_EXT2,VFAT_FS,FAT_DEFAULT_UTF8,MISC_FILESYSTEMS,SQUASHFS,SQUASHFS_XATTR,SQUASHFS_ZLIB,DEVTMPFS,DEVTMPFS_MOUNT,TMPFS,TMPFS_POSIX_ACL,NET,PACKET,UNIX,INET,IPV6,NETDEVICES,NET_CORE,NETCONSOLE,ETHERNET,COMPAT_32BIT_TIME,EARLY_PRINTK,IKCONFIG,IKCONFIG_PROC $KCONF $KEXTRA ; do - echo "# architecture ${X:-independent}" - sed -E '/^$/d;s/([^,]*)($|,)/CONFIG_\1=y\n/g' <<< "$i" - X=specific - done - [ -n "$BUILTIN" ] && echo -e CONFIG_INITRAMFS_SOURCE="\"$OUTPUT/fs\"" - echo "$KERNEL_CONFIG" - } > "$OUTPUT/miniconfig-$TARGET" && - make ARCH=$KARCH allnoconfig KCONFIG_ALLCONFIG="$OUTPUT/miniconfig-$TARGET" && - - # Second config pass to remove stupid kernel defaults - # See http://lkml.iu.edu/hypermail/linux/kernel/1912.3/03493.html - sed -e 's/# CONFIG_EXPERT .*/CONFIG_EXPERT=y/' -e "$(sed -E -e '/^$/d' \ - -e 's@([^,]*)($|,)@/^CONFIG_\1=y/d;$a# CONFIG_\1 is not set/\n@g' \ - <<< VT,SCHED_DEBUG,DEBUG_MISC,X86_DEBUG_FPU)" -i .config && - yes "" | make ARCH=$KARCH oldconfig > /dev/null && - - # Build kernel. Copy config, device tree binary, and kernel binary to output - make ARCH=$KARCH CROSS_COMPILE="$CROSS_COMPILE" -j $(nproc) && - cp .config "$OUTPUT/linux-fullconfig" || exit 1 - [ -n "$DTB" ] && { cp "$DTB" "$OUTPUT" || exit 1 ;} - cp "$VMLINUX" "$OUTPUT" && cd .. && rm -rf linux && popd || exit 1 -fi - -# clean up and package root filesystem for initramfs. -if [ -z "$BUILTIN" ]; then - announce "${CROSS}root.cpio.gz" - (cd "$ROOT" && find . | cpio -o -H newc ${CROSS_COMPILE:+--no-preserve-owner}\ - | gzip) > "$OUTPUT/$CROSS"root.cpio.gz || exit 1 -fi - -mv "$LOG/$CROSS".{n,y} -rmdir "$MYBUILD" "$BUILD" 2>/dev/null || exit 0 # remove if empty, not an error +#!/usr/bin/printf Moved to mkroot/mkroot.sh\n\c%s diff --git a/scripts/mkstatus.py b/scripts/mkstatus.py index ed6dd544..41a1bed2 100755 --- a/scripts/mkstatus.py +++ b/scripts/mkstatus.py @@ -40,7 +40,7 @@ print "all commands=%s" % len(reverse) # Run a couple sanity checks on input for i in toystuff: - if (i in pending): print "barf %s" % i + if (i in pending): print "Pending command not roadmap: %s" % i unknowns=[] for i in toystuff + pending: diff --git a/scripts/portability.sh b/scripts/portability.sh index 3af2be5f..4241916a 100644 --- a/scripts/portability.sh +++ b/scripts/portability.sh @@ -2,9 +2,9 @@ source ./configure -if [ -z "$(command -v "${CROSS_COMPILE}${CC}")" ] +if [ -z "$(command -v "$CROSS_COMPILE$CC")" ] then - echo "No ${CROSS_COMPILE}${CC} found" >&2 + echo "No $CROSS_COMPILE$CC found" >&2 exit 1 fi @@ -16,26 +16,30 @@ fi # Tell linker to do dead code elimination at function level if [ "$(uname)" == "Darwin" ] then + CFLAGS+=" -Wno-deprecated-declarations" : ${LDOPTIMIZE:=-Wl,-dead_strip} ${STRIP:=strip} else : ${LDOPTIMIZE:=-Wl,--gc-sections -Wl,--as-needed} ${STRIP:=strip -s -R .note* -R .comment} fi +# Disable a pointless warning only clang produces +[ -n "$("$CROSS_COMPILE$CC" --version | grep -w clang)" ] && + CFLAGS+=" -Wno-string-plus-int -Wno-invalid-source-encoding" + # Address Sanitizer -if [ ! -z "$ASAN" ]; then +if [ -n "$ASAN" ]; then # Turn ASan on and disable most optimization to get more readable backtraces. # (Technically ASAN is just "-fsanitize=address" and the rest is optional.) - ASAN_FLAGS="-fsanitize=address -O1 -g -fno-omit-frame-pointer -fno-optimize-sibling-calls" - CFLAGS="$CFLAGS $ASAN_FLAGS" - HOSTCC="$HOSTCC $ASAN_FLAGS" - NOSTRIP=1 + export CFLAGS="$CFLAGS -fsanitize=address -O1 -g -fno-omit-frame-pointer -fno-optimize-sibling-calls" + export NOSTRIP=1 # Ignore leaks on exit. TODO export ASAN_OPTIONS="detect_leaks=0" + # only do this once unset ASAN fi -# Centos 7 bug workaround, EOL June 30 2024. TODO -DASHN=-n; wait -n 2>/dev/null; [ $? -eq 2 ] && unset DASHN +# Probe number of available processors, and add one. +: ${CPUS:=$(($(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null)+1))} # If the build is using gnu tools, make them behave less randomly. export LANG=c diff --git a/scripts/record-commands b/scripts/record-commands deleted file mode 100755 index d2b779fa..00000000 --- a/scripts/record-commands +++ /dev/null @@ -1,42 +0,0 @@ -#!/bin/bash - -# Set up command recording wrapper - -[ -z "$WRAPDIR" ] && WRAPDIR="$PWD"/record-commands && RM=$(which rm) -[ -z "$LOGPATH" ] && export LOGPATH="$PWD"/log.txt - -if [ ${#BASH_SOURCE[@]} -lt 2 ] && [ $# -eq 0 ] -then - echo "usage: WRAPDIR=dir LOGPATH=log.txt record-commands COMMAND..." - echo 'Then examine log.txt. "record-commands echo" to just setup $WRAPDIR' - exit 1 -fi - -if [ ! -x "$WRAPDIR/logpath" ] -then - mkdir -p "$WRAPDIR" && PREFIX="$WRAPDIR/" scripts/single.sh logpath || exit 1 - echo "$PATH" | tr : '\n' | while read DIR - do - find "$DIR/" -type f,l -maxdepth 1 -executable -exec basename {} \; | \ - while read FILE - do - ln -s logpath "$WRAPDIR/$FILE" 2>/dev/null - done - done -fi - -# Delete old log (if any) -rm -f "$LOGPATH" - -# When sourced, set up wrapper for current context. -export PATH="$WRAPDIR:$PATH" -if [ ${#BASH_SOURCE[@]} -lt 2 ] -then - "$@" - X=$? - - [ ! -z "$RM" ] && "$RM" -rf "$WRAPDIR" - - exit $X -fi - diff --git a/scripts/root/dropbear b/scripts/root/dropbear deleted file mode 100755 index 75839c34..00000000 --- a/scripts/root/dropbear +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/echo Try "scripts/mkroot.sh dropbear" - -# Example overlay file, adding dropbear (which requires zlib) - -echo === download source - -download e6d119755acdf9104d7ba236b1242696940ed6dd \ - http://downloads.sf.net/libpng/zlib-1.2.11.tar.gz - -download c3d4fe27fa17ec8217dbedbd33dd73a1ca6cda2c \ - https://matt.ucc.asn.au/dropbear/releases/dropbear-2020.81.tar.bz2 - -echo === Native build static zlib - -setupfor zlib -# They keep checking in broken generated files. -rm -f Makefile zconf.h && -CC=${CROSS_COMPILE}cc LD=${CROSS_COMPILE}ld AS=${CROSS_COMPILE}as ./configure && -make -j $(nproc) || exit 1 - -# do _not_ cleanup zlib, we need the files we just built for dropbear -cd .. - -echo === $HOST Native build static dropbear - -setupfor dropbear -# Repeat after me: "autoconf is useless" -echo 'echo "$@"' > config.sub && -ZLIB="$(echo ../zlib*)" && -CFLAGS="-I $ZLIB -O2" LDFLAGS="-L $ZLIB" ./configure --enable-static \ - --disable-wtmp --host="$(basename "$CROSS_COMPILE" | sed 's/-$//')" && -sed -i 's@/usr/bin/dbclient@ssh@' options.h && -sed -i 's@\(#define NON_INETD_MODE\) 1@\1 0@' default_options.h && -make -j $(nproc) PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" MULTI=1 SCPPROGRESS=1 && -${CROSS_COMPILE}strip dropbearmulti && -mkdir -p "$ROOT"/{bin,etc/{rc,dropbear},var/log} && -touch "$ROOT"/var/log/lastlog && -cp dropbearmulti "$ROOT"/bin || exit 1 -for i in "$ROOT"/bin/{ssh,dropbear,scp,dropbearkey} -do - ln -s dropbearmulti $i || exit 1 -done -cleanup - -rm -rf zlib-* - -# user root password root, user guest no password -echo -e 'root:$1$939UTPzb$/PfVYAsF2Hqi/AQ3UBjbK/:::::::\nguest::::::::' > "$ROOT"/etc/shadow && -chmod 600 "$ROOT"/etc/shadow && - -echo 'netcat -p 22 -L dropbear -iRB &' > "$ROOT"/etc/rc/dropbear && - -# file to run on host to ssh into guest -echo 'ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" ${1:+$1@}127.0.0.1 -p 2222' > "$OUTPUT"/ssh2dropbear.sh && -chmod +x "$OUTPUT"/ssh2dropbear.sh - -# Forward 127.0.0.1:2222 into qemu instance -QEMU_MORE="-nic user,hostfwd=tcp:127.0.0.1:2222-:22" diff --git a/scripts/root/plumbing b/scripts/root/plumbing deleted file mode 100755 index ff302803..00000000 --- a/scripts/root/plumbing +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/echo run this from "make root" - -# Plumbing to download files - -[ -z "$ROOT" ] && echo "no" && exit 1 -mkdir -p "${DOWNLOAD:=$PWD/root_download}" || exit 1 - -### Functions to download, extract, and clean up after source packages. - -# Usage: download HASH URL -# Grabs source from URL confirming SHA1 hash (Basically "wget $2") -# If extracted source is in $DOWNLOAD (no version) build will use that instead -download() { - FILE="$(basename "$2")" - [ -d "$DOWNLOAD/${FILE/-*/}" ] && echo "$FILE" local && return 0 - X=0; while true; do - [ "$(sha1sum < "$DOWNLOAD/$FILE" 2>/dev/null)" == "$1 -" ] && - echo "$FILE" confirmed && break - rm -f $DOWNLOAD/${FILE/-[0-9]*/}-[0-9]* || exit 1 - [ $X -eq 0 ] && X=1 || exit 1 - wget "$2" -O "$DOWNLOAD/$FILE" - done -} - -# Usage: setupfor PACKAGE -# Extracts source tarball (or snapshot a repo) to create disposable build dir. -# Basically "tar xvzCf $MYBUILD $DOWNLOAD/$1.tar.gz && cd $NEWDIR" -setupfor() { - PACKAGE="$(basename "$1")" - announce "$PACKAGE" && cd "$MYBUILD" && rm -rf "$PACKAGE" || exit 1 - if [ -d "$DOWNLOAD/$PACKAGE" ]; then - cp -la "$DOWNLOAD/$PACKAGE/." "$PACKAGE" && cd "$PACKAGE" || exit 1 - else - tar xvaf "$DOWNLOAD/$PACKAGE"-*.t* && cd "$PACKAGE"-* || exit 1 - fi -} - -# Usage: cleanup -# Delete setupfor's dir, exiting if build failed (basically "rm -rf $PACKAGE") -cleanup() { - [ $? -ne 0 ] && exit 1 - [ -z "$PACKAGE" ] && exit 1 - [ ! -z "$NO_CLEANUP" ] && return - cd .. && rm -rf "$PACKAGE"* || exit 1 -} diff --git a/scripts/runtest.sh b/scripts/runtest.sh index 5a647677..ce6e0fd0 100644 --- a/scripts/runtest.sh +++ b/scripts/runtest.sh @@ -2,9 +2,7 @@ # # Copyright 2005 by Rob Landley -# This file defines two main functions, "testcmd" and "optional". The -# first performs a test, the second enables/disables tests based on -# configuration options. +# This file defines three main functions: "testing", "testcmd", and "txpect". # The following environment variables enable optional behavior in "testing": # DEBUG - Show every command run by test script. @@ -30,26 +28,13 @@ # The environment variable "FAILCOUNT" contains a cumulative total of the # number of failed tests. # -# The "optional" function is used to skip certain tests (by setting the -# environment variable SKIP), ala: -# optional CFG_THINGY +# The environment variable "SKIP" says how many upcoming tests to skip, +# defaulting to 0 and counting down when set to a higher number. # -# The "optional" function checks the environment variable "OPTIONFLAGS", -# which is either empty (in which case it always clears SKIP) or -# else contains a colon-separated list of features (in which case the function -# clears SKIP if the flag was found, or sets it to 1 if the flag was not found). - -export FAILCOUNT=0 -export SKIP= - -# Helper functions - -# Check config to see if option is enabled, set SKIP if not. - -SHOWPASS=PASS -SHOWFAIL=FAIL -SHOWSKIP=SKIP +# Function "optional" enables/disables tests based on configuration options. +export FAILCOUNT=0 SKIP=0 +: ${SHOWPASS:=PASS} ${SHOWFAIL:=FAIL} ${SHOWSKIP:=SKIP} if tty -s <&1 then SHOWPASS="$(echo -e "\033[1;32m${SHOWPASS}\033[0m")" @@ -57,34 +42,64 @@ then SHOWSKIP="$(echo -e "\033[1;33m${SHOWSKIP}\033[0m")" fi -optional() +# Helper functions + +# Check if VERBOSE= contains a given string. (This allows combining.) +verbose_has() { - option=`printf %s "$OPTIONFLAGS" | egrep "(^|:)$1(:|\$)"` - # Not set? - if [ -z "$1" ] || [ -z "$OPTIONFLAGS" ] || [ ${#option} -ne 0 ] + [ "${VERBOSE/$1/}" != "$VERBOSE" ] +} + +wrong_args() +{ + if [ $# -ne 5 ] then - unset SKIP - return + printf "%s\n" "Test $NAME has the wrong number of arguments ($# $*)" >&2 + exit fi - SKIP=1 } -verbose_has() +# Announce success +do_pass() { - [ "${VERBOSE/$1/}" != "$VERBOSE" ] + verbose_has nopass || printf "%s\n" "$SHOWPASS: $NAME" } +# Announce failure and handle fallout for txpect +do_fail() +{ + FAILCOUNT=$(($FAILCOUNT+1)) + printf "%s\n" "$SHOWFAIL: $NAME" + if [ ! -z "$CASE" ] + then + echo "Expected '$CASE'" + echo "Got '$A'" + fi + ! verbose_has all && exit 1 +} + +# Functions test files call directly + +# Set SKIP high if option not enabled in $OPTIONFLAGS (unless OPTIONFLAGS blank) +optional() +{ + [ -n "$OPTIONFLAGS" ] && [ "$OPTIONFLAGS" == "${OPTIONFLAGS/:$1:/}" ] && + SKIP=99999 || SKIP=0 +} + +# Evalute command line and skip next test when false skipnot() { if verbose_has quiet then - eval "$@" 2>/dev/null + eval "$@" >/dev/null 2>&1 else eval "$@" fi - [ $? -eq 0 ] || SKIPNEXT=1 + [ $? -eq 0 ] || { ((++SKIP)); return 1; } } +# Skip this test (rest of command line) when not running toybox. toyonly() { IS_TOYBOX="$("$C" --version 2>/dev/null)" @@ -93,61 +108,40 @@ toyonly() case "$IS_TOYBOX" in toybox*) ;; This\ is\ not\ GNU*) ;; - *) SKIPNEXT=1 ;; + *) [ $SKIP -eq 0 ] && ((++SKIP)) ;; esac "$@" } -wrong_args() -{ - if [ $# -ne 5 ] - then - printf "%s\n" "Test $NAME has the wrong number of arguments ($# $*)" >&2 - exit - fi -} - -# Announce success -do_pass() -{ - ! verbose_has nopass && printf "%s\n" "$SHOWPASS: $NAME" -} - -# The testing function - +# Takes five arguments: "name" "command" "result" "infile" "stdin" testing() { - NAME="$CMDNAME $1" wrong_args "$@" - [ -z "$1" ] && NAME=$2 + [ -z "$1" ] && NAME="$2" || NAME="$1" + [ "${NAME#$CMDNAME }" == "$NAME" ] && NAME="$CMDNAME $1" [ -n "$DEBUG" ] && set -x - if [ -n "$SKIP" -o -n "$SKIP_HOST" -a -n "$TEST_HOST" -o -n "$SKIPNEXT" ] + if [ "$SKIP" -gt 0 ] then - verbose_has quiet && printf "%s\n" "$SHOWSKIP: $NAME" - unset SKIPNEXT + verbose_has quiet || printf "%s\n" "$SHOWSKIP: $NAME" + ((--SKIP)) + return 0 fi - echo -ne "$3" > expected + echo -ne "$3" > ../expected [ ! -z "$4" ] && echo -ne "$4" > input || rm -f input - echo -ne "$5" | ${EVAL:-eval --} "$2" > actual + echo -ne "$5" | ${EVAL:-eval --} "$2" > ../actual RETVAL=$? # Catch segfaults - [ $RETVAL -gt 128 ] && [ $RETVAL -lt 255 ] && + [ $RETVAL -gt 128 ] && echo "exited with signal (or returned $RETVAL)" >> actual - DIFF="$(diff -au${NOSPACE:+w} expected actual)" - if [ -n "$DIFF" ] - then - FAILCOUNT=$(($FAILCOUNT+1)) - printf "%s\n" "$SHOWFAIL: $NAME" - else - ! verbose_has nopass && printf "%s\n" "$SHOWPASS: $NAME" - fi + DIFF="$(cd ..; diff -au${NOSPACE:+w} expected actual)" + [ -z "$DIFF" ] && do_pass || VERBOSE=all do_fail if ! verbose_has quiet && { [ -n "$DIFF" ] || verbose_has spam; } then [ ! -z "$4" ] && printf "%s\n" "echo -ne \"$4\" > input" @@ -156,34 +150,22 @@ testing() fi [ -n "$DIFF" ] && ! verbose_has all && exit 1 - rm -f input expected actual + rm -f input ../expected ../actual [ -n "$DEBUG" ] && set +x return 0 } +# Wrapper for "testing", adds command name being tested to start of command line testcmd() { wrong_args "$@" - X="$1" - [ -z "$X" ] && X="$CMDNAME $2" - testing "$X" "\"$C\" $2" "$3" "$4" "$5" + testing "${1:-$CMDNAME $2}" "\"$C\" $2" "$3" "$4" "$5" } -# Announce failure and handle fallout for txpect -do_fail() -{ - FAILCOUNT=$(($FAILCOUNT+1)) - printf "%s\n" "$SHOWFAIL: $NAME" - if [ ! -z "$CASE" ] - then - echo "Expected '$CASE'" - echo "Got '$A'" - fi - ! verbose_has all && exit 1 -} +# Simple implementation of "expect" written in shell. # txpect NAME COMMAND [I/O/E/Xstring]... # Run COMMAND and interact with it: send I strings to input, read O or E @@ -191,7 +173,7 @@ do_fail() # X means close stdin/stdout/stderr and match return code (blank means nonzero) txpect() { - local NAME CASE VERBOSITY LEN A B X O + local NAME CASE VERBOSITY LEN PID A B X O # Run command with redirection through fifos NAME="$CMDNAME $1" @@ -204,13 +186,14 @@ txpect() return fi eval "$2" <in-$$ >out-$$ 2>err-$$ & + PID=$! shift 2 : {IN}>in-$$ {OUT}<out-$$ {ERR}<err-$$ && rm in-$$ out-$$ err-$$ [ $? -ne 0 ] && { do_fail;return;} # Loop through challenge/response pairs, with 2 second timeout - while [ $# -gt 0 ] + while [ $# -gt 0 -a -n "$PID" ] do VERBOSITY="$VERBOSITY"$'\n'"$1" LEN=$((${#1}-1)) CASE="$1" A= B= @@ -234,29 +217,33 @@ txpect() then [ -z "$A" -o "$X" -ne 0 ] && { do_fail;break;} else - if [ ${1::1} == 'R' ] && [[ "$A" =~ "${1:2}" ]]; then true + if [ ${1::1} == 'R' ] && grep -q "${1:2}" <<< "$A"; then true elif [ ${1::1} != 'R' ] && [ "$A" == "${1:1}" ]; then true else # Append the rest of the output if there is any. read -t.1 B <&$O A="$A$B" read -t.1 -rN 9999 B<&$ERR - do_fail;break; + do_fail + break fi fi ;; # close I/O and wait for exit X) - exec {IN}<&- {OUT}<&- {ERR}<&- - wait + exec {IN}<&- + wait $PID A=$? + exec {OUT}<&- {ERR}<&- if [ -z "$LEN" ] then [ $A -eq 0 ] && { do_fail;break;} # any error else [ $A != "${1:1}" ] && { do_fail;break;} # specific value fi + do_pass + return ;; *) do_fail; break ;; esac @@ -270,65 +257,6 @@ txpect() do_pass else ! verbose_has quiet && echo "$VERBOSITY" >&2 + do_fail fi } - -# Recursively grab an executable and all the libraries needed to run it. -# Source paths beginning with / will be copied into destpath, otherwise -# the file is assumed to already be there and only its library dependencies -# are copied. - -mkchroot() -{ - [ $# -lt 2 ] && return - - echo -n . - - dest=$1 - shift - for i in "$@" - do - [ "${i:0:1}" == "/" ] || i=$(which $i) - [ -f "$dest/$i" ] && continue - if [ -e "$i" ] - then - d=`echo "$i" | grep -o '.*/'` && - mkdir -p "$dest/$d" && - cat "$i" > "$dest/$i" && - chmod +x "$dest/$i" - else - echo "Not found: $i" - fi - mkchroot "$dest" $(ldd "$i" | egrep -o '/.* ') - done -} - -# Set up a chroot environment and run commands within it. -# Needed commands listed on command line -# Script fed to stdin. - -dochroot() -{ - mkdir tmpdir4chroot - mount -t ramfs tmpdir4chroot tmpdir4chroot - mkdir -p tmpdir4chroot/{etc,sys,proc,tmp,dev} - cp -L testing.sh tmpdir4chroot - - # Copy utilities from command line arguments - - echo -n "Setup chroot" - mkchroot tmpdir4chroot $* - echo - - mknod tmpdir4chroot/dev/tty c 5 0 - mknod tmpdir4chroot/dev/null c 1 3 - mknod tmpdir4chroot/dev/zero c 1 5 - - # Copy script from stdin - - cat > tmpdir4chroot/test.sh - chmod +x tmpdir4chroot/test.sh - chroot tmpdir4chroot /test.sh - umount -l tmpdir4chroot - rmdir tmpdir4chroot -} diff --git a/scripts/single.sh b/scripts/single.sh index 023ccea6..f4f28be9 100755 --- a/scripts/single.sh +++ b/scripts/single.sh @@ -4,6 +4,8 @@ [ -z "$1" ] && { echo "usage: single.sh command..." >&2; exit 1; } +source scripts/portability.sh + # Add trailing / to PREFIX when it's set but hasn't got one [ "$PREFIX" == "${PREFIX%/}" ] && PREFIX="${PREFIX:+$PREFIX/}" @@ -17,7 +19,7 @@ else # Force dependencies to rebuild headers if we build multiplexer after this. touch "$KCONFIG_CONFIG" fi -GLOBDEP="$(sed -n 's/CONFIG_\(TOYBOX_[^=]*\)=y/\1/p' "$KCONFIG_CONFIG")" +GLOBDEP="$($SED -n 's/CONFIG_\(TOYBOX_[^=]*\)=y/\1/p' "$KCONFIG_CONFIG")" KCONFIG_CONFIG=.singleconfig for i in "$@" @@ -36,15 +38,15 @@ do unset DEPENDS MPDEL if [ "$i" == sh ] then - DEPENDS="$(sed -n 's/USE_\([^(]*\)(NEWTOY([^,]*,.*TOYFLAG_MAYFORK.*/\1/p' toys/*/*.c)" + DEPENDS="$($SED -n 's/USE_\([^(]*\)(NEWTOY([^,]*,.*TOYFLAG_MAYFORK.*/\1/p' toys/*/*.c)" else MPDEL='s/CONFIG_TOYBOX=y/# CONFIG_TOYBOX is not set/;t' fi # Enable stuff this command depends on - DEPENDS="$({ echo $DEPENDS $GLOBDEP; sed -n "/^config *$i"'$/,/^$/{s/^[ \t]*depends on //;T;s/[!][A-Z0-9_]*//g;s/ *&& */|/g;p}' $TOYFILE;}| xargs | tr ' ' '|')" + DEPENDS="$({ echo $DEPENDS $GLOBDEP; $SED -n "/^config *$i"'$/,/^$/{s/^[ \t]*depends on //;T;s/[!][A-Z0-9_]*//g;s/ *&& */|/g;p}' $TOYFILE;}| xargs | tr ' ' '|')" NAME=$(echo $i | tr a-z- A-Z_) - sed -ri -e "$MPDEL" \ + $SED -ri -e "$MPDEL" \ -e "s/# (CONFIG_($NAME|${NAME}_.*${DEPENDS:+|$DEPENDS})) is not set/\1=y/" \ "$KCONFIG_CONFIG" || exit 1 diff --git a/scripts/test.sh b/scripts/test.sh index da22f661..c29a9aa9 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -8,26 +8,28 @@ export FILES="$PWD"/tests/files trap 'kill $(jobs -p) 2>/dev/null; exit 1' INT -rm -rf generated/testdir -mkdir -p generated/testdir/testdir +export PREFIX=generated/testdir +rm -rf "$PREFIX" +mkdir -p "$PREFIX"/testdir if [ -z "$TEST_HOST" ] then if [ $# -ne 0 ] then - PREFIX=generated/testdir/ scripts/single.sh "$@" || exit 1 + scripts/single.sh "$@" || exit 1 else - make install_flat PREFIX=generated/testdir || exit 1 + scripts/install.sh --symlink --force || exit 1 fi fi -cd generated/testdir +export -n PREFIX +cd "$PREFIX" PATH="$PWD:$PATH" TESTDIR="$PWD" export LC_COLLATE=C [ -f "$TOPDIR/generated/config.h" ] && - export OPTIONFLAGS=:$(echo $($SED -nr 's/^#define CFG_(.*) 1/\1/p' "$TOPDIR/generated/config.h") | $SED 's/ /:/g') + export OPTIONFLAGS=:$($SED -nr 's/^#define CFG_(.*) 1$/\1/p' "$TOPDIR/generated/config.h" | tr '\n' :) do_test() { @@ -38,16 +40,16 @@ do_test() if [ -z "$TEST_HOST" ] then C="$TESTDIR/$CMDNAME" - [ ! -e "$C" ] && echo "$CMDNAME disabled" && return + [ ! -e "$C" ] && echo "$SHOWSKIP: $CMDNAME disabled" && return C="$(dirname $(realpath "$C"))/$CMDNAME" else C="$(which $CMDNAME 2>/dev/null)" [ -z "$C" ] && printf '%s\n' "$SHOWSKIP: no $CMDNAME" && return fi - (. "$1"; cd "$TESTDIR"; touch continue) + (. "$1"; cd "$TESTDIR"; echo "$FAILCOUNT" > continue) cd "$TESTDIR" - [ -e continue ] || exit 1 + [ -e continue ] && FAILCOUNT=$(($(cat continue)+$FAILCOUNT)) || exit 1 } if [ $# -ne 0 ] |