blob: 79a4901bea1575b567ec788683d03500d0d76d0d [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
Greg Warddf178f91999-09-29 12:29:10 +00004for the Microsoft Visual Studio."""
Greg Warddbd12761999-08-29 18:15:07 +00005
6
7# created 1999/08/19, 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
Greg Ward32c4a8a2000-03-06 03:40:29 +000013import sys, os, string
14from types import *
Greg Ward3add77f2000-05-30 02:02:49 +000015from distutils.errors import \
16 DistutilsExecError, DistutilsPlatformError, \
Greg Wardd1517112000-05-30 01:56:44 +000017 CompileError, LibError, LinkError
Greg Ward3add77f2000-05-30 02:02:49 +000018from distutils.ccompiler import \
19 CCompiler, gen_preprocess_options, gen_lib_options
Greg Ward62e33932000-02-10 02:52:42 +000020
Greg Ward7642f5c2000-03-31 16:47:40 +000021_can_read_reg = 0
22try:
Greg Ward1b5ec762000-06-30 19:37:59 +000023 import _winreg
Greg Ward83c38702000-06-29 23:04:59 +000024
Greg Ward7642f5c2000-03-31 16:47:40 +000025 _can_read_reg = 1
Greg Wardcd079c42000-06-29 22:59:10 +000026 hkey_mod = _winreg
Greg Ward19ce1662000-03-31 19:04:25 +000027
Greg Wardcd079c42000-06-29 22:59:10 +000028 RegOpenKeyEx = _winreg.OpenKeyEx
29 RegEnumKey = _winreg.EnumKey
30 RegEnumValue = _winreg.EnumValue
31 RegError = _winreg.error
Greg Ward19ce1662000-03-31 19:04:25 +000032
Greg Ward7642f5c2000-03-31 16:47:40 +000033except ImportError:
34 try:
35 import win32api
36 import win32con
Greg Ward7642f5c2000-03-31 16:47:40 +000037 _can_read_reg = 1
Greg Ward1027e3f2000-03-31 16:53:42 +000038 hkey_mod = win32con
Greg Ward19ce1662000-03-31 19:04:25 +000039
40 RegOpenKeyEx = win32api.RegOpenKeyEx
41 RegEnumKey = win32api.RegEnumKey
42 RegEnumValue = win32api.RegEnumValue
43 RegError = win32api.error
44
Greg Ward7642f5c2000-03-31 16:47:40 +000045 except ImportError:
46 pass
Greg Ward1027e3f2000-03-31 16:53:42 +000047
48if _can_read_reg:
49 HKEY_CLASSES_ROOT = hkey_mod.HKEY_CLASSES_ROOT
50 HKEY_LOCAL_MACHINE = hkey_mod.HKEY_LOCAL_MACHINE
51 HKEY_CURRENT_USER = hkey_mod.HKEY_CURRENT_USER
52 HKEY_USERS = hkey_mod.HKEY_USERS
Fred Drakeb94b8492001-12-06 20:51:35 +000053
54
Greg Ward7642f5c2000-03-31 16:47:40 +000055
Greg Ward62e33932000-02-10 02:52:42 +000056def get_devstudio_versions ():
Greg Ward62e33932000-02-10 02:52:42 +000057 """Get list of devstudio versions from the Windows registry. Return a
Greg Ward69988092000-02-11 02:47:15 +000058 list of strings containing version numbers; the list will be
Greg Ward62e33932000-02-10 02:52:42 +000059 empty if we were unable to access the registry (eg. couldn't import
60 a registry-access module) or the appropriate registry keys weren't
Greg Ward69988092000-02-11 02:47:15 +000061 found."""
62
Greg Ward7642f5c2000-03-31 16:47:40 +000063 if not _can_read_reg:
Greg Ward62e33932000-02-10 02:52:42 +000064 return []
Greg Ward1b9c6f72000-02-08 02:39:44 +000065
66 K = 'Software\\Microsoft\\Devstudio'
67 L = []
Greg Ward1027e3f2000-03-31 16:53:42 +000068 for base in (HKEY_CLASSES_ROOT,
69 HKEY_LOCAL_MACHINE,
70 HKEY_CURRENT_USER,
71 HKEY_USERS):
Greg Ward1b9c6f72000-02-08 02:39:44 +000072 try:
Greg Ward1027e3f2000-03-31 16:53:42 +000073 k = RegOpenKeyEx(base,K)
Greg Ward1b9c6f72000-02-08 02:39:44 +000074 i = 0
75 while 1:
76 try:
Greg Ward1027e3f2000-03-31 16:53:42 +000077 p = RegEnumKey(k,i)
Greg Ward1b9c6f72000-02-08 02:39:44 +000078 if p[0] in '123456789' and p not in L:
79 L.append(p)
Greg Ward1027e3f2000-03-31 16:53:42 +000080 except RegError:
Greg Ward1b9c6f72000-02-08 02:39:44 +000081 break
82 i = i + 1
Greg Ward1027e3f2000-03-31 16:53:42 +000083 except RegError:
Greg Ward1b9c6f72000-02-08 02:39:44 +000084 pass
85 L.sort()
86 L.reverse()
87 return L
88
Greg Ward62e33932000-02-10 02:52:42 +000089# get_devstudio_versions ()
90
91
92def get_msvc_paths (path, version='6.0', platform='x86'):
Greg Ward69988092000-02-11 02:47:15 +000093 """Get a list of devstudio directories (include, lib or path). Return
94 a list of strings; will be empty list if unable to access the
95 registry or appropriate registry keys not found."""
Fred Drakeb94b8492001-12-06 20:51:35 +000096
Greg Ward7642f5c2000-03-31 16:47:40 +000097 if not _can_read_reg:
Greg Ward69988092000-02-11 02:47:15 +000098 return []
Greg Ward1b9c6f72000-02-08 02:39:44 +000099
100 L = []
Greg Ward62e33932000-02-10 02:52:42 +0000101 if path=='lib':
102 path= 'Library'
Greg Ward1b9c6f72000-02-08 02:39:44 +0000103 path = string.upper(path + ' Dirs')
Greg Ward62e33932000-02-10 02:52:42 +0000104 K = ('Software\\Microsoft\\Devstudio\\%s\\' +
105 'Build System\\Components\\Platforms\\Win32 (%s)\\Directories') % \
106 (version,platform)
Greg Ward1027e3f2000-03-31 16:53:42 +0000107 for base in (HKEY_CLASSES_ROOT,
108 HKEY_LOCAL_MACHINE,
109 HKEY_CURRENT_USER,
110 HKEY_USERS):
Greg Ward1b9c6f72000-02-08 02:39:44 +0000111 try:
Greg Ward1027e3f2000-03-31 16:53:42 +0000112 k = RegOpenKeyEx(base,K)
Greg Ward1b9c6f72000-02-08 02:39:44 +0000113 i = 0
114 while 1:
115 try:
Greg Ward1027e3f2000-03-31 16:53:42 +0000116 (p,v,t) = RegEnumValue(k,i)
Greg Ward62e33932000-02-10 02:52:42 +0000117 if string.upper(p) == path:
Greg Ward1b9c6f72000-02-08 02:39:44 +0000118 V = string.split(v,';')
119 for v in V:
Thomas Heller745b4602002-02-08 14:41:31 +0000120 if hasattr(v, "encode"):
121 try:
122 v = v.encode("mbcs")
123 except UnicodeError:
124 pass
Greg Ward62e33932000-02-10 02:52:42 +0000125 if v == '' or v in L: continue
Greg Ward1b9c6f72000-02-08 02:39:44 +0000126 L.append(v)
127 break
128 i = i + 1
Greg Ward1027e3f2000-03-31 16:53:42 +0000129 except RegError:
Greg Ward1b9c6f72000-02-08 02:39:44 +0000130 break
Greg Ward1027e3f2000-03-31 16:53:42 +0000131 except RegError:
Greg Ward1b9c6f72000-02-08 02:39:44 +0000132 pass
133 return L
134
Greg Ward62e33932000-02-10 02:52:42 +0000135# get_msvc_paths()
136
137
Greg Ward69988092000-02-11 02:47:15 +0000138def find_exe (exe, version_number):
139 """Try to find an MSVC executable program 'exe' (from version
140 'version_number' of MSVC) in several places: first, one of the MSVC
141 program search paths from the registry; next, the directories in the
142 PATH environment variable. If any of those work, return an absolute
143 path that is known to exist. If none of them work, just return the
144 original program name, 'exe'."""
Greg Ward1b9c6f72000-02-08 02:39:44 +0000145
Greg Ward69988092000-02-11 02:47:15 +0000146 for p in get_msvc_paths ('path', version_number):
147 fn = os.path.join (os.path.abspath(p), exe)
148 if os.path.isfile(fn):
149 return fn
150
151 # didn't find it; try existing path
152 for p in string.split (os.environ['Path'],';'):
153 fn = os.path.join(os.path.abspath(p),exe)
154 if os.path.isfile(fn):
155 return fn
156
Fred Drakeb94b8492001-12-06 20:51:35 +0000157 return exe # last desperate hope
Greg Ward1b9c6f72000-02-08 02:39:44 +0000158
Greg Ward62e33932000-02-10 02:52:42 +0000159
Greg Ward5de8cee2000-02-11 02:52:39 +0000160def set_path_env_var (name, version_number):
161 """Set environment variable 'name' to an MSVC path type value obtained
162 from 'get_msvc_paths()'. This is equivalent to a SET command prior
163 to execution of spawned commands."""
Greg Ward69988092000-02-11 02:47:15 +0000164
Greg Ward5de8cee2000-02-11 02:52:39 +0000165 p = get_msvc_paths (name, version_number)
Greg Ward62e33932000-02-10 02:52:42 +0000166 if p:
Greg Ward5de8cee2000-02-11 02:52:39 +0000167 os.environ[name] = string.join (p,';')
Greg Ward62e33932000-02-10 02:52:42 +0000168
Greg Warddbd12761999-08-29 18:15:07 +0000169
Greg Ward3d50b901999-09-08 02:36:01 +0000170class MSVCCompiler (CCompiler) :
171 """Concrete class that implements an interface to Microsoft Visual C++,
172 as defined by the CCompiler abstract class."""
Greg Warddbd12761999-08-29 18:15:07 +0000173
Greg Warddf178f91999-09-29 12:29:10 +0000174 compiler_type = 'msvc'
175
Greg Ward992c8f92000-06-25 02:31:16 +0000176 # Just set this so CCompiler's constructor doesn't barf. We currently
177 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
178 # as it really isn't necessary for this sort of single-compiler class.
179 # Would be nice to have a consistent interface with UnixCCompiler,
180 # though, so it's worth thinking about.
181 executables = {}
182
Greg Ward32c4a8a2000-03-06 03:40:29 +0000183 # Private class data (need to distinguish C from C++ source for compiler)
184 _c_extensions = ['.c']
Greg Ward408e9ae2000-08-30 17:32:24 +0000185 _cpp_extensions = ['.cc', '.cpp', '.cxx']
Greg Ward9c0ea132000-09-19 23:56:43 +0000186 _rc_extensions = ['.rc']
187 _mc_extensions = ['.mc']
Greg Ward32c4a8a2000-03-06 03:40:29 +0000188
189 # Needed for the filename generation methods provided by the
190 # base class, CCompiler.
Greg Ward9c0ea132000-09-19 23:56:43 +0000191 src_extensions = (_c_extensions + _cpp_extensions +
192 _rc_extensions + _mc_extensions)
193 res_extension = '.res'
Greg Ward32c4a8a2000-03-06 03:40:29 +0000194 obj_extension = '.obj'
195 static_lib_extension = '.lib'
196 shared_lib_extension = '.dll'
197 static_lib_format = shared_lib_format = '%s%s'
198 exe_extension = '.exe'
199
200
Greg Warddbd12761999-08-29 18:15:07 +0000201 def __init__ (self,
202 verbose=0,
Greg Wardc74138d1999-10-03 20:47:52 +0000203 dry_run=0,
204 force=0):
Greg Warddbd12761999-08-29 18:15:07 +0000205
Greg Wardc74138d1999-10-03 20:47:52 +0000206 CCompiler.__init__ (self, verbose, dry_run, force)
Greg Ward5de8cee2000-02-11 02:52:39 +0000207 versions = get_devstudio_versions ()
Greg Ward69988092000-02-11 02:47:15 +0000208
Greg Ward5de8cee2000-02-11 02:52:39 +0000209 if versions:
210 version = versions[0] # highest version
Greg Ward69988092000-02-11 02:47:15 +0000211
Greg Ward41b4dd62000-03-29 04:13:00 +0000212 self.cc = find_exe("cl.exe", version)
Greg Ward42406482000-09-27 02:08:14 +0000213 self.linker = find_exe("link.exe", version)
Greg Ward41b4dd62000-03-29 04:13:00 +0000214 self.lib = find_exe("lib.exe", version)
Greg Ward9c0ea132000-09-19 23:56:43 +0000215 self.rc = find_exe("rc.exe", version) # resource compiler
216 self.mc = find_exe("mc.exe", version) # message compiler
Greg Ward5de8cee2000-02-11 02:52:39 +0000217 set_path_env_var ('lib', version)
218 set_path_env_var ('include', version)
219 path=get_msvc_paths('path', version)
Greg Ward69988092000-02-11 02:47:15 +0000220 try:
221 for p in string.split(os.environ['path'],';'):
222 path.append(p)
223 except KeyError:
224 pass
225 os.environ['path'] = string.join(path,';')
226 else:
227 # devstudio not found in the registry
228 self.cc = "cl.exe"
Greg Ward42406482000-09-27 02:08:14 +0000229 self.linker = "link.exe"
Greg Ward09fc5422000-03-10 01:49:26 +0000230 self.lib = "lib.exe"
Greg Ward9c0ea132000-09-19 23:56:43 +0000231 self.rc = "rc.exe"
232 self.mc = "mc.exe"
Greg Ward69988092000-02-11 02:47:15 +0000233
Greg Warddbd12761999-08-29 18:15:07 +0000234 self.preprocess_options = None
Greg Ward8a98cd92000-08-31 00:31:07 +0000235 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ]
236 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
237 '/Z7', '/D_DEBUG']
Greg Warddbd12761999-08-29 18:15:07 +0000238
Greg Ward1b9c6f72000-02-08 02:39:44 +0000239 self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000240 self.ldflags_shared_debug = [
241 '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
242 ]
Greg Warddbd12761999-08-29 18:15:07 +0000243 self.ldflags_static = [ '/nologo']
244
Greg Warddbd12761999-08-29 18:15:07 +0000245
246 # -- Worker methods ------------------------------------------------
Greg Warddbd12761999-08-29 18:15:07 +0000247
Greg Ward9c0ea132000-09-19 23:56:43 +0000248 def object_filenames (self,
249 source_filenames,
250 strip_dir=0,
251 output_dir=''):
252 # Copied from ccompiler.py, extended to return .res as 'object'-file
253 # for .rc input file
254 if output_dir is None: output_dir = ''
255 obj_names = []
256 for src_name in source_filenames:
257 (base, ext) = os.path.splitext (src_name)
258 if ext not in self.src_extensions:
259 # Better to raise an exception instead of silently continuing
260 # and later complain about sources and targets having
261 # different lengths
262 raise CompileError ("Don't know how to compile %s" % src_name)
263 if strip_dir:
264 base = os.path.basename (base)
265 if ext in self._rc_extensions:
266 obj_names.append (os.path.join (output_dir,
267 base + self.res_extension))
268 elif ext in self._mc_extensions:
269 obj_names.append (os.path.join (output_dir,
270 base + self.res_extension))
271 else:
272 obj_names.append (os.path.join (output_dir,
273 base + self.obj_extension))
274 return obj_names
275
276 # object_filenames ()
277
278
Greg Warddbd12761999-08-29 18:15:07 +0000279 def compile (self,
280 sources,
Greg Warddf178f91999-09-29 12:29:10 +0000281 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000282 macros=None,
Greg Ward0bdd90a1999-12-12 17:19:58 +0000283 include_dirs=None,
Greg Ward386b8442000-02-09 02:18:39 +0000284 debug=0,
Greg Warddf178f91999-09-29 12:29:10 +0000285 extra_preargs=None,
286 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +0000287
Greg Ward32c4a8a2000-03-06 03:40:29 +0000288 (output_dir, macros, include_dirs) = \
289 self._fix_compile_args (output_dir, macros, include_dirs)
290 (objects, skip_sources) = self._prep_compile (sources, output_dir)
Greg Warddbd12761999-08-29 18:15:07 +0000291
Greg Ward32c4a8a2000-03-06 03:40:29 +0000292 if extra_postargs is None:
293 extra_postargs = []
Greg Warddbd12761999-08-29 18:15:07 +0000294
Greg Ward32c4a8a2000-03-06 03:40:29 +0000295 pp_opts = gen_preprocess_options (macros, include_dirs)
296 compile_opts = extra_preargs or []
297 compile_opts.append ('/c')
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000298 if debug:
Greg Ward32c4a8a2000-03-06 03:40:29 +0000299 compile_opts.extend (self.compile_options_debug)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000300 else:
Greg Ward32c4a8a2000-03-06 03:40:29 +0000301 compile_opts.extend (self.compile_options)
Fred Drakeb94b8492001-12-06 20:51:35 +0000302
Greg Ward32c4a8a2000-03-06 03:40:29 +0000303 for i in range (len (sources)):
304 src = sources[i] ; obj = objects[i]
305 ext = (os.path.splitext (src))[1]
Greg Warddbd12761999-08-29 18:15:07 +0000306
Greg Ward32c4a8a2000-03-06 03:40:29 +0000307 if skip_sources[src]:
308 self.announce ("skipping %s (%s up-to-date)" % (src, obj))
309 else:
Greg Ward9c0ea132000-09-19 23:56:43 +0000310 self.mkpath (os.path.dirname (obj))
311
Greg Ward32c4a8a2000-03-06 03:40:29 +0000312 if ext in self._c_extensions:
313 input_opt = "/Tc" + src
314 elif ext in self._cpp_extensions:
315 input_opt = "/Tp" + src
Greg Ward9c0ea132000-09-19 23:56:43 +0000316 elif ext in self._rc_extensions:
317 # compile .RC to .RES file
318 input_opt = src
319 output_opt = "/fo" + obj
320 try:
321 self.spawn ([self.rc] +
322 [output_opt] + [input_opt])
323 except DistutilsExecError, msg:
324 raise CompileError, msg
325 continue
326 elif ext in self._mc_extensions:
327
328 # Compile .MC to .RC file to .RES file.
329 # * '-h dir' specifies the directory for the
330 # generated include file
331 # * '-r dir' specifies the target directory of the
332 # generated RC file and the binary message resource
333 # it includes
334 #
335 # For now (since there are no options to change this),
336 # we use the source-directory for the include file and
337 # the build directory for the RC file and message
338 # resources. This works at least for win32all.
339
340 h_dir = os.path.dirname (src)
341 rc_dir = os.path.dirname (obj)
342 try:
343 # first compile .MC to .RC and .H file
344 self.spawn ([self.mc] +
345 ['-h', h_dir, '-r', rc_dir] + [src])
346 base, _ = os.path.splitext (os.path.basename (src))
347 rc_file = os.path.join (rc_dir, base + '.rc')
348 # then compile .RC to .RES file
349 self.spawn ([self.rc] +
350 ["/fo" + obj] + [rc_file])
351
352 except DistutilsExecError, msg:
353 raise CompileError, msg
354 continue
355 else:
356 # how to handle this file?
357 raise CompileError (
358 "Don't know how to compile %s to %s" % \
359 (src, obj))
Greg Warddbd12761999-08-29 18:15:07 +0000360
Greg Ward32c4a8a2000-03-06 03:40:29 +0000361 output_opt = "/Fo" + obj
Greg Wardd1517112000-05-30 01:56:44 +0000362 try:
363 self.spawn ([self.cc] + compile_opts + pp_opts +
364 [input_opt, output_opt] +
365 extra_postargs)
366 except DistutilsExecError, msg:
367 raise CompileError, msg
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000368
Greg Ward32c4a8a2000-03-06 03:40:29 +0000369 return objects
Greg Warddbd12761999-08-29 18:15:07 +0000370
Greg Ward32c4a8a2000-03-06 03:40:29 +0000371 # compile ()
Greg Ward3d50b901999-09-08 02:36:01 +0000372
373
Greg Ward09fc5422000-03-10 01:49:26 +0000374 def create_static_lib (self,
375 objects,
376 output_libname,
377 output_dir=None,
378 debug=0,
379 extra_preargs=None,
380 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +0000381
Greg Ward2f557a22000-03-26 21:42:28 +0000382 (objects, output_dir) = self._fix_object_args (objects, output_dir)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000383 output_filename = \
384 self.library_filename (output_libname, output_dir=output_dir)
Greg Warddbd12761999-08-29 18:15:07 +0000385
Greg Ward32c4a8a2000-03-06 03:40:29 +0000386 if self._need_link (objects, output_filename):
Greg Ward09fc5422000-03-10 01:49:26 +0000387 lib_args = objects + ['/OUT:' + output_filename]
Greg Ward32c4a8a2000-03-06 03:40:29 +0000388 if debug:
389 pass # XXX what goes here?
390 if extra_preargs:
Greg Ward09fc5422000-03-10 01:49:26 +0000391 lib_args[:0] = extra_preargs
Greg Ward32c4a8a2000-03-06 03:40:29 +0000392 if extra_postargs:
Greg Ward09fc5422000-03-10 01:49:26 +0000393 lib_args.extend (extra_postargs)
Greg Wardd1517112000-05-30 01:56:44 +0000394 try:
Greg Ward992c8f92000-06-25 02:31:16 +0000395 self.spawn ([self.lib] + lib_args)
Greg Wardd1517112000-05-30 01:56:44 +0000396 except DistutilsExecError, msg:
397 raise LibError, msg
Fred Drakeb94b8492001-12-06 20:51:35 +0000398
Greg Ward32c4a8a2000-03-06 03:40:29 +0000399 else:
400 self.announce ("skipping %s (up-to-date)" % output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000401
Greg Ward09fc5422000-03-10 01:49:26 +0000402 # create_static_lib ()
Fred Drakeb94b8492001-12-06 20:51:35 +0000403
Greg Ward42406482000-09-27 02:08:14 +0000404 def link (self,
405 target_desc,
406 objects,
407 output_filename,
408 output_dir=None,
409 libraries=None,
410 library_dirs=None,
411 runtime_library_dirs=None,
412 export_symbols=None,
413 debug=0,
414 extra_preargs=None,
415 extra_postargs=None,
416 build_temp=None):
Greg Ward32c4a8a2000-03-06 03:40:29 +0000417
Greg Ward2f557a22000-03-26 21:42:28 +0000418 (objects, output_dir) = self._fix_object_args (objects, output_dir)
419 (libraries, library_dirs, runtime_library_dirs) = \
420 self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
421
Greg Wardf70c6032000-04-19 02:16:49 +0000422 if runtime_library_dirs:
Greg Ward2f557a22000-03-26 21:42:28 +0000423 self.warn ("I don't know what to do with 'runtime_library_dirs': "
424 + str (runtime_library_dirs))
Fred Drakeb94b8492001-12-06 20:51:35 +0000425
Greg Wardd03f88a2000-03-18 15:19:51 +0000426 lib_opts = gen_lib_options (self,
Greg Ward2f557a22000-03-26 21:42:28 +0000427 library_dirs, runtime_library_dirs,
Greg Wardd03f88a2000-03-18 15:19:51 +0000428 libraries)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000429 if output_dir is not None:
430 output_filename = os.path.join (output_dir, output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000431
Greg Ward32c4a8a2000-03-06 03:40:29 +0000432 if self._need_link (objects, output_filename):
433
Greg Ward42406482000-09-27 02:08:14 +0000434 if target_desc == CCompiler.EXECUTABLE:
435 if debug:
436 ldflags = self.ldflags_shared_debug[1:]
437 else:
438 ldflags = self.ldflags_shared[1:]
Greg Ward32c4a8a2000-03-06 03:40:29 +0000439 else:
Greg Ward42406482000-09-27 02:08:14 +0000440 if debug:
441 ldflags = self.ldflags_shared_debug
442 else:
443 ldflags = self.ldflags_shared
Greg Ward32c4a8a2000-03-06 03:40:29 +0000444
Greg Ward5299b6a2000-05-20 13:23:21 +0000445 export_opts = []
446 for sym in (export_symbols or []):
447 export_opts.append("/EXPORT:" + sym)
448
Fred Drakeb94b8492001-12-06 20:51:35 +0000449 ld_args = (ldflags + lib_opts + export_opts +
Greg Ward5299b6a2000-05-20 13:23:21 +0000450 objects + ['/OUT:' + output_filename])
Greg Ward32c4a8a2000-03-06 03:40:29 +0000451
Greg Ward159eb922000-08-02 00:00:30 +0000452 # The MSVC linker generates .lib and .exp files, which cannot be
453 # suppressed by any linker switches. The .lib files may even be
454 # needed! Make sure they are generated in the temporary build
455 # directory. Since they have different names for debug and release
456 # builds, they can go into the same directory.
Greg Ward42406482000-09-27 02:08:14 +0000457 if export_symbols is not None:
458 (dll_name, dll_ext) = os.path.splitext(
459 os.path.basename(output_filename))
460 implib_file = os.path.join(
461 os.path.dirname(objects[0]),
462 self.library_filename(dll_name))
463 ld_args.append ('/IMPLIB:' + implib_file)
Greg Ward159eb922000-08-02 00:00:30 +0000464
Greg Ward32c4a8a2000-03-06 03:40:29 +0000465 if extra_preargs:
466 ld_args[:0] = extra_preargs
467 if extra_postargs:
Greg Ward159eb922000-08-02 00:00:30 +0000468 ld_args.extend(extra_postargs)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000469
470 self.mkpath (os.path.dirname (output_filename))
Greg Wardd1517112000-05-30 01:56:44 +0000471 try:
Greg Ward42406482000-09-27 02:08:14 +0000472 self.spawn ([self.linker] + ld_args)
Greg Wardd1517112000-05-30 01:56:44 +0000473 except DistutilsExecError, msg:
474 raise LinkError, msg
Greg Ward32c4a8a2000-03-06 03:40:29 +0000475
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000476 else:
Greg Ward32c4a8a2000-03-06 03:40:29 +0000477 self.announce ("skipping %s (up-to-date)" % output_filename)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000478
Greg Ward42406482000-09-27 02:08:14 +0000479 # link ()
Greg Wardf70c6032000-04-19 02:16:49 +0000480
481
Greg Ward32c4a8a2000-03-06 03:40:29 +0000482 # -- Miscellaneous methods -----------------------------------------
483 # These are all used by the 'gen_lib_options() function, in
484 # ccompiler.py.
Greg Wardc74138d1999-10-03 20:47:52 +0000485
486 def library_dir_option (self, dir):
487 return "/LIBPATH:" + dir
488
Greg Wardd03f88a2000-03-18 15:19:51 +0000489 def runtime_library_dir_option (self, dir):
490 raise DistutilsPlatformError, \
491 "don't know how to set runtime library search path for MSVC++"
492
Greg Wardc74138d1999-10-03 20:47:52 +0000493 def library_option (self, lib):
494 return self.library_filename (lib)
495
496
Greg Wardd1425642000-08-04 01:29:27 +0000497 def find_library_file (self, dirs, lib, debug=0):
498 # Prefer a debugging library if found (and requested), but deal
499 # with it if we don't have one.
500 if debug:
501 try_names = [lib + "_d", lib]
502 else:
503 try_names = [lib]
Greg Wardc74138d1999-10-03 20:47:52 +0000504 for dir in dirs:
Greg Wardd1425642000-08-04 01:29:27 +0000505 for name in try_names:
506 libfile = os.path.join(dir, self.library_filename (name))
507 if os.path.exists(libfile):
508 return libfile
Greg Wardc74138d1999-10-03 20:47:52 +0000509 else:
510 # Oops, didn't find it in *any* of 'dirs'
511 return None
512
513 # find_library_file ()
514
Greg Warddbd12761999-08-29 18:15:07 +0000515# class MSVCCompiler