cbba9000a752ad7004f3547dff14c813274cda78
[oweals/busybox.git] / scripts / trylink
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 # -O                            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 # or for shlib:
23 # --start-group --whole-archive $A_FILES --no-whole-archive --end-group
24 # otherwise we don't pull in all parts of *.a files. Now we pull in too much.
25 # FIXME: make it work without --whole-archive, or better, with --gc-sections.
26 #
27 # Shared library link:
28 # -shared                       self-explanatory
29 # -fPIC                         position-independent code
30 # -Wl,--enable-new-dtags        ?
31 # -Wl,-z,combreloc              ?
32 # -Wl,-soname="libbusybox.so.$BB_VER"
33 # -static                       Not used, but may be useful! manpage:
34 #                               "... This option can be used with -shared.
35 #                               Doing so means that a shared library
36 #                               is being created but that all of the library's
37 #                               external references must be resolved by pulling
38 #                               in entries from static libraries."
39
40
41 try() {
42     printf "%s\n" "Output of:" >$EXE.out
43     printf "%s\n" "$*" >>$EXE.out
44     printf "%s\n" "==========" >>$EXE.out
45     $debug && echo "Trying: $*"
46     "$@" >>$EXE.out 2>&1
47     exitcode=$?
48     return $exitcode
49 }
50
51 EXE="$1"
52 CC="$2"
53 LDFLAGS="$3"
54 O_FILES="$4"
55 A_FILES="$5"
56 LDLIBS="$6"
57
58 # Sanitize lib list (dups, extra spaces etc)
59 LDLIBS=`echo "$LDLIBS" | xargs -n1 | sort | uniq | xargs`
60
61 # First link with all libs. If it fails, bail out
62 echo "Trying libraries: $LDLIBS"
63 # "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3"
64 l_list=`echo "$LDLIBS" | sed -e 's/ / -l/g' -e 's/^/-l/' -e 's/^-l$//'`
65 test "x$l_list" != "x" && l_list="-Wl,--start-group $l_list -Wl,--end-group"
66 try $CC $LDFLAGS \
67         -o $EXE \
68         -Wl,--sort-common \
69         -Wl,--sort-section -Wl,alignment \
70         -Wl,--gc-sections \
71         -Wl,--start-group $O_FILES $A_FILES -Wl,--end-group \
72         $l_list \
73 || {
74     echo "Failed: $* $l_list"
75     cat $EXE.out
76     exit 1
77 }
78
79 # Now try to remove each lib and build without it.
80 # Stop when no lib can be removed.
81 while test "$LDLIBS"; do
82     $debug && echo "Trying libraries: $LDLIBS"
83     all_needed=true
84     for one in $LDLIBS; do
85         without_one=`echo " $LDLIBS " | sed "s/ $one / /g" | xargs`
86         # "lib1 lib2 lib3" -> "-llib1 -llib2 -llib3"
87         l_list=`echo "$without_one" | sed -e 's/ / -l/g' -e 's/^/-l/' -e 's/^-l$//'`
88         test "x$l_list" != "x" && l_list="-Wl,--start-group $l_list -Wl,--end-group"
89         $debug && echo "Trying -l options: '$l_list'"
90         try $CC $LDFLAGS \
91                 -o $EXE \
92                 -Wl,--sort-common \
93                 -Wl,--sort-section -Wl,alignment \
94                 -Wl,--gc-sections \
95                 -Wl,--start-group $O_FILES $A_FILES -Wl,--end-group \
96                 $l_list
97         if test $? = 0; then
98             echo "Library $one is not needed"
99             LDLIBS="$without_one"
100             all_needed=false
101         else
102             echo "Library $one is needed"
103         fi
104     done
105     # All libs were needed, can't remove any
106     $all_needed && break
107     # If there is no space char, the list has just one lib.
108     # I'm not sure that in this case lib really is 100% needed.
109     # Let's try linking without it anyway... thus commented out.
110     #{ echo "$LDLIBS" | grep -q ' '; } || break
111 done
112
113 # Make the binary with final, minimal list of libs
114 echo "Final link with: $LDLIBS"
115 l_list=`echo "$LDLIBS" | sed -e 's/ / -l/g' -e 's/^/-l/' -e 's/^-l$//'`
116 test "x$l_list" != "x" && l_list="-Wl,--start-group $l_list -Wl,--end-group"
117 # --verbose gives us gobs of info to stdout (e.g. linker script used)
118 if ! test -f busybox_ldscript; then
119     try $CC $LDFLAGS \
120             -o $EXE \
121             -Wl,--sort-common \
122             -Wl,--sort-section -Wl,alignment \
123             -Wl,--gc-sections \
124             -Wl,--start-group $O_FILES $A_FILES -Wl,--end-group \
125             $l_list \
126             -Wl,--warn-common \
127             -Wl,-Map -Wl,$EXE.map \
128             -Wl,--verbose \
129     || {
130         cat $EXE.out
131         exit 1
132     }
133 else
134     echo "Custom linker script 'busybox_ldscript' found, using it"
135     # Add SORT_BY_ALIGNMENT to linker script (found in $EXE.out):
136     #  .rodata         : { *(.rodata SORT_BY_ALIGNMENT(.rodata.*) .gnu.linkonce.r.*) }
137     #  *(.data SORT_BY_ALIGNMENT(.data.*) .gnu.linkonce.d.*)
138     #  *(.bss SORT_BY_ALIGNMENT(.bss.*) .gnu.linkonce.b.*)
139     # This will eliminate most of the padding (~3kb).
140     # Hmm, "ld --sort-section alignment" should do it too.
141     try $CC $LDFLAGS \
142             -o $EXE \
143             -Wl,--sort-common \
144             -Wl,--sort-section -Wl,alignment \
145             -Wl,--gc-sections \
146             -Wl,-T -Wl,busybox_ldscript \
147             -Wl,--start-group $O_FILES $A_FILES -Wl,--end-group \
148             $l_list \
149             -Wl,--warn-common \
150             -Wl,-Map -Wl,$EXE.map \
151             -Wl,--verbose \
152     || {
153         cat $EXE.out
154         exit 1
155     }
156 fi
157
158 . .config
159
160 sharedlib_dir="0_lib"
161
162 if test "$CONFIG_BUILD_LIBBUSYBOX" = y; then
163     mkdir "$sharedlib_dir" 2>/dev/null
164     test -d "$sharedlib_dir" || {
165         echo "Cannot make directory $sharedlib_dir"
166         exit 1
167     }
168     ln -s "libbusybox.so.$BB_VER" "$sharedlib_dir"/libbusybox.so 2>/dev/null
169
170     EXE="$sharedlib_dir/libbusybox.so.${BB_VER}_unstripped"
171     try $CC $LDFLAGS \
172             -o $EXE \
173             -shared -fPIC \
174             -Wl,--enable-new-dtags \
175             -Wl,-z,combreloc \
176             -Wl,-soname="libbusybox.so.$BB_VER" \
177             -Wl,--sort-common \
178             -Wl,--sort-section -Wl,alignment \
179             -Wl,--start-group -Wl,--whole-archive $A_FILES -Wl,--no-whole-archive -Wl,--end-group \
180             $l_list \
181             -Wl,--warn-common \
182             -Wl,-Map -Wl,$EXE.map \
183             -Wl,--verbose \
184     || {
185         echo "Linking $EXE failed"
186         cat $EXE.out
187         exit 1
188     }
189     strip -s --remove-section=.note --remove-section=.comment $EXE -o "$sharedlib_dir/libbusybox.so.$BB_VER"
190     chmod a+x "$sharedlib_dir/libbusybox.so.$BB_VER"
191     echo "libbusybox: $sharedlib_dir/libbusybox.so.$BB_VER"
192 fi
193
194 if test "$CONFIG_FEATURE_SHARED_BUSYBOX" = y; then
195     EXE="$sharedlib_dir/busybox_unstripped"
196     try $CC $LDFLAGS \
197             -o $EXE \
198             -Wl,--sort-common \
199             -Wl,--sort-section -Wl,alignment \
200             -Wl,--gc-sections \
201             -Wl,--start-group $O_FILES -Wl,--end-group \
202             -L"$sharedlib_dir" -lbusybox \
203             -Wl,--warn-common \
204             -Wl,-Map -Wl,$EXE.map \
205             -Wl,--verbose \
206     || {
207         echo "Linking $EXE failed"
208         cat $EXE.out
209         exit 1
210     }
211     strip -s --remove-section=.note --remove-section=.comment $EXE -o "$sharedlib_dir/busybox"
212     echo "busybox linked against libbusybox: $sharedlib_dir/busybox"
213 fi
214
215 if test "$CONFIG_FEATURE_INDIVIDUAL" = y; then
216     echo "Linking individual applets against libbusybox (see $sharedlib_dir/*)"
217     gcc -DNAME_MAIN_CNAME -E -include include/autoconf.h include/applets.h \
218     | grep -v "^#" \
219     | grep -v "^$" \
220     > applet_lst.tmp
221     while read name main junk; do
222
223         echo "\
224 void bbox_prepare_main(char **argv);
225 int $main(int argc, char **argv);
226
227 const char *applet_name = \"$name\";
228
229 int main(int argc, char **argv)
230 {
231         bbox_prepare_main(argv);
232         return $main(argc, argv);
233 }
234 " >"$sharedlib_dir/applet.c"
235
236         EXE="$sharedlib_dir/$name"
237         try $CC $LDFLAGS "$sharedlib_dir/applet.c" \
238                 -o $EXE \
239                 -Wl,--sort-common \
240                 -Wl,--sort-section -Wl,alignment \
241                 -Wl,--gc-sections \
242                 -L"$sharedlib_dir" -lbusybox \
243                 -Wl,--warn-common \
244         || {
245             echo "Linking $EXE failed"
246             cat $EXE.out
247             exit 1
248         }
249         rm -- "$sharedlib_dir/applet.c" $EXE.out
250         strip -s --remove-section=.note --remove-section=.comment $EXE
251
252     done <applet_lst.tmp
253 fi
254
255 # libbusybox.so is needed only for -lbusybox at link time,
256 # it is not needed at runtime. Deleting to reduce confusion.
257 rm "$sharedlib_dir"/libbusybox.so 2>/dev/null
258 exit 0 # or else we may confuse make