blob: c2a431626672916954a68eaff05660034529842c
1 | #!/bin/sh |
2 | |
3 | debug=false |
4 | |
5 | # Linker flags used: |
6 | # |
7 | # Informational: |
8 | # --warn-common |
9 | # -Map $EXE.map |
10 | # --verbose |
11 | # |
12 | # Optimizations: |
13 | # --sort-common reduces padding |
14 | # --sort-section alignment reduces padding |
15 | # --gc-sections throws out unused sections, |
16 | # does not work for shared libs |
17 | # -On Not used, maybe useful? |
18 | # |
19 | # List of files to link: |
20 | # $l_list == --start-group -llib1 -llib2 --end-group |
21 | # --start-group $O_FILES $A_FILES --end-group |
22 | # |
23 | # Shared library link: |
24 | # -shared self-explanatory |
25 | # -fPIC position-independent code |
26 | # --enable-new-dtags ? |
27 | # -z,combreloc ? |
28 | # -soname="libbusybox.so.$BB_VER" |
29 | # --undefined=lbb_main Seed name to start pulling from |
30 | # (otherwise we'll need --whole-archive) |
31 | # -static Not used, but may be useful! manpage: |
32 | # "... This option can be used with -shared. |
33 | # Doing so means that a shared library |
34 | # is being created but that all of the library's |
35 | # external references must be resolved by pulling |
36 | # in entries from static libraries." |
37 | |
38 | |
39 | try() { |
40 | printf "%s\n" "Output of:" >$EXE.out |
41 | printf "%s\n" "$*" >>$EXE.out |
42 | printf "%s\n" "==========" >>$EXE.out |
43 | $debug && echo "Trying: $*" |
44 | $@ >>$EXE.out 2>&1 |
45 | return $? |
46 | } |
47 | |
48 | check_cc() { |
49 | local tempname="$(mktemp tmp.XXXXXXXXXX)" |
50 | local r |
51 | echo "int main(int argc,char**argv){return argv?argc:0;}" >"$tempname".c |
52 | # Can use "-o /dev/null", but older gcc tend to *unlink it* on failure! :( |
53 | # Was using "-xc /dev/null", but we need a valid C program. |
54 | # "eval" may be needed if CFLAGS can contain |
55 | # '... -D"BB_VER=KBUILD_STR(1.N.M)" ...' |
56 | # and we need shell to process quotes! |
57 | $CC $CFLAGS $LDFLAGS $1 "$tempname".c -o "$tempname" >/dev/null 2>&1 |
58 | r=$? |
59 | rm -f "$tempname" "$tempname".c "$tempname".o |
60 | return $r |
61 | } |
62 | |
63 | check_libc_is_glibc() { |
64 | local tempname="$(mktemp tmp.XXXXXXXXXX)" |
65 | local r |
66 | echo "\ |
67 | #include <stdlib.h> |
68 | /* Apparently uclibc defines __GLIBC__ (compat trick?). Oh well. */ |
69 | #if defined(__GLIBC__) && !defined(__UCLIBC__) |
70 | syntax error here |
71 | #endif |
72 | " >"$tempname".c |
73 | ! $CC $CFLAGS "$tempname".c -c -o "$tempname".o >/dev/null 2>&1 |
74 | r=$? |
75 | rm -f "$tempname" "$tempname".c "$tempname".o |
76 | return $r |
77 | } |
78 | |
79 | EXE="$1" |
80 | CC="$2" |
81 | CFLAGS="$3" |
82 | LDFLAGS="$4" |
83 | O_FILES="$5" |
84 | A_FILES="$6" |
85 | LDLIBS="$7" |
86 | |
87 | # The --sort-section option is not supported by older versions of ld |
88 | SORT_SECTION="-Wl,--sort-section,alignment" |
89 | if ! check_cc "-Wl,--sort-section,alignment"; then |
90 | echo "Your linker does not support --sort-section,alignment" |
91 | SORT_SECTION="" |
92 | fi |
93 | |
94 | START_GROUP="-Wl,--start-group" |
95 | END_GROUP="-Wl,--end-group" |
96 | INFO_OPTS="-Wl,--warn-common -Wl,-Map,$EXE.map -Wl,--verbose" |
97 | |
98 | # gold may not support --sort-common (yet) |
99 | SORT_COMMON="-Wl,--sort-common" |
100 | if ! check_cc "-Wl,--sort-common"; then |
101 | echo "Your linker does not support --sort-common" |
102 | SORT_COMMON="" |
103 | fi |
104 | |
105 | # Static linking against glibc produces buggy executables |
106 | # (glibc does not cope well with ld --gc-sections). |
107 | # See sources.redhat.com/bugzilla/show_bug.cgi?id=3400 |
108 | # Note that glibc is unsuitable for static linking anyway. |
109 | # We are removing -Wl,--gc-sections from link command line. |
110 | GC_SECTIONS="-Wl,--gc-sections" |
111 | if (. ./.config && test x"$CONFIG_STATIC" = x"y") then |
112 | if check_libc_is_glibc; then |
113 | echo "Static linking against glibc, can't use --gc-sections" |
114 | GC_SECTIONS="" |
115 | fi |
116 | fi |
117 | # The --gc-sections option is not supported by older versions of ld |
118 | if test -n "$GC_SECTIONS"; then |
119 | if ! check_cc "$GC_SECTIONS"; then |
120 | echo "Your linker does not support $GC_SECTIONS" |
121 | GC_SECTIONS="" |
122 | fi |
123 | fi |
124 | |
125 | # Sanitize lib list (dups, extra spaces etc) |
126 | LDLIBS=`echo "$LDLIBS" | xargs -n1 | sort | uniq | xargs` |
127 | |
128 | # First link with all libs. If it fails, bail out |
129 | echo "Trying libraries: $LDLIBS" |
130 | # "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3" |
131 | l_list=`echo " $LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g'` |
132 | test "x$l_list" != "x" && l_list="$START_GROUP $l_list $END_GROUP" |
133 | try $CC $CFLAGS $LDFLAGS \ |
134 | -o $EXE \ |
135 | $SORT_COMMON \ |
136 | $SORT_SECTION \ |
137 | $GC_SECTIONS \ |
138 | $START_GROUP $O_FILES $A_FILES $END_GROUP \ |
139 | $l_list \ |
140 | || { |
141 | echo "Failed: $l_list" |
142 | cat $EXE.out |
143 | echo 'Note: if build needs additional libraries, put them in CONFIG_EXTRA_LDLIBS.' |
144 | echo 'Example: CONFIG_EXTRA_LDLIBS="pthread dl tirpc audit pam"' |
145 | exit 1 |
146 | } |
147 | |
148 | # Now try to remove each lib and build without it. |
149 | # Stop when no lib can be removed. |
150 | while test "$LDLIBS"; do |
151 | $debug && echo "Trying libraries: $LDLIBS" |
152 | all_needed=true |
153 | last_needed=false |
154 | for one in $LDLIBS; do |
155 | without_one=`echo " $LDLIBS " | sed "s/ $one / /g" | xargs` |
156 | # "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3" |
157 | l_list=`echo " $without_one " | sed -e 's: \([^- ][^ ]*\): -l\1:g'` |
158 | test x"$l_list" != x"" && l_list="$START_GROUP $l_list $END_GROUP" |
159 | $debug && echo "Trying -l options: '$l_list'" |
160 | try $CC $CFLAGS $LDFLAGS \ |
161 | -o $EXE \ |
162 | $SORT_COMMON \ |
163 | $SORT_SECTION \ |
164 | $GC_SECTIONS \ |
165 | $START_GROUP $O_FILES $A_FILES $END_GROUP \ |
166 | $l_list |
167 | if test $? = 0; then |
168 | echo " Library $one is not needed, excluding it" |
169 | LDLIBS="$without_one" |
170 | all_needed=false |
171 | last_needed=false |
172 | else |
173 | echo " Library $one is needed, can't exclude it (yet)" |
174 | last_needed=true |
175 | fi |
176 | done |
177 | # All libs were needed, can't remove any |
178 | $all_needed && break |
179 | # Optimization: was the last tried lib needed? |
180 | if $last_needed; then |
181 | # Was it the only one lib left? Don't test again then. |
182 | { echo "$LDLIBS" | grep -q ' '; } || break |
183 | fi |
184 | done |
185 | |
186 | # Make the binary with final, minimal list of libs |
187 | echo "Final link with: ${LDLIBS:-<none>}" |
188 | l_list=`echo " $LDLIBS " | sed -e 's: \([^- ][^ ]*\): -l\1:g'` |
189 | test "x$l_list" != "x" && l_list="$START_GROUP $l_list $END_GROUP" |
190 | # --verbose gives us gobs of info to stdout (e.g. linker script used) |
191 | if ! test -f busybox_ldscript; then |
192 | try $CC $CFLAGS $LDFLAGS \ |
193 | -o $EXE \ |
194 | $SORT_COMMON \ |
195 | $SORT_SECTION \ |
196 | $GC_SECTIONS \ |
197 | $START_GROUP $O_FILES $A_FILES $END_GROUP \ |
198 | $l_list \ |
199 | $INFO_OPTS \ |
200 | || { |
201 | cat $EXE.out |
202 | exit 1 |
203 | } |
204 | else |
205 | echo "Custom linker script 'busybox_ldscript' found, using it" |
206 | # Add SORT_BY_ALIGNMENT to linker script (found in $EXE.out): |
207 | # .rodata : { *(.rodata SORT_BY_ALIGNMENT(.rodata.*) .gnu.linkonce.r.*) } |
208 | # *(.data SORT_BY_ALIGNMENT(.data.*) .gnu.linkonce.d.*) |
209 | # *(.bss SORT_BY_ALIGNMENT(.bss.*) .gnu.linkonce.b.*) |
210 | # This will eliminate most of the padding (~3kb). |
211 | # Hmm, "ld --sort-section alignment" should do it too. |
212 | # |
213 | # There is a ld hack which is meant to decrease disk usage |
214 | # at the cost of more RAM usage (??!!) in standard ld script: |
215 | # /* Adjust the address for the data segment. We want to adjust up to |
216 | # the same address within the page on the next page up. */ |
217 | # . = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1)); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000); |
218 | # Replace it with: |
219 | # . = ALIGN (0x1000); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000); |
220 | # to unconditionally align .data to the next page boundary, |
221 | # instead of "next page, plus current offset in this page" |
222 | try $CC $CFLAGS $LDFLAGS \ |
223 | -o $EXE \ |
224 | $SORT_COMMON \ |
225 | $SORT_SECTION \ |
226 | $GC_SECTIONS \ |
227 | -Wl,-T,busybox_ldscript \ |
228 | $START_GROUP $O_FILES $A_FILES $END_GROUP \ |
229 | $l_list \ |
230 | $INFO_OPTS \ |
231 | || { |
232 | cat $EXE.out |
233 | exit 1 |
234 | } |
235 | fi |
236 | |
237 | . ./.config |
238 | |
239 | sharedlib_dir="0_lib" |
240 | |
241 | if test "$CONFIG_BUILD_LIBBUSYBOX" = y; then |
242 | mkdir "$sharedlib_dir" 2>/dev/null |
243 | test -d "$sharedlib_dir" || { |
244 | echo "Cannot make directory $sharedlib_dir" |
245 | exit 1 |
246 | } |
247 | ln -s "libbusybox.so.$BB_VER" "$sharedlib_dir"/libbusybox.so 2>/dev/null |
248 | |
249 | EXE="$sharedlib_dir/libbusybox.so.${BB_VER}_unstripped" |
250 | try $CC $CFLAGS $LDFLAGS \ |
251 | -o $EXE \ |
252 | -shared -fPIC \ |
253 | -Wl,--enable-new-dtags \ |
254 | -Wl,-z,combreloc \ |
255 | -Wl,-soname="libbusybox.so.$BB_VER" \ |
256 | -Wl,--undefined=lbb_main \ |
257 | $SORT_COMMON \ |
258 | $SORT_SECTION \ |
259 | $START_GROUP $A_FILES $END_GROUP \ |
260 | $l_list \ |
261 | $INFO_OPTS \ |
262 | || { |
263 | echo "Linking $EXE failed" |
264 | cat $EXE.out |
265 | exit 1 |
266 | } |
267 | $STRIP -s --remove-section=.note --remove-section=.comment $EXE -o "$sharedlib_dir/libbusybox.so.$BB_VER" |
268 | chmod a+x "$sharedlib_dir/libbusybox.so.$BB_VER" |
269 | echo "libbusybox: $sharedlib_dir/libbusybox.so.$BB_VER" |
270 | fi |
271 | |
272 | if test "$CONFIG_FEATURE_SHARED_BUSYBOX" = y; then |
273 | EXE="$sharedlib_dir/busybox_unstripped" |
274 | try $CC $CFLAGS $LDFLAGS \ |
275 | -o $EXE \ |
276 | $SORT_COMMON \ |
277 | $SORT_SECTION \ |
278 | $GC_SECTIONS \ |
279 | $START_GROUP $O_FILES $END_GROUP \ |
280 | -L"$sharedlib_dir" -lbusybox \ |
281 | $l_list \ |
282 | $INFO_OPTS \ |
283 | || { |
284 | echo "Linking $EXE failed" |
285 | cat $EXE.out |
286 | exit 1 |
287 | } |
288 | $STRIP -s --remove-section=.note --remove-section=.comment $EXE -o "$sharedlib_dir/busybox" |
289 | echo "busybox linked against libbusybox: $sharedlib_dir/busybox" |
290 | fi |
291 | |
292 | if test "$CONFIG_FEATURE_INDIVIDUAL" = y; then |
293 | echo "Linking individual applets against libbusybox (see $sharedlib_dir/*)" |
294 | gcc -DNAME_MAIN -E -include include/autoconf.h include/applets.h \ |
295 | | grep -v "^#" \ |
296 | | grep -v "^ *$" \ |
297 | > applet_lst.tmp |
298 | while read name main junk; do |
299 | |
300 | echo "\ |
301 | void lbb_prepare(const char *applet, char **argv); |
302 | int $main(int argc, char **argv); |
303 | |
304 | int main(int argc, char **argv) |
305 | { |
306 | lbb_prepare(\"$name\", argv); |
307 | return $main(argc, argv); |
308 | } |
309 | " >"$sharedlib_dir/applet.c" |
310 | |
311 | EXE="$sharedlib_dir/$name" |
312 | try $CC $CFLAGS $LDFLAGS "$sharedlib_dir/applet.c" \ |
313 | -o $EXE \ |
314 | $SORT_COMMON \ |
315 | $SORT_SECTION \ |
316 | $GC_SECTIONS \ |
317 | -L"$sharedlib_dir" -lbusybox \ |
318 | -Wl,--warn-common \ |
319 | || { |
320 | echo "Linking $EXE failed" |
321 | cat $EXE.out |
322 | exit 1 |
323 | } |
324 | rm -- "$sharedlib_dir/applet.c" $EXE.out |
325 | $STRIP -s --remove-section=.note --remove-section=.comment $EXE |
326 | # Let user see that we do something - list the names of created binaries: |
327 | echo "$EXE" |
328 | |
329 | done <applet_lst.tmp |
330 | fi |
331 | |
332 | # libbusybox.so is needed only for -lbusybox at link time, |
333 | # it is not needed at runtime. Deleting to reduce confusion. |
334 | rm "$sharedlib_dir"/libbusybox.so 2>/dev/null |
335 | exit 0 # or else we may confuse make |
336 |