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