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シェルでこれを行うと、読み取り可能なコマンド文字列が取得され、サブシェルプロセスがすべての行を1つのコマンドとして解釈します。

>>> 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でこれを行うと、各行が一度に1つずつ実行されますが、これは私が望んでいることではありません。

また、コマンドをシェルスクリプトに組み込んでから、シェルスクリプトを実行することは避けたいと思います。これは、文字列をエスケープする狂気を生み出すからです。

これは可能ですか?

更新:
クールナペ、
$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

アクションとジェネレーター (および Eclipse pydev デバッガー) に関する cournape のヒントのおかげで、私は最終的に何をする必要があるかを理解しました。関数を「ジェネレーター」ではなく「アクション」として「ビルダー」クラスに渡したいとします。これにより、実際に 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.

もう 1 つの重要な点は、「ジェネレーター」から「アクション」に切り替えることは、作成しているターゲットが、サブプロセス シェルに渡す実際の文字列に暗黙の依存関係を持たなくなることを意味することを覚えておくことです。環境に文字列を追加することで、この依存関係を再作成できます。

たとえば、私が個人的に望んでいるソリューションは次のようになります。

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

実行するコマンドと、コマンド ラインでのその表現という 2 つのまったく異なるものを混在させています。デフォルトでは、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 に答える