blob: f328232bc02dfab92069307fca09ed8b608d520b [file] [log] [blame]
Greg Warddbd12761999-08-29 18:15:07 +00001"""distutils.ccompiler
2
3Contains MSVCCompiler, an implementation of the abstract CCompiler class
4for the Microsoft Visual Studio """
5
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
22 def __init__ (self,
23 verbose=0,
24 dry_run=0):
25
26 CCompiler.__init__ (self, verbose, dry_run)
27
Greg Warddbd12761999-08-29 18:15:07 +000028 # XXX This is a nasty dependency to add on something otherwise
Greg Ward3d50b901999-09-08 02:36:01 +000029 # pretty clean. move it to build_ext under an nt specific part.
30 # shared libraries need to link against python15.lib
Greg Warddbd12761999-08-29 18:15:07 +000031 self.add_library ( "python" + sys.version[0] + sys.version[2] )
32 self.add_library_dir( os.path.join( sys.exec_prefix, 'libs' ) )
33
34 self.cc = "cl.exe"
35 self.link = "link.exe"
36 self.preprocess_options = None
37 self.compile_options = [ '/nologo' ]
38
39 self.ldflags_shared = ['/DLL', '/nologo']
40 self.ldflags_static = [ '/nologo']
41
Greg Warddbd12761999-08-29 18:15:07 +000042
43 # -- Worker methods ------------------------------------------------
44 # (must be implemented by subclasses)
45
46 _c_extensions = [ '.c' ]
Greg Ward3d50b901999-09-08 02:36:01 +000047 _cpp_extensions = [ '.cc', '.cpp' ]
Greg Warddbd12761999-08-29 18:15:07 +000048
49 _obj_ext = '.obj'
Greg Ward3d50b901999-09-08 02:36:01 +000050 _exe_ext = '.exe'
Greg Warddbd12761999-08-29 18:15:07 +000051 _shared_lib_ext = '.dll'
52 _static_lib_ext = '.lib'
53
54 def compile (self,
55 sources,
56 macros=None,
57 includes=None):
58 """Compile one or more C/C++ source files. 'sources' must be
59 a list of strings, each one the name of a C/C++ source
60 file. Return a list of the object filenames generated
61 (one for each source filename in 'sources').
62
63 'macros', if given, must be a list of macro definitions. A
64 macro definition is either a (name, value) 2-tuple or a (name,)
65 1-tuple. The former defines a macro; if the value is None, the
66 macro is defined without an explicit value. The 1-tuple case
67 undefines a macro. Later definitions/redefinitions/
68 undefinitions take precedence.
69
70 'includes', if given, must be a list of strings, the directories
71 to add to the default include file search path for this
72 compilation only."""
73
74 if macros is None:
75 macros = []
76 if includes is None:
77 includes = []
78
79 objectFiles = []
80
Greg Ward3d50b901999-09-08 02:36:01 +000081 base_pp_opts = gen_preprocess_options (self.macros + macros,
82 self.include_dirs + includes)
Greg Warddbd12761999-08-29 18:15:07 +000083
84 base_pp_opts.append('/c')
85
86 for srcFile in sources:
87 base,ext = os.path.splitext(srcFile)
88 objFile = base + ".obj"
89
90 if ext in self._c_extensions:
91 fileOpt = "/Tc"
92 elif ext in self._cpp_extensions:
93 fileOpt = "/Tp"
94
95 inputOpt = fileOpt + srcFile
96 outputOpt = "/Fo" + objFile
97
98 pp_opts = base_pp_opts + [ outputOpt, inputOpt ]
99
Greg Ward3d50b901999-09-08 02:36:01 +0000100 self.spawn( [ self.cc ] + self.compile_options + pp_opts)
Greg Warddbd12761999-08-29 18:15:07 +0000101 objectFiles.append( objFile )
102
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,
112 libraries=None,
113 library_dirs=None):
114 """Link a bunch of stuff together to create a static library
115 file. The "bunch of stuff" consists of the list of object
116 files supplied as 'objects', the extra object files supplied
117 to 'add_link_object()' and/or 'set_link_objects()', the
118 libraries supplied to 'add_library()' and/or
119 'set_libraries()', and the libraries supplied as 'libraries'
120 (if any).
121
122 'output_libname' should be a library name, not a filename;
123 the filename will be inferred from the library name.
124
125 'library_dirs', if supplied, should be a list of additional
126 directories to search on top of the system default and those
127 supplied to 'add_library_dir()' and/or 'set_library_dirs()'."""
128
129 if libraries is None:
130 libraries = []
131 if library_dirs is None:
132 library_dirs = []
133 if build_info is None:
134 build_info = {}
135
Greg Ward3d50b901999-09-08 02:36:01 +0000136 lib_opts = gen_lib_options (self.libraries + libraries,
137 self.library_dirs + library_dirs,
138 "%s.lib", "/LIBPATH:%s")
Greg Warddbd12761999-08-29 18:15:07 +0000139
140 if build_info.has_key('def_file') :
141 lib_opts.append('/DEF:' + build_info['def_file'] )
142
143 ld_args = self.ldflags_static + lib_opts + \
144 objects + ['/OUT:' + output_filename]
145
146 self.spawn ( [ self.link ] + ld_args )
147
148
149 def link_shared_lib (self,
150 objects,
151 output_libname,
152 libraries=None,
153 library_dirs=None,
154 build_info=None):
155 """Link a bunch of stuff together to create a shared library
156 file. Has the same effect as 'link_static_lib()' except
157 that the filename inferred from 'output_libname' will most
158 likely be different, and the type of file generated will
159 almost certainly be different."""
160 # XXX should we sanity check the library name? (eg. no
161 # slashes)
162 self.link_shared_object (objects, self.shared_library_name(output_libname),
163 build_info=build_info )
164
165 def link_shared_object (self,
166 objects,
167 output_filename,
168 libraries=None,
169 library_dirs=None,
170 build_info=None):
171 """Link a bunch of stuff together to create a shared object
172 file. Much like 'link_shared_lib()', except the output
173 filename is explicitly supplied as 'output_filename'."""
174 if libraries is None:
175 libraries = []
176 if library_dirs is None:
177 library_dirs = []
178 if build_info is None:
179 build_info = {}
180
Greg Ward3d50b901999-09-08 02:36:01 +0000181 lib_opts = gen_lib_options (self.libraries + libraries,
182 self.library_dirs + library_dirs,
183 "%s.lib", "/LIBPATH:%s")
Greg Warddbd12761999-08-29 18:15:07 +0000184
185 if build_info.has_key('def_file') :
186 lib_opts.append('/DEF:' + build_info['def_file'] )
187
188 ld_args = self.ldflags_shared + lib_opts + \
189 objects + ['/OUT:' + output_filename]
190
191 self.spawn ( [ self.link ] + ld_args )
192
193
194 # -- Filename mangling methods -------------------------------------
195
196 def _change_extensions( self, filenames, newExtension ):
197 object_filenames = []
198
199 for srcFile in filenames:
200 base,ext = os.path.splitext( srcFile )
201 # XXX should we strip off any existing path?
202 object_filenames.append( base + newExtension )
203
204 return object_filenames
205
206 def object_filenames (self, source_filenames):
207 """Return the list of object filenames corresponding to each
208 specified source filename."""
209 return self._change_extensions( source_filenames, self._obj_ext )
210
211 def shared_object_filename (self, source_filename):
212 """Return the shared object filename corresponding to a
213 specified source filename."""
214 return self._change_extensions( source_filenames, self._shared_lib_ext )
215
216 def library_filename (self, libname):
217 """Return the static library filename corresponding to the
218 specified library name."""
219 return "lib%s%s" %( libname, self._static_lib_ext )
220
221 def shared_library_filename (self, libname):
222 """Return the shared library filename corresponding to the
223 specified library name."""
224 return "lib%s%s" %( libname, self._shared_lib_ext )
225
226# class MSVCCompiler