在Makefile中,如何防止虚假先决条件包含在$^

在Makefile中,如何防止虚假先决条件包含在$^,makefile,Makefile,我有一个先决条件,我需要为一个目标声明,在我尝试构建目标之前,该目标需要始终运行。它实际上并不生成文件。问题是,如果我将其声明为目标本身的第一个依赖项,那么虚假的依赖项将在$^中结束,并混淆后续的链接步骤 以下是一个例子: .PHONY: start sample-prog-1 : start sample-prog-1.o 在其他地方,我有一个从对象文件构建可执行文件的规则: %: %.o echo "Building executable $@";$(CC)

我有一个先决条件,我需要为一个目标声明,在我尝试构建目标之前,该目标需要始终运行。它实际上并不生成文件。问题是,如果我将其声明为目标本身的第一个依赖项,那么虚假的依赖项将在$^中结束,并混淆后续的链接步骤

以下是一个例子:

    .PHONY: start
    sample-prog-1 : start sample-prog-1.o
在其他地方,我有一个从对象文件构建可执行文件的规则:

%: %.o
        echo "Building executable $@";$(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ $(LDFLAGS_$@)
问题是,“开始”是一个虚假的目标,所以它不存在,但链接阶段被称为“开始”作为一个对象文件,所以构建过程嘎嘎作响

我找到了一个解决方法,就是从对象文件列表中删除“开始”:

%: %.o
    echo "Building executable $@";$(CC) $(LDFLAGS) $(shell echo "$^" | sed s/start//g) $(LOADLIBES) $(LDLIBS) -o $@ $(LDFLAGS_$@)
$(CC) $(LDFLAGS) $(filter %.o $^) $(LOADLIBES) $(LDLIBS) -o $@ 
但是除了看起来非常粗糙和丑陋之外,这也意味着我不能有任何包含“开始”的源文件。我也总是重新构建sample-prog-1,因为“begin”总是被重新制作

这似乎是一个错误的解决方案,但我不知道什么是“正确”的方法。我想我应该做一些事情,用这样的东西来分解可执行文件:

    sample-prog-1 : sample-prog-1.o
    do_sample-prog-1 : start sample-prog-1

但是这是不直观的,因为现在如果我想建立一个给定的目标,我必须记住,在目标代码的前面加上或附加一些其他字符串,以便在可执行文件建立之前运行起始代码。


除其他事项外,仅订购的先决条件不会出现在
$^

中。您可以将虚假目标放在.o目标之后,然后使用
$第一种方法很好,只要目标不需要多个对象文件。第二种是有效的,只是有点笨拙+1在某些情况下,我有多个对象文件,因此必须使用第二种方法。这只是我尝试过的东西的一个较短版本,我认为它的问题仍然是,它仍将尝试重新构建可执行文件,即使它不需要,因为它认为开始已更改。奇怪的是,make并没有首先运行我的订单,尽管我不确定它如何知道它可以摆脱这个问题。但它确实会弄乱输出,因为现在我看到一些东西在我回显正在启动的编译的细节之前编译,这是start所做的一件事。如果你想在构建某个东西之前运行一个prereq,它需要是该东西的一个prereq。在本例中,
start
不是.o文件的预请求,因此可以首先生成.o文件(如果使用-j,则可以同时生成)。当前暗示的唯一顺序是
start
在链接步骤之前运行。
sample-prog-1 : sample-prog-1.o start

%: %.o
        echo "Building executable $@";$(CC) $(LDFLAGS) $< $(LOADLIBES) $(LDLIBS) -o $@ $(LDFLAGS_$@)
$(CC) $(LDFLAGS) $(filter %.o $^) $(LOADLIBES) $(LDLIBS) -o $@