On Nov 15, 2007 10:58 AM, Jeremy Conlin <[EMAIL PROTECTED]> 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/ > module.mk > Particle.cpp > Particle.h > test/ > module.mk > 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. ./GNUmakefile ./src/Other/Other.cpp ./src/Other/Other.h ./src/Particle/Particle.cpp ./src/Particle/Particle.h ./src/test/test_Other.cpp ./src/test/test_Particle.cpp 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 makefile.) 1 source-dirs := Particle Other 2 compile = g++ -MMD $(addprefix -I,$(inc-dirs)) -o $@ -c $< && $(massage-depend) 3 massage-depend = sed -e "s,^`basename [EMAIL PROTECTED],$@," < $(@:.o=.d) > $(@:.o=.dd) 4 link = g++ -o $@ $^ 5 inc-dirs := 6 clean-me := 7 show = $(if $(strip $(show-eval)),$(call info,$(1))$(call info,$(blank-line))) 8 myeval = $(eval $(1))$(call show,$(1)) 9 10 .PHONY: test 11 test: 12 13 .PHONY: clean 14 clean: ; rm -f $(strip $(clean-me)) 15 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 ) 32 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. src/X/X.cpp src/test/test_X.cpp You may also have any number of header files in src/X 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. http://make.paulandlesley.org/autodep.html 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 evaluation. 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 _______________________________________________ Help-make mailing list [email protected] http://lists.gnu.org/mailman/listinfo/help-make
