GNU make 3.81 - 怎么做'--output-sync = target'

Bob*_*Bob 7 c++ makefile gnu-make

最新版本make有一个选项--output-sync,可以使每个目标的STDOUT成为原子,以便在使用时不会交错多个目标的语句make --jobs=N

不幸的是,我必须使用,make v 3.81因为这是我们的SDK附带的那个.

为了确定我是否需要--output-sync,我在目标周围添加了一些"保护声明"

all: $(patsubst %.cpp, %.o, $(wildcard *.cpp))


%.o: %.cpp  
    @echo BEFORE
    @echo MAKEFLAGS=$(MAKEFLAGS)
    qcc.exe $(CC_FLAGS) $@ $< 
    @echo AFTER
Run Code Online (Sandbox Code Playgroud)

输出非常交错.

AFTER
BEFOREAFTER
AFTER
AFTER
Run Code Online (Sandbox Code Playgroud)

有没有办法模拟--output-sync功能?

据我所知,如果有一种方法可以"锁定STDOUT mutex"预配方并在配方后释放它,那么构建速度可能会受到影响.

我很好修改我们的每个目标,如果这是它需要的.

Ren*_*let 0

您可以将配方的所有输出记录在临时文件中,并在最后删除它:

%.o: %.cpp
    @d=$$(mktemp) && \
    echo BEFORE >> $$d 2>&1 && \
    echo MAKEFLAGS=$(MAKEFLAGS) >> $$d 2>&1 && \
    qcc.exe $(CC_FLAGS) $@ $< >> $$d 2>&1 && \
    echo AFTER >> $$d 2>&1 && \
    cat $$d && \
    rm $$d
Run Code Online (Sandbox Code Playgroud)

这不会完全防止交错,因为cat如果您有多个 CPU,则可以并行运行多个命令,但它应该会显着降低概率。如果您确实想完全避免交错,则必须在cat命令周围添加自旋锁。在 GNU/Linux 操作系统下,您可以查看flock,例如:

%.o: %.cpp
    @d=$$(mktemp) && \
    echo BEFORE >> $$d 2>&1 && \
    echo MAKEFLAGS=$(MAKEFLAGS) >> $$d 2>&1 && \
    qcc.exe $(CC_FLAGS) $@ $< >> $$d 2>&1 && \
    echo AFTER >> $$d 2>&1 && \
    flock /tmp/my-lock-file cat $$d && \
    rm $$d
Run Code Online (Sandbox Code Playgroud)

说明:

  • 我在单个 shell 调用中转换了您的配方(make 配方中的每一行都在不同的 shell 中执行),以便dshell 变量在列表中的所有命令中都可用。
  • 这些命令使用&&运算符链接起来:如果其中一个失败,则整个列表都会失败并具有相同的退出状态,并且 make 会告诉您这一点。
  • 我没有将所有命令放在同一行,这样很快就会变得不可读,\而是在除最后一行之外的所有行尾之前添加。更具可读性,但仍被 make 解释为单行。
  • 列表中的第一个命令 ( mktemp) 自动创建一个唯一的临时文件。使用您环境中可用的任何等效项。$注意中的双倍d=$$(mktemp)。需要通过 make 传递第一个扩展,并d=$(mktemp)在传递到 shell 时变为。与 shell 变量的 shell 扩展相同d$$d首先由 make 扩展,就像$d传递到 shell 之前一样。
  • 命令输出的重定向(>> $d 2>&1在第一次通过 make 扩展之后)将标准输出重定向到附加模式 ( >> $d) 中的临时文件,并使标准错误描述符成为标准输出描述符 ( 2>&1) 的副本,其效果还附加了标准错误到同一个临时文件。

  • @Adrian是的,它在我正在使用的集群系统上,我对此无能为力。 (4认同)