Eliminated some deprecations which were not sanctioned. Worked on Cantera.mak. There is a problem with scons eliminating $ from strings.
223 lines
6.3 KiB
Python
223 lines
6.3 KiB
Python
# File: subst.py
|
|
# Author: Brian A. Vanderburg II
|
|
# Purpose: A generic SCons file substitution mechanism
|
|
# Copyright: This file is placed in the public domain.
|
|
# URL: http://www.scons.org/wiki/GenericSubstBuilder
|
|
##############################################################################
|
|
|
|
|
|
# Requirements
|
|
##############################################################################
|
|
import re
|
|
|
|
from SCons.Script import *
|
|
import SCons.Errors
|
|
|
|
|
|
# Helper/core functions
|
|
##############################################################################
|
|
|
|
# Do the substitution
|
|
def _subst_file(target, source, env, pattern, replace):
|
|
# Read file
|
|
#print 'CALLING SUBST_FILE'
|
|
f = open(source, "rU")
|
|
try:
|
|
contents = f.read()
|
|
finally:
|
|
f.close()
|
|
|
|
# Substitute, make sure result is a string
|
|
def subfn(mo):
|
|
value = replace(env, mo)
|
|
if not SCons.Util.is_String(value):
|
|
raise SCons.Errors.UserError("Substitution must be a string.")
|
|
return value
|
|
#print 'pattern = ' , pattern
|
|
contents = re.sub(pattern, subfn, contents)
|
|
|
|
# Write file
|
|
f = open(target, "wt")
|
|
try:
|
|
f.write(contents)
|
|
finally:
|
|
f.close()
|
|
|
|
# Determine which keys are used
|
|
def _subst_keys(source, pattern):
|
|
# Read file
|
|
f = open(source, "rU")
|
|
try:
|
|
contents = f.read()
|
|
finally:
|
|
f.close()
|
|
|
|
# Determine keys
|
|
keys = []
|
|
def subfn(mo):
|
|
key = mo.group("key")
|
|
if key:
|
|
keys.append(key)
|
|
return ''
|
|
|
|
|
|
re.sub(pattern, subfn, contents)
|
|
|
|
return keys
|
|
|
|
# Get the value of a key as a string, or None if it is not in the environment
|
|
def _subst_value(env, key):
|
|
# Why does "if key in env" result in "KeyError: 0:"?
|
|
try:
|
|
env[key]
|
|
except KeyError:
|
|
return None
|
|
|
|
# env.subst already returns a string even if it is stored as a number
|
|
# such as env['HAVE_XYZ'] = 1
|
|
#print 'key = ', key
|
|
#print ' straight env = ', env[key]
|
|
#print ' str of the thing = ', str(env[key])
|
|
#print ' subst(${}) of the thing = ', env.subst("${%s}" % key)
|
|
#print ' %s of the thing = ', "%s" % str(env[key])
|
|
aa = env[key]
|
|
if aa == []:
|
|
aa = ''
|
|
return aa
|
|
#return str(env[key])
|
|
#return env.subst("${%s}" % key)
|
|
|
|
|
|
# Builder related functions
|
|
##############################################################################
|
|
|
|
# Builder action
|
|
def _subst_action(target, source, env):
|
|
# Substitute in the files
|
|
pattern = env["SUBST_PATTERN"]
|
|
replace = env["SUBST_REPLACE"]
|
|
#print 'SUBSTITUTE: ', pattern, ' for ', replace
|
|
|
|
for (t, s) in zip(target, source):
|
|
_subst_file(str(t), str(s), env, pattern, replace)
|
|
|
|
return 0
|
|
|
|
# Builder message
|
|
def _subst_message(target, source, env):
|
|
items = ["Substituting vars from %s to %s" % (s, t)
|
|
for (t, s) in zip(target, source)]
|
|
|
|
return "\n".join(items)
|
|
|
|
# Builder dependency emitter
|
|
def _subst_emitter(target, source, env):
|
|
pattern = env["SUBST_PATTERN"]
|
|
for (t, s) in zip(target, source):
|
|
# When building, if a variant directory is used and source files
|
|
# are being duplicated, the source file will not be duplicated yet
|
|
# when this is called, so the source node must be used instead of
|
|
# the duplicated node
|
|
path = s.srcnode().abspath
|
|
|
|
# Get keys used
|
|
keys = _subst_keys(path, pattern)
|
|
|
|
d = dict()
|
|
for key in keys:
|
|
value = _subst_value(env, key)
|
|
# print 'key = ', key, ' -> value = ', value
|
|
if not value is None:
|
|
d[key] = value
|
|
|
|
# Only the current target depends on this dictionary
|
|
Depends(t, SCons.Node.Python.Value(d))
|
|
|
|
return target, source
|
|
|
|
|
|
# Replace @key@ with the value of that key, and @@ with a single @
|
|
##############################################################################
|
|
|
|
_SubstFile_pattern = "@(?P<key>\w*?)@"
|
|
def _SubstFile_replace(env, mo):
|
|
key = mo.group("key")
|
|
if not key:
|
|
return "@"
|
|
|
|
value = _subst_value(env, key)
|
|
if value is None:
|
|
raise SCons.Errors.UserError("Error: key %s does not exist" % key)
|
|
return value
|
|
|
|
def SubstFile(env, target, source):
|
|
return env.SubstGeneric(target,
|
|
source,
|
|
SUBST_PATTERN=_SubstFile_pattern,
|
|
SUBST_REPLACE=_SubstFile_replace)
|
|
|
|
|
|
# A substitutor similar to config.h header substitution
|
|
# Supported patterns are:
|
|
#
|
|
# Pattern: #define @key@
|
|
# Found: #define key value
|
|
# Missing: /* #define key */
|
|
#
|
|
# Pattern: #define @key@ default
|
|
# Found: #define key value
|
|
# Missing: #define key default
|
|
#
|
|
# Pattern: #undef @key@
|
|
# Found: #define key value
|
|
# Missing: #undef key
|
|
#
|
|
# The "@" is used to that these defines can be used in addition to
|
|
# other defines that you do not desire to be replaced.
|
|
##############################################################################
|
|
|
|
_SubstHeader_pattern = "(?m)^(?P<space>\\s*?)(?P<type>#define|#undef)\\s+?@(?P<key>\w+?)@(?P<ending>.*?)$"
|
|
def _SubstHeader_replace(env, mo):
|
|
space = mo.group("space")
|
|
type = mo.group("type")
|
|
key = mo.group("key")
|
|
ending = mo.group("ending")
|
|
|
|
value = _subst_value(env, key)
|
|
if not value is None:
|
|
# If found it is always #define key value
|
|
return "%s#define %s %s" % (space, key, value)
|
|
|
|
# Not found
|
|
if type == "#define":
|
|
defval = ending.strip()
|
|
if defval:
|
|
# There is a default value
|
|
return "%s#define %s %s" % (space, key, defval)
|
|
else:
|
|
# There is no default value
|
|
return "%s/* #define %s */" % (space, key)
|
|
|
|
# It was #undef
|
|
return "%s#undef %s" % (space, key)
|
|
|
|
def SubstHeader(env, target, source):
|
|
return env.SubstGeneric(target,
|
|
source,
|
|
SUBST_PATTERN=_SubstHeader_pattern,
|
|
SUBST_REPLACE=_SubstHeader_replace)
|
|
|
|
|
|
def generate(env, **kw):
|
|
# The generic builder
|
|
subst = SCons.Action.Action(_subst_action, _subst_message)
|
|
env['BUILDERS']['SubstGeneric'] = Builder(action=subst,
|
|
emitter=_subst_emitter)
|
|
|
|
# Additional ones
|
|
env.AddMethod(SubstFile)
|
|
env.AddMethod(SubstHeader)
|
|
|
|
|
|
def exists(env):
|
|
return True
|