Why doesn't my makefile target-specific variable work?

build, makefile

Solution

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)))

Problem

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.

Original source