undefined reference when using makefile
Solution 1
The error message is clear: the linker did not find the printMsg
function. And this is perfectly normal: the link command that was executed was:
gcc -o main main.o
See? No trace of functions.o
where the printMsg
function is implemented. To fix this you must link with this command:
gcc -o main main.o functions.o
The problem is that your Makefile does not mention functions.o
as a pre-requisite of main
and it does not use it neither in the recipe. Either you did not understand the professor's instructions (who did not ask you to add functions.c
and functions.h
), or you forgot that he also indicated how to update the Makefile, or his Makefile is not compatible with his own instructions. In the two last cases you can adapt the Makefile by changing the rule for $(EXECS)
:
$(EXECS) : %: %.o functions.o
$(CC) -o $@ $^ $(LIBS)
$^
expands as the list of all pre-requisites, that is, in your case, main.o functions.o
. This new rule will:
- Re-build
main
ifmain.o
orfunctions.o
changed. - Link
main.o
andfunctions.o
.
Warning: if you have other executables listed in $(EXECS)
that do not depend on functions.o
, or that depend on other object files, or if you have more other files like functions.o
, you will need something a bit more sophisticated. Ask a new question.
Note: as SO is English, it is better to translate the French comments in your example code. I suggest:
Add the executable names after '=', separated by one space. If a line is full, add a '\' at the end and continue on the next line.
One last note: letter case matters. If your file is functions.c
do not type FUNCTIONS.C
in your question. Same with the other file names.
Solution 2
Use this makefile it works and it is more comprehensible/better
GREEN = \033[1;32m
WHITE = \033[0;m
NAME = main
CC = gcc -g
RM = rm -f
SRCS = functions.c \
main.c
OBJS = $(SRCS:.c=.o)
CFLAGS = -I ./include/
CFLAGS += -W -Wall -Wextra
all: $(NAME)
$(NAME): $(OBJS)
@$(CC) $(OBJS) -o $(NAME) $(LDFLAGS)
@printf "\n[$(GREEN)OK$(WHITE)] Binary : $(NAME)\n"
@echo "-------------------\n"
%.o : %.c
@$(CC) $(CFLAGS) -c -o $@ $<
@printf "[$(GREEN)OK$(WHITE)] $<\n"
clean:
$(RM) $(OBJS)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY: all clean fclean re
The functions.h file :
#ifndef FUNCTIONS_H_
#define FUNCTIONS_H_
void printMsg();
#endif /* !FUNCTIONS_H_ */
And the same main.c. You don't need to include "functions.h" in the function.c
Allez l'om,
Nicolas :)
Comments
-
Hajar Elkoumikhi almost 2 years
I have a given makefile, written by our Professor. `
SHELL = /bin/bash CC = gcc CFLAGS = -Wall -W -std=c99 -pedantic LIBS = # Rajouter le nom des executables apres '=', separes par un espace. # Si une ligne est pleine, rajouter '\' en fin de ligne et passer a la suivante. # To compile without bor-util.c file EXECS = main # To compile with bor-util.c file EXECSUTIL = # To compile with bor-util.c & bor-timer.c files EXECSTIMER = .c.o : $(CC) -c $(CFLAGS) $*.c help :: @echo "Options du make : help all clean distclean" all :: $(EXECS) $(EXECSUTIL) $(EXECSTIMER) $(EXECS) : %: %.o $(CC) -o $@ [email protected] $(LIBS) $(EXECSUTIL) : %: %.o bor-util.o $(CC) -o $@ [email protected] bor-util.o $(LIBS) $(EXECSTIMER) : %: %.o bor-util.o bor-timer.o $(CC) -o $@ [email protected] bor-util.o bor-timer.o $(LIBS) clean :: \rm -f *.o core distclean :: clean \rm -f *% $(EXECS) $(EXECSUTIL) $(EXECSTIMER) `
All we have to do in this project, is to write our code in other file and use this makefile to compile as usual. I've written a helloWorld function to test. I have 3 files FUNCTIONS.C
#include <stdio.h> #include "functions.h" void printMsg(){ printf("Hello World !"); }
FUNCTIONS.H
#ifndef FUNCTIONS_H #define FUNCTIONS_H void printMsg(); #endif /* FUNCTIONS_H */
And a MAIN.C file to test out everything
#include "functions.h" int main(){ printMsg(); return 0; }
and I've added
main
to the makefile. But I get this error message when I compilegcc -o main main.o main.o: In function `main': main.c:(.text+0xa): undefined reference to `printMsg' collect2: error: ld returned 1 exit status Makefile:32: recipe for target 'main' failed make: *** [main] Error 1
Does anyone know what's the solutions please ? Thank you