[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to execute targets in Makefile-A from Makefile-B?

From: Ken Smith
Subject: Re: How to execute targets in Makefile-A from Makefile-B?
Date: Mon, 19 Nov 2007 11:27:48 -0800

On Nov 15, 2007 10:58 AM, Jeremy Conlin <address@hidden> wrote:
> OK so either this isn't as obvious as I had thought, or I'm a real newbie.
> After refactoring my Makefile (trying to follow the suggestions) now I can't
> even do the simplest thing.  I have a directory structure
> src/
>     Particle/
>         Particle.cpp
>         Particle.h
>     test/
>         test_Particle.cpp      //Includes main()
>     AnotherDirectory/
> All I want to do (initially) is make a Particle.o file in the Particle
> directory, but I can't get make to do this.  Of course eventually I want to
> link Particle.o and test_Particle.cpp, but I can't get the simpler step yet.

Hi Jeremy,

I don't know if your question has been answered off the list but I
finally found time to check it out and I came up with this solution.
Here's my directory structure.


And here is a makefile that builds the objects Other.o and Particle.o
and the programs test_Other and test_Particle.  This makefile enforces
the naming of the directories and the test programs.  The test program
must match the object under test.  An explanation of the makefile
follows.  (You'll have to remove the line numbers before using this

  1 source-dirs := Particle Other
  2 compile = g++ -MMD $(addprefix -I,$(inc-dirs)) -o $@ -c $< &&
  3 massage-depend = sed -e "s,^`basename address@hidden,$@," < $(@:.o=.d) > 
  4 link = g++ -o $@ $^
  5 inc-dirs :=
  6 clean-me :=
  7 show = $(if $(strip $(show-eval)),$(call info,$(1))$(call
  8 myeval = $(eval $(1))$(call show,$(1))
 10 .PHONY: test
 11 test:
 13 .PHONY: clean
 14 clean: ; rm -f $(strip $(clean-me))
 16 $(foreach d,$(source-dirs), \
 17   $(call myeval,src/$(d)/$(d).o : src/$(d)/$(d).cpp ; $$(compile)) \
 18   $(call myeval,inc-dirs := $(inc-dirs) src/$(d)) \
 19   $(call myeval,-include src/$(d)/$(d).dd) \
 20   $(call myeval,src/test/test_$(d).o : src/test/test_$(d).cpp ;
$$(compile)) \
 21   $(call myeval,src/test/test_$(d) : src/test/test_$(d).o
src/$(d)/$(d).o ; $$(link)) \
 22   $(call myeval,test: src/test/test_$(d)) \
 23   $(call myeval,clean-me := $(clean-me) \
 24     src/$(d)/$(d).o \
 25     src/$(d)/$(d).d \
 26     src/$(d)/$(d).dd \
 27     src/test/test_$(d).dd \
 28     src/test/test_$(d).d \
 29     src/test/test_$(d) \
 30    ) \
 31  )
 33 $(call show,$(blank-line))

line 1: Place the names of your source files here.  For each X in this
variable you must have the following.


You may also have any number of header files in


which may be included by either of the .cpp files.

line 2: A compile rule which automatically generates a .d dependency
file alongside the .o file.  Find out how your compiler does this if
you aren't using GCC as it will save you build time by not generating
dependencies as a separate step.  If your compiler doesn't support
this, refer to Tom Tromey's excellent article frequently mentioned on
this list.

line 3: GCC's -MMD option doesn't prepend the relative path to the
object files even though it prepends the relative path to the source
files.  I don't know why.  This sed incantation remedies this
situation.  This makefile operates on the relative paths so the
dependency file must also have relative paths.

line 4: A link command line

line 5: Not strictly necessary.  The eval rules build this variable up
to include all the source directories which are passed to -I in the
compile rule.  This allows you to include Particle.h from
test_Particle.cpp.  You could even include Particle.h from Other.cpp.

line 6: Also, not strictly necessary.  This ultimately contains a list
of all the build products for use by the clean target.

line 7: When you run `make show-eval=t`, the evals will be displayed
to the terminal as they are executed.  Kinda useful to see what the
variables expand to.

line 8: A wrapper for the $(eval) built-in which optionally shows the

line 10-11: The default rule, test, which builds all of the tests.

line 13-14: The clean rule, `make clean`

line 16: Iterate once for every space separated member of $(source-dirs).

line 17: Generate a rule to compile each object file.

line 18: Add this object file's path to the include path.

line 19: Include the .dd dependency file if it exists.  This is what
causes the .o to be rebuilt if the .h changes.

line 20: A rule to compile the corresponding test program.

line 21: A rule to link the corresponding test program.

line 22: Add this test program to the phony target, 'test'

line 23-29: Register the build products with the clean rule.

line 33: Place a blank line between the rule generation and the rule execution.

Feel free to send me any questions directly or on the list.

   Ken Smith

reply via email to

[Prev in Thread] Current Thread [Next in Thread]