busybox/scripts/trylink
<<
>>
Prefs
   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