1

我的Makefile:

CC=cc
INC=-I.
CFLAGS=-g  -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN
LDFLAGS=-ldl
OBJS=*.o
OBJDIR=.obj
BINDIR=.obj
LIBDIR=.obj

%.o: %.c
        $(CC) $(INC) $(CFLAGS) -DSFHASH -o $(OBJDIR)/$@ -c $<


VPATH = .obj
#vpath %.o $(OBJDIR)

hashtest: hashfuncs.o hast.o scanners.o parseargs.o
        $(CC) -rdynamic -o $(BINDIR)/$@ $^ $(LDFLAGS)

clean:
        @rm -f $(OBJDIR)/$(OBJS) $(BINDIR)/hashtest

第一次使用它:make 不会重写 gcc 的输入文件路径:

@delphi# make clean
@delphi# make
cc -I. -g  -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN -DSFHASH -o .obj/hashfuncs.o -c hashfuncs.c
cc -I. -g  -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN -DSFHASH -o .obj/hast.o -c hast.c
cc -I. -g  -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN -DSFHASH -o .obj/scanners.o -c scanners.c
cc -I. -g  -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN -DSFHASH -o .obj/parseargs.o -c parseargs.c
cc -rdynamic -o .obj/hashtest hashfuncs.o hast.o scanners.o parseargs.o -ldl
cc: error: hashfuncs.o: No such file or directory
cc: error: hast.o: No such file or directory
cc: error: scanners.o: No such file or directory
cc: error: parseargs.o: No such file or directory
make: *** [hashtest] Error 1

连续第二次使用它,它确实:

@delphi# make
cc -rdynamic -o .obj/hashtest .obj/hashfuncs.o .obj/hast.o .obj/scanners.o .obj/parseargs.o -ldl
@delphi# 

GNU Make 手册说:

make 变量 VPATH 的值指定了 make 应该搜索的目录列表。大多数情况下,目录应该包含不在当前目录中的必备文件;但是,make 使用 VPATH 作为先决条件和 *规则目标* 的搜索列表。

我会理解 VPATH 是否是一个在启动时设置一次的类型变量,但它不是。正确查找在运行时生成的目标依赖项这一事实说明了这一点。

那是怎么回事?为什么 make 仅第二次正确重写 gcc 的输入文件路径?

4

2 回答 2

2
Subject: Re: (un)expected make behavior while using VPATH
From: mad scientist

<<< %.o: %.c

<<< $(CC) $(INC) $(CFLAGS) -DSFHASH -o $(OBJDIR)/$@ -c $<

这是一个无效的规则。它违反了我的“makefile 规则”之一:

http://make.mad-scientist.net/rules.html

<<< 第一次使用:make不会重写gcc的输入文件路径:

<<< 连续第二次使用它,它确实:

经典的。不要难过,这就是每个人一开始都会做的事情。这很可能表明 VPATH 设计错误(或者需要其他一些工具)。然而,那是另一个对话。这可能会有所帮助:

http://make.mad-scientist.net/vpath.html

干杯!

来自 help-make ml,线程http://lists.gnu.org/archive/html/help-make/2012-11/msg00018.html

于 2012-11-14T07:50:52.903 回答
1

可以在GNU Make 手册的第 3.7 节中找到对此行为的解释:

3.7 make 如何读取 Makefile

GNU make 在两个不同的阶段完成它的工作。在第一阶段,它读取所有的 makefile、包含的 makefile 等,并内化所有变量及其值、隐式和显式规则,并构建所有目标及其先决条件的依赖图。

在第二阶段,make 使用这些内部结构来确定需要重建哪些目标并调用必要的规则来这样做。

make首次运行时,.obj目录中的先决条件尚不存在。这意味着它们不会成为第一阶段创建的依赖关系图的一部分。因此,在执行创建规则时,在第二阶段不会使用这些先决条件hashtest——即使由于之前在第二阶段执行的规则,它们在那时已经存在。

当您make第二次运行时,这些先决条件确实存在,并通过VPATH设置找到并包含在依赖关系图中。

请注意,其中的表达式VPATH只是一个搜索路径,此而已。它可以包含多个目录名称,以冒号分隔。make在第一阶段构建依赖图时,将在该搜索路径中搜索先决条件和目标。如果它在该搜索列表中的目录中找到特定目标,则该目标将作为现有文件添加到依赖关系图中,该文件可能已过期,也可能不会过期。

您似乎期望make将子目录从添加VPATH到目标,即使该目标在该子目录中不存在并且需要创建。这不是它的工作方式——在这种情况下如何make处理多个目录VPATH

于 2012-11-13T17:22:25.013 回答