3
votes

I am trying to make a makefile which does the following:

  • gets source files from the src directory
  • puts object files in the obj directory
  • puts binary files in the bin directory
  • puts release targets in the rel directory
  • puts debug targets in the dbg directory

The first problem i'm having is that my target-specific variables don't seem to be working here is the makefile:

# Build Directories
src_dir=src
obj_dir=obj
bin_dir=bin

cc=cl
cc_flags=

# create the directory for the current target.
dir_guard=@mkdir -p $(@D)

# source files
src = MainTest.cpp

# object files - replace .cpp on source files with .o and add the temp directory prefix
obj = $(addprefix $(obj_dir)/$(cfg_dir)/, $(addsuffix .obj, $(basename $(src))))

release: cfg_dir = rel
release: executable

debug: cfg_dir = dbg
debug: cc_flags += -Yd -ZI
debug: executable

executable: $(bin_dir)/$(cfg_dir)/MainTest.exe

# build TwoDee.exe from all of the object files.
$(bin_dir)/$(cfg_dir)/MainTest.exe : $(obj)
    $(dir_guard)
    $(cc) -out:$@ $(obj) -link

# build all of the object files in the temp directory from their corresponding cpp files.
$(obj_dir)/$(cfg_dir)/%.obj : $(source_dir)/%.cpp
    $(dir_guard)
    $(cc) $(cc_flags) -Fo$(obj_dir)/$(cfg_dir) -c $<

When I run make debug I get:

make: *** No rule to make target `obj//MainTest.obj', needed by `bin//MainTest.exe'.

There is also something else wrong because if I remove the debug and release variables and hardcode cfg_dir to rel I then get:

make: *** No rule to make target `obj/rel/MainTest.obj', needed by `bin/rel/MainTest.exe'.  Stop.

So my object rule must also be wrong. I am new to make files so if anyone sees other things which are wrong, comments are welcome.

1

1 Answers

4
votes

Target-specific variables are only available in the recipes, not in the rules. This is because the rules are parsed when the Makefile is read, and dependencies are deduced from that.

To get your rules tailored for multiple possible values of cfg_dir, I suggest you look at the example in the eval section of the GNU Make manual. This explains things like this:

release: $(bin_dir)/rel/MainTest.exe

debug: cc_flags += -Yd -ZI
debug: $(bin_dir)/dbg/MainTest.exe

define template =

# build TwoDee.exe from all of the object files.
$(bin_dir)/$(cfg_dir)/MainTest.exe : $(obj)
    $$(dir_guard)
    $$(cc) -out:$$@ $(obj) -link

# build all of the object files in the temp directory from their corresponding cpp files.
$(obj): $(obj_dir)/$(cfg_dir)/%.obj : $$(src_dir)/%.cpp
    $$(dir_guard)
    $$(cc) $$(cc_flags) -Fo$(obj_dir)/$(cfg_dir) -c $$<

endef
$(foreach cfg_dir,rel dbg,$(eval $(template)))