views:

49

answers:

4

I have recently begun writing unit tests (using GoogleTest) for a C++ project. Building the main project is fairly simple: I use GCC's -MM and -MD flags to automatically generate dependencies for my object files, then I link all of the object files together for the output executable. No surpirses.

But as I'm writing unit tests, is there a way to have make or GCC figure out which object files are needed to compile each test? Right now, I have a fairly naive solution (if you can call it that) which compiles ALL available object files together for EVERY unit test, which is obviously wasteful (in terms of both time and space). Is there a way (with make, gcc, sed, or whatever else) to divine which object files are needed for a given unit test in a fashion similar to how dependencies are generated for the original source files?

+1  A: 

You should look to a higher abstraction of project management, like Cmake or GNU Automake.

itsmyown
David Wheeler said "All problems in computer science can be solved with another level of indirection." So while you make a valid observation (your advice doesn't fall upon deaf ears), it really doesn't directly answer the question.
Chris
For clarification, I was assuming you already understand makes `target: dependencies` syntax. On rereading your question I see enough ambiguity to make this unclear. If you were in fact asking for instruction in this area, I would refer you to rlduffy's answer, as it is doing exactly what you need. I assume, though, that you are looking for a higher level of automation.
itsmyown
A: 

In your Makefile

     SOURCES.cpp = a.cpp b.cpp ...
     OBJECTS = $(SOURCES.cpp:%.cpp=%.o)

     all: program

     program: $(OBJECTS)
          $(LINK) -o $@ $(OBJECTS)
rlduffy
A: 

Maybe, depending on how orderly your test system is.

If there's a nice one-to-one relationship between header and source files, then you can use some text-converting functions (or a call to sed) to convert the machine-generated rule you already have:

foo.o: foo.cc foo.h bar.h gaz.h

into a rule for the corresponding test:

unit_test_foo: unit_test_foo.o foo.o stub_bar.o stub_gaz.o

Or if you use a lot of stubs without corresponding headers (which is a warning sign) you can link with every stub except stub_foo.o. These object files are small and don't change often, so it's cheap.

Beta
+1  A: 

It sounds like you have two groups of source files: one that actually implements your program, and another that's all the unit tests. I assume each unit test has its own main function, and unit tests never need to call each other.

If all that's true, you can put all the files from the first group in a static library, and link each of the unit tests against that library. The linker will automatically pull from the library only the object files that are needed.

In concrete Makefile terms:

LIBRARY_OBJECTS = a.o b.o c.o d.o # etc
UNIT_TESTS = u1 u2 u3 u4 # etc
UNIT_TEST_OBJECTS = $(UNIT_TESTS:=.o)

libprogram.a: $(LIBRARY_OBJECTS)
        ar cr $@ $?

$(UNIT_TESTS): %: %.o libprogram.a
        $(CC) $(CFLAGS) -o $@ $< -lprogram
Zack
Thanks, @Zack - hit the nail on the head.
Chris