Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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

In your Makefile

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

     all: program

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top