题
在一个 最近一期, ,我发现DJGPP只能接受DOS命令行字符限制。为了解决这个限制,我决定尝试编写一个 makefile 以允许我 传递更长的字符串. 。在编写 makefile 并对其进行测试的过程中,我遇到了一个奇怪的错误。生成文件如下:
AS := nasm
CC := gcc
LD := ld
TARGET := $(shell basename $(CURDIR))
BUILD := build
SOURCES := source
CFLAGS := -Wall -O -fstrength-reduce -fomit-frame-pointer -finline-functions \
-nostdinc -fno-builtin -I./include
ASFLAGS := -f aout
export OUTPUT := $(CURDIR)/$(TARGET)
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
SOBJS := $(SFILES:.s=.o)
COBJS := $(CFILES:.c=.o)
OBJS := $(SOBJS) $(COBJS)
build : $(TARGET).img
$(TARGET).img : $(TARGET).bin
concat.py
$(TARGET).bin : $(OBJS)
$(LD) -T link.ld -o $@ $^
$(SOBJS) : %.o : %.asm
$(AS) $(ASFLAGS) $< -o $@
$(COBJS) : %.o : %.c
$(CC) -c $< $(CFLAGS) -o $@
当尝试运行它时,我收到此错误:
make: *** No rule to make target `consoleio.c', needed by `consoleio.o'. Stop.
我不明白的是为什么它试图找到 .c 文件的规则。据我了解,如果该文件存在,就应该使用它。如何使 make 不需要 .c 文件的规则?
解决方案
如果没有 VPATH,您尝试做的事情将无法工作,并且由于您仍在学习 makefile,因此我会避免使用 VPATH。
该规则正在寻找“consoleio.c”,如果我正确理解你的makefile,它不存在;存在的是“source/consoleio.c”。您可能应该将其更改为“$(SOURCES)/%.c”而不是“%c”。
但是,我没有检查您的语法是否符合该规则。如果不正确,内置的“%.o:将使用 %.c" 规则来代替,这会出现同样的问题。
然而,你所做的方式并不是我所见过的通常的方式。通常的方法是:
- 创建隐式规则“%.o:%.c”(或者在你的情况下为“%.o:$(来源)/%.c")
- 显式列出每个文件的依赖关系:“foo.o:foo.c bar.h baz.h"(没有命令,隐式规则有命令)
其他提示
让我们尝试一个非评论答案......
可能性A:
- 您的 SFILES 宏正在查找以 ' 结尾的文件
.s
'. - 您编译 SOBJS 的规则是查找以 ' 结尾的文件
.asm
'.
可能性B:
- 您对 SOBJS 和 COBJS 的规则采用了我不认识的符号。
根据 GNU Make 手册,您可以将隐式规则编写为:
%.o:%。C ; 命令
您似乎有一个目标列表 $(SOBJS) 取决于 '%.o : %.asm
'。我不确定 make 将如何解释它。
就我个人而言,我不相信构建规则中的通配符。我宁愿花时间准确列出构建代码所需的源文件。因此,我并不经常遇到这个问题。
@CesarB似乎已经解决了这个问题,我只想补充几点意见。
-
我强烈建议不要在构建规则中使用通配符。构建规则应该明确定义正在构建的内容,而不是依赖于目录中的文件。
-
我还建议不要使用VPATH,除非您(1)在单独的构建目录中构建,或者(2)将源文件分布在大量目录中。如果所有源都在一个目录中,那么使用VPATH只会让人感到困惑。
-
:=赋值表通常仅在已知变量评估需要很长时间时使用,例如使用$(shell ...)时。否则,<!> quot; = <!> quot;是喜欢的。
-
使用<!> quot; export <!> quot;将OUTDIR传播到concat.py(我认为它是,因为concat.py不接受任何参数)是代码气味。如果可能,请将其作为参数传递。
醇>