Very strange linker behavior - gcc

This is strange because I was able to get the error below to go away by removing the reference to libm.
gcc -o example example.o -Wl -L/home/kensey/cdev/lib -L/usr/lib/x86_64-linux-gnu -lmysqlclient -lpthread -lz -L/usr/lib/x86_64-linux-gnu -lm -lrt -ldl -lcdev -L/home/kensey/www.tools/gplot-lib -lgplot -L/home/kensey/www.tools/gd1_3ret -lgd -lxml2 -lcurl
/usr/bin/ld: /home/kensey/www.tools/gplot-lib/libgplot.a(set.o): undefined reference to symbol 'floor##GLIBC_2.2.5'
/usr/bin/ld: note: 'floor##GLIBC_2.2.5' is defined in DSO /usr/lib/x86_64-linux-gnu/libm.so so try adding it to the linker command line
/usr/lib/x86_64-linux-gnu/libm.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
So, if I remove the -lm part of the command, I do not get the error. However, I wonder if anyone knows as to why removing a reference to a library that is needed would fix this. How does the linker know which library to look in? Also - is there a way to query a built executable and say 'which library did you resolve the reference to 'floor'? obviously, there is something going on that I don't understand, and that bothers me...

The explanation to what's happening is very simple:
Your libgplot.a depends on libm.so, yet the order of -lm and -lgplot on the link line is wrong.
The order of libraries on the link line does matter. In general, system libraries (-lpthread, -lm, -lrt, -ldl) should follow everything else on the link line.
When you remove -lm from the link line, libm.so.6 is still pulled into the link by some other library that appears later on the link line (libgd, libxml2 or libcurl) because that library depends on libm.so.6. But now libm.so.6 is in correct place on the link line, and so everything works.
if I put -lm at the end of the link command, listing it as the last library, I do not get the error.
That confirms above explanation.

I've solved the same problem with export LDFLAGS="$LDFLAGS -lm"

Perhaps, your library search paths (/usr/local/lib/ or /usr/lib/, ...) do not contain 64bit libm so gcc cannot locate it if you specify with l flag. If you only specify only the directory it looks like it can find the right one. So you can try:
LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu
and use -lm

Hard to tell. Because there are custom library directories in the command line it's conceivable that -lm links an incompatible alternative version. Without -lm the linker could pull in another version of it because it's needed by one of the libraries you link.
To make sure strace both invocations and see where libm.so is coming from in both cases.
BTW, -Wl switch seems to do nothing and -L/usr/lib/x86_64-linux-gnu is mentioned twice.

Just to add to the list of answers, http://fedoraproject.org/wiki/UnderstandingDSOLinkChange It is informative. It isn't relevant to the question asked above, but, the explanation relates to the error message /usr/bin/ld: note: 'some_reference' is defined in DSO some.so so try adding it to the linker command line

One explanation could be:
It's possibly there is a weakly linked function foo defined outside of libm that is replaced by a strongly linked version of foo defined inside libm, and it is this strongly linked version that calls the undefined function.
This would explain how adding a library can cause an undefined function error.

I just ran into a similar problem; I remember that the order of the libraries did not matter (at least not in the cases I worked with) in the past for gcc. In this question here somebody noticed that the behaviour seems to have changed between 4.4 and 4.5 .
In my case, I got rid of the error message by doing the linking at:
g++ -Wl,--copy-dt-needed-entries [options] [libraries] [object files] -o executable-file

I faced the similar issue because I had manually updated the dev toolchain on my centOS machine to solve a VScode Remote dependency and was linking C++ library with c code.
In my case, I solved this by adding in the Makefile:
LDFLAG=-Wl,--copy-dt-needed-entries
I also pointed my gcc to the version I wanted (After updating toolchain, gcc pointed to the toolchain : /opt/rh/devtoolset-2/root/usr/bin/gcc)
CC=\usr\bin\gcc which is (gcc version 4.4.7)

Use this:
administrator#administrator-Veriton-M200-H81:~/ishan$ gcc polyscanline1.cpp -lglut -lGLU -lGL -lm

Related

-fPIC error when linking static and dynamic libs with GCC

