Linking to so library in gcc - gcc

I will start by saying that I am new to gcc and makefiles. I have a .so file on the desktop (~/Desktop) called lib.so. I want to link my program (called myProgram) to it. What I wrote in my makefile is:
g++ myProgram.o -L ~/Desktop -l lib -o myProgram
When I run make I get an error:
/usr/bin/ld: cannot find -llib
I also tried -l lib.so and got the same error.
What is the correct way to link?

Two solutions:
Rename the file to libsomething.so, then use -l something. The linker automatically wraps the name with lib prefix and .so suffix (or .a suffix for static libraries).
Use the option -l :lib.so. When you prefix the name with :, the linker uses the name as given.
These are explained in the ld man page.

Related

GCC keeps on showing "/usr/bin/ld: cannot find" even when -L path is specified

I am trying to compile main.c with a static library and header files on an Ubuntu server using gcc and ssh using Terminal on Mac. I uploaded the library file and specified it with -L option and specified the header files using the -I option.
I tried using:
gcc main.c -L/Libraries/lib/libRNA.a -lRNA -ILibraries/include/ViennaRNA
It comes out with:
/usr/bin/ld: cannot find -lRNA
collect2: error: ld returned 1 exit status
-L expects a directory as argument. You're passing the name of the library.
Just do:
gcc main.c -L/Libraries/lib -lRNA -ILibraries/include/ViennaRNA
or link with the absolute path of the .a file directly:
gcc main.c /Libraries/lib/libRNA.a -ILibraries/include/ViennaRNA
The -L option specifies a directory where the library file is.
The -L option to gcc (which gets actually passed to ld) is expecting a directory (in which further -l options are seeked).
The -I option is expecting a directory containing included header files.
So you want
gcc -Wall -g main.c -L/Libraries/lib/ -lRNA -ILibraries/include/ViennaRNA
You really want all warnings (-Wall) and debug information (-g) to be able to use the gdb debugger.

GCC linked static library failed

I tried to use gcc command to link a static library, but it didn't work.
If you want to use the -l flag command to link your application like so:
gcc t.c -L. -lt1.a -o t
Then your .a archive needs to have a filename of libt1.a not just t1.a.
When using -lsome_name to link in a library, the linker will look for a file named libsomename.so or libsomename.a
If you do not want to rename your .a archive, you can also just do
gcc t.c t1.a -o t
also, in the future please don't post an image of your code or commands, just copy paste it as text into your post
Libraries in POSIX environments (like Linux and OSX) are usually named in the pattern lib<name of library>.a. When you link with the library you either use the -l option and only use <name of library> and the linker will automatically add the lib prefix and .a suffix. Or you don't use the -l option and istead give the whole file-name verbatime.
Since you don't use the standard naming scheme for the libraries, you can't use the -l option and instead have to explicitly use the library file, similar to
$ gcc ... t1.a
If you want to use the -l option you have to name your library libt1.a and only use t1 when linking:
$ gcc ... -L. -lt1

Force solib dependency to have relative path of non-standard named shared library under a directory using gcc

I have an issue regarding the linking of a shared library with a non-standard naming convention under several directories. I need the generated executable to search for the shared library within the executables current location, but cannot find a command line parameter to force this behavior.
To demonstrate this behavior all that is required is a shared library that is under a directory.
gcc -shared mylib.c -o some/dir/mylib.so
gcc main.c -o main -Lsome/dir -l:mylib.so
The executable main gives the following ldd output:
ldd main
some/dir/mylib.so (0xf76e2000)
The output that I require is:
ldd main
mylib.so => some/dir/mylib.so (0xf7700000)
This output can be created if the library is named conventionally as libmylib.so rather than mylib.so like so:
mv some/dir/mylib.so some/dir/libmylib.so
gcc main.c -o main -Lsome/dir -lmylib
This also drops the path some/dir in the ldd listing as required.
I have investigated the use of rpath, and command line options for both the ld and gcc but I am unable to find a satisfactory solution. The strict requirements of a non-standard name and directory structure cannot be changed easily in this case.
My question is how can I force the dependency of the library to be relative to the current directory rather than absolute as in the second ldd through gcc command line options.
Thank you for your time, I hope I have explained the problem reasonably.
Jon.
Try to add soname in your shared library:
$ gcc -shared mylib.c -o some/dir/mylib.so -Wl,-soname=mylib.so
$ gcc main.c -o main -Lsome/dir -l:mylib.so
$ LD_LIBRARY_PATH=some/dir:$LD_LIBRARY_PATH ldd main
mylib.so => some/dir/mylib.so (0x00007fa7a4fd6000)
There's a magic variable you can pass to rpath to do this: $ORIGIN. See man ld.so for details.
I think in your case, the command should look like this (untested):
gcc main.c -o main -Lsome/dir -lmylib -Wl,-rpath,'$ORIGIN/some/path'
Note that you mustn't let the shell expand $ORIGIN as a shell variable.
BTW, this was the first Google hit for "rpath relative".

