1 """SCons.Platform.win32
3 Platform-specific initialization for Win32 systems.
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()
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:
21 # The above copyright notice and this permission notice shall be included
22 # in all copies or substantial portions of the Software.
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.
33 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
41 from SCons.Platform.posix import exitvalmap
42 from SCons.Platform import TempFileMunge
51 win32api.SetHandleInformation
52 win32con.HANDLE_FLAG_INHERIT
55 "you do not seem to have the pywin32 extensions installed;\n" + \
56 "\tparallel (-j) builds may not work reliably with open Python files."
57 except AttributeError:
59 "your pywin32 extensions do not support file handle operations;\n" + \
60 "\tparallel (-j) builds may not work reliably with open Python files."
66 _builtin_file = __builtin__.file
67 _builtin_open = __builtin__.open
69 def _scons_file(*args, **kw):
70 fp = apply(_builtin_file, args, kw)
71 win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()),
72 win32con.HANDLE_FLAG_INHERIT,
76 def _scons_open(*args, **kw):
77 fp = apply(_builtin_open, args, kw)
78 win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()),
79 win32con.HANDLE_FLAG_INHERIT,
83 __builtin__.file = _scons_file
84 __builtin__.open = _scons_open
88 # The upshot of all this is that, if you are using Python 1.5.2,
89 # you had better have cmd or command.com in your PATH when you run
92 def piped_spawn(sh, escape, cmd, args, env, stdout, stderr):
93 # There is no direct way to do that in python. What we do
94 # here should work for most cases:
95 # In case stdout (stderr) is not redirected to a file,
96 # we redirect it into a temporary file tmpFileStdout
97 # (tmpFileStderr) and copy the contents of this file
98 # to stdout (stderr) given in the argument
100 sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
103 # one temporary file for stdout and stderr
104 tmpFileStdout = os.path.normpath(tempfile.mktemp())
105 tmpFileStderr = os.path.normpath(tempfile.mktemp())
107 # check if output is redirected
111 # are there more possibilities to redirect stdout ?
112 if (string.find( arg, ">", 0, 1 ) != -1 or
113 string.find( arg, "1>", 0, 2 ) != -1):
115 # are there more possibilities to redirect stderr ?
116 if string.find( arg, "2>", 0, 2 ) != -1:
119 # redirect output of non-redirected streams to our tempfiles
120 if stdoutRedirected == 0:
121 args.append(">" + str(tmpFileStdout))
122 if stderrRedirected == 0:
123 args.append("2>" + str(tmpFileStderr))
125 # actually do the spawn
127 args = [sh, '/C', escape(string.join(args)) ]
128 ret = os.spawnve(os.P_WAIT, sh, args, env)
132 ret = exitvalmap[e[0]]
134 sys.stderr.write("scons: unknown OSError exception code %d - %s: %s\n" % (e[0], cmd, e[1]))
135 if stderr is not None:
136 stderr.write("scons: %s: %s\n" % (cmd, e[1]))
137 # copy child output from tempfiles to our streams
138 # and do clean up stuff
139 if stdout is not None and stdoutRedirected == 0:
141 stdout.write(open( tmpFileStdout, "r" ).read())
142 os.remove( tmpFileStdout )
143 except (IOError, OSError):
146 if stderr is not None and stderrRedirected == 0:
148 stderr.write(open( tmpFileStderr, "r" ).read())
149 os.remove( tmpFileStderr )
150 except (IOError, OSError):
154 def exec_spawn(l, env):
156 result = os.spawnve(os.P_WAIT, l[0], l, env)
159 result = exitvalmap[e[0]]
160 sys.stderr.write("scons: %s: %s\n" % (l[0], e[1]))
165 command = string.join(l[0:3])
170 sys.stderr.write("scons: unknown OSError exception code %d - '%s': %s\n" % (e[0], command, e[1]))
173 def spawn(sh, escape, cmd, args, env):
175 sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
177 return exec_spawn([sh, '/C', escape(string.join(args))], env)
179 # Windows does not allow special characters in file names anyway, so no
180 # need for a complex escape function, we will just quote the arg, except
181 # that "cmd /c" requires that if an argument ends with a backslash it
182 # needs to be escaped so as not to interfere with closing double quote
189 # Get the windows system directory name
192 def get_system_root():
194 if _system_root is not None:
197 # A resonable default if we can't read the registry
198 val = os.environ.get('SystemRoot', "C:\\WINDOWS")
200 if SCons.Util.can_read_reg:
202 # Look for Windows NT system root
203 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
204 'Software\\Microsoft\\Windows NT\\CurrentVersion')
205 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
206 except SCons.Util.RegError:
208 # Okay, try the Windows 9x system root
209 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
210 'Software\\Microsoft\\Windows\\CurrentVersion')
211 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
212 except KeyboardInterrupt:
219 # Get the location of the program files directory
220 def get_program_files_dir():
221 # Now see if we can look in the registry...
223 if SCons.Util.can_read_reg:
225 # Look for Windows Program Files directory
226 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
227 'Software\\Microsoft\\Windows\\CurrentVersion')
228 val, tok = SCons.Util.RegQueryValueEx(k, 'ProgramFilesDir')
229 except SCons.Util.RegError:
234 # A reasonable default if we can't read the registry
235 # (Actually, it's pretty reasonable even if we can :-)
236 val = os.path.join(os.path.dirname(get_system_root()),"Program Files")
242 # Determine which windows CPU were running on.
243 class ArchDefinition:
245 A class for defining architecture-specific settings and logic.
247 def __init__(self, arch, synonyms=[]):
249 self.synonyms = synonyms
251 SupportedArchitectureList = [
254 ['i386', 'i486', 'i586', 'i686'],
259 ['AMD64', 'amd64', 'em64t', 'EM64T', 'x86_64'],
268 SupportedArchitectureMap = {}
269 for a in SupportedArchitectureList:
270 SupportedArchitectureMap[a.arch] = a
272 SupportedArchitectureMap[s] = a
274 def get_architecture(arch=None):
275 """Returns the definition for the specified architecture string.
277 If no string is specified, the system default is returned (as defined
278 by the PROCESSOR_ARCHITEW6432 or PROCESSOR_ARCHITECTURE environment
282 arch = os.environ.get('PROCESSOR_ARCHITEW6432')
284 arch = os.environ.get('PROCESSOR_ARCHITECTURE')
285 return SupportedArchitectureMap.get(arch, ArchDefinition('', ['']))
288 # Attempt to find cmd.exe (for WinNT/2k/XP) or
289 # command.com for Win9x
291 # First see if we can look in the registry...
292 if SCons.Util.can_read_reg:
294 # Look for Windows NT system root
295 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
296 'Software\\Microsoft\\Windows NT\\CurrentVersion')
297 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
298 cmd_interp = os.path.join(val, 'System32\\cmd.exe')
299 except SCons.Util.RegError:
301 # Okay, try the Windows 9x system root
302 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
303 'Software\\Microsoft\\Windows\\CurrentVersion')
304 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
305 cmd_interp = os.path.join(val, 'command.com')
306 except KeyboardInterrupt:
311 # For the special case of not having access to the registry, we
312 # use a temporary path and pathext to attempt to find the command
313 # interpreter. If we fail, we try to find the interpreter through
314 # the env's PATH. The problem with that is that it might not
315 # contain an ENV and a PATH.
317 systemroot = get_system_root()
318 tmp_path = systemroot + os.pathsep + \
319 os.path.join(systemroot,'System32')
320 tmp_pathext = '.com;.exe;.bat;.cmd'
321 if os.environ.has_key('PATHEXT'):
322 tmp_pathext = os.environ['PATHEXT']
323 cmd_interp = SCons.Util.WhereIs('cmd', tmp_path, tmp_pathext)
325 cmd_interp = SCons.Util.WhereIs('command', tmp_path, tmp_pathext)
328 cmd_interp = env.Detect('cmd')
330 cmd_interp = env.Detect('command')
333 if not env.has_key('ENV'):
336 # Import things from the external environment to the construction
337 # environment's ENV. This is a potential slippery slope, because we
338 # *don't* want to make builds dependent on the user's environment by
339 # default. We're doing this for SystemRoot, though, because it's
340 # needed for anything that uses sockets, and seldom changes, and
341 # for SystemDrive because it's related.
343 # Weigh the impact carefully before adding other variables to this list.
344 import_env = [ 'SystemDrive', 'SystemRoot', 'TEMP', 'TMP' ]
345 for var in import_env:
346 v = os.environ.get(var)
350 if not env['ENV'].has_key('COMSPEC'):
351 v = os.environ.get("COMSPEC")
353 env['ENV']['COMSPEC'] = v
355 env.AppendENVPath('PATH', get_system_root() + '\System32')
357 env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD'
358 env['OBJPREFIX'] = ''
359 env['OBJSUFFIX'] = '.obj'
360 env['SHOBJPREFIX'] = '$OBJPREFIX'
361 env['SHOBJSUFFIX'] = '$OBJSUFFIX'
362 env['PROGPREFIX'] = ''
363 env['PROGSUFFIX'] = '.exe'
364 env['LIBPREFIX'] = ''
365 env['LIBSUFFIX'] = '.lib'
366 env['SHLIBPREFIX'] = ''
367 env['SHLIBSUFFIX'] = '.dll'
368 env['LIBPREFIXES'] = [ '$LIBPREFIX' ]
369 env['LIBSUFFIXES'] = [ '$LIBSUFFIX' ]
370 env['PSPAWN'] = piped_spawn
372 env['SHELL'] = cmd_interp
373 env['TEMPFILE'] = TempFileMunge
374 env['TEMPFILEPREFIX'] = '@'
375 env['MAXLINELENGTH'] = 2048
376 env['ESCAPE'] = escape
378 env['HOST_OS'] = 'win32'
379 env['HOST_ARCH'] = get_architecture().arch
384 # indent-tabs-mode:nil
386 # vim: set expandtab tabstop=4 shiftwidth=4: