3

ソース コードとマークダウン ドキュメントを含むテキスト ファイルを使用してドキュメントを構築するためのツールを使用するカスタム ビルダーがあります。

このツールは、すべての入力ファイルと出力オプションを指定する構成ファイルを受け取ります。

実行すると、html というラベルの付いたフォルダーにドキュメントが作成されます。

私のビルダーには、すべての入力ファイルを見つけるためのスキャナーがあります

出力ディレクトリを設定するためのエミッター。

スキャナーとエミッターは、必要なすべてのファイルを見つけます。ただし、再構築すると、入力ファイルの変更が検出されません。

問題を再現するビルダーを作成し、以下を単一のディレクトリに配置しました。

gen_doc.py

import SCons.Builder
import os
import ConfigParser

def _doc_build_function(target, source, env):
    #print '***** Builder *****'
    config = ConfigParser.SafeConfigParser()
    try:
        fp = open(str(source[0]), 'r')
        config.readfp(fp)
    finally:
        fp.close()
    output_dir = ''
    if config.has_option('output_options', 'output_dir'):
        output_dir = config.get('output_options', 'output_dir')
    input_files = []
    if config.has_option('input_options', 'input'):
         input_files = config.get('input_options', 'input').split()
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    with open(output_dir + os.sep + 'index.html', 'wb') as out_file:
        for file in input_files:
            try:
                in_file = open(file, 'r')
                out_file.write(in_file.read())
            finally:
                in_file.close()


def _doc_scanner(node, env, path):
    source = []
    config = ConfigParser.SafeConfigParser()
    try:
        fp = open(str(node), 'r')
        config.readfp(fp)
    finally:
        fp.close()
    if config.has_option('input_options', 'input'):
        for i in config.get('input_options', 'input').split():
            source.append(os.path.abspath(i))
    return source

def _doc_emitter(target, source, env):
    target = []
    config = ConfigParser.SafeConfigParser()
    try:
        fp = open(str(source[0]), 'r')
        config.readfp(fp)
    finally:
        fp.close()
    if config.has_option('output_options', 'output_dir'):
        target.append(env.Dir(os.path.abspath(config.get('output_options', 'output_dir'))))
        env.Clean(source, env.Dir(os.path.abspath(config.get('output_options', 'output_dir'))))

    return target, source


def generate(env):
    doc_scanner = env.Scanner(function = _doc_scanner)

    doc_builder = SCons.Builder.Builder(
        action = _doc_build_function,
        emitter = _doc_emitter,
        source_scanner = doc_scanner,
        single_source = 1
    )

    env.Append(BUILDERS = {
        'gen_doc': doc_builder,
    })

def exists(env):
    '''Using internal builder'''
    return True

SConstruct

env = Environment()
env.Tool('gen_doc', toolpath=['.'])
env.gen_doc('config_doc')

config_doc

[input_options]
input = a.md b.md

[output_options]
output_dir = html

a.md

Hello

b.md

 world

これを実行すると、正しい出力が生成されます

html「index.html」という名前のファイルがあるフォルダー内のファイル

言葉でHello world

私が走るとき

scons -n tree=status html

私は次のことを得る

scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
scons: `html' is up to date.
 E         = exists
  R        = exists in repository only
   b       = implicit builder
   B       = explicit builder
    S      = side effect
     P     = precious
      A    = always build
       C   = current
        N  = no clean
         H = no cache

[E B   C  ]+-html
[E     C  ]  +-config_doc
[E     C  ]  +-a.md
[E     C  ]  +-b.md
scons: done building targets.

入って b.md ファイルを変更し、再実行します

scons -n tree=status html

出力は同じで、b.md が最新として報告されるため、ドキュメントは再構築されません。

scons に、スキャナが認識したソース ファイルへの変更を認識させ、ファイルが変更されたときに再構築する方法はありますか?

アップデート

これらのファイルが追加されない理由を見つけることができるかどうかを確認するために、ダミーの Decider を作成して少し遊んでみました。

def foo(dependency, target, prev_ni):
    print 'dependency = %s' % (dependency)
    print 'target = %s' % (target)
    return True

「generate(env)」に「env.Decider(foo)」という行を追加します

_doc_scanner によってツリーに追加されたファイルは Decider 関数を呼び出していないため、MD5 ハッシュは計算されません。

これらのファイルがディサイダーを呼び出すにはどうすればよいですか?

update2:

投稿時にエミッターのリターンを追加するのを忘れていました。

アップデート 3

外部ビルダーを呼び出さないようにコードを修正しました。ビルダーをエミュレートする内部ビルダー関数を呼び出すようになりました。これは、外部ビルダーの動作をエミュレートしているだけです。元のビルダー アクションはaction = 'cd ${SOURCE.dir} && gen_docs ${SOURCE.file}

4

2 に答える 2

0

エミッターが変更されたターゲット、ソース リストを返していません。

詳細については、 http ://www.scons.org/doc/HTML/scons-user/x3798.html を参照してください。

エミッター関数は、ビルドする必要があるターゲットとターゲットのビルド元のソースの変更されたリストを返す必要があります。

于 2013-10-18T18:48:46.600 に答える