how to add interdependent libraries in a makefile - c

I need to make a makefile for my project and I have two interdependent libraries which are libpcsc.so and libccid.so .
could someone tell me what my mistake is? Thanks for your answers in advance.
and please let me know when you need more information.
my makefile is like:
by the way, one of lib directory is /home/hasanbucak/Desktop/pcsc-lite-1.8.23/src/.libs/ and other one's is usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/
CC = gcc
LIB_DIRS = -L/home/hasanbucak/Desktop/pcsc-lite-1.8.23/src/.libs/
-L../../usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/
INCLUDE_DIR = /home/hasanbucak/Desktop/ccid-1.4.28/src/ #ccid_usb.h
CFLAGS = -g -Wall
obj-y:= smcard
default: all
all: smcard
smcard:
$(CC) $(CFLAGS) $(LIB_DIRS) -I$(INCLUDE_DIR) -c -o $(obj-y).o $(obj-y).c
$(CC) $(CFLAGS) -lccid -lpcsclite $(LIB_DIRS) -I$(INCLUDE_DIR) -o $(obj-y) $(obj-y).c
clean:
rm $(obj-y).o $(obj-y)
and when I write make in terminal , it says:
hasanbucak#ubuntu:~/Desktop/hasan$ make
gcc -g -Wall -L/home/hasanbucak/Desktop/pcsc-lite-1.8.23/src/.libs/ -L../../usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/ -I/home/hasanbucak/Desktop/ccid-1.4.28/src/ -c -o smcard.o smcard.c
gcc -g -Wall -lccid -lpcsclite -L/home/hasanbucak/Desktop/pcsc-lite-1.8.23/src/.libs/ -L../../usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/ -I/home/hasanbucak/Desktop/ccid-1.4.28/src/ -o smcard smcard.c
/usr/bin/ld: cannot find -lccid
collect2: error: ld returned 1 exit status
Makefile:20: recipe for target 'smcard' failed
make: *** [smcard] Error 1

Make already told you what was wrong with the Makefile:
/usr/bin/ld: cannot find -lccid
You should specify the path to ccid properly:
LIB_DIRS = -L/home/hasanbucak/Desktop/pcsc-lite-1.8.23/src/.libs/
-L/usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/
Note that /usr and ../../usr are not at all the same directory.
The first one is absolute (i.e. relative to your root directory), while the second is relative, it expands to ~/Desktop/hasan/../../usr, which is equivalent to /home/hasanbucak/usr.

Related

C Makefile Linking Error: Undefined reference to 'main'

