blob: d74aa6a27758b7c4c3d23d201e201e8124ab2569 [file] [log] [blame]
Greg Ward28a5f442000-06-06 02:57:07 +00001"""distutils.command.config
2
3Implements the Distutils 'config' command, a (mostly) empty command class
4that exists mainly to be sub-classed by specific module distributions and
5applications. The idea is that while every "config" command is different,
6at least they're all named the same, and users always see "config" in the
7list of standard commands. Also, this is a good place to put common
8configure-like tasks: "try to compile this C code", or "figure out where
9this header file lives".
10"""
11
12# created 2000/05/29, Greg Ward
13
14__revision__ = "$Id$"
15
Greg Ward59ac7092000-06-21 03:00:50 +000016import sys, os, string, re
Greg Ward2e38a502000-10-14 03:40:20 +000017from types import *
Greg Ward28a5f442000-06-06 02:57:07 +000018from distutils.core import Command
19from distutils.errors import DistutilsExecError
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000020from distutils import log
Greg Ward28a5f442000-06-06 02:57:07 +000021
22LANG_EXT = {'c': '.c',
23 'c++': '.cxx'}
24
25class config (Command):
26
27 description = "prepare to build"
28
29 user_options = [
30 ('compiler=', None,
31 "specify the compiler type"),
32 ('cc=', None,
33 "specify the compiler executable"),
34 ('include-dirs=', 'I',
35 "list of directories to search for header files"),
36 ('define=', 'D',
37 "C preprocessor macros to define"),
38 ('undef=', 'U',
39 "C preprocessor macros to undefine"),
40 ('libraries=', 'l',
41 "external C libraries to link with"),
42 ('library-dirs=', 'L',
43 "directories to search for external C libraries"),
Greg Ward59ac7092000-06-21 03:00:50 +000044
45 ('noisy', None,
46 "show every action (compile, link, run, ...) taken"),
47 ('dump-source', None,
48 "dump generated source files before attempting to compile them"),
Greg Ward28a5f442000-06-06 02:57:07 +000049 ]
50
51
52 # The three standard command methods: since the "config" command
53 # does nothing by default, these are empty.
54
55 def initialize_options (self):
56 self.compiler = None
57 self.cc = None
58 self.include_dirs = None
59 #self.define = None
60 #self.undef = None
61 self.libraries = None
62 self.library_dirs = None
63
Greg Ward59ac7092000-06-21 03:00:50 +000064 # maximal output for now
65 self.noisy = 1
66 self.dump_source = 1
67
68 # list of temporary files generated along-the-way that we have
69 # to clean at some point
70 self.temp_files = []
71
Greg Ward28a5f442000-06-06 02:57:07 +000072 def finalize_options (self):
Greg Ward2e38a502000-10-14 03:40:20 +000073 if self.include_dirs is None:
74 self.include_dirs = self.distribution.include_dirs or []
75 elif type(self.include_dirs) is StringType:
76 self.include_dirs = string.split(self.include_dirs, os.pathsep)
77
78 if self.libraries is None:
79 self.libraries = []
80 elif type(self.libraries) is StringType:
81 self.libraries = [self.libraries]
82
83 if self.library_dirs is None:
84 self.library_dirs = []
85 elif type(self.library_dirs) is StringType:
86 self.library_dirs = string.split(self.library_dirs, os.pathsep)
87
Greg Ward28a5f442000-06-06 02:57:07 +000088
89 def run (self):
90 pass
91
92
93 # Utility methods for actual "config" commands. The interfaces are
94 # loosely based on Autoconf macros of similar names. Sub-classes
95 # may use these freely.
96
97 def _check_compiler (self):
98 """Check that 'self.compiler' really is a CCompiler object;
99 if not, make it one.
100 """
101 # We do this late, and only on-demand, because this is an expensive
102 # import.
103 from distutils.ccompiler import CCompiler, new_compiler
104 if not isinstance(self.compiler, CCompiler):
Greg Wardcb1f4c42000-09-30 18:27:54 +0000105 self.compiler = new_compiler(compiler=self.compiler,
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000106 dry_run=self.dry_run, force=1)
Greg Ward28a5f442000-06-06 02:57:07 +0000107 if self.include_dirs:
108 self.compiler.set_include_dirs(self.include_dirs)
109 if self.libraries:
110 self.compiler.set_libraries(self.libraries)
111 if self.library_dirs:
112 self.compiler.set_library_dirs(self.library_dirs)
113
114
Greg Ward59ac7092000-06-21 03:00:50 +0000115 def _gen_temp_sourcefile (self, body, headers, lang):
Greg Ward28a5f442000-06-06 02:57:07 +0000116 filename = "_configtest" + LANG_EXT[lang]
117 file = open(filename, "w")
Greg Ward59ac7092000-06-21 03:00:50 +0000118 if headers:
119 for header in headers:
120 file.write("#include <%s>\n" % header)
121 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000122 file.write(body)
Greg Ward59ac7092000-06-21 03:00:50 +0000123 if body[-1] != "\n":
124 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000125 file.close()
126 return filename
127
Greg Ward855dab92000-06-27 01:21:22 +0000128 def _preprocess (self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000129 src = self._gen_temp_sourcefile(body, headers, lang)
130 out = "_configtest.i"
131 self.temp_files.extend([src, out])
Greg Ward855dab92000-06-27 01:21:22 +0000132 self.compiler.preprocess(src, out, include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000133 return (src, out)
134
Greg Ward855dab92000-06-27 01:21:22 +0000135 def _compile (self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000136 src = self._gen_temp_sourcefile(body, headers, lang)
137 if self.dump_source:
138 dump_file(src, "compiling '%s':" % src)
139 (obj,) = self.compiler.object_filenames([src])
140 self.temp_files.extend([src, obj])
Greg Ward855dab92000-06-27 01:21:22 +0000141 self.compiler.compile([src], include_dirs=include_dirs)
Greg Ward28a5f442000-06-06 02:57:07 +0000142 return (src, obj)
143
Greg Ward855dab92000-06-27 01:21:22 +0000144 def _link (self, body,
145 headers, include_dirs,
146 libraries, library_dirs, lang):
147 (src, obj) = self._compile(body, headers, include_dirs, lang)
Fred Drake21d45352001-12-06 21:01:19 +0000148 prog = os.path.splitext(os.path.basename(src))[0]
Greg Ward59ac7092000-06-21 03:00:50 +0000149 self.compiler.link_executable([obj], prog,
150 libraries=libraries,
151 library_dirs=library_dirs)
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000152
153 prog = prog + self.compiler.exe_extension
154 self.temp_files.append(prog)
155
Greg Ward59ac7092000-06-21 03:00:50 +0000156 return (src, obj, prog)
Greg Ward28a5f442000-06-06 02:57:07 +0000157
158 def _clean (self, *filenames):
Greg Ward59ac7092000-06-21 03:00:50 +0000159 if not filenames:
160 filenames = self.temp_files
161 self.temp_files = []
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000162 log.info("removing: %s", string.join(filenames))
Greg Ward28a5f442000-06-06 02:57:07 +0000163 for filename in filenames:
164 try:
165 os.remove(filename)
166 except OSError:
167 pass
168
169
Greg Ward28a5f442000-06-06 02:57:07 +0000170 # XXX these ignore the dry-run flag: what to do, what to do? even if
171 # you want a dry-run build, you still need some sort of configuration
172 # info. My inclination is to make it up to the real config command to
173 # consult 'dry_run', and assume a default (minimal) configuration if
174 # true. The problem with trying to do it here is that you'd have to
175 # return either true or false from all the 'try' methods, neither of
176 # which is correct.
177
Greg Ward59ac7092000-06-21 03:00:50 +0000178 # XXX need access to the header search path and maybe default macros.
179
Greg Ward855dab92000-06-27 01:21:22 +0000180 def try_cpp (self, body=None, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000181 """Construct a source file from 'body' (a string containing lines
182 of C/C++ code) and 'headers' (a list of header files to include)
183 and run it through the preprocessor. Return true if the
184 preprocessor succeeded, false if there were any errors.
185 ('body' probably isn't of much use, but what the heck.)
186 """
187 from distutils.ccompiler import CompileError
188 self._check_compiler()
189 ok = 1
190 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000191 self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000192 except CompileError:
193 ok = 0
194
195 self._clean()
196 return ok
197
Greg Ward855dab92000-06-27 01:21:22 +0000198 def search_cpp (self, pattern, body=None,
199 headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000200 """Construct a source file (just like 'try_cpp()'), run it through
201 the preprocessor, and return true if any line of the output matches
202 'pattern'. 'pattern' should either be a compiled regex object or a
203 string containing a regex. If both 'body' and 'headers' are None,
204 preprocesses an empty file -- which can be useful to determine the
205 symbols the preprocessor and compiler set by default.
206 """
207
208 self._check_compiler()
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000209 (src, out) = self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000210
211 if type(pattern) is StringType:
212 pattern = re.compile(pattern)
213
214 file = open(out)
215 match = 0
216 while 1:
217 line = file.readline()
218 if line == '':
219 break
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000220 if pattern.search(line):
Greg Ward59ac7092000-06-21 03:00:50 +0000221 match = 1
222 break
223
224 file.close()
225 self._clean()
226 return match
227
Greg Ward855dab92000-06-27 01:21:22 +0000228 def try_compile (self, body, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000229 """Try to compile a source file built from 'body' and 'headers'.
230 Return true on success, false otherwise.
Greg Ward28a5f442000-06-06 02:57:07 +0000231 """
232 from distutils.ccompiler import CompileError
233 self._check_compiler()
234 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000235 self._compile(body, headers, include_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000236 ok = 1
237 except CompileError:
238 ok = 0
239
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000240 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000241 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000242 return ok
243
Greg Ward855dab92000-06-27 01:21:22 +0000244 def try_link (self, body,
245 headers=None, include_dirs=None,
Greg Ward59ac7092000-06-21 03:00:50 +0000246 libraries=None, library_dirs=None,
247 lang="c"):
248 """Try to compile and link a source file, built from 'body' and
249 'headers', to executable form. Return true on success, false
Greg Ward28a5f442000-06-06 02:57:07 +0000250 otherwise.
251 """
252 from distutils.ccompiler import CompileError, LinkError
253 self._check_compiler()
254 try:
Greg Ward855dab92000-06-27 01:21:22 +0000255 self._link(body, headers, include_dirs,
256 libraries, library_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000257 ok = 1
258 except (CompileError, LinkError):
259 ok = 0
260
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000261 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000262 self._clean()
263 return ok
Fred Drake21d45352001-12-06 21:01:19 +0000264
Greg Ward855dab92000-06-27 01:21:22 +0000265 def try_run (self, body,
266 headers=None, include_dirs=None,
Greg Ward59ac7092000-06-21 03:00:50 +0000267 libraries=None, library_dirs=None,
268 lang="c"):
269 """Try to compile, link to an executable, and run a program
270 built from 'body' and 'headers'. Return true on success, false
271 otherwise.
272 """
273 from distutils.ccompiler import CompileError, LinkError
274 self._check_compiler()
275 try:
Andrew M. Kuchling246c4252001-08-13 13:56:24 +0000276 src, obj, exe = self._link(body, headers, include_dirs,
277 libraries, library_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000278 self.spawn([exe])
279 ok = 1
280 except (CompileError, LinkError, DistutilsExecError):
281 ok = 0
282
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000283 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000284 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000285 return ok
286
Greg Ward59ac7092000-06-21 03:00:50 +0000287
288 # -- High-level methods --------------------------------------------
289 # (these are the ones that are actually likely to be useful
290 # when implementing a real-world config command!)
291
Greg Ward855dab92000-06-27 01:21:22 +0000292 def check_func (self, func,
293 headers=None, include_dirs=None,
Greg Ward59ac7092000-06-21 03:00:50 +0000294 libraries=None, library_dirs=None,
295 decl=0, call=0):
296
297 """Determine if function 'func' is available by constructing a
298 source file that refers to 'func', and compiles and links it.
299 If everything succeeds, returns true; otherwise returns false.
300
301 The constructed source file starts out by including the header
302 files listed in 'headers'. If 'decl' is true, it then declares
303 'func' (as "int func()"); you probably shouldn't supply 'headers'
304 and set 'decl' true in the same call, or you might get errors about
305 a conflicting declarations for 'func'. Finally, the constructed
306 'main()' function either references 'func' or (if 'call' is true)
307 calls it. 'libraries' and 'library_dirs' are used when
308 linking.
309 """
310
311 self._check_compiler()
312 body = []
313 if decl:
314 body.append("int %s ();" % func)
315 body.append("int main () {")
316 if call:
317 body.append(" %s();" % func)
318 else:
319 body.append(" %s;" % func)
320 body.append("}")
321 body = string.join(body, "\n") + "\n"
322
Greg Ward855dab92000-06-27 01:21:22 +0000323 return self.try_link(body, headers, include_dirs,
324 libraries, library_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000325
326 # check_func ()
327
Greg Ward855dab92000-06-27 01:21:22 +0000328 def check_lib (self, library, library_dirs=None,
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000329 headers=None, include_dirs=None, other_libraries=[]):
Greg Ward855dab92000-06-27 01:21:22 +0000330 """Determine if 'library' is available to be linked against,
331 without actually checking that any particular symbols are provided
332 by it. 'headers' will be used in constructing the source file to
333 be compiled, but the only effect of this is to check if all the
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000334 header files listed are available. Any libraries listed in
335 'other_libraries' will be included in the link, in case 'library'
336 has symbols that depend on other libraries.
Greg Ward855dab92000-06-27 01:21:22 +0000337 """
338 self._check_compiler()
339 return self.try_link("int main (void) { }",
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000340 headers, include_dirs,
341 [library]+other_libraries, library_dirs)
Greg Ward855dab92000-06-27 01:21:22 +0000342
343 def check_header (self, header, include_dirs=None,
344 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000345 """Determine if the system header file named by 'header_file'
346 exists and can be found by the preprocessor; return true if so,
347 false otherwise.
348 """
Greg Ward855dab92000-06-27 01:21:22 +0000349 return self.try_cpp(headers=[header], include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000350
351
Greg Ward28a5f442000-06-06 02:57:07 +0000352# class config
Greg Ward59ac7092000-06-21 03:00:50 +0000353
354
355def dump_file (filename, head=None):
356 if head is None:
357 print filename + ":"
358 else:
359 print head
360
361 file = open(filename)
362 sys.stdout.write(file.read())
363 file.close()