4 # Permission is hereby granted, free of charge, to any person obtaining
5 # a copy of this software and associated documentation files (the
6 # "Software"), to deal in the Software without restriction, including
7 # without limitation the rights to use, copy, modify, merge, publish,
8 # distribute, sublicense, and/or sell copies of the Software, and to
9 # permit persons to whom the Software is furnished to do so, subject to
10 # the following conditions:
12 # The above copyright notice and this permission notice shall be included
13 # in all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
16 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
17 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
27 Common helper functions for working with the Microsoft tool chain.
38 logfile = os.environ.get('SCONS_MSCOMMON_DEBUG')
46 debug = lambda x: open(logfile, 'a').write(x + '\n')
48 logging.basicConfig(filename=logfile, level=logging.DEBUG)
51 debug = lambda x: None
57 """Return true if running on windows 64 bits.
59 Works whether python itself runs in 64 bits or 32 bits."""
60 # Unfortunately, python does not provide a useful way to determine
61 # if the underlying Windows OS is 32-bit or 64-bit. Worse, whether
62 # the Python itself is 32-bit or 64-bit affects what it returns,
63 # so nothing in sys.* or os.* help.
65 # Apparently the best solution is to use env vars that Windows
66 # sets. If PROCESSOR_ARCHITECTURE is not x86, then the python
67 # process is running in 64 bit mode (on a 64-bit OS, 64-bit
68 # hardware, obviously).
69 # If this python is 32-bit but the OS is 64, Windows will set
70 # ProgramW6432 and PROCESSOR_ARCHITEW6432 to non-null.
71 # (Checking for HKLM\Software\Wow6432Node in the registry doesn't
72 # work, because some 32-bit installers create it.)
75 # I structured these tests to make it easy to add new ones or
76 # add exceptions in the future, because this is a bit fragile.
78 if os.environ.get('PROCESSOR_ARCHITECTURE','x86') != 'x86':
80 if os.environ.get('PROCESSOR_ARCHITEW6432'):
82 if os.environ.get('ProgramW6432'):
88 return SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, value)[0]
91 """Return True if the given key exists in HKEY_LOCAL_MACHINE, False
94 SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, value)
100 # Functions for fetching environment variable settings from batch files.
102 def normalize_env(env, keys):
103 """Given a dictionary representing a shell environment, add the variables
104 from os.environ needed for the processing of .bat files; the keys are
105 controlled by the keys argument.
107 It also makes sure the environment values are correctly encoded.
109 Note: the environment is copied"""
113 normenv[k] = copy.deepcopy(env[k]).encode('mbcs')
117 normenv[k] = os.environ[k].encode('mbcs')
121 def get_output(vcbat, args = None, env = None):
122 """Parse the output of given bat file, with given args."""
124 debug("Calling '%s %s'" % (vcbat, args))
125 popen = subprocess.Popen('"%s" %s & set' % (vcbat, args),
126 stdout=subprocess.PIPE,
127 stderr=subprocess.PIPE,
130 debug("Calling '%s'" % vcbat)
131 popen = subprocess.Popen('"%s" & set' % vcbat,
132 stdout=subprocess.PIPE,
133 stderr=subprocess.PIPE,
136 # Use the .stdout and .stderr attributes directly because the
137 # .communicate() method uses the threading module on Windows
138 # and won't work under Pythons not built with threading.
139 stdout = popen.stdout.read()
140 if popen.wait() != 0:
141 raise IOError(popen.stderr.read().decode("mbcs"))
143 output = stdout.decode("mbcs")
146 def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")):
147 # dkeep is a dict associating key: path_list, where key is one item from
148 # keep, and pat_list the associated list of paths
150 # TODO(1.5): replace with the following list comprehension:
151 #dkeep = dict([(i, []) for i in keep])
152 dkeep = dict([(i, []) for i in keep])
154 # rdk will keep the regex to match the .bat file output line starts
157 rdk[i] = re.compile('%s=(.*)' % i, re.I)
159 def add_env(rmatch, key, dkeep=dkeep):
160 plist = rmatch.group(1).split(os.pathsep)
162 # Do not add empty paths (when a var ends with ;)
165 # XXX: For some reason, VC98 .bat file adds "" around the PATH
166 # values, and it screws up the environment later, so we strip
171 for line in output.splitlines():
172 for k,v in rdk.items():
180 def output_to_dict(output):
181 """Given an output string, parse it to find env variables.
183 Return a dict where keys are variables names, and values their content"""
184 envlinem = re.compile(r'^([a-zA-z0-9]+)=([\S\s]*)$')
186 for line in output.splitlines():
187 m = envlinem.match(line)
189 parsedenv[m.group(1)] = m.group(2)
194 """Given two list l1 and l2, return the items in l2 which are not in l1.
195 Order is maintained."""
197 # We don't try to be smart: lists are small, and this is not the bottleneck
208 # indent-tabs-mode:nil
210 # vim: set expandtab tabstop=4 shiftwidth=4: