简体   繁体   English

如何生成多行构建命令?

[英]How can I generate multi-line build commands?

In SCons, my command generators create ridiculously long command lines. 在SCons中,我的命令生成器创建了可笑的长命令行。 I'd like to be able to split these commands across multiple lines for readability in the build log. 我希望能够在多行中拆分这些命令,以便在构建日志中提供可读性。

eg I have a SConscipt like: 例如,我有一个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)

When it executes, I get: 当它执行时,我得到:

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.

Doing this in the python shell with os.system and os.popen works -- I get a readable command string and the sub-shell process interprets all the lines as one command. 使用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

When I do this in SCons, it executes each line one at a time, which is not what I want. 当我在SCons中执行此操作时,它一次执行一行,这不是我想要的。

I also want to avoid building up my commands into a shell-script and then executing the shell script, because that will create string escaping madness. 我还想避免将我的命令构建到shell脚本然后执行shell脚本,因为这将创建字符串转义疯狂。

Is this possible? 这可能吗?

UPDATE: 更新:
cournape, cournape,
Thanks for the clue about the $CCCOMSTR. 感谢关于$ CCCOMSTR的线索。 Unfortunately, I'm not using any of the languages that SCons supports out of the box, so I'm creating my own command generator. 不幸的是,我没有使用SCons开箱即用的任何语言,所以我正在创建自己的命令生成器。 Using a generator, how can I get SCons to do: 使用生成器,我如何让SCons做:

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

but print 但打印

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

?

Thanks to cournape's tip about Actions versus Generators ( and eclipse pydev debugger), I've finally figured out what I need to do. 感谢cournape关于动作与生成器(以及eclipse pydev调试器)的提示,我终于找到了我需要做的事情。 You want to pass in your function to the 'Builder' class as an 'action' not a 'generator'. 您希望将函数作为“动作”传递给“构建器”类,而不是“生成器”。 This will allow you to actually execute the os.system or os.popen call directly. 这将允许您直接执行os.system或os.popen调用。 Here's the updated code: 这是更新的代码:

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())

This SConstruct file will produce the following output: 此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.

The other crucial piece is to remember that switching from a 'generator' to an 'action' means the target you're building no longer has an implicit dependency on the actual string that you are passing to the sub-process shell. 另一个关键部分是要记住,从'generator'切换到'action'意味着你正在构建的目标不再对你传递给子进程shell的实际字符串有一个隐式依赖。 You can re-create this dependency by adding the string into your environment. 您可以通过将字符串添加到环境中来重新创建此依赖关系。

eg, the solution that I personally want looks like: 例如,我个人想要的解决方案如下:

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())

You are mixing two totally different things: the command to be executed, and its representation in the command line. 您正在混合两个完全不同的东西:要执行的命令,以及它在命令行中的表示。 By default, scons prints the command line, but if you split the command line, you are changing the commands executed. 默认情况下,scons打印命令行,但如果拆分命令行,则更改执行的命令。

Now, scons has a mechanism to change the printed commands. 现在,scons有一个改变打印命令的机制。 They are registered per Action instances, and many default ones are available: 它们是根据Action实例注册的,并且有许多默认实例:

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

Will print, assuming only C and CXX sources: 将打印,假设只有C和CXX来源:

CC    foo.c
CC    bla.c
CXX   yo.cc
LINK  yo.o bla.o foo.o

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM