Creating a simple shared library - c

I am trying to learn the shared library concepts on linux using GCC. So I have created a simple library.
library.c
int foo(void) {
return 10;
}
This is compiled using,
cc -fPIC -g -c library.c
cc -shared -fPIC -Wl,-soname,libmytest.so.1 -o libmytest.so.1.0.1 library.o -lc
It created the file libmytest.so.1.0.1 in the current directory. Now I am writing a client to consume this library in the same directory.
client.c
#include <stdio.h>
extern int foo(void);
int main()
{
int a = foo();
printf("a is %d", a);
return 0;
}
compiling using,
cc client.c -o client -lmytest
but this exits with the message
/usr/bin/ld: cannot find -lmytest
collect2: ld returned 1 exit status
Can anyone help me to find out what I am doing wrong here?

Try using a -L option which is used to add a directory to the list of directories that are searched for the -l option:
cc client.c -L. -o client -lmytest
Assuming the .so is present in the same directory as client.c. If not add suitable path.
The linker on seeing -lmytest looks for libmytest.so but you have a version number appended to it so it does not work. Way to fix this is to create a symlink named libmytest.so pointing to libmytest.so.1.0.1
ln -s libmytest.so.1.0.1 libmytest.so
Alternatively you can use the complete library name on the compile/link line as:
cc client.c ./libmytest.so.1.0.1 -o client

You are missing the -Ldir option.
From the GCC manpage:
-Ldir Add directory dir to the list of directories to be searched for -l.
You'll also need to specify where the shared library is located if you try to run the executable, otherwise the library won't be found. This can be done with:
LD_LIBRARY_PATH=. ./client
Edit:
Thanks but no luck. still the same
error. I even tried with specifying
the full path, but not worked.
I think the linker needs the library to have a .so extension. Try ln -s libmytest.so.1.0.1 libmytest.so and see if it links.

The linker normally searches only the system paths for libraries. Pass -L to gcc in order to specify additional paths to search.

Related

Unable to link dynamic library in macOS

I'm trying to use a C library called quirc in my C project. So far, I have generated a libquirc.dylib.1.0 by modifying the Makefile which was using Linux .so files.
quirc/helloquirc.c
#include <quirc.h>
#include <stdio.h>
int main() {
struct quirc *qr;
qr = quirc_new();
if (!qr) {
printf("Failed to allocate memory");
}
quirc_destroy(qr);
return 0;
}
I've created the above source file at the root of the repository. I'm using the following command to compile it:
gcc helloquirc.c -lquirc -L. -Ilib -o helloquirc
To my understanding the -l flag specifies the name of the dynamic library, the -L flag specifies the location of the dynamic library, the -I flag specifies the location of the header files, and -o specifies the name of the executable.
When I run this command I get the following error:
ld: library not found for -lquirc
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I changed the Makefile by using this line
.PHONY: libquirc.dylib
libquirc.dylib: libquirc.$(LIB_VERSION).dylib
libquirc.$(LIB_VERSION).dylib: $(LIB_OBJ)
$(CC) -shared -dynamiclib -o $# $(LIB_OBJ) $(LDFLAGS) -lm
and changing other instances of .so.$(LIB_VERSION) to .$(LIB_VERSION).dylib
Something is wrong with the way quirc was built. The correct library name would be something like libquirc.1.0.dylib with a symlink named libquirc.dylib.
It looks like quirc has a handwritten makefile instead of using something sensible like gyp or cmake. Handwritten makefiles are just fine as long as you're not trying to build shared libraries on multiple platforms.
However, if you are just compiling it yourself, you may find things simpler if you just use a static library instead. There is no point in having a shared library if you are not sharing it with anybody (if no other programs are using the same exact copy of libquirc).

How to compile gcc with static library?

I have static library lib.a and in all tutorials using:
gcc -o main main.o -L. -lib
But I cant, I have errors:
/usr/bin/ld: cannot find -lib
collect2: error: ld returned 1 exit status
I need to use:
gcc -o main main.o -L. -lib.a
Why? What should I do to repair it ?
From the documentation of gcc -l:
-llibrary:
The linker searches a standard list of directories for the library, which is actually a file named liblibrary.a. The linker then uses this file as if it had been specified precisely by name.
...
The only difference between using an -l option and specifying a file name is that -l surrounds library with ‘lib’ and ‘.a’ and searches several directories.
So you cannot use -l with a library named 'lib.a'. Use 'lib.a' without the -l to include it. Of course, you cannot use -L then to set the directories to be searched for this particular library.
Do you have the error with this line ?
gcc -o main main.o -L. -llib
As MicroVirus found in the documentation, you will have to rename your library in liblib.a to use my previous line or just pass your library to gcc like a simple file.

