Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

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?

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

default:test

%.o:%.d
    $(Gpp) -c $*.cpp

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

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

-include $(deps)

.PHONY:clean default

clean:
    -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?

share|improve this question
5  
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." –  Charles Bailey May 22 '11 at 12:01
    
@Charles Bailey : thanks! that made it even nicer –  salsabear May 22 '11 at 16:58

3 Answers 3

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.
deps=
else
# doing build, so make deps.
deps=$(srcs:.cpp=.d)

%.d:%.cpp
   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:

target=test  
rm -f $(objs) $(srcs:.cpp=.d) $(target)
share|improve this answer

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.

http://www.cmake.org

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

cmake_minimum_required(VERSION 2.8)
project(test)
file(GLOB files *.cpp)
add_executable(test ${files})
install(TARGETS test RUNTIME DESTINATION bin)

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
share|improve this answer
    
+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... –  Michael Wild Apr 24 '12 at 9:41
    
Interesting point. I looked around and found this stackoverflow question that discuss advantages and disadvantages of using file(GLOB). –  Erik Sjölund May 2 '12 at 7:44

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
clean:
    $(RM) $(objs) $(deps) test

-include $(deps)
share|improve this answer
    
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. –  bta Oct 17 '12 at 21:35

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.