3

在 SCons 中,我的命令生成器创建了非常长的命令行。我希望能够将这些命令拆分为多行,以便在构建日志中阅读。

例如,我有一个 SConscipt,例如:

import os

# create dependency
def my_cmd_generator(source, target, env, for_signature):
    return r'''echo its a small world after all \
        its a small world after all'''

my_cmd_builder = Builder(generator=my_cmd_generator, suffix = '.foo')

env = Environment()
env.Append( BUILDERS = {'MyCmd' : my_cmd_builder } )

my_cmd = env.MyCmd('foo.foo',os.popen('which bash').read().strip())
AlwaysBuild(my_cmd)

当它执行时,我得到:

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
echo its a small world after all \
its a small world after all
its a small world after all
sh: line 1: its: command not found
scons: *** [foo.foo] Error 127
scons: building terminated because of errors.

在带有 os.system 和 os.popen 的 python shell 中执行此操作——我得到一个可读的命令字符串,并且子 shell 进程将所有行解释为一个命令。

>>> import os
>>> cmd = r'''echo its a small world after all \
... its a small world after all'''
>>> print cmd
echo its a small world after all \
its a small world after all
>>> os.system( cmd)
its a small world after all its a small world after all
0

当我在 SCons 中执行此操作时,它一次执行每一行,这不是我想要的。

我还想避免将我的命令构建到 shell 脚本中,然后执行 shell 脚本,因为这会造成字符串转义的疯狂。

这可能吗?

更新:
cournape,
感谢您提供有关 $CCCOMSTR 的线索。不幸的是,我没有使用 SCons 开箱即用支持的任何语言,所以我正在创建自己的命令生成器。使用生成器,我怎样才能让 SCons 去做:

echo its a small world after all its a small world after all' 

但打印

echo its a small world after all \
    its a small world after all

?

4

2 回答 2

3

感谢 cournape 关于动作与生成器(和 eclipse pydev 调试器)的提示,我终于弄清楚了我需要做什么。您想将函数作为“操作”而不是“生成器”传递给“生成器”类。这将允许您直接执行 os.system 或 os.popen 调用。这是更新的代码:

import os

def my_action(source, target, env):
    cmd = r'''echo its a small world after all \
        its a small world after all'''
    print cmd
    return os.system(cmd)

my_cmd_builder = Builder(
    action=my_action,  # <-- CRUCIAL PIECE OF SOLUTION
    suffix = '.foo')

env = Environment()
env.Append( BUILDERS = {'MyCmd' : my_cmd_builder } )

my_cmd = env.MyCmd('foo.foo',os.popen('which bash').read().strip())

此 SConstruct 文件将产生以下输出:

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
my_action(["foo.foo"], ["/bin/bash"])
echo its a small world after all \
        its a small world after all
its a small world after all its a small world after all
scons: done building targets.

另一个关键部分是要记住,从“生成器”切换到“动作”意味着您正在构建的目标不再隐含依赖于您传递给子流程外壳的实际字符串。您可以通过将字符串添加到您的环境中来重新创建此依赖项。

例如,我个人想要的解决方案如下:

import os

cmd = r'''echo its a small world after all \
        its a small world after all'''

def my_action(source, target, env):
    print cmd
    return os.system(cmd)

my_cmd_builder = Builder(
    action=my_action,
    suffix = '.foo')

env = Environment()
env['_MY_CMD'] = cmd  # <-- CREATE IMPLICIT DEPENDENCY ON CMD STRING
env.Append( BUILDERS = {'MyCmd' : my_cmd_builder } )

my_cmd = env.MyCmd('foo.foo',os.popen('which bash').read().strip())
于 2009-02-06T19:24:02.457 回答
1

您正在混合两种完全不同的东西:要执行的命令及其在命令行中的表示。默认情况下,scons 会打印命令行,但如果拆分命令行,则会更改执行的命令。

现在,scons 有一种机制来更改打印的命令。它们是按 Action 实例注册的,并且有许多默认的可用实例:

env = Environment()
env['CCCOMSTR']  = "CC                 $SOURCE"
env['CXXCOMSTR'] = "CXX                $SOURCE"
env['LINKCOM']   = "LINK               $SOURCE"

将打印,假设只有 C 和 CXX 源:

CC    foo.c
CC    bla.c
CXX   yo.cc
LINK  yo.o bla.o foo.o
于 2009-02-04T10:49:13.343 回答