Cross compiling with arm-linux-gnueabihf - gcc

I am quite new to cross compiling. After downloading the arm-linux-gnueabihf tool from arm. I tried to use the binary called arm-linux-gnueabihf-g++ and arm-linux-gnueabihf-gcc to compile my code. My command looks something like:
~/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -Isrc -I/usr/include -std=c++11 -Wall -Wno-unknown-pragmas -O0 -g3 -D__DEBUG_BUILD__ -DDEVELOPMENT -MMD -c -o "Debug/src/BatteryStatus.o" "src/BatteryStatus.cpp"
I immediately run into this issue:
~/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/stdlib.h:133:35: error: missing binary operator before token "("
#if __HAVE_FLOAT16 && __GLIBC_USE (IEC_60559_TYPES_EXT)
It's weird that the issue happens in the tool chain, I would expect some incompatibilities in the libraries I am using. The environment entails CentOS 7.2, c++ 11 and I am compiling for an ARM 32-bit target on a x86_64 host machine. Building a simple hello world program went fine, it compiled and ran successfully on the target machine.

You are pointing to your native header files directory, /usr/include, in your build command. This is very likely the cause of your problem. Try this command instead:
~/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -Isrc -std=c++11 -Wall -Wno-unknown-pragmas -O0 -g3 -D__DEBUG_BUILD__ -DDEVELOPMENT -MMD -c -o "Debug/src/BatteryStatus.o" "src/BatteryStatus.cpp
The default directories used by the toolchain can be displayed using:
echo | /opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -v -x c -E -
Using built-in specs.
COLLECT_GCC=/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc
Target: arm-linux-gnueabihf
Configured with: /tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/src/gcc/configure --target=arm-linux-gnueabihf --prefix= --with-sysroot=/arm-linux-gnueabihf/libc --with-build-sysroot=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/install//arm-linux-gnueabihf/libc --with-bugurl=https://bugs.linaro.org/ --enable-gnu-indirect-function --enable-shared --disable-libssp --disable-libmudflap --enable-checking=release --enable-languages=c,c++,fortran --with-gmp=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpfr=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-mpc=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-isl=/tmp/dgboter/bbs/rhev-vm8--rhe6x86_64/buildbot/rhe6x86_64--arm-linux-gnueabihf/build/build-arm-linux-gnueabihf/host-tools --with-arch=armv7-a --with-fpu=neon --with-float=hard --with-arch=armv7-a --with-pkgversion='GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36)'
Thread model: posix
gcc version 8.3.0 (GNU Toolchain for the A-profile Architecture 8.3-2019.03 (arm-rel-8.36))
COLLECT_GCC_OPTIONS='-v' '-E' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'
/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/cc1 -E -quiet -v -iprefix /opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/ -isysroot /opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc - -mfloat-abi=hard -mfpu=neon -mtls-dialect=gnu -marm -march=armv7-a+simd
ignoring duplicate directory "/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include"
ignoring nonexistent directory "/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/local/include"
ignoring duplicate directory "/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed"
ignoring duplicate directory "/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/../../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include"
#include "..." search starts here:
#include <...> search starts here:
/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include
/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed
/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include
/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include
End of search list.
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "<stdin>"
COMPILER_PATH=/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/8.3.0/:/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../libexec/gcc/:/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/bin/
LIBRARY_PATH=/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/:/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/:/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/lib/:/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/lib/:/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-E' '-mfloat-abi=hard' '-mfpu=neon' '-mtls-dialect=gnu' '-marm' '-march=armv7-a+simd'
That is, on my system, the correct, default directories for the header files would be:
/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include
/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/include-fixed
/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/8.3.0/../../../../arm-linux-gnueabihf/include
/opt/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin/../arm-linux-gnueabihf/libc/usr/include
and not /usr/include.

Related

Why GCC can't pass options to `gas` assembler with `-Wa,-adhln=a.lst`?

