blob: d93c74c76d9d1d3f4d19274ccea5476f6cdeaa0c [file] [log] [blame]
Greg Warddbd12761999-08-29 18:15:07 +00001"""distutils.ccompiler
2
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
8#
9__rcsid__ = "$Id$"
10
11import os
12import sys
13from distutils.errors import *
Greg Ward3d50b901999-09-08 02:36:01 +000014from distutils.ccompiler import \
15 CCompiler, gen_preprocess_options, gen_lib_options
Greg Warddbd12761999-08-29 18:15:07 +000016
17
Greg Ward3d50b901999-09-08 02:36:01 +000018class MSVCCompiler (CCompiler) :
19 """Concrete class that implements an interface to Microsoft Visual C++,
20 as defined by the CCompiler abstract class."""
Greg Warddbd12761999-08-29 18:15:07 +000021
Greg Warddf178f91999-09-29 12:29:10 +000022 compiler_type = 'msvc'
23
Greg Warddbd12761999-08-29 18:15:07 +000024 def __init__ (self,
25 verbose=0,
Greg Wardc74138d1999-10-03 20:47:52 +000026 dry_run=0,
27 force=0):
Greg Warddbd12761999-08-29 18:15:07 +000028
Greg Wardc74138d1999-10-03 20:47:52 +000029 CCompiler.__init__ (self, verbose, dry_run, force)
Greg Warddbd12761999-08-29 18:15:07 +000030
Greg Warddbd12761999-08-29 18:15:07 +000031 # XXX This is a nasty dependency to add on something otherwise
Greg Ward3d50b901999-09-08 02:36:01 +000032 # pretty clean. move it to build_ext under an nt specific part.
33 # shared libraries need to link against python15.lib
Greg Warddbd12761999-08-29 18:15:07 +000034 self.add_library ( "python" + sys.version[0] + sys.version[2] )
35 self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) )
36
37 self.cc = "cl.exe"
38 self.link = "link.exe"
39 self.preprocess_options = None
40 self.compile_options = [ '/nologo' ]
41
42 self.ldflags_shared = ['/DLL', '/nologo']
43 self.ldflags_static = [ '/nologo']
44
Greg Warddbd12761999-08-29 18:15:07 +000045
46 # -- Worker methods ------------------------------------------------
47 # (must be implemented by subclasses)
48
49 _c_extensions = [ '.c' ]
Greg Ward3d50b901999-09-08 02:36:01 +000050 _cpp_extensions = [ '.cc', '.cpp' ]
Greg Warddbd12761999-08-29 18:15:07 +000051
52 _obj_ext = '.obj'
Greg Ward3d50b901999-09-08 02:36:01 +000053 _exe_ext = '.exe'
Greg Warddbd12761999-08-29 18:15:07 +000054 _shared_lib_ext = '.dll'
55 _static_lib_ext = '.lib'
Greg Warddf178f91999-09-29 12:29:10 +000056
57 # XXX the 'output_dir' parameter is ignored by the methods in this
58 # class! I just put it in to be consistent with CCompiler and
59 # UnixCCompiler, but someone who actually knows Visual C++ will
60 # have to make it work...
Greg Warddbd12761999-08-29 18:15:07 +000061
62 def compile (self,
63 sources,
Greg Warddf178f91999-09-29 12:29:10 +000064 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +000065 macros=None,
Greg Ward0bdd90a1999-12-12 17:19:58 +000066 include_dirs=None,
Greg Warddf178f91999-09-29 12:29:10 +000067 extra_preargs=None,
68 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +000069
70 if macros is None:
71 macros = []
Greg Ward0bdd90a1999-12-12 17:19:58 +000072 if include_dirs is None:
73 include_dirs = []
Greg Warddbd12761999-08-29 18:15:07 +000074
75 objectFiles = []
76
Greg Ward0bdd90a1999-12-12 17:19:58 +000077 base_pp_opts = \
78 gen_preprocess_options (self.macros + macros,
79 self.include_dirs + include_dirs)
Greg Warddbd12761999-08-29 18:15:07 +000080
81 base_pp_opts.append('/c')
82
83 for srcFile in sources:
84 base,ext = os.path.splitext(srcFile)
85 objFile = base + ".obj"
86
87 if ext in self._c_extensions:
88 fileOpt = "/Tc"
89 elif ext in self._cpp_extensions:
90 fileOpt = "/Tp"
91
92 inputOpt = fileOpt + srcFile
93 outputOpt = "/Fo" + objFile
94
Greg Warddf178f91999-09-29 12:29:10 +000095 cc_args = self.compile_options + \
96 base_pp_opts + \
97 [outputOpt, inputOpt]
98 if extra_preargs:
99 cc_args[:0] = extra_preargs
100 if extra_postargs:
101 cc_args.extend (extra_postargs)
Greg Warddbd12761999-08-29 18:15:07 +0000102
Greg Warddf178f91999-09-29 12:29:10 +0000103 self.spawn ([self.cc] + cc_args)
Greg Warddbd12761999-08-29 18:15:07 +0000104 objectFiles.append( objFile )
Greg Warddbd12761999-08-29 18:15:07 +0000105 return objectFiles
Greg Ward3d50b901999-09-08 02:36:01 +0000106
107
Greg Warddbd12761999-08-29 18:15:07 +0000108 # XXX this is kind of useless without 'link_binary()' or
109 # 'link_executable()' or something -- or maybe 'link_static_lib()'
110 # should not exist at all, and we just have 'link_binary()'?
111 def link_static_lib (self,
112 objects,
113 output_libname,
Greg Warddf178f91999-09-29 12:29:10 +0000114 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000115 libraries=None,
Greg Warddf178f91999-09-29 12:29:10 +0000116 library_dirs=None,
117 extra_preargs=None,
118 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +0000119
Greg Warddbd12761999-08-29 18:15:07 +0000120 if libraries is None:
121 libraries = []
122 if library_dirs is None:
123 library_dirs = []
Greg Warddbd12761999-08-29 18:15:07 +0000124
Greg Ward3d50b901999-09-08 02:36:01 +0000125 lib_opts = gen_lib_options (self.libraries + libraries,
126 self.library_dirs + library_dirs,
127 "%s.lib", "/LIBPATH:%s")
Greg Warddbd12761999-08-29 18:15:07 +0000128
Greg Warddbd12761999-08-29 18:15:07 +0000129 ld_args = self.ldflags_static + lib_opts + \
130 objects + ['/OUT:' + output_filename]
Greg Warddf178f91999-09-29 12:29:10 +0000131 if extra_preargs:
132 ld_args[:0] = extra_preargs
133 if extra_postargs:
134 ld_args.extend (extra_postargs)
Greg Warddbd12761999-08-29 18:15:07 +0000135
136 self.spawn ( [ self.link ] + ld_args )
137
138
139 def link_shared_lib (self,
140 objects,
141 output_libname,
Greg Warddf178f91999-09-29 12:29:10 +0000142 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000143 libraries=None,
144 library_dirs=None,
Greg Warddf178f91999-09-29 12:29:10 +0000145 extra_preargs=None,
146 extra_postargs=None):
147
Greg Warddbd12761999-08-29 18:15:07 +0000148 # XXX should we sanity check the library name? (eg. no
149 # slashes)
Greg Warddf178f91999-09-29 12:29:10 +0000150 self.link_shared_object (objects,
151 self.shared_library_name(output_libname))
Greg Warddbd12761999-08-29 18:15:07 +0000152
153 def link_shared_object (self,
154 objects,
155 output_filename,
Greg Warddf178f91999-09-29 12:29:10 +0000156 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000157 libraries=None,
158 library_dirs=None,
Greg Warddf178f91999-09-29 12:29:10 +0000159 extra_preargs=None,
160 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +0000161 """Link a bunch of stuff together to create a shared object
162 file. Much like 'link_shared_lib()', except the output
163 filename is explicitly supplied as 'output_filename'."""
164 if libraries is None:
165 libraries = []
166 if library_dirs is None:
167 library_dirs = []
Greg Warddbd12761999-08-29 18:15:07 +0000168
Greg Wardc74138d1999-10-03 20:47:52 +0000169 lib_opts = gen_lib_options (self,
170 self.library_dirs + library_dirs,
171 self.libraries + libraries)
Greg Warddbd12761999-08-29 18:15:07 +0000172
Greg Warddbd12761999-08-29 18:15:07 +0000173 ld_args = self.ldflags_shared + lib_opts + \
174 objects + ['/OUT:' + output_filename]
Greg Warddf178f91999-09-29 12:29:10 +0000175 if extra_preargs:
176 ld_args[:0] = extra_preargs
177 if extra_postargs:
178 ld_args.extend (extra_postargs)
Greg Warddbd12761999-08-29 18:15:07 +0000179
180 self.spawn ( [ self.link ] + ld_args )
181
182
183 # -- Filename mangling methods -------------------------------------
184
185 def _change_extensions( self, filenames, newExtension ):
186 object_filenames = []
187
188 for srcFile in filenames:
189 base,ext = os.path.splitext( srcFile )
190 # XXX should we strip off any existing path?
191 object_filenames.append( base + newExtension )
192
193 return object_filenames
194
195 def object_filenames (self, source_filenames):
196 """Return the list of object filenames corresponding to each
197 specified source filename."""
198 return self._change_extensions( source_filenames, self._obj_ext )
199
200 def shared_object_filename (self, source_filename):
201 """Return the shared object filename corresponding to a
202 specified source filename."""
203 return self._change_extensions( source_filenames, self._shared_lib_ext )
204
Greg Wardc74138d1999-10-03 20:47:52 +0000205 # XXX ummm... these aren't right, are they? I thought library 'foo' on
206 # DOS/Windows was to be found in "foo.lib", not "libfoo.lib"!
207
Greg Warddbd12761999-08-29 18:15:07 +0000208 def library_filename (self, libname):
209 """Return the static library filename corresponding to the
210 specified library name."""
211 return "lib%s%s" %( libname, self._static_lib_ext )
212
213 def shared_library_filename (self, libname):
214 """Return the shared library filename corresponding to the
215 specified library name."""
216 return "lib%s%s" %( libname, self._shared_lib_ext )
217
Greg Wardc74138d1999-10-03 20:47:52 +0000218
219 def library_dir_option (self, dir):
220 return "/LIBPATH:" + dir
221
222 def library_option (self, lib):
223 return self.library_filename (lib)
224
225
226 def find_library_file (self, dirs, lib):
227
228 for dir in dirs:
229 libfile = os.path.join (dir, self.library_filename (lib))
230 if os.path.exists (libfile):
231 return libfile
232
233 else:
234 # Oops, didn't find it in *any* of 'dirs'
235 return None
236
237 # find_library_file ()
238
Greg Warddbd12761999-08-29 18:15:07 +0000239# class MSVCCompiler