comparison scripts/make.sh @ 1578:a34104fc7544 draft

Add "make change" target to build the big toybox binary as a bunch of little ones (in the "change" subdirectory), and tweak scripts/make.sh to avoid redundant work when rebuilding.
author Rob Landley <rob@landley.net>
date Fri, 28 Nov 2014 16:49:46 -0600
parents 8bf5f528d352
children 1250bc526316
comparison
equal deleted inserted replaced
1577:ac84a209cb05 1578:a34104fc7544
13 # as we have processors so they don't exit faster than we can start them. 13 # as we have processors so they don't exit faster than we can start them.
14 [ -z "$CPUS" ] && 14 [ -z "$CPUS" ] &&
15 CPUS=$((($(echo /sys/devices/system/cpu/cpu[0-9]* | wc -w)*3)/2)) 15 CPUS=$((($(echo /sys/devices/system/cpu/cpu[0-9]* | wc -w)*3)/2))
16 16
17 # Respond to V= by echoing command lines as well as running them 17 # Respond to V= by echoing command lines as well as running them
18 DOTPROG=
18 do_loudly() 19 do_loudly()
19 { 20 {
20 [ ! -z "$V" ] && echo "$@" 21 [ ! -z "$V" ] && echo "$@" || echo -n "$DOTPROG"
21 "$@" 22 "$@"
22 } 23 }
23 24
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
24 mkdir -p generated 33 mkdir -p generated
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 \
52 | sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -k 1,1 \
53 | sed 's/[^ ]* //' >> generated/newtoys.h &&
54 sed -n -e 's/.*(NEWTOY(\([^,]*\), *\(\("[^"]*"[^,]*\)*\),.*/#define OPTSTR_\1\t\2/p' \
55 generated/newtoys.h > generated/oldtoys.h || exit 1
56 fi
57
58 [ ! -z "$V" ] && echo "Which C files to build..."
59
60 # Extract a list of toys/*/*.c files to compile from the data in $KCONFIG_CONFIG
61 TOYFILES="$(egrep -l "TOY[(]($(sed -n 's/^CONFIG_\([^=]*\)=.*/\1/p' "$KCONFIG_CONFIG" | xargs | tr ' [A-Z]' '|[a-z]'))[ ,]" toys/*/*.c)"
62 BUILD="$(echo ${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE)"
63 FILES="$(echo lib/*.c main.c $TOYFILES)"
64
65 genbuildsh()
66 {
67 # Write a canned build line for use on crippled build machines.
68
69 echo "#!/bin/sh"
70 echo
71 echo "BUILD=\"$BUILD\""
72 echo
73 echo "FILES=\"$FILES\""
74 echo
75 echo "LINK=\"$LINK\""
76 echo
77 echo
78 echo '$BUILD $FILES $LINK'
79 }
80
81 if ! cmp -s <(genbuildsh | head -n 3) \
82 <(head -n 3 generated/build.sh 2>/dev/null)
83 then
84 echo -n "Library probe"
85
86 # We trust --as-needed to remove each library if we don't use any symbols
87 # out of it, this loop is because the compiler has no way to ignore a library
88 # that doesn't exist, so we have to detect and skip nonexistent libraries
89 # for it.
90
91 > generated/optlibs.dat
92 for i in util crypt m resolv
93 do
94 echo "int main(int argc, char *argv[]) {return 0;}" | \
95 ${CROSS_COMPILE}${CC} $CFLAGS -xc - -o /dev/null -Wl,--as-needed -l$i > /dev/null 2>/dev/null &&
96 echo -l$i >> generated/optlibs.dat
97 echo -n .
98 done
99 echo
100 fi
101
102 # LINK needs optlibs.dat, above
103
104 LINK="$(echo $LDOPTIMIZE -o toybox_unstripped -Wl,--as-needed $(cat generated/optlibs.dat))"
105 genbuildsh > generated/build.sh && chmod +x generated/build.sh || exit 1
106
25 echo "Make generated/config.h from $KCONFIG_CONFIG." 107 echo "Make generated/config.h from $KCONFIG_CONFIG."
26 108
27 # This long and roundabout sed invocation is to make old versions of sed happy. 109 # This long and roundabout sed invocation is to make old versions of sed happy.
28 # New ones have '\n' so can replace one line with two without all the branches 110 # New ones have '\n' so can replace one line with two without all the branches
29 # and tedious mucking about with hold space. 111 # and tedious mucking about with hold space.
46 -e 's/.*/#define CFG_& 1/p' \ 128 -e 's/.*/#define CFG_& 1/p' \
47 -e 'g' \ 129 -e 'g' \
48 -e 's/.*/#define USE_&(...) __VA_ARGS__/p' \ 130 -e 's/.*/#define USE_&(...) __VA_ARGS__/p' \
49 $KCONFIG_CONFIG > generated/config.h || exit 1 131 $KCONFIG_CONFIG > generated/config.h || exit 1
50 132
51 133 if [ generated/mkflags -ot scripts/mkflags.c ]
52 echo "Extract configuration information from toys/*.c files..." 134 then
53 scripts/genconfig.sh 135 do_loudly $HOSTCC scripts/mkflags.c -o generated/mkflags || exit 1
54 136 fi
55 echo "Generate headers from toys/*/*.c..."
56
57 # Create a list of all the commands toybox can provide. Note that the first
58 # entry is out of order on purpose (the toybox multiplexer command must be the
59 # first element of the array). The rest must be sorted in alphabetical order
60 # for fast binary search.
61
62 echo -n "generated/newtoys.h "
63
64 echo "USE_TOYBOX(NEWTOY(toybox, NULL, TOYFLAG_STAYROOT))" > generated/newtoys.h
65 sed -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \
66 | sed 's/\(.*TOY(\)\([^,]*\),\(.*\)/\2 \1\2,\3/' | sort -k 1,1 \
67 | sed 's/[^ ]* //' >> generated/newtoys.h
68 sed -n -e 's/.*(NEWTOY(\([^,]*\), *\(\("[^"]*"[^,]*\)*\),.*/#define OPTSTR_\1\t\2/p' \
69 generated/newtoys.h > generated/oldtoys.h
70
71 do_loudly $HOSTCC scripts/mkflags.c -o generated/mkflags || exit 1
72 137
73 echo -n "generated/flags.h " 138 echo -n "generated/flags.h "
74 139
75 # Process config.h and newtoys.h to generate FLAG_x macros. Note we must 140 # Process config.h and newtoys.h to generate FLAG_x macros. Note we must
76 # always #define the relevant macro, even when it's disabled, because we 141 # always #define the relevant macro, even when it's disabled, because we
124 189
125 [ ! -z "$DATA" ] && echo -e "// $i\n\n$DATA\n" 190 [ ! -z "$DATA" ] && echo -e "// $i\n\n$DATA\n"
126 done 191 done
127 } 192 }
128 193
129 echo -n "generated/globals.h " 194 if isnewer generated/globals.h toys
130 195 then
131 GLOBSTRUCT="$(getglobals)" 196 echo -n "generated/globals.h "
132 ( 197 GLOBSTRUCT="$(getglobals)"
133 echo "$GLOBSTRUCT" 198 (
134 echo 199 echo "$GLOBSTRUCT"
135 echo "extern union global_union {" 200 echo
136 echo "$GLOBSTRUCT" | sed -n 's/struct \(.*\)_data {/ struct \1_data \1;/p' 201 echo "extern union global_union {"
137 echo "} this;" 202 echo "$GLOBSTRUCT" | \
138 ) > generated/globals.h 203 sed -n 's/struct \(.*\)_data {/ struct \1_data \1;/p'
204 echo "} this;"
205 ) > generated/globals.h
206 fi
139 207
140 echo "generated/help.h" 208 echo "generated/help.h"
141 do_loudly $HOSTCC scripts/config2help.c -I . lib/xwrap.c lib/llist.c lib/lib.c \ 209 if [ generated/config2help -ot scripts/config2help.c ]
142 -o generated/config2help && \ 210 then
211 do_loudly $HOSTCC scripts/config2help.c -I . lib/xwrap.c lib/llist.c \
212 lib/lib.c -o generated/config2help || exit 1
213 fi
143 generated/config2help Config.in $KCONFIG_CONFIG > generated/help.h || exit 1 214 generated/config2help Config.in $KCONFIG_CONFIG > generated/help.h || exit 1
144 215
145 echo -n "Library probe" 216 [ ! -z "$NOBUILD" ] && exit 0
146
147 # We trust --as-needed to remove each library if we don't use any symbols
148 # out of it, this loop is because the compiler has no way to ignore a library
149 # that doesn't exist, so we have to detect and skip nonexistent libraries
150 # for it.
151
152 > generated/optlibs.dat
153 for i in util crypt m resolv
154 do
155 echo "int main(int argc, char *argv[]) {return 0;}" | \
156 ${CROSS_COMPILE}${CC} $CFLAGS -xc - -o /dev/null -Wl,--as-needed -l$i > /dev/null 2>/dev/null &&
157 echo -l$i >> generated/optlibs.dat
158 echo -n .
159 done
160 echo
161 217
162 echo -n "Compile toybox" 218 echo -n "Compile toybox"
163 [ ! -z "$V" ] && echo 219 [ ! -z "$V" ] && echo
164 220 DOTPROG=.
165 # Extract a list of toys/*/*.c files to compile from the data in $KCONFIG_CONFIG
166
167 TOYFILES="$(egrep -l "TOY[(]($(sed -n 's/^CONFIG_\([^=]*\)=.*/\1/p' "$KCONFIG_CONFIG" | xargs | tr ' [A-Z]' '|[a-z]'))[ ,]" toys/*/*.c)"
168
169 do_loudly()
170 {
171 [ ! -z "$V" ] && echo "$@" || echo -n .
172 "$@"
173 }
174
175 BUILD="$(echo ${CROSS_COMPILE}${CC} $CFLAGS -I . $OPTIMIZE)"
176 FILES="$(echo lib/*.c main.c $TOYFILES)"
177 LINK="$(echo $LDOPTIMIZE -o toybox_unstripped -Wl,--as-needed $(cat generated/optlibs.dat))"
178 221
179 # This is a parallel version of: do_loudly $BUILD $FILES $LINK || exit 1 222 # This is a parallel version of: do_loudly $BUILD $FILES $LINK || exit 1
180 223
181 # Write a canned build line for use on crippled build machines. 224 X="$(ls -1t generated/obj/* 2>/dev/null | tail -n 1)"
182 ( 225 if [ ! -e "$X" ] || [ ! -z "$(find toys -name "*.h" -newer "$X")" ]
183 echo "#!/bin/sh" 226 then
184 echo 227 rm -rf generated/obj && mkdir -p generated/obj || exit 1
185 echo "BUILD=\"$BUILD\"" 228 else
186 echo 229 rm -f generated/obj/{main,lib_help}.o || exit 1
187 echo "LINK=\"$LINK\"" 230 fi
188 echo
189 echo "FILES=\"$FILES\""
190 echo
191 echo '$BUILD $FILES $LINK'
192 ) > generated/build.sh && chmod +x generated/build.sh || echo 1
193
194 rm -rf generated/obj && mkdir -p generated/obj || exit 1
195 PENDING= 231 PENDING=
232 LFILES=
196 for i in $FILES 233 for i in $FILES
197 do 234 do
198 # build each generated/obj/*.o file in parallel 235 # build each generated/obj/*.o file in parallel
199 236
200 X=${i/lib\//lib_} 237 X=${i/lib\//lib_}
201 X=${X##*/} 238 X=${X##*/}
202 do_loudly $BUILD -c $i -o generated/obj/${X%%.c}.o & 239 OUT="generated/obj/${X%%.c}.o"
240 LFILES="$LFILES $OUT"
241 [ "$OUT" -nt "$i" ] && continue
242 do_loudly $BUILD -c $i -o $OUT &
203 243
204 # ratelimit to $CPUS many parallel jobs, detecting errors 244 # ratelimit to $CPUS many parallel jobs, detecting errors
205 245
206 while true 246 while true
207 do 247 do
218 for i in $PENDING 258 for i in $PENDING
219 do 259 do
220 wait $i || exit 1 260 wait $i || exit 1
221 done 261 done
222 262
223 do_loudly $BUILD generated/obj/*.o $LINK || exit 1 263 do_loudly $BUILD $LFILES $LINK || exit 1
224 do_loudly ${CROSS_COMPILE}${STRIP} toybox_unstripped -o toybox || exit 1 264 do_loudly ${CROSS_COMPILE}${STRIP} toybox_unstripped -o toybox || exit 1
225 # gcc 4.4's strip command is buggy, and doesn't set the executable bit on 265 # gcc 4.4's strip command is buggy, and doesn't set the executable bit on
226 # its output the way SUSv4 suggests it do so. 266 # its output the way SUSv4 suggests it do so.
227 do_loudly chmod +x toybox || exit 1 267 do_loudly chmod +x toybox || exit 1
228 echo 268 echo