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 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__ = "/home/scons/scons/branch.0/baseline/src/engine/SCons/Platform/win32.py 0.96.1.D001 2004/08/23 09:55:29 knight"
40
from SCons.Platform.posix import exitvalmap
42
# XXX See note below about why importing SCons.Action should be
43
# eventually refactored.
48
"""A callable class. You can set an Environment variable to this,
49
then call it with a string argument, then it will perform temporary
50
file substitution on it. This is used to circumvent the win32 long command
54
env["TEMPFILE"] = TempFileMunge
55
env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES')}"
57
def __init__(self, cmd):
60
def __call__(self, target, source, env, for_signature):
63
cmd = env.subst_list(self.cmd, 0, target, source)[0]
65
maxline = int(env.subst('$MAXLINELENGTH'))
68
if (reduce(lambda x, y: x + len(y), cmd, 0) + len(cmd)) <= maxline:
71
# We do a normpath because mktemp() has what appears to be
72
# a bug in Win32 that will use a forward slash as a path
73
# delimiter. Win32's link mistakes that for a command line
76
# We use the .lnk suffix for the benefit of the Phar Lap
77
# linkloc linker, which likes to append an .lnk suffix if
79
tmp = os.path.normpath(tempfile.mktemp('.lnk'))
80
native_tmp = SCons.Util.get_native_path(tmp)
82
if env['SHELL'] and env['SHELL'] == 'sh':
83
# The sh shell will try to escape the backslashes in the
84
# path, so unescape them.
85
native_tmp = string.replace(native_tmp, '\\', r'\\\\')
86
# In Cygwin, we want to use rm to delete the temporary
87
# file, because del does not exist in the sh shell.
88
rm = env.Detect('rm') or 'del'
90
# Don't use 'rm' if the shell is not sh, because rm won't
91
# work with the win32 shells (cmd.exe or command.com) or
95
args = map(SCons.Util.quote_spaces, cmd[1:])
96
open(tmp, 'w').write(string.join(args, " ") + "\n")
97
# XXX Using the SCons.Action.print_actions value directly
98
# like this is bogus, but expedient. This class should
99
# really be rewritten as an Action that defines the
100
# __call__() and strfunction() methods and lets the
101
# normal action-execution logic handle whether or not to
102
# print/execute the action. The problem, though, is all
103
# of that is decided before we execute this method as
104
# part of expanding the $TEMPFILE construction variable.
105
# Consequently, refactoring this will have to wait until
106
# we get more flexible with allowing Actions to exist
107
# independently and get strung together arbitrarily like
108
# Ant tasks. In the meantime, it's going to be more
109
# user-friendly to not let obsession with architectural
110
# purity get in the way of just being helpful, so we'll
111
# reach into SCons.Action directly.
112
if SCons.Action.print_actions:
113
print("Using tempfile "+native_tmp+" for command line:\n"+
114
str(cmd[0]) + " " + string.join(args," "))
115
return [ cmd[0], '@' + native_tmp + '\n' + rm, native_tmp ]
117
# The upshot of all this is that, if you are using Python 1.5.2,
118
# you had better have cmd or command.com in your PATH when you run
121
def piped_spawn(sh, escape, cmd, args, env, stdout, stderr):
122
# There is no direct way to do that in python. What we do
123
# here should work for most cases:
124
# In case stdout (stderr) is not redirected to a file,
125
# we redirect it into a temporary file tmpFileStdout
126
# (tmpFileStderr) and copy the contents of this file
127
# to stdout (stderr) given in the argument
129
sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
132
# one temporary file for stdout and stderr
133
tmpFileStdout = os.path.normpath(tempfile.mktemp())
134
tmpFileStderr = os.path.normpath(tempfile.mktemp())
136
# check if output is redirected
140
# are there more possibilities to redirect stdout ?
141
if (string.find( arg, ">", 0, 1 ) != -1 or
142
string.find( arg, "1>", 0, 2 ) != -1):
144
# are there more possibilities to redirect stderr ?
145
if string.find( arg, "2>", 0, 2 ) != -1:
148
# redirect output of non-redirected streams to our tempfiles
149
if stdoutRedirected == 0:
150
args.append(">" + str(tmpFileStdout))
151
if stderrRedirected == 0:
152
args.append("2>" + str(tmpFileStderr))
154
# actually do the spawn
156
args = [sh, '/C', escape(string.join(args)) ]
157
ret = os.spawnve(os.P_WAIT, sh, args, env)
160
ret = exitvalmap[e[0]]
162
stderr.write("scons: %s: %s\n" % (cmd, e[1]))
163
# copy child output from tempfiles to our streams
164
# and do clean up stuff
165
if stdout != None and stdoutRedirected == 0:
167
stdout.write(open( tmpFileStdout, "r" ).read())
168
os.remove( tmpFileStdout )
169
except (IOError, OSError):
172
if stderr != None and stderrRedirected == 0:
174
stderr.write(open( tmpFileStderr, "r" ).read())
175
os.remove( tmpFileStderr )
176
except (IOError, OSError):
180
def spawn(sh, escape, cmd, args, env):
182
sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n")
186
args = [sh, '/C', escape(string.join(args)) ]
187
ret = os.spawnve(os.P_WAIT, sh, args, env)
189
ret = exitvalmap[e[0]]
190
sys.stderr.write("scons: %s: %s\n" % (cmd, e[1]))
193
# Windows does not allow special characters in file names anyway, so
194
# no need for a complex escape function, we will just quote the arg.
195
escape = lambda x: '"' + x + '"'
197
# Get the windows system directory name
198
def get_system_root():
199
# A resonable default if we can't read the registry
201
val = os.environ['SYSTEMROOT']
206
# First see if we can look in the registry...
207
if SCons.Util.can_read_reg:
209
# Look for Windows NT system root
210
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
211
'Software\\Microsoft\\Windows NT\\CurrentVersion')
212
val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
213
except SCons.Util.RegError:
215
# Okay, try the Windows 9x system root
216
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
217
'Software\\Microsoft\\Windows\\CurrentVersion')
218
val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
219
except KeyboardInterrupt:
225
# Get the location of the program files directory
226
def get_program_files_dir():
227
# Now see if we can look in the registry...
229
if SCons.Util.can_read_reg:
231
# Look for Windows Program Files directory
232
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
233
'Software\\Microsoft\\Windows\\CurrentVersion')
234
val, tok = SCons.Util.RegQueryValueEx(k, 'ProgramFilesDir')
235
except SCons.Util.RegError:
240
# A reasonable default if we can't read the registry
241
# (Actually, it's pretty reasonable even if we can :-)
242
val = os.path.join(os.path.dirname(get_system_root()),"Program Files")
247
# Attempt to find cmd.exe (for WinNT/2k/XP) or
248
# command.com for Win9x
250
# First see if we can look in the registry...
251
if SCons.Util.can_read_reg:
253
# Look for Windows NT system root
254
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
255
'Software\\Microsoft\\Windows NT\\CurrentVersion')
256
val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
257
cmd_interp = os.path.join(val, 'System32\\cmd.exe')
258
except SCons.Util.RegError:
260
# Okay, try the Windows 9x system root
261
k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE,
262
'Software\\Microsoft\\Windows\\CurrentVersion')
263
val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot')
264
cmd_interp = os.path.join(val, 'command.com')
265
except KeyboardInterrupt:
270
# For the special case of not having access to the registry, we
271
# use a temporary path and pathext to attempt to find the command
272
# interpreter. If we fail, we try to find the interpreter through
273
# the env's PATH. The problem with that is that it might not
274
# contain an ENV and a PATH.
276
systemroot = r'C:\Windows'
277
if os.environ.has_key('SYSTEMROOT'):
278
systemroot = os.environ['SYSTEMROOT']
279
tmp_path = systemroot + os.pathsep + \
280
os.path.join(systemroot,'System32')
281
tmp_pathext = '.com;.exe;.bat;.cmd'
282
if os.environ.has_key('PATHEXT'):
283
tmp_pathext = os.environ['PATHEXT']
284
cmd_interp = SCons.Util.WhereIs('cmd', tmp_path, tmp_pathext)
286
cmd_interp = SCons.Util.WhereIs('command', tmp_path, tmp_pathext)
289
cmd_interp = env.Detect('cmd')
291
cmd_interp = env.Detect('command')
294
if not env.has_key('ENV'):
297
# Import things from the external environment to the construction
298
# environment's ENV. This is a potential slippery slope, because we
299
# *don't* want to make builds dependent on the user's environment by
300
# default. We're doing this for SYSTEMROOT, though, because it's
301
# needed for anything that uses sockets, and seldom changes. Weigh
302
# the impact carefully before adding other variables to this list.
303
import_env = [ 'SYSTEMROOT' ]
304
for var in import_env:
305
v = os.environ.get(var)
309
env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD'
310
env['OBJPREFIX'] = ''
311
env['OBJSUFFIX'] = '.obj'
312
env['SHOBJPREFIX'] = '$OBJPREFIX'
313
env['SHOBJSUFFIX'] = '$OBJSUFFIX'
314
env['PROGPREFIX'] = ''
315
env['PROGSUFFIX'] = '.exe'
316
env['LIBPREFIX'] = ''
317
env['LIBSUFFIX'] = '.lib'
318
env['SHLIBPREFIX'] = ''
319
env['SHLIBSUFFIX'] = '.dll'
320
env['LIBPREFIXES'] = [ '$LIBPREFIX' ]
321
env['LIBSUFFIXES'] = [ '$LIBSUFFIX' ]
322
env['PSPAWN'] = piped_spawn
324
env['SHELL'] = cmd_interp
325
env['TEMPFILE'] = TempFileMunge
326
env['MAXLINELENGTH'] = 2048
327
env['ESCAPE'] = escape