During a cross-compilation I got this linker error:
/home/tech/opt/gcc-4.7-linaro-rpi-gnueabihf/bin/../lib/gcc/arm-linux-gnueabihf/4.7.2/../../../../arm-linux-gnueabihf/bin/ld: cannot find -lfontconfig
This is the g++ command line:
/home/tech/opt/gcc-4.7-linaro-rpi-gnueabihf/bin/arm-linux-gnueabihf-g++ -Wl,-rpath-link,/mnt/rasp-pi-rootfs/opt/vc/lib -Wl,-rpath-link,/mnt/rasp-pi-rootfs/usr/lib/arm-linux-gnueabihf -Wl,-rpath-link,/mnt/rasp-pi-rootfs/lib/arm-linux-gnueabihf -mfloat-abi=hard --sysroot=/mnt/rasp-pi-rootfs -Wl,-O1 -o fontconfig fontconfig.o --sysroot=/mnt/rasp-pi-rootfs -lpthread -L/mnt/rasp-pi-rootfs/usr/lib/arm-linux-gnueabihf/ -lfreetype -lfontconfig
And
ls /mnt/rasp-pi-rootfs/usr/lib/arm-linux-gnueabihf/libfontconfig*
/mnt/rasp-pi-rootfs/usr/lib/arm-linux-gnueabihf/libfontconfig.so.1
/mnt/rasp-pi-rootfs/usr/lib/arm-linux-gnueabihf/libfontconfig.so.1.8.0
I don't understand "why" the linker cannot find that library.
What do you suggest to do in such a case to investigate further?
Linker requires import library with .a extension of the library for linker operations because it contains the signatures of classes and functions needed by the linker for linking while .so libraries are shared objects used at runtime.
You need to find the directory where you have libfontconfig.a (e.g.: through the command locate libfontconfig.a or 'find / -name libfontconfig.a') and then add it to the command line with -L/path/of/directory.
Related
I have an OpenGL program. I have all the include directories, and everything.
Directory Structure:
Main.cpp
Lib/
GL/
GLEW/
glm/
I compile the program by running:
g++ main.cpp -lGL -lm -lX11 -lpthread -lXi -lXrandr -ldl -I. -lglfw -Llib/ -o main -lGLEW
The error is on -lGLEW. The program compiles with no errors, but when I run ./main, it gives me this:
Error while loading shared libraries: libGLEW.so.2.2: No such file or directory.
This is confusing, as in my lib/ directory, libGLEW.so.2.2 is present, so is libGLEW.so and libGLEW.a.
Can someone please help me?
When running a dynamic linked executable, the linker must be able to find all the libraries it needs. It always searches
a list of fixed default paths like /lib and /usr/lib
additional paths defined by the environment variable LD_LIBRARY_PATH
any non-standard paths hard-coded in the binary by the -Wl,-rpath g++ option.
These are your options for making this non-standard library known to the runtime linker.
So either use export LD_LIBRARY_PATH=<somepath>/lib when running or use -Wl,-rpath=<somepath>/lib (with comma and without spaces) when building.
I have study makefile projec. I am using the gnu gcc and as linker, I use the gcc with the following argument:
linkerCmdLine=$(exe) -Wl,--start-group -nostdlib -Map=test_mapfile.map -l:libc.a -l:libgcc.a -l:libm.a -Wl,--end-group -o $(output)
During the linking process, the linker does not use all of this flags:
The flag -Map=test_mapfile.map is not used.
Why??
There is a project settings file and in this one is also stored the linker settings.
\u201ClinkerCmdLine\=$(exe) -Wl, --start-group -nostdlib -Map\=./99_output/PUZ_GPF.map --gc-sections -l\:libc.a -l\:libgcc.a -l\:libm.a -Wl,--end-group -o $(output)\u201D
How must I store the settings correct?
Edited:
With the the map file works fine, but I have actually problem with the linker file. I use only the following flag:
"linkerCmdLine=$(exe) -Wl, --script=C:/workspace/test_project/test_linker_file.ld -static -o $(output)”
I get this error in the console window:
arm-none-eabi-gcc.exe: error: unrecognized command line option '--script=C:/workspace/test_project/test_linker_file.ld'
I don't understand why, because the map file and the .ld file belong to the linker flags.
The -Wl, prefix only passes the current argument, with commas separating linker arguments. So in order to pass -z defs, you would use -Wl,-z,defs.
This mechanism only works for true flags, i.e. when the position in the command line is irrelevant. The -l parameters are not flags, and the gcc compiler driver collects them into a separate list and passes them in a single block.
So this technique doesn't work for the exact commandline you want. On the other hand, the -nostdlib inhibits the -lc -lgcc -lm that would be the default.
Normally there is a provision in the gcc specs (the script for the compiler driver) to use --start-group and --end-group around the standard libraries when linking statically (which appears to be what you want to do).
So I think that
linkerCmdLine=$(exe) -Wl,-Map=test_mapfile.map -static -o $(output)
should work for your case.
I'm trying to compile a sample LLVM program. The linker step uses this command.
llvm-config-3.2 --ldflags --libs
That results in the following command.
g++ -o bin/Debug/test-llvm obj/Debug/main.o -L/usr/lib/llvm-3.2/lib -lpthread -lffi -ldl -lm (a boat load of LLVM libraries here)
However, it fails to link. I get errors like this.
undefined reference to ffi_type_float
So, I added -lffi and -ldl to the end.
g++ -o bin/Debug/test-llvm obj/Debug/main.o -L/usr/lib/llvm-3.2/lib -lpthread -lffi -ldl -lm (a boat load of LLVM libraries here) -lffi -ldl
So, yes, they show up TWICE in the command... but it works this way. Why? They are clearly referenced earlier in the arguments.
One or more of the libraries appearing on the command line after -lffi and -ldl refer to symbol(s) defined in one of those libraries. But the linker has already finished scanning libffi and libdl and does not rescan them for these symbols. This circular dependency can be resolved by forcing the linker to scan those libraries again by re-listing their names at the end of the list.
A more scalable solution is to use --start-group archives --end-group option to list the libraries to link to. Quoting from the man page:
-( archives -)
--start-group archives --end-group
The archives should be a list of archive files. They may be either explicit file names, or -l options.
The specified archives are searched repeatedly until no new undefined references are created. Normally, an archive is searched
only once in the order that it is specified on the command line. If a
symbol in that archive is needed to resolve an undefined symbol
referred to by an object in an archive that appears later on the
command line, the linker would not be able to resolve that reference.
By grouping the archives, they all be searched repeatedly until all
possible references are resolved.
Using this option has a significant performance cost. It is best to use it only when there are unavoidable circular references between
two or more archives.
So your command line would look like this:
g++ -o bin/Debug/test-llvm obj/Debug/main.o -L/usr/lib/llvm-3.2/lib --start-group -lpthread -lffi -ldl -lm ... --end-group
Ah, I found the solution. Swapping the flags didn't actually change the order. I had to break it out into two separate calls.
llvm-config-3.2 --libs
llvm-config-3.2 --ldflags
And yeah, this is technically answered in that other question: Why does the order in which libraries are linked sometimes cause errors in GCC?
I still just think this question is relevant because doing what the docs told me to do led me into danger. :(
Why do I have to link these libraries twice
Because the order of archive libraries on command line matters, and yours is wrong.
I installed these two libraries: glut and curl.
sudo apt-get install libcurl4-gnutls-dev
sudo apt-get install freeglut3-dev
when I have to compile a program I use:
g++ -o executable file11.cpp file2.cpp -lglut -lcurl
and it works!
How can I know where the linker search for "-lglut" or "-lcurl"?
"-lsomething" correspond to a path, How can I find out?
It checks /lib, /usr/lib, and any paths passed to -L.
The linker will look in directories specified by the -L option and in standard system directories, which are usually /lib and /usr/lib. Although you're not using any -L options GCC will usually pass some to the linker so it can find GCC's own libraries (e.g. the C++ standard library) unless you use -nostdlib. GCC will also add -L options for the contents of the LIBRARY_PATH environment variable.
To see the options GCC passes to the linker you can compile with -v (for verbose) and to see which libraries the linker uses you can pass -Wl,--trace to GCC, which causes it to pass --trace to the linker, which makes it output something like:
/usr/bin/ld: mode elf_x86_64
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crt1.o
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crti.o
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/crtbegin.o
/tmp/ccJHrbSx.o
-lglut (/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/libglut.so)
-lcurl (/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/libcurl.so)
-lgcc_s (/usr/lib/gcc/x86_64-redhat-linux/4.7.2/libgcc_s.so)
/lib64/libc.so.6
(/usr/lib64/libc_nonshared.a)elf-init.oS
/lib64/ld-linux-x86-64.so.2
-lgcc_s (/usr/lib/gcc/x86_64-redhat-linux/4.7.2/libgcc_s.so)
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/crtend.o
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/crtn.o
This shows the libraries that were found for the -lglut and lcurl libs on my system. The libs are found in that path because on my system GCC passed -L/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64 to the linker (shown by compiling with -v)
You can canonicalize those paths using readlink
$ readlink -f /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib64/
/usr/lib64/
http://gcc.gnu.org/onlinedocs/gcc/Link-Options.html
It just turns the string into a filename, and checks normal locations for it, it seems.
Try
ldd /path/to/your/executable
I'm trying to link to a static library, libcovis.a. Everything looks fine but I still have
undefined reference to `CoViG_PublicDemo::MoInS::reset()'
I checked that the name exists in the library
$nm libcovis.a | grep reset
...
_ZN16CoViG_PublicDemo5MoInS5resetEv
...
I'm using linking arguments -L/path/to/libcovis.a -lcovis
What am I doing wrong ?
Edit:
The error might be something else, if do
gcc main.cpp -I/usr/include/opencv -I/usr/include/cairo -I../../Source -o slam -rdynamic -lGLU -lGL -lSM -lICE -lX11 -lXext -lglut -lXi -lxml2 -lboost_filesystem-mt -llapack -lblas -lcv -lcxcore -lcvaux -lhighgui -lcairo ../../Source/libcovis.a ../../Source/contrib/gnuplot_i/libcovis_contrib_gnuplot_i.a -lgl2ps
It works !
But when I'm in KDevelop using cmake, I doesn't work anymore. I use
CMAKE_EXE_LINKER_FLAGS:STRING=-rdynamic -lGLU -lGL -lSM -lICE -lX11 -lXext -lglut -lXi -lxml2 -lboost_filesystem-mt -llapack -lblas -lcv -lcxcore -lcvaux -lhighgui -lcairo /usr/local/src/CoViS-0.0.0-1/Source/libcovis.a /usr/local/src/CoViS-0.0.0-1/Source/contrib/gnuplot_i/libcovis_contrib_gnuplot_i.a -lgl2ps
CMAKE_CXX_FLAGS:STRING=-I/usr/local/src/CoViS-0.0.0-1/Source -I/usr/include/opencv -I/usr/include/cairo
The only difference I can see is that the paths are absolute and not relative, but if he couldn't find the libs, he would say it...
There are two different issues there, the first of which is the simplest, you have used the wrong compiler options. The -L option tells the linker to also look in the directory when looking for a library. The -l tells it to link the specific library. To link you would then use:
g++ -o test test.o -L/path/to -lcovis
or
g++ -o test test.o -l/path/to/libcovis.a
To force static linking if the same library is present as a dynamic library in the same directory.
The second potential issue is that the order of static libraries in the linker command line does matter, so that might also be an issue if there is a dependency on different static libs.
g++ -o test tests.o -ldependent -lprovider
The linker will process the libraries in order as they are in the command line, and from each static lib it will only pull those symbols that are required (with as much information as the linker has at that time). In the command line above, the linker will extract from dependent the symbols it needs for test.o, and that might in turn add new undefined symbols to the program (the dependencies of dependent). When it processes provider it will fill in those symbols. If the order was reversed in the command line, the symbols that are required by dependent but not by test.o would not be added to the executable, as the linker does not know that those symbols will be needed when processing provider.
Should the arguments be like -L/path/to/ -lcovis?
Besides, object files should be placed before libs, for example
g++ obj1.o obj2.o -L/path/to/ -lcovis.
If you see the link succeeding in one context but not another, I suspect the problem may be caused by the order in which the link operation is executed as the linker will discard symbols in a library if they're not needed at the point in which the library is referenced.
Here is a link explaining: http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html
I've run into similar situations in the past the linking order was found to be the cause of the problem.