Is there some flags for gcc to avoid link with unused shared libraries? - gcc

echo "void main(){}" |gcc -xc -lm -lpthread -o test - && ldd test
Here is an example. I don't use any math function in fact. But gcc still links with libm.so finally.
Are there any optimization flags to tell gcc not to link with libm.so in such case?

I find out the result finally. -Wl,--as-needed is for this case.

In
echo "void main(){}" |gcc -xc -lm -lpthread -o test - && ldd test
the -lm explicitly asks for to link with libm.so, gcc as a good boy just follows your request.
May be you have a good reason to link with, gcc / ld cannot know why you do that and cannot decide by themselves to not follow your request, and there is no option -dontDoWhatIaskYouToDo ^^
If you do not want to link with that lib do not ask to link with it

Related

Use fgsl in fortran: how to compile with gfortran

I am trying to do something basic, but I can't find the relevant information on how to compile. I tried the following without success:
gfortran testintegral.f90 -lgsl -lgslcblas
testintegral.f90:19.6:
use fgsl
1
Fatal Error: Can't open module file 'fgsl.mod' for reading at (1): No such file
The file is taken from http://de.wikibooks.org/wiki/Fortran:_FGSL#Beispiel:_Numerische_Integration (page in german but readily understandable) so I suppose it is OK.
Maybe the syntax of the compilation command is incorrect ?
EDIT:
I edit my initial post so as not to bury important information in the comments.
Those are the paths of the libraries:
sudo find -name '*libgsl.so*'
./usr/lib/libgsl.so.0
./usr/lib/libgsl.so.0.17.0
sudo find -name '*libgslcblas.so*'
./usr/lib/libgslcblas.so.0
./usr/lib/libgslcblas.so.0.0.0
But I still got an error message when doing:
gfortran testintegral.f90 -L/usr/lib -I/usr/include/fgsl -lfgsl -lgsl -lgslcblas
/usr/bin/ld: cannot find -lgsl
/usr/bin/ld: cannot find -lgslcblas
collect2: error: ld returned 1 exit status
Use the -I flag. For example,
gfortran -I/usr/local/fgsl/include testintegral.f90 -lgsl -lgslcblas
All the .mod files in that directory are then included.
EDIT: See also comments below.
Compilation of a file containing modules in gfortran produces two file types: The source file foo.f90 is translated into foo.o. If foo.f90 contains the modules bar and baz, then bar.mod and baz.mod are also generated. They contain the interface information for these modules. Note that there is no required mapping between module and file names (although programming guildelines may require this).
When the statement use fsgl is found, the interface information is read from fsgl.mod. If that file is not found, you get the error message
Can't open module file 'fgsl.mod' for reading at (1): No such file
So, you have to change your order of compilation (possibly through changing a Makefile).
1) the easiest way is
gfortran testintegral.f90 -I/usr/local/include/fgsl -lfgsl
2) this also works
gfortran -I/usr/local/include/fgsl testintegral.f90 -lgsl -lgslcblas -lm
3) I read the log of the make check in the package, the developer used such a way
gfortran -I/usr/local/include/fgsl -g -O2 -c -o test.o testintegral.f90
/bin/bash /path/.../fgsl-1.3.0/libtool --tag=FC --mode=link gfortran -g -O2 -o test test.o /usr/local/lib/libfgsl.la -lgsl -lgslcblas -lm
UPDATE:
First check the linkers for fgsl
pkg-config --libs fgsl
probably will get something like this
-L/usr/local/lib -lfgsl -lgsl -lgslcblas -lm
Then you put the linkers, works for all the cases!
gfortran -I/usr/include/fgsl example.f90 -lfgsl -lgsl -lgslcblas -lm
UPDATE: I answered too soon, here is the best universal method I found:
gfortran `pkg-config --cflags fgsl` testintegral.f90 -o integral `pkg-config --libs fgsl`

What's the Difference between linking by GCC and LD?

Recently I was creating a loadable module and found that both
gcc -fPIC --shared -o foo.so.1 foo.c
and
gcc -fPIC --shared -c foo.c
ld --shared -o foo.so.2 foo.o
can achieve the same effect.
I also discovered that foo.so.1 is larger than foo.so.2 by about 3KB, and
gcc -### -fPIC --shared -o foo.so.1 foo.c
revealed that GCC added stuffs other than foo.c into foo.so.1 (e.g, crtendS.o and crtn.o):
/usr/lib/gcc/x86_64-linux-gnu/4.7/collect2 "--sysroot=/" --build-id --no-add-needed --eh-frame-hdr -m elf_x86_64 "--hash-style=both" -shared -o foo.so.1 /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.7/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/4.7 -L/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.7/../../.. /tmp/cc3JBdCJ.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.7/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/4.7/../../../x86_64-linux-gnu/crtn.o
Since both foo.so.1 and foo.so.2 can be loaded via dlopen, I was wondering:
What's the difference between these 2 linking methods?
Do crtendS.o and crtn.o make any difference to functions in created libraries?
There's no difference in principle. When you "link by gcc" it actually calls ld. If you get a message at the linking stage when "linking by gcc" you'll immediately see that it is actually from ld. If you want to pass some ld-specific command-line options to ld, gcc's command-line interface has features intended specifically for that purpose (-Xlinker and -Wl options).
As for the additional objects files... they probably contain global load-time library initialization/de-initialization code implicitly added by the compiler. (Requested by the standard library?) You can find some information about it here: https://gcc.gnu.org/onlinedocs/gccint/Initialization.html