I have tried looking through other answers, unfortunately I have not found anyone with quite the same problem. I am trying to link two C files together, one has a header file, and the other the main file. When trying to make I receive this error:
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
Below is the makefile I use to compile.
INC_DIR = include
SRC_DIR = src
BIN_DIR = bin
UNAME := $(shell uname)
CC = gcc
CFLAGS = -Wall -std=c11 -g -I$(INC_DIR) -I/usr/include/libxml2/
LDFLAGS= -L.
all: XMLParser
XMLParser: $(BIN_DIR)/XMLParser.o $(BIN_DIR)/SVGParser.o
$(CC) $(CFLAGS) -o XMLParser $(BIN_DIR)/XMLParser.o $(BIN_DIR)/SVGParser.o
$(BIN_DIR)/XMLParser.o: $(SRC_DIR)/XMLParser.c $(INC_DIR)/SVGParser.h
$(CC) $(CFLAGS) -o $(BIN_DIR)/XMLParser.o -c $(SRC_DIR)/XMLParser.c
$(BIN_DIR)/SVGParser.o: $(SRC_DIR)/SVGParser.c $(INC_DIR)/SVGParser.h
$(CC) $(CFLAGS) `xml2-config --cflags --libs` -o $(BIN_DIR)/SVGParser.o $(SRC_DIR)/SVGParser.c
clean:
rm *.o XMLParser $(BIN_DIR)/*
XMLParser.c has my main function:
int main(int argc, char **argv) {
...;
return 0;
}
Your recipe for generating the intermediate SVGParser.o is attempting to link and generate a runnable executable. You need to add -c to skip the link step.
You will also need to remove the —libs on that object file and move it to the final link step. In other words add xml2-config —libs for the rule generating the final XMLParser target.
Disclaimer: I’ve never specifically used xml2-config, so I guess there’s some chance I’m wrong here, but it’s a very common paradigm for building and linking against complex libraries, I assume it’s following the same patterns.
A full sample code showing the error must be posted to be able to test it elsewhere, so I cannot fully test your makefile, but providing a true main() and see what happens.
After generating stub files to check your Makefile I found the following output from make:
$ make
gcc -Wall -std=c11 -g -Iinclude -I/usr/include/libxml2/ -o bin/XMLParser.o -c src/XMLParser.c
gcc -Wall -std=c11 -g -Iinclude -I/usr/include/libxml2/ `xml2-config --cflags --libs` -o bin/SVGParser.o src/SVGParser.c
/usr/local/bin/ld: /usr/lib/gcc/x86_64-unknown-freebsd13.0/10.2.1/../../../crt1.o: en la función `_start':
/home/usr/src/lib/csu/amd64/crt1_c.c:75: referencia a `main' sin definir
collect2: error: ld devolvió el estado de salida 1
*** Error code 1
Stop.
make: stopped in /home/lcu/so/makefile
$ _
which is trying to link (alone) the module SVGParser.o (THIS IS BECAUSE YOU DIDN'T ADD THE -c COMPILATION OPTION TO COMPILE ONLY).
Change the compilation line for the SVGParser.o module to use the -c compile-only option and you will get the executable properly.

gcc - how to create an so from a source file and other o files?

I am working on a c project. https://github.com/eantoranz/gitmod It's broken up into separate c/h files. In my current Makefile, I take each one of the c files and compile them into their own .o file, then when I want to create the final program, I ask to compile a c file that has a main and provide all the other .o files. So far, so good (let me know if this approach is not correct).
As a next step, I want to separate the main part of the program from all the other pieces of the code and would like to pack all of the previous o files into a single so file (that had been compiled as just another .o file so far).
So, old approach was like this:
gitmod.o: src/gitmod.c include/gitmod.h lock.o root_tree.o thread.o object.o cache.o
$(CC) -c -o $# $< $(CFLAGS)
gitmod: src/main.c gitmod.o
$(CC) $< *.o -o $# $(CFLAGS)
These would be the last 2 steps of this process using the so replacing gitmod.o for libgitmod.so, after creating all the previous .o files:
libgitmod.so: src/gitmod.c include/gitmod.h lock.o root_tree.o thread.o object.o cache.o
$(CC) $< *.o -shared -o $# $(CFLAGS)
gitmod: src/main.c libgitmod.so
$(CC) $< -llibgitmod.so -o $# $(CFLAGS)
libgitmod.so would be the shared library that I would like to actually contain all the other sections of code (I really hope that is possible).
When make is going through libgitmod.so, I am getting this:
gcc src/gitmod.c *.o -shared -o libgitmod.so -Iinclude `pkg-config fuse3 libgit2 glib-2.0 --cflags --libs` -DGITMOD_DEBUG -Wall -g
/usr/bin/ld: object.o: warning: relocation against `stderr##GLIBC_2.2.5' in read-only section `.text'
/usr/bin/ld: /tmp/ccir4Ou9.o: relocation R_X86_64_PC32 against symbol `stderr##GLIBC_2.2.5' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make: *** [Makefile:32: libgitmod.so] Error 1
What am I doing wrong?
-fPIC, which means Position Indepent Code, flags is required to create shared object.
You can add the flag in the compile flag, then you can create a shared object.

Using debugger in MakeFile

I've written an entire program and its makefile, the only trouble is I have to idea how to implement the debugger. I've been looking at similar questions online but to no avail.
Here's my makefile:
# the variable CC is the compiler to use.
CC=gcc
# the variable CFLAGS is compiler options.
CFLAGS=-c -Wall
assign4: main1.o ObjectManager.o
$(CC) main1.o ObjectManager.o -o assign4
main1.o: main1.c ObjectManager.h
$(CC) $(CFLAGS) main1.c
ObjectManager.o: ObjectManager.c ObjectManager.h
$(CC) $(CFLAGS) ObjectManager.c
clean:
rm -rf *o assign4
I've tried to adjust the CFLAGS: to -g Wall, but all it says is:
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [ObjectManager.o] Error 1
Any suggestions to fix this?
Look at this rule:
ObjectManager.o: ...
$(CC) $(CFLAGS) ObjectManager.c
If CFLAGS is -c -Wall, that -c means that gcc will compile the source file, but not attempt to link it. This is exactly what was intended, to produce an object file and not an executable. One consequence of this is that the source dile (ObjectManager.c) need not contain a main function-- the compiler trusts you to provide one at link time.
But if CFLAGS is -g -Wall, the -g does not imply -c. So gcc will attempt to create an executable, and abort if main is not present.
Solution:
CFLAGS := -Wall -g # the -g can be added with a conditional if you like
ObjectManager.o: ...
$(CC) $(CFLAGS) -c ObjectManager.c

"undefined reference to function" error on a function in the library

I am trying to work with id3 tags with C, so I downloaded mplib and installed it.
I am trying to call this function inside mplib.h where __P is a Macro
extern id3_tag_list* mp_get_tag_list_from_file __P((const char* path));
by writing in
example.c:
int main() {
char* pa = "R U MINE";
id3_tag_list* list = mp_get_tag_list_from_file(pa);
id3_tag *newTag = list->tag;
printf("tag %d\n", newTag->version);
return 0;
}
but when I link, I get an error:
example.o: In function `main':
example.c:(.text+0x27): undefined reference to `mp_get_tag_list_from_file'
collect2: error: ld returned 1 exit status
make: *** [example] Error 1
My makefile looks like this
OBJECTS = example.o
target=example
misc=Makefile
cflags=-Wall -g -O0 -Werror -pedantic -std=c99
all: $(target)
$(target) : $(OBJECTS) $(misc)
gcc $(cflags) -o $(target) $(OBJECTS)
clean:
rm -f $(OBJECTS) $(target)
I am having trouble compiling this. I believe the problem is that I am having issues with linking it to the actual mplib.c file where that function is actually defined, but I am not sure how to do it exactly. I got the library from http://mplib.sourceforge.net/ and I installed it by using 'make' and 'make install'. Am I supposed to manually move the mplib.c file somewhere?
If you build mplib 1.0.3, it creates a library libmp.a. Therefore, you need to specify -lmp on the linker command line, and perhaps -L /where/you/installed/it/lib to specify the directory where the library was installed.
The linker command line should probably look like:
LDFLAGS = -L/usr/local/lib
LDLIBS = -lmp
gcc $(cflags) -o $(target) $(OBJECTS) $(LDFLAGS) $(LDLIBS)
Actually, it would be better if it looked like:
$(CC) $(CFLAGS) -o $# $(OBJECTS) $(LDFLAGS) $(LDLIBS)
The upper-case macro CFLAGS is used for flags to the C compiler. $# means 'the name of the current target'. LDFLAGS are flags for the linker, such as where to find libraries, and LDLIBS contains the specification of libraries. An option such as -lmp means 'look for libmp.so or libmp.a in each of the directories on the list of places searched for libraries' (to a sufficiently close approximation). The -L option prefixes the following directory to the list of places searched for libraries.

Makefile: Linking .*a library

DESCRIPTION:
I have a library libshell.a, inside of it is the function ord_interna that i'm attempting to use, however it seems i linked it wrong, could you guys fix my error, so i dont make it in the future? Cheers,
Error:
/tmp/ccn5lbmJ.o: In function `main':
minishell.c:(.text+0x4e): undefined reference to `ord_interna'
collect2: error: ld returned 1 exit status
make: *** [minishell.o] Error 1
Makefile:
CC=gcc
CFLAGS=-Wall -pedantic -c
all: microshell
microshell: minishell.o
gcc minishell.o -o microshell
minishell.o: minishell.c
gcc minishell.c minishell.h entrada_minishell.c entrada_minishell.h ejecutar.c ejecutar.h libshell.a
clean:
rm -rf *o microshell
From your makefile, I'm guessing you have these source files:
minishell.c
entrada_minishell.c
ejecutar.c
And that you want to compile them, and then link them all together with libshell.a to create an executable called microshell. In that case, you want something like:
CC=gcc
CFLAGS=-Wall -pedantic
all: microshell
microshell: minishell.o entrada_minishell.o ejecutar.o
$(CC) -o $# $^ -L. -lshell
You can add a clean target if you want, but just that should get you going.
Editorial notes:
it's really weird to put header files on the compilation line; I assumed you didn't actually want to do that.
You should look into gcc's -MMD flag to do automatic dependency generation.

Resources