Override/clear g++ default search path for libraries - linux

Question
I want to override/clear g++ default search path for libraries, so that g++ does only search libraries under paths explicitly specified:
$ arm-linux-gnueabihf-g++ --print-search-dirs | grep libraries:
libraries: =/usr/lib/gcc-cross/arm-linux-gnueabihf/6/:/usr/lib/gcc-cross/arm-lin
ux-gnueabihf/6/../../../../arm-linux-gnueabihf/lib/arm-linux-gnueabihf/6/:/usr/l
ib/gcc-cross/arm-linux-gnueabihf/6/../../../../arm-linux-gnueabihf/lib/arm-linux
-gnueabihf/:/usr/lib/gcc-cross/arm-linux-gnueabihf/6/../../../../arm-linux-gnuea
bihf/lib/../lib/:/lib/arm-linux-gnueabihf/6/:/lib/arm-linux-gnueabihf/:/lib/../l
ib/:/usr/lib/arm-linux-gnueabihf/6/:/usr/lib/arm-linux-gnueabihf/:/usr/lib/../li
b/:/usr/lib/gcc-cross/arm-linux-gnueabihf/6/../../../../arm-linux-gnueabihf/lib/
:/lib/:/usr/lib/
Can this be done?
Background
I'm on Ubuntu 17.04 compiling c++ code for several cross-platform distributions.
I've installed Ubuntu g++-arm-linux-gnueabihf package, and created a target image under /opt/jessie_root, in this case for Jessie armhf. I also fixed all the links under this jessie_root image to be relative and not absolute.
I want to compile dynamic executables with the target rootfs libraries.
Initially I was compiling "fine" but I realized that I was linking to symbols on the host cross-toolchain libstdc++.
I'm using cmake, but for simplicity consider this commands:
/usr/bin/arm-linux-gnueabihf-g++ main.c
This will link to the host libstdc++ under /usr/lib/gcc-cross/arm-linux-gnueabihf/6/libstdc++.so, which is not desirable.
/usr/bin/arm-linux-gnueabihf-g++ main.cpp --sysroot=/opt/jessie_root -L=/usr/lib/gcc/arm-linux-gnueabihf/4.9 -D_GLIBCXX_USE_CXX11_ABI=0
This will link correctly to the target libstdc++ under /opt/jessie_root/usr/lib/gcc/arm-linux-gnueabihf/4.9/libstdc++.so, which I want.
The issue is that this seems a disaster waiting to happen, as if one of the default libs are not found on the target, the compiler will haply take one from the host cross-toolchain.
I could remove or rename them, but I don't want to mess on /usr/.
I have also played with GCC -nostdlib and LD -nostdlib, which seem to have different meanings. GCC -nostdlib is for libraries, and LD -nostdlib is for the search directories. LD -nostdlib have no effect, and GCC -nostdlib just forces me to specify the libraries manually, but it still keeps the search paths.
Naturally I could use another toolchain/compile my own, but I would prefer to stay on the packaged toolchain.

Related

How do I dump linker library search paths from the linux linker. Using 'make'

How do I get my 'make' process to show me the actual search paths and libraries found with the linker?
I have link errors for symbols I know are in libraries I am trying to use ( verified using objdump ). What I don't know is if the linker is finding the correct libraries. It should be, since all of the libraries I am using are in one directory and some of them ARE being found and used.
So I would like to get diagnostic output showing what library search paths were used, and what libraries ( with paths ) that were actually found and used by the linker.
I tried make -n and got
g++ -g -Wall -DLINUX -I../../../Common/include -I../../../Common/libs/liblua/src main.o IDUpdater.o version.o -L../../../Common/libs -lapp -lserver -lthreading -lnet -lmsgqueue -lcpp -lisam -lisamcore -ldb -ldbisam -ldbsql -Wl,--whole-archive -Wl,--no-whole-archive -o foo
I know libisam.a ,libdbisam.a and others are found and used, but libmsgqueue.a is not. These libraries are all in ../../..'Common/libs/.

Is it possible to compile a standalone Fortran executable in Linux?

