blob: 9c22d4f4e55f5b27431a66e95d095c4c15ba2e49 [file] [log] [blame]
Rob Landley28964802008-01-19 17:08:39 -06001#!/bin/bash
2
3# Grab default values for $CFLAGS and such.
4
Rob Landleyb3d4f0b2013-04-29 16:00:40 -05005export LANG=c
Rob Landley082a9a72014-08-30 16:34:46 -05006export LC_ALL=C
Rob Landley7a07c6b2014-09-09 20:13:03 -05007set -o pipefail
Rob Landley28964802008-01-19 17:08:39 -06008source ./configure
9
Rob Landleya8d0d132016-03-23 03:25:37 -050010[ -z "$KCONFIG_CONFIG" ] && KCONFIG_CONFIG=.config
11[ -z "$OUTNAME" ] && OUTNAME=toybox
12UNSTRIPPED="generated/unstripped/$(basename "$OUTNAME")"
Rob Landleyd04dc1f2013-08-30 01:53:31 -050013
Rob Landleyd3df4232014-09-20 13:07:53 -050014# Since each cc invocation is short, launch half again as many processes
15# as we have processors so they don't exit faster than we can start them.
Rob Landleycf6a2352017-05-14 15:10:29 -050016[ -z "$CPUS" ] && CPUS=$(($(nproc)+1))
Rob Landleyd3df4232014-09-20 13:07:53 -050017
Rob Landley72e25912016-12-07 22:22:38 -060018if [ -z "$SED" ]
19then
Rob Landley3701b512016-12-08 21:44:22 -060020 [ ! -z "$(which gsed 2>/dev/null)" ] && SED=gsed || SED=sed
Rob Landley72e25912016-12-07 22:22:38 -060021fi
22
Rob Landley86cafe12014-01-03 18:23:09 -060023# Respond to V= by echoing command lines as well as running them
Rob Landley62390fd2014-11-28 16:49:46 -060024DOTPROG=
Rob Landley86cafe12014-01-03 18:23:09 -060025do_loudly()
26{
Rob Landley62390fd2014-11-28 16:49:46 -060027 [ ! -z "$V" ] && echo "$@" || echo -n "$DOTPROG"
Rob Landley86cafe12014-01-03 18:23:09 -060028 "$@"
29}
30
Rob Landley62390fd2014-11-28 16:49:46 -060031# Is anything under directory $2 newer than file $1
32isnewer()
33{
Rob Landley9cfdb482016-05-20 07:32:51 -050034 CHECK="$1"
35 shift
36 [ ! -z "$(find "$@" -newer "$CHECK" 2>/dev/null || echo yes)" ]
Rob Landley62390fd2014-11-28 16:49:46 -060037}
38
39echo "Generate headers from toys/*/*.c..."
40
Rob Landleya8d0d132016-03-23 03:25:37 -050041mkdir -p generated/unstripped
Rob Landley62390fd2014-11-28 16:49:46 -060042
43if isnewer generated/Config.in toys
44then
45 echo "Extract configuration information from toys/*.c files..."
46 scripts/genconfig.sh
47fi
48
49# Create a list of all the commands toybox can provide. Note that the first
50# entry is out of order on purpose (the toybox multiplexer command must be the
51# first element of the array). The rest must be sorted in alphabetical order
52# for fast binary search.
53
54if isnewer generated/newtoys.h toys
55then
56 echo -n "generated/newtoys.h "
57
58 echo "USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT))" > generated/newtoys.h
Rob Landley72e25912016-12-07 22:22:38 -060059 $SED -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \
60 | $SED 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -s -k 1,1 \
Rob Landley3dd0d0d2016-12-07 22:57:12 -060061 | $SED 's/[^ ]* //' >> generated/newtoys.h
62 [ $? -ne 0 ] && exit 1
Rob Landley62390fd2014-11-28 16:49:46 -060063fi
64
65[ ! -z "$V" ] && echo "Which C files to build..."
66
67# Extract a list of toys/*/*.c files to compile from the data in $KCONFIG_CONFIG
Rob Landley912b2be2015-02-07 17:20:23 -060068# (First command names, then filenames with relevant {NEW,OLD}TOY() macro.)
69
Rob Landley90afbad2015-04-17 02:46:11 -050070GITHASH="$(git describe --tags --abbrev=12 2>/dev/null)"
71[ ! -z "$GITHASH" ] && GITHASH="-DTOYBOX_VERSION=\"$GITHASH\""
Rob Landley72e25912016-12-07 22:22:38 -060072TOYFILES="$($SED -n 's/^CONFIG_\([^=]*\)=.*/\1/p' "$KCONFIG_CONFIG" | xargs | tr ' [A-Z]' '|[a-z]')"
Rob Landley912b2be2015-02-07 17:20:23 -060073TOYFILES="$(egrep -l "TOY[(]($TOYFILES)[ ,]" toys/*/*.c)"
Rob Landleya913d922015-05-09 17:07:22 -050074CFLAGS="$CFLAGS $(cat generated/cflags)"
Rob Landley90afbad2015-04-17 02:46:11 -050075BUILD="$(echo ${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE $GITHASH)"
Rob Landley9cfdb482016-05-20 07:32:51 -050076LIBFILES="$(ls lib/*.c | grep -v lib/help.c)"
77TOYFILES="lib/help.c main.c $TOYFILES"
Rob Landley62390fd2014-11-28 16:49:46 -060078
Rob Landley712e43e2016-02-07 18:15:53 -060079if [ "${TOYFILES/pending//}" != "$TOYFILES" ]
Rob Landley36790242016-02-07 12:27:40 -060080then
81 echo -e "\n\033[1;31mwarning: using unfinished code from toys/pending\033[0m"
82fi
83
Rob Landley62390fd2014-11-28 16:49:46 -060084genbuildsh()
85{
86 # Write a canned build line for use on crippled build machines.
87
88 echo "#!/bin/sh"
89 echo
Rob Landleyd620f772016-07-05 19:36:00 -050090 echo "BUILD='$BUILD'"
Rob Landley62390fd2014-11-28 16:49:46 -060091 echo
Rob Landleyd620f772016-07-05 19:36:00 -050092 echo "FILES='$LIBFILES $TOYFILES'"
Rob Landley62390fd2014-11-28 16:49:46 -060093 echo
Rob Landleyd620f772016-07-05 19:36:00 -050094 echo "LINK='$LINK'"
Rob Landley62390fd2014-11-28 16:49:46 -060095 echo
96 echo
97 echo '$BUILD $FILES $LINK'
98}
99
100if ! cmp -s <(genbuildsh | head -n 3) \
101 <(head -n 3 generated/build.sh 2>/dev/null)
102then
103 echo -n "Library probe"
104
105 # We trust --as-needed to remove each library if we don't use any symbols
106 # out of it, this loop is because the compiler has no way to ignore a library
107 # that doesn't exist, so we have to detect and skip nonexistent libraries
108 # for it.
109
110 > generated/optlibs.dat
Elliott Hughes333b4d32017-04-28 15:25:56 -0700111 for i in util crypt m resolv selinux smack attr rt crypto z log
Rob Landley62390fd2014-11-28 16:49:46 -0600112 do
113 echo "int main(int argc, char *argv[]) {return 0;}" | \
Rob Landley712e1632015-09-23 22:10:23 -0500114 ${CROSS_COMPILE}${CC} $CFLAGS -xc - -o generated/libprobe -Wl,--as-needed -l$i > /dev/null 2>/dev/null &&
Rob Landley62390fd2014-11-28 16:49:46 -0600115 echo -l$i >> generated/optlibs.dat
116 echo -n .
117 done
Rob Landley712e1632015-09-23 22:10:23 -0500118 rm -f generated/libprobe
Rob Landley62390fd2014-11-28 16:49:46 -0600119 echo
120fi
121
122# LINK needs optlibs.dat, above
123
Rob Landleya8d0d132016-03-23 03:25:37 -0500124LINK="$(echo $LDOPTIMIZE $LDFLAGS -o "$UNSTRIPPED" -Wl,--as-needed $(cat generated/optlibs.dat))"
Rob Landley62390fd2014-11-28 16:49:46 -0600125genbuildsh > generated/build.sh && chmod +x generated/build.sh || exit 1
126
Rob Landley72e25912016-12-07 22:22:38 -0600127#TODO: "make $SED && make" doesn't regenerate config.h because diff .config
Rob Landley3214c872016-10-20 15:26:38 -0500128if true #isnewer generated/config.h "$KCONFIG_CONFIG"
Rob Landley9cfdb482016-05-20 07:32:51 -0500129then
130 echo "Make generated/config.h from $KCONFIG_CONFIG."
Rob Landley28964802008-01-19 17:08:39 -0600131
Rob Landley9cfdb482016-05-20 07:32:51 -0500132 # This long and roundabout sed invocation is to make old versions of sed
133 # happy. New ones have '\n' so can replace one line with two without all
134 # the branches and tedious mucking about with hold space.
Rob Landley28964802008-01-19 17:08:39 -0600135
Rob Landley72e25912016-12-07 22:22:38 -0600136 $SED -n \
Rob Landley9cfdb482016-05-20 07:32:51 -0500137 -e 's/^# CONFIG_\(.*\) is not set.*/\1/' \
138 -e 't notset' \
139 -e 's/^CONFIG_\(.*\)=y.*/\1/' \
140 -e 't isset' \
141 -e 's/^CONFIG_\([^=]*\)=\(.*\)/#define CFG_\1 \2/p' \
142 -e 'd' \
143 -e ':notset' \
144 -e 'h' \
145 -e 's/.*/#define CFG_& 0/p' \
146 -e 'g' \
147 -e 's/.*/#define USE_&(...)/p' \
148 -e 'd' \
149 -e ':isset' \
150 -e 'h' \
151 -e 's/.*/#define CFG_& 1/p' \
152 -e 'g' \
153 -e 's/.*/#define USE_&(...) __VA_ARGS__/p' \
154 $KCONFIG_CONFIG > generated/config.h || exit 1
155fi
Rob Landley28964802008-01-19 17:08:39 -0600156
Rob Landley62390fd2014-11-28 16:49:46 -0600157if [ generated/mkflags -ot scripts/mkflags.c ]
158then
159 do_loudly $HOSTCC scripts/mkflags.c -o generated/mkflags || exit 1
160fi
Rob Landley6cf0a112012-11-26 14:14:29 -0600161
Rob Landleye36a9dd2014-02-23 20:11:06 -0600162# Process config.h and newtoys.h to generate FLAG_x macros. Note we must
163# always #define the relevant macro, even when it's disabled, because we
164# allow multiple NEWTOY() in the same C file. (When disabled the FLAG is 0,
165# so flags&0 becomes a constant 0 allowing dead code elimination.)
166
Rob Landley9cfdb482016-05-20 07:32:51 -0500167make_flagsh()
168{
169 # Parse files through C preprocessor twice, once to get flags for current
170 # .config and once to get flags for allyesconfig
171 for I in A B
172 do
173 (
174 # define macros and select header files with option string data
Rob Landley207cada2013-10-03 03:18:00 -0500175
Rob Landley9cfdb482016-05-20 07:32:51 -0500176 echo "#define NEWTOY(aa,bb,cc) aa $I bb"
177 echo '#define OLDTOY(...)'
178 if [ "$I" == A ]
179 then
180 cat generated/config.h
181 else
Rob Landley72e25912016-12-07 22:22:38 -0600182 $SED '/USE_.*([^)]*)$/s/$/ __VA_ARGS__/' generated/config.h
Rob Landley9cfdb482016-05-20 07:32:51 -0500183 fi
Rob Landleycb8e5ad2017-03-20 12:41:22 -0500184 echo '#include "lib/toyflags.h"'
Rob Landley9cfdb482016-05-20 07:32:51 -0500185 cat generated/newtoys.h
Rob Landley207cada2013-10-03 03:18:00 -0500186
Rob Landley9cfdb482016-05-20 07:32:51 -0500187 # Run result through preprocessor, glue together " " gaps leftover from USE
188 # macros, delete comment lines, print any line with a quoted optstring,
189 # turn any non-quoted opstring (NULL or 0) into " " (because fscanf can't
190 # handle "" with nothing in it, and mkflags uses that).
Rob Landley207cada2013-10-03 03:18:00 -0500191
Rob Landley9cfdb482016-05-20 07:32:51 -0500192 ) | ${CROSS_COMPILE}${CC} -E - | \
Rob Landley72e25912016-12-07 22:22:38 -0600193 $SED -n -e 's/" *"//g;/^#/d;t clear;:clear;s/"/"/p;t;s/\( [AB] \).*/\1 " "/p'
Rob Landley207cada2013-10-03 03:18:00 -0500194
Rob Landley9cfdb482016-05-20 07:32:51 -0500195 # Sort resulting line pairs and glue them together into triplets of
196 # command "flags" "allflags"
197 # to feed into mkflags C program that outputs actual flag macros
198 # If no pair (because command's disabled in config), use " " for flags
199 # so allflags can define the appropriate zero macros.
Rob Landley207cada2013-10-03 03:18:00 -0500200
Rob Landley72e25912016-12-07 22:22:38 -0600201 done | sort -s | $SED -n -e 's/ A / /;t pair;h;s/\([^ ]*\).*/\1 " "/;x' \
Rob Landley9cfdb482016-05-20 07:32:51 -0500202 -e 'b single;:pair;h;n;:single;s/[^ ]* B //;H;g;s/\n/ /;p' | \
203 tee generated/flags.raw | generated/mkflags > generated/flags.h || exit 1
204}
205
206if isnewer generated/flags.h toys "$KCONFIG_CONFIG"
207then
208 echo -n "generated/flags.h "
209 make_flagsh
210fi
Rob Landley6cf0a112012-11-26 14:14:29 -0600211
Rob Landleyc0e56ed2012-10-08 00:02:30 -0500212# Extract global structure definitions and flag definitions from toys/*/*.c
213
214function getglobals()
215{
Rob Landleyc0e56ed2012-10-08 00:02:30 -0500216 for i in toys/*/*.c
217 do
Rob Landley72e25912016-12-07 22:22:38 -0600218 NAME="$(echo $i | $SED 's@.*/\(.*\)\.c@\1@')"
219 DATA="$($SED -n -e '/^GLOBALS(/,/^)/b got;b;:got' \
Rob Landley207cada2013-10-03 03:18:00 -0500220 -e 's/^GLOBALS(/struct '"$NAME"'_data {/' \
221 -e 's/^)/};/' -e 'p' $i)"
Rob Landleyc0e56ed2012-10-08 00:02:30 -0500222
Rob Landley207cada2013-10-03 03:18:00 -0500223 [ ! -z "$DATA" ] && echo -e "// $i\n\n$DATA\n"
Rob Landleyc0e56ed2012-10-08 00:02:30 -0500224 done
225}
226
Rob Landley62390fd2014-11-28 16:49:46 -0600227if isnewer generated/globals.h toys
228then
229 echo -n "generated/globals.h "
230 GLOBSTRUCT="$(getglobals)"
231 (
232 echo "$GLOBSTRUCT"
233 echo
234 echo "extern union global_union {"
235 echo "$GLOBSTRUCT" | \
Rob Landley72e25912016-12-07 22:22:38 -0600236 $SED -n 's/struct \(.*\)_data {/ struct \1_data \1;/p'
Rob Landley62390fd2014-11-28 16:49:46 -0600237 echo "} this;"
238 ) > generated/globals.h
239fi
Rob Landleyc0e56ed2012-10-08 00:02:30 -0500240
Rob Landleyf96bb3d2015-12-13 16:52:26 -0600241if [ generated/mktags -ot scripts/mktags.c ]
242then
243 do_loudly $HOSTCC scripts/mktags.c -o generated/mktags || exit 1
244fi
245
246if isnewer generated/tags.h toys
247then
248 echo -n "generated/tags.h "
249
Rob Landley72e25912016-12-07 22:22:38 -0600250 $SED -n '/TAGGED_ARRAY(/,/^)/{s/.*TAGGED_ARRAY[(]\([^,]*\),/\1/;p}' \
Rob Landley4b4ab6a2015-12-27 14:41:30 -0600251 toys/*/*.c lib/*.c | generated/mktags > generated/tags.h
Rob Landleyf96bb3d2015-12-13 16:52:26 -0600252fi
253
Rob Landley62390fd2014-11-28 16:49:46 -0600254if [ generated/config2help -ot scripts/config2help.c ]
255then
Rob Landleyd20b9ff2015-11-02 08:32:21 -0600256 do_loudly $HOSTCC scripts/config2help.c -I . lib/xwrap.c lib/llist.c \
Rob Landley79839a42014-12-13 12:09:25 -0600257 lib/lib.c lib/portability.c -o generated/config2help || exit 1
Rob Landley62390fd2014-11-28 16:49:46 -0600258fi
Rob Landley9cfdb482016-05-20 07:32:51 -0500259if isnewer generated/help.h generated/Config.in
260then
261 echo "generated/help.h"
262 generated/config2help Config.in $KCONFIG_CONFIG > generated/help.h || exit 1
263fi
Rob Landleyc0e56ed2012-10-08 00:02:30 -0500264
Rob Landley62390fd2014-11-28 16:49:46 -0600265[ ! -z "$NOBUILD" ] && exit 0
Rob Landleyfb98c1e2012-05-23 21:54:16 -0500266
Rob Landley91b360a2014-08-09 14:33:34 -0500267echo -n "Compile toybox"
268[ ! -z "$V" ] && echo
Rob Landley62390fd2014-11-28 16:49:46 -0600269DOTPROG=.
Rob Landley91b360a2014-08-09 14:33:34 -0500270
271# This is a parallel version of: do_loudly $BUILD $FILES $LINK || exit 1
272
Rob Landley9cfdb482016-05-20 07:32:51 -0500273# Any headers newer than the oldest generated/obj file?
Rob Landley62390fd2014-11-28 16:49:46 -0600274X="$(ls -1t generated/obj/* 2>/dev/null | tail -n 1)"
Rob Landley9cfdb482016-05-20 07:32:51 -0500275# TODO: redo this
Rob Landley62390fd2014-11-28 16:49:46 -0600276if [ ! -e "$X" ] || [ ! -z "$(find toys -name "*.h" -newer "$X")" ]
277then
278 rm -rf generated/obj && mkdir -p generated/obj || exit 1
279else
280 rm -f generated/obj/{main,lib_help}.o || exit 1
281fi
Rob Landley9cfdb482016-05-20 07:32:51 -0500282
283# build each generated/obj/*.o file in parallel
284
Rob Landley5d16faa2014-08-24 22:42:47 -0500285PENDING=
Rob Landley9cfdb482016-05-20 07:32:51 -0500286LNKFILES=
Rob Landley42a36d62014-11-28 17:30:46 -0600287DONE=0
Rob Landley86f7c042016-03-01 23:39:27 -0600288COUNT=0
Rob Landley9cfdb482016-05-20 07:32:51 -0500289CLICK=
290
291for i in $LIBFILES click $TOYFILES
Rob Landley91b360a2014-08-09 14:33:34 -0500292do
Rob Landley9cfdb482016-05-20 07:32:51 -0500293 [ "$i" == click ] && CLICK=1 && continue
Rob Landley91b360a2014-08-09 14:33:34 -0500294
295 X=${i/lib\//lib_}
296 X=${X##*/}
Rob Landley62390fd2014-11-28 16:49:46 -0600297 OUT="generated/obj/${X%%.c}.o"
Rob Landley9cfdb482016-05-20 07:32:51 -0500298 LNKFILES="$LNKFILES $OUT"
299
300 # $LIBFILES doesn't need to be rebuilt if newer than .config, $TOYFILES does
301
302 [ "$OUT" -nt "$i" ] && [ -z "$CLICK" -o "$OUT" -nt "$KCONFIG_CONFIG" ] &&
303 continue
304
Rob Landley62390fd2014-11-28 16:49:46 -0600305 do_loudly $BUILD -c $i -o $OUT &
Rob Landleye17fbf12016-02-26 00:22:15 -0600306 PENDING="$PENDING $!"
Rob Landley86f7c042016-03-01 23:39:27 -0600307 COUNT=$(($COUNT+1))
Rob Landley91b360a2014-08-09 14:33:34 -0500308
309 # ratelimit to $CPUS many parallel jobs, detecting errors
310
Rob Landley86f7c042016-03-01 23:39:27 -0600311 for j in $PENDING
Rob Landley91b360a2014-08-09 14:33:34 -0500312 do
Rob Landley86f7c042016-03-01 23:39:27 -0600313 [ "$COUNT" -lt "$CPUS" ] && break;
Rob Landley5d16faa2014-08-24 22:42:47 -0500314
Rob Landley86f7c042016-03-01 23:39:27 -0600315 wait $j
Rob Landley42a36d62014-11-28 17:30:46 -0600316 DONE=$(($DONE+$?))
Rob Landley86f7c042016-03-01 23:39:27 -0600317 COUNT=$(($COUNT-1))
318 PENDING="${PENDING## $j}"
Rob Landley91b360a2014-08-09 14:33:34 -0500319 done
Rob Landley42a36d62014-11-28 17:30:46 -0600320 [ $DONE -ne 0 ] && break
Rob Landley91b360a2014-08-09 14:33:34 -0500321done
322
323# wait for all background jobs, detecting errors
324
Rob Landley5d16faa2014-08-24 22:42:47 -0500325for i in $PENDING
Rob Landley91b360a2014-08-09 14:33:34 -0500326do
Rob Landley42a36d62014-11-28 17:30:46 -0600327 wait $i
328 DONE=$(($DONE+$?))
Rob Landley91b360a2014-08-09 14:33:34 -0500329done
330
Rob Landley42a36d62014-11-28 17:30:46 -0600331[ $DONE -ne 0 ] && exit 1
332
Rob Landley9cfdb482016-05-20 07:32:51 -0500333do_loudly $BUILD $LNKFILES $LINK || exit 1
Rob Landleya8d0d132016-03-23 03:25:37 -0500334if [ ! -z "$NOSTRIP" ] ||
335 ! do_loudly ${CROSS_COMPILE}strip "$UNSTRIPPED" -o "$OUTNAME"
Rob Landley57f93c82015-02-28 12:39:16 -0600336then
Rob Landleya8d0d132016-03-23 03:25:37 -0500337 echo "strip failed, using unstripped" && cp "$UNSTRIPPED" "$OUTNAME" ||
Rob Landley1f44b5f2015-03-06 15:11:38 -0600338 exit 1
Rob Landley57f93c82015-02-28 12:39:16 -0600339fi
Rob Landleyb8f5eff2015-10-29 07:34:08 -0500340
341# gcc 4.4's strip command is buggy, and doesn't set the executable bit on
342# its output the way SUSv4 suggests it do so. While we're at it, make sure
343# we don't have the "w" bit set so things like bzip2's "cp -f" install don't
344# overwrite our binary through the symlink.
Rob Landleya8d0d132016-03-23 03:25:37 -0500345do_loudly chmod 555 "$OUTNAME" || exit 1
Rob Landleyb8f5eff2015-10-29 07:34:08 -0500346
Rob Landley91b360a2014-08-09 14:33:34 -0500347echo