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.
This commit is contained in:
José Fonseca
2008-07-03 12:42:23 +09:00
parent 1ca2306147
commit 27d8d6f44f

View File

@@ -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()