blob: 5d235e7ee209d02f12847bf4472601db86a59c2b [file] [log] [blame]
Devin Jeanpierre19fc55f2017-04-24 10:49:00 -07001# Copyright 2010 The JsonCpp Authors
Sam Clegg63860612015-04-09 18:01:33 -07002# Distributed under MIT license, or public domain if desired and
3# recognized in your jurisdiction.
4# See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
5
Christopher Dunnf9864232007-06-14 21:01:26 +00006import re
7from SCons.Script import * # the usual scons stuff you get in a SConscript
Christopher Dunnbd1e8952014-11-19 23:30:47 -06008import collections
Christopher Dunnf9864232007-06-14 21:01:26 +00009
10def generate(env):
11 """
12 Add builders and construction variables for the
13 SubstInFile tool.
14
15 Adds SubstInFile builder, which substitutes the keys->values of SUBST_DICT
16 from the source to the target.
17 The values of SUBST_DICT first have any construction variables expanded
18 (its keys are not expanded).
19 If a value of SUBST_DICT is a python callable function, it is called and
20 the result is expanded as the value.
21 If there's more than one source and more than one target, each target gets
22 substituted from the corresponding source.
23 """
24 def do_subst_in_file(targetfile, sourcefile, dict):
25 """Replace all instances of the keys of dict with their values.
26 For example, if dict is {'%VERSION%': '1.2345', '%BASE%': 'MyProg'},
27 then all instances of %VERSION% in the file will be replaced with 1.2345 etc.
28 """
29 try:
30 f = open(sourcefile, 'rb')
31 contents = f.read()
32 f.close()
33 except:
Christopher Dunnbd1e8952014-11-19 23:30:47 -060034 raise SCons.Errors.UserError("Can't read source file %s"%sourcefile)
35 for (k,v) in list(dict.items()):
Christopher Dunnf9864232007-06-14 21:01:26 +000036 contents = re.sub(k, v, contents)
37 try:
38 f = open(targetfile, 'wb')
39 f.write(contents)
40 f.close()
41 except:
Christopher Dunnbd1e8952014-11-19 23:30:47 -060042 raise SCons.Errors.UserError("Can't write target file %s"%targetfile)
Christopher Dunnf9864232007-06-14 21:01:26 +000043 return 0 # success
44
45 def subst_in_file(target, source, env):
Christopher Dunnbd1e8952014-11-19 23:30:47 -060046 if 'SUBST_DICT' not in env:
47 raise SCons.Errors.UserError("SubstInFile requires SUBST_DICT to be set.")
Christopher Dunnf9864232007-06-14 21:01:26 +000048 d = dict(env['SUBST_DICT']) # copy it
Christopher Dunnbd1e8952014-11-19 23:30:47 -060049 for (k,v) in list(d.items()):
50 if isinstance(v, collections.Callable):
Christopher Dunnf9864232007-06-14 21:01:26 +000051 d[k] = env.subst(v()).replace('\\','\\\\')
52 elif SCons.Util.is_String(v):
53 d[k] = env.subst(v).replace('\\','\\\\')
54 else:
Christopher Dunnbd1e8952014-11-19 23:30:47 -060055 raise SCons.Errors.UserError("SubstInFile: key %s: %s must be a string or callable"%(k, repr(v)))
Christopher Dunnf9864232007-06-14 21:01:26 +000056 for (t,s) in zip(target, source):
57 return do_subst_in_file(str(t), str(s), d)
58
59 def subst_in_file_string(target, source, env):
60 """This is what gets printed on the console."""
61 return '\n'.join(['Substituting vars from %s into %s'%(str(s), str(t))
62 for (t,s) in zip(target, source)])
63
64 def subst_emitter(target, source, env):
65 """Add dependency from substituted SUBST_DICT to target.
66 Returns original target, source tuple unchanged.
67 """
68 d = env['SUBST_DICT'].copy() # copy it
Christopher Dunnbd1e8952014-11-19 23:30:47 -060069 for (k,v) in list(d.items()):
70 if isinstance(v, collections.Callable):
Christopher Dunnf9864232007-06-14 21:01:26 +000071 d[k] = env.subst(v())
72 elif SCons.Util.is_String(v):
73 d[k]=env.subst(v)
74 Depends(target, SCons.Node.Python.Value(d))
75 return target, source
76
77## env.Append(TOOLS = 'substinfile') # this should be automaticaly done by Scons ?!?
Christopher Dunn494950a2015-01-24 15:29:52 -060078 subst_action = SCons.Action.Action(subst_in_file, subst_in_file_string)
Christopher Dunnf9864232007-06-14 21:01:26 +000079 env['BUILDERS']['SubstInFile'] = Builder(action=subst_action, emitter=subst_emitter)
80
81def exists(env):
82 """
83 Make sure tool exists.
84 """
85 return True