| From 7a912823158a4113256c3113a34c38d6b241d275 Mon Sep 17 00:00:00 2001 |
| From: Alexey Brodkin <abrodkin@synopsys.com> |
| Date: Wed, 13 Jan 2016 20:15:36 +0300 |
| Subject: [PATCH] Fix library inclusion order when building statically |
| |
| When building application statically it's important to keep |
| libraries we're linking against in order. Otherwise if libA depends on |
| libB but it is mentioned after libB in linker command line |
| there will be unresolved symbols. |
| |
| Consider real example - configuration of Qt with glib for static build. |
| Initially reported by Buildroot autobuilder here: |
| http://autobuild.buildroot.net/results/174/174c6e47eb761f9897275b6fedff742ace2f3081 |
| |
| What happens here: |
| |
| [1] Qt's configuration script tries to build glib test app |
| (in config.tests/unix/glib) |
| |
| [2] For that it first asks which libs to use during linkage this way: |
| QT_LIBS_GLIB=`$PKG_CONFIG --libs glib-2.0 gthread-2.0 2>/dev/null` |
| |
| In our case we're getting something like this: |
| -L/.../sysroot/usr/lib -lintl -lgthread-2.0 -pthread -lglib-2.0 \ |
| -lintl -pthread -lintl |
| |
| Note "-lintl" is mentioned 3 times because libgthread depends on |
| libthread and both of them plus libglib all depend on libintl - so |
| we're getting "lintl" for each separate library mentioned above. |
| |
| [3] Now we execute "compileTest" for real heavy lifting this way: |
| compileTest unix/glib "Glib" $QT_CFLAGS_GLIB $QT_LIBS_GLIB ... |
| |
| [4] compileTest (the one for unix) parses command-line passed to it |
| groups all entries with "-l" prefix and puts them in LFLAGS |
| variable. And finally executes qmake passing it that kind of |
| construction: |
| $OUTDIR/bin/qmake ..."LIBS*=$LFLAGS" |
| |
| [5] When qmake sees construction "MYVAR*=MYVAL" it populates MYVAR with |
| unique values from MYVAL string. |
| |
| [6] As a result qmake generated Makefile with the following: |
| LIBS = $(SUBLIBS) -pthread -L/.../sysroot/usr/lib -lintl -lgthread-2.0 \ |
| -lglib-2.0 |
| |
| [7] And essentially on attempt to link glib test app a failure happens |
| because libglib needs libintl, i.e. "-lintl" must follow "-lglib-2.0": |
| -------------------->8------------------ |
| linking glib |
| |
| g++ -static -Wl,-O1 -o glib glib.o -pthread -L/.../sysroot/usr/lib \ |
| -lintl -lgthread-2.0 -lglib-2.0 |
| |
| /.../sysroot/usr/lib/libglib-2.0.a(libglib_2_0_la-ggettext.o): In function '_g_dgettext_should_translate': |
| ggettext.c:(.text+0x28): undefined reference to `libintl_textdomain' |
| ggettext.c:(.text+0x36): undefined reference to `libintl_gettext' |
| /.../sysroot/usr/lib/libglib-2.0.a(libglib_2_0_la-ggettext.o): In function `ensure_gettext_initialized': |
| ggettext.c:(.text+0xe6): undefined reference to `libintl_bindtextdomain' |
| ggettext.c:(.text+0xf6): undefined reference to `libintl_bind_textdomain_codeset' |
| /.../sysroot/usr/lib/libglib-2.0.a(libglib_2_0_la-ggettext.o): In function `g_dgettext': |
| ggettext.c:(.text+0x148): undefined reference to `libintl_dgettext' |
| /.../sysroot/usr/lib/libglib-2.0.a(libglib_2_0_la-ggettext.o): In function `g_dcgettext': |
| ggettext.c:(.text+0x2dc): undefined reference to `libintl_dcgettext' |
| /.../sysroot/usr/lib/libglib-2.0.a(libglib_2_0_la-ggettext.o): In function `g_dngettext': |
| ggettext.c:(.text+0x32a): undefined reference to `libintl_dngettext' |
| collect2: error: ld returned 1 exit status |
| Makefile:99: recipe for target 'glib' failed |
| make: *** [glib] Error 1 |
| |
| Glib disabled. |
| Glib support cannot be enabled due to functionality tests! |
| Turn on verbose messaging (-v) to ./configure to see the final report. |
| If you believe this message is in error you may use the continue |
| switch (-continue) to ./configure to continue. |
| -------------------->8------------------ |
| |
| Solution to this problem is simple we have to pass all libraries exactly |
| in order of their initial mention by upper layers. |
| |
| Change-Id: I7ff00901031a8eb85b4fbd7889b0e0c02be806bb |
| |
| This fix was sent to Qt Gerrit for review here: |
| https://codereview.qt-project.org/#/c/145967/ |
| |
| --- |
| config.tests/unix/compile.test | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| diff --git a/config.tests/unix/compile.test b/config.tests/unix/compile.test |
| index f484f03..dac0a4f 100755 |
| --- a/config.tests/unix/compile.test |
| +++ b/config.tests/unix/compile.test |
| @@ -73,7 +73,7 @@ test -r Makefile && $MAKE distclean >/dev/null 2>&1 |
| rm -f "$EXE" "${EXE}.exe" |
| |
| echo "QT_BUILD_TREE = $OUTDIR" > "$OUTDIR/$TEST/.qmake.cache" |
| -"$OUTDIR/bin/qmake" -spec "$QMKSPEC" "CONFIG+=$QMAKE_CONFIG" "CONFIG-=debug_and_release" "LIBS*=$LFLAGS" "LIBS+=$MAC_ARCH_LFLAGS" "INCLUDEPATH*=$INCLUDEPATH" "QMAKE_CXXFLAGS*=$CXXFLAGS" "QMAKE_CXXFLAGS+=$MAC_ARCH_CXXFLAGS" "$SRCDIR/$TEST/$EXE.pro" -o "$OUTDIR/$TEST/Makefile" |
| +"$OUTDIR/bin/qmake" -spec "$QMKSPEC" "CONFIG+=$QMAKE_CONFIG" "CONFIG-=debug_and_release" "LIBS=$LFLAGS" "LIBS+=$MAC_ARCH_LFLAGS" "INCLUDEPATH*=$INCLUDEPATH" "QMAKE_CXXFLAGS*=$CXXFLAGS" "QMAKE_CXXFLAGS+=$MAC_ARCH_CXXFLAGS" "$SRCDIR/$TEST/$EXE.pro" -o "$OUTDIR/$TEST/Makefile" |
| |
| if [ "$VERBOSE" = "yes" ]; then |
| $MAKE |
| -- |
| 2.4.3 |
| |