Build 为什么';我的makefile目标特定变量不能工作吗?

Build 为什么';我的makefile目标特定变量不能工作吗?,build,makefile,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 t

我正在尝试创建一个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 $<
还有其他一些错误,因为如果我删除调试和发布变量以及硬代码cfg_dir to rel我会得到:

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

因此,我的对象规则也肯定是错误的。我对制作文件是新手,因此如果有人看到其他错误的东西,欢迎发表评论。

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

为了使您的规则适合于
cfg_dir
的多个可能值,我建议您查看GNU Make手册一节中的示例。这就解释了这样的事情:

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)))
release:$(bin_dir)/rel/MainTest.exe
调试:cc_标志+=-Yd-ZI
调试:$(bin_dir)/dbg/MainTest.exe
定义模板=
#从所有对象文件生成TwoDee.exe。
$(bin_dir)/$(cfg_dir)/MainTest.exe:$(obj)
$$(方向盘)
$$(cc)-输出:$$@$(obj)-链接
#从相应的cpp文件生成temp目录中的所有对象文件。
$(obj):$(obj_dir)/$(cfg_dir)/%。obj:$(src_dir)/%。cpp
$$(方向盘)
$$(cc)$$(cc_标志)-Fo$(obj_dir)/$(cfg_dir)-c$$<
恩德夫
$(foreach cfg_dir,rel dbg,$(eval$(模板)))

有道理,我将尝试使用eval。你知道为什么我的obj规则不起作用吗,即使我使用了一个非目标特定的变量?我试图使用eval,但它似乎不起作用。有什么方法可以调试它吗?您应该列出您的模式规则应用于的所有文件:prepend
$(obj):
如我前面所做的那样应用于该规则。还要确保不要将
src_dir
source_dir
混合使用。通过这些修改,并调整gcc及其不同的选项,事情对我来说是可行的。好吧,如果你把
src\u dir
/
source\u dir
混音整理好,就不需要
$(obj):
。您可以使用模式规则而不是模式规则。但是错误消息对于静态模式规则更有用。请参阅以进行比较。@payala:建议两者都可以使用,
=
而不是
:=
使延迟计算更加明确。
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)))