waf

Multiple outputs from one input based on features


I would like to build many outputs based on the same input, e.g. a hex and a binary from an elf. I will do this multiple times, different places in the wscript so I'd like to wrap it in a feature.

Ideally something like:

bld(features="hex", source="output.elf")
bld(features="bin", source="output.elf")

How would I go about implementing this?


Solution

  • If your elf files always have the same extension, you can simply use that:

    # untested, naive code
    
    from waflib import TaskGen
    
    @TaskGen.extension('.elf')
    def process_elf(self, node): # <- self = task gen, node is the current input node
        if "bin" in self.features:
            bin_node = node.change_ext('.bin')
            self.create_task('make_bin_task', node, bin_node)
    
        if "hex" in self.features:
            hex_node = node.change_ext('.hex')
            self.create_task('make_hex_task', node, hex_node)
    

    If not, you have to define the features you want like that:

    from waflib import TaskGen
    
    @Taskgen.feature("hex", "bin") # <- attach method features hex AND bin
    @TaskGen.before('process_source')
    
    def transform_source(self):  # <- here self = task generator
        self.inputs = self.to_nodes(getattr(self, 'source', []))
        self.meths.remove('process_source') # <- to disable the standard process_source
    
    @Taskgen.feature("hex") # <- attach method to feature hex
    @TaskGen.after('transform_source')
    def process_hex(self):
        for i in self.inputs:
            self.create_task("make_hex_task", i, i.change_ext(".hex"))
    
    @Taskgen.feature("bin") # <- attach method to feature bin
    @TaskGen.after('transform_source')
    def process_hex(self):
        for i in self.inputs:
            self.create_task("make_bin_task", i, i.change_ext(".bin"))
    

    You have to write the two tasks make_elf_task and make_bin_task. You should put all this in a separate python file and make a "plugin".

    You can also define a "shortcut" to call:

    def build(bld):
        bld.make_bin(source = "output.elf")
        bld.make_hex(source = "output.elf")
    
        bld(features = "hex bin", source = "output.elf") # when both needed in the same place
    

    Like that:

    from waflib.Configure import conf
    
    @conf
    def make_bin(self, *k, **kw): # <- here self = build context
    
        kw["features"] = "bin" # <- you can add bin to existing features kw
        return self(*k, **kw)
    
    @conf
    def make_hex(self, *k, **kw):
    
        kw["features"] = "hex"
        return self(*k, **kw)