I have written a small code that I want to compile with a combination of static and dynamic libs. The code uses functions from hdf5 and exodusII (a specialist CAE lib) as well as math, and of course good-old stdio.
To make the binary highly portable, I wanted to link hdf5 and exodusII statically into the code, but leave math and libc as shared, so that the code is optimised on different platforms.
I cannot work out what the correct method is to compile something like this. I already have tried:
gcc -lm -lc -fPIC test1.c /usr/lib/libexodus.a /usr/lib/libhdf5.a -Wl,-pie
This gives the error:
/usr/lib64/crt1.o: relocation R_X86_64_32S against '__libc_csu_fini' can not be used when making a shared object; recompile with -fPIC
/usr/lib64/crt1.o: could not read symbols: Bad value
I have also tried:
gcc -c test1.c (WORKS!)
ld /usr/lib/libhdf5.a /usr/lib/libexodus.a -lm -lc test1.o
Which gives a warning of not being able to find an entry symbol _start followed by a whole lot of undefined reference errors to the libexodus functions in test1.c. (I have checked libexodus.a with nm, and the functions being reported do actually exist in the archive.
I would really appreciate a hand in this. I am not overly experienced in using static libs, but for this application, I think it is the best choice, so long as I can work out a reliable way of compiling and linking.
The error was in the linking order. I have now learned that the linking order works like babushka dolls where the library at the top of the dependency tree comes first, and the most general library comes last.
For future reference, in the end, the working build command was as follows:
gcc test1.c -lexodus -lnetcdf -lhdf5_hl -hdf5 -lcurl -ldl -lm
What I don't really understand is that when I had built the exodus library as a shared library, I only had to link against the shared library, and the dependency libraries (-lnetcdf -lhdf5_hl -lhdf5 -lcurl) were not specified; however, with the static compilation of the exact same library, I now need to link all the libraries explicitly.
If someone has an answer to this behaviour, it would be helpful for my understanding and very appreciated, but as I can continue coding with this current build method, it is not an urgent matter.

OSX: How do I convert a static library to a dynamic one?

Suppose I have a third party library called somelib.a on a Mac running Mountain Lion with Xcode 4.4 installed. I want to get a dynamic library out of it called somelib.dylib. An appropriate Linux command would be:
g++ -fpic -shared -Wl,-whole-archive somelib.a -Wl,-no-whole-archive -o somelib.so
where -whole-archive and -no-whole-archive are passed to the linker.
When I do the equivalent for Mac:
g++ -fpic -shared -Wl,-whole-archive somelib.a -Wl,-no-whole-archive -o somelib.dylib
ld fails with an error:
ld: unknown option: -whole-archive
It seems that the ld on OSX is different from GNU ld. How do I have to modify above command so I will get the desired result?
Thank you in advance!
I found out the solution to my problem:
g++ -fpic -shared -Wl,-force_load somelib.a -o somelib.dylib
The required argument is -force_load:
Which needs to be followed by a single library you wanna ensure gets loaded.
I mean, it needs to be repeated for each library (unlike -noall_load approach, which wrapped them).
For example, -Wl,-force_load libYetAnotherFile.a (where -Wl, part is only required because we don't pass parameter directly to linker).
Note that Old answer (before edit) was using -noall_load instead, but nowadays that causes a linker error (as -noall_load has been removed, was obsolete previously).
Note: A link for the documentation of the OSX ld linker.
http://www.unix.com/man-page/osx/1/ld/
I know it is late to give an answer for this, but I do not have enough reputation to make a comment on #hanslovsky answer.
However, it helps me a lot to have the docs of the options too.
It helps what the options do exactly, and that other options the ld linker also has.
So I just wanted to share with others who finds linking an issue.
UPDATE:
After the comment from #GhostCat I have decided to expand my answer.
The docs for -all_load is:
-all_load
Loads all members of static archive libraries.
So it loads for all static libraries that you note.
If you want something similar to --whole-archive and --no-whole-archive, then you need to use -force_load and -noall_load.
-force_load "path_to_archive"
Loads all members of the specified static archive library. Note: -
all_load forces all members of all archives to be loaded.
This option allows you to target a specific archive.
-noall_load
This is the default. This option is obsolete.
Then you can define which libraries to fully load with -force_load and then later turn it off again with -noall_load.
According to the ld manual, -noall_load is the default and is ignored. (If you use it, you get an error message: ld: warning: option -noall_load is obsolete and being ignored)
Apparently the way to get -all_load to apply to only one library is as follows:
-Wl,-force_load,somelib.a

gcc/g++ parameter order

i just compiled chironfs on my new ubuntu 12.10 server and got the following error:
gcc -Wall -W -Wmissing-prototypes -g -O2 -DFUSE_USE_VERSION=25 -D_FILE_OFFSET_BITS=64 -I/usr/local/include -g -O2 -lm -lfuse -o chironfs chironfs.o chiron-conf.o chirondbg.o chironfn.o
chironfs.o: In function `chiron_init':
/root/chironfs-1.1.1/src/chironfs.c:2000: undefined reference to `pthread_create'
chironfs.o: In function `get_rights_by_name':
/root/chironfs-1.1.1/src/chironfs.c:452: undefined reference to `fuse_get_context'
the pthread error tells me that -lpthread is missing, but the fuse error is kinda weird cause -lfuse is being used
i found a solution here which suggests to put libraries after object files
so i removed -lfuse and added -lfuse -lpthread at the very end of the line
now it compiles without an error and it seems that this is the way it should be: library after object files
my question is:
why is the parameter order relevant for gcc/ld? i tought gcc just parses the params like every other application and may forward the necessary params to ld or such
in general: anyone knows facts or tips for gcc parameter ordering and maybe a bit background
information about why it is needed this way?
thanks
The order of objects and libraries is relevant to the linker (called implicitly by the compiler when creating an executable). When the linker, in its left-to-right scan, finds a use of a name it doesn't know about it starts looking for a definition from that point on. If a definition passes by, it doesn't remember it for later use.
GCC itself passes parameters to ld in relatively transparent fashion
Your question really is about how ld linker works. For simplicity and to handle circular references without infinite loops, it passes through the list of libraries only once, resolving references. So if your reference occurs somewhere and it hasn't seen the library that contains it yet then it's just an error.
Also please read this discussion, where this question is discussed in greater details.

Order of objects in a static library

I have a C project using several object files that needs to be linked in a specific order to find all needed symbols.
For example this command works fine (lib2.o depends on lib1.o etc.)
gcc -o my_app main.o lib1.o lib2.o lib3.o -lm
but
gcc -o my_app main.o lib3.o lib2.o lib1.o -lm
ends with undefined reference to `my_variable' errors.
This is a known behavior and can be solved for example by adding these objects to GROUP section in a linker script.
Now I'd like to share these object as a static library with my colleagues. So...
ar -rcs mylib.a lib1.o lib2.o lib3.o
gcc -o my_app main.o mylib.a -lm
Unfortunately this gives the same undefined reference errors like the specifying the objects in incorrect order.
I have not found any linker or archiver options to make it working and also no solution by googling even if I think that this problem should be relatively common.
Do please anybody know a solution?
regards
Jan
This might be a link order problem. When the GNU linker sees a library, it discards all symbols that it doesn't need. It also does that in the sequential order form left to right.
Recent versions of gcc/ld default to linking with --as-needed flag.
This means if you write -lmylib.a before the C file the library will automatically get excluded (the order matters when testing if things are "needed" like this)
You can fix this with either:
gcc -L. -o example example.c -lmylib.a
gcc -L. -Wl,--no-as-needed -o example example.c -lmylib.a
The latter of which passes --no-as-needed to the linker, which would cause the library to still be linked, even if you didn't call any function external from it.
Your error implies that the problem is in one of your lib?.o files [lib{later}.o depends on lib{earlier}.o]
How did you manage to compile them?
Were there any compilation warnings?
It has been a while since I used C, but I think that you will need to include dependent libraries within the library that has the dependency - this may be the reason why you can't find too many references to the problem, because it does not really exist.

GCC - Linking is unsuccessful

and sorry for my not really good english. I'll try my best :)
I am trying to compile a addin for my Casio graphic calculator in C. This works without problems when using the official SDK. Because it is only available for Windows, I want to use gcc.
So I got sh-rtems-gcc and it's binutils from macports and tried to compile my program according to this instructions. I copy-pasted the described addin.ld and crt0.s and placed my main.c and libfxsys.a (from the same guys as the instructions mentioned above) in the same directory. The sub-dir include contains fxsys' headers. I verified the presence of all the functions of the library in the .a file with nm.
When using this command for compilation:
sh-rtems-gcc-4.2.3 -m3 -mb -nostdlib -I./include -c crt0.s main.c
Everything works fine. But then im trying to link:
sh-rtems-gcc-4.2.3 -m3 -mb -nostdlib -L. -o myaddin.elf -Taddin.ld crt0.o main.o -lfxsys
and get the following error:
main.o: In function `__main':
main.c:(.text+0x248): undefined reference to `_Bdisp_AllClr_VRAM'
...
... (--- cut 16 other errors in the same format ---)
...
main.c:(.text+0x360): undefined reference to `_Sleep'
./libfxsys.a(locate.o): In function `_locate':
locate.c:(.text+0x28): undefined reference to `_locate_OS'
collect2: ld gab 1 als Ende-Status zurück
All the missing symbols are in the libfxsys.a. I have verified this with nm.
I have already played with the positions of the library in the command, as this is often mentioned as a source of failure in other posts found in google, but without success. I also tried adding and removing the -lgcc option that is used in the above mentioned instructions, without success.
My Host-Machine is a Intel Mac, OS X 10.6
Because I have no idea how to solve this problem, and get to compile my program, I have to ask: What am I doing wrong? How can I compile my program without using the SDK?
Thanks in advance,
xythobuz
Edit:
I have also tried linking with:
sh-rtems-ld -EB -L. -o myaddin.elf -Taddin.ld crt0.o --start-group main.o libfxsys.a --end-group
But it produces the same output as above.
I can't say the exact problem, but would investigate like this:
Find the library that contains the missing symbols. Use nm to see symbol names
Once you know which library contains the symbols make sure you're linking to it, and in the correct order. Try using recursive symbol resolution options -( -) with your linker.

Resources