Writing a custom builder executing an external command and python function

I want to write a custom font builder that:

  • Executes an external command to create foo.temp
  • It then executes a python function to control foo.tempand creates the final output file

I mentioned the next two sections, but I'm not sure that they can be “glued” together.

I know that it Commandaccepts a list of actions to be taken. But how to properly handle this intermediate file? Ideally, the intermediate file will be invisible to the user - the entire Builder will work atomically.


Here is what I came up with, it seems to work. However, the file is .binnot deleted automatically.

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
+4
source share
1 answer

This can actually be done using the Command builder , specifying a list of actions as follows:

Command('foo.temp', 'foo.in',
        ['your_external_action',
         your_python_function])

Note what foo.inis the source, and you should name it accordingly. But if it foo.tempis internal, as you mention, then this approach is probably not the best approach.

Another way, which, in my opinion, is much more flexible, would be to use Custom Builder with a Generator and / or Emitter .

Generator - Python, , , Python.

An Emitter . Builder Emitter ( Generator) ++ Java IDL Thrift. Thrift, , ( ), Emitter - / - . , Emitter / . , foo.temp , .

Builder , , SCSSS , , , . , .

, , Builder, , , ..

+3

Source: https://habr.com/ru/post/1569116/


All Articles