Is it not allowed create a static library without a .c file in it?

I have two files -> fact.h and main.c in the /home/snyp1/new folder. main.c has the main function which calls the fact(int x) function in fact.h. I am creating a .a archive with the ar command ->
snyp1#Snyp:~/new$ ar -r -s libfact.a fact.o
ar: creating libfact.a
fact.h fact.o libfact.a main.c
snyp1#Snyp:~/new$ gcc main.c -L/home/snyp1/new -lfact -o main
/home/snyp1/new/libfact.a: could not read symbols: Archive has no index; run ranlib to add one
collect2: ld returned 1 exit status
snyp1#Snyp:~/new$ ranlib libfact.a
snyp1#Snyp:~/new$ gcc main.c -L/home/snyp1/new -lfact -o main
/home/snyp1/new/libfact.a: could not read symbols: Archive has no index; run ranlib to add one
collect2: ld returned 1 exit status
I am on ubuntu 12.04. Please let me know whats wrong. (Also, if I don't use the -L/.../new, gcc will say it can't find "lfact", maybe its because its not in /usr/local/lib)
EDIT: OK I have found the cause. Its due to the fact that I was using fact.h to build the fact.o and then putting it in the library, it wasn't working as expected. So I now changed it into file.c and is working fine now. I should have provided that information, I'm sorry. Though I don't know why this kind of problem should arise. Aren't libraries possible to make without at least one .c file in it?
I was using fact.h to build the fact.o and then putting it in the library, it wasn't working as expected.
Do you mean you were compiling fact.h to produce fact.o?
If so, that wasn't doing what you expect. When you invoke gcc on a header file it produces a precompiled header, not an object file. So although you got a file called foo.o it wasn't a valid object file. If you had just run gcc -c fact.h it would have produced a precompiled header fact.gch, but presumably you ran gcc -c fact.h -o fact.o which causes the file to be called fact.o even though it's still a precompiled header. file fact.o would have shown that:
$ file fact.o
fact.o: GCC precompiled header (version 013) for C
You could have forced GCC to treat the file as C code, not a header, by running gcc -x c -c fact.h -o fact.o (the -x c says to treat the input as C code instead of inferring the type from the file extension) but it's probably simpler and less confusing to just name your file correctly instead of trying to compile a header.
Aren't libraries possible to make without at least one .c file in it?
They need at least one object file (i.e. .o file) but you didn't have a valid object, you had a precompiled header misleadingly named as .o, but it was not actually an object file.
if I don't use the -L/.../new, gcc will say it can't find "lfact", maybe its because its not in /usr/local/lib
The linker doesn't only look in /usr/local/lib, there are other default places it looks, but yes, that's basically the problem. Note that you can also say -L. if the library is in the current directory, that's easier than giving an absolute path.
I'm not sure ar supports a dash on anything other than the first option. Try
ar -rs libfact.a fact.o
or just
ar rs libfact.a fact.o
Mind you, I don't know why running ranlib didn't work though.

How to link to a shared library without lib* prefix in a different directory? [duplicate]

This question already has answers here:
How to link using GCC without -l nor hardcoding path for a library that does not follow the libNAME.so naming convention?
(3 answers)
Closed 3 years ago.
I have to link my code to a shared library without the lib prefix. (say, foo.so) The first problem is -l option does not find the file. So I tried directly including this file to the last compilation like this:
gcc a a.o /PATH/TO/FOO/foo.so
But in this case, a is hard linked to foo.so as an absolute path as seen in "ldd a":
/PATH/TO/FOO/foo.so
In the final deployment both files would end up being in the same folder, so this should be normal link, not the absolute path. How can I do this?
Assuming an ELF platform, if you can rebuild foo.so:
- the best fix is to simply name it libfoo.so
- the next best fix is to set SONAME on it:
gcc -Wl,-soname,foo.so -o foo.so foo.o
when you later link with:
gcc -o a.out a.o /path/to/foo.so
only the SONAME will be recorded as a dependency, not a full /path/to/foo.so.
If you can't rebuild foo.so, then do this:
rm -f foo.so && ln -s /path/to/foo.so foo.so &&
gcc -o a.out a.o ./foo.so && rm -f foo.so
-Wl,-rpath,. --> to use current directory for searching lib files. (even if not found in compilation, ok at run-time)
instead of -llibrary --> use library.so.
This seems to work correctly. Hope anyone finds this useful.

Resources