blob: 0e69fd368cac78f3967f16336731c7bd6dc87151 [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
Greg Ward3ce77fd2000-03-02 01:49:45 +000011__revision__ = "$Id$"
Greg Warddbd12761999-08-29 18:15:07 +000012
Tarek Ziadé2b66da72009-12-21 01:22:46 +000013import sys
14import os
15import string
16
17from distutils.errors import (DistutilsExecError, DistutilsPlatformError,
18 CompileError, LibError, LinkError)
19from distutils.ccompiler import CCompiler, gen_lib_options
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000020from distutils import log
Greg Ward62e33932000-02-10 02:52:42 +000021
Greg Ward7642f5c2000-03-31 16:47:40 +000022_can_read_reg = 0
23try:
Greg Ward1b5ec762000-06-30 19:37:59 +000024 import _winreg
Greg Ward83c38702000-06-29 23:04:59 +000025
Greg Ward7642f5c2000-03-31 16:47:40 +000026 _can_read_reg = 1
Greg Wardcd079c42000-06-29 22:59:10 +000027 hkey_mod = _winreg
Greg Ward19ce1662000-03-31 19:04:25 +000028
Greg Wardcd079c42000-06-29 22:59:10 +000029 RegOpenKeyEx = _winreg.OpenKeyEx
30 RegEnumKey = _winreg.EnumKey
31 RegEnumValue = _winreg.EnumValue
32 RegError = _winreg.error
Greg Ward19ce1662000-03-31 19:04:25 +000033
Greg Ward7642f5c2000-03-31 16:47:40 +000034except ImportError:
35 try:
36 import win32api
37 import win32con
Greg Ward7642f5c2000-03-31 16:47:40 +000038 _can_read_reg = 1
Greg Ward1027e3f2000-03-31 16:53:42 +000039 hkey_mod = win32con
Greg Ward19ce1662000-03-31 19:04:25 +000040
41 RegOpenKeyEx = win32api.RegOpenKeyEx
42 RegEnumKey = win32api.RegEnumKey
43 RegEnumValue = win32api.RegEnumValue
44 RegError = win32api.error
45
Greg Ward7642f5c2000-03-31 16:47:40 +000046 except ImportError:
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +000047 log.info("Warning: Can't read registry to find the "
48 "necessary compiler setting\n"
49 "Make sure that Python modules _winreg, "
50 "win32api or win32con are installed.")
Greg Ward7642f5c2000-03-31 16:47:40 +000051 pass
Greg Ward1027e3f2000-03-31 16:53:42 +000052
53if _can_read_reg:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000054 HKEYS = (hkey_mod.HKEY_USERS,
55 hkey_mod.HKEY_CURRENT_USER,
56 hkey_mod.HKEY_LOCAL_MACHINE,
57 hkey_mod.HKEY_CLASSES_ROOT)
Fred Drakeb94b8492001-12-06 20:51:35 +000058
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000059def read_keys(base, key):
60 """Return list of registry keys."""
Fred Drakeb94b8492001-12-06 20:51:35 +000061
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000062 try:
63 handle = RegOpenKeyEx(base, key)
64 except RegError:
65 return None
Greg Ward1b9c6f72000-02-08 02:39:44 +000066 L = []
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000067 i = 0
68 while 1:
Greg Ward1b9c6f72000-02-08 02:39:44 +000069 try:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000070 k = RegEnumKey(handle, i)
Greg Ward1027e3f2000-03-31 16:53:42 +000071 except RegError:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000072 break
73 L.append(k)
74 i = i + 1
Greg Ward1b9c6f72000-02-08 02:39:44 +000075 return L
76
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000077def read_values(base, key):
78 """Return dict of registry keys and values.
Greg Ward62e33932000-02-10 02:52:42 +000079
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000080 All names are converted to lowercase.
81 """
82 try:
83 handle = RegOpenKeyEx(base, key)
84 except RegError:
85 return None
86 d = {}
87 i = 0
88 while 1:
Greg Ward1b9c6f72000-02-08 02:39:44 +000089 try:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000090 name, value, type = RegEnumValue(handle, i)
Greg Ward1027e3f2000-03-31 16:53:42 +000091 except RegError:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000092 break
93 name = name.lower()
94 d[convert_mbcs(name)] = convert_mbcs(value)
95 i = i + 1
96 return d
97
98def convert_mbcs(s):
99 enc = getattr(s, "encode", None)
100 if enc is not None:
101 try:
102 s = enc("mbcs")
103 except UnicodeError:
Greg Ward1b9c6f72000-02-08 02:39:44 +0000104 pass
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000105 return s
Greg Ward1b9c6f72000-02-08 02:39:44 +0000106
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000107class MacroExpander:
Greg Ward62e33932000-02-10 02:52:42 +0000108
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000109 def __init__(self, version):
110 self.macros = {}
111 self.load_macros(version)
Greg Ward62e33932000-02-10 02:52:42 +0000112
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000113 def set_macro(self, macro, path, key):
114 for base in HKEYS:
115 d = read_values(base, path)
116 if d:
117 self.macros["$(%s)" % macro] = d[key]
118 break
Tim Peters182b5ac2004-07-18 06:16:08 +0000119
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000120 def load_macros(self, version):
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000121 vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000122 self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
123 self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
124 net = r"Software\Microsoft\.NETFramework"
125 self.set_macro("FrameworkDir", net, "installroot")
Tim Peters26be2062004-11-28 01:10:01 +0000126 try:
127 if version > 7.0:
128 self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
129 else:
130 self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
Tarek Ziadé2b66da72009-12-21 01:22:46 +0000131 except KeyError:
Fredrik Lundhcb328f32004-11-24 22:31:11 +0000132 raise DistutilsPlatformError, \
Martin v. Löwis77621582006-07-30 13:27:31 +0000133 ("""Python was built with Visual Studio 2003;
134extensions must be built with a compiler than can generate compatible binaries.
135Visual Studio 2003 was not found on this system. If you have Cygwin installed,
136you can try compiling with MingW32, by passing "-c mingw32" to setup.py.""")
Greg Ward1b9c6f72000-02-08 02:39:44 +0000137
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000138 p = r"Software\Microsoft\NET Framework Setup\Product"
139 for base in HKEYS:
140 try:
141 h = RegOpenKeyEx(base, p)
142 except RegError:
143 continue
144 key = RegEnumKey(h, 0)
145 d = read_values(base, r"%s\%s" % (p, key))
146 self.macros["$(FrameworkVersion)"] = d["version"]
Greg Ward69988092000-02-11 02:47:15 +0000147
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000148 def sub(self, s):
149 for k, v in self.macros.items():
150 s = string.replace(s, k, v)
151 return s
Greg Ward69988092000-02-11 02:47:15 +0000152
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000153def get_build_version():
154 """Return the version of MSVC that was used to build Python.
Greg Ward1b9c6f72000-02-08 02:39:44 +0000155
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000156 For Python 2.3 and up, the version number is included in
157 sys.version. For earlier versions, assume the compiler is MSVC 6.
158 """
Greg Ward62e33932000-02-10 02:52:42 +0000159
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000160 prefix = "MSC v."
161 i = string.find(sys.version, prefix)
162 if i == -1:
163 return 6
Marc-André Lemburgf0b5d172003-05-14 19:48:57 +0000164 i = i + len(prefix)
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000165 s, rest = sys.version[i:].split(" ", 1)
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000166 majorVersion = int(s[:-2]) - 6
167 minorVersion = int(s[2:3]) / 10.0
168 # I don't think paths are affected by minor version in version 6
169 if majorVersion == 6:
170 minorVersion = 0
171 if majorVersion >= 6:
172 return majorVersion + minorVersion
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000173 # else we don't know what version of the compiler this is
174 return None
Tim Peters182b5ac2004-07-18 06:16:08 +0000175
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000176def get_build_architecture():
177 """Return the processor architecture.
178
179 Possible results are "Intel", "Itanium", or "AMD64".
180 """
181
182 prefix = " bit ("
183 i = string.find(sys.version, prefix)
184 if i == -1:
185 return "Intel"
186 j = string.find(sys.version, ")", i)
187 return sys.version[i+len(prefix):j]
Tim Peters32cbc962006-02-20 21:42:18 +0000188
Neal Norwitz8f35f442007-04-01 18:24:22 +0000189def normalize_and_reduce_paths(paths):
190 """Return a list of normalized paths with duplicates removed.
191
192 The current order of paths is maintained.
193 """
194 # Paths are normalized so things like: /a and /a/ aren't both preserved.
195 reduced_paths = []
196 for p in paths:
197 np = os.path.normpath(p)
198 # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
199 if np not in reduced_paths:
200 reduced_paths.append(np)
201 return reduced_paths
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000202
Greg Warddbd12761999-08-29 18:15:07 +0000203
Greg Ward3d50b901999-09-08 02:36:01 +0000204class MSVCCompiler (CCompiler) :
205 """Concrete class that implements an interface to Microsoft Visual C++,
206 as defined by the CCompiler abstract class."""
Greg Warddbd12761999-08-29 18:15:07 +0000207
Greg Warddf178f91999-09-29 12:29:10 +0000208 compiler_type = 'msvc'
209
Greg Ward992c8f92000-06-25 02:31:16 +0000210 # Just set this so CCompiler's constructor doesn't barf. We currently
211 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
212 # as it really isn't necessary for this sort of single-compiler class.
213 # Would be nice to have a consistent interface with UnixCCompiler,
214 # though, so it's worth thinking about.
215 executables = {}
216
Greg Ward32c4a8a2000-03-06 03:40:29 +0000217 # Private class data (need to distinguish C from C++ source for compiler)
218 _c_extensions = ['.c']
Greg Ward408e9ae2000-08-30 17:32:24 +0000219 _cpp_extensions = ['.cc', '.cpp', '.cxx']
Greg Ward9c0ea132000-09-19 23:56:43 +0000220 _rc_extensions = ['.rc']
221 _mc_extensions = ['.mc']
Greg Ward32c4a8a2000-03-06 03:40:29 +0000222
223 # Needed for the filename generation methods provided by the
224 # base class, CCompiler.
Greg Ward9c0ea132000-09-19 23:56:43 +0000225 src_extensions = (_c_extensions + _cpp_extensions +
226 _rc_extensions + _mc_extensions)
227 res_extension = '.res'
Greg Ward32c4a8a2000-03-06 03:40:29 +0000228 obj_extension = '.obj'
229 static_lib_extension = '.lib'
230 shared_lib_extension = '.dll'
231 static_lib_format = shared_lib_format = '%s%s'
232 exe_extension = '.exe'
233
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000234 def __init__ (self, verbose=0, dry_run=0, force=0):
Greg Wardc74138d1999-10-03 20:47:52 +0000235 CCompiler.__init__ (self, verbose, dry_run, force)
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000236 self.__version = get_build_version()
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000237 self.__arch = get_build_architecture()
238 if self.__arch == "Intel":
239 # x86
240 if self.__version >= 7:
241 self.__root = r"Software\Microsoft\VisualStudio"
242 self.__macros = MacroExpander(self.__version)
243 else:
244 self.__root = r"Software\Microsoft\Devstudio"
245 self.__product = "Visual Studio version %s" % self.__version
Greg Ward69988092000-02-11 02:47:15 +0000246 else:
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000247 # Win64. Assume this was built with the platform SDK
248 self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
Tim Peters32cbc962006-02-20 21:42:18 +0000249
Martin v. Löwisc72dd382005-03-04 13:50:17 +0000250 self.initialized = False
251
252 def initialize(self):
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000253 self.__paths = []
Guido van Rossum8bc09652008-02-21 18:18:37 +0000254 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 +0000255 # Assume that the SDK set up everything alright; don't try to be
256 # smarter
257 self.cc = "cl.exe"
258 self.linker = "link.exe"
259 self.lib = "lib.exe"
260 self.rc = "rc.exe"
261 self.mc = "mc.exe"
262 else:
263 self.__paths = self.get_msvc_paths("path")
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000264
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000265 if len (self.__paths) == 0:
266 raise DistutilsPlatformError, \
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000267 ("Python was built with %s, "
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000268 "and extensions need to be built with the same "
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000269 "version of the compiler, but it isn't installed." % self.__product)
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000270
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000271 self.cc = self.find_exe("cl.exe")
272 self.linker = self.find_exe("link.exe")
273 self.lib = self.find_exe("lib.exe")
274 self.rc = self.find_exe("rc.exe") # resource compiler
275 self.mc = self.find_exe("mc.exe") # message compiler
276 self.set_path_env_var('lib')
277 self.set_path_env_var('include')
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000278
279 # extend the MSVC path with the current path
280 try:
281 for p in string.split(os.environ['path'], ';'):
282 self.__paths.append(p)
283 except KeyError:
284 pass
Neal Norwitz8f35f442007-04-01 18:24:22 +0000285 self.__paths = normalize_and_reduce_paths(self.__paths)
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000286 os.environ['path'] = string.join(self.__paths, ';')
Greg Ward69988092000-02-11 02:47:15 +0000287
Greg Warddbd12761999-08-29 18:15:07 +0000288 self.preprocess_options = None
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000289 if self.__arch == "Intel":
290 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
291 '/DNDEBUG']
292 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
293 '/Z7', '/D_DEBUG']
294 else:
295 # Win64
296 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
297 '/DNDEBUG']
298 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
Tim Peters32cbc962006-02-20 21:42:18 +0000299 '/Z7', '/D_DEBUG']
Greg Warddbd12761999-08-29 18:15:07 +0000300
Greg Ward1b9c6f72000-02-08 02:39:44 +0000301 self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
Thomas Heller41f70382004-11-10 09:01:41 +0000302 if self.__version >= 7:
303 self.ldflags_shared_debug = [
304 '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
305 ]
306 else:
307 self.ldflags_shared_debug = [
308 '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
309 ]
Greg Warddbd12761999-08-29 18:15:07 +0000310 self.ldflags_static = [ '/nologo']
311
Tim Petersa733bd92005-03-12 19:05:58 +0000312 self.initialized = True
Greg Warddbd12761999-08-29 18:15:07 +0000313
314 # -- Worker methods ------------------------------------------------
Greg Warddbd12761999-08-29 18:15:07 +0000315
Greg Ward9c0ea132000-09-19 23:56:43 +0000316 def object_filenames (self,
317 source_filenames,
318 strip_dir=0,
319 output_dir=''):
320 # Copied from ccompiler.py, extended to return .res as 'object'-file
321 # for .rc input file
322 if output_dir is None: output_dir = ''
323 obj_names = []
324 for src_name in source_filenames:
325 (base, ext) = os.path.splitext (src_name)
Martin v. Löwisb813c532005-08-07 20:51:04 +0000326 base = os.path.splitdrive(base)[1] # Chop off the drive
327 base = base[os.path.isabs(base):] # If abs, chop off leading /
Greg Ward9c0ea132000-09-19 23:56:43 +0000328 if ext not in self.src_extensions:
329 # Better to raise an exception instead of silently continuing
330 # and later complain about sources and targets having
331 # different lengths
332 raise CompileError ("Don't know how to compile %s" % src_name)
333 if strip_dir:
334 base = os.path.basename (base)
335 if ext in self._rc_extensions:
336 obj_names.append (os.path.join (output_dir,
337 base + self.res_extension))
338 elif ext in self._mc_extensions:
339 obj_names.append (os.path.join (output_dir,
340 base + self.res_extension))
341 else:
342 obj_names.append (os.path.join (output_dir,
343 base + self.obj_extension))
344 return obj_names
345
346 # object_filenames ()
347
348
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000349 def compile(self, sources,
350 output_dir=None, macros=None, include_dirs=None, debug=0,
351 extra_preargs=None, extra_postargs=None, depends=None):
Greg Warddbd12761999-08-29 18:15:07 +0000352
Brett Cannon3304a142005-03-05 05:28:45 +0000353 if not self.initialized: self.initialize()
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000354 macros, objects, extra_postargs, pp_opts, build = \
355 self._setup_compile(output_dir, macros, include_dirs, sources,
356 depends, extra_postargs)
Greg Warddbd12761999-08-29 18:15:07 +0000357
Greg Ward32c4a8a2000-03-06 03:40:29 +0000358 compile_opts = extra_preargs or []
359 compile_opts.append ('/c')
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000360 if debug:
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000361 compile_opts.extend(self.compile_options_debug)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000362 else:
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000363 compile_opts.extend(self.compile_options)
Fred Drakeb94b8492001-12-06 20:51:35 +0000364
Thomas Heller9436a752003-12-05 20:12:23 +0000365 for obj in objects:
366 try:
367 src, ext = build[obj]
368 except KeyError:
369 continue
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000370 if debug:
371 # pass the full pathname to MSVC in debug mode,
372 # this allows the debugger to find the source file
373 # without asking the user to browse for it
374 src = os.path.abspath(src)
Greg Warddbd12761999-08-29 18:15:07 +0000375
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000376 if ext in self._c_extensions:
377 input_opt = "/Tc" + src
378 elif ext in self._cpp_extensions:
379 input_opt = "/Tp" + src
380 elif ext in self._rc_extensions:
381 # compile .RC to .RES file
382 input_opt = src
383 output_opt = "/fo" + obj
Greg Wardd1517112000-05-30 01:56:44 +0000384 try:
Thomas Heller95827942003-01-31 20:40:15 +0000385 self.spawn ([self.rc] + pp_opts +
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000386 [output_opt] + [input_opt])
Greg Wardd1517112000-05-30 01:56:44 +0000387 except DistutilsExecError, msg:
388 raise CompileError, msg
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000389 continue
390 elif ext in self._mc_extensions:
391
392 # Compile .MC to .RC file to .RES file.
393 # * '-h dir' specifies the directory for the
394 # generated include file
395 # * '-r dir' specifies the target directory of the
396 # generated RC file and the binary message resource
397 # it includes
398 #
399 # For now (since there are no options to change this),
400 # we use the source-directory for the include file and
401 # the build directory for the RC file and message
402 # resources. This works at least for win32all.
403
404 h_dir = os.path.dirname (src)
405 rc_dir = os.path.dirname (obj)
406 try:
407 # first compile .MC to .RC and .H file
408 self.spawn ([self.mc] +
409 ['-h', h_dir, '-r', rc_dir] + [src])
410 base, _ = os.path.splitext (os.path.basename (src))
411 rc_file = os.path.join (rc_dir, base + '.rc')
412 # then compile .RC to .RES file
413 self.spawn ([self.rc] +
414 ["/fo" + obj] + [rc_file])
415
416 except DistutilsExecError, msg:
417 raise CompileError, msg
418 continue
419 else:
420 # how to handle this file?
421 raise CompileError (
422 "Don't know how to compile %s to %s" % \
423 (src, obj))
424
425 output_opt = "/Fo" + obj
426 try:
427 self.spawn ([self.cc] + compile_opts + pp_opts +
428 [input_opt, output_opt] +
429 extra_postargs)
430 except DistutilsExecError, msg:
431 raise CompileError, msg
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000432
Greg Ward32c4a8a2000-03-06 03:40:29 +0000433 return objects
Greg Warddbd12761999-08-29 18:15:07 +0000434
Greg Ward32c4a8a2000-03-06 03:40:29 +0000435 # compile ()
Greg Ward3d50b901999-09-08 02:36:01 +0000436
437
Greg Ward09fc5422000-03-10 01:49:26 +0000438 def create_static_lib (self,
439 objects,
440 output_libname,
441 output_dir=None,
442 debug=0,
Gustavo Niemeyer6b016852002-11-05 16:12:02 +0000443 target_lang=None):
Greg Warddbd12761999-08-29 18:15:07 +0000444
Brett Cannon1bfd85b2005-03-05 05:32:14 +0000445 if not self.initialized: self.initialize()
Greg Ward2f557a22000-03-26 21:42:28 +0000446 (objects, output_dir) = self._fix_object_args (objects, output_dir)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000447 output_filename = \
448 self.library_filename (output_libname, output_dir=output_dir)
Greg Warddbd12761999-08-29 18:15:07 +0000449
Greg Ward32c4a8a2000-03-06 03:40:29 +0000450 if self._need_link (objects, output_filename):
Greg Ward09fc5422000-03-10 01:49:26 +0000451 lib_args = objects + ['/OUT:' + output_filename]
Greg Ward32c4a8a2000-03-06 03:40:29 +0000452 if debug:
453 pass # XXX what goes here?
Greg Wardd1517112000-05-30 01:56:44 +0000454 try:
Greg Ward992c8f92000-06-25 02:31:16 +0000455 self.spawn ([self.lib] + lib_args)
Greg Wardd1517112000-05-30 01:56:44 +0000456 except DistutilsExecError, msg:
457 raise LibError, msg
Fred Drakeb94b8492001-12-06 20:51:35 +0000458
Greg Ward32c4a8a2000-03-06 03:40:29 +0000459 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000460 log.debug("skipping %s (up-to-date)", output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000461
Greg Ward09fc5422000-03-10 01:49:26 +0000462 # create_static_lib ()
Fred Drakeb94b8492001-12-06 20:51:35 +0000463
Greg Ward42406482000-09-27 02:08:14 +0000464 def link (self,
465 target_desc,
466 objects,
467 output_filename,
468 output_dir=None,
469 libraries=None,
470 library_dirs=None,
471 runtime_library_dirs=None,
472 export_symbols=None,
473 debug=0,
474 extra_preargs=None,
475 extra_postargs=None,
Gustavo Niemeyer6b016852002-11-05 16:12:02 +0000476 build_temp=None,
477 target_lang=None):
Greg Ward32c4a8a2000-03-06 03:40:29 +0000478
Brett Cannon1bfd85b2005-03-05 05:32:14 +0000479 if not self.initialized: self.initialize()
Greg Ward2f557a22000-03-26 21:42:28 +0000480 (objects, output_dir) = self._fix_object_args (objects, output_dir)
481 (libraries, library_dirs, runtime_library_dirs) = \
482 self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
483
Greg Wardf70c6032000-04-19 02:16:49 +0000484 if runtime_library_dirs:
Greg Ward2f557a22000-03-26 21:42:28 +0000485 self.warn ("I don't know what to do with 'runtime_library_dirs': "
486 + str (runtime_library_dirs))
Fred Drakeb94b8492001-12-06 20:51:35 +0000487
Greg Wardd03f88a2000-03-18 15:19:51 +0000488 lib_opts = gen_lib_options (self,
Greg Ward2f557a22000-03-26 21:42:28 +0000489 library_dirs, runtime_library_dirs,
Greg Wardd03f88a2000-03-18 15:19:51 +0000490 libraries)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000491 if output_dir is not None:
492 output_filename = os.path.join (output_dir, output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000493
Greg Ward32c4a8a2000-03-06 03:40:29 +0000494 if self._need_link (objects, output_filename):
495
Greg Ward42406482000-09-27 02:08:14 +0000496 if target_desc == CCompiler.EXECUTABLE:
497 if debug:
498 ldflags = self.ldflags_shared_debug[1:]
499 else:
500 ldflags = self.ldflags_shared[1:]
Greg Ward32c4a8a2000-03-06 03:40:29 +0000501 else:
Greg Ward42406482000-09-27 02:08:14 +0000502 if debug:
503 ldflags = self.ldflags_shared_debug
504 else:
505 ldflags = self.ldflags_shared
Greg Ward32c4a8a2000-03-06 03:40:29 +0000506
Greg Ward5299b6a2000-05-20 13:23:21 +0000507 export_opts = []
508 for sym in (export_symbols or []):
509 export_opts.append("/EXPORT:" + sym)
510
Fred Drakeb94b8492001-12-06 20:51:35 +0000511 ld_args = (ldflags + lib_opts + export_opts +
Greg Ward5299b6a2000-05-20 13:23:21 +0000512 objects + ['/OUT:' + output_filename])
Greg Ward32c4a8a2000-03-06 03:40:29 +0000513
Greg Ward159eb922000-08-02 00:00:30 +0000514 # The MSVC linker generates .lib and .exp files, which cannot be
515 # suppressed by any linker switches. The .lib files may even be
516 # needed! Make sure they are generated in the temporary build
517 # directory. Since they have different names for debug and release
518 # builds, they can go into the same directory.
Greg Ward42406482000-09-27 02:08:14 +0000519 if export_symbols is not None:
520 (dll_name, dll_ext) = os.path.splitext(
521 os.path.basename(output_filename))
522 implib_file = os.path.join(
523 os.path.dirname(objects[0]),
524 self.library_filename(dll_name))
525 ld_args.append ('/IMPLIB:' + implib_file)
Greg Ward159eb922000-08-02 00:00:30 +0000526
Greg Ward32c4a8a2000-03-06 03:40:29 +0000527 if extra_preargs:
528 ld_args[:0] = extra_preargs
529 if extra_postargs:
Greg Ward159eb922000-08-02 00:00:30 +0000530 ld_args.extend(extra_postargs)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000531
532 self.mkpath (os.path.dirname (output_filename))
Greg Wardd1517112000-05-30 01:56:44 +0000533 try:
Greg Ward42406482000-09-27 02:08:14 +0000534 self.spawn ([self.linker] + ld_args)
Greg Wardd1517112000-05-30 01:56:44 +0000535 except DistutilsExecError, msg:
536 raise LinkError, msg
Greg Ward32c4a8a2000-03-06 03:40:29 +0000537
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000538 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000539 log.debug("skipping %s (up-to-date)", output_filename)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000540
Greg Ward42406482000-09-27 02:08:14 +0000541 # link ()
Greg Wardf70c6032000-04-19 02:16:49 +0000542
543
Greg Ward32c4a8a2000-03-06 03:40:29 +0000544 # -- Miscellaneous methods -----------------------------------------
545 # These are all used by the 'gen_lib_options() function, in
546 # ccompiler.py.
Greg Wardc74138d1999-10-03 20:47:52 +0000547
548 def library_dir_option (self, dir):
549 return "/LIBPATH:" + dir
550
Greg Wardd03f88a2000-03-18 15:19:51 +0000551 def runtime_library_dir_option (self, dir):
552 raise DistutilsPlatformError, \
553 "don't know how to set runtime library search path for MSVC++"
554
Greg Wardc74138d1999-10-03 20:47:52 +0000555 def library_option (self, lib):
556 return self.library_filename (lib)
557
558
Greg Wardd1425642000-08-04 01:29:27 +0000559 def find_library_file (self, dirs, lib, debug=0):
560 # Prefer a debugging library if found (and requested), but deal
561 # with it if we don't have one.
562 if debug:
563 try_names = [lib + "_d", lib]
564 else:
565 try_names = [lib]
Greg Wardc74138d1999-10-03 20:47:52 +0000566 for dir in dirs:
Greg Wardd1425642000-08-04 01:29:27 +0000567 for name in try_names:
568 libfile = os.path.join(dir, self.library_filename (name))
569 if os.path.exists(libfile):
570 return libfile
Greg Wardc74138d1999-10-03 20:47:52 +0000571 else:
572 # Oops, didn't find it in *any* of 'dirs'
573 return None
574
575 # find_library_file ()
576
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000577 # Helper methods for using the MSVC registry settings
578
579 def find_exe(self, exe):
580 """Return path to an MSVC executable program.
581
582 Tries to find the program in several places: first, one of the
583 MSVC program search paths from the registry; next, the directories
584 in the PATH environment variable. If any of those work, return an
585 absolute path that is known to exist. If none of them work, just
586 return the original program name, 'exe'.
587 """
588
589 for p in self.__paths:
590 fn = os.path.join(os.path.abspath(p), exe)
591 if os.path.isfile(fn):
592 return fn
593
594 # didn't find it; try existing path
595 for p in string.split(os.environ['Path'],';'):
596 fn = os.path.join(os.path.abspath(p),exe)
597 if os.path.isfile(fn):
598 return fn
599
600 return exe
Tim Peters182b5ac2004-07-18 06:16:08 +0000601
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000602 def get_msvc_paths(self, path, platform='x86'):
603 """Get a list of devstudio directories (include, lib or path).
604
605 Return a list of strings. The list will be empty if unable to
606 access the registry or appropriate registry keys not found.
607 """
608
609 if not _can_read_reg:
610 return []
611
612 path = path + " dirs"
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000613 if self.__version >= 7:
614 key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
615 % (self.__root, self.__version))
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000616 else:
617 key = (r"%s\6.0\Build System\Components\Platforms"
Jeremy Hylton93724db2003-05-09 16:55:28 +0000618 r"\Win32 (%s)\Directories" % (self.__root, platform))
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000619
620 for base in HKEYS:
621 d = read_values(base, key)
622 if d:
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000623 if self.__version >= 7:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000624 return string.split(self.__macros.sub(d[path]), ";")
625 else:
626 return string.split(d[path], ";")
Thomas Hellerb3105912003-11-28 19:42:56 +0000627 # MSVC 6 seems to create the registry entries we need only when
628 # the GUI is run.
629 if self.__version == 6:
630 for base in HKEYS:
631 if read_values(base, r"%s\6.0" % self.__root) is not None:
632 self.warn("It seems you have Visual Studio 6 installed, "
633 "but the expected registry settings are not present.\n"
634 "You must at least run the Visual Studio GUI once "
635 "so that these entries are created.")
Trent Micke96b2292006-04-25 00:34:50 +0000636 break
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000637 return []
638
639 def set_path_env_var(self, name):
640 """Set environment variable 'name' to an MSVC path type value.
641
642 This is equivalent to a SET command prior to execution of spawned
643 commands.
644 """
645
646 if name == "lib":
647 p = self.get_msvc_paths("library")
648 else:
649 p = self.get_msvc_paths(name)
650 if p:
651 os.environ[name] = string.join(p, ';')
Christian Heimes3305c522007-12-03 13:47:29 +0000652
653
654if get_build_version() >= 8.0:
655 log.debug("Importing new compiler from distutils.msvc9compiler")
656 OldMSVCCompiler = MSVCCompiler
657 from distutils.msvc9compiler import MSVCCompiler
Mark Hammond495cf992008-04-07 01:53:39 +0000658 # get_build_architecture not really relevant now we support cross-compile
Christian Heimes3305c522007-12-03 13:47:29 +0000659 from distutils.msvc9compiler import MacroExpander