custom.py revision 54d8c5e3c2fc7db643a2bae61be203ab9cbb1efa
197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca"""custom
297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé FonsecaCustom builders and methods.
497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca"""
697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# All Rights Reserved.
1097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
1197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# Permission is hereby granted, free of charge, to any person obtaining a
1297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# copy of this software and associated documentation files (the
1397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# "Software"), to deal in the Software without restriction, including
1497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# without limitation the rights to use, copy, modify, merge, publish,
1597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# distribute, sub license, and/or sell copies of the Software, and to
1697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# permit persons to whom the Software is furnished to do so, subject to
1797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# the following conditions:
1897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
1997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# The above copyright notice and this permission notice (including the
2097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# next paragraph) shall be included in all copies or substantial portions
2197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# of the Software.
2297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
2397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca#
3197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
3297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
3397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport os
3497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport os.path
3597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport re
3697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
3797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport SCons.Action
3897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport SCons.Builder
3997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport SCons.Scanner
4097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
4197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport fixes
4297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
4397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
4497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef quietCommandLines(env):
4597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Quiet command lines
4697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # See also http://www.scons.org/wiki/HidingCommandLinesInOutput
4797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['ASCOMSTR'] = "  Assembling $SOURCE ..."
4897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['ASPPCOMSTR'] = "  Assembling $SOURCE ..."
4997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['CCCOMSTR'] = "  Compiling $SOURCE ..."
5097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['SHCCCOMSTR'] = "  Compiling $SOURCE ..."
5197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['CXXCOMSTR'] = "  Compiling $SOURCE ..."
5297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['SHCXXCOMSTR'] = "  Compiling $SOURCE ..."
5397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['ARCOMSTR'] = "  Archiving $TARGET ..."
5497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['RANLIBCOMSTR'] = "  Indexing $TARGET ..."
5597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['LINKCOMSTR'] = "  Linking $TARGET ..."
5697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['SHLINKCOMSTR'] = "  Linking $TARGET ..."
5797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['LDMODULECOMSTR'] = "  Linking $TARGET ..."
5897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env['SWIGCOMSTR'] = "  Generating $TARGET ..."
5954d8c5e3c2fc7db643a2bae61be203ab9cbb1efaJosé Fonseca    env['LEXCOMSTR'] = "  Generating $TARGET ..."
6054d8c5e3c2fc7db643a2bae61be203ab9cbb1efaJosé Fonseca    env['YACCCOMSTR'] = "  Generating $TARGET ..."
612311e2adf0db3c46a1054d94cdfcd2ec0badbfd3José Fonseca    env['CODEGENCOMSTR'] = "  Generating $TARGET ..."
6297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef createConvenienceLibBuilder(env):
6597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """This is a utility function that creates the ConvenienceLibrary
6697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    Builder in an Environment if it is not there already.
6797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    If it is already there, we return the existing one.
6997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
7097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    Based on the stock StaticLibrary and SharedLibrary builders.
7197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """
7297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
7397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    try:
7497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        convenience_lib = env['BUILDERS']['ConvenienceLibrary']
7597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    except KeyError:
7697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
7797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        if env.Detect('ranlib'):
7897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
7997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            action_list.append(ranlib_action)
8097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
8197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        convenience_lib = SCons.Builder.Builder(action = action_list,
8297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  emitter = '$LIBEMITTER',
8397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  prefix = '$LIBPREFIX',
8497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  suffix = '$LIBSUFFIX',
8597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  src_suffix = '$SHOBJSUFFIX',
8697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  src_builder = 'SharedObject')
8797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        env['BUILDERS']['ConvenienceLibrary'] = convenience_lib
8897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
8997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return convenience_lib
9097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
9197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
9297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# TODO: handle import statements with multiple modules
9397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# TODO: handle from import statements
9497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport_re = re.compile(r'^import\s+(\S+)$', re.M)
9597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
9697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef python_scan(node, env, path):
9797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # http://www.scons.org/doc/0.98.5/HTML/scons-user/c2781.html#AEN2789
9897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    contents = node.get_contents()
9997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    source_dir = node.get_dir()
10097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    imports = import_re.findall(contents)
10197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    results = []
10297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    for imp in imports:
10397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        for dir in path:
10497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            file = os.path.join(str(dir), imp.replace('.', os.sep) + '.py')
10597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            if os.path.exists(file):
10697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                results.append(env.File(file))
10797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                break
10897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            file = os.path.join(str(dir), imp.replace('.', os.sep), '__init__.py')
10997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            if os.path.exists(file):
11097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                results.append(env.File(file))
11197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                break
11297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return results
11397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecapython_scanner = SCons.Scanner.Scanner(function = python_scan, skeys = ['.py'])
11597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef code_generate(env, script, target, source, command):
11897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """Method to simplify code generation via python scripts.
11997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
12097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    http://www.scons.org/wiki/UsingCodeGenerators
12197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    http://www.scons.org/doc/0.98.5/HTML/scons-user/c2768.html
12297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """
12397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
12497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # We're generating code using Python scripts, so we have to be
12597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # careful with our scons elements.  This entry represents
12697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # the generator file *in the source directory*.
12797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    script_src = env.File(script).srcnode()
12897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
12997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # This command creates generated code *in the build directory*.
13097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    command = command.replace('$SCRIPT', script_src.path)
1312311e2adf0db3c46a1054d94cdfcd2ec0badbfd3José Fonseca    action = SCons.Action.Action(command, "$CODEGENCOMSTR")
1322311e2adf0db3c46a1054d94cdfcd2ec0badbfd3José Fonseca    code = env.Command(target, source, action)
13397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
13497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Explicitly mark that the generated code depends on the generator,
13597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # and on implicitly imported python modules
13697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    path = (script_src.get_dir(),)
13797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    deps = [script_src]
13897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    deps += script_src.get_implicit_deps(env, python_scanner, path)
13997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.Depends(code, deps)
14097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
14197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Running the Python script causes .pyc files to be generated in the
14297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # source directory.  When we clean up, they should go too. So add side
14397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # effects for .pyc files
14497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    for dep in deps:
14597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        pyc = env.File(str(dep) + 'c')
14697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        env.SideEffect(pyc, code)
14797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
14897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return code
14997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef createCodeGenerateMethod(env):
15297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.Append(SCANNERS = python_scanner)
15397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.AddMethod(code_generate, 'CodeGenerate')
15497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef generate(env):
15797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """Common environment generation code"""
15897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    if env.get('quiet', True):
16097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        quietCommandLines(env)
16197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
16297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Custom builders and methods
16397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    createConvenienceLibBuilder(env)
16497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    createCodeGenerateMethod(env)
16597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
16697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # for debugging
16797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    #print env.Dump()
16897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
16997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
17097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef exists(env):
17197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return 1
172