1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org"""custom
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgCustom builders and methods.
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org"""
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# All Rights Reserved.
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# Permission is hereby granted, free of charge, to any person obtaining a
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# copy of this software and associated documentation files (the
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# "Software"), to deal in the Software without restriction, including
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# without limitation the rights to use, copy, modify, merge, publish,
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# distribute, sub license, and/or sell copies of the Software, and to
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# permit persons to whom the Software is furnished to do so, subject to
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# the following conditions:
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# The above copyright notice and this permission notice (including the
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# next paragraph) shall be included in all copies or substantial portions
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# of the Software.
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport os
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport os.path
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport re
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport sys
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport subprocess
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport SCons.Action
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport SCons.Builder
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport SCons.Scanner
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport fixes
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport source_list
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef quietCommandLines(env):
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # Quiet command lines
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # See also http://www.scons.org/wiki/HidingCommandLinesInOutput
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['ASCOMSTR'] = "  Assembling $SOURCE ..."
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['ASPPCOMSTR'] = "  Assembling $SOURCE ..."
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['CCCOMSTR'] = "  Compiling $SOURCE ..."
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['SHCCCOMSTR'] = "  Compiling $SOURCE ..."
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['CXXCOMSTR'] = "  Compiling $SOURCE ..."
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['SHCXXCOMSTR'] = "  Compiling $SOURCE ..."
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['ARCOMSTR'] = "  Archiving $TARGET ..."
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['RANLIBCOMSTR'] = "  Indexing $TARGET ..."
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['LINKCOMSTR'] = "  Linking $TARGET ..."
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['SHLINKCOMSTR'] = "  Linking $TARGET ..."
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['LDMODULECOMSTR'] = "  Linking $TARGET ..."
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['SWIGCOMSTR'] = "  Generating $TARGET ..."
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['LEXCOMSTR'] = "  Generating $TARGET ..."
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['YACCCOMSTR'] = "  Generating $TARGET ..."
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['CODEGENCOMSTR'] = "  Generating $TARGET ..."
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['INSTALLSTR'] = "  Installing $TARGET ..."
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef createConvenienceLibBuilder(env):
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """This is a utility function that creates the ConvenienceLibrary
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Builder in an Environment if it is not there already.
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    If it is already there, we return the existing one.
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    Based on the stock StaticLibrary and SharedLibrary builders.
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    try:
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        convenience_lib = env['BUILDERS']['ConvenienceLibrary']
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    except KeyError:
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if env.Detect('ranlib'):
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            action_list.append(ranlib_action)
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        convenience_lib = SCons.Builder.Builder(action = action_list,
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  emitter = '$LIBEMITTER',
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  prefix = '$LIBPREFIX',
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  suffix = '$LIBSUFFIX',
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  src_suffix = '$SHOBJSUFFIX',
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                  src_builder = 'SharedObject')
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        env['BUILDERS']['ConvenienceLibrary'] = convenience_lib
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return convenience_lib
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# TODO: handle import statements with multiple modules
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org# TODO: handle from import statements
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport_re = re.compile(r'^import\s+(\S+)$', re.M)
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef python_scan(node, env, path):
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # http://www.scons.org/doc/0.98.5/HTML/scons-user/c2781.html#AEN2789
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    contents = node.get_contents()
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    source_dir = node.get_dir()
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    imports = import_re.findall(contents)
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    results = []
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for imp in imports:
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for dir in path:
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            file = os.path.join(str(dir), imp.replace('.', os.sep) + '.py')
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if os.path.exists(file):
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                results.append(env.File(file))
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            file = os.path.join(str(dir), imp.replace('.', os.sep), '__init__.py')
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if os.path.exists(file):
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                results.append(env.File(file))
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                break
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return results
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpython_scanner = SCons.Scanner.Scanner(function = python_scan, skeys = ['.py'])
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef code_generate(env, script, target, source, command):
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Method to simplify code generation via python scripts.
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    http://www.scons.org/wiki/UsingCodeGenerators
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    http://www.scons.org/doc/0.98.5/HTML/scons-user/c2768.html
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # We're generating code using Python scripts, so we have to be
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # careful with our scons elements.  This entry represents
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # the generator file *in the source directory*.
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    script_src = env.File(script).srcnode()
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # This command creates generated code *in the build directory*.
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    command = command.replace('$SCRIPT', script_src.path)
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    action = SCons.Action.Action(command, "$CODEGENCOMSTR")
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    code = env.Command(target, source, action)
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # Explicitly mark that the generated code depends on the generator,
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # and on implicitly imported python modules
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    path = (script_src.get_dir(),)
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    deps = [script_src]
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    deps += script_src.get_implicit_deps(env, python_scanner, path)
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env.Depends(code, deps)
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # Running the Python script causes .pyc files to be generated in the
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # source directory.  When we clean up, they should go too. So add side
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # effects for .pyc files
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for dep in deps:
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        pyc = env.File(str(dep) + 'c')
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        env.SideEffect(pyc, code)
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return code
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef createCodeGenerateMethod(env):
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env.Append(SCANNERS = python_scanner)
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env.AddMethod(code_generate, 'CodeGenerate')
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef _pkg_check_modules(env, name, modules):
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    '''Simple wrapper for pkg-config.'''
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['HAVE_' + name] = False
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # For backwards compatability
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env[name.lower()] = False
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if env['platform'] == 'windows':
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if not env.Detect('pkg-config'):
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if subprocess.call(["pkg-config", "--exists", ' '.join(modules)]) != 0:
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # Strip version expressions from modules
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    modules = [module.split(' ', 1)[0] for module in modules]
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # Other flags may affect the compilation of unrelated targets, so store
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # them with a prefix, (e.g., XXX_CFLAGS, XXX_LIBS, etc)
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    try:
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        flags = env.ParseFlags('!pkg-config --cflags --libs ' + ' '.join(modules))
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    except OSError:
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    prefix = name + '_'
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for flag_name, flag_value in flags.iteritems():
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        assert '_' not in flag_name
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        env[prefix + flag_name] = flag_value
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env['HAVE_' + name] = True
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef pkg_check_modules(env, name, modules):
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    sys.stdout.write('Checking for %s (%s)...' % (name, ' '.join(modules)))
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    _pkg_check_modules(env, name, modules)
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    result = env['HAVE_' + name]
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    sys.stdout.write(' %s\n' % ['no', 'yes'][int(bool(result))])
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # XXX: For backwards compatability
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env[name.lower()] = result
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef pkg_use_modules(env, names):
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    '''Search for all environment flags that match NAME_FOO and append them to
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    the FOO environment variable.'''
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    names = env.Flatten(names)
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for name in names:
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        prefix = name + '_'
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if not 'HAVE_' + name in env:
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            raise Exception('Attempt to use unknown module %s' % name)
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if not env['HAVE_' + name]:
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            raise Exception('Attempt to use unavailable module %s' % name)
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        flags = {}
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for flag_name, flag_value in env.Dictionary().iteritems():
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if flag_name.startswith(prefix):
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                flag_name = flag_name[len(prefix):]
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if '_' not in flag_name:
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    flags[flag_name] = flag_value
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if flags:
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            env.MergeFlags(flags)
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef createPkgConfigMethods(env):
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env.AddMethod(pkg_check_modules, 'PkgCheckModules')
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env.AddMethod(pkg_use_modules, 'PkgUseModules')
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef parse_source_list(env, filename, names=None):
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # parse the source list file
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    parser = source_list.SourceListParser()
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    src = env.File(filename).srcnode()
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    cur_srcdir = env.Dir('.').srcnode().abspath
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    top_srcdir = env.Dir('#').abspath
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    top_builddir = os.path.join(top_srcdir, env['build_dir'])
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # Populate the symbol table of the Makefile parser.
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    parser.add_symbol('top_srcdir', top_srcdir)
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    parser.add_symbol('top_builddir', top_builddir)
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    sym_table = parser.parse(src.abspath)
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if names:
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        if isinstance(names, basestring):
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            names = [names]
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        symbols = names
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    else:
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        symbols = sym_table.keys()
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # convert the symbol table to source lists
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    src_lists = {}
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    for sym in symbols:
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        val = sym_table[sym]
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        srcs = []
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for f in val.split():
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if f:
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                # Process source paths
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if f.startswith(top_builddir + '/src'):
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    # Automake puts build output on a `src` subdirectory, bue
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    # SCons does no, so strip it here.
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    f = top_builddir + f[len(top_builddir + '/src'):]
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                if f.startswith(cur_srcdir + '/'):
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    # Prefer relative source paths, as absolute files tend to
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    # cause duplicate actions.
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    f = f[len(cur_srcdir + '/'):]
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                srcs.append(f)
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        src_lists[sym] = srcs
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # if names are given, concatenate the lists
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if names:
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        srcs = []
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        for name in names:
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            srcs.extend(src_lists[name])
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return srcs
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    else:
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        return src_lists
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef createParseSourceListMethod(env):
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    env.AddMethod(parse_source_list, 'ParseSourceList')
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef generate(env):
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    """Common environment generation code"""
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    verbose = env.get('verbose', False) or not env.get('quiet', True)
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    if not verbose:
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org        quietCommandLines(env)
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # Custom builders and methods
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    createConvenienceLibBuilder(env)
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    createCodeGenerateMethod(env)
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    createPkgConfigMethods(env)
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    createParseSourceListMethod(env)
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    # for debugging
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    #print env.Dump()
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdef exists(env):
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    return 1
310