blob: 385a47a72603823d99aa4af28c50d45778e8d5ad [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
Greg Ward28a5f442000-06-06 02:57:07 +000012__revision__ = "$Id$"
13
Neal Norwitz9d72bb42007-04-17 08:48:32 +000014import sys, os, re
Greg Ward28a5f442000-06-06 02:57:07 +000015from distutils.core import Command
16from distutils.errors import DistutilsExecError
Andrew M. Kuchling679bc9f2003-02-18 01:28:51 +000017from distutils.sysconfig import customize_compiler
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000018from distutils import log
Greg Ward28a5f442000-06-06 02:57:07 +000019
Collin Winter5b7e9d72007-08-30 03:52:21 +000020LANG_EXT = {"c": ".c", "c++": ".cxx"}
Greg Ward28a5f442000-06-06 02:57:07 +000021
Collin Winter5b7e9d72007-08-30 03:52:21 +000022class config(Command):
Greg Ward28a5f442000-06-06 02:57:07 +000023
24 description = "prepare to build"
25
26 user_options = [
27 ('compiler=', None,
28 "specify the compiler type"),
29 ('cc=', None,
30 "specify the compiler executable"),
31 ('include-dirs=', 'I',
32 "list of directories to search for header files"),
33 ('define=', 'D',
34 "C preprocessor macros to define"),
35 ('undef=', 'U',
36 "C preprocessor macros to undefine"),
37 ('libraries=', 'l',
38 "external C libraries to link with"),
39 ('library-dirs=', 'L',
40 "directories to search for external C libraries"),
Greg Ward59ac7092000-06-21 03:00:50 +000041
42 ('noisy', None,
43 "show every action (compile, link, run, ...) taken"),
44 ('dump-source', None,
45 "dump generated source files before attempting to compile them"),
Greg Ward28a5f442000-06-06 02:57:07 +000046 ]
47
48
49 # The three standard command methods: since the "config" command
50 # does nothing by default, these are empty.
51
Collin Winter5b7e9d72007-08-30 03:52:21 +000052 def initialize_options(self):
Greg Ward28a5f442000-06-06 02:57:07 +000053 self.compiler = None
54 self.cc = None
55 self.include_dirs = None
Greg Ward28a5f442000-06-06 02:57:07 +000056 self.libraries = None
57 self.library_dirs = None
58
Greg Ward59ac7092000-06-21 03:00:50 +000059 # maximal output for now
60 self.noisy = 1
61 self.dump_source = 1
62
63 # list of temporary files generated along-the-way that we have
64 # to clean at some point
65 self.temp_files = []
66
Collin Winter5b7e9d72007-08-30 03:52:21 +000067 def finalize_options(self):
Greg Ward2e38a502000-10-14 03:40:20 +000068 if self.include_dirs is None:
69 self.include_dirs = self.distribution.include_dirs or []
Guido van Rossum3172c5d2007-10-16 18:12:55 +000070 elif isinstance(self.include_dirs, str):
Neal Norwitz9d72bb42007-04-17 08:48:32 +000071 self.include_dirs = self.include_dirs.split(os.pathsep)
Greg Ward2e38a502000-10-14 03:40:20 +000072
73 if self.libraries is None:
74 self.libraries = []
Guido van Rossum3172c5d2007-10-16 18:12:55 +000075 elif isinstance(self.libraries, str):
Greg Ward2e38a502000-10-14 03:40:20 +000076 self.libraries = [self.libraries]
77
78 if self.library_dirs is None:
79 self.library_dirs = []
Guido van Rossum3172c5d2007-10-16 18:12:55 +000080 elif isinstance(self.library_dirs, str):
Neal Norwitz9d72bb42007-04-17 08:48:32 +000081 self.library_dirs = self.library_dirs.split(os.pathsep)
Greg Ward2e38a502000-10-14 03:40:20 +000082
Collin Winter5b7e9d72007-08-30 03:52:21 +000083 def run(self):
Greg Ward28a5f442000-06-06 02:57:07 +000084 pass
85
Greg Ward28a5f442000-06-06 02:57:07 +000086 # Utility methods for actual "config" commands. The interfaces are
87 # loosely based on Autoconf macros of similar names. Sub-classes
88 # may use these freely.
89
Collin Winter5b7e9d72007-08-30 03:52:21 +000090 def _check_compiler(self):
Greg Ward28a5f442000-06-06 02:57:07 +000091 """Check that 'self.compiler' really is a CCompiler object;
92 if not, make it one.
93 """
94 # We do this late, and only on-demand, because this is an expensive
95 # import.
96 from distutils.ccompiler import CCompiler, new_compiler
97 if not isinstance(self.compiler, CCompiler):
Greg Wardcb1f4c42000-09-30 18:27:54 +000098 self.compiler = new_compiler(compiler=self.compiler,
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000099 dry_run=self.dry_run, force=1)
Andrew M. Kuchling679bc9f2003-02-18 01:28:51 +0000100 customize_compiler(self.compiler)
Greg Ward28a5f442000-06-06 02:57:07 +0000101 if self.include_dirs:
102 self.compiler.set_include_dirs(self.include_dirs)
103 if self.libraries:
104 self.compiler.set_libraries(self.libraries)
105 if self.library_dirs:
106 self.compiler.set_library_dirs(self.library_dirs)
107
Collin Winter5b7e9d72007-08-30 03:52:21 +0000108 def _gen_temp_sourcefile(self, body, headers, lang):
Greg Ward28a5f442000-06-06 02:57:07 +0000109 filename = "_configtest" + LANG_EXT[lang]
110 file = open(filename, "w")
Greg Ward59ac7092000-06-21 03:00:50 +0000111 if headers:
112 for header in headers:
113 file.write("#include <%s>\n" % header)
114 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000115 file.write(body)
Greg Ward59ac7092000-06-21 03:00:50 +0000116 if body[-1] != "\n":
117 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000118 file.close()
119 return filename
120
Collin Winter5b7e9d72007-08-30 03:52:21 +0000121 def _preprocess(self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000122 src = self._gen_temp_sourcefile(body, headers, lang)
123 out = "_configtest.i"
124 self.temp_files.extend([src, out])
Greg Ward855dab92000-06-27 01:21:22 +0000125 self.compiler.preprocess(src, out, include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000126 return (src, out)
127
Collin Winter5b7e9d72007-08-30 03:52:21 +0000128 def _compile(self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000129 src = self._gen_temp_sourcefile(body, headers, lang)
130 if self.dump_source:
131 dump_file(src, "compiling '%s':" % src)
132 (obj,) = self.compiler.object_filenames([src])
133 self.temp_files.extend([src, obj])
Greg Ward855dab92000-06-27 01:21:22 +0000134 self.compiler.compile([src], include_dirs=include_dirs)
Greg Ward28a5f442000-06-06 02:57:07 +0000135 return (src, obj)
136
Tarek Ziadé9d254892009-04-12 15:07:31 +0000137 def _link(self, body, headers, include_dirs, libraries, library_dirs,
138 lang):
Greg Ward855dab92000-06-27 01:21:22 +0000139 (src, obj) = self._compile(body, headers, include_dirs, lang)
Fred Drake21d45352001-12-06 21:01:19 +0000140 prog = os.path.splitext(os.path.basename(src))[0]
Greg Ward59ac7092000-06-21 03:00:50 +0000141 self.compiler.link_executable([obj], prog,
142 libraries=libraries,
Gustavo Niemeyer6b016852002-11-05 16:12:02 +0000143 library_dirs=library_dirs,
144 target_lang=lang)
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000145
Just van Rossumca3fec72003-02-03 11:43:54 +0000146 if self.compiler.exe_extension is not None:
147 prog = prog + self.compiler.exe_extension
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000148 self.temp_files.append(prog)
149
Greg Ward59ac7092000-06-21 03:00:50 +0000150 return (src, obj, prog)
Greg Ward28a5f442000-06-06 02:57:07 +0000151
Collin Winter5b7e9d72007-08-30 03:52:21 +0000152 def _clean(self, *filenames):
Greg Ward59ac7092000-06-21 03:00:50 +0000153 if not filenames:
154 filenames = self.temp_files
155 self.temp_files = []
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000156 log.info("removing: %s", ' '.join(filenames))
Greg Ward28a5f442000-06-06 02:57:07 +0000157 for filename in filenames:
158 try:
159 os.remove(filename)
160 except OSError:
161 pass
162
163
Greg Ward28a5f442000-06-06 02:57:07 +0000164 # XXX these ignore the dry-run flag: what to do, what to do? even if
165 # you want a dry-run build, you still need some sort of configuration
166 # info. My inclination is to make it up to the real config command to
167 # consult 'dry_run', and assume a default (minimal) configuration if
168 # true. The problem with trying to do it here is that you'd have to
169 # return either true or false from all the 'try' methods, neither of
170 # which is correct.
171
Greg Ward59ac7092000-06-21 03:00:50 +0000172 # XXX need access to the header search path and maybe default macros.
173
Collin Winter5b7e9d72007-08-30 03:52:21 +0000174 def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000175 """Construct a source file from 'body' (a string containing lines
176 of C/C++ code) and 'headers' (a list of header files to include)
177 and run it through the preprocessor. Return true if the
178 preprocessor succeeded, false if there were any errors.
179 ('body' probably isn't of much use, but what the heck.)
180 """
181 from distutils.ccompiler import CompileError
182 self._check_compiler()
Collin Winter5b7e9d72007-08-30 03:52:21 +0000183 ok = True
Greg Ward59ac7092000-06-21 03:00:50 +0000184 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000185 self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000186 except CompileError:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000187 ok = False
Greg Ward59ac7092000-06-21 03:00:50 +0000188
189 self._clean()
190 return ok
191
Tarek Ziadé9d254892009-04-12 15:07:31 +0000192 def search_cpp(self, pattern, body=None, headers=None, include_dirs=None,
193 lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000194 """Construct a source file (just like 'try_cpp()'), run it through
195 the preprocessor, and return true if any line of the output matches
196 'pattern'. 'pattern' should either be a compiled regex object or a
197 string containing a regex. If both 'body' and 'headers' are None,
198 preprocesses an empty file -- which can be useful to determine the
199 symbols the preprocessor and compiler set by default.
200 """
201
202 self._check_compiler()
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000203 (src, out) = self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000204
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000205 if isinstance(pattern, str):
Greg Ward59ac7092000-06-21 03:00:50 +0000206 pattern = re.compile(pattern)
207
208 file = open(out)
Collin Winter5b7e9d72007-08-30 03:52:21 +0000209 match = False
210 while True:
Greg Ward59ac7092000-06-21 03:00:50 +0000211 line = file.readline()
212 if line == '':
213 break
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000214 if pattern.search(line):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000215 match = True
Greg Ward59ac7092000-06-21 03:00:50 +0000216 break
217
218 file.close()
219 self._clean()
220 return match
221
Collin Winter5b7e9d72007-08-30 03:52:21 +0000222 def try_compile(self, body, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000223 """Try to compile a source file built from 'body' and 'headers'.
224 Return true on success, false otherwise.
Greg Ward28a5f442000-06-06 02:57:07 +0000225 """
226 from distutils.ccompiler import CompileError
227 self._check_compiler()
228 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000229 self._compile(body, headers, include_dirs, lang)
Collin Winter5b7e9d72007-08-30 03:52:21 +0000230 ok = True
Greg Ward28a5f442000-06-06 02:57:07 +0000231 except CompileError:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000232 ok = False
Greg Ward28a5f442000-06-06 02:57:07 +0000233
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000234 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000235 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000236 return ok
237
Tarek Ziadé9d254892009-04-12 15:07:31 +0000238 def try_link(self, body, headers=None, include_dirs=None, libraries=None,
239 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000240 """Try to compile and link a source file, built from 'body' and
241 'headers', to executable form. Return true on success, false
Greg Ward28a5f442000-06-06 02:57:07 +0000242 otherwise.
243 """
244 from distutils.ccompiler import CompileError, LinkError
245 self._check_compiler()
246 try:
Greg Ward855dab92000-06-27 01:21:22 +0000247 self._link(body, headers, include_dirs,
248 libraries, library_dirs, lang)
Collin Winter5b7e9d72007-08-30 03:52:21 +0000249 ok = True
Greg Ward59ac7092000-06-21 03:00:50 +0000250 except (CompileError, LinkError):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000251 ok = False
Greg Ward59ac7092000-06-21 03:00:50 +0000252
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000253 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000254 self._clean()
255 return ok
Fred Drake21d45352001-12-06 21:01:19 +0000256
Tarek Ziadé9d254892009-04-12 15:07:31 +0000257 def try_run(self, body, headers=None, include_dirs=None, libraries=None,
258 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000259 """Try to compile, link to an executable, and run a program
260 built from 'body' and 'headers'. Return true on success, false
261 otherwise.
262 """
263 from distutils.ccompiler import CompileError, LinkError
264 self._check_compiler()
265 try:
Andrew M. Kuchling246c4252001-08-13 13:56:24 +0000266 src, obj, exe = self._link(body, headers, include_dirs,
267 libraries, library_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000268 self.spawn([exe])
Collin Winter5b7e9d72007-08-30 03:52:21 +0000269 ok = True
Greg Ward28a5f442000-06-06 02:57:07 +0000270 except (CompileError, LinkError, DistutilsExecError):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000271 ok = False
Greg Ward28a5f442000-06-06 02:57:07 +0000272
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000273 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000274 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000275 return ok
276
Greg Ward59ac7092000-06-21 03:00:50 +0000277
278 # -- High-level methods --------------------------------------------
279 # (these are the ones that are actually likely to be useful
280 # when implementing a real-world config command!)
281
Collin Winter5b7e9d72007-08-30 03:52:21 +0000282 def check_func(self, func, headers=None, include_dirs=None,
283 libraries=None, library_dirs=None, decl=0, call=0):
Greg Ward59ac7092000-06-21 03:00:50 +0000284 """Determine if function 'func' is available by constructing a
285 source file that refers to 'func', and compiles and links it.
286 If everything succeeds, returns true; otherwise returns false.
287
288 The constructed source file starts out by including the header
289 files listed in 'headers'. If 'decl' is true, it then declares
290 'func' (as "int func()"); you probably shouldn't supply 'headers'
291 and set 'decl' true in the same call, or you might get errors about
292 a conflicting declarations for 'func'. Finally, the constructed
293 'main()' function either references 'func' or (if 'call' is true)
294 calls it. 'libraries' and 'library_dirs' are used when
295 linking.
296 """
Greg Ward59ac7092000-06-21 03:00:50 +0000297 self._check_compiler()
298 body = []
299 if decl:
300 body.append("int %s ();" % func)
301 body.append("int main () {")
302 if call:
303 body.append(" %s();" % func)
304 else:
305 body.append(" %s;" % func)
306 body.append("}")
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000307 body = "\n".join(body) + "\n"
Greg Ward59ac7092000-06-21 03:00:50 +0000308
Greg Ward855dab92000-06-27 01:21:22 +0000309 return self.try_link(body, headers, include_dirs,
310 libraries, library_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000311
Collin Winter5b7e9d72007-08-30 03:52:21 +0000312 def check_lib(self, library, library_dirs=None, headers=None,
313 include_dirs=None, other_libraries=[]):
Greg Ward855dab92000-06-27 01:21:22 +0000314 """Determine if 'library' is available to be linked against,
315 without actually checking that any particular symbols are provided
316 by it. 'headers' will be used in constructing the source file to
317 be compiled, but the only effect of this is to check if all the
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000318 header files listed are available. Any libraries listed in
319 'other_libraries' will be included in the link, in case 'library'
320 has symbols that depend on other libraries.
Greg Ward855dab92000-06-27 01:21:22 +0000321 """
322 self._check_compiler()
Collin Winter5b7e9d72007-08-30 03:52:21 +0000323 return self.try_link("int main (void) { }", headers, include_dirs,
324 [library] + other_libraries, library_dirs)
Greg Ward855dab92000-06-27 01:21:22 +0000325
Collin Winter5b7e9d72007-08-30 03:52:21 +0000326 def check_header(self, header, include_dirs=None, library_dirs=None,
327 lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000328 """Determine if the system header file named by 'header_file'
329 exists and can be found by the preprocessor; return true if so,
330 false otherwise.
331 """
Andrew M. Kuchling4013cbd2002-09-09 12:10:00 +0000332 return self.try_cpp(body="/* No body */", headers=[header],
333 include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000334
335
Collin Winter5b7e9d72007-08-30 03:52:21 +0000336def dump_file(filename, head=None):
Tarek Ziadé0eb13042009-04-12 14:57:46 +0000337 """Dumps a file content into log.info.
Greg Ward59ac7092000-06-21 03:00:50 +0000338
Tarek Ziadé0eb13042009-04-12 14:57:46 +0000339 If head is not None, will be dumped before the file content.
340 """
341 if head is None:
342 log.info('%s' % filename)
343 else:
344 log.info(head)
Greg Ward59ac7092000-06-21 03:00:50 +0000345 file = open(filename)
Tarek Ziadé0eb13042009-04-12 14:57:46 +0000346 try:
347 log.info(file.read())
348 finally:
349 file.close()