gcc doesn't find header file in static library I made

I made a static library.
This not have error, library file too.
So, I tried use that library.
gcc -o hash_gen main.c -L../ -lhashbundle
Library file exist in that directory ../, library file name is libhashbundle.a.
So, I thought not have problem in this command.
but I tried compile with gcc, but gcc print this error.
main.c:4:10: fatal error: 'hash.h' file not found
#include "hash.h"
^
I don't understand. I made library make, and this is Makefile
all : libhashbundle.a
libhashbundle.a : hash.o
ar rscv libhashbundle.a hash.o
hash.o : src/hash.c
gcc -c src/hash.c
clean:
rm -rf hash.o
I thought this code many times, but I didn't found error.
and this is directory tree
tree
Makefile
libhashbundle.a
|src
|hash.c
|hash.h
|test
|main.c
So, I ask to you.
How could solve this problem?
You only specified a library search path (-L).
If you want a header search path, you need to use -I.
gcc -o hash_gen main.c -I.. -L.. -lhashbundle
The problem is the fact that you're running your build from your "root" directory, not from /src/. So when the compiler sees #include "hash.h" it will try to open the file in the current directory, which will be / rather than /src/ (where the files are).
To fix this, just add your source directory to the include search paths using -Isrc:
gcc -o hash_gen main.c -Isrc -lhashbundle
Note that I omitted -L since the library file is in your current working directory and should be found there anyway.

Fatal error: modbus.h: No such file or directory

I'm expecting a lot of difficulties to make my program working with the library libmodbus on Linux.
I've installed libmodbus with the command sudo make install and after make but the problem is when I want to link the library in my C program.
My Makefile for now is like:
all: test
test: main.o com.o
gcc main.o com.o -o test
main.o: main.c
gcc -c main.c -o main.o
com.o: com.c
gcc -c com.c -Wl,-rpath=/usr/local/lib -Wl,LIBDIR -o com.o
clean:
rm -rf *o test
In my file com.c I include the file modbus.h like this:
#include <modbus.h>
And I always get the error:
fatal error: modbus.h: No such file or directory.
If it can help when I did make install, the code return me this:
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the '-LLIBDIR'
flag during linking and do at least one of the following:
add LIBDIR to the `LD_LIBRARY_PATH' environment variable during execution
add LIBDIR to the `LD_RUN_PATH' environment variable during linking
use the `-Wl,-rpath -Wl,LIBDIR' linker flag
have your system administrator add LIBDIR to `/etc/ld.so.conf'
It seems like the modbus.h is not in the standard include directory.
You should to add the -I/<includes_path> flag to gcc options.
I suppose here:
gcc -I/<include_dir_path> -c com.c -Wl,-rpath=/usr/local/lib -Wl,LIBDIR -o com.o

Creating libraries in C/C++ - ld can't find my library

I'm trying to learn how to create a C/C++ library in a linux environment but I'm having a problem (probably a trivial one) that online tutorials had not helped to solve.
For definiteness let's say I have a foo.c file with the following code:
//file: foo.c
#include <stdio.h>
void hello(void)
{
printf("hello!\n");
}
a foo.h:
//file: foo.h
void hello(void);
and a program that uses the function hello() from foo.c, named prog.c:
//file: prog.c
#include "foo.h"
int main(void)
{
hello();
return 0;
}
The three files are all on the same directory. Then I compiled foo.c with:
gcc -fPIC -c foo.c
and got a foo.o file. Then I used ld to create the library file:
ld -G foo.o -o libfoo.so
But when I try to compile prog.c with:
gcc -o prog prog.c -lfoo
I got an error message:
/usr/bin/ld: cannot find -lfoo
collect2: ld returned 1 exit status
I'm convinced that this is some kind of trivial path problem, but I couldn't find the solution. So my question is really if this procedure above is wrong or if I have to put the libfoo.so file in a special path.
Another question is how this changes if I'm using g++ instead of gcc.
Thanks.
EDIT:
I know I can compile both prog.c and foo.c to prog.o and foo.o an then link them to make an executable. But in my original problem I want to compile foo.c in a way that I can distribute to people who will use my functions in their own programs.
ld doesn't search the current directory by default. If you want it to do this you need to use the -L command line option, so if your library is in the current directory you need to add -L. to the last gcc call. If the library is dynamically linked you also need to add the current directory to the environment variable LD_LIBRARY_PATH (I assume you're on linux).
Of course, if your library is in any other non-standard path you need to use that instead of the current directory.
Try
gcc -o prog prog.c -lfoo -L.
The -L switch adds its argument to the set of paths that ld looks in for library files. The syntax is identical for g++.

Resources