Reputation: 225
Iam working with gcc and MinGW on a Windows platform. I have a directory containing two *.c files: main.c and funcs.c
I am using the following makefile:
CC=gcc
CFLAGS=-c
LDFLAGS=
SOURCEDIR = src
BUILDDIR = build
SOURCES=$(wildcard $(SOURCEDIR)/*.c)
OBJECTS=$(patsubst $(SOURCEDIR)/%.c,$(BUILDDIR)/%.o,$(SOURCES))
LIBRARIES=-L/mingw64/lib
INC= -I./include
EXECUTABLE=testLink
VPATH = src include build
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) $(LIBRARIES) -o ./dist/$@
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $@
Which should take the *.c files and generate *.o files with the same name. However I get the following output on make -
$ make
gcc -I./include -c src/funcs.c -o build/funcs.o
gcc -I./include -c src/funcs.c -o build/main.o
gcc build/funcs.o build/main.o -L/mingw64/lib -o ./dist/testLink
followed of course by a bunch of multiple definition errors. As you can see from the first two lines it is taking the same *.c file and compiling it twice into two different *.o files.
I am new to makefiles but I assume it is something wrong with my $(OBJECTS) rule and I'm pretty sure it's the $< which is causing the problem. I'm trying to create a generic makefile which will always work on my projects which have the same directory structure and take .c files turn them into .o files and link. Am I going about this entirely the wrong way or is there a simple fix to my makefile?
Thanks!
James
Upvotes: 4
Views: 3950
Reputation: 1264
This rule:
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $@
expands to:
funcs.o main.c: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $@
which is equivalent to:
funcs.o: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $@
main.o: funcs.c main.c
$(CC) $(INC) $(CFLAGS) $< -o $@
$<
refers to the first dependency (funcs.c) so your Makefile is trying to generate both funcs.o and main.o from the same source.
You just want a generic rule using %
wildcard matching:
%.o: %.c
$(CC) $(INC) $(CFLAGS) $< -o $@
See https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html
Upvotes: 4
Reputation: 140148
Jeff pointed the mistake in his answer (all objects depend on all sources: that isn't a generic compilation rule for c sources).
However, the generic rule must have source & object paths. To sum it up, just replace
$(OBJECTS): $(SOURCES)
$(CC) $(INC) $(CFLAGS) $< -o $@
by
$(BUILDDIR)/%.o : $(SOURCEDIR)/%.c
$(CC) $(INC) $(CFLAGS) $< -o $@
(as explained in How to generate a Makefile with source in sub-directories using just one makefile)
note that this kind of dependency test doesn't take included .h
files into account, so it's only intended for first builds. Modifying .h
files afterwards doesn't trigger a compilation since the header files are not listed as dependencies.
Upvotes: 2