Mercurial > hg > toybox
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 |