Create a static libary and link against it - c

Hello beautiful people,
i'm trying to create a static libary and to compile against it.
I've allready created a small static libary and a header for it.
Header (math.h):
int add (int a, int b);
int sub (int a, int b);
add.c:
int add (int a, int b) { return a + b; }
sub.c:
int sub (int a, int b) { return a - b; }
I've created my static libary with the following commands:
gcc -c add.c
gcc -c sub.c
ar rcs libmymath.a add.o sub.o
Now my main.c
#include <stdio.h>
#include "math.h"
int main( int argc, char **argv ) {
printf("Result : %d\n", add(5,7) );
return 0;
}
I can compile it with the following command:
gcc main.c libmymath.a -o main
But if i compile it the following way, it fails.
gcc main.c -lmymath -L. -o main
It fails with the following error:
/usr/bin/ld: cannot find -lmymath collect2:
error: ld returned 1 exit status
even a change to
gcc main.c -llibmymath -L. -o main
fails and even if i include the header mymath.h to gcc
Can you help me ?

gcc understood -lmymath by libmath.so or libmath.a already. So when you add lib word in -llibmymath. This case the gcc understood your library name being liblibmymath.a. So, please replace this command
gcc main.c -llibmymath -L. -o main
by
gcc main.c -o main -L. -lmymath
It should work.

Related

Compile time error while running multiple c files

#Edited
I am tested on simple two files now that are add.h and add.c.
I made a Makefile in order to compile my program. Here is my makefile.
# Make file for running the project
CC=gcc
CFLAGS= -Wall -g
LDFLAGS = -include
OBJFILES = add.o
LIB = add.h
TARGET = add
all: ${TARGET}
%.o: %.c
${CC} ${CFLAGS} -c -o $# $<
${TARGET}: ${OBJFILES}
${CC} ${CFLAGS} -o ${TARGET} ${OBJFILES}
clean:
rm -f $(OBJFILES) $(TARGET) *~
when I run
make add
I get the following error:
gcc -Wall -g -c -o add.o add.c
gcc -Wall -g -o add add.o
Undefined symbols for architecture x86_64:
"_b", referenced from:
_main in add.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [add] Error 1
here are snippets of my code
add.c
#include <stdio.h>
#include <stdlib.h>
#include "add.h"
int main(void) {
int a = 10, b=20;
add(a, b);
return 0;
}
add.h
#ifndef __ADD_H_
#define __ADD_H_
extern int a,b;
int add(a,b)
{
return a+b;
}
#endif // __ADD_H_
You are lacking a rule to actually build your object files. Right now you only have one to link them all together once they already exist. Try adding:
%.o: %.c
${CC} ${CFLAGS} -c -o $# $<
This tells make how to build object files out of source files.
You are misusing the extern keyword, losing track of your variables and making your code too complicated.
Let's try something very simple:
int main(void) {
int a = 10; b=20;
return 0;
}
This fails. The compiler complains about the statement b=20;, since it has never heard of this b. The semicolon that made this a separate statement was either a typo or a conceptual error caused by declaring extern int b elsewhere. There is no need for extern here, at least not yet.
This:
int main(void) {
int a=10, b=20;
return 0;
}
works.
Now for an add function.
int add(int a, int b)
{
return a+b;
}
int main(void) {
int a = 10, b=20;
add(a,b);
return 0;
}
Note that the a and b in add are not the same variables as the a and b in main. This is crucial; do not proceed until you understand it.
Now add a declaration of the add function:
int add(int a, int b); // <- declaration
int add(int a, int b) // <- definition
{
return a+b;
}
The declaration can be moved into a header file (add.h); the definition belongs in a source file (add.c).
Finally, I would advise you to add a line to the makefile:
add.o: add.h
Aren't you missing an #endif at the end of the last header file queue.h ?
This can be for sure an issue when compiling. Moreover, aren't you missing the main_application.h header file you are then including within the stack.h one for example?
Have a look at this: https://medium.com/#m.muizzsuddin_25037/error-ld-symbol-not-found-for-architecture-x86-64-a5e5b648ffc seems helpful here and point our attention to the header files again!..

Linking extern variables using multiple library in C

