blob: d725905bd0c5d921eafd58127f900282dc6a28d7 [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
Martin v. Löwis5a6601c2004-11-10 22:23:15 +000011# This module should be kept compatible with Python 2.1.
Andrew M. Kuchlingd448f662002-11-19 13:12:28 +000012
Greg Ward3ce77fd2000-03-02 01:49:45 +000013__revision__ = "$Id$"
Greg Warddbd12761999-08-29 18:15:07 +000014
Greg Ward32c4a8a2000-03-06 03:40:29 +000015import sys, os, string
Greg Ward3add77f2000-05-30 02:02:49 +000016from distutils.errors import \
17 DistutilsExecError, DistutilsPlatformError, \
Greg Wardd1517112000-05-30 01:56:44 +000018 CompileError, LibError, LinkError
Greg Ward3add77f2000-05-30 02:02:49 +000019from distutils.ccompiler import \
20 CCompiler, gen_preprocess_options, gen_lib_options
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000021from distutils import log
Greg Ward62e33932000-02-10 02:52:42 +000022
Greg Ward7642f5c2000-03-31 16:47:40 +000023_can_read_reg = 0
24try:
Greg Ward1b5ec762000-06-30 19:37:59 +000025 import _winreg
Greg Ward83c38702000-06-29 23:04:59 +000026
Greg Ward7642f5c2000-03-31 16:47:40 +000027 _can_read_reg = 1
Greg Wardcd079c42000-06-29 22:59:10 +000028 hkey_mod = _winreg
Greg Ward19ce1662000-03-31 19:04:25 +000029
Greg Wardcd079c42000-06-29 22:59:10 +000030 RegOpenKeyEx = _winreg.OpenKeyEx
31 RegEnumKey = _winreg.EnumKey
32 RegEnumValue = _winreg.EnumValue
33 RegError = _winreg.error
Greg Ward19ce1662000-03-31 19:04:25 +000034
Greg Ward7642f5c2000-03-31 16:47:40 +000035except ImportError:
36 try:
37 import win32api
38 import win32con
Greg Ward7642f5c2000-03-31 16:47:40 +000039 _can_read_reg = 1
Greg Ward1027e3f2000-03-31 16:53:42 +000040 hkey_mod = win32con
Greg Ward19ce1662000-03-31 19:04:25 +000041
42 RegOpenKeyEx = win32api.RegOpenKeyEx
43 RegEnumKey = win32api.RegEnumKey
44 RegEnumValue = win32api.RegEnumValue
45 RegError = win32api.error
46
Greg Ward7642f5c2000-03-31 16:47:40 +000047 except ImportError:
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +000048 log.info("Warning: Can't read registry to find the "
49 "necessary compiler setting\n"
50 "Make sure that Python modules _winreg, "
51 "win32api or win32con are installed.")
Greg Ward7642f5c2000-03-31 16:47:40 +000052 pass
Greg Ward1027e3f2000-03-31 16:53:42 +000053
54if _can_read_reg:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000055 HKEYS = (hkey_mod.HKEY_USERS,
56 hkey_mod.HKEY_CURRENT_USER,
57 hkey_mod.HKEY_LOCAL_MACHINE,
58 hkey_mod.HKEY_CLASSES_ROOT)
Fred Drakeb94b8492001-12-06 20:51:35 +000059
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000060def read_keys(base, key):
61 """Return list of registry keys."""
Fred Drakeb94b8492001-12-06 20:51:35 +000062
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000063 try:
64 handle = RegOpenKeyEx(base, key)
65 except RegError:
66 return None
Greg Ward1b9c6f72000-02-08 02:39:44 +000067 L = []
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000068 i = 0
69 while 1:
Greg Ward1b9c6f72000-02-08 02:39:44 +000070 try:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000071 k = RegEnumKey(handle, i)
Greg Ward1027e3f2000-03-31 16:53:42 +000072 except RegError:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000073 break
74 L.append(k)
75 i = i + 1
Greg Ward1b9c6f72000-02-08 02:39:44 +000076 return L
77
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000078def read_values(base, key):
79 """Return dict of registry keys and values.
Greg Ward62e33932000-02-10 02:52:42 +000080
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000081 All names are converted to lowercase.
82 """
83 try:
84 handle = RegOpenKeyEx(base, key)
85 except RegError:
86 return None
87 d = {}
88 i = 0
89 while 1:
Greg Ward1b9c6f72000-02-08 02:39:44 +000090 try:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000091 name, value, type = RegEnumValue(handle, i)
Greg Ward1027e3f2000-03-31 16:53:42 +000092 except RegError:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +000093 break
94 name = name.lower()
95 d[convert_mbcs(name)] = convert_mbcs(value)
96 i = i + 1
97 return d
98
99def convert_mbcs(s):
100 enc = getattr(s, "encode", None)
101 if enc is not None:
102 try:
103 s = enc("mbcs")
104 except UnicodeError:
Greg Ward1b9c6f72000-02-08 02:39:44 +0000105 pass
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000106 return s
Greg Ward1b9c6f72000-02-08 02:39:44 +0000107
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000108class MacroExpander:
Greg Ward62e33932000-02-10 02:52:42 +0000109
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000110 def __init__(self, version):
111 self.macros = {}
112 self.load_macros(version)
Greg Ward62e33932000-02-10 02:52:42 +0000113
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000114 def set_macro(self, macro, path, key):
115 for base in HKEYS:
116 d = read_values(base, path)
117 if d:
118 self.macros["$(%s)" % macro] = d[key]
119 break
Tim Peters182b5ac2004-07-18 06:16:08 +0000120
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000121 def load_macros(self, version):
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000122 vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000123 self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
124 self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
125 net = r"Software\Microsoft\.NETFramework"
126 self.set_macro("FrameworkDir", net, "installroot")
Tim Peters26be2062004-11-28 01:10:01 +0000127 try:
128 if version > 7.0:
129 self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
130 else:
131 self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
132 except KeyError, exc: #
Fredrik Lundhcb328f32004-11-24 22:31:11 +0000133 raise DistutilsPlatformError, \
134 ("The .NET Framework SDK needs to be installed before "
135 "building extensions for Python.")
Greg Ward1b9c6f72000-02-08 02:39:44 +0000136
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000137 p = r"Software\Microsoft\NET Framework Setup\Product"
138 for base in HKEYS:
139 try:
140 h = RegOpenKeyEx(base, p)
141 except RegError:
142 continue
143 key = RegEnumKey(h, 0)
144 d = read_values(base, r"%s\%s" % (p, key))
145 self.macros["$(FrameworkVersion)"] = d["version"]
Greg Ward69988092000-02-11 02:47:15 +0000146
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000147 def sub(self, s):
148 for k, v in self.macros.items():
149 s = string.replace(s, k, v)
150 return s
Greg Ward69988092000-02-11 02:47:15 +0000151
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000152def get_build_version():
153 """Return the version of MSVC that was used to build Python.
Greg Ward1b9c6f72000-02-08 02:39:44 +0000154
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000155 For Python 2.3 and up, the version number is included in
156 sys.version. For earlier versions, assume the compiler is MSVC 6.
157 """
Greg Ward62e33932000-02-10 02:52:42 +0000158
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000159 prefix = "MSC v."
160 i = string.find(sys.version, prefix)
161 if i == -1:
162 return 6
Marc-André Lemburgf0b5d172003-05-14 19:48:57 +0000163 i = i + len(prefix)
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000164 s, rest = sys.version[i:].split(" ", 1)
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000165 majorVersion = int(s[:-2]) - 6
166 minorVersion = int(s[2:3]) / 10.0
167 # I don't think paths are affected by minor version in version 6
168 if majorVersion == 6:
169 minorVersion = 0
170 if majorVersion >= 6:
171 return majorVersion + minorVersion
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000172 # else we don't know what version of the compiler this is
173 return None
Tim Peters182b5ac2004-07-18 06:16:08 +0000174
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000175def get_build_architecture():
176 """Return the processor architecture.
177
178 Possible results are "Intel", "Itanium", or "AMD64".
179 """
180
181 prefix = " bit ("
182 i = string.find(sys.version, prefix)
183 if i == -1:
184 return "Intel"
185 j = string.find(sys.version, ")", i)
186 return sys.version[i+len(prefix):j]
Tim Peters32cbc962006-02-20 21:42:18 +0000187
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000188
Greg Warddbd12761999-08-29 18:15:07 +0000189
Greg Ward3d50b901999-09-08 02:36:01 +0000190class MSVCCompiler (CCompiler) :
191 """Concrete class that implements an interface to Microsoft Visual C++,
192 as defined by the CCompiler abstract class."""
Greg Warddbd12761999-08-29 18:15:07 +0000193
Greg Warddf178f91999-09-29 12:29:10 +0000194 compiler_type = 'msvc'
195
Greg Ward992c8f92000-06-25 02:31:16 +0000196 # Just set this so CCompiler's constructor doesn't barf. We currently
197 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
198 # as it really isn't necessary for this sort of single-compiler class.
199 # Would be nice to have a consistent interface with UnixCCompiler,
200 # though, so it's worth thinking about.
201 executables = {}
202
Greg Ward32c4a8a2000-03-06 03:40:29 +0000203 # Private class data (need to distinguish C from C++ source for compiler)
204 _c_extensions = ['.c']
Greg Ward408e9ae2000-08-30 17:32:24 +0000205 _cpp_extensions = ['.cc', '.cpp', '.cxx']
Greg Ward9c0ea132000-09-19 23:56:43 +0000206 _rc_extensions = ['.rc']
207 _mc_extensions = ['.mc']
Greg Ward32c4a8a2000-03-06 03:40:29 +0000208
209 # Needed for the filename generation methods provided by the
210 # base class, CCompiler.
Greg Ward9c0ea132000-09-19 23:56:43 +0000211 src_extensions = (_c_extensions + _cpp_extensions +
212 _rc_extensions + _mc_extensions)
213 res_extension = '.res'
Greg Ward32c4a8a2000-03-06 03:40:29 +0000214 obj_extension = '.obj'
215 static_lib_extension = '.lib'
216 shared_lib_extension = '.dll'
217 static_lib_format = shared_lib_format = '%s%s'
218 exe_extension = '.exe'
219
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000220 def __init__ (self, verbose=0, dry_run=0, force=0):
Greg Wardc74138d1999-10-03 20:47:52 +0000221 CCompiler.__init__ (self, verbose, dry_run, force)
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000222 self.__version = get_build_version()
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000223 self.__arch = get_build_architecture()
224 if self.__arch == "Intel":
225 # x86
226 if self.__version >= 7:
227 self.__root = r"Software\Microsoft\VisualStudio"
228 self.__macros = MacroExpander(self.__version)
229 else:
230 self.__root = r"Software\Microsoft\Devstudio"
231 self.__product = "Visual Studio version %s" % self.__version
Greg Ward69988092000-02-11 02:47:15 +0000232 else:
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000233 # Win64. Assume this was built with the platform SDK
234 self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
Tim Peters32cbc962006-02-20 21:42:18 +0000235
Martin v. Löwisc72dd382005-03-04 13:50:17 +0000236 self.initialized = False
237
238 def initialize(self):
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000239 self.__paths = []
Martin v. Löwis8d656812006-07-10 07:23:48 +0000240 if os.environ.has_key("DISTUTILS_USE_SDK") and os.environ.has_key("MSSdk") and self.find_exe("cl.exe"):
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000241 # Assume that the SDK set up everything alright; don't try to be
242 # smarter
243 self.cc = "cl.exe"
244 self.linker = "link.exe"
245 self.lib = "lib.exe"
246 self.rc = "rc.exe"
247 self.mc = "mc.exe"
248 else:
249 self.__paths = self.get_msvc_paths("path")
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000250
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000251 if len (self.__paths) == 0:
252 raise DistutilsPlatformError, \
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000253 ("Python was built with %s, "
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000254 "and extensions need to be built with the same "
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000255 "version of the compiler, but it isn't installed." % self.__product)
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000256
Martin v. Löwise46af8c2006-02-20 12:15:15 +0000257 self.cc = self.find_exe("cl.exe")
258 self.linker = self.find_exe("link.exe")
259 self.lib = self.find_exe("lib.exe")
260 self.rc = self.find_exe("rc.exe") # resource compiler
261 self.mc = self.find_exe("mc.exe") # message compiler
262 self.set_path_env_var('lib')
263 self.set_path_env_var('include')
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000264
265 # extend the MSVC path with the current path
266 try:
267 for p in string.split(os.environ['path'], ';'):
268 self.__paths.append(p)
269 except KeyError:
270 pass
271 os.environ['path'] = string.join(self.__paths, ';')
Greg Ward69988092000-02-11 02:47:15 +0000272
Greg Warddbd12761999-08-29 18:15:07 +0000273 self.preprocess_options = None
Martin v. Löwisde2cde62006-02-20 12:26:58 +0000274 if self.__arch == "Intel":
275 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ,
276 '/DNDEBUG']
277 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
278 '/Z7', '/D_DEBUG']
279 else:
280 # Win64
281 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GS-' ,
282 '/DNDEBUG']
283 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GS-',
Tim Peters32cbc962006-02-20 21:42:18 +0000284 '/Z7', '/D_DEBUG']
Greg Warddbd12761999-08-29 18:15:07 +0000285
Greg Ward1b9c6f72000-02-08 02:39:44 +0000286 self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
Thomas Heller41f70382004-11-10 09:01:41 +0000287 if self.__version >= 7:
288 self.ldflags_shared_debug = [
289 '/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG'
290 ]
291 else:
292 self.ldflags_shared_debug = [
293 '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
294 ]
Greg Warddbd12761999-08-29 18:15:07 +0000295 self.ldflags_static = [ '/nologo']
296
Tim Petersa733bd92005-03-12 19:05:58 +0000297 self.initialized = True
Greg Warddbd12761999-08-29 18:15:07 +0000298
299 # -- Worker methods ------------------------------------------------
Greg Warddbd12761999-08-29 18:15:07 +0000300
Greg Ward9c0ea132000-09-19 23:56:43 +0000301 def object_filenames (self,
302 source_filenames,
303 strip_dir=0,
304 output_dir=''):
305 # Copied from ccompiler.py, extended to return .res as 'object'-file
306 # for .rc input file
307 if output_dir is None: output_dir = ''
308 obj_names = []
309 for src_name in source_filenames:
310 (base, ext) = os.path.splitext (src_name)
Martin v. Löwisb813c532005-08-07 20:51:04 +0000311 base = os.path.splitdrive(base)[1] # Chop off the drive
312 base = base[os.path.isabs(base):] # If abs, chop off leading /
Greg Ward9c0ea132000-09-19 23:56:43 +0000313 if ext not in self.src_extensions:
314 # Better to raise an exception instead of silently continuing
315 # and later complain about sources and targets having
316 # different lengths
317 raise CompileError ("Don't know how to compile %s" % src_name)
318 if strip_dir:
319 base = os.path.basename (base)
320 if ext in self._rc_extensions:
321 obj_names.append (os.path.join (output_dir,
322 base + self.res_extension))
323 elif ext in self._mc_extensions:
324 obj_names.append (os.path.join (output_dir,
325 base + self.res_extension))
326 else:
327 obj_names.append (os.path.join (output_dir,
328 base + self.obj_extension))
329 return obj_names
330
331 # object_filenames ()
332
333
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000334 def compile(self, sources,
335 output_dir=None, macros=None, include_dirs=None, debug=0,
336 extra_preargs=None, extra_postargs=None, depends=None):
Greg Warddbd12761999-08-29 18:15:07 +0000337
Brett Cannon3304a142005-03-05 05:28:45 +0000338 if not self.initialized: self.initialize()
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000339 macros, objects, extra_postargs, pp_opts, build = \
340 self._setup_compile(output_dir, macros, include_dirs, sources,
341 depends, extra_postargs)
Greg Warddbd12761999-08-29 18:15:07 +0000342
Greg Ward32c4a8a2000-03-06 03:40:29 +0000343 compile_opts = extra_preargs or []
344 compile_opts.append ('/c')
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000345 if debug:
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000346 compile_opts.extend(self.compile_options_debug)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000347 else:
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000348 compile_opts.extend(self.compile_options)
Fred Drakeb94b8492001-12-06 20:51:35 +0000349
Thomas Heller9436a752003-12-05 20:12:23 +0000350 for obj in objects:
351 try:
352 src, ext = build[obj]
353 except KeyError:
354 continue
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000355 if debug:
356 # pass the full pathname to MSVC in debug mode,
357 # this allows the debugger to find the source file
358 # without asking the user to browse for it
359 src = os.path.abspath(src)
Greg Warddbd12761999-08-29 18:15:07 +0000360
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000361 if ext in self._c_extensions:
362 input_opt = "/Tc" + src
363 elif ext in self._cpp_extensions:
364 input_opt = "/Tp" + src
365 elif ext in self._rc_extensions:
366 # compile .RC to .RES file
367 input_opt = src
368 output_opt = "/fo" + obj
Greg Wardd1517112000-05-30 01:56:44 +0000369 try:
Thomas Heller95827942003-01-31 20:40:15 +0000370 self.spawn ([self.rc] + pp_opts +
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000371 [output_opt] + [input_opt])
Greg Wardd1517112000-05-30 01:56:44 +0000372 except DistutilsExecError, msg:
373 raise CompileError, msg
Jeremy Hylton1bba31d2002-06-13 17:28:18 +0000374 continue
375 elif ext in self._mc_extensions:
376
377 # Compile .MC to .RC file to .RES file.
378 # * '-h dir' specifies the directory for the
379 # generated include file
380 # * '-r dir' specifies the target directory of the
381 # generated RC file and the binary message resource
382 # it includes
383 #
384 # For now (since there are no options to change this),
385 # we use the source-directory for the include file and
386 # the build directory for the RC file and message
387 # resources. This works at least for win32all.
388
389 h_dir = os.path.dirname (src)
390 rc_dir = os.path.dirname (obj)
391 try:
392 # first compile .MC to .RC and .H file
393 self.spawn ([self.mc] +
394 ['-h', h_dir, '-r', rc_dir] + [src])
395 base, _ = os.path.splitext (os.path.basename (src))
396 rc_file = os.path.join (rc_dir, base + '.rc')
397 # then compile .RC to .RES file
398 self.spawn ([self.rc] +
399 ["/fo" + obj] + [rc_file])
400
401 except DistutilsExecError, msg:
402 raise CompileError, msg
403 continue
404 else:
405 # how to handle this file?
406 raise CompileError (
407 "Don't know how to compile %s to %s" % \
408 (src, obj))
409
410 output_opt = "/Fo" + obj
411 try:
412 self.spawn ([self.cc] + compile_opts + pp_opts +
413 [input_opt, output_opt] +
414 extra_postargs)
415 except DistutilsExecError, msg:
416 raise CompileError, msg
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000417
Greg Ward32c4a8a2000-03-06 03:40:29 +0000418 return objects
Greg Warddbd12761999-08-29 18:15:07 +0000419
Greg Ward32c4a8a2000-03-06 03:40:29 +0000420 # compile ()
Greg Ward3d50b901999-09-08 02:36:01 +0000421
422
Greg Ward09fc5422000-03-10 01:49:26 +0000423 def create_static_lib (self,
424 objects,
425 output_libname,
426 output_dir=None,
427 debug=0,
Gustavo Niemeyer6b016852002-11-05 16:12:02 +0000428 target_lang=None):
Greg Warddbd12761999-08-29 18:15:07 +0000429
Brett Cannon1bfd85b2005-03-05 05:32:14 +0000430 if not self.initialized: self.initialize()
Greg Ward2f557a22000-03-26 21:42:28 +0000431 (objects, output_dir) = self._fix_object_args (objects, output_dir)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000432 output_filename = \
433 self.library_filename (output_libname, output_dir=output_dir)
Greg Warddbd12761999-08-29 18:15:07 +0000434
Greg Ward32c4a8a2000-03-06 03:40:29 +0000435 if self._need_link (objects, output_filename):
Greg Ward09fc5422000-03-10 01:49:26 +0000436 lib_args = objects + ['/OUT:' + output_filename]
Greg Ward32c4a8a2000-03-06 03:40:29 +0000437 if debug:
438 pass # XXX what goes here?
Greg Wardd1517112000-05-30 01:56:44 +0000439 try:
Greg Ward992c8f92000-06-25 02:31:16 +0000440 self.spawn ([self.lib] + lib_args)
Greg Wardd1517112000-05-30 01:56:44 +0000441 except DistutilsExecError, msg:
442 raise LibError, msg
Fred Drakeb94b8492001-12-06 20:51:35 +0000443
Greg Ward32c4a8a2000-03-06 03:40:29 +0000444 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000445 log.debug("skipping %s (up-to-date)", output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000446
Greg Ward09fc5422000-03-10 01:49:26 +0000447 # create_static_lib ()
Fred Drakeb94b8492001-12-06 20:51:35 +0000448
Greg Ward42406482000-09-27 02:08:14 +0000449 def link (self,
450 target_desc,
451 objects,
452 output_filename,
453 output_dir=None,
454 libraries=None,
455 library_dirs=None,
456 runtime_library_dirs=None,
457 export_symbols=None,
458 debug=0,
459 extra_preargs=None,
460 extra_postargs=None,
Gustavo Niemeyer6b016852002-11-05 16:12:02 +0000461 build_temp=None,
462 target_lang=None):
Greg Ward32c4a8a2000-03-06 03:40:29 +0000463
Brett Cannon1bfd85b2005-03-05 05:32:14 +0000464 if not self.initialized: self.initialize()
Greg Ward2f557a22000-03-26 21:42:28 +0000465 (objects, output_dir) = self._fix_object_args (objects, output_dir)
466 (libraries, library_dirs, runtime_library_dirs) = \
467 self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
468
Greg Wardf70c6032000-04-19 02:16:49 +0000469 if runtime_library_dirs:
Greg Ward2f557a22000-03-26 21:42:28 +0000470 self.warn ("I don't know what to do with 'runtime_library_dirs': "
471 + str (runtime_library_dirs))
Fred Drakeb94b8492001-12-06 20:51:35 +0000472
Greg Wardd03f88a2000-03-18 15:19:51 +0000473 lib_opts = gen_lib_options (self,
Greg Ward2f557a22000-03-26 21:42:28 +0000474 library_dirs, runtime_library_dirs,
Greg Wardd03f88a2000-03-18 15:19:51 +0000475 libraries)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000476 if output_dir is not None:
477 output_filename = os.path.join (output_dir, output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000478
Greg Ward32c4a8a2000-03-06 03:40:29 +0000479 if self._need_link (objects, output_filename):
480
Greg Ward42406482000-09-27 02:08:14 +0000481 if target_desc == CCompiler.EXECUTABLE:
482 if debug:
483 ldflags = self.ldflags_shared_debug[1:]
484 else:
485 ldflags = self.ldflags_shared[1:]
Greg Ward32c4a8a2000-03-06 03:40:29 +0000486 else:
Greg Ward42406482000-09-27 02:08:14 +0000487 if debug:
488 ldflags = self.ldflags_shared_debug
489 else:
490 ldflags = self.ldflags_shared
Greg Ward32c4a8a2000-03-06 03:40:29 +0000491
Greg Ward5299b6a2000-05-20 13:23:21 +0000492 export_opts = []
493 for sym in (export_symbols or []):
494 export_opts.append("/EXPORT:" + sym)
495
Fred Drakeb94b8492001-12-06 20:51:35 +0000496 ld_args = (ldflags + lib_opts + export_opts +
Greg Ward5299b6a2000-05-20 13:23:21 +0000497 objects + ['/OUT:' + output_filename])
Greg Ward32c4a8a2000-03-06 03:40:29 +0000498
Greg Ward159eb922000-08-02 00:00:30 +0000499 # The MSVC linker generates .lib and .exp files, which cannot be
500 # suppressed by any linker switches. The .lib files may even be
501 # needed! Make sure they are generated in the temporary build
502 # directory. Since they have different names for debug and release
503 # builds, they can go into the same directory.
Greg Ward42406482000-09-27 02:08:14 +0000504 if export_symbols is not None:
505 (dll_name, dll_ext) = os.path.splitext(
506 os.path.basename(output_filename))
507 implib_file = os.path.join(
508 os.path.dirname(objects[0]),
509 self.library_filename(dll_name))
510 ld_args.append ('/IMPLIB:' + implib_file)
Greg Ward159eb922000-08-02 00:00:30 +0000511
Greg Ward32c4a8a2000-03-06 03:40:29 +0000512 if extra_preargs:
513 ld_args[:0] = extra_preargs
514 if extra_postargs:
Greg Ward159eb922000-08-02 00:00:30 +0000515 ld_args.extend(extra_postargs)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000516
517 self.mkpath (os.path.dirname (output_filename))
Greg Wardd1517112000-05-30 01:56:44 +0000518 try:
Greg Ward42406482000-09-27 02:08:14 +0000519 self.spawn ([self.linker] + ld_args)
Greg Wardd1517112000-05-30 01:56:44 +0000520 except DistutilsExecError, msg:
521 raise LinkError, msg
Greg Ward32c4a8a2000-03-06 03:40:29 +0000522
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000523 else:
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000524 log.debug("skipping %s (up-to-date)", output_filename)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000525
Greg Ward42406482000-09-27 02:08:14 +0000526 # link ()
Greg Wardf70c6032000-04-19 02:16:49 +0000527
528
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
533 def library_dir_option (self, dir):
534 return "/LIBPATH:" + dir
535
Greg Wardd03f88a2000-03-18 15:19:51 +0000536 def runtime_library_dir_option (self, dir):
537 raise DistutilsPlatformError, \
538 "don't know how to set runtime library search path for MSVC++"
539
Greg Wardc74138d1999-10-03 20:47:52 +0000540 def library_option (self, lib):
541 return self.library_filename (lib)
542
543
Greg Wardd1425642000-08-04 01:29:27 +0000544 def find_library_file (self, dirs, lib, debug=0):
545 # 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
560 # find_library_file ()
561
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000562 # Helper methods for using the MSVC registry settings
563
564 def find_exe(self, exe):
565 """Return path to an MSVC executable program.
566
567 Tries to find the program in several places: first, one of the
568 MSVC program search paths from the registry; next, the directories
569 in the PATH environment variable. If any of those work, return an
570 absolute path that is known to exist. If none of them work, just
571 return the original program name, 'exe'.
572 """
573
574 for p in self.__paths:
575 fn = os.path.join(os.path.abspath(p), exe)
576 if os.path.isfile(fn):
577 return fn
578
579 # didn't find it; try existing path
580 for p in string.split(os.environ['Path'],';'):
581 fn = os.path.join(os.path.abspath(p),exe)
582 if os.path.isfile(fn):
583 return fn
584
585 return exe
Tim Peters182b5ac2004-07-18 06:16:08 +0000586
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000587 def get_msvc_paths(self, path, platform='x86'):
588 """Get a list of devstudio directories (include, lib or path).
589
590 Return a list of strings. The list will be empty if unable to
591 access the registry or appropriate registry keys not found.
592 """
593
594 if not _can_read_reg:
595 return []
596
597 path = path + " dirs"
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000598 if self.__version >= 7:
599 key = (r"%s\%0.1f\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories"
600 % (self.__root, self.__version))
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000601 else:
602 key = (r"%s\6.0\Build System\Components\Platforms"
Jeremy Hylton93724db2003-05-09 16:55:28 +0000603 r"\Win32 (%s)\Directories" % (self.__root, platform))
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000604
605 for base in HKEYS:
606 d = read_values(base, key)
607 if d:
Jeremy Hyltone9a92aa2003-07-17 14:41:07 +0000608 if self.__version >= 7:
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000609 return string.split(self.__macros.sub(d[path]), ";")
610 else:
611 return string.split(d[path], ";")
Thomas Hellerb3105912003-11-28 19:42:56 +0000612 # MSVC 6 seems to create the registry entries we need only when
613 # the GUI is run.
614 if self.__version == 6:
615 for base in HKEYS:
616 if read_values(base, r"%s\6.0" % self.__root) is not None:
617 self.warn("It seems you have Visual Studio 6 installed, "
618 "but the expected registry settings are not present.\n"
619 "You must at least run the Visual Studio GUI once "
620 "so that these entries are created.")
Trent Micke96b2292006-04-25 00:34:50 +0000621 break
Jeremy Hylton9ddf6c32003-05-09 16:06:42 +0000622 return []
623
624 def set_path_env_var(self, name):
625 """Set environment variable 'name' to an MSVC path type value.
626
627 This is equivalent to a SET command prior to execution of spawned
628 commands.
629 """
630
631 if name == "lib":
632 p = self.get_msvc_paths("library")
633 else:
634 p = self.get_msvc_paths(name)
635 if p:
636 os.environ[name] = string.join(p, ';')