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 无法检测到明显的规则的主要内容,如果未能解决你的问题,请参考以下文章

GNU make规则的命令④书写命令

GNU make:规则专题

GNU Make - 终端规则和关键字“null”

GNU make学习笔记

《GNU_makefile》第五章——为规则书写命令

《GNU_makefile》第五章——为规则书写命令