-1

I have 2 .cpp files : main.cpp A.cpp and few header files in include dir.

I am trying to write a makefile that recompiles whenever a header file changes.

Now I tried following the method outlines in the example here. However I could not get started. Here is my attempt so far.

CC := g++
OBJS := main.o A.o
OUTPUT := program.exe
INCLUDE_DIR := -I ./include \

#linking step
all: $(OBJS)
    $(CC) $(INCLUDE_DIR) $(OBJS) -o $(OUTPUT)

#compile and generate dependency info
%.o : %.cpp
    $(CC) $(INCLUDE_DIR) -c $*.cpp -o $*.o 
    $(CC) $(INCLUDE_DIR) -MMD -c -o $@ $<

-include *.d
Community
  • 1
  • 1
bhavesh
  • 1,343
  • 2
  • 14
  • 23

2 Answers2

3

You're not including your dependency files correctly. The wildcard there doesn't do what you want. It'd be simpler to just:

DEPS = $(OBJS:.o=.d)
-include $(DEPS)

To actually use a wildcard with the dependencies, you'd have to do:

-include $(wildcard *.d)

Note that gcc actually lets you generate the dependency and the object files at the same time. This could simplify your rule. Also I find it better to explicitly state where everything is going, in case of any issues:

%.o : %.cpp
    $(CC) $(INCLUDE_DIR) -c $< -o $@ -MMD -MF $(@:.o=.d)
Furynolo
  • 41
  • 8
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    Could you explain how the line with `-MMD` and `-MF` flags works? – SU3 Jun 20 '15 at 18:09
  • 1
    @SU3 See [Preprocessor Options](https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html), specifically the description for `-M`. – Barry Jun 20 '15 at 18:13
  • The `MF` flag is pointless when `MMD` is used, contrary to the `MD` flag. – Chnossos Jun 22 '15 at 13:02
  • 1
    @Chnossos False. From the documentation "When used with the driver options -MD or -MMD, -MF overrides the default dependency output file." If you want to put the dependency outfile files somewhere other than the default, that's what `-MF` is for. – Barry Jun 22 '15 at 13:24
  • Yeah, I should've added "when used like you did in your answer" since you're basically doing manually what is done automatically. – Chnossos Jun 22 '15 at 13:26
  • @Chnossos I like being explicit. – Barry Jun 22 '15 at 13:29
  • Nothing wrong with that, I for one like to be minimalist, so I thought indicating that fact could be useful to someone else like me :) – Chnossos Jun 22 '15 at 13:30
  • Please remember to include this after the All, or it will check the receipt and then exit – FrankX Aug 14 '18 at 10:07
1

You need to include the header files in the dependencies' list. For example:

%.o : %.cpp %.hh
    $(CC) $(INCLUDE_DIR) -c $*.cpp -o $*.o 
    $(CC) $(INCLUDE_DIR) -MMD -c -o $@ $<

If you have an a.hh for every a.cpp.

The make file syntax is

target: dependency_1 dependency_2 etc
    rule

All the dependencies are checked for when they were updated last time, and if either of them has a time stamp more recent then the target, the rule is executed. In your Makefile, you don't have any headers in the list of dependencies.

SU3
  • 5,064
  • 3
  • 35
  • 66
  • There may not be a %.hh for every %.cpp, and the whole point of autogenerating the dependencies is to get them correct. – Barry Jun 20 '15 at 18:01
  • @Barry I understand that, that's why I wrote "**If** you have an `a.hh` for every `a.cpp`". Also, I just expanded the answer. – SU3 Jun 20 '15 at 18:02
  • That's a large assumption that is probably never going to be true, made even more unnecessary by the fact that the goal of OP is to have the compiler generate the correct dependencies for him via the `*.d` files. This answer is just wrong. – Barry Jun 20 '15 at 18:14