From 27d8d6f44faa61a61c330d032111eee64dd8b8c7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jos=C3=A9=20Fonseca?= Date: Thu, 3 Jul 2008 12:42:23 +0900 Subject: [PATCH] scons: Add a env.CodeGenerate method to simplify code generation via python scripts. env.CodeGenerate( target = 'my_source.c', script = 'my_generator.py', source = ['input.txt', 'another.txt'], command = 'python $SCRIPT $SOURCE > $TARGET' ) It will take care generating all appropriate dependencies, including any module imported by the generator script, and the respective .pyc file side effects. --- scons/gallium.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 3 deletions(-) diff --git a/scons/gallium.py b/scons/gallium.py index 59ba34844b7..bfdd2de8db3 100644 --- a/scons/gallium.py +++ b/scons/gallium.py @@ -30,10 +30,13 @@ Frontend-tool for Gallium3D architecture. # +import os import os.path +import re import SCons.Action import SCons.Builder +import SCons.Scanner def quietCommandLines(env): @@ -70,11 +73,73 @@ def createConvenienceLibBuilder(env): src_suffix = '$SHOBJSUFFIX', src_builder = 'SharedObject') env['BUILDERS']['ConvenienceLibrary'] = convenience_lib - env['BUILDERS']['Library'] = convenience_lib return convenience_lib +# TODO: handle import statements with multiple modules +# TODO: handle from import statements +import_re = re.compile(r'^import\s+(\S+)$', re.M) + +def python_scan(node, env, path): + # http://www.scons.org/doc/0.98.5/HTML/scons-user/c2781.html#AEN2789 + contents = node.get_contents() + source_dir = node.get_dir() + imports = import_re.findall(contents) + results = [] + for imp in imports: + for dir in path: + file = os.path.join(str(dir), imp.replace('.', os.sep) + '.py') + if os.path.exists(file): + results.append(env.File(file)) + break + file = os.path.join(str(dir), imp.replace('.', os.sep), '__init__.py') + if os.path.exists(file): + results.append(env.File(file)) + break + return results + +python_scanner = SCons.Scanner.Scanner(function = python_scan, skeys = ['.py']) + + +def code_generate(env, script, target, source, command): + """Method to simplify code generation via python scripts. + + http://www.scons.org/wiki/UsingCodeGenerators + http://www.scons.org/doc/0.98.5/HTML/scons-user/c2768.html + """ + + # We're generating code using Python scripts, so we have to be + # careful with our scons elements. This entry represents + # the generator file *in the source directory*. + script_src = env.File(script).srcnode() + + # This command creates generated code *in the build directory*. + command = command.replace('$SCRIPT', script_src.path) + code = env.Command(target, source, command) + + # Explicitly mark that the generated code depends on the generator, + # and on implicitly imported python modules + path = (script_src.get_dir(),) + deps = [script_src] + deps += script_src.get_implicit_deps(env, python_scanner, path) + env.Depends(code, deps) + + # Running the Python script causes .pyc files to be generated in the + # source directory. When we clean up, they should go too. So add side + # effects for .pyc files + for dep in deps: + pyc = env.File(str(dep) + 'c') + env.SideEffect(pyc, code) + + return code + + +def createCodeGenerateMethod(env): + env.Append(SCANNERS = python_scanner) + env.AddMethod(code_generate, 'CodeGenerate') + + def generate(env): """Common environment generation code""" @@ -336,9 +401,10 @@ def generate(env): ] env.Append(LINKFLAGS = linkflags) - # Convenience Library Builder + # Custom builders and methods createConvenienceLibBuilder(env) - + createCodeGenerateMethod(env) + # for debugging #print env.Dump() -- 2.30.2