custom.py revision c7bd0fa4851187c3102948f5f4d70c26d1b55a5e
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 ..."
6237058c3497850f452bdaf70a5dda07ee4840b6b9José Fonseca    env['INSTALLSTR'] = "  Installing $TARGET ..."
6397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef createConvenienceLibBuilder(env):
6697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """This is a utility function that creates the ConvenienceLibrary
6797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    Builder in an Environment if it is not there already.
6897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
6997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    If it is already there, we return the existing one.
7097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
7197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    Based on the stock StaticLibrary and SharedLibrary builders.
7297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """
7397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
7497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    try:
7597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        convenience_lib = env['BUILDERS']['ConvenienceLibrary']
7697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    except KeyError:
7797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
7897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        if env.Detect('ranlib'):
7997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
8097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            action_list.append(ranlib_action)
8197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
8297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        convenience_lib = SCons.Builder.Builder(action = action_list,
8397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  emitter = '$LIBEMITTER',
8497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  prefix = '$LIBPREFIX',
8597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  suffix = '$LIBSUFFIX',
8697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  src_suffix = '$SHOBJSUFFIX',
8797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                                  src_builder = 'SharedObject')
8897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        env['BUILDERS']['ConvenienceLibrary'] = convenience_lib
8997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
9097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return convenience_lib
9197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
9297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
9397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# TODO: handle import statements with multiple modules
9497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca# TODO: handle from import statements
9597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecaimport_re = re.compile(r'^import\s+(\S+)$', re.M)
9697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
9797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef python_scan(node, env, path):
9897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # http://www.scons.org/doc/0.98.5/HTML/scons-user/c2781.html#AEN2789
9997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    contents = node.get_contents()
10097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    source_dir = node.get_dir()
10197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    imports = import_re.findall(contents)
10297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    results = []
10397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    for imp in imports:
10497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        for dir in path:
10597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            file = os.path.join(str(dir), imp.replace('.', os.sep) + '.py')
10697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            if os.path.exists(file):
10797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                results.append(env.File(file))
10897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                break
10997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            file = os.path.join(str(dir), imp.replace('.', os.sep), '__init__.py')
11097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca            if os.path.exists(file):
11197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                results.append(env.File(file))
11297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca                break
11397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return results
11497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecapython_scanner = SCons.Scanner.Scanner(function = python_scan, skeys = ['.py'])
11697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
11897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef code_generate(env, script, target, source, command):
11997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """Method to simplify code generation via python scripts.
12097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
12197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    http://www.scons.org/wiki/UsingCodeGenerators
12297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    http://www.scons.org/doc/0.98.5/HTML/scons-user/c2768.html
12397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """
12497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
12597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # We're generating code using Python scripts, so we have to be
12697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # careful with our scons elements.  This entry represents
12797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # the generator file *in the source directory*.
12897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    script_src = env.File(script).srcnode()
12997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
13097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # This command creates generated code *in the build directory*.
13197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    command = command.replace('$SCRIPT', script_src.path)
1322311e2adf0db3c46a1054d94cdfcd2ec0badbfd3José Fonseca    action = SCons.Action.Action(command, "$CODEGENCOMSTR")
1332311e2adf0db3c46a1054d94cdfcd2ec0badbfd3José Fonseca    code = env.Command(target, source, action)
13497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
13597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Explicitly mark that the generated code depends on the generator,
13697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # and on implicitly imported python modules
13797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    path = (script_src.get_dir(),)
13897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    deps = [script_src]
13997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    deps += script_src.get_implicit_deps(env, python_scanner, path)
14097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.Depends(code, deps)
14197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
14297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Running the Python script causes .pyc files to be generated in the
14397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # source directory.  When we clean up, they should go too. So add side
14497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # effects for .pyc files
14597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    for dep in deps:
14697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        pyc = env.File(str(dep) + 'c')
14797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        env.SideEffect(pyc, code)
14897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
14997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return code
15097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef createCodeGenerateMethod(env):
15397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.Append(SCANNERS = python_scanner)
15497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    env.AddMethod(code_generate, 'CodeGenerate')
15597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
15797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef generate(env):
15897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    """Common environment generation code"""
15997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
160c7bd0fa4851187c3102948f5f4d70c26d1b55a5eJosé Fonseca    verbose = env.get('verbose', False) or not env.get('quiet', True)
161c7bd0fa4851187c3102948f5f4d70c26d1b55a5eJosé Fonseca    if not verbose:
16297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca        quietCommandLines(env)
16397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
16497e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # Custom builders and methods
16597e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    createConvenienceLibBuilder(env)
16697e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    createCodeGenerateMethod(env)
16797e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
16897e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    # for debugging
16997e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    #print env.Dump()
17097e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
17197e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca
17297e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonsecadef exists(env):
17397e2c5ac0bba7298c9a32703fe3d19de1f7b815aJosé Fonseca    return 1
174