GNU make 3.81 - 如何做'--output-sync=target'

GNU make 3.81 - how to do '--output-sync=target'

本文关键字:target --output-sync 何做 make GNU      更新时间:2023-10-16

最新版本的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

输出非常交错。

AFTER
BEFOREAFTER
AFTER
AFTER

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

我知道,例如,如果有一种方法可以在配方前"锁定 STDOUT 互斥锁"并在配方后释放它,则构建速度可能会受到影响。

如果这是需要的,我可以修改我们的每个目标。

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

%.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

这不会完全防止交错,因为如果您有多个 CPU,则可以并行运行多个cat命令,但它应该会显着降低概率。如果您真的想完全避免交错,则必须在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

解释:

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