Reputation: 137
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 compile
gcc -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
Upvotes: 3
Views: 29705
Reputation: 29290
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:
main
if main.o
or functions.o
changed.main.o
and functions.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.
Upvotes: 8
Reputation: 366
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 :)
Upvotes: 1