In my project, I have two libraries and one program.
Lib1.c and Lib1.h are two files of first library(Lib1.so).
Lib2.c and Lib2.h are two files of second library(Lib2.so).
prog.c is the main file of program(prog).
The program(prog) is linked only to the second library(Lib2.so) and the second library(Lib2.so) is linked to the first library(Lib1.so).
In Lib1.c, I have a declaration of global variable (int var = 0;) and in Lib1.h, I have a declaration (extern int var;).
In Lib2.h, I have a declaration (extern int var;) in order to use var variable in main program.
In main() function, I include the Lib2.h in prog.c file and I have a declaration (var = 5;)
Lib1.c :
#include <stdio.h>
#include "Lib1.h"
int var = 0;
int funct(void)
{
printf("hello world \n");
return 0;
}
Lib1.h :
extern int var;
int funct(void);
Lib2.c :
#include <stdio.h>
#include "Lib2.h"
int funct2(void)
{
printf("Library 2 \n");
funct();
return 0;
}
Lib2.h :
#include "Lib1.h"
extern int var;
int funct2(void);
prog.c :
#include <stdio.h>
#include "Lib2.h"
int main()
{
var = 5;
printf("===>var=%d\n", var);
funct2();
return 1;
}
Commands :
gcc -c -Wall -Werror -fpic Lib1.c
gcc -shared -o Lib1.so Lib1.o
gcc -c -Wall -Werror -fpic Lib2.c
gcc -shared -o Lib2.so Lib2.o -ldl /home/test/Lib1.so
gcc prog.c -o prog -ldl /home/test/Lib2.so
When I try to compile the program(prog.c), I get an error in the link step as below.
/usr/bin/ld: /tmp/ccKaq16a.o: undefined reference to symbol 'var'
/home/test/Lib1.so: error adding symbols: DSO missing from command line
Is there a way to use var variable in the main function when its defined in the first library?
You link your program against Lib2 but not Lib1. You need to add that as well. You also don't need to explicitly link Lib1 when you create Lib2
gcc -c -Wall -Werror -fpic Lib1.c
gcc -shared -o Lib1.so Lib1.o
gcc -c -Wall -Werror -fpic Lib2.c
gcc -shared -o Lib2.so Lib2.o
gcc prog.c -o prog /home/test/Lib2.so /home/test/Lib1.so

Linking to an executable on OSX

On Windows it is possible to dynamically link to an executable with exported symbols. For example following code:
// main.c
void __declspec(dllexport) interface_function() {}
int main() {}
// ext.c
void interface_function();
void extension_function() {
interface_function();
}
With
cl.exe main.c
cl.exe ext.c /LD /link main.lib
would produce an executable main.exe, a static library main.lib for implicit linking, and a dynamic library ext.dll.
Similar behavior can be achieved in OSX with shared libraries:
// main.c
void interface_function() {}
int main() {}
// ext.c
void interface_function();
void extension_function() {
interface_function();
}
With
gcc main.c -o main
gcc ext.c -bundle -bundle_loader main -o ext.bundle
it is virtually equivalent to the Windows setup.
But for dynamiclib:
> gcc ext.c -dynamiclib -o ext.dylib
and shared:
> gcc ext.c -shared -o ext.so
I cannot get them to work because of undefined symbols on one hand and unable to load an executable with -l flag on the other.
I can let them resolve undefined symbols in runtime with -undefined dynamic_lookup. But this is not a sustainable way because all the link errors are now happening in run-time instead.
Is there a way to provide the list of symbols to dynamically load from an executable when linking as -shared and -dynamiclib?
Yes this is possible, but then you'll want to create a bundle rather than a shared library (see this answer for more detail).
If you have a main application like so:
#include <stdio.h>
#include <dlfcn.h>
int func(void)
{
return 42;
}
int main(void)
{
void *dl = dlopen("plugin.so", RTLD_LOCAL);
if(!dl) return -1;
int (*derp)(void) = dlsym(dl, "derp");
if(!derp) return -1;
printf("derp(): %i\n", derp());
return 0;
}
clang -o main main.c -Wall -Wl,-export_dynamic
Then you can compile bundles against it like so:
int func(void);
int derp(void)
{
return -func();
}
clang -o plugin.so plugin.c -Wall -bundle -bundle_loader ./main