When I want to generate the list file of a.c with the name a.lst, I execute the command:
gcc -v -S -Wa,-adhln=a.lst a.c
and some of the output is as following:
gcc version 5.3.1 20160413 (Ubuntu 5.3.1-14ubuntu2)
COLLECT_GCC_OPTIONS='-v' '-S' '-mtune=generic' '-march=x86-64'
/usr/lib/gcc/x86_64-linux-gnu/5/cc1 -quiet -v -imultiarch x86_64-linux-gnu a.c -quiet -dumpbase a.c -mtune=generic -march=x86-64 -auxbase a -version -o a.s -fstack-protector-strong -Wformat -Wformat-security
So, according to the output, I can't find the options of assembler -adhln=a.lst is being passed, and there is no a.lst file generated. My gcc version is gcc (Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413, as version is GNU assembler (GNU Binutils for Ubuntu) 2.26. What's wrong with me?
The -Wa option passes flags to the assembler.
Your command uses -S which means "do not run the assembler".

How to convert assembly code to executable in LLVM

I have converted c program into assembly code using following commands in LLVM :
clang -emit-llvm matrix.c -c -o matrix.bc
llc -march=alpha matrix.bc -o matrix.s
Now how to convert matrix.s assembly file into executable file of alpha.
How to do that?
clang can also be used
clang matrix.s -L [additional library locations] -mllvm -Wall -g -L. -Wl,-pie -I. -I[additional include locations] -o [executable output]
Adjust the flags as your needs dictate.
EDIT
Without the need for other includes or libraries just call:
clang matrix.s -mllvm -Wall -g -Wl,-pie -o matrix.out

Changing OCaml's gcc after installation

I installed OCaml via OPAM, and by default it uses gcc as the command to compile .c files. For instance, if I run ocamlopt -verbose file.c, I obtain:
+ gcc -Wall -D_FILE_OFFSET_BITS=64 -D_REENTRANT -g
-fno-omit-frame-pointer -c -I'/home/user/.opam/4.02.1+fp/lib/ocaml' 'test.c'
I'd like to change the GCC binary that is used by OCaml, for instance to replace it with gcc-5.1 or /opt/my-gcc/bin/gcc.
Is it possible to do so without reconfiguring and recompiling OCaml? I suppose I could add a gcc alias to a directory in the PATH, but I'd prefer a cleaner solution if there is one.
To check if gcc was not chosen based on a textual configuration file (that I could easily change), I searched for occurrences of gcc in my /home/user/.opam/4.02.1+fp directory, but the only occurrence in a non-binary file that I found was in lib/ocaml/Makefile.config, and changing it does nothing for the already-compiled binary.
ocamlopt uses gcc for three things. First, for compiling .c files that appear on the command line of ocamlopt. Second, for assembling the .s files that it generates internally when compiling an OCaml source file. Third, for linking the object files together at the end.
For the first and third, you can supply a different compiler with the -cc flag.
For the second, you need to rebuild the OCaml compiler.
Update
Here's what I see on OS X when compiling a C and an OCaml module with the -verbose flag:
$ ocamlopt -verbose -cc gcc -o m m.ml c.c 2>&1 | grep -v warning
+ clang -arch x86_64 -c -o 'm.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlasm461f1b.s' \
+ gcc -c -I'/usr/local/lib/ocaml' 'c.c'
+ clang -arch x86_64 -c -o \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartupb6b001.s'
+ gcc -o 'm' '-L/usr/local/lib/ocaml' \
'/var/folders/w4/1tgxn_s936b148fdgb8l9xv80000gn/T/camlstartup695941.o' \
'/usr/local/lib/ocaml/std_exit.o' 'm.o' \
'/usr/local/lib/ocaml/stdlib.a' 'c.o' \
'/usr/local/lib/ocaml/libasmrun.a'
So, the compiler given by the -cc option is used to do the compilation of the .c file and the final linking. To change the handling of the .s files you need to rebuild the compiler. I'm going to update my answer above.

"CPU you selected does not support x86-64 instruction set" error on Cygwin-x64

