OLD | NEW |
(Empty) | |
| 1 """SCons.Tool.swig |
| 2 |
| 3 Tool-specific initialization for swig. |
| 4 |
| 5 There normally shouldn't be any need to import this module directly. |
| 6 It will usually be imported through the generic SCons.Tool.Tool() |
| 7 selection method. |
| 8 |
| 9 """ |
| 10 |
| 11 # |
| 12 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The S
Cons Foundation |
| 13 # |
| 14 # Permission is hereby granted, free of charge, to any person obtaining |
| 15 # a copy of this software and associated documentation files (the |
| 16 # "Software"), to deal in the Software without restriction, including |
| 17 # without limitation the rights to use, copy, modify, merge, publish, |
| 18 # distribute, sublicense, and/or sell copies of the Software, and to |
| 19 # permit persons to whom the Software is furnished to do so, subject to |
| 20 # the following conditions: |
| 21 # |
| 22 # The above copyright notice and this permission notice shall be included |
| 23 # in all copies or substantial portions of the Software. |
| 24 # |
| 25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
| 26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| 27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 32 # |
| 33 |
| 34 __revision__ = "src/engine/SCons/Tool/swig.py 5134 2010/08/16 23:02:40 bdeegan" |
| 35 |
| 36 import os.path |
| 37 import re |
| 38 import subprocess |
| 39 |
| 40 import SCons.Action |
| 41 import SCons.Defaults |
| 42 import SCons.Scanner |
| 43 import SCons.Tool |
| 44 import SCons.Util |
| 45 |
| 46 SwigAction = SCons.Action.Action('$SWIGCOM', '$SWIGCOMSTR') |
| 47 |
| 48 def swigSuffixEmitter(env, source): |
| 49 if '-c++' in SCons.Util.CLVar(env.subst("$SWIGFLAGS", source=source)): |
| 50 return '$SWIGCXXFILESUFFIX' |
| 51 else: |
| 52 return '$SWIGCFILESUFFIX' |
| 53 |
| 54 # Match '%module test', as well as '%module(directors="1") test' |
| 55 # Also allow for test to be quoted (SWIG permits double quotes, but not single) |
| 56 _reModule = re.compile(r'%module(\s*\(.*\))?\s+("?)(.+)\2') |
| 57 |
| 58 def _find_modules(src): |
| 59 """Find all modules referenced by %module lines in `src`, a SWIG .i file. |
| 60 Returns a list of all modules, and a flag set if SWIG directors have |
| 61 been requested (SWIG will generate an additional header file in this |
| 62 case.)""" |
| 63 directors = 0 |
| 64 mnames = [] |
| 65 try: |
| 66 matches = _reModule.findall(open(src).read()) |
| 67 except IOError: |
| 68 # If the file's not yet generated, guess the module name from the filena
me |
| 69 matches = [] |
| 70 mnames.append(os.path.splitext(src)[0]) |
| 71 |
| 72 for m in matches: |
| 73 mnames.append(m[2]) |
| 74 directors = directors or m[0].find('directors') >= 0 |
| 75 return mnames, directors |
| 76 |
| 77 def _add_director_header_targets(target, env): |
| 78 # Directors only work with C++ code, not C |
| 79 suffix = env.subst(env['SWIGCXXFILESUFFIX']) |
| 80 # For each file ending in SWIGCXXFILESUFFIX, add a new target director |
| 81 # header by replacing the ending with SWIGDIRECTORSUFFIX. |
| 82 for x in target[:]: |
| 83 n = x.name |
| 84 d = x.dir |
| 85 if n[-len(suffix):] == suffix: |
| 86 target.append(d.File(n[:-len(suffix)] + env['SWIGDIRECTORSUFFIX'])) |
| 87 |
| 88 def _swigEmitter(target, source, env): |
| 89 swigflags = env.subst("$SWIGFLAGS", target=target, source=source) |
| 90 flags = SCons.Util.CLVar(swigflags) |
| 91 for src in source: |
| 92 src = str(src.rfile()) |
| 93 mnames = None |
| 94 if "-python" in flags and "-noproxy" not in flags: |
| 95 if mnames is None: |
| 96 mnames, directors = _find_modules(src) |
| 97 if directors: |
| 98 _add_director_header_targets(target, env) |
| 99 python_files = [m + ".py" for m in mnames] |
| 100 outdir = env.subst('$SWIGOUTDIR', target=target, source=source) |
| 101 # .py files should be generated in SWIGOUTDIR if specified, |
| 102 # otherwise in the same directory as the target |
| 103 if outdir: |
| 104 python_files = [env.fs.File(os.path.join(outdir, j)) for j in py
thon_files] |
| 105 else: |
| 106 python_files = [target[0].dir.File(m) for m in python_files] |
| 107 target.extend(python_files) |
| 108 if "-java" in flags: |
| 109 if mnames is None: |
| 110 mnames, directors = _find_modules(src) |
| 111 if directors: |
| 112 _add_director_header_targets(target, env) |
| 113 java_files = [[m + ".java", m + "JNI.java"] for m in mnames] |
| 114 java_files = SCons.Util.flatten(java_files) |
| 115 outdir = env.subst('$SWIGOUTDIR', target=target, source=source) |
| 116 if outdir: |
| 117 java_files = [os.path.join(outdir, j) for j in java_files] |
| 118 java_files = list(map(env.fs.File, java_files)) |
| 119 for jf in java_files: |
| 120 t_from_s = lambda t, p, s, x: t.dir |
| 121 SCons.Util.AddMethod(jf, t_from_s, 'target_from_source') |
| 122 target.extend(java_files) |
| 123 return (target, source) |
| 124 |
| 125 def _get_swig_version(env): |
| 126 """Run the SWIG command line tool to get and return the version number""" |
| 127 pipe = SCons.Action._subproc(env, [env['SWIG'], '-version'], |
| 128 stdin = 'devnull', |
| 129 stderr = 'devnull', |
| 130 stdout = subprocess.PIPE) |
| 131 if pipe.wait() != 0: return |
| 132 |
| 133 out = pipe.stdout.read() |
| 134 match = re.search(r'SWIG Version\s+(\S+)$', out, re.MULTILINE) |
| 135 if match: |
| 136 return match.group(1) |
| 137 |
| 138 def generate(env): |
| 139 """Add Builders and construction variables for swig to an Environment.""" |
| 140 c_file, cxx_file = SCons.Tool.createCFileBuilders(env) |
| 141 |
| 142 c_file.suffix['.i'] = swigSuffixEmitter |
| 143 cxx_file.suffix['.i'] = swigSuffixEmitter |
| 144 |
| 145 c_file.add_action('.i', SwigAction) |
| 146 c_file.add_emitter('.i', _swigEmitter) |
| 147 cxx_file.add_action('.i', SwigAction) |
| 148 cxx_file.add_emitter('.i', _swigEmitter) |
| 149 |
| 150 java_file = SCons.Tool.CreateJavaFileBuilder(env) |
| 151 |
| 152 java_file.suffix['.i'] = swigSuffixEmitter |
| 153 |
| 154 java_file.add_action('.i', SwigAction) |
| 155 java_file.add_emitter('.i', _swigEmitter) |
| 156 |
| 157 env['SWIG'] = 'swig' |
| 158 env['SWIGVERSION'] = _get_swig_version(env) |
| 159 env['SWIGFLAGS'] = SCons.Util.CLVar('') |
| 160 env['SWIGDIRECTORSUFFIX'] = '_wrap.h' |
| 161 env['SWIGCFILESUFFIX'] = '_wrap$CFILESUFFIX' |
| 162 env['SWIGCXXFILESUFFIX'] = '_wrap$CXXFILESUFFIX' |
| 163 env['_SWIGOUTDIR'] = r'${"-outdir \"%s\"" % SWIGOUTDIR}' |
| 164 env['SWIGPATH'] = [] |
| 165 env['SWIGINCPREFIX'] = '-I' |
| 166 env['SWIGINCSUFFIX'] = '' |
| 167 env['_SWIGINCFLAGS'] = '$( ${_concat(SWIGINCPREFIX, SWIGPATH, SWIGINCSUF
FIX, __env__, RDirs, TARGET, SOURCE)} $)' |
| 168 env['SWIGCOM'] = '$SWIG -o $TARGET ${_SWIGOUTDIR} ${_SWIGINCFLAGS}
$SWIGFLAGS $SOURCES' |
| 169 |
| 170 expr = '^[ \t]*%[ \t]*(?:include|import|extern)[ \t]*(<|"?)([^>\s"]+)(?:>|"?
)' |
| 171 scanner = SCons.Scanner.ClassicCPP("SWIGScan", ".i", "SWIGPATH", expr) |
| 172 |
| 173 env.Append(SCANNERS = scanner) |
| 174 |
| 175 def exists(env): |
| 176 return env.Detect(['swig']) |
| 177 |
| 178 # Local Variables: |
| 179 # tab-width:4 |
| 180 # indent-tabs-mode:nil |
| 181 # End: |
| 182 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |