Reputation: 347
I am using the following simple Makefile to build some simple files. I am really new to making Makefile. I don't know why it keeps in rebuilding even though the files are built after first make and I am not editing any of the file.
EXE = nextgenrsm
CC = gcc
LIBS = StarterWare_Files/
CFLAGS = -c
INCLUDE_PATH = StarterWare_Files/
MAIN_SRC = $(wildcard *.c)
MAIN_OBS = $(patsubst %.c,%.o,$(MAIN_SRC))
LIB_SRC = $(wildcard StarterWare_Files/*.c)
LIB_OBS = $(patsubst StarterWare_Files/%.c,%.o,$(LIB_SRC))
output: $(EXE)
$(EXE): $(MAIN_OBS) $(LIB_OBS)
$(CC) $(MAIN_OBS) $(LIBS)$(LIB_OBS) -o $(EXE)
$(MAIN_OBS): $(MAIN_SRC)
$(CC) $(CFLAGS) *.c -I$(INCLUDE_PATH)
$(LIB_OBS): $(LIB_SRC)
cd $(LIBS); \
$(CC) $(CFLAGS) *.c -I../
clean:
rm -rf $(LIBS)*.o $(EXE) *.o
NEW EDITED MAKEFILE
EXE = nextgenrsm
CC = gcc
LIBS = StarterWare_Files/
CPPFLAGS = _IStarterWare_Files/
MAIN_OBS = $(patsubst %.c,%.o,$(wildcard *.c))
LIB_OBS = $(patsubst %.c,%.o,$(wildcard StarterWare_Files/*.c))
all: $(EXE)
$(EXE): $(MAIN_OBS) $(LIB_OBS)
$(CC) -o $@ $(LDFLAGS) $(MAIN_OBS) $(LIB_OBS) $(LDLIBS)
%.o: %.c
$(CC) -o $@ -MD -MP $(CPPFLAGS) $(CFLAGS) -c $^
ALL_DEPS = $(patsubst %.o,%.d,$(MAIN_OBS), $(LIB_OBS))
-include $(ALL_DEPS)
clean:
rm -f $(LIB_OBS) $(EXE) $(MAIN_OBS) $(ALL_DEPS)
.PHONY: all clean
Whenever I do touch StarterWare_Files/example.h and try to do make again it throws me error that gcc cannot specify -o with -c or -S with Multiple files. Basically the command becomes something like this gcc -o main.o -IStarterWare_Files -c main.c StarterWare_Files/test.h StarterWare_Files/add.h..
Upvotes: 11
Views: 16363
Reputation: 136505
Your default target is output
but your makefile never produces such a file, so that every time you invoke make
it tries to build output
file.
The solution is to mark output
target as a phony target. As well as clean
target:
.PHONY: output clean
You can take advantage of built-in rules that compile .o
from .c
and automatic variables to reduce your makefile to:
EXE := nextgenrsm
CC := gcc
LIBS := StarterWare_Files/
CPPFLAGS := -IStarterWare_Files
MAIN_OBS := $(patsubst %.c,%.o,$(wildcard *.c))
LIB_OBS := $(patsubst %.c,%.o,$(wildcard StarterWare_Files/*.c))
all: $(EXE)
$(EXE) : $(MAIN_OBS) $(LIB_OBS)
$(CC) -o $@ $(LDFLAGS) $^ $(LDLIBS)
clean:
rm -f $(MAIN_OBS) $(LIB_OBS) $(EXE)
.PHONY: all clean
And if you would like automatic header dependency generation add:
# This rule produces .o and also .d (-MD -MP) from .c.
%.o : %.c
$(CC) -o $@ -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
# This includes all .d files produced along when building .o.
# On the first build there are not going to be any .d files.
# Hence, ignore include errors with -.
ALL_DEPS := $(patsubst %.o,%.d,$(MAIN_OBS) $(LIB_OBS))
-include $(ALL_DEPS)
clean:
rm -f $(MAIN_OBS) $(LIB_OBS) $(EXE) $(ALL_DEPS)
Upvotes: 20
Reputation: 58637
The problem is this:
$(MAIN_OBS): $(MAIN_SRC)
You have declared that every object file dependent on every source file. Likewise for the library ones. The above rule expands to:
foo.o bar.o xyzzy.o .... : foo.c bar.c xyzzy.c ...
Therefore, if a time-stamp changes on any source file, every object file will be rebuilt.
What you have to do is have individual dependencies:
# foo.o depends only on foo.c, not on bar.c
foo.o: foo.c
# bar.o depends only on bar.c, not on foo.c
bar.o: bar.c
and so on. Usually, this is not done. Rather, we use GNU Make's pattern rules to write one common rule:
%.o: %c
# build commands to make .o from .c
There is already a built-in rule for this which is often sufficient, and can be customized it by altering variables like CC
and CFLAGS
.
Thanks to built-in rules, simple makefiles usually only have to declare the dependency between the executable object and the object files. Make will automatically deduce the prerequisite from an object file by trying various possibilities. When asked to evaluate foo.o
, it will automatically discover that there exists a foo.c
file, which must be foo.o
's prerequisite. Then if foo.o
is older than foo.c
or does not exist, Make will search its database of rules and discover that this combination matches the %.o: %.c
pattern rule, and it will run its recipe body to update foo.o
.
You should use the :=
style immediate variable assignment rather than the delayed =
assignment. Because you have $(wildcard ...)
in the right hand side of an =
assignment, every time the variable is substituted, the $(wildcard ...)
syntax is evaluated, and the file system is traversed to find files.
Do not use $(wildcard ...)
in the first place to gather the source files. Unless you work in a meticulously clean way, this will pull in unwanted files, like some random test.c
that you happen to create, and so test.o
gets linked to your program (perhaps successfully). It doesn't take much effort to explicitly list all the object files:
OBJS := foo.o bar.o ...
for objects in a subdirectory, you can use $(addprefix ...)
to shorten it:
OBJS := foo.o bar.o ... $(addprefix subdir/,stack.o parser.o ...)
Upvotes: 3