我正在寻找一个自定义的SCons Builder:
foo.temp
foo.temp
并生成最终输出文件我已经提到了以下两个部分,但我不确定正确的方法来粘合"他们在一起。
我知道Command
接受了要采取的行动清单。但是如何正确处理该中间文件?理想情况下,中间文件对用户是不可见的 - 整个构建器似乎是原子操作的。
在这里,我提出的似乎正在发挥作用。但是,.bin
文件不会自动删除。
from SCons.Action import Action
from SCons.Util import is_List
from SCons.Script import Delete
_objcopy_builder = Builder(
action = 'objcopy -O binary $SOURCE $TARGET',
suffix = '.bin',
single_source = 1
)
def _add_header(target, source, env):
source = str(source[0])
target = str(target[0])
with open(source, 'rb') as src:
with open(target, 'wn') as tgt:
tgt.write('MODULE\x00\x00')
tgt.write(src.read())
return 0
_addheader_builder = Builder(
action = _add_header,
single_source = 1
)
def Elf2Mod(env, target, source, *args, **kw):
def check_one(x, what):
if not is_List(x):
x = [x]
if len(x) != 1:
raise StopError('Only one {0} allowed'.format(what))
return x
target = check_one(target, 'target')
source = check_one(source, 'source')
# objcopy a binary file
binfile = _objcopy_builder.__call__(env, source=source, **kw)
# write the module header
_addheader_builder.__call__(env, target=target, source=binfile, **kw)
# delete the intermediate binary file
# TODO: Not working
Delete(binfile)
return target
def generate(env):
"""Add Builders and construction variables to the Environment."""
env.AddMethod(Elf2Mod, 'Elf2Mod')
print 'Added Elf2Mod to env {0}'.format(env)
def exists(env):
return True
答案 0 :(得分:4)
通过指定操作列表,确实可以使用Command builder来完成,如下所示:
Command('foo.temp', 'foo.in',
['your_external_action',
your_python_function])
请注意foo.in
是来源,您应该相应地命名。但是如果你提到foo.temp
是内部的,那么这种方法可能不是最好的方法。
我认为更灵活的另一种方法是将Custom Builder与Generator和/或Emitter一起使用。
Generator
是一个Python函数,您可以在其中执行实际工作,在您的情况下将调用外部命令,并调用Python函数。
使用Emitter
可以对源和目标进行微调控制。我使用Builder
和Emitter
(和Generator
)一次使用Thrift输入IDL文件进行C ++和Java代码生成。我必须阅读并处理Thrift输入文件以确切地知道代码生成了哪些文件(哪些是实际目标),而Emitter
是执行此类操作的最佳/唯一方式。如果您的特定用例不是那么复杂,您可以跳过Emitter
并在调用构建器中列出您的源/目标。但是,如果您希望foo.temp
对最终用户透明,那么您将需要一个发射器。
当使用带有Generator和Emitter的Custom Builder时,SCons每次都会调用发射器来计算源和依赖关系,以了解是否需要调用Generator。只有在其中一个目标被视为较旧的源时,才会调用生成器。
有许多示例显示如何在自定义生成器中使用生成器和发射器,因此我不会在此列出代码,但如果您需要语法等方面的帮助,请告诉我。