blob: 9ebe0d919138217573bd8250bf6fff86c477a4ec [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,
Gustavo Niemeyer6b016852002-11-05 16:12:02 +0000151 library_dirs=library_dirs,
152 target_lang=lang)
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000153
154 prog = prog + self.compiler.exe_extension
155 self.temp_files.append(prog)
156
Greg Ward59ac7092000-06-21 03:00:50 +0000157 return (src, obj, prog)
Greg Ward28a5f442000-06-06 02:57:07 +0000158
159 def _clean (self, *filenames):
Greg Ward59ac7092000-06-21 03:00:50 +0000160 if not filenames:
161 filenames = self.temp_files
162 self.temp_files = []
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000163 log.info("removing: %s", string.join(filenames))
Greg Ward28a5f442000-06-06 02:57:07 +0000164 for filename in filenames:
165 try:
166 os.remove(filename)
167 except OSError:
168 pass
169
170
Greg Ward28a5f442000-06-06 02:57:07 +0000171 # XXX these ignore the dry-run flag: what to do, what to do? even if
172 # you want a dry-run build, you still need some sort of configuration
173 # info. My inclination is to make it up to the real config command to
174 # consult 'dry_run', and assume a default (minimal) configuration if
175 # true. The problem with trying to do it here is that you'd have to
176 # return either true or false from all the 'try' methods, neither of
177 # which is correct.
178
Greg Ward59ac7092000-06-21 03:00:50 +0000179 # XXX need access to the header search path and maybe default macros.
180
Greg Ward855dab92000-06-27 01:21:22 +0000181 def try_cpp (self, body=None, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000182 """Construct a source file from 'body' (a string containing lines
183 of C/C++ code) and 'headers' (a list of header files to include)
184 and run it through the preprocessor. Return true if the
185 preprocessor succeeded, false if there were any errors.
186 ('body' probably isn't of much use, but what the heck.)
187 """
188 from distutils.ccompiler import CompileError
189 self._check_compiler()
190 ok = 1
191 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000192 self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000193 except CompileError:
194 ok = 0
195
196 self._clean()
197 return ok
198
Greg Ward855dab92000-06-27 01:21:22 +0000199 def search_cpp (self, pattern, body=None,
200 headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000201 """Construct a source file (just like 'try_cpp()'), run it through
202 the preprocessor, and return true if any line of the output matches
203 'pattern'. 'pattern' should either be a compiled regex object or a
204 string containing a regex. If both 'body' and 'headers' are None,
205 preprocesses an empty file -- which can be useful to determine the
206 symbols the preprocessor and compiler set by default.
207 """
208
209 self._check_compiler()
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000210 (src, out) = self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000211
212 if type(pattern) is StringType:
213 pattern = re.compile(pattern)
214
215 file = open(out)
216 match = 0
217 while 1:
218 line = file.readline()
219 if line == '':
220 break
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000221 if pattern.search(line):
Greg Ward59ac7092000-06-21 03:00:50 +0000222 match = 1
223 break
224
225 file.close()
226 self._clean()
227 return match
228
Greg Ward855dab92000-06-27 01:21:22 +0000229 def try_compile (self, body, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000230 """Try to compile a source file built from 'body' and 'headers'.
231 Return true on success, false otherwise.
Greg Ward28a5f442000-06-06 02:57:07 +0000232 """
233 from distutils.ccompiler import CompileError
234 self._check_compiler()
235 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000236 self._compile(body, headers, include_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000237 ok = 1
238 except CompileError:
239 ok = 0
240
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000241 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000242 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000243 return ok
244
Greg Ward855dab92000-06-27 01:21:22 +0000245 def try_link (self, body,
246 headers=None, include_dirs=None,
Greg Ward59ac7092000-06-21 03:00:50 +0000247 libraries=None, library_dirs=None,
248 lang="c"):
249 """Try to compile and link a source file, built from 'body' and
250 'headers', to executable form. Return true on success, false
Greg Ward28a5f442000-06-06 02:57:07 +0000251 otherwise.
252 """
253 from distutils.ccompiler import CompileError, LinkError
254 self._check_compiler()
255 try:
Greg Ward855dab92000-06-27 01:21:22 +0000256 self._link(body, headers, include_dirs,
257 libraries, library_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000258 ok = 1
259 except (CompileError, LinkError):
260 ok = 0
261
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000262 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000263 self._clean()
264 return ok
Fred Drake21d45352001-12-06 21:01:19 +0000265
Greg Ward855dab92000-06-27 01:21:22 +0000266 def try_run (self, body,
267 headers=None, include_dirs=None,
Greg Ward59ac7092000-06-21 03:00:50 +0000268 libraries=None, library_dirs=None,
269 lang="c"):
270 """Try to compile, link to an executable, and run a program
271 built from 'body' and 'headers'. Return true on success, false
272 otherwise.
273 """
274 from distutils.ccompiler import CompileError, LinkError
275 self._check_compiler()
276 try:
Andrew M. Kuchling246c4252001-08-13 13:56:24 +0000277 src, obj, exe = self._link(body, headers, include_dirs,
278 libraries, library_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000279 self.spawn([exe])
280 ok = 1
281 except (CompileError, LinkError, DistutilsExecError):
282 ok = 0
283
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000284 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000285 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000286 return ok
287
Greg Ward59ac7092000-06-21 03:00:50 +0000288
289 # -- High-level methods --------------------------------------------
290 # (these are the ones that are actually likely to be useful
291 # when implementing a real-world config command!)
292
Greg Ward855dab92000-06-27 01:21:22 +0000293 def check_func (self, func,
294 headers=None, include_dirs=None,
Greg Ward59ac7092000-06-21 03:00:50 +0000295 libraries=None, library_dirs=None,
296 decl=0, call=0):
297
298 """Determine if function 'func' is available by constructing a
299 source file that refers to 'func', and compiles and links it.
300 If everything succeeds, returns true; otherwise returns false.
301
302 The constructed source file starts out by including the header
303 files listed in 'headers'. If 'decl' is true, it then declares
304 'func' (as "int func()"); you probably shouldn't supply 'headers'
305 and set 'decl' true in the same call, or you might get errors about
306 a conflicting declarations for 'func'. Finally, the constructed
307 'main()' function either references 'func' or (if 'call' is true)
308 calls it. 'libraries' and 'library_dirs' are used when
309 linking.
310 """
311
312 self._check_compiler()
313 body = []
314 if decl:
315 body.append("int %s ();" % func)
316 body.append("int main () {")
317 if call:
318 body.append(" %s();" % func)
319 else:
320 body.append(" %s;" % func)
321 body.append("}")
322 body = string.join(body, "\n") + "\n"
323
Greg Ward855dab92000-06-27 01:21:22 +0000324 return self.try_link(body, headers, include_dirs,
325 libraries, library_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000326
327 # check_func ()
328
Greg Ward855dab92000-06-27 01:21:22 +0000329 def check_lib (self, library, library_dirs=None,
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000330 headers=None, include_dirs=None, other_libraries=[]):
Greg Ward855dab92000-06-27 01:21:22 +0000331 """Determine if 'library' is available to be linked against,
332 without actually checking that any particular symbols are provided
333 by it. 'headers' will be used in constructing the source file to
334 be compiled, but the only effect of this is to check if all the
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000335 header files listed are available. Any libraries listed in
336 'other_libraries' will be included in the link, in case 'library'
337 has symbols that depend on other libraries.
Greg Ward855dab92000-06-27 01:21:22 +0000338 """
339 self._check_compiler()
340 return self.try_link("int main (void) { }",
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000341 headers, include_dirs,
342 [library]+other_libraries, library_dirs)
Greg Ward855dab92000-06-27 01:21:22 +0000343
344 def check_header (self, header, include_dirs=None,
345 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000346 """Determine if the system header file named by 'header_file'
347 exists and can be found by the preprocessor; return true if so,
348 false otherwise.
349 """
Andrew M. Kuchling4013cbd2002-09-09 12:10:00 +0000350 return self.try_cpp(body="/* No body */", headers=[header],
351 include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000352
353
Greg Ward28a5f442000-06-06 02:57:07 +0000354# class config
Greg Ward59ac7092000-06-21 03:00:50 +0000355
356
357def dump_file (filename, head=None):
358 if head is None:
359 print filename + ":"
360 else:
361 print head
362
363 file = open(filename)
364 sys.stdout.write(file.read())
365 file.close()