C - multiple definition with makefile

I am trying to compile my C program using make and I've come across this problem that I can't quite understand. I have 3 files in the 'calc' folder of my project: add.c sub.c and main.c. I have my Makefile located in the root folder of my project, which has the calc folder that I mentioned in it. This is what my Makefile looks like:
CC=gcc
OBJECTS=obj/main.o obj/add.o obj/sub.o
elf/new: ${OBJECTS}
${CC} -o elf/new ${OBJECTS}
obj/main.o: calc/main.c
${CC} -c -g calc/main.c -o obj/main.o
obj/add.o: calc/add.c
${CC} -c -g calc/add.c -o obj/add.o
obj/sub.o: calc/sub.c
${CC} -c -g calc/sub.c -o obj/sub.o
clean:
rm obj/${OBJECTS} elf/new
When I type 'make' into the terminal to compile, I get an error like this:
gcc -c -g calc/add.c -o obj/add.o
gcc -c -g calc/sub.c -o obj/sub.o
gcc -o elf/new obj/main.o obj/add.o obj/sub.o
obj/add.o: In function `add':
/home/bigger/workspace/test/calc/add.c:1: multiple definition of `add'
obj/main.o:/home/bigger/workspace/test/calc/add.c:1: first defined here
obj/sub.o: In function `sub':
/home/bigger/workspace/test/calc/sub.c:1: multiple definition of `sub'
obj/main.o:/home/bigger/workspace/test/calc/sub.c:1: first defined here
collect2: error: ld returned 1 exit status
makefile:5: recipe for target 'elf/new' failed
make: *** [elf/new] Error 1
And my code are there:
bigger#linux:~/workspace/test> cat calc/add.c
int add(int a, int b){
return a+b;
}
bigger#linux:~/workspace/test> cat calc/sub.c
int sub(int a, int b) {
return a-b;
}
bigger#linux:~/workspace/test> cat calc/main.c
#include <stdio.h>
#include "add.c"
#include "sub.c"
int main(int argc, char* argv[])
{
int a = 10;
int b = 5;
printf("add: %d\nsub:%d\n", a+b, a-b);
return 0;
}
When you include it is making the functions add and sub part of your main.c, then when you make you are linking main (which already has the functions by include) to the add and sub objects which have the same function symbols. You need to include header files with function declarations rather than include function definitions. See http://www.cprogramming.com/declare_vs_define.html for a longer discussion.

dynamic link library in c can not find -lmean

The code for the library:
calc_mean.c
//#include <stdio.h>
double mean(double a, double b) {
return (a+b) / 2;
}
The header file:
calc_mean.h
double mean(double, double);
The programm using the library:
main.c
#include <stdio.h>
#include "calc_mean.h"
int main(int argc, char* argv[]) {
double v1, v2, m;
v1 = 5.2;
v2 = 7.9;
m = mean(v1, v2);
printf("The mean of %3.2f and %3.2f is %3.2f\n", v1, v2, m);
return 0;
}
I created static library using following commands:
gcc -c calc_mean.c -o calc_mean.o
ar rcs libmean.a calc_mean.o
Linking against static library:
gcc -static main.c -L. -lmean -o statically_linked
everything works perfectly fine as long as its static library...
Now these are the commands which I used to create shared library:
gcc -c -fPIC calc_mean.c -o calc_mean.o
gcc -shared -Wl,-soname,libmean.so.1 -o libmean.so.1.0.1 calc_mean.o
after these two commands when I enter the linkng command
gcc main.c -o dynamically_linked -L. -lmean
I am getting error message can not find -lmean
ld returned 1 exit status
attaching error message here
can some one give me steps to create DLL in C?
This is because you are creating a file named libmean.so.1.0.1, but you ask the linker to link with libmean.so (this is what -lmean expands to).
You need a symbolic link libmean.so pointing to libmean.so.1.0.1.
When you try to link the lib by giving -lmean, it automatically searches for libmean.so, but you have created the lib as libmean.so.1.0.1. This is the problem. Either change the lib name or create a symbolic link.
Did you copy the libmean.so.1 in /usr/lib/ (or) /opt/lib/?

Resources