首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >编写执行外部命令和python函数的自定义生成器

编写执行外部命令和python函数的自定义生成器
EN

Stack Overflow用户
提问于 2014-12-27 10:36:55
回答 1查看 4.9K关注 0票数 4

我想编写一个定制的SCons生成器:

  1. 执行外部命令以生成foo.temp
  2. 然后执行python函数来操作foo.temp并生成最终的输出文件。

我已经提到了以下两个部分,但我不确定将它们“粘合”在一起的正确方法。

  • 18.1.编写执行外部命令的生成器
  • 18.4.执行Python函数的构建器

我知道Command接受要采取的一系列行动。但是如何正确处理这个中间文件呢?理想情况下,中间文件对用户是不可见的--整个Builder看起来都是原子操作的。

我想出的办法似乎很有效。但是,.bin文件不会被自动删除。

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

发布于 2014-12-27 13:03:34

这确实可以通过命令生成器来完成,方法是指定一个操作列表,如下所示:

代码语言:javascript
复制
Command('foo.temp', 'foo.in',
        ['your_external_action',
         your_python_function])

请注意,foo.in是源,您应该相应地命名它。但是,如果foo.temp是内部的,那么这种方法可能不是最好的方法。

另一种更灵活的方法是将自定义生成器生成器和/或发射器一起使用。

Generator是一个Python函数,在这里您可以执行实际的工作,在您的示例中,它将调用外部命令,并调用Python函数。

Emitter允许您对源和目标进行微调控制。我曾经使用带有BuilderEmitter (和Generator)来生成C++和Java代码,并使用Generator输入IDL文件。我必须读取和处理the输入文件,才能确切地知道哪些文件将由代码生成(这些文件是实际的目标),而Emitter是这样做的最佳/唯一方法。如果您的特定用例没有那么复杂,您可以跳过Emitter,只需在对构建器的调用中列出源/目标。但是如果你想让foo.temp对最终用户透明,那么你就需要一个发射器。

当使用带有生成器和发射器的自定义生成器时,每次SCons都会调用发射器来计算源和依赖项,以了解是否需要调用生成器。只有当其中一个目标相对于源而言被认为较旧时,才会调用生成器。

有许多例子展示了如何在自定义生成器中使用生成器和发射器,所以我不会在这里列出代码,但是如果您需要语法帮助,请告诉我。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27666431

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档