GNU Make 无法检测到明显的规则
Posted
技术标签:
【中文标题】GNU Make 无法检测到明显的规则【英文标题】:GNU Make can't detect obvious rule 【发布时间】:2017-12-21 22:48:42 【问题描述】:出于某种原因,我从来没有掌握现代编程方法的窍门。作为 68k 汇编程序员,我试图退出使用单个树文件来链接最终文件的所有内容,而是遵循更典型的“构建/链接对象”方案。但是,我花了 4 天时间试图找到一个合乎逻辑的解释并解决这个问题。
我正在尝试自动检测和构建来自某个文件夹的每个文件,其对象被打包到一个特定定义的对象中,该对象与其他特定定义的对象链接在一起。
这是生成文件:https://pastebin.com/H6QE29fj
CUR = $(SRC)\lib
VPATH = $(OBJ) $(CUR)
INPUT = $(notdir $(wildcard $(CUR:\=/)/*))
$(OBJ)\library.md.o: $(INPUT:.asm=.o)
$(VLINK) -r -o $@ $(addprefix $(OBJ)\,$(notdir $^))
问题就在上面。几天前,我使用相同的代码 sn-p 从文件夹 $(SRC)\ints 生成 $(OBJ)\ints.md.o。完全没有问题,我什至在使用 $(INPUT) 变量之前手动添加了一个文件名,因此它在 SECTION 的开头被组装(引擎恶作剧)。
如果所述代码“有效”,为什么它不适用于库?
make: *** No rule to make target `loadtilemap.o', needed by `.\src\__obj\library.md.o'. Stop.
用 %.o: %.asm 规则还不够吗?
【问题讨论】:
【参考方案1】:首先,我建议您在使用 makefile 中的路径时始终使用正斜杠,而不是反斜杠。几乎所有 Windows 命令都将接受路径中的任何一种样式。如果您需要调用不接受正斜杠作为路径分隔符的命令,请在需要的地方转换它们。 make
是一个 UNIX/POSIX 工具,因此它通常使用正斜杠作为目录分隔符和反斜杠作为转义序列。为 Windows 编译时,在反斜杠方面对 DTRT 做了一些努力,但它可能并非在任何地方都有效。只需使用正斜杠并继续其他事情。
这是来自您的 makefile 的提示:
%.o: %.asm
$(V68k) $(BUILDARGS) -L $(LST)\$(notdir $(basename $@)).txt -o $(OBJ)\$@ $<
目标创建除$@
以外的文件(几乎)永远不会正确。这是我的Second Rule of Makefiles。任何时候你看到构造一个不只是简单的文件的规则$@
你就知道有问题。 Make想建立一个目标。它知道要构建什么目标,并将该目标的路径放在$@
变量中。如果您在您的配方中觉得有必要创建一个不完全是 $@
的文件,那么您知道您和 make 在一些基本问题上不同意,并且不同意 make 不会给您结果你想要:)。
如果要在与源目录不同的目录中创建文件,则该目录必须包含在规则中:
$(OBJ)/%.o: %.asm
$(V68k) $(BUILDARGS) -L $(LST)\$(notdir $(basename $@)).txt -o $@ $<
这也意味着您的链接配方:
$(OBJ)\library.md.o: $(INPUT:.asm=.o)
$(VLINK) -r -o $@ $(addprefix $(OBJ)\,$(notdir $^))
行不通。为什么?因为先决条件不包括目录。您需要将其更改为:
$(OBJ)\library.md.o: $(INPUT:%.asm=$(OBJ)/%.o)
$(VLINK) -r -o $@ $^
您可能认为将$(OBJ)
添加到VPATH
将有助于解决此问题,但事实并非如此。 VPATH
不是这样设计的。 VPATH
只能用于搜索 source 文件,不能像目标文件那样生成文件。原因很复杂,但如果您想了解详细信息,请联系detailed explanation here。
【讨论】:
我让它工作了,现在它看起来也好多了。非常感谢! :D以上是关于GNU Make 无法检测到明显的规则的主要内容,如果未能解决你的问题,请参考以下文章