~bless/bless/trunk

« back to all changes in this revision

Viewing changes to scons_helpers.py

  • Committer: Alexandros Frantzis
  • Date: 2010-02-28 21:33:08 UTC
  • Revision ID: alf82@freemail.gr-20100228213308-nuor1zssp1o4zysc
Initial commit.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from string import Template
 
2
import os
 
3
import fnmatch
 
4
import tarfile, zipfile
 
5
import re
 
6
 
 
7
def register_builders(env):
 
8
        register_template_builder(env)
 
9
        register_archive_builder(env)
 
10
        register_localsymlink_builder(env)
 
11
 
 
12
def get_configure_tests():
 
13
        return { 'CheckPKGConfig' : CheckPKGConfig,
 
14
                     'CheckPKG' : CheckPKG }
 
15
 
 
16
class AtTemplate(Template):
 
17
        delimiter = '@';
 
18
 
 
19
# A builder that replaces variables in a file
 
20
# Adapted from http://www.scons.org/wiki/ReplacementBuilder
 
21
def register_template_builder(env):
 
22
        action = env.Action(template_action, template_string)
 
23
        env['BUILDERS']['Template'] = env.Builder(action=action, src_suffix='.in',
 
24
                        emitter=template_emitter, single_source=True)
 
25
 
 
26
def template_emitter(target, source, env):
 
27
        """this emitter adds all the variables referenced in the target file as
 
28
        dependencies for this target"""
 
29
        text = open(str(source[0]), 'r').read()
 
30
        i = 0
 
31
        r = re.compile('@\{?(\w*)\}?')
 
32
        dep_str = ''
 
33
        for match in re.findall(r, text):
 
34
                dep_str += '${' + match + '}'
 
35
        
 
36
        env.Depends(target[0], env.Value(env.subst(dep_str)))
 
37
        
 
38
        return (target, source)
 
39
        
 
40
def template_action(target, source, env):
 
41
        fin = open(str(source[0]), 'r')
 
42
        fout = open(str(target[0]), 'w')
 
43
        fout.write(AtTemplate(fin.read()).safe_substitute(env))
 
44
        return 0
 
45
 
 
46
def template_string(target, source, env):
 
47
        return "Creating '%s' from '%s'" % (str(target[0]), str(source[0]))
 
48
 
 
49
def accept_pattern(name, include, exclude):
 
50
        included = False
 
51
        excluded = False
 
52
        for pattern in include:
 
53
                if fnmatch.fnmatch (name, pattern):
 
54
                        included = True
 
55
                        for pattern in exclude:
 
56
                                if fnmatch.fnmatch (name, pattern):
 
57
                                        excluded = True
 
58
                                        break
 
59
                        break
 
60
 
 
61
        return included and not excluded
 
62
 
 
63
def get_files(path, include = ['*'],  exclude= []):
 
64
        """ Recursively find files in path matching include patterns list
 
65
                and not matching exclude patterns
 
66
        """
 
67
 
 
68
        ret_files = []
 
69
        for root, dirs, files in os.walk(path):
 
70
 
 
71
                for filename in files:
 
72
                        if accept_pattern(filename, include, exclude):
 
73
                                fullname = os.path.join (root, filename)
 
74
                                ret_files.append(fullname)
 
75
 
 
76
                dirs[:] = [d for d in dirs if accept_pattern(d, include, exclude)]
 
77
 
 
78
        return ret_files
 
79
 
 
80
 
 
81
# A builder that creates a rooted archive
 
82
# Adapted from http://www.scons.org/wiki/ArchiveBuilder
 
83
def register_archive_builder(env):
 
84
        action = env.Action(archive_action, archive_string)
 
85
        env['BUILDERS']['Archive'] = env.Builder(action=action)
 
86
 
 
87
def archive_action (target, source, env):
 
88
        """ Make an archive from sources """
 
89
 
 
90
        path = str(target[0])
 
91
        base = os.path.basename(path)
 
92
 
 
93
        if path.endswith('.tgz'):
 
94
                archive = tarfile.open (path, 'w:gz')
 
95
                prefix = base[:-len('.tgz')]
 
96
        elif path.endswith('.tar.gz'):
 
97
                archive = tarfile.open (path, 'w:gz')
 
98
                prefix = base[:-len('.tar.gz')]
 
99
        elif path.endswith('.tar.bz2'):
 
100
                archive = tarfile.open (path, 'w:bz2')
 
101
                prefix = base[:-len('.tar.bz2')]
 
102
        elif path.endswith('.zip'):
 
103
                archive = zipfile.ZipFile (path, 'w')
 
104
                archive.add = archive.write
 
105
                prefix = base[:-len('.zip')]
 
106
        else:
 
107
                print "Unknown archive type (%s)" % type
 
108
                return
 
109
 
 
110
        src = [str(s) for s in source if str(s) != path]
 
111
        for s in src:
 
