Rob Landley | 2896480 | 2008-01-19 17:08:39 -0600 | [diff] [blame] | 1 | #!/bin/bash |
| 2 | |
| 3 | # Grab default values for $CFLAGS and such. |
| 4 | |
Rob Landley | b3d4f0b | 2013-04-29 16:00:40 -0500 | [diff] [blame] | 5 | export LANG=c |
Rob Landley | 082a9a7 | 2014-08-30 16:34:46 -0500 | [diff] [blame] | 6 | export LC_ALL=C |
Rob Landley | 7a07c6b | 2014-09-09 20:13:03 -0500 | [diff] [blame] | 7 | set -o pipefail |
Rob Landley | 2896480 | 2008-01-19 17:08:39 -0600 | [diff] [blame] | 8 | source ./configure |
| 9 | |
Rob Landley | d04dc1f | 2013-08-30 01:53:31 -0500 | [diff] [blame] | 10 | [ -z "$KCONFIG_CONFIG" ] && KCONFIG_CONFIG=".config" |
| 11 | |
Rob Landley | d3df423 | 2014-09-20 13:07:53 -0500 | [diff] [blame] | 12 | # Since each cc invocation is short, launch half again as many processes |
| 13 | # as we have processors so they don't exit faster than we can start them. |
| 14 | [ -z "$CPUS" ] && |
| 15 | CPUS=$((($(echo /sys/devices/system/cpu/cpu[0-9]* | wc -w)*3)/2)) |
| 16 | |
Rob Landley | 86cafe1 | 2014-01-03 18:23:09 -0600 | [diff] [blame] | 17 | # Respond to V= by echoing command lines as well as running them |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 18 | DOTPROG= |
Rob Landley | 86cafe1 | 2014-01-03 18:23:09 -0600 | [diff] [blame] | 19 | do_loudly() |
| 20 | { |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 21 | [ ! -z "$V" ] && echo "$@" || echo -n "$DOTPROG" |
Rob Landley | 86cafe1 | 2014-01-03 18:23:09 -0600 | [diff] [blame] | 22 | "$@" |
| 23 | } |
| 24 | |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 25 | # Is anything under directory $2 newer than file $1 |
| 26 | isnewer() |
| 27 | { |
| 28 | [ ! -z "$(find "$2" -newer "$1" 2>/dev/null || echo yes)" ] |
| 29 | } |
| 30 | |
| 31 | echo "Generate headers from toys/*/*.c..." |
| 32 | |
Rob Landley | 94a4603 | 2014-09-20 14:20:28 -0500 | [diff] [blame] | 33 | mkdir -p generated |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 34 | |
| 35 | if isnewer generated/Config.in toys |
| 36 | then |
| 37 | echo "Extract configuration information from toys/*.c files..." |
| 38 | scripts/genconfig.sh |
| 39 | fi |
| 40 | |
| 41 | # Create a list of all the commands toybox can provide. Note that the first |
| 42 | # entry is out of order on purpose (the toybox multiplexer command must be the |
| 43 | # first element of the array). The rest must be sorted in alphabetical order |
| 44 | # for fast binary search. |
| 45 | |
| 46 | if isnewer generated/newtoys.h toys |
| 47 | then |
| 48 | echo -n "generated/newtoys.h " |
| 49 | |
| 50 | echo "USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT))" > generated/newtoys.h |
| 51 | sed -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \ |
Elliott Hughes | 627cd0f | 2014-12-23 19:17:13 -0600 | [diff] [blame] | 52 | | sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -s -k 1,1 \ |
Rob Landley | f3e56f4 | 2014-12-31 21:30:59 -0600 | [diff] [blame] | 53 | | sed 's/[^ ]* //' >> generated/newtoys.h || exit 1 |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 54 | fi |
| 55 | |
| 56 | [ ! -z "$V" ] && echo "Which C files to build..." |
| 57 | |
| 58 | # Extract a list of toys/*/*.c files to compile from the data in $KCONFIG_CONFIG |
Rob Landley | 912b2be | 2015-02-07 17:20:23 -0600 | [diff] [blame] | 59 | # (First command names, then filenames with relevant {NEW,OLD}TOY() macro.) |
| 60 | |
Rob Landley | 90afbad | 2015-04-17 02:46:11 -0500 | [diff] [blame] | 61 | GITHASH="$(git describe --tags --abbrev=12 2>/dev/null)" |
| 62 | [ ! -z "$GITHASH" ] && GITHASH="-DTOYBOX_VERSION=\"$GITHASH\"" |
Rob Landley | 912b2be | 2015-02-07 17:20:23 -0600 | [diff] [blame] | 63 | TOYFILES="$(sed -n 's/^CONFIG_\([^=]*\)=.*/\1/p' "$KCONFIG_CONFIG" | xargs | tr ' [A-Z]' '|[a-z]')" |
| 64 | TOYFILES="$(egrep -l "TOY[(]($TOYFILES)[ ,]" toys/*/*.c)" |
Rob Landley | a913d92 | 2015-05-09 17:07:22 -0500 | [diff] [blame^] | 65 | CFLAGS="$CFLAGS $(cat generated/cflags)" |
Rob Landley | 90afbad | 2015-04-17 02:46:11 -0500 | [diff] [blame] | 66 | BUILD="$(echo ${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE $GITHASH)" |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 67 | FILES="$(echo lib/*.c main.c $TOYFILES)" |
| 68 | |
| 69 | genbuildsh() |
| 70 | { |
| 71 | # Write a canned build line for use on crippled build machines. |
| 72 | |
| 73 | echo "#!/bin/sh" |
| 74 | echo |
| 75 | echo "BUILD=\"$BUILD\"" |
| 76 | echo |
| 77 | echo "FILES=\"$FILES\"" |
| 78 | echo |
| 79 | echo "LINK=\"$LINK\"" |
| 80 | echo |
| 81 | echo |
| 82 | echo '$BUILD $FILES $LINK' |
| 83 | } |
| 84 | |
| 85 | if ! cmp -s <(genbuildsh | head -n 3) \ |
| 86 | <(head -n 3 generated/build.sh 2>/dev/null) |
| 87 | then |
| 88 | echo -n "Library probe" |
| 89 | |
| 90 | # We trust --as-needed to remove each library if we don't use any symbols |
| 91 | # out of it, this loop is because the compiler has no way to ignore a library |
| 92 | # that doesn't exist, so we have to detect and skip nonexistent libraries |
| 93 | # for it. |
| 94 | |
| 95 | > generated/optlibs.dat |
Xavier Roche | 58c3269 | 2015-04-17 20:18:30 -0500 | [diff] [blame] | 96 | for i in util crypt m resolv selinux smack attr |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 97 | do |
| 98 | echo "int main(int argc, char *argv[]) {return 0;}" | \ |
| 99 | ${CROSS_COMPILE}${CC} $CFLAGS -xc - -o /dev/null -Wl,--as-needed -l$i > /dev/null 2>/dev/null && |
| 100 | echo -l$i >> generated/optlibs.dat |
| 101 | echo -n . |
| 102 | done |
| 103 | echo |
| 104 | fi |
| 105 | |
| 106 | # LINK needs optlibs.dat, above |
| 107 | |
Rob Landley | 57f93c8 | 2015-02-28 12:39:16 -0600 | [diff] [blame] | 108 | LINK="$(echo $LDOPTIMIZE $LDFLAGS -o toybox_unstripped -Wl,--as-needed $(cat generated/optlibs.dat))" |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 109 | genbuildsh > generated/build.sh && chmod +x generated/build.sh || exit 1 |
| 110 | |
Rob Landley | d04dc1f | 2013-08-30 01:53:31 -0500 | [diff] [blame] | 111 | echo "Make generated/config.h from $KCONFIG_CONFIG." |
Rob Landley | 2896480 | 2008-01-19 17:08:39 -0600 | [diff] [blame] | 112 | |
| 113 | # This long and roundabout sed invocation is to make old versions of sed happy. |
| 114 | # New ones have '\n' so can replace one line with two without all the branches |
| 115 | # and tedious mucking about with hold space. |
| 116 | |
Rob Landley | 1193a02 | 2009-01-30 16:10:55 -0600 | [diff] [blame] | 117 | sed -n \ |
| 118 | -e 's/^# CONFIG_\(.*\) is not set.*/\1/' \ |
| 119 | -e 't notset' \ |
| 120 | -e 's/^CONFIG_\(.*\)=y.*/\1/' \ |
| 121 | -e 't isset' \ |
Rob Landley | 687bea5 | 2009-01-30 16:17:35 -0600 | [diff] [blame] | 122 | -e 's/^CONFIG_\([^=]*\)=\(.*\)/#define CFG_\1 \2/p' \ |
Rob Landley | 1193a02 | 2009-01-30 16:10:55 -0600 | [diff] [blame] | 123 | -e 'd' \ |
| 124 | -e ':notset' \ |
| 125 | -e 'h' \ |
| 126 | -e 's/.*/#define CFG_& 0/p' \ |
| 127 | -e 'g' \ |
| 128 | -e 's/.*/#define USE_&(...)/p' \ |
| 129 | -e 'd' \ |
| 130 | -e ':isset' \ |
| 131 | -e 'h' \ |
| 132 | -e 's/.*/#define CFG_& 1/p' \ |
| 133 | -e 'g' \ |
| 134 | -e 's/.*/#define USE_&(...) __VA_ARGS__/p' \ |
Rob Landley | d04dc1f | 2013-08-30 01:53:31 -0500 | [diff] [blame] | 135 | $KCONFIG_CONFIG > generated/config.h || exit 1 |
Rob Landley | 2896480 | 2008-01-19 17:08:39 -0600 | [diff] [blame] | 136 | |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 137 | if [ generated/mkflags -ot scripts/mkflags.c ] |
| 138 | then |
| 139 | do_loudly $HOSTCC scripts/mkflags.c -o generated/mkflags || exit 1 |
| 140 | fi |
Rob Landley | 6cf0a11 | 2012-11-26 14:14:29 -0600 | [diff] [blame] | 141 | |
Rob Landley | 46c8069 | 2013-12-28 17:06:55 -0600 | [diff] [blame] | 142 | echo -n "generated/flags.h " |
Rob Landley | 207cada | 2013-10-03 03:18:00 -0500 | [diff] [blame] | 143 | |
Rob Landley | e36a9dd | 2014-02-23 20:11:06 -0600 | [diff] [blame] | 144 | # Process config.h and newtoys.h to generate FLAG_x macros. Note we must |
| 145 | # always #define the relevant macro, even when it's disabled, because we |
| 146 | # allow multiple NEWTOY() in the same C file. (When disabled the FLAG is 0, |
| 147 | # so flags&0 becomes a constant 0 allowing dead code elimination.) |
| 148 | |
Rob Landley | 207cada | 2013-10-03 03:18:00 -0500 | [diff] [blame] | 149 | # Parse files through C preprocessor twice, once to get flags for current |
| 150 | # .config and once to get flags for allyesconfig |
| 151 | for I in A B |
| 152 | do |
| 153 | ( |
| 154 | # define macros and select header files with option string data |
| 155 | |
| 156 | echo "#define NEWTOY(aa,bb,cc) aa $I bb" |
| 157 | echo '#define OLDTOY(...)' |
| 158 | if [ "$I" == A ] |
| 159 | then |
| 160 | cat generated/config.h |
| 161 | else |
| 162 | sed '/USE_.*([^)]*)$/s/$/ __VA_ARGS__/' generated/config.h |
| 163 | fi |
| 164 | cat generated/newtoys.h |
| 165 | |
| 166 | # Run result through preprocessor, glue together " " gaps leftover from USE |
| 167 | # macros, delete comment lines, print any line with a quoted optstring, |
| 168 | # turn any non-quoted opstring (NULL or 0) into " " (because fscanf can't |
Rob Landley | 170c397 | 2014-02-28 20:46:16 -0600 | [diff] [blame] | 169 | # handle "" with nothing in it, and mkflags uses that). |
Rob Landley | 207cada | 2013-10-03 03:18:00 -0500 | [diff] [blame] | 170 | |
Rob Landley | 73fff3b | 2013-10-23 02:52:01 -0500 | [diff] [blame] | 171 | ) | ${CROSS_COMPILE}${CC} -E - | \ |
Rob Landley | 170c397 | 2014-02-28 20:46:16 -0600 | [diff] [blame] | 172 | sed -n -e 's/" *"//g;/^#/d;t clear;:clear;s/"/"/p;t;s/\( [AB] \).*/\1 " "/p' |
Rob Landley | 207cada | 2013-10-03 03:18:00 -0500 | [diff] [blame] | 173 | |
| 174 | # Sort resulting line pairs and glue them together into triplets of |
| 175 | # command "flags" "allflags" |
| 176 | # to feed into mkflags C program that outputs actual flag macros |
Rob Landley | e36a9dd | 2014-02-23 20:11:06 -0600 | [diff] [blame] | 177 | # If no pair (because command's disabled in config), use " " for flags |
| 178 | # so allflags can define the appropriate zero macros. |
Rob Landley | 207cada | 2013-10-03 03:18:00 -0500 | [diff] [blame] | 179 | |
Elliott Hughes | 627cd0f | 2014-12-23 19:17:13 -0600 | [diff] [blame] | 180 | done | sort -s | sed -n 's/ A / /;t pair;h;s/\([^ ]*\).*/\1 " "/;x;b single;:pair;h;n;:single;s/[^ ]* B //;H;g;s/\n/ /;p' |\ |
Rob Landley | 207cada | 2013-10-03 03:18:00 -0500 | [diff] [blame] | 181 | generated/mkflags > generated/flags.h || exit 1 |
Rob Landley | 6cf0a11 | 2012-11-26 14:14:29 -0600 | [diff] [blame] | 182 | |
Rob Landley | c0e56ed | 2012-10-08 00:02:30 -0500 | [diff] [blame] | 183 | # Extract global structure definitions and flag definitions from toys/*/*.c |
| 184 | |
| 185 | function getglobals() |
| 186 | { |
Rob Landley | c0e56ed | 2012-10-08 00:02:30 -0500 | [diff] [blame] | 187 | for i in toys/*/*.c |
| 188 | do |
| 189 | NAME="$(echo $i | sed 's@.*/\(.*\)\.c@\1@')" |
Rob Landley | 207cada | 2013-10-03 03:18:00 -0500 | [diff] [blame] | 190 | DATA="$(sed -n -e '/^GLOBALS(/,/^)/b got;b;:got' \ |
| 191 | -e 's/^GLOBALS(/struct '"$NAME"'_data {/' \ |
| 192 | -e 's/^)/};/' -e 'p' $i)" |
Rob Landley | c0e56ed | 2012-10-08 00:02:30 -0500 | [diff] [blame] | 193 | |
Rob Landley | 207cada | 2013-10-03 03:18:00 -0500 | [diff] [blame] | 194 | [ ! -z "$DATA" ] && echo -e "// $i\n\n$DATA\n" |
Rob Landley | c0e56ed | 2012-10-08 00:02:30 -0500 | [diff] [blame] | 195 | done |
| 196 | } |
| 197 | |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 198 | if isnewer generated/globals.h toys |
| 199 | then |
| 200 | echo -n "generated/globals.h " |
| 201 | GLOBSTRUCT="$(getglobals)" |
| 202 | ( |
| 203 | echo "$GLOBSTRUCT" |
| 204 | echo |
| 205 | echo "extern union global_union {" |
| 206 | echo "$GLOBSTRUCT" | \ |
| 207 | sed -n 's/struct \(.*\)_data {/ struct \1_data \1;/p' |
| 208 | echo "} this;" |
| 209 | ) > generated/globals.h |
| 210 | fi |
Rob Landley | c0e56ed | 2012-10-08 00:02:30 -0500 | [diff] [blame] | 211 | |
| 212 | echo "generated/help.h" |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 213 | if [ generated/config2help -ot scripts/config2help.c ] |
| 214 | then |
| 215 | do_loudly $HOSTCC scripts/config2help.c -I . lib/xwrap.c lib/llist.c \ |
Rob Landley | 79839a4 | 2014-12-13 12:09:25 -0600 | [diff] [blame] | 216 | lib/lib.c lib/portability.c -o generated/config2help || exit 1 |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 217 | fi |
Rob Landley | 0e040df | 2014-02-04 06:14:30 -0600 | [diff] [blame] | 218 | generated/config2help Config.in $KCONFIG_CONFIG > generated/help.h || exit 1 |
Rob Landley | c0e56ed | 2012-10-08 00:02:30 -0500 | [diff] [blame] | 219 | |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 220 | [ ! -z "$NOBUILD" ] && exit 0 |
Rob Landley | fb98c1e | 2012-05-23 21:54:16 -0500 | [diff] [blame] | 221 | |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 222 | echo -n "Compile toybox" |
| 223 | [ ! -z "$V" ] && echo |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 224 | DOTPROG=. |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 225 | |
| 226 | # This is a parallel version of: do_loudly $BUILD $FILES $LINK || exit 1 |
| 227 | |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 228 | X="$(ls -1t generated/obj/* 2>/dev/null | tail -n 1)" |
| 229 | if [ ! -e "$X" ] || [ ! -z "$(find toys -name "*.h" -newer "$X")" ] |
| 230 | then |
| 231 | rm -rf generated/obj && mkdir -p generated/obj || exit 1 |
| 232 | else |
| 233 | rm -f generated/obj/{main,lib_help}.o || exit 1 |
| 234 | fi |
Rob Landley | 5d16faa | 2014-08-24 22:42:47 -0500 | [diff] [blame] | 235 | PENDING= |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 236 | LFILES= |
Rob Landley | 42a36d6 | 2014-11-28 17:30:46 -0600 | [diff] [blame] | 237 | DONE=0 |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 238 | for i in $FILES |
| 239 | do |
Rob Landley | 7a07c6b | 2014-09-09 20:13:03 -0500 | [diff] [blame] | 240 | # build each generated/obj/*.o file in parallel |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 241 | |
| 242 | X=${i/lib\//lib_} |
| 243 | X=${X##*/} |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 244 | OUT="generated/obj/${X%%.c}.o" |
| 245 | LFILES="$LFILES $OUT" |
| 246 | [ "$OUT" -nt "$i" ] && continue |
| 247 | do_loudly $BUILD -c $i -o $OUT & |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 248 | |
| 249 | # ratelimit to $CPUS many parallel jobs, detecting errors |
| 250 | |
| 251 | while true |
| 252 | do |
Rob Landley | 5d16faa | 2014-08-24 22:42:47 -0500 | [diff] [blame] | 253 | PENDING="$(echo $PENDING $(jobs -rp) | tr ' ' '\n' | sort -u)" |
Rob Landley | 9bb73ad | 2014-09-04 00:23:51 -0500 | [diff] [blame] | 254 | [ $(echo -n "$PENDING" | wc -l) -lt "$CPUS" ] && break; |
Rob Landley | 5d16faa | 2014-08-24 22:42:47 -0500 | [diff] [blame] | 255 | |
Rob Landley | 42a36d6 | 2014-11-28 17:30:46 -0600 | [diff] [blame] | 256 | wait $(echo "$PENDING" | head -n 1) |
| 257 | DONE=$(($DONE+$?)) |
Rob Landley | 5d16faa | 2014-08-24 22:42:47 -0500 | [diff] [blame] | 258 | PENDING="$(echo "$PENDING" | tail -n +2)" |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 259 | done |
Rob Landley | 42a36d6 | 2014-11-28 17:30:46 -0600 | [diff] [blame] | 260 | [ $DONE -ne 0 ] && break |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 261 | done |
| 262 | |
| 263 | # wait for all background jobs, detecting errors |
| 264 | |
Rob Landley | 5d16faa | 2014-08-24 22:42:47 -0500 | [diff] [blame] | 265 | for i in $PENDING |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 266 | do |
Rob Landley | 42a36d6 | 2014-11-28 17:30:46 -0600 | [diff] [blame] | 267 | wait $i |
| 268 | DONE=$(($DONE+$?)) |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 269 | done |
| 270 | |
Rob Landley | 42a36d6 | 2014-11-28 17:30:46 -0600 | [diff] [blame] | 271 | [ $DONE -ne 0 ] && exit 1 |
| 272 | |
Rob Landley | 62390fd | 2014-11-28 16:49:46 -0600 | [diff] [blame] | 273 | do_loudly $BUILD $LFILES $LINK || exit 1 |
Rob Landley | 1f44b5f | 2015-03-06 15:11:38 -0600 | [diff] [blame] | 274 | if ! do_loudly ${CROSS_COMPILE}strip toybox_unstripped -o toybox |
Rob Landley | 57f93c8 | 2015-02-28 12:39:16 -0600 | [diff] [blame] | 275 | then |
Rob Landley | 1f44b5f | 2015-03-06 15:11:38 -0600 | [diff] [blame] | 276 | echo "strip failed, using unstripped" && cp toybox_unstripped toybox || |
| 277 | exit 1 |
Rob Landley | 57f93c8 | 2015-02-28 12:39:16 -0600 | [diff] [blame] | 278 | fi |
Rob Landley | b704ad2 | 2009-12-13 00:12:26 -0600 | [diff] [blame] | 279 | # gcc 4.4's strip command is buggy, and doesn't set the executable bit on |
| 280 | # its output the way SUSv4 suggests it do so. |
Rob Landley | 1aa66ba | 2012-02-17 12:06:12 -0600 | [diff] [blame] | 281 | do_loudly chmod +x toybox || exit 1 |
Rob Landley | 91b360a | 2014-08-09 14:33:34 -0500 | [diff] [blame] | 282 | echo |