For example, consider that I wrote a Fortran program in one computer and want to run it on another computer which may not have required libraries and/or has a different compiler (or even better, no Fortran compiler at all). Is it possible to create an executable with all its dependencies?
I am using gfortran (7.2.1) in Fedora 26 and sometimes use LAPACK routines in my code.
Using -static option with the program
program main
write (*,*) 'Hello'
end
I get the output
gfortran -static a.f90
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lm
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
There is no error with gfortran -static-libgfortran a.f90
In Fedora, gcc does not ship by default with static libraries.
You need to install the package glibc-static for the -static option to work, as hinted in this related question.
Note that -static-libgfortran will only do static linking of the libgfortran library and that you must have static versions of your dependencies as well.
The best option is to use Alpine Linux that uses musl libc. I highly recommend using the docker image (only 5 Mb).

How do I link libraries from multiple locations (corresponding to multiple GCC versions)?

I am currently trying to use Oracle Linux 6 OS on a SPARC S7 server to run the NPB benchmarks (with OpenMP multithreading support). The OS comes preloaded with gcc 4.4.7, which is missing the Niagara 7 optimizations. I downloaded devtoolset-3 from the Oracle Yum Repository, which has gcc 4.9.2 installed in /opt/rh/devtoolset-3/root/usr/bin. However, when I compile the NPB benchmark using the newer gcc, it automatically links to libraries associated with the older gcc 4.4.7 (located in /usr/lib). This caused my program to segfault during execution. I believe that it is because libgomp 4.4.7 is incompatible with libgomp 4.9.2. I have tried several ways of linking to the libraries in the gcc 4.9.2 folder (which is /opt/rh/devtoolset-3/root/usr/lib/gcc); none of the methods work:
-Xlinker -rpath=lib_location
-Wl -Bstatic
-L lib_location
The closest I got was when using -Wl -Bstatic ~/libgomp.a or -static -L ~/libgomp.a. It fails to find libraries such as libm that reside in the default gcc lib folder (usr/lib).
The actual command used to link is:
/opt/rh/devtoolset-3/root/usr/bin/gcc -O3 -fopenmp -mcmodel=medmid -static -L/opt/rh/devtoolset-3/root/usr/lib/gcc/sparc64-redhat-linux/4.9.2 -o ../bin/bt.W.x bt.o initialize.o exact_solution.o exact_rhs.o set_constants.o adi.o rhs.o x_solve.o y_solve.o solve_subs.o z_solve.o add.o error.o verify.o ../common/print_results.o ../common/c_timers.o ../common/wtime.o -lm -L/opt/rh/devtoolset-3/root/usr/lib/gcc/sparc64-redhat-linux/4.9.2/lib/
/opt/rh/devtoolset-3/root/usr/libexec/gcc/sparc64-redhat-linux/4.9.2/ld: cannot find -lm
/opt/rh/devtoolset-3/root/usr/libexec/gcc/sparc64-redhat-linux/4.9.2/ld: cannot find -lrt
/opt/rh/devtoolset-3/root/usr/libexec/gcc/sparc64-redhat-linux/4.9.2/ld: cannot find -lpthread
/opt/rh/devtoolset-3/root/usr/libexec/gcc/sparc64-redhat-linux/4.9.2/ld: cannot find -lc
Is there a way I can link just the libgomp library from gcc 4.9.2 while linking the remaining libraries from gcc 4.4.7?
The devtoolset compilers are all using the system libgcc, libstdc++, version 4.4.7, and can therefore not compile e.g. c++11.
I guess the gcc53-c++-5.3.0-1.el6.x86_64.rpm will do. Comes with the internal */gcc53/lib64{libgcc_s.so**, libgomp.so**, libstdc++} (version 5.3.0) ... Provides /usr/bin/{ gcc53, g++53 }
The package was created a year ago ... well tested, as extra compiler. Download link : https://drive.google.com/file/d/0B7S255p3kFXNbTBneHgwSzBodFE/view?usp=sharing
If you're going to do the -Wl,-Bstatic thing, make sure to follow it immediately by -Wl,-Bdynamic to reset to normal after your added library argument. By default, not all system libraries have static versions installed, which is why you get e.g. cannot find -lc.
So you can try this as a modification of your workaround:
-Wl,-Bstatic ~/libgomp.a -Wl,-Bdynamic
Not pretty, and this question deserves a much better answer (this is still pretty much a hack), but it should get the job done for now.

