6
votes

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..

2
Is make rebuilding $(MAIN_OBS)? $(LIB_OBS)? $(EXE)? All of them? Run make -d and look through the output and it will tell you what it thinks needs to be rebuilt and why. Also your makefile isn't correct. It tells make that every .o file has every .c file as a prerequisite not just its matching one. So changing any .c file is going to recompile every .o file in that set.Etan Reisner
@EtanReisner Yes it is building all of them. How to make that change? that it only refers to it's own C file.Aakash
It probably is only building the $(LIB_OBS) files again. That's because you remove the directory prefix from the .c file when you set the value of $(LIB_OBS) but you then have the target make the .o files in the directory so make can't match those up (because foo.o isn't the same as StarterWare_Files/foo.o).Etan Reisner
@EtanReisner Thanks for pointing that outAakash
@EtanReisner what is the significance of $^?Aakash

2 Answers

16
votes

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)
2
votes

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 ...)