senfscons: Much improved install implementation
[senf.git] / senfscons / InstallIncludes.py
1 ## \file
2 # \brief InstallIncludes builder
3
4 ## \package senfscons.InstallIncludes
5 # \brief Install all include files which some targets depend upon
6 #
7 # \ingroup builder
8
9 import SCons.Builder, SCons.Action, SCons.Environment, SCons.Node.FS
10
11 def recursiveChildren(f):
12     rv = {}
13     map(rv.setdefault,f)    
14     for c in f:
15         map(rv.setdefault,recursiveChildren(c.children()))
16     return rv.keys()
17
18 def filterIncludes(files, extensions):
19     return [ f for f in files
20              if f.get_suffix() in extensions ]
21
22 def filterDirectory(files, dir):
23     return [ f for f in files
24              if f.abspath.startswith(dir.abspath) ]
25
26 def excludeDirectories(files, dirs):
27     return [ f for f in files
28              if not [ True for d in dirs if files.abspath.startswith(dirs.abspath) ] ]
29
30 def emitter(target, source, env):
31     source = recursiveChildren(source)
32     source = filterIncludes(source, env['CPP_INCLUDE_EXTENSIONS'])
33     source = filterDirectory(source, env['INSTALL_BASE'])
34     source = excludeDirectories(source, env['INCLUDE_IGNORED_DIRECTORIES'])
35
36     # Build target file by appending the path of 'src' relative to INSTALL_BASE to target[0]
37     target = [ target[0].File(src.get_path(env.Dir(env['INSTALL_BASE'])))
38                for src in source ]
39
40     return (target, source)
41
42 class Installer:
43     def __init__(self, target, source):
44         self.target = target;
45         self.source = source
46
47     def __call__(self, target, source, env):
48         SCons.Environment.installFunc([self.target], [self.source], env)
49
50 def generator(target, source, env, for_signature):
51     return [ SCons.Action.Action( Installer(trg, src),
52                                   SCons.Environment.installString([trg], [src], env) )
53              for trg, src in zip(target,source) ]
54
55 InstallIncludes = SCons.Builder.Builder(emitter = emitter,
56                                         generator = generator,
57                                         source_factory = SCons.Node.FS.Entry,
58                                         target_factory = SCons.Node.FS.Dir,
59                                         name = 'InstallIncludesBuilder',
60                                         )
61
62 def generate(env):
63     env['BUILDERS']['InstallIncludes'] = InstallIncludes
64     env['INSTALL_BASE'] = '#'
65     env['INCLUDE_IGNORED_DIRECTORIES'] = []
66
67 def exists(env):
68     return 1