OLD | NEW |
(Empty) | |
| 1 """SCons.Platform.win32 |
| 2 |
| 3 Platform-specific initialization for Win32 systems. |
| 4 |
| 5 There normally shouldn't be any need to import this module directly. It |
| 6 will usually be imported through the generic SCons.Platform.Platform() |
| 7 selection method. |
| 8 """ |
| 9 |
| 10 # |
| 11 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 The S
Cons Foundation |
| 12 # |
| 13 # Permission is hereby granted, free of charge, to any person obtaining |
| 14 # a copy of this software and associated documentation files (the |
| 15 # "Software"), to deal in the Software without restriction, including |
| 16 # without limitation the rights to use, copy, modify, merge, publish, |
| 17 # distribute, sublicense, and/or sell copies of the Software, and to |
| 18 # permit persons to whom the Software is furnished to do so, subject to |
| 19 # the following conditions: |
| 20 # |
| 21 # The above copyright notice and this permission notice shall be included |
| 22 # in all copies or substantial portions of the Software. |
| 23 # |
| 24 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
| 25 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
| 26 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 27 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 28 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 29 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 30 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 31 # |
| 32 |
| 33 __revision__ = "src/engine/SCons/Platform/win32.py 5134 2010/08/16 23:02:40 bdee
gan" |
| 34 |
| 35 import os |
| 36 import os.path |
| 37 import sys |
| 38 import tempfile |
| 39 |
| 40 from SCons.Platform.posix import exitvalmap |
| 41 from SCons.Platform import TempFileMunge |
| 42 import SCons.Util |
| 43 |
| 44 try: |
| 45 import msvcrt |
| 46 import win32api |
| 47 import win32con |
| 48 |
| 49 msvcrt.get_osfhandle |
| 50 win32api.SetHandleInformation |
| 51 win32con.HANDLE_FLAG_INHERIT |
| 52 except ImportError: |
| 53 parallel_msg = \ |
| 54 "you do not seem to have the pywin32 extensions installed;\n" + \ |
| 55 "\tparallel (-j) builds may not work reliably with open Python files." |
| 56 except AttributeError: |
| 57 parallel_msg = \ |
| 58 "your pywin32 extensions do not support file handle operations;\n" + \ |
| 59 "\tparallel (-j) builds may not work reliably with open Python files." |
| 60 else: |
| 61 parallel_msg = None |
| 62 |
| 63 import builtins |
| 64 |
| 65 _builtin_file = builtins.file |
| 66 _builtin_open = builtins.open |
| 67 |
| 68 def _scons_file(*args, **kw): |
| 69 fp = _builtin_file(*args, **kw) |
| 70 win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()), |
| 71 win32con.HANDLE_FLAG_INHERIT, |
| 72 0) |
| 73 return fp |
| 74 |
| 75 def _scons_open(*args, **kw): |
| 76 fp = _builtin_open(*args, **kw) |
| 77 win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()), |
| 78 win32con.HANDLE_FLAG_INHERIT, |
| 79 0) |
| 80 return fp |
| 81 |
| 82 builtins.file = _scons_file |
| 83 builtins.open = _scons_open |
| 84 |
| 85 |
| 86 |
| 87 # The upshot of all this is that, if you are using Python 1.5.2, |
| 88 # you had better have cmd or command.com in your PATH when you run |
| 89 # scons. |
| 90 |
| 91 def piped_spawn(sh, escape, cmd, args, env, stdout, stderr): |
| 92 # There is no direct way to do that in python. What we do |
| 93 # here should work for most cases: |
| 94 # In case stdout (stderr) is not redirected to a file, |
| 95 # we redirect it into a temporary file tmpFileStdout |
| 96 # (tmpFileStderr) and copy the contents of this file |
| 97 # to stdout (stderr) given in the argument |
| 98 if not sh: |
| 99 sys.stderr.write("scons: Could not find command interpreter, is it in yo
ur PATH?\n") |
| 100 return 127 |
| 101 else: |
| 102 # one temporary file for stdout and stderr |
| 103 tmpFileStdout = os.path.normpath(tempfile.mktemp()) |
| 104 tmpFileStderr = os.path.normpath(tempfile.mktemp()) |
| 105 |
| 106 # check if output is redirected |
| 107 stdoutRedirected = 0 |
| 108 stderrRedirected = 0 |
| 109 for arg in args: |
| 110 # are there more possibilities to redirect stdout ? |
| 111 if (arg.find( ">", 0, 1 ) != -1 or |
| 112 arg.find( "1>", 0, 2 ) != -1): |
| 113 stdoutRedirected = 1 |
| 114 # are there more possibilities to redirect stderr ? |
| 115 if arg.find( "2>", 0, 2 ) != -1: |
| 116 stderrRedirected = 1 |
| 117 |
| 118 # redirect output of non-redirected streams to our tempfiles |
| 119 if stdoutRedirected == 0: |
| 120 args.append(">" + str(tmpFileStdout)) |
| 121 if stderrRedirected == 0: |
| 122 args.append("2>" + str(tmpFileStderr)) |
| 123 |
| 124 # actually do the spawn |
| 125 try: |
| 126 args = [sh, '/C', escape(' '.join(args)) ] |
| 127 ret = os.spawnve(os.P_WAIT, sh, args, env) |
| 128 except OSError, e: |
| 129 # catch any error |
| 130 try: |
| 131 ret = exitvalmap[e[0]] |
| 132 except KeyError: |
| 133 sys.stderr.write("scons: unknown OSError exception code %d - %s:
%s\n" % (e[0], cmd, e[1])) |
| 134 if stderr is not None: |
| 135 stderr.write("scons: %s: %s\n" % (cmd, e[1])) |
| 136 # copy child output from tempfiles to our streams |
| 137 # and do clean up stuff |
| 138 if stdout is not None and stdoutRedirected == 0: |
| 139 try: |
| 140 stdout.write(open( tmpFileStdout, "r" ).read()) |
| 141 os.remove( tmpFileStdout ) |
| 142 except (IOError, OSError): |
| 143 pass |
| 144 |
| 145 if stderr is not None and stderrRedirected == 0: |
| 146 try: |
| 147 stderr.write(open( tmpFileStderr, "r" ).read()) |
| 148 os.remove( tmpFileStderr ) |
| 149 except (IOError, OSError): |
| 150 pass |
| 151 return ret |
| 152 |
| 153 def exec_spawn(l, env): |
| 154 try: |
| 155 result = os.spawnve(os.P_WAIT, l[0], l, env) |
| 156 except OSError, e: |
| 157 try: |
| 158 result = exitvalmap[e[0]] |
| 159 sys.stderr.write("scons: %s: %s\n" % (l[0], e[1])) |
| 160 except KeyError: |
| 161 result = 127 |
| 162 if len(l) > 2: |
| 163 if len(l[2]) < 1000: |
| 164 command = ' '.join(l[0:3]) |
| 165 else: |
| 166 command = l[0] |
| 167 else: |
| 168 command = l[0] |
| 169 sys.stderr.write("scons: unknown OSError exception code %d - '%s': %
s\n" % (e[0], command, e[1])) |
| 170 return result |
| 171 |
| 172 def spawn(sh, escape, cmd, args, env): |
| 173 if not sh: |
| 174 sys.stderr.write("scons: Could not find command interpreter, is it in yo
ur PATH?\n") |
| 175 return 127 |
| 176 return exec_spawn([sh, '/C', escape(' '.join(args))], env) |
| 177 |
| 178 # Windows does not allow special characters in file names anyway, so no |
| 179 # need for a complex escape function, we will just quote the arg, except |
| 180 # that "cmd /c" requires that if an argument ends with a backslash it |
| 181 # needs to be escaped so as not to interfere with closing double quote |
| 182 # that we add. |
| 183 def escape(x): |
| 184 if x[-1] == '\\': |
| 185 x = x + '\\' |
| 186 return '"' + x + '"' |
| 187 |
| 188 # Get the windows system directory name |
| 189 _system_root = None |
| 190 |
| 191 def get_system_root(): |
| 192 global _system_root |
| 193 if _system_root is not None: |
| 194 return _system_root |
| 195 |
| 196 # A resonable default if we can't read the registry |
| 197 val = os.environ.get('SystemRoot', "C:\\WINDOWS") |
| 198 |
| 199 if SCons.Util.can_read_reg: |
| 200 try: |
| 201 # Look for Windows NT system root |
| 202 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, |
| 203 'Software\\Microsoft\\Windows NT\\CurrentV
ersion') |
| 204 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot') |
| 205 except SCons.Util.RegError: |
| 206 try: |
| 207 # Okay, try the Windows 9x system root |
| 208 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE
, |
| 209 'Software\\Microsoft\\Windows\\Current
Version') |
| 210 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot') |
| 211 except KeyboardInterrupt: |
| 212 raise |
| 213 except: |
| 214 pass |
| 215 _system_root = val |
| 216 return val |
| 217 |
| 218 # Get the location of the program files directory |
| 219 def get_program_files_dir(): |
| 220 # Now see if we can look in the registry... |
| 221 val = '' |
| 222 if SCons.Util.can_read_reg: |
| 223 try: |
| 224 # Look for Windows Program Files directory |
| 225 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, |
| 226 'Software\\Microsoft\\Windows\\CurrentVers
ion') |
| 227 val, tok = SCons.Util.RegQueryValueEx(k, 'ProgramFilesDir') |
| 228 except SCons.Util.RegError: |
| 229 val = '' |
| 230 pass |
| 231 |
| 232 if val == '': |
| 233 # A reasonable default if we can't read the registry |
| 234 # (Actually, it's pretty reasonable even if we can :-) |
| 235 val = os.path.join(os.path.dirname(get_system_root()),"Program Files") |
| 236 |
| 237 return val |
| 238 |
| 239 |
| 240 |
| 241 # Determine which windows CPU were running on. |
| 242 class ArchDefinition(object): |
| 243 """ |
| 244 A class for defining architecture-specific settings and logic. |
| 245 """ |
| 246 def __init__(self, arch, synonyms=[]): |
| 247 self.arch = arch |
| 248 self.synonyms = synonyms |
| 249 |
| 250 SupportedArchitectureList = [ |
| 251 ArchDefinition( |
| 252 'x86', |
| 253 ['i386', 'i486', 'i586', 'i686'], |
| 254 ), |
| 255 |
| 256 ArchDefinition( |
| 257 'x86_64', |
| 258 ['AMD64', 'amd64', 'em64t', 'EM64T', 'x86_64'], |
| 259 ), |
| 260 |
| 261 ArchDefinition( |
| 262 'ia64', |
| 263 ['IA64'], |
| 264 ), |
| 265 ] |
| 266 |
| 267 SupportedArchitectureMap = {} |
| 268 for a in SupportedArchitectureList: |
| 269 SupportedArchitectureMap[a.arch] = a |
| 270 for s in a.synonyms: |
| 271 SupportedArchitectureMap[s] = a |
| 272 |
| 273 def get_architecture(arch=None): |
| 274 """Returns the definition for the specified architecture string. |
| 275 |
| 276 If no string is specified, the system default is returned (as defined |
| 277 by the PROCESSOR_ARCHITEW6432 or PROCESSOR_ARCHITECTURE environment |
| 278 variables). |
| 279 """ |
| 280 if arch is None: |
| 281 arch = os.environ.get('PROCESSOR_ARCHITEW6432') |
| 282 if not arch: |
| 283 arch = os.environ.get('PROCESSOR_ARCHITECTURE') |
| 284 return SupportedArchitectureMap.get(arch, ArchDefinition('', [''])) |
| 285 |
| 286 def generate(env): |
| 287 # Attempt to find cmd.exe (for WinNT/2k/XP) or |
| 288 # command.com for Win9x |
| 289 cmd_interp = '' |
| 290 # First see if we can look in the registry... |
| 291 if SCons.Util.can_read_reg: |
| 292 try: |
| 293 # Look for Windows NT system root |
| 294 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, |
| 295 'Software\\Microsoft\\Windows NT\\Curr
entVersion') |
| 296 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot') |
| 297 cmd_interp = os.path.join(val, 'System32\\cmd.exe') |
| 298 except SCons.Util.RegError: |
| 299 try: |
| 300 # Okay, try the Windows 9x system root |
| 301 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE
, |
| 302 'Software\\Microsoft\\Windows\\Cur
rentVersion') |
| 303 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot') |
| 304 cmd_interp = os.path.join(val, 'command.com') |
| 305 except KeyboardInterrupt: |
| 306 raise |
| 307 except: |
| 308 pass |
| 309 |
| 310 # For the special case of not having access to the registry, we |
| 311 # use a temporary path and pathext to attempt to find the command |
| 312 # interpreter. If we fail, we try to find the interpreter through |
| 313 # the env's PATH. The problem with that is that it might not |
| 314 # contain an ENV and a PATH. |
| 315 if not cmd_interp: |
| 316 systemroot = get_system_root() |
| 317 tmp_path = systemroot + os.pathsep + \ |
| 318 os.path.join(systemroot,'System32') |
| 319 tmp_pathext = '.com;.exe;.bat;.cmd' |
| 320 if 'PATHEXT' in os.environ: |
| 321 tmp_pathext = os.environ['PATHEXT'] |
| 322 cmd_interp = SCons.Util.WhereIs('cmd', tmp_path, tmp_pathext) |
| 323 if not cmd_interp: |
| 324 cmd_interp = SCons.Util.WhereIs('command', tmp_path, tmp_pathext) |
| 325 |
| 326 if not cmd_interp: |
| 327 cmd_interp = env.Detect('cmd') |
| 328 if not cmd_interp: |
| 329 cmd_interp = env.Detect('command') |
| 330 |
| 331 |
| 332 if 'ENV' not in env: |
| 333 env['ENV'] = {} |
| 334 |
| 335 # Import things from the external environment to the construction |
| 336 # environment's ENV. This is a potential slippery slope, because we |
| 337 # *don't* want to make builds dependent on the user's environment by |
| 338 # default. We're doing this for SystemRoot, though, because it's |
| 339 # needed for anything that uses sockets, and seldom changes, and |
| 340 # for SystemDrive because it's related. |
| 341 # |
| 342 # Weigh the impact carefully before adding other variables to this list. |
| 343 import_env = [ 'SystemDrive', 'SystemRoot', 'TEMP', 'TMP' ] |
| 344 for var in import_env: |
| 345 v = os.environ.get(var) |
| 346 if v: |
| 347 env['ENV'][var] = v |
| 348 |
| 349 if 'COMSPEC' not in env['ENV']: |
| 350 v = os.environ.get("COMSPEC") |
| 351 if v: |
| 352 env['ENV']['COMSPEC'] = v |
| 353 |
| 354 env.AppendENVPath('PATH', get_system_root() + '\System32') |
| 355 |
| 356 env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD' |
| 357 env['OBJPREFIX'] = '' |
| 358 env['OBJSUFFIX'] = '.obj' |
| 359 env['SHOBJPREFIX'] = '$OBJPREFIX' |
| 360 env['SHOBJSUFFIX'] = '$OBJSUFFIX' |
| 361 env['PROGPREFIX'] = '' |
| 362 env['PROGSUFFIX'] = '.exe' |
| 363 env['LIBPREFIX'] = '' |
| 364 env['LIBSUFFIX'] = '.lib' |
| 365 env['SHLIBPREFIX'] = '' |
| 366 env['SHLIBSUFFIX'] = '.dll' |
| 367 env['LIBPREFIXES'] = [ '$LIBPREFIX' ] |
| 368 env['LIBSUFFIXES'] = [ '$LIBSUFFIX' ] |
| 369 env['PSPAWN'] = piped_spawn |
| 370 env['SPAWN'] = spawn |
| 371 env['SHELL'] = cmd_interp |
| 372 env['TEMPFILE'] = TempFileMunge |
| 373 env['TEMPFILEPREFIX'] = '@' |
| 374 env['MAXLINELENGTH'] = 2048 |
| 375 env['ESCAPE'] = escape |
| 376 |
| 377 env['HOST_OS'] = 'win32' |
| 378 env['HOST_ARCH'] = get_architecture().arch |
| 379 |
| 380 |
| 381 # Local Variables: |
| 382 # tab-width:4 |
| 383 # indent-tabs-mode:nil |
| 384 # End: |
| 385 # vim: set expandtab tabstop=4 shiftwidth=4: |
OLD | NEW |