How to dynamically link libraries in automake?

I'm trying to build a package on lauchpad. For it to build I need to set a static path using the LDADD variable in automake:
relay_LDADD = /usr/lib/x86_64-linux-gnu/libm.so /usr/lib/x86_64-linux-gnu/libX11.so.6 $(RELAY_LIBS)
This compiles on the 64 bit build but fails on the 32 bit build. I tried using PKG_CHECK_MODULES but it says
No package 'm' found
No package 'X11' found
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix.
I know it not a non standard path since launchpad is doing the building? How can I get this to work?
The build failed without the libraries specified even though the package specifies them in the build-requires.
You have tried to outwit the buid-system, and it has outwitted you.
It's generally a bad idea to hard-code paths.
Debian (and ubuntu is just a derivative), has started to ship binaries (like libraries) in architecture-dependent directories, to allow installations for multiple architectures on a single system.
These libraries are installed into /usr/lib/<host-triplet>, where <host-triplet> depends on the architecture; e.g. x86_64-linux-gnu is the amd64 architecture for systems with a linux and the gnu tools.
a 32bit system would typically have a host-triplet of i386-linux-gnu.
Since you are hard-coding the library path to a 64bit location( /usr/lib/x86_64-linux-gnu/libm.so) this fails on all systems but 64bit/linux/gnu.
Instead you should just tell the linker to link against the m library (libm), resp the X11 library (libX11).
Let the linker care for the correct architecture to pick:
relay_LDADD = -lm -lX11 $(RELAY_LIBS)
In general, if you want to link against a library foo, that provides a library-file libfoo.so you would use -lfoo (stripping away the leading lib and the trailing .so).
However, sometimes this is not enough; in those cases your library might use pkg-config to provide the full CFLAGS and LDFLAGS needed to compile/link against this library.
e.g. if I want to use libquicktime:
$ pkg-config --cflags libquicktime
-I/usr/include/lqt
$ pkg-config --libs libquicktime
-lquicktime -lpthread -lm -lz -ldl
So I would use something like:
myprog_CFLAGS += $(shell pkg-config --cflags libquicktime)
myprog_LDADD += $(shell pkg-config --libs libquicktime)
That would work in any GNU(?) Makefile (not related to autotools).
In an autotools project, you would probably move the pkg-config check into configure, using the m4-macro PKG_CHECK_MODULES

Gcc linker automagically finds needed extra libraries

I am developing and testing some code on 2 different machines: my own *buntu laptop and a remote linux machine configured by someone else.
My code uses a library, let's say libfoo, that in turn depends on, say, libbase.
I would like to keep a single makefile across both the machines, but I found out things works differently when I build my project (with GCC):
On my laptop, I need to specify -lfoo -lbase for the code to link
correctly.
On the remote machine, I only need the -lfoo flag, and the linker
somehow picks up the base library automagically.
Anyone knows what is going on? Is there any flag that might have been passed when building libfoo from source that made this automatical "depencency detection" possible?
PS: I know I could just specify every library in the make file, but keeping the list of flags to the minimum looks interesting, and I would like to know what's going on under the hood.
Yes. Both -lfoo and -lbase refer to some shared libraries libfoo.so and libbase.so (perhaps with some version number).
On the remote machine, libfoo.so was built and linked to libbase.so, perhaps from some foo1.c and foo2.c like
gcc -Wall -O -fPIC foo1.c -o foo1.pic.o
gcc -Wall -O -fPIC foo2.c -o foo2.pic.o
gcc -shared -O foo1.pic.o foo2.pic.o -lbase -o libfoo.so
(of course, probably some Makefile did run above commands thru make)
On your own laptop, you (or your distribution maker) did not link -lbase inside libfoo.so
Read Drepper's how to write shared library (long) paper (and the program library howto)
It is possible to link a shared (low-level) library inside another (higher-level) shared library (and that is not possible with static libraries libfoo.a).
You could use ldd on (the absolute path of) your libraries libfoo.so and libbase.so to find out how they have been linked.

Resources