I'm trying to install openssl in cygwin by following these instructions:
I dowloaded the latest tarball from this site http://www.openssl.org/source/, and put it in C:\cygwin64\home, then I run these commands from cygwin
tar zxvf openssl-1.0.1e.tar.gz
cd openssl-1.0.1e
./config
make
make test
make install
(Instructions from here :http://www.slideshare.net/ganaaturuu/cygwinandopen-sslinstallguide)
Up to the 3rd step ./config it works fine I believe, at least there are no errors reported, and it gives the message "Configured for Cygwin." in the end. When I run make though it gives me this output:
making all in crypto...
make[1]: Entering directory '/home/openssl-1.0.1e/crypto'
( echo "#ifndef MK1MF_BUILD"; \
echo ' /* auto-generated by crypto/Makefile for crypto/cversion.c */'; \
echo ' #define CFLAGS "gcc -DOPENSSL_THREADS -DDSO_DLFCN -DHAVE_DLFCN_H -DTERM IOS -DL_ENDIAN -fomit-frame-pointer -O3 -march=i486 -Wall -DOPENSSL_BN_ASM_PART_ WORDS -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DRMD160_ASM -DAES_ASM -DVPAES_ASM -DWHIRLP OOL_ASM -DGHASH_ASM"'; \
echo ' #define PLATFORM "Cygwin"'; \
echo " #define DATE \"`LC_ALL=C LC_TIME=C date`\""; \
echo '#endif' ) >buildinf.h
gcc -I. -I.. -I../include -DOPENSSL_THREADS -DDSO_DLFCN -DHAVE_DLFCN_H -DTERMI OS -DL_ENDIAN -fomit-frame-pointer -O3 -march=i486 -Wall -DOPENSSL_BN_ASM_PART_W ORDS -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DRMD160_ASM -DAES_ASM -DVPAES_ASM -DWHIRLPO OL_ASM -DGHASH_ASM -c -o cryptlib.o cryptlib.c
cryptlib.c:1:0: error: CPU you selected does not support x86-64 instruction set
/* crypto/cryptlib.c */
^
cryptlib.c:1:0: error: CPU you selected does not support x86-64 instruction set
<builtin>: recipe for target 'cryptlib.o' failed
make[1]: *** [cryptlib.o] Error 1
make[1]: Leaving directory '/home/openssl-1.0.1e/crypto'
Makefile:278: recipe for target 'build_crypto' failed
make: *** [build_crypto] Error 1
I searched about the "CPU you selected does not support x86-64 instruction set" and I think it has to do with CFLAGS and -march=i486 option, but I'm not at all sure as into what it should be changed.
In this How to compile a C++ program as 64-bit on 64-bit machine? question there are some solutions suggested, but in my case there are nowhere in the makefile options like -m32 and -march=i686 to remove.
If you could please show me the right direction to search this, if not the solution, I would be grateful.
I'm working on Windows 7 64-bit, with cygwin and gcc version 4.8.2.
Here's a "mee too" answer because things have changed a bit. Cygwin-x64 support was cut-in in May 2015 under Issue 3110: Adding support for x86_64 Cygwin.
However, config still selects the i686 version of the library to build. Also see Issue #4326: Failed to configure for Cygwin-x64 in the OpenSSL bug tracker.
To build OpenSSL 1.0.2 on Cygwin-x64, you have to use Configure and select the triplet. Below is the soup-to-nuts recipe.
$ curl https://www.openssl.org/source/openssl-1.0.2f.tar.gz -o openssl-1.0.2f.tar.gz
...
$ tar -xzf openssl-1.0.2f.tar.gz
...
$ cd openssl-1.0.2f
Then:
$ ./Configure Cygwin-x86_64 shared no-ssl2 no-ssl3 --openssldir="$HOME/ssl"
...
$ make depend
...
$ make
...
$ make install_sw
install_sw installs the headers in $OPENSSLDIR/include, and the libraries in $OPENSSLDIR/lib. It does not install the man pages.
You then compile and link with:
$ gcc -I "$HOME/ssl/include" test.c -o test.exe "$HOME/ssl/lib/libcrypto.a" "$HOME/ssl/lib/libssl.a"
Linking against libcrypto.a and libssl.a means you avoid library path problems. Things will "just work" for you.
Also, if you need this for OpenSSL 1.0.1, then you can copy/paste the triplet's settings from 1.0.2's Configure (from line 613):
$ grep "Cygwin-x86_64" Configure
"Cygwin-x86_64", "gcc:-DTERMIOS -DL_ENDIAN -O3 -Wall:::CYGWIN::SIXTY_FOUR_BIT_LONG RC4_CHUNK DES_INT DES_UNROLL:${x86_64_asm}:mingw64:dlfcn:cygwin-shared:-D_WINDLL:-shared:.dll.a",
If you want config to "just work" for 1.0.1, then add the following. Be sure the line for Cygwin-x86_64 was added to Configure.
x86_64-*-cygwin) OUT="Cygwin-x86_64" ;; <== Add this in front of the ones below
*-*-cygwin_pre1.3) OUT="Cygwin-pre1.3" ;;
*-*-cygwin) OUT="Cygwin" ;;
It would seem that 1.0.1 does not have support for Cygwin/x64.
This thread indicates that the necessary patches have been pulled into the 1.0.2 branch.
here is one post you can refer to. the basic idea is that specifying -march=x86-64 and avoid using assembly language. assembly language is not as portable as c language.

