blob: 64b2730713382220feacaecc9c1c286f567eae4e [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,
26 dry_run=0):
27
28 CCompiler.__init__ (self, verbose, dry_run)
29
Greg Warddbd12761999-08-29 18:15:07 +000030 # XXX This is a nasty dependency to add on something otherwise
Greg Ward3d50b901999-09-08 02:36:01 +000031 # pretty clean. move it to build_ext under an nt specific part.
32 # shared libraries need to link against python15.lib
Greg Warddbd12761999-08-29 18:15:07 +000033 self.add_library ( "python" + sys.version[0] + sys.version[2] )
34 self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) )
35
36 self.cc = "cl.exe"
37 self.link = "link.exe"
38 self.preprocess_options = None
39 self.compile_options = [ '/nologo' ]
40
41 self.ldflags_shared = ['/DLL', '/nologo']
42 self.ldflags_static = [ '/nologo']
43
Greg Warddbd12761999-08-29 18:15:07 +000044
45 # -- Worker methods ------------------------------------------------
46 # (must be implemented by subclasses)
47
48 _c_extensions = [ '.c' ]
Greg Ward3d50b901999-09-08 02:36:01 +000049 _cpp_extensions = [ '.cc', '.cpp' ]
Greg Warddbd12761999-08-29 18:15:07 +000050
51 _obj_ext = '.obj'
Greg Ward3d50b901999-09-08 02:36:01 +000052 _exe_ext = '.exe'
Greg Warddbd12761999-08-29 18:15:07 +000053 _shared_lib_ext = '.dll'
54 _static_lib_ext = '.lib'
Greg Warddf178f91999-09-29 12:29:10 +000055
56 # XXX the 'output_dir' parameter is ignored by the methods in this
57 # class! I just put it in to be consistent with CCompiler and
58 # UnixCCompiler, but someone who actually knows Visual C++ will
59 # have to make it work...
Greg Warddbd12761999-08-29 18:15:07 +000060
61 def compile (self,
62 sources,
Greg Warddf178f91999-09-29 12:29:10 +000063 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +000064 macros=None,
Greg Warddf178f91999-09-29 12:29:10 +000065 includes=None,
66 extra_preargs=None,
67 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +000068
69 if macros is None:
70 macros = []
71 if includes is None:
72 includes = []
73
74 objectFiles = []
75
Greg Ward3d50b901999-09-08 02:36:01 +000076 base_pp_opts = gen_preprocess_options (self.macros + macros,
77 self.include_dirs + includes)
Greg Warddbd12761999-08-29 18:15:07 +000078
79 base_pp_opts.append('/c')
80
81 for srcFile in sources:
82 base,ext = os.path.splitext(srcFile)
83 objFile = base + ".obj"
84
85 if ext in self._c_extensions:
86 fileOpt = "/Tc"
87 elif ext in self._cpp_extensions:
88 fileOpt = "/Tp"
89
90 inputOpt = fileOpt + srcFile
91 outputOpt = "/Fo" + objFile
92
Greg Warddf178f91999-09-29 12:29:10 +000093 cc_args = self.compile_options + \
94 base_pp_opts + \
95 [outputOpt, inputOpt]
96 if extra_preargs:
97 cc_args[:0] = extra_preargs
98 if extra_postargs:
99 cc_args.extend (extra_postargs)
Greg Warddbd12761999-08-29 18:15:07 +0000100
Greg Warddf178f91999-09-29 12:29:10 +0000101 self.spawn ([self.cc] + cc_args)
Greg Warddbd12761999-08-29 18:15:07 +0000102 objectFiles.append( objFile )
Greg Warddbd12761999-08-29 18:15:07 +0000103 return objectFiles
Greg Ward3d50b901999-09-08 02:36:01 +0000104
105
Greg Warddbd12761999-08-29 18:15:07 +0000106 # XXX this is kind of useless without 'link_binary()' or
107 # 'link_executable()' or something -- or maybe 'link_static_lib()'
108 # should not exist at all, and we just have 'link_binary()'?
109 def link_static_lib (self,
110 objects,
111 output_libname,
Greg Warddf178f91999-09-29 12:29:10 +0000112 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000113 libraries=None,
Greg Warddf178f91999-09-29 12:29:10 +0000114 library_dirs=None,
115 extra_preargs=None,
116 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +0000117
Greg Warddbd12761999-08-29 18:15:07 +0000118 if libraries is None:
119 libraries = []
120 if library_dirs is None:
121 library_dirs = []
Greg Warddbd12761999-08-29 18:15:07 +0000122
Greg Ward3d50b901999-09-08 02:36:01 +0000123 lib_opts = gen_lib_options (self.libraries + libraries,
124 self.library_dirs + library_dirs,
125 "%s.lib", "/LIBPATH:%s")
Greg Warddbd12761999-08-29 18:15:07 +0000126
Greg Warddbd12761999-08-29 18:15:07 +0000127 ld_args = self.ldflags_static + lib_opts + \
128 objects + ['/OUT:' + output_filename]
Greg Warddf178f91999-09-29 12:29:10 +0000129 if extra_preargs:
130 ld_args[:0] = extra_preargs
131 if extra_postargs:
132 ld_args.extend (extra_postargs)
Greg Warddbd12761999-08-29 18:15:07 +0000133
134 self.spawn ( [ self.link ] + ld_args )
135
136
137 def link_shared_lib (self,
138 objects,
139 output_libname,
Greg Warddf178f91999-09-29 12:29:10 +0000140 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000141 libraries=None,
142 library_dirs=None,
Greg Warddf178f91999-09-29 12:29:10 +0000143 extra_preargs=None,
144 extra_postargs=None):
145
Greg Warddbd12761999-08-29 18:15:07 +0000146 # XXX should we sanity check the library name? (eg. no
147 # slashes)
Greg Warddf178f91999-09-29 12:29:10 +0000148 self.link_shared_object (objects,
149 self.shared_library_name(output_libname))
Greg Warddbd12761999-08-29 18:15:07 +0000150
151 def link_shared_object (self,
152 objects,
153 output_filename,
Greg Warddf178f91999-09-29 12:29:10 +0000154 output_dir=None,
Greg Warddbd12761999-08-29 18:15:07 +0000155 libraries=None,
156 library_dirs=None,
Greg Warddf178f91999-09-29 12:29:10 +0000157 extra_preargs=None,
158 extra_postargs=None):
Greg Warddbd12761999-08-29 18:15:07 +0000159 """Link a bunch of stuff together to create a shared object
160 file. Much like 'link_shared_lib()', except the output
161 filename is explicitly supplied as 'output_filename'."""
162 if libraries is None:
163 libraries = []
164 if library_dirs is None:
165 library_dirs = []
Greg Warddbd12761999-08-29 18:15:07 +0000166
Greg Warddf178f91999-09-29 12:29:10 +0000167 lib_opts = gen_lib_options (self.library_dirs + library_dirs,
168 self.libraries + libraries,
169 "/LIBPATH:%s", "%s.lib")
Greg Warddbd12761999-08-29 18:15:07 +0000170
Greg Warddbd12761999-08-29 18:15:07 +0000171 ld_args = self.ldflags_shared + lib_opts + \
172 objects + ['/OUT:' + output_filename]
Greg Warddf178f91999-09-29 12:29:10 +0000173 if extra_preargs:
174 ld_args[:0] = extra_preargs
175 if extra_postargs:
176 ld_args.extend (extra_postargs)
Greg Warddbd12761999-08-29 18:15:07 +0000177
178 self.spawn ( [ self.link ] + ld_args )
179
180
181 # -- Filename mangling methods -------------------------------------
182
183 def _change_extensions( self, filenames, newExtension ):
184 object_filenames = []
185
186 for srcFile in filenames:
187 base,ext = os.path.splitext( srcFile )
188 # XXX should we strip off any existing path?
189 object_filenames.append( base + newExtension )
190
191 return object_filenames
192
193 def object_filenames (self, source_filenames):
194 """Return the list of object filenames corresponding to each
195 specified source filename."""
196 return self._change_extensions( source_filenames, self._obj_ext )
197
198 def shared_object_filename (self, source_filename):
199 """Return the shared object filename corresponding to a
200 specified source filename."""
201 return self._change_extensions( source_filenames, self._shared_lib_ext )
202
203 def library_filename (self, libname):
204 """Return the static library filename corresponding to the
205 specified library name."""
206 return "lib%s%s" %( libname, self._static_lib_ext )
207
208 def shared_library_filename (self, libname):
209 """Return the shared library filename corresponding to the
210 specified library name."""
211 return "lib%s%s" %( libname, self._shared_lib_ext )
212
213# class MSVCCompiler