Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Makefile 定义;如果出现错误,则继续“;直接在目标依赖项中使用策略_Makefile_Gnu Make - Fatal编程技术网

Makefile 定义;如果出现错误,则继续“;直接在目标依赖项中使用策略

Makefile 定义;如果出现错误,则继续“;直接在目标依赖项中使用策略,makefile,gnu-make,Makefile,Gnu Make,下面是一个简单的Makefile,它有4个目标(a、b、c和all)。目标b可能失败(此处用退出1表示) 运行make all时,c永远不会打印,因为b失败,因此目标c不会运行。但在我的特殊情况下,我希望运行c,即使b失败 我想知道是否有一种方法可以直接在targetall的依赖项中定义“如果出错则继续”策略 我知道可以通过以下方式达到预期的行为: 运行make-i all(--忽略错误)或make-k all(--继续运行) 使用 在b中用-作为失败命令的前缀(如-退出1) 使用单独运行任务

下面是一个简单的Makefile,它有4个目标(
a
b
c
all
)。目标
b
可能失败(此处用
退出1
表示)

运行
make all
时,
c
永远不会打印,因为
b
失败,因此目标
c
不会运行。但在我的特殊情况下,我希望运行
c
,即使
b
失败

我想知道是否有一种方法可以直接在target
all
的依赖项中定义“如果出错则继续”策略

我知道可以通过以下方式达到预期的行为:

  • 运行
    make-i all
    --忽略错误
    )或
    make-k all
    --继续运行
  • 使用
  • b
    中用
    -
    作为失败命令的前缀(如
    -退出1
  • 使用
    单独运行任务,创建一个;做b | |做c
但所有这些选项都意味着要修改目标
a
b
c
,或者修改调用
make all
的方式

是否有一种方法可以通过修改
all
目标依赖项(类似于
all:a-bc
,但该定义显然不起作用)来实现预期行为


附加要求
make all
如果
b
失败,即使
c
目标成功,也应返回退出代码1。

虽然无法通过先决条件名称传输参数(或者至少只有在完全更改先决条件的情况下),但可以使用特定于目标的变量。但解决方案并不完美,每个配方行前面都有一个额外的变量:

CIE_DASH = $(if $(filter $@,$(CONTINUE_SET)),-)

all: a b c
all: CONTINUE_SET += b

a: 
    $(CIE_DASH)echo "a"

b: CONTINUE_SET += e
b: e 
    $(CIE_DASH)exit 1

e:
    $(CIE_DASH)exit 1
c:
    $(CIE_DASH)echo "c"

如果要运行
a、-b、c的所有配方,即使
-
配方失败,也可以对
-
目标使用模式规则:

a c:
    @echo "$@"

b:
    @echo "$@"; exit 1

all: a -b c

-%:
    -@$(MAKE) $*
演示(使用
--无打印目录
,输出更简单):

但如果你还想“记住”他们的退出状态,事情就有点困难了。我们需要将退出状态存储在某个位置,例如在一个文件中,并将其重新用于
all
配方:

a c:
    @echo "$@"

b:
    @echo "$@"; exit 1

all: a -b c
    @exit_status=`cat b_exit_status`; exit $$exit_status

-%:
    -@$(MAKE) $*; echo "$$?" > $*_exit_status
演示:

硬接线
all
配方中潜在失败目标的名称不是很优雅。但这应该很容易解决:

a b c:
    @echo "$@"

d:
    @echo "$@"; exit 1

all: a -b c -d
    @for f in $(patsubst -%,%_exit_status,$(filter -%,$^)); do \
        tmp=`cat $$f`; \
        printf '%s: %s\n' "$$f" "$$tmp"; \
        if [ "$$tmp" -ne 0 ]; then exit $$tmp; fi; \
    done

-%:
    -@$(MAKE) $*; echo "$$?" > $*_exit_status

.PHONY: clean
clean:
    rm -f *_exit_status
演示:


谢谢你的回答。在我的例子中,为什么
exit 1
不是唯一应该以
$(CIE_DASH)
作为前缀的行?因为只有
b
目标才能失败。还有,为什么需要
e
?最后,使用此解决方案,我如何捕获
b
的退出代码并将其传播到
c
(请参阅我问题中的附加要求)?我只需输入
$(CIE_DASH)
出现在所有内容之前,因为您事先不知道某一天是否要将
a
c
添加到
继续设置中<不需要代码>e
,我只是想证明这是一种抑制出错退出的分层方法-编写
all
目标的程序员可能不知道
b
下面发生的事情。传播到
c
是不可能/不可靠的,因为make可以自由决定独立目标的求值顺序。正在传播到顶级规则。。。老实说,我认为这将变得更加丑陋,你不能使用我的解决方案,因为破折号强制忽略返回代码-无法访问它。谢谢你的解释。有了这个想法,它很聪明,在某些情况下可能有用。但在我解释的具体案例中,这个解决方案类似于我的第三点:在
b
中用
-
作为失败命令的前缀(如
-exit 1
),因为我知道在我的示例中只有
b
可以失败。因此,这里不需要使用
CONTINUE\u SET
,也不需要使用
CIE\u DASH
作为所有行的前缀。感谢您给出的详细解释。另一个问题(尽管不相关):如果我当前文件夹中有多个
Makefile
,或者如果我必须将参数传递给
Makefile
,我如何在
$(MAKE)中指定这些参数
call?
make-f VAR1=VALUE1 VAR2=VALUE2…
-f
告诉make要使用的make文件是
,并且
VAR1=VALUE1
用值
VALUE1
定义make变量
VAR1
。我的问题不清楚,对不起,事实上我已经在运行
make-f VAR1=VALUE1=VALUE2
。但是在
Makefile
中运行
$(MAKE)
时,命令run是
MAKE
,没有我用来运行初始
MAKE
的参数。我想知道是否有一种简单的方法可以将这些参数传播到
$(MAKE)
。这是一个非常不同的问题,很难在注释中回答。您可能应该问一个新问题。原始参数不会出现在运行sub make的命令行上。然而,潜艇制造商会知道他们。它们通过其他方式传递。(共享内存?环境变量?谁在乎……如果你在乎,请查看手册。)
a c:
    @echo "$@"

b:
    @echo "$@"; exit 1

all: a -b c
    @exit_status=`cat b_exit_status`; exit $$exit_status

-%:
    -@$(MAKE) $*; echo "$$?" > $*_exit_status
$ make --no-print-directory all
a
b
Makefile:5: recipe for target 'b' failed
make[1]: *** [b] Error 1
c
Makefile:8: recipe for target 'all' failed
make: *** [all] Error 2
a b c:
    @echo "$@"

d:
    @echo "$@"; exit 1

all: a -b c -d
    @for f in $(patsubst -%,%_exit_status,$(filter -%,$^)); do \
        tmp=`cat $$f`; \
        printf '%s: %s\n' "$$f" "$$tmp"; \
        if [ "$$tmp" -ne 0 ]; then exit $$tmp; fi; \
    done

-%:
    -@$(MAKE) $*; echo "$$?" > $*_exit_status

.PHONY: clean
clean:
    rm -f *_exit_status
$ make --no-print-directory all
a
b
c
d
Makefile:5: recipe for target 'd' failed
make[1]: *** [d] Error 1
b_exit_status: 0
d_exit_status: 2
Makefile:8: recipe for target 'all' failed
make: *** [all] Error 2