[Scons-users] Creation of an archive of source files with Node.all_children()

Paul Grégoire pg.ensiie at gmail.com
Fri Jan 23 05:38:28 EST 2015


Finally I use a special tree printer that I install with a tool and
called via a Pseudo-Builder. This is the code of the tool :

import tarfile

import SCons.Script
import SCons.Tool

def archive_tree(root, targets, filter_func, keep=False):
    result = set()
    rname = str(root)

    if not keep:
        if rname in targets:
            keep = True

    if keep and filter_func(root):

    children = root.all_children()
    if children:
        for c in children:
            result |= archive_tree(c, targets, filter_func, keep)

    return result

def filter_sources(src):
    for s in SCons.Tool.CSuffixes:
        if src.name.endswith(s):
            return True
    return False

class Archiver():
    def __init__(self, env, archive_name, targets, **kw):
        self._name = str(archive_name)
        if not self._name.endswith('.tar.gz'):
            self._name += '.tar.gz'
        self._targets = targets
        self._src_filter = kw.get('ARCHIVE_SRC_FILTER',

    def display(self, t):
        print "Retrieve sources for", self._targets
        files = archive_tree(t, self._targets, self._src_filter)
        print "Create archive {} containing {}
file{}".format(self._name, len(files), 's' if len(files) > 0 else '')
        t = tarfile.open(self._name, 'w:gz')
        for f in files:

def install_archiver(env, archive_name, targets=None, **kw):
    if SCons.Util.is_List(archive_name):
        archive_name = archive_name[0]
    if not targets:
        targets = [archive_name]
    if not SCons.Util.is_List(targets):
        targets = [targets]
    targets = [ str(t) for t in targets ]
    tp = Archiver(env, archive_name, targets, **kw)

def generate(env):
    env.AddMethod(install_archiver, "Archive")
    env.SetDefault(ARCHIVE_SRC_FILTER = filter_sources)

def exists(env):
    return 1

And how I use it in a SConstruct:

f = env.get('ARCHIVE_SRC_FILTER')
def sfilter(s):
    return f(s) and not str(s).startswith('/')

env.Archive('all_sources', BUILD_TARGETS)
env.Archive('project_sources', BUILD_TARGETS, ARCHIVE_SRC_FILTER=sfilter)
env.Archive('a_sources', 'a.out')

That compiles the program and produces XXX_sources.tar.gz as a side
effect, with all sources and headers found by the scanners. When
executing a dry-tun, only the archive is produced. Unfortunately the
archive is not deleted when a clean is performed, but this is
acceptable for me.

If you have some suggestions or improvements, you are welcome.

Thank for your help,

Best Regards,


2015-01-20 19:18 GMT+01:00 Dirk Bächle <tshortik at gmx.de>:
> Paul,
> On 20.01.2015 06:01, Paul Grégoire wrote:
>> Hi Dirk,
>> Thank you, your answer makes sense for me, and I realise I never noticed
>> that scanners are called during the compilation phase and
>> not during the analysis phase.
>> So, to solve my problem, I do not imagine a clean solution now. My last
>> idea is to use the result of the --tree option. Using scons
>> --tree=prune, perhaps with --dry-run to get the complete list of
>> dependencies, and then post process this output with an external
>> script to create the archive. I will try to create such a script. Could
>> you tell me if it is simple to add an option to the --tree
>> option to obtain an output that will be simpler to parse with a script ?
>> If it is not simple, I will do the job with one of the
>> existing output.
> I'd probably not bother to mess with the way SCons outputs its dependencies.
> There are already some starting points for your script, see:
>   https://el-tramo.be/blog/scons2ninja/
>   http://www.scons.org/wiki/SconsTreeView
> Best regards,
> Dirk
> _______________________________________________
> Scons-users mailing list
> Scons-users at scons.org
> https://pairlist4.pair.net/mailman/listinfo/scons-users

More information about the Scons-users mailing list