我有一个自定义构建器,它使用一种工具来使用源代码和带有降价文档的文本文件来构建文档。
该工具采用一个配置文件,该文件指定所有输入文件和输出选项。
运行时,它会在标记为 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 看到扫描仪看到的源文件的更改并在文件更改时重建?
更新
我做了一点尝试,我创建了一个虚拟决策者,看看我是否能找出为什么没有添加这些文件。
def foo(dependency, target, prev_ni):
print 'dependency = %s' % (dependency)
print 'target = %s' % (target)
return True
在“生成(env)”中,我添加了“env.Decider(foo)”行
_doc_scanner 添加到树中的文件没有调用 Decider 函数,因此永远不会计算 MD5 哈希。
我该怎么做才能让这些文件调用决策者?
更新2:
发帖时忘记添加发射器的返回值。
更新 3
修改了代码,使其不再调用外部构建器。它现在调用模拟构建器的内部构建器函数。这只是模拟外部构建器的行为。最初的建造者行动是action = 'cd ${SOURCE.dir} && gen_docs ${SOURCE.file}