blob: ea58a79cd360f963f9826cfc4717989bd042ac86 [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
Greg Ward1027e3f2000-03-31 16:53:42 +000053
Greg Ward7642f5c2000-03-31 16:47:40 +000054
55
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."""
96
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:
Greg Ward62e33932000-02-10 02:52:42 +0000120 if v == '' or v in L: continue
Greg Ward1b9c6f72000-02-08 02:39:44 +0000121 L.append(v)
122 break
123 i = i + 1
Greg Ward1027e3f2000-03-31 16:53:42 +0000124 except RegError:
Greg Ward1b9c6f72000-02-08 02:39:44 +0000125 break
Greg Ward1027e3f2000-03-31 16:53:42 +0000126 except RegError:
Greg Ward1b9c6f72000-02-08 02:39:44 +0000127 pass
128 return L
129
Greg Ward62e33932000-02-10 02:52:42 +0000130# get_msvc_paths()
131
132
Greg Ward69988092000-02-11 02:47:15 +0000133def find_exe (exe, version_number):
134 """Try to find an MSVC executable program 'exe' (from version
135 'version_number' of MSVC) in several places: first, one of the MSVC
136 program search paths from the registry; next, the directories in the
137 PATH environment variable. If any of those work, return an absolute
138 path that is known to exist. If none of them work, just return the
139 original program name, 'exe'."""
Greg Ward1b9c6f72000-02-08 02:39:44 +0000140
Greg Ward69988092000-02-11 02:47:15 +0000141 for p in get_msvc_paths ('path', version_number):
142 fn = os.path.join (os.path.abspath(p), exe)
143 if os.path.isfile(fn):
144 return fn
145
146 # didn't find it; try existing path
147 for p in string.split (os.environ['Path'],';'):
148 fn = os.path.join(os.path.abspath(p),exe)
149 if os.path.isfile(fn):
150 return fn
151
152 return exe # last desperate hope
Greg Ward1b9c6f72000-02-08 02:39:44 +0000153
Greg Ward62e33932000-02-10 02:52:42 +0000154
Greg Ward5de8cee2000-02-11 02:52:39 +0000155def set_path_env_var (name, version_number):
156 """Set environment variable 'name' to an MSVC path type value obtained
157 from 'get_msvc_paths()'. This is equivalent to a SET command prior
158 to execution of spawned commands."""
Greg Ward69988092000-02-11 02:47:15 +0000159
Greg Ward5de8cee2000-02-11 02:52:39 +0000160 p = get_msvc_paths (name, version_number)
Greg Ward62e33932000-02-10 02:52:42 +0000161 if p:
Greg Ward5de8cee2000-02-11 02:52:39 +0000162 os.environ[name] = string.join (p,';')
Greg Ward62e33932000-02-10 02:52:42 +0000163
Greg Warddbd12761999-08-29 18:15:07 +0000164
Greg Ward3d50b901999-09-08 02:36:01 +0000165class MSVCCompiler (CCompiler) :
166 """Concrete class that implements an interface to Microsoft Visual C++,
167 as defined by the CCompiler abstract class."""
Greg Warddbd12761999-08-29 18:15:07 +0000168
Greg Warddf178f91999-09-29 12:29:10 +0000169 compiler_type = 'msvc'
170
Greg Ward992c8f92000-06-25 02:31:16 +0000171 # Just set this so CCompiler's constructor doesn't barf. We currently
172 # don't use the 'set_executables()' bureaucracy provided by CCompiler,
173 # as it really isn't necessary for this sort of single-compiler class.
174 # Would be nice to have a consistent interface with UnixCCompiler,
175 # though, so it's worth thinking about.
176 executables = {}
177
Greg Ward32c4a8a2000-03-06 03:40:29 +0000178 # Private class data (need to distinguish C from C++ source for compiler)
179 _c_extensions = ['.c']
Greg Ward408e9ae2000-08-30 17:32:24 +0000180 _cpp_extensions = ['.cc', '.cpp', '.cxx']
Greg Ward9c0ea132000-09-19 23:56:43 +0000181 _rc_extensions = ['.rc']
182 _mc_extensions = ['.mc']
Greg Ward32c4a8a2000-03-06 03:40:29 +0000183
184 # Needed for the filename generation methods provided by the
185 # base class, CCompiler.
Greg Ward9c0ea132000-09-19 23:56:43 +0000186 src_extensions = (_c_extensions + _cpp_extensions +
187 _rc_extensions + _mc_extensions)
188 res_extension = '.res'
Greg Ward32c4a8a2000-03-06 03:40:29 +0000189 obj_extension = '.obj'
190 static_lib_extension = '.lib'
191 shared_lib_extension = '.dll'
192 static_lib_format = shared_lib_format = '%s%s'
193 exe_extension = '.exe'
194
195
Greg Warddbd12761999-08-29 18:15:07 +0000196 def __init__ (self,
197 verbose=0,
Greg Wardc74138d1999-10-03 20:47:52 +0000198 dry_run=0,
199 force=0):
Greg Warddbd12761999-08-29 18:15:07 +0000200
Greg Wardc74138d1999-10-03 20:47:52 +0000201 CCompiler.__init__ (self, verbose, dry_run, force)
Greg Ward5de8cee2000-02-11 02:52:39 +0000202 versions = get_devstudio_versions ()
Greg Ward69988092000-02-11 02:47:15 +0000203
Greg Ward5de8cee2000-02-11 02:52:39 +0000204 if versions:
205 version = versions[0] # highest version
Greg Ward69988092000-02-11 02:47:15 +0000206
Greg Ward41b4dd62000-03-29 04:13:00 +0000207 self.cc = find_exe("cl.exe", version)
208 self.link = find_exe("link.exe", version)
209 self.lib = find_exe("lib.exe", version)
Greg Ward9c0ea132000-09-19 23:56:43 +0000210 self.rc = find_exe("rc.exe", version) # resource compiler
211 self.mc = find_exe("mc.exe", version) # message compiler
Greg Ward5de8cee2000-02-11 02:52:39 +0000212 set_path_env_var ('lib', version)
213 set_path_env_var ('include', version)
214 path=get_msvc_paths('path', version)
Greg Ward69988092000-02-11 02:47:15 +0000215 try:
216 for p in string.split(os.environ['path'],';'):
217 path.append(p)
218 except KeyError:
219 pass
220 os.environ['path'] = string.join(path,';')
221 else:
222 # devstudio not found in the registry
223 self.cc = "cl.exe"
224 self.link = "link.exe"
Greg Ward09fc5422000-03-10 01:49:26 +0000225 self.lib = "lib.exe"
Greg Ward9c0ea132000-09-19 23:56:43 +0000226 self.rc = "rc.exe"
227 self.mc = "mc.exe"
Greg Ward69988092000-02-11 02:47:15 +0000228
Greg Warddbd12761999-08-29 18:15:07 +0000229 self.preprocess_options = None
Greg Ward8a98cd92000-08-31 00:31:07 +0000230 self.compile_options = [ '/nologo', '/Ox', '/MD', '/W3', '/GX' ]
231 self.compile_options_debug = ['/nologo', '/Od', '/MDd', '/W3', '/GX',
232 '/Z7', '/D_DEBUG']
Greg Warddbd12761999-08-29 18:15:07 +0000233
Greg Ward1b9c6f72000-02-08 02:39:44 +0000234 self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000235 self.ldflags_shared_debug = [
236 '/DLL', '/nologo', '/INCREMENTAL:no', '/pdb:None', '/DEBUG'
237 ]
Greg Warddbd12761999-08-29 18:15:07 +0000238 self.ldflags_static = [ '/nologo']
239
Greg Warddbd12761999-08-29 18:15:07 +0000240
241 # -- Worker methods ------------------------------------------------
Greg Warddbd12761999-08-29 18:15:07 +0000242
Greg Ward9c0ea132000-09-19 23:56:43 +0000243 def object_filenames (self,
244 source_filenames,
245 strip_dir=0,
246 output_dir=''):
247 # Copied from ccompiler.py, extended to return .res as 'object'-file
248 # for .rc input file
249 if output_dir is None: output_dir = ''
250 obj_names = []
251 for src_name in source_filenames:
252 (base, ext) = os.path.splitext (src_name)
253 if ext not in self.src_extensions:
254 # Better to raise an exception instead of silently continuing
255 # and later complain about sources and targets having
256 # different lengths
257 raise CompileError ("Don't know how to compile %s" % src_name)
258 if strip_dir:
259 base = os.path.basename (base)
260 if ext in self._rc_extensions:
261 obj_names.append (os.path.join (output_dir,
262 base + self.res_extension))
263 elif ext in self._mc_extensions:
264 obj_names.append (os.path.join (output_dir,
265 base + self.res_extension))
266 else:
267 obj_names.append (os.path.join (output_dir,
268 base + self.obj_extension))
269 return obj_names
270
271 # object_filenames ()
272
273
Greg Warddbd12761999-08-29 18:15:07 +0000274 def compile (self,
275 sources,
Greg Warddf178f91999-09-29 12:29:10 +0000276 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000277 macros=None,
Greg Ward0bdd90a1999-12-12 17:19:58 +0000278 include_dirs=None,
Greg Ward386b8442000-02-09 02:18:39 +0000279 debug=0,
Greg Warddf178f91999-09-29 12:29:10 +0000280 extra_preargs=None,
281 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +0000282
Greg Ward32c4a8a2000-03-06 03:40:29 +0000283 (output_dir, macros, include_dirs) = \
284 self._fix_compile_args (output_dir, macros, include_dirs)
285 (objects, skip_sources) = self._prep_compile (sources, output_dir)
Greg Warddbd12761999-08-29 18:15:07 +0000286
Greg Ward32c4a8a2000-03-06 03:40:29 +0000287 if extra_postargs is None:
288 extra_postargs = []
Greg Warddbd12761999-08-29 18:15:07 +0000289
Greg Ward32c4a8a2000-03-06 03:40:29 +0000290 pp_opts = gen_preprocess_options (macros, include_dirs)
291 compile_opts = extra_preargs or []
292 compile_opts.append ('/c')
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000293 if debug:
Greg Ward32c4a8a2000-03-06 03:40:29 +0000294 compile_opts.extend (self.compile_options_debug)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000295 else:
Greg Ward32c4a8a2000-03-06 03:40:29 +0000296 compile_opts.extend (self.compile_options)
Greg Warddbd12761999-08-29 18:15:07 +0000297
Greg Ward32c4a8a2000-03-06 03:40:29 +0000298 for i in range (len (sources)):
299 src = sources[i] ; obj = objects[i]
300 ext = (os.path.splitext (src))[1]
Greg Warddbd12761999-08-29 18:15:07 +0000301
Greg Ward32c4a8a2000-03-06 03:40:29 +0000302 if skip_sources[src]:
303 self.announce ("skipping %s (%s up-to-date)" % (src, obj))
304 else:
Greg Ward9c0ea132000-09-19 23:56:43 +0000305 self.mkpath (os.path.dirname (obj))
306
Greg Ward32c4a8a2000-03-06 03:40:29 +0000307 if ext in self._c_extensions:
308 input_opt = "/Tc" + src
309 elif ext in self._cpp_extensions:
310 input_opt = "/Tp" + src
Greg Ward9c0ea132000-09-19 23:56:43 +0000311 elif ext in self._rc_extensions:
312 # compile .RC to .RES file
313 input_opt = src
314 output_opt = "/fo" + obj
315 try:
316 self.spawn ([self.rc] +
317 [output_opt] + [input_opt])
318 except DistutilsExecError, msg:
319 raise CompileError, msg
320 continue
321 elif ext in self._mc_extensions:
322
323 # Compile .MC to .RC file to .RES file.
324 # * '-h dir' specifies the directory for the
325 # generated include file
326 # * '-r dir' specifies the target directory of the
327 # generated RC file and the binary message resource
328 # it includes
329 #
330 # For now (since there are no options to change this),
331 # we use the source-directory for the include file and
332 # the build directory for the RC file and message
333 # resources. This works at least for win32all.
334
335 h_dir = os.path.dirname (src)
336 rc_dir = os.path.dirname (obj)
337 try:
338 # first compile .MC to .RC and .H file
339 self.spawn ([self.mc] +
340 ['-h', h_dir, '-r', rc_dir] + [src])
341 base, _ = os.path.splitext (os.path.basename (src))
342 rc_file = os.path.join (rc_dir, base + '.rc')
343 # then compile .RC to .RES file
344 self.spawn ([self.rc] +
345 ["/fo" + obj] + [rc_file])
346
347 except DistutilsExecError, msg:
348 raise CompileError, msg
349 continue
350 else:
351 # how to handle this file?
352 raise CompileError (
353 "Don't know how to compile %s to %s" % \
354 (src, obj))
Greg Warddbd12761999-08-29 18:15:07 +0000355
Greg Ward32c4a8a2000-03-06 03:40:29 +0000356 output_opt = "/Fo" + obj
Greg Wardd1517112000-05-30 01:56:44 +0000357 try:
358 self.spawn ([self.cc] + compile_opts + pp_opts +
359 [input_opt, output_opt] +
360 extra_postargs)
361 except DistutilsExecError, msg:
362 raise CompileError, msg
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000363
Greg Ward32c4a8a2000-03-06 03:40:29 +0000364 return objects
Greg Warddbd12761999-08-29 18:15:07 +0000365
Greg Ward32c4a8a2000-03-06 03:40:29 +0000366 # compile ()
Greg Ward3d50b901999-09-08 02:36:01 +0000367
368
Greg Ward09fc5422000-03-10 01:49:26 +0000369 def create_static_lib (self,
370 objects,
371 output_libname,
372 output_dir=None,
373 debug=0,
374 extra_preargs=None,
375 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +0000376
Greg Ward2f557a22000-03-26 21:42:28 +0000377 (objects, output_dir) = self._fix_object_args (objects, output_dir)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000378 output_filename = \
379 self.library_filename (output_libname, output_dir=output_dir)
Greg Warddbd12761999-08-29 18:15:07 +0000380
Greg Ward32c4a8a2000-03-06 03:40:29 +0000381 if self._need_link (objects, output_filename):
Greg Ward09fc5422000-03-10 01:49:26 +0000382 lib_args = objects + ['/OUT:' + output_filename]
Greg Ward32c4a8a2000-03-06 03:40:29 +0000383 if debug:
384 pass # XXX what goes here?
385 if extra_preargs:
Greg Ward09fc5422000-03-10 01:49:26 +0000386 lib_args[:0] = extra_preargs
Greg Ward32c4a8a2000-03-06 03:40:29 +0000387 if extra_postargs:
Greg Ward09fc5422000-03-10 01:49:26 +0000388 lib_args.extend (extra_postargs)
Greg Wardd1517112000-05-30 01:56:44 +0000389 try:
Greg Ward992c8f92000-06-25 02:31:16 +0000390 self.spawn ([self.lib] + lib_args)
Greg Wardd1517112000-05-30 01:56:44 +0000391 except DistutilsExecError, msg:
392 raise LibError, msg
393
Greg Ward32c4a8a2000-03-06 03:40:29 +0000394 else:
395 self.announce ("skipping %s (up-to-date)" % output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000396
Greg Ward09fc5422000-03-10 01:49:26 +0000397 # create_static_lib ()
Greg Warddbd12761999-08-29 18:15:07 +0000398
399
400 def link_shared_lib (self,
401 objects,
402 output_libname,
Greg Warddf178f91999-09-29 12:29:10 +0000403 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000404 libraries=None,
405 library_dirs=None,
Greg Ward2f557a22000-03-26 21:42:28 +0000406 runtime_library_dirs=None,
Greg Ward5299b6a2000-05-20 13:23:21 +0000407 export_symbols=None,
Greg Ward386b8442000-02-09 02:18:39 +0000408 debug=0,
Greg Warddf178f91999-09-29 12:29:10 +0000409 extra_preargs=None,
Greg Wardbfc79d62000-06-28 01:29:09 +0000410 extra_postargs=None,
411 build_temp=None):
Greg Warddf178f91999-09-29 12:29:10 +0000412
Greg Warddf178f91999-09-29 12:29:10 +0000413 self.link_shared_object (objects,
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000414 self.shared_library_name(output_libname),
415 output_dir=output_dir,
416 libraries=libraries,
417 library_dirs=library_dirs,
Greg Ward5299b6a2000-05-20 13:23:21 +0000418 runtime_library_dirs=runtime_library_dirs,
419 export_symbols=export_symbols,
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000420 debug=debug,
421 extra_preargs=extra_preargs,
Greg Wardbfc79d62000-06-28 01:29:09 +0000422 extra_postargs=extra_postargs,
423 build_temp=build_temp)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000424
Greg Warddbd12761999-08-29 18:15:07 +0000425
426 def link_shared_object (self,
427 objects,
428 output_filename,
Greg Warddf178f91999-09-29 12:29:10 +0000429 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000430 libraries=None,
431 library_dirs=None,
Greg Ward2f557a22000-03-26 21:42:28 +0000432 runtime_library_dirs=None,
Greg Ward5299b6a2000-05-20 13:23:21 +0000433 export_symbols=None,
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000434 debug=0,
Greg Warddf178f91999-09-29 12:29:10 +0000435 extra_preargs=None,
Greg Wardbfc79d62000-06-28 01:29:09 +0000436 extra_postargs=None,
437 build_temp=None):
Greg Ward32c4a8a2000-03-06 03:40:29 +0000438
Greg Ward2f557a22000-03-26 21:42:28 +0000439 (objects, output_dir) = self._fix_object_args (objects, output_dir)
440 (libraries, library_dirs, runtime_library_dirs) = \
441 self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
442
Greg Wardf70c6032000-04-19 02:16:49 +0000443 if runtime_library_dirs:
Greg Ward2f557a22000-03-26 21:42:28 +0000444 self.warn ("I don't know what to do with 'runtime_library_dirs': "
445 + str (runtime_library_dirs))
Greg Warddbd12761999-08-29 18:15:07 +0000446
Greg Wardd03f88a2000-03-18 15:19:51 +0000447 lib_opts = gen_lib_options (self,
Greg Ward2f557a22000-03-26 21:42:28 +0000448 library_dirs, runtime_library_dirs,
Greg Wardd03f88a2000-03-18 15:19:51 +0000449 libraries)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000450 if output_dir is not None:
451 output_filename = os.path.join (output_dir, output_filename)
Greg Warddbd12761999-08-29 18:15:07 +0000452
Greg Ward32c4a8a2000-03-06 03:40:29 +0000453 if self._need_link (objects, output_filename):
454
455 if debug:
456 ldflags = self.ldflags_shared_debug
Greg Ward32c4a8a2000-03-06 03:40:29 +0000457 else:
458 ldflags = self.ldflags_shared
459
Greg Ward5299b6a2000-05-20 13:23:21 +0000460 export_opts = []
461 for sym in (export_symbols or []):
462 export_opts.append("/EXPORT:" + sym)
463
464 ld_args = (ldflags + lib_opts + export_opts +
465 objects + ['/OUT:' + output_filename])
Greg Ward32c4a8a2000-03-06 03:40:29 +0000466
Greg Ward159eb922000-08-02 00:00:30 +0000467 # The MSVC linker generates .lib and .exp files, which cannot be
468 # suppressed by any linker switches. The .lib files may even be
469 # needed! Make sure they are generated in the temporary build
470 # directory. Since they have different names for debug and release
471 # builds, they can go into the same directory.
472 (dll_name, dll_ext) = os.path.splitext(
473 os.path.basename(output_filename))
474 implib_file = os.path.join(
475 os.path.dirname(objects[0]),
476 self.library_filename(dll_name))
477 ld_args.append ('/IMPLIB:' + implib_file)
478
Greg Ward32c4a8a2000-03-06 03:40:29 +0000479 if extra_preargs:
480 ld_args[:0] = extra_preargs
481 if extra_postargs:
Greg Ward159eb922000-08-02 00:00:30 +0000482 ld_args.extend(extra_postargs)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000483
484 self.mkpath (os.path.dirname (output_filename))
Greg Wardd1517112000-05-30 01:56:44 +0000485 try:
486 self.spawn ([self.link] + ld_args)
487 except DistutilsExecError, msg:
488 raise LinkError, msg
Greg Ward32c4a8a2000-03-06 03:40:29 +0000489
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000490 else:
Greg Ward32c4a8a2000-03-06 03:40:29 +0000491 self.announce ("skipping %s (up-to-date)" % output_filename)
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000492
Greg Ward32c4a8a2000-03-06 03:40:29 +0000493 # link_shared_object ()
Greg Wardf70c6032000-04-19 02:16:49 +0000494
495
496 def link_executable (self,
497 objects,
498 output_progname,
499 output_dir=None,
500 libraries=None,
501 library_dirs=None,
502 runtime_library_dirs=None,
503 debug=0,
504 extra_preargs=None,
505 extra_postargs=None):
506
507 (objects, output_dir) = self._fix_object_args (objects, output_dir)
508 (libraries, library_dirs, runtime_library_dirs) = \
509 self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
510
511 if runtime_library_dirs:
512 self.warn ("I don't know what to do with 'runtime_library_dirs': "
513 + str (runtime_library_dirs))
514
515 lib_opts = gen_lib_options (self,
516 library_dirs, runtime_library_dirs,
517 libraries)
518 output_filename = output_progname + self.exe_extension
519 if output_dir is not None:
520 output_filename = os.path.join (output_dir, output_filename)
521
522 if self._need_link (objects, output_filename):
523
524 if debug:
525 ldflags = self.ldflags_shared_debug[1:]
526 else:
527 ldflags = self.ldflags_shared[1:]
528
529 ld_args = ldflags + lib_opts + \
530 objects + ['/OUT:' + output_filename]
531
532 if extra_preargs:
533 ld_args[:0] = extra_preargs
534 if extra_postargs:
535 ld_args.extend (extra_postargs)
536
537 self.mkpath (os.path.dirname (output_filename))
Greg Wardd1517112000-05-30 01:56:44 +0000538 try:
539 self.spawn ([self.link] + ld_args)
540 except DistutilsExecError, msg:
541 raise LinkError, msg
Greg Wardf70c6032000-04-19 02:16:49 +0000542 else:
543 self.announce ("skipping %s (up-to-date)" % output_filename)
Greg Ward32c4a8a2000-03-06 03:40:29 +0000544
Greg Ward4ba9b2e2000-02-10 02:15:52 +0000545
Greg Ward32c4a8a2000-03-06 03:40:29 +0000546 # -- Miscellaneous methods -----------------------------------------
547 # These are all used by the 'gen_lib_options() function, in
548 # ccompiler.py.
Greg Wardc74138d1999-10-03 20:47:52 +0000549
550 def library_dir_option (self, dir):
551 return "/LIBPATH:" + dir
552
Greg Wardd03f88a2000-03-18 15:19:51 +0000553 def runtime_library_dir_option (self, dir):
554 raise DistutilsPlatformError, \
555 "don't know how to set runtime library search path for MSVC++"
556
Greg Wardc74138d1999-10-03 20:47:52 +0000557 def library_option (self, lib):
558 return self.library_filename (lib)
559
560
Greg Wardd1425642000-08-04 01:29:27 +0000561 def find_library_file (self, dirs, lib, debug=0):
562 # Prefer a debugging library if found (and requested), but deal
563 # with it if we don't have one.
564 if debug:
565 try_names = [lib + "_d", lib]
566 else:
567 try_names = [lib]
Greg Wardc74138d1999-10-03 20:47:52 +0000568 for dir in dirs:
Greg Wardd1425642000-08-04 01:29:27 +0000569 for name in try_names:
570 libfile = os.path.join(dir, self.library_filename (name))
571 if os.path.exists(libfile):
572 return libfile
Greg Wardc74138d1999-10-03 20:47:52 +0000573 else:
574 # Oops, didn't find it in *any* of 'dirs'
575 return None
576
577 # find_library_file ()
578
Greg Warddbd12761999-08-29 18:15:07 +0000579# class MSVCCompiler