ソース コードとマークダウン ドキュメントを含むテキスト ファイルを使用してドキュメントを構築するためのツールを使用するカスタム ビルダーがあります。
このツールは、すべての入力ファイルと出力オプションを指定する構成ファイルを受け取ります。
実行すると、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}