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()
11 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
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__ = "src/engine/SCons/Platform/win32.py 3842 2008/12/20 22:59:52 scons"
41 from SCons.Platform.posix import exitvalmap
42 from SCons.Platform import TempFileMunge
53 win32api.SetHandleInformation
54 win32con.HANDLE_FLAG_INHERIT
57 "you do not seem to have the pywin32 extensions installed;\n" + \
58 "\tparallel (-j) builds may not work reliably with open Python files."
59 except AttributeError:
61 "your pywin32 extensions do not support file handle operations;\n" + \
62 "\tparallel (-j) builds may not work reliably with open Python files."
68 _builtin_file = __builtin__.file
69 _builtin_open = __builtin__.open
71 def _scons_file(*args, **kw):
72 fp = apply(_builtin_file, args, kw)
73 win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()),
74 win32con.HANDLE_FLAG_INHERIT,
78 def _scons_open(*args, **kw):
79 fp = apply(_builtin_open, args, kw)
80 win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()),
81 win32con.HANDLE_FLAG_INHERIT,
85 __builtin__.file = _scons_file
86 __builtin__.open = _scons_open
90 # The upshot of all this is that, if you are using Python 1.5.2,
91 # you had better have cmd or command.com in your PATH when you run
94 def piped_spawn(sh, escape, cmd, args, env, stdout, stderr):
95 # There is no direct way to do that in python. What we do
96 # here should work for most cases:
97 # In case stdout (stderr) is not redirected to a file,
98 # we redirect it into a temporary file tmpFileStdout
99 # (tmpFileStderr) and copy the contents of this file
100 # to stdout (stderr) given in the argument
102 sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
105 # one temporary file for stdout and stderr
106 tmpFileStdout = os.path.normpath(tempfile.mktemp())
107 tmpFileStderr = os.path.normpath(tempfile.mktemp())
109 # check if output is redirected
113 # are there more possibilities to redirect stdout ?
114 if (string.find( arg, ">", 0, 1 ) != -1 or
115 string.find( arg, "1>", 0, 2 ) != -1):
117 # are there more possibilities to redirect stderr ?
118 if string.find( arg, "2>", 0, 2 ) != -1:
121 # redirect output of non-redirected streams to our tempfiles
122 if stdoutRedirected == 0:
123 args.append(">" + str(tmpFileStdout))
124 if stderrRedirected == 0:
125 args.append("2>" + str(tmpFileStderr))
127 # actually do the spawn
129 args = [sh, '/C', escape(string.join(args)) ]
130 ret = os.spawnve(os.P_WAIT, sh, args, env)
134 ret = exitvalmap[e[0]]
136 sys.stderr.write("scons: unknown OSError exception code %d - %s: %s\n" % (e[0], cmd, e[1]))
138 stderr.write("scons: %s: %s\n" % (cmd, e[1]))
139 # copy child output from tempfiles to our streams
140 # and do clean up stuff
141 if stdout != None and stdoutRedirected == 0:
143 stdout.write(open( tmpFileStdout, "r" ).read())
144 os.remove( tmpFileStdout )
145 except (IOError, OSError):
148 if stderr != None and stderrRedirected == 0:
150 stderr.write(open( tmpFileStderr, "r" ).read())
151 os.remove( tmpFileStderr )
152 except (IOError, OSError):
156 def exec_spawn(l, env):
158 result = os.spawnve(os.P_WAIT, l[0], l, env)
161 result = exitvalmap[e[0]]
162 sys.stderr.write("scons: %s: %s\n" % (l[0], e[1]))
167 command = string.join(l[0:3])
172 sys.stderr.write("scons: unknown OSError exception code %d - '%s': %s\n" % (e[0], command, e[1]))
175 def spawn(sh, escape, cmd, args, env):
177 sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
179 return exec_spawn([sh, '/C', escape(string.join(args))], env)
181 # Windows does not allow special characters in file names anyway, so no
182 # need for a complex escape function, we will just quote the arg, except
183 # that "cmd /c" requires that if an argument ends with a backslash it
184 # needs to be escaped so as not to interfere with closing double quote
191 # Get the windows system directory name
192 def get_system_root():
193 # A resonable default if we can't read the registry
195 val = os.environ['SYSTEMROOT']
200 # First see if we can look in the registry...
201 if SCons.Util.can_read_reg:
203 # Look for Windows NT system root
204 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
205 'Software\\Microsoft\\Windows NT\\CurrentVersion')
206 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
207 except SCons.Util.RegError:
209 # Okay, try the Windows 9x system root
210 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
211 'Software\\Microsoft\\Windows\\CurrentVersion')
212 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
213 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")
241 # Attempt to find cmd.exe (for WinNT/2k/XP) or
242 # command.com for Win9x
244 # First see if we can look in the registry...
245 if SCons.Util.can_read_reg:
247 # Look for Windows NT system root
248 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
249 'Software\\Microsoft\\Windows NT\\CurrentVersion')
250 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
251 cmd_interp = os.path.join(val, 'System32\\cmd.exe')
252 except SCons.Util.RegError:
254 # Okay, try the Windows 9x system root
255 k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
256 'Software\\Microsoft\\Windows\\CurrentVersion')
257 val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
258 cmd_interp = os.path.join(val, 'command.com')
259 except KeyboardInterrupt:
264 # For the special case of not having access to the registry, we
265 # use a temporary path and pathext to attempt to find the command
266 # interpreter. If we fail, we try to find the interpreter through
267 # the env's PATH. The problem with that is that it might not
268 # contain an ENV and a PATH.
270 systemroot = r'C:\Windows'
271 if os.environ.has_key('SYSTEMROOT'):
272 systemroot = os.environ['SYSTEMROOT']
273 tmp_path = systemroot + os.pathsep + \
274 os.path.join(systemroot,'System32')
275 tmp_pathext = '.com;.exe;.bat;.cmd'
276 if os.environ.has_key('PATHEXT'):
277 tmp_pathext = os.environ['PATHEXT']
278 cmd_interp = SCons.Util.WhereIs('cmd', tmp_path, tmp_pathext)
280 cmd_interp = SCons.Util.WhereIs('command', tmp_path, tmp_pathext)
283 cmd_interp = env.Detect('cmd')
285 cmd_interp = env.Detect('command')
288 if not env.has_key('ENV'):
291 # Import things from the external environment to the construction
292 # environment's ENV. This is a potential slippery slope, because we
293 # *don't* want to make builds dependent on the user's environment by
294 # default. We're doing this for SYSTEMROOT, though, because it's
295 # needed for anything that uses sockets, and seldom changes, and
296 # for SYSTEMDRIVE because it's related.
298 # Weigh the impact carefully before adding other variables to this list.
299 import_env = [ 'SYSTEMDRIVE', 'SYSTEMROOT', 'TEMP', 'TMP' ]
300 for var in import_env:
301 v = os.environ.get(var)
305 env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD'
306 env['OBJPREFIX'] = ''
307 env['OBJSUFFIX'] = '.obj'
308 env['SHOBJPREFIX'] = '$OBJPREFIX'
309 env['SHOBJSUFFIX'] = '$OBJSUFFIX'
310 env['PROGPREFIX'] = ''
311 env['PROGSUFFIX'] = '.exe'
312 env['LIBPREFIX'] = ''
313 env['LIBSUFFIX'] = '.lib'
314 env['SHLIBPREFIX'] = ''
315 env['SHLIBSUFFIX'] = '.dll'
316 env['LIBPREFIXES'] = [ '$LIBPREFIX' ]
317 env['LIBSUFFIXES'] = [ '$LIBSUFFIX' ]
318 env['PSPAWN'] = piped_spawn
320 env['SHELL'] = cmd_interp
321 env['TEMPFILE'] = TempFileMunge
322 env['TEMPFILEPREFIX'] = '@'
323 env['MAXLINELENGTH'] = 2048
324 env['ESCAPE'] = escape