Telling ld where to look for dependent shared libraries during compilation

I'm trying to crosscompile some libraries for an ARM processor, specifically:
DirectFB, which depends on libpng, which depends on zlib.
Libpng is linked against zlib, but since the paths on the build system don't match the paths on the target system, ld can't find the zlib that libpng is linked against during the compilation of DirectFB.
I've reduced the issue to the following example:
testb depends on libb, which depends on liba.
Build liba:
gcc -Wall -fPIC -c a.c
gcc -shared -Wl,-soname,liba.so.1 -o liba.so.1.0 a.o
ln -fs liba.so.1.0 liba.so.1
ln -fs liba.so.1 liba.so
Built testa:
gcc -Wall -I. -L. testa.c -la -o testa
LD_LIBRARY_PATH=. ./testa
a: 0
Build libb:
gcc -Wall -fPIC -I. -L. -c b.c -la
gcc -shared -Wl,-soname,libb.so.1 -o libb.so.1.0 b.o
ln -fs libb.so.1.0 libb.so.1
ln -fs libb.so.1 libb.so
So far, so good. However, building testb fails:
gcc -Wall -I. -L. testb.c -lb -o testb
Results in:
./libb.so: undefined reference to `a'
collect2: ld returned 1 exit status
make: *** [testb] Error 1
So ld can't find the definition of a in liba, even though libb is linked against liba, and both are in the current directory, which is being passed with "-L."
Running gcc with -v results in:
gcc -v -Wall -I. -L. testb.c -lb -o testb
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5.1' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu --target=i486-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1)
COLLECT_GCC_OPTIONS='-v' '-Wall' '-I.' '-L.' '-o' 'testb' '-mtune=generic' '-march=i486'
/usr/lib/gcc/i486-linux-gnu/4.4.3/cc1 -quiet -v -I. testb.c -D_FORTIFY_SOURCE=2 -quiet -dumpbase testb.c -mtune=generic -march=i486 -auxbase testb -Wall -version -fstack-protector -o /tmp/ccqAkMFb.s
GNU C (Ubuntu 4.4.3-4ubuntu5.1) version 4.4.3 (i486-linux-gnu)
compiled by GNU C version 4.4.3, GMP version 4.3.2, MPFR version 2.4.2-p1.
GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=128244
ignoring nonexistent directory "/usr/local/include/i486-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../i486-linux-gnu/include"
ignoring nonexistent directory "/usr/include/i486-linux-gnu"
#include "..." search starts here:
#include <...> search starts here:
.
/usr/local/include
/usr/lib/gcc/i486-linux-gnu/4.4.3/include
/usr/lib/gcc/i486-linux-gnu/4.4.3/include-fixed
/usr/include
End of search list.
GNU C (Ubuntu 4.4.3-4ubuntu5.1) version 4.4.3 (i486-linux-gnu)
compiled by GNU C version 4.4.3, GMP version 4.3.2, MPFR version 2.4.2-p1.
GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=128244
Compiler executable checksum: 2349e080d2b2f3f970047e63bbe98cb2
COLLECT_GCC_OPTIONS='-v' '-Wall' '-I.' '-L.' '-o' 'testb' '-mtune=generic' '-march=i486'
as -V -Qy -o /tmp/ccc6ux7S.o /tmp/ccqAkMFb.s
GNU assembler version 2.20.1 (i486-linux-gnu) using BFD version (GNU Binutils for Ubuntu) 2.20.1-system.20100303
COMPILER_PATH=/usr/lib/gcc/i486-linux-gnu/4.4.3/:/usr/lib/gcc/i486-linux-gnu/4.4.3/:/usr/lib/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.4.3/:/usr/lib/gcc/i486-linux-gnu/:/usr/lib/gcc/i486-linux-gnu/4.4.3/:/usr/lib/gcc/i486-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/i486-linux-gnu/4.4.3/:/usr/lib/gcc/i486-linux-gnu/4.4.3/:/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../:/lib/:/usr/lib/:/usr/lib/i486-linux-gnu/
COLLECT_GCC_OPTIONS='-v' '-Wall' '-I.' '-L.' '-o' 'testb' '-mtune=generic' '-march=i486'
/usr/lib/gcc/i486-linux-gnu/4.4.3/collect2 --build-id --eh-frame-hdr -m elf_i386 --hash-style=both -dynamic-linker /lib/ld-linux.so.2 -o testb -z relro /usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crt1.o /usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crti.o /usr/lib/gcc/i486-linux-gnu/4.4.3/crtbegin.o -L. -L/usr/lib/gcc/i486-linux-gnu/4.4.3 -L/usr/lib/gcc/i486-linux-gnu/4.4.3 -L/usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/i486-linux-gnu/4.4.3/../../.. -L/usr/lib/i486-linux-gnu /tmp/ccc6ux7S.o -lb -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/i486-linux-gnu/4.4.3/crtend.o /usr/lib/gcc/i486-linux-gnu/4.4.3/../../../../lib/crtn.o
./libb.so: undefined reference to `a'
collect2: ld returned 1 exit status
make: *** [testb] Error 1
Setting LD_LIBRARY_PATH and/or LIBRARY_PATH to the current directory doesn't resolve the problem.
Compiling with -la works, but it shouldn't be necessary, since libb is linked against liba. For example, when linking against libpng in a native build environment (correct paths, library paths in ld.so.conf) doesn't require -lz.
Also, setting additional libs to link against is a pain, because I would have to patch the Makefiles for every compilation that depends on a lib that depends on another lib.
In summary, how do I tell ld where to look for dependent shared libraries during compilation?
My problem is similar to these two:
Cross-linking for ARM/QNX fails with indirect/transitive dependencies
How to resolve shared library linking during compilation( GCC )?
Neither suggests a solution which doesn't require the addition of -la, which in my opinion shouldn't be necessary.
Files used:
a.c:
int a() {
return 0;
}
liba.h:
#ifndef LIBA_H
#define LIBA_H
int a();
#endif
testa.c:
#include <stdio.h>
#include <liba.h>
int main() {
printf("a: %d\r\n", a());
return 0;
}
b.c:
#include <liba.h>
int b() {
return a();
}
libb.h:
#ifndef LIBB_H
#define LIBB_H
int b();
#endif
testb.c:
#include <stdio.h>
#include <libb.h>
int main() {
printf("b: %d\r\n", b());
return 0;
}
Makefile:
# Makefile for shared library test
all:
liba:
gcc -Wall -fPIC -c a.c
gcc -shared -Wl,-soname,liba.so.1 -o liba.so.1.0 a.o
ln -fs liba.so.1.0 liba.so.1
ln -fs liba.so.1 liba.so
testa: liba
gcc -Wall -I. -L. testa.c -la -o testa
runtesta: testa
LD_LIBRARY_PATH=. ./testa
libb: liba
gcc -Wall -fPIC -I. -L. -c b.c -la
gcc -shared -Wl,-soname,libb.so.1 -o libb.so.1.0 b.o
ln -fs libb.so.1.0 libb.so.1
ln -fs libb.so.1 libb.so
testb: libb
gcc -v -Wall -I. -L. testb.c -lb -o testb
runtestb: testb
LD_LIBRARY_PATH=. ./testb
clean:
# clean up
rm -rf *.o
rm -rf liba.s*
rm -rf libb.s*
rm -rf testa testb
You must add -la to linking phase of lb (second line below is essential):
$ gcc -Wall -fPIC -I. -L. -c b.c -la
$ gcc -L. -shared -o libb.so b.o -la
$ LD_LIBRARY_PATH=. gcc -Wall -I. -L. testb.c -lb -o testb
$ LD_LIBRARY_PATH=. ./testb
b: 0
Also -la on compilation isn't really required, I left it only because it was in your original example. Instead first line
$ gcc -Wall -fPIC -I. -L. -c b.c
will be enough.
Common rule is -- linker is guy, who need libraries, not compiler.

Resources