I don't get it. I usually install third party software into /usr/local so libraries are installed into /usr/local/lib and never had problems linking to these libraries. But now it suddenly no longer works:
$ gcc -lkaytils -o test test.c
/usr/bin/ld.gold.real: error: cannot find -lkaytils
/usr/bin/ld.gold.real: /tmp/ccXwCkYk.o: in function main:test.c(.text+0x15):
error: undefined reference to 'strCreate'
collect2: ld returned 1 exit status
When I add the parameter -L/usr/local/lib than it works but I never had to use this before. Header files in /usr/local/include are found without adding -I/usr/local/include.
I'm using Debian GNU/Linux 6 (Squeeze) which has an entry for /usr/local/lib in /etc/ld.so.conf.d/libc.conf by default and the ldconfig cache knows the library I'm trying to use:
k#vincent:~$ ldconfig -p | grep kaytils
libkaytils.so.0 (libc6,x86-64) => /usr/local/lib/libkaytils.so.0
libkaytils.so (libc6,x86-64) => /usr/local/lib/libkaytils.so
So what the heck is going on here? Where can I check which library paths are searched by gcc by default? Maybe something is wrong there.
gcc -print-search-dirs will tell you what path the compiler checks. /usr/local/lib is simply not among them, so your compile time linker (in this case the new gold ld from binutils) doesn't find the library while the dynamic one (ld-linux.so which reads the cache written by ldconfig) does. Presumably the builds you've done previously added -L/usr/local/lib as necessary in their makefiles (usually done by a ./configure script), or you installed binaries.
This is probably an issue of environment variables - you have something set that's including /usr/local/include but not /usr/local/lib
From the GCC mapage on environment variables
CPATH specifies a list of directories to be searched as if speci‐
fied with -I, but after any paths given with -I options on the com‐
mand line. This environment variable is used regardless of which
language is being preprocessed.
and
The value of LIBRARY_PATH is a colon-separated list of directories,
much like PATH. When configured as a native compiler, GCC tries
the directories thus specified when searching for special linker
files, if it can’t find them using GCC_EXEC_PREFIX. Linking using
GCC also uses these directories when searching for ordinary
libraries for the -l option (but directories specified with -L come
first).
try "printenv" to see what you have set
Related
I've read this question: ld cannot find shared library even with -L specified, but I'm asking a follow-up: why does GCC do this?
This is something I ran into while building a binary with links to two in-house libraries.
gcc cannot find the symbols from one of the libraries with -l, but uses the other one just fine!
Originally, the command from my Makefile was gcc baz.o qux.o -lfoo -lbar, with the linker unable to find the symbols from libfoo, while finding the symbols from -lbar. The libraries are the exact same type of file in the same locations: headers in /usr/local/include and libraries in /usr/local/lib. In fact, libfoo depends on libbar.
Corrected, the command is now gcc baz.o qux.o -lbar /usr/local/lib/libfoo.so. I have determined this is not an ordering issue.
Why does gcc need the shared object instead of an -l? Is there a better way to do this, other than using the absolute path? This solution seems kludgy to me.
The exact code and output I'm using are as follows:
Output from using -lsandbox
The content of libsandbox.h
The Makefile I'm referencing, annotated.
Thanks!
I'm using OSX command line gcc and attempting to build a dynamic library. when I do the build I get the following warning. How is it it is not finding this library given /usr/lib is well known? And /usr/lib does indeed exist on my machine
this is what I am using:
gcc -arch i386 cata/*.c -dynamiclib -o build/cata.dylib -LC_ID_DYLIB=/usr/lib
Thanks
the way i solved it was to make it so the string that got stuck in the library (on where to find the library at runtime) was relative to nowhere -- if that makes sense. so it would be forced to use the LD_LOAD_PATH.
I was using the other flags because someone suggested I use them.
so the gcc i ended up using is this:
# my tree is like this
# cata/*.c
# build/*.dylib
#
cd build
gcc -arch i386 ../cata/*.c -dynamiclib -o cata.dylib
Doing this compiles/makes a library in the same directory where it thinks it is 'used' (basically having no path). I am now free to put it somewhere else. When it is later linked at compile time by a different program and then examined using
otool -L
it appears with no path in front of the library name. This is apparently preferable as now when the system goes to try to find it it resorts to looking at the standard libraries and eventually finds it (because I install it to one of the standard locations).
In the original way, otool -L was showing it having a required path of
'build/cata.dylib'
This made it un-findable and which is why i was trying to use the apple documentation to get around the problem.
This doesn't really solve why LC_ID_DYLIB doesn't work. I looked into the Loader.h file (line 643) and it has room for an identifier(0xd), a path, and a structure, so I don't really understand why my path wasn't getting picked up. but its two different topics. Loader.h is runtime and the other is gcc AFAIK. I'm still learning apple.
I set up this toolchain on my Windows machine for my Pi (raspberry-gcc4.6.3-nosysroot.exe) and then I followed the instructions here to synchronize my sysroot.
I use a library called WiringPi in my project, and I have confirmed that it is in the synchronized sysroot:
Then I attempt to compile it:
arm-linux-gnueabihf-gcc -Wall -O -c main.c
But I get the following error:
fatal error: wiringPi.h: No such file or directory
What do I have to do to make the compiler find the header file? I thought the whole point of synchronizing the sysroot was to make this kind of thing work?
You'll have to let gcc know where to look for the include files via the -I argument. In the case above, -IC:\SysGCC\Raspberry\...\usr\local. You may have to add more than one include path, depending on where the required files are scattered. You can also try to set gcc's environment variable(s).
Finding out the correct include path can be a little tedious (see above: should it be local\ or local\include\?). Maybe you can find the environment setting for all default include paths on your Pi and just copy it over to your Windows machine.
Edit: Think I got it: echo | gcc -v -E -
I have a makefile in Mac OS X and the last command line for the final compilation is:
gcc count_words.o lexer.o -lfl -o count_words
but it responds:
ld: library not found for -lfl
collect2: ld returned 1 exit status
I found that the library libfl.a is in /opt/local/lib/ and that modifying the command line to read:
gcc count_words.o lexer.o -L/opt/local/lib/ -lfl -o count_words
it works perfectly, but I've read when a prerequisite of the form -l is seen, GNU make searches for a file of the form libNAME.so; if no match is found, it then searches for libNAME.a. Here make should find /opt/local/lib/libfl.a and proceed with the final action, linking, but this is not happening.
I tried using LD_LIBRARY_PATH, then realized that as I'm working on Mac I have to use DYLD_LIBRARY_PATH, I exported the variable pointing to /opt/local/lib and tried running the makefile again, didn't work. Found another environment variable called DYLD_FALLBACK_LIBRARY_PATH, exported, didn't work.
What should I do?
DYLD_LIBRARY_PATH (and LD_LIBRARY_PATH on other unices) provides search paths for the loader, to resolve linked libraries at runtime. LIBRARY_PATH is the relevant var for providing paths that the compiler will pass to the linker at link time.
However, OS X's linker ld64 has no way to prefer static linking over dynamic in the presence of both kinds of libraries, which means your only option is to pass the full path to the archive anyway.
gcc count_words.o lexer.o /opt/local/lib/libfl.a -o count_words
Which is really all that -l does after it searches the paths and expands the lib name.
make does not search for the library at all. make just invokes other tools that do that. (ld, which is invoked by gcc) All you need to do is pass the proper flags to gcc from make. Possibly, this just means adding
LDFLAGS=-L/opt/local/lib
to your Makefile (or editing the command directly, as it appears you have done during testing), but it is difficult to tell without seeing the Makefile.
Probably this question Library not found for -lfl is relevant. For some reason if you try -ll instead of -lfl it works on OS X. Also see http://linux-digest.blogspot.hk/2013/01/using-flex-on-os-x.html
With gcc in ubuntu I used this command to compile my source code:
gcc 1.c -L. -lagent -lm -lpthread -o 1
but I got this error:
/usr/bin/ld: skipping incompatible ./libagent.so when searching for -lagent
/usr/bin/ld: cannot find -lagent
collect2: ld returned 1 exit status
How can I solve this?
The linker is telling you that the file ./libagent.so exists, but isn't in the appropriate format.
It could be an empty file, or built for 32-bit instead of 64-bit, or it could be a symlink pointing to the wrong version.
Let's look at your command line parameters first.
gcc 1.c -L. -lagent -lm -lpthread -o 1
You call the compiler gcc with the input source code of 1.c and then you specify an additional (link) library path to include the current directory (.) -L.. Then you tell it to link against the agent and pthread libraries, where shared (dynamic) libraries have the default name format of libNAME.so where NAME is replaced with the name. Static libraries have the default file extension .a (from the term archive). Then you specify the output (executable in this case) to be the file 1 (digit one, not the letter 'ell').
/usr/bin/ld: skipping incompatible ./libagent.so when searching for -lagent
This is the linker (ld) telling you that the file ./libagent.so (it found presumably in the current directory) is not a valid shared library format as it was expecting. This could be for a different machine architecture (x86-64, ARMle, PowerPC, MIPS) or a incompatible library format (I don't know if library files, .so, have any COFF or ELF or PE dependencies or not). Or simply otherwise empty or corrupted (e.g. interrupted output due to errors compiling / linking).
So you normally want to not include your current directory in your linker's search path, unless you have the copy of the library that you have not yet installed (typically to /usr/lib/ or /usr/local/lib/), such as you wrote the library and wish to link test programs to it before you install it.
Debian and Unbuntu-oriented part of the answer:
Normally you want to install shared library's runtime component (often named something like libagent) and the associated development files (most often at least a header file and hopefully a manpage) in the format libagent-dev. RPM based Linux systems use libagent-devel style naming conventions (from memory). So sudo aptitude install libagent-dev should do the trick if that is the package's name.