scons专家 -
Scons认为这个失败的命令成功,而另一个时间运行scons表示所有目标都是最新的。 fribbleblat
命令不存在。当管道中的“中间”命令失败时,会发生此行为,但是当管道中的最后一个命令失败时,则会发生此行为。
如何将管道命令中的错误传播到scons?
import os
from SCons.Script import Environment
env = Environment()
env.Command(source='foo',
target='bar',
action='cat $SOURCE | fribbleblat | cat >$TARGET')
运行两次表明scons认为它已正确构建了目标
[编辑:我创建了一个包含随机内容的文件'foo',echo dslkfjds >foo
]
$ scons -f SConstruct.exp
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cat foo | fribbleblat | cat > bar
sh: 1: fribbleblat: not found
cat: write error: Broken pipe
scons: done building targets.
$ scons -f SConstruct.exp
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
$ scons --version
SCons by Steven Knight et al.:
script: v2.3.0.rel_2.3.0:2870:c8dbbaa4598e, 2013/07/31 13:02:49, by bdbaddog on Williams-MacBook
engine: v2.3.0, 2013/03/03 09:48:35, by garyo on reepicheep
engine path: ['/usr/lib/scons/SCons']
Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 The SCons Foundation
答案 0 :(得分:2)
你的假设是错误的:它不是认为命令成功的SCons。在我的Linux系统上命令
> cat test.txt | fribblecat | cat > out.txt
产生" fribblecat:命令未找到。"
> echo $?
给出" 0" (成功)结果。因此shell打开输出文件,并向SCons发出成功信号。您必须找到一种方法让管道序列在shell级别失败,例如通过将命令包装在一个shell脚本中来检查可执行文件" fribblecat"实际存在。 另一种选择是写一个简单的" fribblecat"构建器,假设可执行文件支持输入和输出文件的命令行选项:
env = Environment()
env.Command('out.txt','test.txt','fribblecat -o $TARGET $SOURCE')
查看UserGuide" 18。编写自己的建筑商" (http://www.scons.org/doc/production/HTML/scons-user.html),以及我们在http://www.scons.org/wiki/ToolsForFools撰写工具的指南。
答案 1 :(得分:2)
dirkbaechle是对的 - 事实证明这不是一个scons问题,而是一个shell问题。再多一点搜索,我得到了以下答案:
简短回答是'set -o pipefail',但这只适用于bash
,ksh
和zsh
,但不适用于sh
,所以我有确保scons也在调用bash
。
以下scons文件按预期工作并捕获失败的命令。
import os
from SCons.Script import Environment
env = Environment()
env['SHELL'] = 'bash'
env['ENV']['SHELLOPTS'] = 'pipefail'
env.Command(source='foo',
target='bar',
action='cat $SOURCE | fribbleblat | cat >$TARGET')