为什么我的makefile特定于目标的变量不起作用?

时间:2012-07-04 14:51:28

标签: build makefile

我正在尝试创建一个执行以下操作的makefile:

  • src 目录
  • 获取源文件
  • 将对象文件放在 obj 目录
  • 将二进制文件放入 bin 目录
  • 将发布目标放在 rel 目录
  • 将调试目标放在 dbg 目录

我遇到的第一个问题是我的目标特定变量似乎不起作用是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 $<

当我运行make debug时,我得到:

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

还有其他问题,因为如果我删除调试和释放变量并将 cfg_dir硬编码为rel ,我会得到:

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

所以我的对象规则也必须是错误的。我是新手制作文件,所以如果有人看到其他错误的内容,欢迎提出意见。

1 个答案:

答案 0 :(得分:1)

特定于目标的变量仅在配方中可用,而不在规则中。这是因为在读取Makefile时会解析规则,并从中推断出依赖关系。

要为cfg_dir的多个可能值量身定制规则,建议您查看GNU Make手册的eval部分中的示例。这解释了这样的事情:

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