I need automatic dependency generation to be done in my makefile. So, I have tried to write one, after googling for similar ones. I have found some ways to do that, but the problem is that they are usually too complicated for me (because of usage of sed command etc. and I want a way for me to create a makefile without the need of refering to some other makefile).

Below is a makefile I hope should do the same job i.e. automatically find out all the dependencies of the object files and build them. Could you please review this makefile and point out cases where the build may fail when it should not have?

srcs=$(wildcard *.cpp)


    $(Gpp) -c $*.cpp

    echo -n "$*.d ">$*.d
    $(Gpp) -MM $*.cpp>>$*.d

test: $(objs)
    $(Gpp) $^ -o $@

-include $(deps)

.PHONY:clean default

    -rm -rf *.o test *.d

One place where the makefile fails is when for example a.cpp initially included a1.h but it has been updated to exclude a1.h and a1.h file has been deleted from file-system. So, except that is there any place that this makefile fails?

  • 5
    \$\begingroup\$ You may want to investigate the -MP option. "This option instructs CPP to add a phony target for each dependency other than the main file, causing each to depend on nothing. These dummy rules work around errors 'make' gives if you remove header files without updating the 'Makefile' to match." \$\endgroup\$
    – CB Bailey
    May 22, 2011 at 12:01
  • \$\begingroup\$ @Charles Bailey : thanks! that made it even nicer \$\endgroup\$
    – user4473
    May 22, 2011 at 16:58

3 Answers 3


Not to be too blunt; but, you're going about this the wrong way. Look into the command line option -MMD for GCC, specify it when compiling your source; and, retain the inclusion statement for dependencies.

Also, no need for a default target. The first target is the default target.

An example:

Gpp = g++
srcs = $(wildcard *.cpp)
objs = $(srcs:.cpp=.o)
deps = $(srcs:.cpp=.d)

test: $(objs)
    $(Gpp) $^ -o $@

%.o: %.cpp
    $(Gpp) -MMD -MP -c $< -o $@

.PHONY: clean

# $(RM) is rm -f by default
    $(RM) $(objs) $(deps) test

-include $(deps)
  • \$\begingroup\$ This is the right way to approach the problem. Dependencies are only useful in re-compilation (everything gets built the first time through), so you don't need to generate the .d files in a separate step. \$\endgroup\$
    – bta
    Oct 17, 2012 at 21:35

That will likely generate deps all the time, even if your target is 'clean'. Put the dep targets and includes in an ifeq block which checks the makefile target, then there wont be any dependency generation prior to cleaning (since those files should be removed by the clean, it is a waste to generate them prior to clean).

ifeq ($(MAKECMDGOALS),clean)
# doing clean, so dont make deps.
# doing build, so make deps.

   echo -n "$*.d ">$*.d
   $(Gpp) -MM $*.cpp>>$*.d

-include $(deps)
endif # ($(MAKECMDGOALS),clean)

Also it is much cleaner to create subdirs and place the .d and .o files in the subdirs. Then the source directories (i.e. 'src', ...) remain spotless and the dangerous "-rm -rf *.o test *.d" is completely avoided.

Also "-rm -rf *.o test *.d" in itself is not optimal. Best to only remove what is defined, don't remove arbitrary files (and no need for "-r" either). New code:

rm -f $(objs) $(srcs:.cpp=.d) $(target)

Not exactly what you are asking for but I would suggest using cmake to generate the Makefile. cmake is good at automatically finding dependencies and it also lets you build in a separate build directory.


First create a file called CMakeLists.txt with this content:

cmake_minimum_required(VERSION 2.8)
file(GLOB files *.cpp)
add_executable(test ${files})

then build and install your program test like this

erik@linux:~$ ls ~/codereview/
file.cpp  file.h  CMakeLists.txt  main.cpp
erik@linux:~$ mkdir /tmp/build
erik@linux:~$ mkdir /tmp/install
erik@linux:~$ cd /tmp/build/
erik@linux:/tmp/build$ cmake -DCMAKE_INSTALL_PREFIX=/tmp/install ~/codereview/
-- The C compiler identification is GNU
-- The CXX compiler identification is GNU
-- Check for working C compiler: /usr/bin/gcc
-- Check for working C compiler: /usr/bin/gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/build
erik@linux:/tmp/build$ make
Scanning dependencies of target test
[ 50%] Building CXX object CMakeFiles/test.dir/main.cpp.o
[100%] Building CXX object CMakeFiles/test.dir/file.cpp.o
Linking CXX executable test
[100%] Built target test
erik@linux:/tmp/build$ ls -l /tmp/build/test
-rwxrwxr-x 1 erik erik 7702 2012-04-12 16:58 /tmp/build/test
erik@linux:/tmp/build$ make install
[100%] Built target test
Install the project...
-- Install configuration: ""
-- Installing: /tmp/install/bin/test
erik@linux:/tmp/build$ ls -l /tmp/install/bin/test
-rwxr-xr-x 1 erik erik 7702 2012-04-12 16:58 /tmp/install/bin/test
  • \$\begingroup\$ +1 for bringing up CMake, but please, please, never use file(GLOB). It completely breaks CMake (i.e. when you add or remove source files you will have to re-run CMake manually). Just list the sources explicitly. It's not so much work... \$\endgroup\$ Apr 24, 2012 at 9:41
  • 2
    \$\begingroup\$ Interesting point. I looked around and found this stackoverflow question that discuss advantages and disadvantages of using file(GLOB). \$\endgroup\$ May 2, 2012 at 7:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy