libtool changes the order of my linker flags in autotools? - c

I am trying to statically build the web server lighttpd (version 1.4.49) using musl (for x86) as my compiler and lighttpd's autotools build system. My configuration script is as follows:
CC=/home/musl-1.1.23/install/bin/musl-gcc CFLAGS="-g --static" LDFLAGS="-L/home/lighttpd -lwrappers -static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown LIGHTTPD_STATIC=yes ./configure --prefix=/home/lighttpd/install --enable-static --disable-shared --without-zlib --disable-ipv6 --without-bzip2 --without-pcre
Where I have created my own static library "wrappers" that contains the wrapped definitions for the functions specified in my LDFLAGS argument for configure. The way everything is set up I need my wrapped library to be the first library linked (even before musl's standard c library), however libtool is changing the order of my LDFLAGS argument from above to the following:
libtool: link: /home/musl-1.1.23/install/bin/musl-gcc -g --static -Wall -W -Wshadow -pedantic -static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown -o proc_open proc_open-proc_open.o proc_open-buffer.o -L/home/lighttpd-1.4.49 -lwrappers
instead of:
libtool: link: /home/musl-1.1.23/install/bin/musl-gcc -g --static -Wall -W -Wshadow -pedantic -L/home/lighttpd-1.4.49 -lwrappers -static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown -o proc_open proc_open-proc_open.o proc_open-buffer.o
Which causes the following errors (I have only included the first few, but the rest are similar):
/usr/local/bin/ld: /home/musl-1.1.23/install/lib/libc.a(syslog.o): in function `__openlog':
/home/musl-1.1.23/src/misc/syslog.c:51: undefined reference to `__wrap_socket'
/usr/local/bin/ld: /home/musl-1.1.23/install/lib/libc.a(syslog.o): in function `_vsyslog':
/usr/local/bin/ld: /home/musl-1.1.23/src/misc/syslog.c:111: undefined reference to `__wrap_send'
/usr/local/bin/ld: /home/musl-1.1.23/src/misc/syslog.c:113: undefined reference to `__wrap_send'
Its weird to me why this is happening, as everywhere else the LDFLAGS appear in the right order:
/bin/bash ../libtool --tag=CC --mode=link /home/musl-1.1.23/install/bin/musl-gcc -g --static -Wall -W -Wshadow -pedantic -module -export-dynamic -avoid-version -L/home/lighttpd -lwrappers -static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown -o mod_setenv.la -rpath /home/lighttpd/install/lib mod_setenv.lo
libtool: link: ranlib .libs/mod_scgi.a
Any help would be greatly appreciated! Thank you in advance.

LDFLAGS is not for libraries to add to the link. libtool notwithstanding, LDFLAGS is expanded too early in the link command, and this is not specific to the autotools.
In your case, libtool appears to be recognizing that error, and in the case where that matters, moving the -L and -l options where they need to be, after the object(s) being linked. (Or at least the -l options need to be there, especially for a static link, and if libtool is going to move those, then there are practical reasons for moving the -L options, too.)
Unfortunately, there is no other user-oriented Autotools variable appropriate to your stated purpose, either. Injecting extra libraries into the link is not a use case the Autotools are designed to support, and injecting them at the beginning of the link is unlikely to be feasible without hacking the autotooling.
On the third hand, you appear to be misinterpreting the problem. You claim that
I need my wrapped library to be the first library linked (even before musl's standard c library)
But this ...
/usr/local/bin/ld: /home/musl-1.1.23/install/lib/libc.a(syslog.o): in function `_vsyslog':
/usr/local/bin/ld: /home/musl-1.1.23/src/misc/syslog.c:111: undefined reference to `__wrap_send'
... tells me exactly the opposite: even calls from inside standard library functions in libc are being wrapped, so the wrapper needs to appear last, even after the standard library (which ordinarily is last, not first).* And since libwrap probably calls standard library functions itself, you may need to link libc twice. Of course, that assumes that you really want to be messing with the standard library that way, which does not seem advisable to me.
If you were performing a dynamic link then this would not be an issue: it would not be possible to wrap the internal calls of the C library in the first place. This suggests to me that the linker's --wrap option probably was not designed with static linking of the standard library in mind.
I'm not inclined to set up a testbed to verify the following, but if you really do want to wrap libc's own internal function calls, then this may work: ... LDFLAGS="-static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown" LIBS="-L/home/lighttpd -lc -lwrappers -lc" ./configure ...
LIBS is not really intended to be a user variable, and that's the potential weak point of this plan. But it is among Autoconf's standard output variables, and its contents should appear at the end of the link line. configure may prepend other libraries to LIBS, but it should not append any. The risk is that configure may clear any initial contents.
The -lc appearing before -lwrappersis the secret sauce. Normally, you do not need to specify -lc explicitly, but in this case you do, because you need to resolve some symbols in it against libwrappers, which otherwise would be linked too early. You also (probably) need to link some symbols in libwrappers against libc. It may be redundant, but explicitly linking libc again, after libwrappers, may be necessary to overcome unwanted cleverness by the linker.
If you want to avoid wrapping the internal libc self-calls, then you could try ... LDFLAGS="-static-libgcc -Wl,--wrap=socket -Wl,--wrap=bind -Wl,--wrap=listen -Wl,--wrap=accept4 -Wl,--wrap=send -Wl,--wrap=recv -Wl,--wrap=shutdown" LIBS="-L/home/lighttpd -lwrappers -Wl,--no-wrap=socket -Wl,--no-wrap=bind -Wl,--no-wrap=listen -Wl,--no-wrap=accept4 -Wl,--no-wrap=send -Wl,--no-wrap=recv -Wl,--no-wrap=shutdown" ./configure .... The idea there is to turn off wrapping for libc (only), but it's pretty speculative, because although negating long options with no- is standard GNU form, the --no-wrap option in particular is not documented.
*So libtool's reordering is not causing the issue you present. In fact, if libtool did not perform that reordering then you would have even more link errors.

Related

How to include file containing declared gcc wrap functions using autotools?

I am trying to wrap the socket() system call with my own custom __wrap_socket() system call in a wrap.c file in lighttpd (a web server application).
Lighttpd uses auto-tools to build, and I am attempting to build it completely static using musl.
The configure script I pass is as follows:
CC="/home/riscv64-linux-musl-cross/bin/riscv64-linux-musl-gcc" CFLAGS="-g -Wl,--wrap=socket -static --static -static-libstdc++ -static-libgcc /home/lighttpd/wrap.c" LDFLAGS="-L/musl/lib/ -lcrypt -lc" ./configure --prefix=/lighttpd/install/ --enable-static --without-zlib --without-bzip2 --without-pcre
However, due to lighttpd's build script and Makefile generated by autotools, I get the following errors (I have only included some of the many errors):
/home/riscv64-linux-musl-cross/bin/riscv64-linux-musl-gcc -DHAVE_CONFIG_H -DHAVE_VERSIONSTAMP_H -DLIBRARY_DIR="\"/home/lighttpd/install/lib\"" -DSBIN_DIR="\"/home/lighttpd/install/sbin\"" -I. -I.. -DDEBUG_PROC_OPEN -D_REENTRANT -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGE_FILES -g -Wl,--wrap=socket -static --static -static-libstdc++ -static-libgcc /home/lighttpd/wrap.c -Wall -W -Wshadow -pedantic -MT proc_open-proc_open.o -MD -MP -MF .deps/proc_open-proc_open.Tpo -c -o proc_open-proc_open.o `test -f 'proc_open.c' || echo './'`proc_open.c
riscv64-linux-musl-gcc: fatal error: cannot specify ‘-o’ with ‘-c’, ‘-S’ or ‘-E’ with multiple files
However, if I do not include the path to the wrap.c file in the CFLAGS argument, I get the following errors:
/home/riscv64-linux-musl-cross/bin/../lib/gcc/riscv64-linux-musl/10.2.1/../../../../riscv64-linux-musl/bin/ld: /home/musl/lib//libc.a(if_nametoindex.lo):/home/musl-1.1.23/src/network/if_nametoindex.c:13: more undefined references to `__wrap_socket' follow
and
/home/riscv64-linux-musl-cross/bin/../lib/gcc/riscv64-linux-musl/10.2.1/../../../../riscv64-linux-musl/bin/ld: /home/lighttpd/src/fdevent.c:491: undefined reference to `__wrap_socket'
I have the wrap.c function (__wrap_socket()) in a file wrap.h which I have included in lighttpd's main file (server.c). Any help would be greatly appreciated.
There are lots of issues here. Among them:
You are using the CC variable to sub in a cross compiler, but that's the wrong way to perform a cross build with an Autotools build system. The right way is to specify the system type for cross compilation is via a --host triplet. It looks like you may want --host=riscv64-linux-musl in particular. As long as the cross tools are in the executable search path, with the expected names, configure will then find them -- including the correct linker for the toolchain, whose use should reduce the number of flags you need to specify. configure will also behave a bit differently than it does for configuring an ordinary build.
You are specifying link flags in your CFLAGS variable, which is for compilation flags. This might not always cause a problem in practice, but it is a muddle that you should avoid. LDFLAGS is the correct variable for link flags other than -l and maybe -L options, including -Wl,--wrap=socket, -static, --static, -static-libstdc++, and -static-libgcc, though some of those should not be necessary at all.
You have put a source file name into your CFLAGS. This flat out will not work. The build system will build each source file to an object file, separately, using the CFLAGS where those are C sources. You are tricking it into trying to compile two sources with each such command, and that conflicts with some of the other flags that the build system chooses.
You appear to have a C++ project, but you are specifying C compiler flags (CFLAGS) and no C++ compiler flags (CXXFLAGS). If there are sources in both languages then you may need both. Do not expect the CFLAGS to be used when compiling C++ sources.
You are specifying link libraries in LDFLAGS. This probably won't break your build in itself, but it also will not get you the link behavior you probably expect, because link commands are sensitive to the order of command-line arguments. You should use LIBS for this, instead.
You cannot add a source file to an Autotools build without modifying the autotooling. If you want to avoid that then my suggestion would be to instead (cross-)build the extra sources into a library, and add that to the link. I leave building the library to you, but supposing that you build it as libsocket_wrap.a, you might then inject it into lighthttpd by configuring something like this:
CFLAGS="-g" \
CXXFLAGS="-g" \
LDFLAGS="-Wl,--wrap=socket -static-libstdc++ -static-libgcc" \
LIBS="/path/to/libsocket_wrap.a -lcrypt" \
./configure \
--host=riscv64-linux-musl \
--prefix=/lighttpd/install \
--enable-static \
--disable-shared \
--without-zlib \
--without-bzip2 \
--without-pcre
I cannot guarantee that that will work as-is, because much depends on details of your build environment and the specifics of the project you are trying to build. But it's a much better position to work from than the one presented in the question.

version node not found for symbol

I've build a shared library on my desktop that uses statically linked gstreamer and gstreamer plugins (base, good, rtsp-server).
Now I'm trying to compile the library using yocto but its giving me a linker error:
version node not found for symbol _IO_do_write##GLIBC_2.17
failed to set dynamic section sizes: Bad value
The solutions I found on stack overflow did not seem to help me.
use compiler with --disable-symvers
link libc libs in different orders (-ldl -lm -lc -lpthread -ltinfo -lrt)
link libc libs statically/shared
What I find particularly odd is that the linker is looking for GLIBC_2.17 while yocto uses 2.27 and my system is using 2.24. I don't know if this matters or if it is normal (the function did not change since 2.17?).
NM -C shows the symbol in libc.a:
nm -C recipe-sysroot/usr/lib/libc.a | grep IO_do_write
U _IO_do_write
U _IO_do_write
0000000000001ba8 W _IO_do_write
So I would thinks that lib is linked incorrectly?
The linker command is a long one because of all the shared libs so I shortend it a bit (removed boost and custom libs):
aarch64-poky-linux-g++ -fPIC --sysroot=recipe-sysroot -O2 -pipe -g -feliminate-unused-debug-types -fdebug-prefix-map=recipe-root/git-r0 -fdebug-prefix-map=recipe-sysroot= -fdebug-prefix-map=recipe-sysroot-native= -fvisibility-inlines-hidden --sysroot=recipe-sysroot -Wl,-allow-multiple-definition -Wall -Wextra -Wpedantic -Wsuggest-override -Wswitch-default -Wduplicated-cond -Wshadow -Werror -ftemplate-depth=1024 -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -lc -Wl,--no-as-needed -Wl,--no-undefined -pthread -ldl -shared -Wl,-soname,rtsp_streamer.so -o rtsp_streamer.so ... custom static libs .and boost static libs ... -lpthread recipe-sysroot/usr/lib/gstreamer-1.0/libgstrtsp.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstrtp.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstrtpmanager.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstcoreelements.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstadder.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstapp.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstaudioconvert.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstaudiorate.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstaudioresample.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstaudiotestsrc.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstgio.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstpango.a recipe-sysroot/usr/lib/gstreamer-1.0/libgsttypefindfunctions.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstvideoconvert.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstvideorate.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstvideoscale.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstvideotestsrc.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstvolume.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstautodetect.a recipe-sysroot/usr/lib/gstreamer-1.0/libgstvideofilter.a recipe-sysroot/usr/lib/libBrokenLocale.a recipe-sysroot/usr/lib/libBrokenLocale_pic.a recipe-sysroot/usr/lib/libanl.a recipe-sysroot/usr/lib/libanl_pic.a recipe-sysroot/usr/lib/libatomic.a recipe-sysroot/usr/lib/libatomic_ops.a recipe-sysroot/usr/lib/libatomic_ops_gpl.a ... more boost static libs ... recipe-sysroot/usr/lib/libc.a recipe-sysroot/usr/lib/libc_nonshared.a recipe-sysroot/usr/lib/libc_pic.a recipe-sysroot/usr/lib/libcidn_pic.a recipe-sysroot/usr/lib/libcrypt.a recipe-sysroot/usr/lib/libcrypt_pic.a recipe-sysroot/usr/lib/libcrypto.a recipe-sysroot/usr/lib/libdl.a recipe-sysroot/usr/lib/libdl_pic.a recipe-sysroot/usr/lib/libg.a recipe-sysroot/usr/lib/libgomp.a recipe-sysroot/usr/lib/libgstallocators-1.0.a recipe-sysroot/usr/lib/libgstaudio-1.0.a recipe-sysroot/usr/lib/libgstbase-1.0.a recipe-sysroot/usr/lib/libgstcheck-1.0.a recipe-sysroot/usr/lib/libgstcontroller-1.0.a recipe-sysroot/usr/lib/libgstfft-1.0.a recipe-sysroot/usr/lib/libgstpbutils-1.0.a recipe-sysroot/usr/lib/libgstreamer-1.0.a recipe-sysroot/usr/lib/libgstriff-1.0.a recipe-sysroot/usr/lib/libgstrtp-1.0.a recipe-sysroot/usr/lib/libgstrtsp-1.0.a recipe-sysroot/usr/lib/libgstrtspserver-1.0.a recipe-sysroot/usr/lib/libgstapp-1.0.a recipe-sysroot/usr/lib/libgstnet-1.0.a recipe-sysroot/usr/lib/libgstsdp-1.0.a recipe-sysroot/usr/lib/libgsttag-1.0.a recipe-sysroot/usr/lib/libgstvideo-1.0.a recipe-sysroot/usr/lib/libhistory.a recipe-sysroot/usr/lib/libitm.a recipe-sysroot/usr/lib/liblicensing.a recipe-sysroot/usr/lib/libm.a recipe-sysroot/usr/lib/libm_pic.a recipe-sysroot/usr/lib/libmcheck.a recipe-sysroot/usr/lib/libncurses++.a recipe-sysroot/usr/lib/libncurses++w.a recipe-sysroot/usr/lib/libnsl.a recipe-sysroot/usr/lib/libnsl_pic.a recipe-sysroot/usr/lib/libnss_compat_pic.a recipe-sysroot/usr/lib/libnss_db_pic.a recipe-sysroot/usr/lib/libnss_dns_pic.a recipe-sysroot/usr/lib/libnss_files_pic.a recipe-sysroot/usr/lib/libnss_hesiod_pic.a recipe-sysroot/usr/lib/libnss_nis_pic.a recipe-sysroot/usr/lib/libnss_nisplus_pic.a recipe-sysroot/usr/lib/libprotobuf-lite.a recipe-sysroot/usr/lib/libprotobuf.a recipe-sysroot/usr/lib/libprotoc.a recipe-sysroot/usr/lib/libpthread.a recipe-sysroot/usr/lib/libpthread_nonshared.a recipe-sysroot/usr/lib/libreadline.a recipe-sysroot/usr/lib/libresolv.a recipe-sysroot/usr/lib/libresolv_pic.a recipe-sysroot/usr/lib/librpcsvc.a recipe-sysroot/usr/lib/librt.a recipe-sysroot/usr/lib/librt_pic.a recipe-sysroot/usr/lib/libsqlite3.a recipe-sysroot/usr/lib/libssl.a recipe-sysroot/usr/lib/libssp.a recipe-sysroot/usr/lib/libssp_nonshared.a recipe-sysroot/usr/lib/libstdc++.a recipe-sysroot/usr/lib/libstdc++fs.a recipe-sysroot/usr/lib/libsupc++.a recipe-sysroot/usr/lib/libthread_db_pic.a recipe-sysroot/usr/lib/libutil.a recipe-sysroot/usr/lib/libutil_pic.a recipe-sysroot/usr/lib/libz.a recipe-sysroot/usr/lib/librt.a recipe-sysroot/usr/lib/libpthread.a recipe-sysroot/usr/lib/libm.a recipe-sysroot/usr/lib/libc.a
Does anybody know what is wrong? If more info is needed please ask. Thanks in advance!
Does anybody know what is wrong?
I suspect that you are not linking against GLIBC-2.27 from Yocto, but against some other GLIBC, though it is hard to see how that could happen.
Your first step should be to find out which libc.so.6 is actually being used. You can do so by adding -Wl,-t flag to your link line. Also add -Wl,-y,_IO_do_write while you are at it.
After you know which libc.so.6 is being used, run readelf -Ws /path/to/libc.so.6 | grep _IO_do_write to see what (if any) versioned symbols are defined in it.
I don't know if this matters or if it is normal (the function did not change since 2.17)?
Yes: that is normal -- the function didn't change its ABI since GLIBC-2.17, so that's the version that is attached to it.
I figured out what went wrong. The shared library is build using a CMAKE project and our own written FindGSTREAMER.cmake. To find gstreamer, among other things, a glob is used to find all the static libs. Because on my desktop I have gstreamer installed in its seperate location this works. With Yocto however this causes every static lib in the recipe-sysroot/usr/lib directory to be linked. Including every libc library (.a, _pic.a and .so). Apparently this causes the linker unable to resolve the symbols.
Correctly filtering the libraries needed by gstreamer fixed the problem.

How to figure out which function of a shared library is used if linking fails due to missing -lX fails?

Expanding a bit: given a project that you didn't see before and a linking failure like /usr/bin/ld.bfd.real: cannot find -lperl caused by gcc -shared -o PERLUAFS/ukernel.so -fPIC -Wl,-E -fstack-protector -L/usr/local/lib -L/usr/lib/x86_64-linux-gnu/perl/5.20/CORE -lperl -ldl -lm -lpthread -lc -lcrypt PERLUAFS/ukernel_swig_perl.o .libs/libuafs_pic.a /home/richter/openafs/lib/libcmd_pic.a /home/richter/openafs/lib/libafsutil_pic.a /home/richter/openafs/lib/libopr_pic.a -L/home/richter/openafs/lib -L/home/richter/openafs/lib -lafshcrypto -lrokenafs -lcrypt -lresolv
How would I figure out the functions which are used for linking to be passed to autoconf's AC_CHECK_LIB which doesn't allow omitting the function name and even if it would I'd still prefer to know exactly which functions are used.
The most trivial answer: ask the author(s) of the code which I would always do, but I'm interested in a theoretical solution as well.
Steps to resolv are imo:
determine the implementation source file which creates the .a files -> Assuming you have a configure.ac and Makefile.am which create Makefile.in and Makefile with thousands of lines what's the best proceedure here
check the source and findout where functions of the library X used by -lX are used
I have no idea how to do any of those. I would also be happy with a listing of complications which can be solved infinitely faster by the original author(s) than me so that I will really no ever try to solve this task.

_sbrk function not found when placed in a static library

I'm creating a bare-metal application for the stm32f407 microcontroller, which has an ARM Cortex M4 core. As such, I'm delivering the implementation of functions like _sbrk myself. I now find that when I try to create a static library containing _sbrk, and link it with my main.c into an application, the linker says
"c:/progra~2/gnutoo~1/4947e~1.920/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/softfp\libg_nano.a(lib_a-sbrkr.o): In function _sbrk_r: sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'".
If I take that same function out of the static library, and put it into main.c, everything compiles/links/runs just fine.
I am almost certain that this has something to do with the order in which the linker reads in all libraries, and that when my own static library is read, no definition of _sbrk is required yet, and is therefore thrown out, only to find that it was needed anyway when later one of the standard libraries is linked in. However, I do not specify any standard libraries myself, and can therefore not change the order of linking those libraries. I also tried to declare the _sbrk function as __attribute __ ((__ used__ )), thinking that the linker would not throw away that function, but alas, this has not solved my problem.
So my question is, how can I put _sbrk into a static library, without running into unresolved references?
Update: The command to link the final application is:
C:\PROGRA~2\GNUTOO~1\4947E~1.920\bin\AR10B2~1.EXE -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -fno-rtti -fno-exceptions -std=c++11 -fno-use-cxa-atexit -fno-threadsafe-statics -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -Wl,--gc-sections -nostartfiles -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/mem.ld" -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/sections.ld" "CMakeFiles\http_server.http_server.dir\src\main.cpp.obj" "CMakeFiles\http_server.http_server.dir\src\vectors_stm32f4xx.c.obj" "CMakeFiles\http_server.http_server.dir\http_server.http_server_linker_script_dummy.c.obj" -o "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\http_server.http_server\Generic-stm32f4xx\bin\http_server.http_server.elf" "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
Where AR10B2~.EXE resolves to arm-none-eabi-g++.exe.
Adding the following makes the thing link:
-lc -lg "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
Th libcmsis_stm.cmsis_stm.a library is built with the following command:
C:\PROGRA~2\GNUTOO~1\4947E~1.920\bin\ARM-NO~2.EXE cq "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a" CMakeFiles/cmsis_stm.cmsis_stm.dir/src/cmsis/system_stm32f4xx.c.obj
Where ARM-NO~2.EXE resolves to arm-none-eabi-ar.exe
So one question remains: I would like to place the interrupt vector table, which is a variable, into the static library, but the linker throws that variable away because no source file needs that variable. Is there a mechanism to keep that variable until the linker processes the output sections in the linker file?
When ld links against a library, it will only pick those functions which are required at that time (because of references to functions from translation units which have been linked in before). The linker will forget all other functions (and the library won't be considered later).
Therefore the linking order does matter. Normally you would link in your application object file (which references malloc), then the standard library (which provides malloc and in turn references _sbrk), and then your (application) library which provides _sbrk.
So linking should look like
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -lm -lapp
with the _sbrk function being provided by libapp.
So the order of the objects to be linked does matter.
Update
As stated in one of the comments: If you add debug symbols using -g during compilation, then you have to link against libg as well (-lg).
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -g -lm -lapp

Specifying Exact Library to Link with In Automake

I am having extreme trouble cross compiling a project related to gstreamer. I am trying to link it to a library on my cross compile machine's /usr/lib
If I do the standard linker flags -L{FILESYS_DIR}/usr/lib -lGLESv2 I get pthread complaints from my cross compile toolchain. Thus, I am trying to link to this library without using the -L flag.
No matter what I do, I am getting undefined symbol glFramebuffer2D. However a quick readelf -Wc $FILESYS_DIR/usr/lib/libGLESv2.so | glFrame shows me a glFramebuffer2D symbol.
I'm pulling my hair out because no matter what flags I specify to autoconf, something called libtool throws away my link request unless I use the -L -l approach...
Edit: I had another idea, I tried -Wl, $FILESYS_DIR/usr/lib/libGLESv2.so which worked in compiling and linking but not during runtime... Obvious to me (now) because the host machine root is $FILESYS_DIR. Anyways, this is on the right approach, but I guess I need relative names.
libtool: link: arm-none-linux-gnueabi-gcc -shared .libs/libgstbla_la-gstblaoverlay.o
.libs/libgstbla_la-gstblastabilize.o .libs/libgstbla_la-gles2_utilities.o -Wl,-
rpath -Wl,/home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib -Wl,-rpath -
Wl,/home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib -L/home/z3/z3-
netra/filesys/fs/opt/gstreamer/lib /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgstbase-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgstreamer-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgstvideo-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgobject-2.0.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgmodule-2.0.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libgthread-2.0.so -lrt /home/z3/z3-netra/filesys/fs//opt/gstreamer-
0.4/lib/libglib-2.0.so -pthread -Wl,-soname -Wl,libgstbla.so -Wl,-version-script -
Wl,.libs/libgstbla.ver -o .libs/libgstbla.so
If needed, in one line as well:
libtool: link: arm-none-linux-gnueabi-gcc -shared .libs/libgstbla_la-gstblaoverlay.o .libs/libgstbla_la-gstblastabilize.o .libs/libgstbla_la-gles2_utilities.o -Wl,-rpath -Wl,/home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib -Wl,-rpath -Wl,/home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib -L/home/z3/z3-netra/filesys/fs/opt/gstreamer/lib /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgstbase-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgstreamer-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgstvideo-0.10.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgobject-2.0.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgmodule-2.0.so /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libgthread-2.0.so -lrt /home/z3/z3-netra/filesys/fs//opt/gstreamer-0.4/lib/libglib-2.0.so -pthread -Wl,-soname -Wl,libgstbla.so -Wl,-version-script -Wl,.libs/libgstbla.ver -o .libs/libgstbla.so
/usr/lib should already be on the library search path, so you shouldn't need to specify an RPATH. What you do need to do though, is to tell your (cross-)linker where to find the libraries. I think that includes transitively dependencies, such as libpthread. Do you have $FILESYS_DIR/usr/lib/libpthread.so? Does it point to /lib/libpthread.so.N? Oh wait, I see something now that I wrote it out: notice the (likely) absence of $FILESYS_DIR there: so it's possible that your linker is looking for libpthread transitively needed by libGLESv2, but not finding it, since $FILESYS_DIR/lib is not on the library include path. Add -L $FILESYS_DIR/lib to your linker flags and try again.
All, this was related to the following question: set global gcc default search paths
The problem here is related to the pthread.so (also glib.so). /usr/lib/pthread.so on a lot of systems is an ASCII script which then further links to the system's /lib/pthread.so.0 (which is a soft link). When compiling, my $(FILESYS_DIR) was correct, however the the libpthread.so there pointed to the host systems pthread.so
I made a HUGE mistake here which could have been easily avoided with correct cross compilation management. When compiling for a target system, do not use files on the target system filesystem (if it's a NFS as mine was.) Use local libraries compiled for that target system. FURTHERMORE, specify -Wl,-rpath-link=/[local location where your *.so reside]
That compiler/linker flag allows for the runtime path to be on the local system during compile and link, but maintain the standard runtime path during runtime.... Hope that made sense.

Resources