Evan
Evan

Reputation: 75

How do I structure Makefiles so that a target in one depends on a target in another?

I have a base directory src, and two subdirectories src/foo and src/tests. In src/tests I have a Makefile that builds src/tests/tests.cpp. I want this to depend on src/foo/*.o, which I am compiling with

%.o : %.cpp
    ${GCC} -c ${CXXFLAGS} $< -o $@

in src/foo/Makefile. Is there a good way to structure my Makefiles by including one in another or something?

In other words, src/foo/Makefile looks like:

OBJECT_FILES += bar.o baz.o ...

main: main.o ${OBJECT_FILES}
    ${GCC} ${CXXFLAGS} main.o ${OBJECT_FILES} -o main

%.o : %.cpp
    ${GCC} -c ${CXXFLAGS} $< -o $@

and I want src/tests/Makefile to do something like:

# Obviously this is impossible right now since OBJECT_FILES is not defined in this Makefile.
tests: tests.o ${OBJECT_FILES}
    ${GCC} ${CXXFLAGS} tests.o ${OBJECT_FILES} -o tests

tests.o: tests.cpp
    ...

Upvotes: 0

Views: 69

Answers (2)

R Sahu
R Sahu

Reputation: 206697

Assuming you are using GNU make, you can use a phony target.

.PHONY: foo_objets

foo_objects:
    $(MAKE) -C ../../src/foo

and define foo_objects as a dependency of test.

tests: tests.o ${OBJECT_FILES} foo_objects
    ${GCC} ${CXXFLAGS} tests.o ${OBJECT_FILES} -o tests

Upvotes: 0

Shachar Shemesh
Shachar Shemesh

Reputation: 8583

Combining two self contained make files for a single project is difficult, and, in fact, not recommended. Please read Recursive Make Considered Harmful for fuller explanation as to why. Please note, this applies only to calling make recursively, and only when the different parts of the project have inter-dependencies.

The problem is that when you forgo the recursive option, the other options are not great. The most obvious would be to include your src makefile from your tests directory. This won't work, however, as that src makefile makes implicit assumptions about current directory that do not hold true when you are in the tests directory.

Your best options is to create one make file in the root of the project, that builds both src and tests. This would make the dependency specification trivial.

While at it, it seems to me that your project needs are as standard as they can get. Even your pattern rule for compiling is just a simplified version of the pattern rule built into make (i.e. - you could drop it from your make file, and everything will continue to work). When such is the case, trying to reinvent the wheel seems unnecessary to me.

I recommend using one of the standard build generating tools. automake is my favorite, because it is universally available and requires no special tools on the compiling machines. Its learning curve is slightly steeper to climb than others, especially for simple projects, but the tools you gain while learning it are also useful for projects not using it.

Then again, for the above stated reasons, some hate the auto tools with a vengeance. To each his own.

Upvotes: 1

Related Questions