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

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++.

Related

ld would not link the static library because of it consider the library is not needed, but I need this library [duplicate]

I have a program and a static library:
// main.cpp
int main() {}
// mylib.cpp
#include <iostream>
struct S {
S() { std::cout << "Hello World\n";}
};
S s;
I want to link the static library (libmylib.a) to the program object (main.o), although the latter does not use any symbol of the former directly.
The following commands do not seem to the job with g++ 4.7. They will run without any errors or warnings, but apparently libmylib.a will not be linked:
g++ -o program main.o -Wl,--no-as-needed /path/to/libmylib.a
or
g++ -o program main.o -L/path/to/ -Wl,--no-as-needed -lmylib
Do you have any better ideas?
Use --whole-archive linker option.
Libraries that come after it in the command line will not have unreferenced symbols discarded. You can resume normal linking behaviour by adding --no-whole-archive after these libraries.
In your example, the command will be:
g++ -o program main.o -Wl,--whole-archive /path/to/libmylib.a
In general, it will be:
g++ -o program main.o \
-Wl,--whole-archive -lmylib \
-Wl,--no-whole-archive -llib1 -llib2
The original suggestion was "close":
How to force gcc to link unreferenced, static C++ objects from a library
Try this: -Wl,--whole-archive -lyourlib
I like the other answers better, but here is another "solution".
Use the ar command to extract all the .o files from the archive.
cd mylib ; ar x /path/to/libmylib.a
Then add all those .o files to the linker command
g++ -o program main.o mylib/*.o
If there is a specific function in the static library that is stripped by the linker as unused, but you really need it (one common example is JNI_OnLoad() function), you can force the linker to keep it (and naturally, all code that is called from this function). Add -u JNI_OnLoad to your link command.

Undefined reference error but symbol existing in the library

I get an undefined reference error for the example below. I have seen lots of questions that relate to this issue but believe I gave a stripped, reproducible, conceptual example as opposed specific issues in other questions,
dynlib.h:
void printMe_dyn();
dynlib.c:
#include <stdio.h>
#include "dynlib.h"
void printMe_dyn() {
printf("I am execuded from a dynamic lib");
}
myapp.c:
#include <stdio.h>
#include "dynlib.h"
int main()
{
printMe_dyn();
return 0;
}
Build steps:
gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
gcc -Wall -L. -ldynlib myapp.c -o myapp
Error:
/tmp/ccwb6Fnv.o: In function `main':
myapp.c:(.text+0xa): undefined reference to `printMe_dyn'
collect2: error: ld returned 1 exit status
Proof that the symbol is in the library:
nm libdynlib.so | grep printMe_dyn
00000000000006e0 T printMe_dyn
Am I using the correct compiler flags for building the dynamic
library?
Is the proof I've presented really an unambiguous proof?
What other approach could be taken to diagnose the issue?
The order of appearance of libraries matter.
To quote the online gcc manual
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.
You should be changing your compilation statement to
gcc -o myapp -Wall -L. myapp.c -ldynlib
to tell gcc to search for the symbols used in (compiled) myapp.c to be present in dynlib.
Just as additional notice. The same behavior one may obtain when the library has been built by gcc and linked to the c++ project. Like follows:
gcc -Wall -fpic -c dynlib.c
gcc -shared -o libdynlib.so dynlib.o
g++ -o myapp -Wall -L. myapp.cpp -ldynlib
In such case the reason is name-mangling used by g++. To have it turned off one must wrap C-function prototypes by extern "C" within C-library. For example like follows:
dynlib.h:
#ifdef __cplusplus
extern "C"{
#endif
void printMe_dyn();
#ifdef __cplusplus
}
#endif
The order of libraries in linker command line matters. Fix:
gcc -o myapp -Wall -L. myapp.c -ldynlib

Static library cannot be found

Let me explain the context first. I have a header with a function declaration, a .c program with the body of the function, and the main program.
foo.h
#ifndef _FOO_H_
#define _FOO_H_
void foo();
#endif
foo.c
#include<stdio.h>
#include "include/foo.h"
void foo()
{
printf("Hello\n");
}
mainer.c
#include <stdio.h>
#include "include/foo.h"
int main()
{ foo();
return 0;
}
For the purpose of this program, both the header and the static library need to be in separate folders, so the header is on /include/foo.h and the static library generated will be on /lib/libfoo.a, and both .c programs on the main directory. The idea is to generate the object program, then the static library, then linking the static library to create the executable, and finally executing the program.
I have no problem in both creating the object program and the static library.
$ gcc -c foo.c -o foo.o
$ ar rcs lib/libfoo.a foo.o
But when I try to link the static library...
$ gcc -static mainer.c -L. -lfoo -o mainfoo
It gaves to me an error, claiming the static library can't be found
/usr/bin/ld: cannot find -lfoo
collect2: ld returned 1 exit status
It's strange, considering I asked before how to work with static libraries and headers on separate folders and in this case the static libraries were found. Any idea what I'm doing wrong?
Change -L. to -Llib as it looks like you create the .a file there.
Basically the linker is telling you that it cannot find the library foo. It normally searches in the default library directories + any you give it with the -L option. You're telling it to look in the current directory, but not in lib where libfoo.a is located, which is why it can't find it. You need to change -L. to -Llib.
I am not completely sure that I understand your directory structure, but maybe what you need is this:
gcc -static mainer.c -L./lib -lfoo -o mainfoo

erl_interface linker error

I need to use erl_interface in my C-program. There is Erlang R15B01 on Debian Wheezy.
I just do the following (for example).
// main.c
#include <ei.h>
#include <erl_interface.h>
int main() {
erl_init(NULL,0);
return 0;
}
Then i say:
cc -I/usr/lib/erlang/lib/erl_interface-3.7.7/include -L/usr/lib/erlang/lib/erl_interface-3.7.7/ -lei -lerl_interface -o prog main.c
Directory specified as -L contains libei.a and liberl_interface.a but linker abusing that reference to erl_init is undefined: undefined reference to erl_init
What may be wrong? Sorry for really stupid question.
Newest versions of the GNU toolchain require that the object files and libraries be specified in the same order their symbols depend on each other. So you should generally put the library flags to the end of the invocation, like this:
gcc -o prog main.c -L<libdir> -I<includedir> -lerl_interface -lei

Creating a simple shared library

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.

Resources