Makefiles, what are you doing with them? 155

Posted by Brett Schuchert Wed, 27 Jan 2010 15:02:00 GMT

Half a year ago, I took some exercises written in Java and ported them to C++. At that time I punted on writing makefiles and decided to reply on an IDE (Visual Studio). That worked fine but recently we almost had a customer that was going to take this class and, bless their heart, use the command line.

Turns out they are going to use visual studio, so I can shelve this, but I figured I’d get feedback on what I have created for a makefile. Since I have not written a makefile for 12ish years, I figured things have changed. They have, but I suspect they have even more.

What follows are my environment assumptions and the makefile. I’d appreciate any suggestions.

FWIW, I wrote this makefile because it turns out fully building all files takes longer than just building what has changed. I know this seems obvious, but it is not always the case with small projects like this. There is some point where the project becomes big enough to warrant dependency-based building. The exercise meets that criteria. Sometimes the time taken to evaluate build changes is enough overhead that it can be safely removed in lieu of a full build. This is a consideration when creating custom build files for legacy-based refactoring efforts.

Environment
  • Generic Unix
  • zsh – though any shell will do really
  • g++
  • gnu make
  • This source base will still be used in Visual Studio but not this makefile
  • CppUTest used for unit testing tool
  • Provide default location for CppUTest, which can be overridden by environment variable
  • Boost library installed in /usr/local/include and /usr/local/lib (reasonable assumption or should I go ahead and allow this to be configured easily in the makefile – what’s your opinion?)
  • Project is small enough that all headers and source files are in the same directory (should I build the .o’s and put them in another directory to hide them?)
Current Makefile
ifdef CPP_U_TEST
    CppUTest_base = $(CPP_U_TEST)
else
    CppUTest_base = $(wildcard ~/src/cpputest)
endif

LIB_DIRS = -L$(CppUTest_base)/lib
INC_DIRS = -I$(CppUTest_base)/include
LIBS = -lCppUTest -lboost_date_time -lboost_regex -lboost_thread
CFLAGS = -g $(INC_DIRS) 
LDFLAGS = $(LIB_DIRS) $(LIBS)
CC = g++
SRCS := $(wildcard *.cpp)
OBJS = $(SRCS:.cpp=.o)
OUT = run_all_tests
DEP_DIR = dependencies

all: $(OBJS)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $(OUT) $(OBJS)

clean:
    @rm -rf $(DEP_DIR) $(OBJS) $(OUT)

-include $(SRCS:.cpp=$(dep_dir)/.d)

.cpp.o:
    @if [ ! -d $(DEP_DIR) ] ; then mkdir $(DEP_DIR) ; fi
    $(CC) -c $(CFLAGS) -o $@ $< 
    @$(CC) -MM $(CFLAGS) $*.cpp > $(DEP_DIR)/$*.d