112
                archive.add (s, os.path.join (prefix, s))
 
113
        archive.close()
 
114
 
 
115
def archive_string (target, source, env):
 
116
        """ Information string for Archive """
 
117
        return 'Making archive %s' % os.path.basename (str (target[0]))
 
118
 
 
119
# A symbolic link builder that creates a symlink to a file in the 
 
120
# same directory as that source file
 
121
def register_localsymlink_builder(env):
 
122
        action = env.Action(localsymlink_action, localsymlink_string)
 
123
        env['BUILDERS']['LocalSymlink'] = env.Builder(action=action,
 
124
                        emitter = localsymlink_emitter)
 
125
 
 
126
def localsymlink_emitter(target, source, env):
 
127
        t_base = os.path.basename(str(target[0]))
 
128
        s_dir = os.path.dirname(str(source[0]))
 
129
 
 
130
        return ([os.path.join(s_dir, t_base)], source)
 
131
 
 
132
def localsymlink_action (target, source, env):
 
133
        """ Make an symlink target pointing to source"""
 
134
        t = str(target[0])
 
135
        if os.path.lexists(t):
 
136
                if os.path.islink(t):
 
137
                        os.unlink(t)
 
138
        
 
139
        os.symlink(os.path.basename(str(source[0])), str(target[0]))
 
140
        return 0
 
141
 
 
142
def localsymlink_string (target, source, env):
 
143
        """ Information string for symlink """
 
144
        return 'Creating symlink %s -> %s' % (str(target[0]), str(source[0]))
 
145
 
 
146
def create_library_links(lib, soname, env):
 
147
        # Dummy builders for links
 
148
        lnk1 = env.Command(None, None, "")
 
149
        lnk2 = env.Command(None, None, "")
 
150
 
 
151
        if env['SHLIBSUFFIX'] == '.so':
 
152
        
 
153
                lib_base = os.path.basename(lib)
 
154
                lnk1_name = soname
 
155
                lnk1_base = os.path.basename(lnk1_name)
 
156
 
 
157
                if lnk1_base != lib_base:
 
158
                        lnk1 = env.LocalSymlink(lnk1_name, lib)
 
159
                        env.Depends(lnk1, lib)
 
160
        
 
161
                so_index = soname.rfind('.so')
 
162
                lnk2_name = soname[:so_index + 3]
 
163
                lnk2_base = os.path.basename(lnk2_name)
 
164
 
 
165
                if lnk2_base != lib_base and lnk2_base != lnk1_base:
 
166
                        lnk2 = env.LocalSymlink(lnk2_name, lib)
 
167
                        env.Depends(lnk2, lib)
 
168
 
 
169
        return lnk2, lnk2
 
170
 
 
171
# Helper function to create a versioned library and related symlinks
 
172
def versioned_library(target, source, soname, env):
 
173
        """Creates the shared library named 'target' from Nodes 'source'
 
174
        using the specified 'soname' and the scons 'env'"""
 
175
 
 
176
        env_lib = env.Clone()
 
177
 
 
178
        if env.subst('$SHLIBSUFFIX') == '.so':
 
179
                env_lib.Append(SHLINKFLAGS = '-Wl,-soname=%s' % soname)
 
180
                so_index = target.rfind('.so')
 
181
                env_lib['SHLIBSUFFIX'] = target[so_index:]
 
182
                env_lib.Append(LIBSUFFIXES=['$SHLIBSUFFIX'])
 
183
        
 
184
        suffix_index = target.rfind(env_lib.subst('$SHLIBSUFFIX'))
 
185
        prefix_length = len(env_lib.subst('$SHLIBPREFIX'))
 
186
 
 
187
        lib_name = target[prefix_length:suffix_index]
 
188
        
 
189
        lib = env_lib.SharedLibrary(lib_name, source)
 
190
 
 
191
        lnk1, lnk2 = create_library_links(str(lib[0]), soname, env)
 
192
        
 
193
        return [lib, lnk1, lnk2]
 
194
 
 
195
def install_versioned_library(target_dir, source, soname, env):
 
196
        
 
197
        lib = env.Install(target_dir, source)
 
198
 
 
199
        lnk1, lnk2 = create_library_links(str(lib[0]), soname, env)
 
200
        
 
201
        return [lib, lnk1, lnk2]
 
202
 
 
203
def CheckPKGConfig(context, version):
 
204
        context.Message( 'Checking for pkg-config... ' )
 
205
        ret = context.TryAction('pkg-config --atleast-pkgconfig-version=%s' % version)[0]
 
206
        context.Result( ret )
 
207
        return ret
 
208
 
 
209
def CheckPKG(context, name):
 
210
        context.Message( 'Checking for %s... ' % name )
 
211
        ret = context.TryAction('pkg-config --exists \'%s\'' % name)[0]
 
212
        context.Result( ret )
 
213
        return ret