views:

79

answers:

2

I'm struggling to write Makefiles that properly build my unit tests. As an example, suppose the file structure looks like this

src/foo.cpp
src/foo.hpp
src/main.cpp
tests/test_foo.cpp
tests/test_all.cpp

So, to build the executable test_all, I'd need to build test_foo.o which in turn depends on test_foo.cpp but also on src/foo.o.

What is the best practice in this case? One Makefile in the parent folder? One Makefile per folder? If so, how do I manage the dependencies across folders?

+1  A: 

The common practice is one Makefile for each folder. Here is a simple Makefile.am script for the root folder:

#SUBDIRS = src tests
all:
    make -C ./src
    make -C ./tests    
install:
    make -C ./src install
uninstall:
    make -C ./src uninstall
clean:
    make -C ./src clean
test:
    make -C ./tests test

The corresponding Makefile.am for the src folder will look like this:

AM_CPPFLAGS = -I./

bin_PROGRAMS = progName

progName_SOURCES = foo.cpp main.cpp
LDADD = lib-to-link

progName_LDADD = ../libs/

Makefile.am for tests will look similar:

AM_CPPFLAGS = -I../src

bin_PROGRAMS = tests

tests_SOURCES = test_foo.cpp test_all.cpp

Use automake to generate Makefile.in files from the .am files. The configure script will use the .in files to produce the Makefiles. (For small projects you would like to directly hand-code the Makefiles).

Vijay Mathew
This doesn't seem to take the dependency of test_all.cpp on src/foo.o into account. E.g. what happens after make clean; make test in the top level directory?
Michael Ulm
If the tests are driven from main.cpp, there won't be any dependency problems.
Vijay Mathew
But main.cpp will be the executable of the application, not driving the tests. The executable conducting the tests should reside in the tests folder.
Michael Ulm
@Michael have you tried `tests_SOURCES = test_foo.cpp test_all.cpp ..\src\foo.cpp`? I gave an example so that you can easily pick up the rest :-)
Vijay Mathew
Thanks Vijay, that was the last missing piece of the puzzle for me. I wasn't aware that dependencies across folders were handled correctly.
Michael Ulm
+1  A: 

Common practice is a Makefile per directory. That's what I would have suggested before I read "Recursive Make Considered Harmfull" (http://miller.emu.id.au/pmiller/books/rmch/). Now I'd recommend one Makefile. Also check out the automatic dependency generation - now you don't even need to work out what your tests depends on. All you need is some targets.

dave
Thanks dave for the very interesting read. However, trying to really implement a non-recursive Makefile seems to be very complicated, as shown in http://www.xs4all.nl/~evbergen/nonrecursive-make.html -- This seems to be too much work for the small- to medium sized projects I'm involved in.
Michael Ulm
They do a lot more in that example than just have one Makefile. I set up a top level Makefile reading their instructions with out all the bells and whistles in about 2 hours after reading that article (+ another 2-4 hours beforehand reading about make)
dave