blob: 81166569619b6fca7d0afcb8860c8bf78ea56fb9 [file] [log] [blame]
Greg Wardbfc79d62000-06-28 01:29:09 +00001"""distutils.msvccompiler
Greg Warddbd12761999-08-29 18:15:07 +00002
3Contains MSVCCompiler, an implementation of the abstract CCompiler class
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +00004for the Microsoft Visual Studio.
5"""
Greg Warddbd12761999-08-29 18:15:07 +00006
Andrew M. Kuchlinga6483d22002-11-14 02:25:42 +00007# Written by Perry Stoll
Greg Ward32c4a8a2000-03-06 03:40:29 +00008# hacked by Robin Becker and Thomas Heller to do a better job of
9# finding DevStudio (through the registry)
10
Tarek Ziadé36797272010-07-22 12:50:05 +000011import sys, os
12from distutils.errors import \
13 DistutilsExecError, DistutilsPlatformError, \
14 CompileError, LibError, LinkError
15from distutils.ccompiler import \
16 CCompiler, gen_preprocess_options, gen_lib_options
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000017from distutils import log
Greg Ward62e33932000-02-10 02:52:42 +000018
Collin Winter5b7e9d72007-08-30 03:52:21 +000019_can_read_reg = False
Greg Ward7642f5c2000-03-31 16:47:40 +000020try:
Georg Brandl38feaf02008-05-25 07:45:51 +000021 import winreg
Greg Ward83c38702000-06-29 23:04:59 +000022
Collin Winter5b7e9d72007-08-30 03:52:21 +000023 _can_read_reg = True
Georg Brandl38feaf02008-05-25 07:45:51 +000024 hkey_mod = winreg
Greg Ward19ce1662000-03-31 19:04:25 +000025
Georg Brandl38feaf02008-05-25 07:45:51 +000026 RegOpenKeyEx = winreg.OpenKeyEx
27 RegEnumKey = winreg.EnumKey
28 RegEnumValue = winreg.EnumValue
29 RegError = winreg.error
Greg Ward19ce1662000-03-31 19:04:25 +000030
Greg Ward7642f5c2000-03-31 16:47:40 +000031except ImportError:
32 try:
33 import win32api
34 import win32con
Collin Winter5b7e9d72007-08-30 03:52:21 +000035 _can_read_reg = True
Greg Ward1027e3f2000-03-31 16:53:42 +000036 hkey_mod = win32con
Greg Ward19ce1662000-03-31 19:04:25 +000037
38 RegOpenKeyEx = win32api.RegOpenKeyEx
39 RegEnumKey = win32api.RegEnumKey
40 RegEnumValue = win32api.RegEnumValue
41 RegError = win32api.error
Greg Ward7642f5c2000-03-31 16:47:40 +000042 except ImportError:
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +000043 log.info("Warning: Can't read registry to find the "
44 "necessary compiler setting\n"
Georg Brandl38feaf02008-05-25 07:45:51 +000045 "Make sure that Python modules winreg, "
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +000046 "win32api or win32con are installed.")
Greg Ward7642f5c2000-03-31 16:47:40 +000047 pass
Greg Ward1027e3f2000-03-31 16:53:42 +000048
49if _can_read_reg:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000050 HKEYS = (hkey_mod.HKEY_USERS,
51 hkey_mod.HKEY_CURRENT_USER,
52 hkey_mod.HKEY_LOCAL_MACHINE,
53 hkey_mod.HKEY_CLASSES_ROOT)
Fred Drakeb94b8492001-12-06 20:51:35 +000054
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000055def read_keys(base, key):
56 """Return list of registry keys."""
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000057 try:
58 handle = RegOpenKeyEx(base, key)
59 except RegError:
60 return None
Greg Ward1b9c6f72000-02-08 02:39:44 +000061 L = []
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000062 i = 0
Collin Winter5b7e9d72007-08-30 03:52:21 +000063 while True:
Greg Ward1b9c6f72000-02-08 02:39:44 +000064 try:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000065 k = RegEnumKey(handle, i)
Greg Ward1027e3f2000-03-31 16:53:42 +000066 except RegError:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000067 break
68 L.append(k)
Collin Winter5b7e9d72007-08-30 03:52:21 +000069 i += 1
Greg Ward1b9c6f72000-02-08 02:39:44 +000070 return L
71
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000072def read_values(base, key):
73 """Return dict of registry keys and values.
Greg Ward62e33932000-02-10 02:52:42 +000074
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000075 All names are converted to lowercase.
76 """
77 try:
78 handle = RegOpenKeyEx(base, key)
79 except RegError:
80 return None
81 d = {}
82 i = 0
Collin Winter5b7e9d72007-08-30 03:52:21 +000083 while True:
Greg Ward1b9c6f72000-02-08 02:39:44 +000084 try:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000085 name, value, type = RegEnumValue(handle, i)
Greg Ward1027e3f2000-03-31 16:53:42 +000086 except RegError:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000087 break
88 name = name.lower()
89 d[convert_mbcs(name)] = convert_mbcs(value)
Collin Winter5b7e9d72007-08-30 03:52:21 +000090 i += 1
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000091 return d
92
93def convert_mbcs(s):
Christian Heimesd157e692007-11-17 11:46:54 +000094 dec = getattr(s, "decode", None)
95 if dec is not None:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000096 try:
Christian Heimesd157e692007-11-17 11:46:54 +000097 s = dec("mbcs")
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000098 except UnicodeError:
Greg Ward1b9c6f72000-02-08 02:39:44 +000099 pass
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000100 return s
Greg Ward1b9c6f72000-02-08 02:39:44 +0000101
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000102class MacroExpander:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000103 def __init__(self, version):
104 self.macros = {}
105 self.load_macros(version)
Greg Ward62e33932000-02-10 02:52:42 +0000106
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000107 def set_macro(self, macro, path, key):
108 for base in HKEYS:
109 d = read_values(base, path)
110 if d:
111 self.macros["$(%s)" % macro] = d[key]
112 break
Tim Peters182b5ac2004-07-18 06:16:08 +0000113
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000114 def load_macros(self, version):
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000115 vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000116 self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
117 self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
118 net = r"Software\Microsoft\.NETFramework"
119 self.set_macro("FrameworkDir", net, "installroot")
Tim Peters26be2062004-11-28 01:10:01 +0000120 try:
121 if version > 7.0:
122 self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
123 else:
124 self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
Tarek Ziadé36797272010-07-22 12:50:05 +0000125 except KeyError as exc: #
Collin Winter5b7e9d72007-08-30 03:52:21 +0000126 raise DistutilsPlatformError(
127 """Python was built with Visual Studio 2003;
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000128extensions must be built with a compiler than can generate compatible binaries.
129Visual Studio 2003 was not found on this system. If you have Cygwin installed,
130you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
Greg Ward1b9c6f72000-02-08 02:39:44 +0000131
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000132 p = r"Software\Microsoft\NET Framework Setup\Product"
133 for base in HKEYS:
134 try:
135 h = RegOpenKeyEx(base, p)
136 except RegError:
137 continue
138 key = RegEnumKey(h, 0)
139 d = read_values(base, r"%s\%s" % (p, key))
140 self.macros["$(FrameworkVersion)"] = d["version"]
Greg Ward69988092000-02-11 02:47:15 +0000141
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000142 def sub(self, s):
143 for k, v in self.macros.items():
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000144 s = s.replace(k, v)
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000145 return s
Greg Ward69988092000-02-11 02:47:15 +0000146
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000147def get_build_version():
148 """Return the version of MSVC that was used to build Python.
Greg Ward1b9c6f72000-02-08 02:39:44 +0000149
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000150 For Python 2.3 and up, the version number is included in
151 sys.version. For earlier versions, assume the compiler is MSVC 6.
152 """
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000153 prefix = "MSC v."
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000154 i = sys.version.find(prefix)
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000155 if i == -1:
156 return 6
Marc-André Lemburgf0b5d172003-05-14 19:48:57 +0000157 i = i + len(prefix)
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000158 s, rest = sys.version[i:].split(" ", 1)
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000159 majorVersion = int(s[:-2]) - 6
160 minorVersion = int(s[2:3]) / 10.0
161 # I don't think paths are affected by minor version in version 6
162 if majorVersion == 6:
163 minorVersion = 0
164 if majorVersion >= 6:
165 return majorVersion + minorVersion
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000166 # else we don't know what version of the compiler this is
167 return None
Tim Peters182b5ac2004-07-18 06:16:08 +0000168
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000169def get_build_architecture():
170 """Return the processor architecture.
171
172 Possible results are "Intel", "Itanium", or "AMD64".
173 """
174
175 prefix = " bit ("
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000176 i = sys.version.find(prefix)
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000177 if i == -1:
178 return "Intel"
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000179 j = sys.version.find(")", i)
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000180 return sys.version[i+len(prefix):j]
Tim Peters32cbc962006-02-20 21:42:18 +0000181
Guido van Rossumd8faa362007-04-27 19:54:29 +0000182def normalize_and_reduce_paths(paths):
183 """Return a list of normalized paths with duplicates removed.
184
185 The current order of paths is maintained.
186 """
187 # Paths are normalized so things like: /a and /a/ aren't both preserved.
188 reduced_paths = []
189 for p in paths:
190 np = os.path.normpath(p)
191 # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
192 if np not in reduced_paths:
193 reduced_paths.append(np)
194 return reduced_paths
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000195
Greg Warddbd12761999-08-29 18:15:07 +0000196
Collin Winter5b7e9d72007-08-30 03:52:21 +0000197class MSVCCompiler(CCompiler) :
Greg Ward3d50b901999-09-08 02:36:01 +0000198 """Concrete class that implements an interface to Microsoft Visual C++,
199 as defined by the CCompiler abstract class."""
Greg Warddbd12761999-08-29 18:15:07 +0000200
Greg Warddf178f91999-09-29 12:29:10 +0000201 compiler_type = 'msvc'
202
Greg Ward992c8f92000-06-25 02:31:16 +0000203 # Just set this so CCompiler's constructor doesn't barf. We currently
204 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
205 # as it really isn't necessary for this sort of single-compiler class.
206 # Would be nice to have a consistent interface with UnixCCompiler,
207 # though, so it's worth thinking about.
208 executables = {}
209
Greg Ward32c4a8a2000-03-06 03:40:29 +0000210 # Private class data (need to distinguish C from C++ source for compiler)
211 _c_extensions = ['.c']
Greg Ward408e9ae2000-08-30 17:32:24 +0000212 _cpp_extensions = ['.cc', '.cpp', '.cxx']
Greg Ward9c0ea132000-09-19 23:56:43 +0000213 _rc_extensions = ['.rc']
214 _mc_extensions = ['.mc']
Greg Ward32c4a8a2000-03-06 03:40:29 +0000215
216 # Needed for the filename generation methods provided by the
217 # base class, CCompiler.
Greg Ward9c0ea132000-09-19 23:56:43 +0000218 src_extensions = (_c_extensions + _cpp_extensions +
219 _rc_extensions + _mc_extensions)
220 res_extension = '.res'
Greg Ward32c4a8a2000-03-06 03:40:29 +0000221 obj_extension = '.obj'
222 static_lib_extension = '.lib'
223 shared_lib_extension = '.dll'
224 static_lib_format = shared_lib_format = '%s%s'
225 exe_extension = '.exe'
226
Collin Winter5b7e9d72007-08-30 03:52:21 +0000227 def __init__(self, verbose=0, dry_run=0, force=0):
Greg Wardc74138d1999-10-03 20:47:52 +0000228 CCompiler.__init__ (self, verbose, dry_run, force)
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000229 self.__version = get_build_version()
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000230 self.__arch = get_build_architecture()
231 if self.__arch == "Intel":
232 # x86
233 if self.__version >= 7:
234 self.__root = r"Software\Microsoft\VisualStudio"
235 self.__macros = MacroExpander(self.__version)
236 else:
237 self.__root = r"Software\Microsoft\Devstudio"
238 self.__product = "Visual Studio version %s" % self.__version
Greg Ward69988092000-02-11 02:47:15 +0000239 else:
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000240 # Win64. Assume this was built with the platform SDK
241 self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
Tim Peters32cbc962006-02-20 21:42:18 +0000242
Martin v. Löwisc72dd382005-03-04 13:50:17 +0000243 self.initialized = False
244
245 def initialize(self):
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000246 self.__paths = []
Neal Norwitzf1a69c12006-08-20 16:25:10 +0000247 if "DISTUTILS_USE_SDK" in os.environ and "MSSdk" in os.environ and self.find_exe("cl.exe"):
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000248 # Assume that the SDK set up everything alright; don't try to be
249 # smarter
250 self.cc = "cl.exe"
251 self.linker = "link.exe"
252 self.lib = "lib.exe"
253 self.rc = "rc.exe"
254 self.mc = "mc.exe"
255 else:
256 self.__paths = self.get_msvc_paths("path")
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000257
Collin Winter5b7e9d72007-08-30 03:52:21 +0000258 if len(self.__paths) == 0:
259 raise DistutilsPlatformError("Python was built with %s, "
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000260 "and extensions need to be built with the same "
Collin Winter5b7e9d72007-08-30 03:52:21 +0000261 "version of the compiler, but it isn't installed."
262 % self.__product)
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000263
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000264 self.cc = self.find_exe("cl.exe")
265 self.linker = self.find_exe("link.exe")
266 self.lib = self.find_exe("lib.exe")
267 self.rc = self.find_exe("rc.exe") # resource compiler
268 self.mc = self.find_exe("mc.exe") # message compiler
269 self.set_path_env_var('lib')
270 self.set_path_env_var('include')
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000271
272 # extend the MSVC path with the current path
273 try:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000274 for p in os.environ['path'].split(';'):
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000275 self.__paths.append(p)
276 except KeyError:
277 pass
Guido van Rossumd8faa362007-04-27 19:54:29 +0000278 self.__paths = normalize_and_reduce_paths(self.__paths)
279 os.environ['path'] = ";".join(self.__paths)
Greg Ward69988092000-02-11 02:47:15 +0000280
Greg Warddbd12761999-08-29 18:15:07 +0000281 self.preprocess_options = None
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000282 if self.__arch == "Intel":
283 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
284 '/DNDEBUG']
285 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
286 '/Z7', '/D_DEBUG']
287 else:
288 # Win64
289 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
290 '/DNDEBUG']
291 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
Tim Peters32cbc962006-02-20 21:42:18 +0000292 '/Z7', '/D_DEBUG']
Greg Warddbd12761999-08-29 18:15:07 +0000293
Greg Ward1b9c6f72000-02-08 02:39:44 +0000294 self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
Thomas Heller41f70382004-11-10 09:01:41 +0000295 if self.__version >= 7:
296 self.ldflags_shared_debug = [
297 '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
298 ]
299 else:
300 self.ldflags_shared_debug = [
301 '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
302 ]
Greg Warddbd12761999-08-29 18:15:07 +0000303 self.ldflags_static = [ '/nologo']
304
Tim Petersa733bd92005-03-12 19:05:58 +0000305 self.initialized = True
Greg Warddbd12761999-08-29 18:15:07 +0000306
307 # -- Worker methods ------------------------------------------------
Greg Warddbd12761999-08-29 18:15:07 +0000308
Collin Winter5b7e9d72007-08-30 03:52:21 +0000309 def object_filenames(self,
310 source_filenames,
311 strip_dir=0,
312 output_dir=''):
Greg Ward9c0ea132000-09-19 23:56:43 +0000313 # Copied from ccompiler.py, extended to return .res as 'object'-file
314 # for .rc input file
315 if output_dir is None: output_dir = ''
316 obj_names = []
317 for src_name in source_filenames:
318 (base, ext) = os.path.splitext (src_name)
Martin v. Löwisb813c532005-08-07 20:51:04 +0000319 base = os.path.splitdrive(base)[1] # Chop off the drive
320 base = base[os.path.isabs(base):] # If abs, chop off leading /
Greg Ward9c0ea132000-09-19 23:56:43 +0000321 if ext not in self.src_extensions:
322 # Better to raise an exception instead of silently continuing
323 # and later complain about sources and targets having
324 # different lengths
325 raise CompileError ("Don't know how to compile %s" % src_name)
326 if strip_dir:
327 base = os.path.basename (base)
328 if ext in self._rc_extensions:
329 obj_names.append (os.path.join (output_dir,
330 base + self.res_extension))
331 elif ext in self._mc_extensions:
332 obj_names.append (os.path.join (output_dir,
333 base + self.res_extension))
334 else:
335 obj_names.append (os.path.join (output_dir,
336 base + self.obj_extension))
337 return obj_names
338
Greg Ward9c0ea132000-09-19 23:56:43 +0000339
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000340 def compile(self, sources,
341 output_dir=None, macros=None, include_dirs=None, debug=0,
342 extra_preargs=None, extra_postargs=None, depends=None):
Greg Warddbd12761999-08-29 18:15:07 +0000343
Collin Winter5b7e9d72007-08-30 03:52:21 +0000344 if not self.initialized:
345 self.initialize()
346 compile_info = self._setup_compile(output_dir, macros, include_dirs,
347 sources, depends, extra_postargs)
348 macros, objects, extra_postargs, pp_opts, build = compile_info
Greg Warddbd12761999-08-29 18:15:07 +0000349
Greg Ward32c4a8a2000-03-06 03:40:29 +0000350 compile_opts = extra_preargs or []
351 compile_opts.append ('/c')
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000352 if debug:
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000353 compile_opts.extend(self.compile_options_debug)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000354 else:
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000355 compile_opts.extend(self.compile_options)
Fred Drakeb94b8492001-12-06 20:51:35 +0000356
Thomas Heller9436a752003-12-05 20:12:23 +0000357 for obj in objects:
358 try:
359 src, ext = build[obj]
360 except KeyError:
361 continue
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000362 if debug:
363 # pass the full pathname to MSVC in debug mode,
364 # this allows the debugger to find the source file
365 # without asking the user to browse for it
366 src = os.path.abspath(src)
Greg Warddbd12761999-08-29 18:15:07 +0000367
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000368 if ext in self._c_extensions:
369 input_opt = "/Tc" + src
370 elif ext in self._cpp_extensions:
371 input_opt = "/Tp" + src
372 elif ext in self._rc_extensions:
373 # compile .RC to .RES file
374 input_opt = src
375 output_opt = "/fo" + obj
Greg Wardd1517112000-05-30 01:56:44 +0000376 try:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000377 self.spawn([self.rc] + pp_opts +
378 [output_opt] + [input_opt])
Guido van Rossumb940e112007-01-10 16:19:56 +0000379 except DistutilsExecError as msg:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000380 raise CompileError(msg)
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000381 continue
382 elif ext in self._mc_extensions:
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000383 # Compile .MC to .RC file to .RES file.
384 # * '-h dir' specifies the directory for the
385 # generated include file
386 # * '-r dir' specifies the target directory of the
387 # generated RC file and the binary message resource
388 # it includes
389 #
390 # For now (since there are no options to change this),
391 # we use the source-directory for the include file and
392 # the build directory for the RC file and message
393 # resources. This works at least for win32all.
Collin Winter5b7e9d72007-08-30 03:52:21 +0000394 h_dir = os.path.dirname(src)
395 rc_dir = os.path.dirname(obj)
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000396 try:
397 # first compile .MC to .RC and .H file
Collin Winter5b7e9d72007-08-30 03:52:21 +0000398 self.spawn([self.mc] +
399 ['-h', h_dir, '-r', rc_dir] + [src])
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000400 base, _ = os.path.splitext (os.path.basename (src))
401 rc_file = os.path.join (rc_dir, base + '.rc')
402 # then compile .RC to .RES file
Collin Winter5b7e9d72007-08-30 03:52:21 +0000403 self.spawn([self.rc] +
404 ["/fo" + obj] + [rc_file])
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000405
Guido van Rossumb940e112007-01-10 16:19:56 +0000406 except DistutilsExecError as msg:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000407 raise CompileError(msg)
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000408 continue
409 else:
410 # how to handle this file?
Collin Winter5b7e9d72007-08-30 03:52:21 +0000411 raise CompileError("Don't know how to compile %s to %s"
412 % (src, obj))
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000413
414 output_opt = "/Fo" + obj
415 try:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000416 self.spawn([self.cc] + compile_opts + pp_opts +
417 [input_opt, output_opt] +
418 extra_postargs)
Guido van Rossumb940e112007-01-10 16:19:56 +0000419 except DistutilsExecError as msg:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000420 raise CompileError(msg)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000421
Greg Ward32c4a8a2000-03-06 03:40:29 +0000422 return objects
Greg Warddbd12761999-08-29 18:15:07 +0000423
Greg Ward3d50b901999-09-08 02:36:01 +0000424
Collin Winter5b7e9d72007-08-30 03:52:21 +0000425 def create_static_lib(self,
426 objects,
427 output_libname,
428 output_dir=None,
429 debug=0,
430 target_lang=None):
Greg Ward3d50b901999-09-08 02:36:01 +0000431
Collin Winter5b7e9d72007-08-30 03:52:21 +0000432 if not self.initialized:
433 self.initialize()
434 (objects, output_dir) = self._fix_object_args(objects, output_dir)
435 output_filename = self.library_filename(output_libname,
436 output_dir=output_dir)
Greg Warddbd12761999-08-29 18:15:07 +0000437
Collin Winter5b7e9d72007-08-30 03:52:21 +0000438 if self._need_link(objects, output_filename):
Greg Ward09fc5422000-03-10 01:49:26 +0000439 lib_args = objects + ['/OUT:' + output_filename]
Greg Ward32c4a8a2000-03-06 03:40:29 +0000440 if debug:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000441 pass # XXX what goes here?
Greg Wardd1517112000-05-30 01:56:44 +0000442 try:
Collin Winterfd519752007-08-30 18:46:25 +0000443 self.spawn([self.lib] + lib_args)
Guido van Rossumb940e112007-01-10 16:19:56 +0000444 except DistutilsExecError as msg:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000445 raise LibError(msg)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000446 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000447 log.debug("skipping %s (up-to-date)", output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000448
Fred Drakeb94b8492001-12-06 20:51:35 +0000449
Collin Winter5b7e9d72007-08-30 03:52:21 +0000450 def link(self,
451 target_desc,
452 objects,
453 output_filename,
454 output_dir=None,
455 libraries=None,
456 library_dirs=None,
457 runtime_library_dirs=None,
458 export_symbols=None,
459 debug=0,
460 extra_preargs=None,
461 extra_postargs=None,
462 build_temp=None,
463 target_lang=None):
Greg Ward32c4a8a2000-03-06 03:40:29 +0000464
Collin Winter5b7e9d72007-08-30 03:52:21 +0000465 if not self.initialized:
466 self.initialize()
467 (objects, output_dir) = self._fix_object_args(objects, output_dir)
468 fixed_args = self._fix_lib_args(libraries, library_dirs,
469 runtime_library_dirs)
470 (libraries, library_dirs, runtime_library_dirs) = fixed_args
Greg Ward2f557a22000-03-26 21:42:28 +0000471
Greg Wardf70c6032000-04-19 02:16:49 +0000472 if runtime_library_dirs:
Greg Ward2f557a22000-03-26 21:42:28 +0000473 self.warn ("I don't know what to do with 'runtime_library_dirs': "
474 + str (runtime_library_dirs))
Fred Drakeb94b8492001-12-06 20:51:35 +0000475
Collin Winter5b7e9d72007-08-30 03:52:21 +0000476 lib_opts = gen_lib_options(self,
477 library_dirs, runtime_library_dirs,
478 libraries)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000479 if output_dir is not None:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000480 output_filename = os.path.join(output_dir, output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000481
Collin Winter5b7e9d72007-08-30 03:52:21 +0000482 if self._need_link(objects, output_filename):
Greg Ward42406482000-09-27 02:08:14 +0000483 if target_desc == CCompiler.EXECUTABLE:
484 if debug:
485 ldflags = self.ldflags_shared_debug[1:]
486 else:
487 ldflags = self.ldflags_shared[1:]
Greg Ward32c4a8a2000-03-06 03:40:29 +0000488 else:
Greg Ward42406482000-09-27 02:08:14 +0000489 if debug:
490 ldflags = self.ldflags_shared_debug
491 else:
492 ldflags = self.ldflags_shared
Greg Ward32c4a8a2000-03-06 03:40:29 +0000493
Greg Ward5299b6a2000-05-20 13:23:21 +0000494 export_opts = []
495 for sym in (export_symbols or []):
496 export_opts.append("/EXPORT:" + sym)
497
Fred Drakeb94b8492001-12-06 20:51:35 +0000498 ld_args = (ldflags + lib_opts + export_opts +
Greg Ward5299b6a2000-05-20 13:23:21 +0000499 objects + ['/OUT:' + output_filename])
Greg Ward32c4a8a2000-03-06 03:40:29 +0000500
Greg Ward159eb922000-08-02 00:00:30 +0000501 # The MSVC linker generates .lib and .exp files, which cannot be
502 # suppressed by any linker switches. The .lib files may even be
503 # needed! Make sure they are generated in the temporary build
504 # directory. Since they have different names for debug and release
505 # builds, they can go into the same directory.
Greg Ward42406482000-09-27 02:08:14 +0000506 if export_symbols is not None:
507 (dll_name, dll_ext) = os.path.splitext(
508 os.path.basename(output_filename))
509 implib_file = os.path.join(
510 os.path.dirname(objects[0]),
511 self.library_filename(dll_name))
512 ld_args.append ('/IMPLIB:' + implib_file)
Greg Ward159eb922000-08-02 00:00:30 +0000513
Greg Ward32c4a8a2000-03-06 03:40:29 +0000514 if extra_preargs:
515 ld_args[:0] = extra_preargs
516 if extra_postargs:
Greg Ward159eb922000-08-02 00:00:30 +0000517 ld_args.extend(extra_postargs)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000518
Collin Winter5b7e9d72007-08-30 03:52:21 +0000519 self.mkpath(os.path.dirname(output_filename))
Greg Wardd1517112000-05-30 01:56:44 +0000520 try:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000521 self.spawn([self.linker] + ld_args)
Guido van Rossumb940e112007-01-10 16:19:56 +0000522 except DistutilsExecError as msg:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000523 raise LinkError(msg)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000524
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000525 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000526 log.debug("skipping %s (up-to-date)", output_filename)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000527
Greg Wardf70c6032000-04-19 02:16:49 +0000528
Greg Ward32c4a8a2000-03-06 03:40:29 +0000529 # -- Miscellaneous methods -----------------------------------------
530 # These are all used by the 'gen_lib_options() function, in
531 # ccompiler.py.
Greg Wardc74138d1999-10-03 20:47:52 +0000532
Collin Winter5b7e9d72007-08-30 03:52:21 +0000533 def library_dir_option(self, dir):
Greg Wardc74138d1999-10-03 20:47:52 +0000534 return "/LIBPATH:" + dir
535
Collin Winter5b7e9d72007-08-30 03:52:21 +0000536 def runtime_library_dir_option(self, dir):
537 raise DistutilsPlatformError(
538 "don't know how to set runtime library search path for MSVC++")
Greg Wardd03f88a2000-03-18 15:19:51 +0000539
Collin Winter5b7e9d72007-08-30 03:52:21 +0000540 def library_option(self, lib):
541 return self.library_filename(lib)
Greg Wardc74138d1999-10-03 20:47:52 +0000542
543
Collin Winter5b7e9d72007-08-30 03:52:21 +0000544 def find_library_file(self, dirs, lib, debug=0):
Greg Wardd1425642000-08-04 01:29:27 +0000545 # Prefer a debugging library if found (and requested), but deal
546 # with it if we don't have one.
547 if debug:
548 try_names = [lib + "_d", lib]
549 else:
550 try_names = [lib]
Greg Wardc74138d1999-10-03 20:47:52 +0000551 for dir in dirs:
Greg Wardd1425642000-08-04 01:29:27 +0000552 for name in try_names:
553 libfile = os.path.join(dir, self.library_filename (name))
554 if os.path.exists(libfile):
555 return libfile
Greg Wardc74138d1999-10-03 20:47:52 +0000556 else:
557 # Oops, didn't find it in *any* of 'dirs'
558 return None
559
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000560 # Helper methods for using the MSVC registry settings
561
562 def find_exe(self, exe):
563 """Return path to an MSVC executable program.
564
565 Tries to find the program in several places: first, one of the
566 MSVC program search paths from the registry; next, the directories
567 in the PATH environment variable. If any of those work, return an
568 absolute path that is known to exist. If none of them work, just
569 return the original program name, 'exe'.
570 """
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000571 for p in self.__paths:
572 fn = os.path.join(os.path.abspath(p), exe)
573 if os.path.isfile(fn):
574 return fn
575
576 # didn't find it; try existing path
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000577 for p in os.environ['Path'].split(';'):
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000578 fn = os.path.join(os.path.abspath(p),exe)
579 if os.path.isfile(fn):
580 return fn
581
582 return exe
Tim Peters182b5ac2004-07-18 06:16:08 +0000583
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000584 def get_msvc_paths(self, path, platform='x86'):
585 """Get a list of devstudio directories (include, lib or path).
586
587 Return a list of strings. The list will be empty if unable to
588 access the registry or appropriate registry keys not found.
589 """
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000590 if not _can_read_reg:
591 return []
592
593 path = path + " dirs"
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000594 if self.__version >= 7:
595 key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
596 % (self.__root, self.__version))
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000597 else:
598 key = (r"%s\6.0\Build System\Components\Platforms"
Jeremy Hylton93724db2003-05-09 16:55:28 +0000599 r"\Win32 (%s)\Directories" % (self.__root, platform))
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000600
601 for base in HKEYS:
602 d = read_values(base, key)
603 if d:
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000604 if self.__version >= 7:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000605 return self.__macros.sub(d[path]).split(";")
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000606 else:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000607 return d[path].split(";")
Thomas Hellerb3105912003-11-28 19:42:56 +0000608 # MSVC 6 seems to create the registry entries we need only when
609 # the GUI is run.
610 if self.__version == 6:
611 for base in HKEYS:
612 if read_values(base, r"%s\6.0" % self.__root) is not None:
613 self.warn("It seems you have Visual Studio 6 installed, "
614 "but the expected registry settings are not present.\n"
615 "You must at least run the Visual Studio GUI once "
616 "so that these entries are created.")
Thomas Wouters477c8d52006-05-27 19:21:47 +0000617 break
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000618 return []
619
620 def set_path_env_var(self, name):
621 """Set environment variable 'name' to an MSVC path type value.
622
623 This is equivalent to a SET command prior to execution of spawned
624 commands.
625 """
626
627 if name == "lib":
628 p = self.get_msvc_paths("library")
629 else:
630 p = self.get_msvc_paths(name)
631 if p:
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000632 os.environ[name] = ';'.join(p)
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000633
634
635if get_build_version() >= 8.0:
636 log.debug("Importing new compiler from distutils.msvc9compiler")
637 OldMSVCCompiler = MSVCCompiler
638 from distutils.msvc9compiler import MSVCCompiler
Christian Heimes5e696852008-04-09 08:37:03 +0000639 # get_build_architecture not really relevant now we support cross-compile
Christian Heimescbf3b5c2007-12-03 21:02:03 +0000640 from distutils.msvc9compiler import MacroExpander