GCC suppress flags

I'm trying to create a shared library with my gcc. It's a gcc for vxworks (thats probably the problem...).
I use the gcc as following:
./gcc -shared -B/path/to/gnutools/bin -o test.so test.c
Result:
/path/to/ld: -r and -shared may not be used together
collect2: ld returned 1 exit status
If I try the same with the linux gcc, there's no problem. So i guess the gcc for VxWorks automatically passes the -r (or -i, which is the same and results in the same) flag to the linker. Is there a way to suppress this?
Greetz
marty
PS: making it static is not really an alternative...
Try compile object file separately with -fPIC and then link:
gcc -Wall -fPIC -c -o test.o test.c
gcc -Wall -shared -o test.so test.o
Another suggestion is to use libtool (at least to figure out the correct flags).
A workaround may be to go directly with ld:
ld -shared -o test.so test.o -lc

linker tells me it can't resolve symbols, but they're there?

I am trying to compile a simple test app using a library I've written. This compiles and runs fine on other machines.
I have libroller.so available at /usr/lib. I'm compiling a main.cpp as such:
g++ -g3 -Wall -I"../../" -lrt -lroller -o rap main.o
It complains of numerous errors such as:
/....../main.cpp:51: undefined reference to `Log::i(char const*, ...)'
However, I know that these exist in this so:
nm -Ca /usr/lib/libroller.so | grep "Log::i"
00000000001f5d50 T Log::i(char const*, ...)
0000000000149530 W Log::i(std::string const&)
Both are 64 bit:
file /usr/lib/libroller.so
/usr/lib/libroller.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped
file main.o
main.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
Unlike GCC and ld can't find exported symbols...but they're there! I'm pretty sure these symbols are defined. The same .so works with another using some of the same symbols.
EDIT/ANSWER: The order of objects is important. Placing main.o before the libraries was necessary. I'm guessing the linker had no unresolved symbols to deal with until it got to main.o -- which was the last object in its list. I'm still a little confused as to why this worked on other machines for many months...
Change:
g++ -g3 -Wall -I"../../" -lrt -lroller -o rap main.o
to:
g++ -g3 -Wall main.o -lroller -lrt -o rap
Link order matters (and the -I is redundant in this instance).
Consider changing the sequence of library and main.o:
g++ -g3 -Wall -I"../../" -o rap main.o -lrt -lroller
Have a look at this post: Why does the order in which libraries are linked sometimes cause errors in GCC?
Your question is a dup of this one, and has the same answer: order of libraries on link line matters.

Why does the order in which libraries are linked sometimes cause errors in GCC?

Why does the order in which libraries are linked sometimes cause errors in GCC?
(See the history on this answer to get the more elaborate text, but I now think it's easier for the reader to see real command lines).
Common files shared by all below commands
// a depends on b, b depends on d
$ cat a.cpp
extern int a;
int main() {
return a;
}
$ cat b.cpp
extern int b;
int a = b;
$ cat d.cpp
int b;
Linking to static libraries
$ g++ -c b.cpp -o b.o
$ ar cr libb.a b.o
$ g++ -c d.cpp -o d.o
$ ar cr libd.a d.o
$ g++ -L. -ld -lb a.cpp # wrong order
$ g++ -L. -lb -ld a.cpp # wrong order
$ g++ a.cpp -L. -ld -lb # wrong order
$ g++ a.cpp -L. -lb -ld # right order
The linker searches from left to right, and notes unresolved symbols as it goes. If a library resolves the symbol, it takes the object files of that library to resolve the symbol (b.o out of libb.a in this case).
Dependencies of static libraries against each other work the same - the library that needs symbols must be first, then the library that resolves the symbol.
If a static library depends on another library, but the other library again depends on the former library, there is a cycle. You can resolve this by enclosing the cyclically dependent libraries by -( and -), such as -( -la -lb -) (you may need to escape the parens, such as -\( and -\)). The linker then searches those enclosed lib multiple times to ensure cycling dependencies are resolved. Alternatively, you can specify the libraries multiple times, so each is before one another: -la -lb -la.
Linking to dynamic libraries
$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -L. -ld -o libb.so # specifies its dependency!
$ g++ -L. -lb a.cpp # wrong order (works on some distributions)
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong order
$ g++ -Wl,--as-needed a.cpp -L. -lb # right order
It's the same here - the libraries must follow the object files of the program. The difference here compared with static libraries is that you need not care about the dependencies of the libraries against each other, because dynamic libraries sort out their dependencies themselves.
Some recent distributions apparently default to using the --as-needed linker flag, which enforces that the program's object files come before the dynamic libraries. If that flag is passed, the linker will not link to libraries that are not actually needed by the executable (and it detects this from left to right). My recent archlinux distribution doesn't use this flag by default, so it didn't give an error for not following the correct order.
It is not correct to omit the dependency of b.so against d.so when creating the former. You will be required to specify the library when linking a then, but a doesn't really need the integer b itself, so it should not be made to care about b's own dependencies.
Here is an example of the implications if you miss specifying the dependencies for libb.so
$ export LD_LIBRARY_PATH=. # not needed if libs go to /usr/lib etc
$ g++ -fpic -shared d.cpp -o libd.so
$ g++ -fpic -shared b.cpp -o libb.so # wrong (but links)
$ g++ -L. -lb a.cpp # wrong, as above
$ g++ -Wl,--as-needed -L. -lb a.cpp # wrong, as above
$ g++ a.cpp -L. -lb # wrong, missing libd.so
$ g++ a.cpp -L. -ld -lb # wrong order (works on some distributions)
$ g++ -Wl,--as-needed a.cpp -L. -ld -lb # wrong order (like static libs)
$ g++ -Wl,--as-needed a.cpp -L. -lb -ld # "right"
If you now look into what dependencies the binary has, you note the binary itself depends also on libd, not just libb as it should. The binary will need to be relinked if libb later depends on another library, if you do it this way. And if someone else loads libb using dlopen at runtime (think of loading plugins dynamically), the call will fail as well. So the "right" really should be a wrong as well.
The GNU ld linker is a so-called smart linker. It will keep track of the functions used by preceding static libraries, permanently tossing out those functions that are not used from its lookup tables. The result is that if you link a static library too early, then the functions in that library are no longer available to static libraries later on the link line.
The typical UNIX linker works from left to right, so put all your dependent libraries on the left, and the ones that satisfy those dependencies on the right of the link line. You may find that some libraries depend on others while at the same time other libraries depend on them. This is where it gets complicated. When it comes to circular references, fix your code!
Here's an example to make it clear how things work with GCC when static libraries are involved. So let's assume we have the following scenario:
myprog.o - containing main() function, dependent on libmysqlclient
libmysqlclient - static, for the sake of the example (you'd prefer the shared library, of course, as the libmysqlclient is huge); in /usr/local/lib; and dependent on stuff from libz
libz (dynamic)
How do we link this? (Note: examples from compiling on Cygwin using gcc 4.3.4)
gcc -L/usr/local/lib -lmysqlclient myprog.o
# undefined reference to `_mysql_init'
# myprog depends on libmysqlclient
# so myprog has to come earlier on the command line
gcc myprog.o -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# we have to link with libz, too
gcc myprog.o -lz -L/usr/local/lib -lmysqlclient
# undefined reference to `_uncompress'
# libz is needed by libmysqlclient
# so it has to appear *after* it on the command line
gcc myprog.o -L/usr/local/lib -lmysqlclient -lz
# this works
If you add -Wl,--start-group to the linker flags it does not care which order they're in or if there are circular dependencies.
On Qt this means adding:
QMAKE_LFLAGS += -Wl,--start-group
Saves loads of time messing about and it doesn't seem to slow down linking much (which takes far less time than compilation anyway).
Another alternative would be to specify the list of libraries twice:
gcc prog.o libA.a libB.a libA.a libB.a -o prog.x
Doing this, you don't have to bother with the right sequence since the reference will be resolved in the second block.
A quick tip that tripped me up: if you're invoking the linker as "gcc" or "g++", then using "--start-group" and "--end-group" won't pass those options through to the linker -- nor will it flag an error. It will just fail the link with undefined symbols if you had the library order wrong.
You need to write them as "-Wl,--start-group" etc. to tell GCC to pass the argument through to the linker.
You may can use -Xlinker option.
g++ -o foobar -Xlinker -start-group -Xlinker libA.a -Xlinker libB.a -Xlinker libC.a -Xlinker -end-group
is ALMOST equal to
g++ -o foobar -Xlinker -start-group -Xlinker libC.a -Xlinker libB.a -Xlinker libA.a -Xlinker -end-group
Careful !
The order within a group is important !
Here's an example: a debug library has a debug routine, but the non-debug
library has a weak version of the same. You must put the debug library
FIRST in the group or you will resolve to the non-debug version.
You need to precede each library in the group list with -Xlinker
Link order certainly does matter, at least on some platforms. I have seen crashes for applications linked with libraries in wrong order (where wrong means A linked before B but B depends on A).
I have seen this a lot, some of our modules link in excess of a 100 libraries of our code plus system & 3rd party libs.
Depending on different linkers HP/Intel/GCC/SUN/SGI/IBM/etc you can get unresolved functions/variables etc, on some platforms you have to list libraries twice.
For the most part we use structured hierarchy of libraries, core, platform, different layers of abstraction, but for some systems you still have to play with the order in the link command.
Once you hit upon a solution document it so the next developer does not have to work it out again.
My old lecturer used to say, "high cohesion & low coupling", it’s still true today.

Resources