我尝试使用make将目标文件放置在单独的子目录中时遇到了问题,这可能是一种非常基本的技术。我已经尝试使用此页面中的信息: http://www.gnu.org/software/hello/manual/make/Prerequisite-Types.html#Prerequisite-Types
运行make后,我得到了以下输出:
make: *** No rule to make target `ku.h', needed by `obj/kumain.o'. Stop.
然而,ku.h是一个依赖项,而不是一个目标(尽管它显然被包含在C源文件中)。当我不试图使用子目录来存储对象文件(即省略OBJDIR部分)时,它可以正常工作。为什么make会把ku.h视为目标?我的makefile如下:(这种风格是在阅读各种信息源后得出的)
.SUFFIXES:
.SUFFIXES: .c .o
CC=gcc
CPPFLAGS=-Wall
LDLIBS=-lhpdf
VPATH=%.c src
VPATH=%.h src
VPATH=%.o obj
OBJDIR=obj
objects= $(addprefix $(OBJDIR)/, kumain.o kudlx.o kusolvesk.o kugetpuz.o kuutils.o \
kurand.o kuASCboard.o kuPDFs.o kupuzstrings.o kugensud.o \
kushapes.o )
ku : $(objects)
$(CC) $(CPPFLAGS) -o ku $(objects) $(LDLIBS)
$(objects) : ku.h kudefines.h kuglobals.h kufns.h | $(OBJDIR)
$(OBJDIR):
mkdir $(OBJDIR)
.PHONY: clean
clean :
rm $(objects)
编辑: 我已经应用了使用vpath指令的更改。我的版本是VPATH=xxx和vpath %.c xxx的糟糕混合体。但是,现在我遇到另一个问题(在添加错误的vpath之前是原始问题)。以下是现在的输出:
gcc -o ku -lhpdf obj/kumain.o obj/kudlx.o obj/kusolvesk.o ..etc
gcc: obj/kumain.o: No such file or directory
gcc: obj/kudlx.o: No such file or directory
gcc: obj/kusolvesk.o: No such file or directory
gcc: obj/kugetpuz.o: No such file or directory
gcc: obj/kuutils.o: No such file or directory
gcc: obj/kurand.o: No such file or directory
gcc: obj/kuASCboard.o: No such file or directory
gcc: obj/kuPDFs.o: No such file or directory
gcc: obj/kupuzstrings.o: No such file or directory
gcc: obj/kugensud.o: No such file or directory
gcc: obj/kushapes.o: No such file or directory
make: *** [ku] Error 1
看起来 make 没有应用对象文件的隐式规则,尽管手册上说:“隐式规则告诉 make 如何使用常规技术,这样当您想要使用它们时,您就不必详细指定它们。例如,C 编译有一个隐式规则。文件名确定运行哪些隐式规则。例如,C 编译通常需要一个 .c 文件并生成一个 .o 文件。因此,当 make 看到这种文件名后缀组合时,会应用 C 编译的隐式规则。” 以及 “在考虑隐式规则时,make 还会在 VPATH 中指定的目录或使用 vpath 指定的目录中搜索(请参阅使用隐式规则)。”同样,在这里,“例如,当文件 foo.o 没有显式规则时,make 会考虑隐式规则,例如编译 foo.c 的内置规则(如果该文件存在)。如果当前目录中缺少这样的文件,则会在适当的目录中搜索它。如果 foo.c 存在(或在任何目录中被 makefile 提及),则应用 C 编译的隐式规则。”
如何使隐式规则在我的 makefile 中工作,任何帮助都将不胜感激。
修改2: 由于我无法使用隐式规则,所以感谢 Jack Kelly 我已经制定了显式规则来编译 .c 文件。也感谢 al_miro 提供的 vpath 信息。
这是有效的 makefile:
.SUFFIXES:
.SUFFIXES: .c .o
CC=gcc
CPPFLAGS=-Wall
LDLIBS=-lhpdf
OBJDIR=obj
vpath %.c src
vpath %.h src
objects = $(addprefix $(OBJDIR)/, kumain.o kudlx.o kusolvesk.o kugetpuz.o kuutils.o \
kurand.o kuASCboard.o kuPDFs.o kupuzstrings.o kugensud.o \
kushapes.o )
ku : $(objects)
$(CC) $(CPPFLAGS) -o ku $(objects) $(LDLIBS)
$(OBJDIR) obj/%.o : %.c ku.h kudefines.h kuglobals.h kufns.h
$(CC) -c $(CPPFLAGS) $< -o $@
.PHONY : clean
clean :
rm $(objects)
$(CPPFLAGS)
通常用于 C 预处理器标志,而$(CFLAGS)
用于编译器的标志。 - Jack Kelly