关于makefile中的执行顺序

问题描述 投票:0回答:1

在此Makefile中:

ifeq ($(shell uname),Darwin)
    LDFLAGS := -Wl,-dead_strip
else
    LDFLAGS := -Wl,--gc-sections -lpthread -ldl
endif

all: target/double
    target/double

target:
    mkdir -p $@

target/double: target/main.o target/debug/libdouble_input.a
    $(CC) -o $@ $^ $(LDFLAGS)

target/debug/libdouble_input.a: src/lib.rs Cargo.toml
    cargo build

target/main.o: src/main.c | target
    $(CC) -o $@ -c $<

clean:
    rm -rf target

当我执行make all时,得到以下输出:

hello_c_use_rust [master] ⚡  make all
mkdir -p target
cc -o target/main.o -c src/main.c
cargo build
   Compiling hello_c_use_rust v0.1.0 (/Users/jelly/code/own/hello_rust/hello_c_use_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.20s
cc -o target/double target/main.o target/debug/libdouble_input.a -Wl,-dead_strip
target/double
4 * 2 = 8

请告诉我为什么这是执行顺序? txs ^ _ ^。让我感到困惑的是,为什么第一步是mkdir -p target;

makefile
1个回答
0
投票

您的目标是allall取决于target/double,因此必须首先完成。反过来,target/double取决于target/main.otarget/debug/libdouble_input.a。因此,必须先完成target/main.otarget/debug/libdouble_input.a。在这里,您很幸运(我们稍后将说明原因):首先尝试构建target/main.o。由于target/main.o具有target作为仅订购的先决条件(|符号开始列出仅订购的先决条件),因此必须首先完成target。 Qed。

为什么会这样?因为如果target/main.o目录尚不存在,则无法构建target。构建将完全失败。因此,仅订购的先决条件告诉make必须首先存在目录。因为它是仅订购的先决条件,而不是常规先决条件,所以make只注意其存在。它会忽略其上次修改时间,这很好,因为目录的上次修改时间通常与构建过程无关。

你为什么幸运?因为如果make首先尝试构建target/debug/libdouble_input.a,并且cargo build没有创建目标目录,则它将失败。即使您知道首先构建了target/main.o,也不应依靠它。有一天或另一天,有人可能会尝试使用并行make(make -j),但可能会出错。

确实target/debug/libdouble_input.a并没有target/debug作为仅订购的先决条件。因此,make将执行其配方(cargo build)而无需创建第一个target/debug。并且,如果cargo build不处理此操作,则它将失败。即使您知道cargo build负责创建目标目录,也最好将其添加到Makefile中。以防万一某天或另一天发生变化。并向Makefile的读者显示您知道自己在做什么:

target target/debug:
    mkdir -p $@

target/debug/libdouble_input.a: src/lib.rs Cargo.toml | target/debug
    cargo build

这没什么大不了,可以为您节省一些错误。

© www.soinside.com 2019 - 2024. All rights reserved.