blob: c31220553ce9758f6588b93d9afd927e5994aca6 [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 """
Greg Ward59ac7092000-06-21 03:00:50 +0000201 self._check_compiler()
Tarek Ziadéfd39b7a2009-04-12 16:34:34 +0000202 src, out = self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000203
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000204 if isinstance(pattern, str):
Greg Ward59ac7092000-06-21 03:00:50 +0000205 pattern = re.compile(pattern)
206
207 file = open(out)
Collin Winter5b7e9d72007-08-30 03:52:21 +0000208 match = False
209 while True:
Greg Ward59ac7092000-06-21 03:00:50 +0000210 line = file.readline()
211 if line == '':
212 break
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000213 if pattern.search(line):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000214 match = True
Greg Ward59ac7092000-06-21 03:00:50 +0000215 break
216
217 file.close()
218 self._clean()
219 return match
220
Collin Winter5b7e9d72007-08-30 03:52:21 +0000221 def try_compile(self, body, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000222 """Try to compile a source file built from 'body' and 'headers'.
223 Return true on success, false otherwise.
Greg Ward28a5f442000-06-06 02:57:07 +0000224 """
225 from distutils.ccompiler import CompileError
226 self._check_compiler()
227 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000228 self._compile(body, headers, include_dirs, lang)
Collin Winter5b7e9d72007-08-30 03:52:21 +0000229 ok = True
Greg Ward28a5f442000-06-06 02:57:07 +0000230 except CompileError:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000231 ok = False
Greg Ward28a5f442000-06-06 02:57:07 +0000232
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000233 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000234 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000235 return ok
236
Tarek Ziadé9d254892009-04-12 15:07:31 +0000237 def try_link(self, body, headers=None, include_dirs=None, libraries=None,
238 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000239 """Try to compile and link a source file, built from 'body' and
240 'headers', to executable form. Return true on success, false
Greg Ward28a5f442000-06-06 02:57:07 +0000241 otherwise.
242 """
243 from distutils.ccompiler import CompileError, LinkError
244 self._check_compiler()
245 try:
Greg Ward855dab92000-06-27 01:21:22 +0000246 self._link(body, headers, include_dirs,
247 libraries, library_dirs, lang)
Collin Winter5b7e9d72007-08-30 03:52:21 +0000248 ok = True
Greg Ward59ac7092000-06-21 03:00:50 +0000249 except (CompileError, LinkError):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000250 ok = False
Greg Ward59ac7092000-06-21 03:00:50 +0000251
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000252 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000253 self._clean()
254 return ok
Fred Drake21d45352001-12-06 21:01:19 +0000255
Tarek Ziadé9d254892009-04-12 15:07:31 +0000256 def try_run(self, body, headers=None, include_dirs=None, libraries=None,
257 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000258 """Try to compile, link to an executable, and run a program
259 built from 'body' and 'headers'. Return true on success, false
260 otherwise.
261 """
262 from distutils.ccompiler import CompileError, LinkError
263 self._check_compiler()
264 try:
Andrew M. Kuchling246c4252001-08-13 13:56:24 +0000265 src, obj, exe = self._link(body, headers, include_dirs,
266 libraries, library_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000267 self.spawn([exe])
Collin Winter5b7e9d72007-08-30 03:52:21 +0000268 ok = True
Greg Ward28a5f442000-06-06 02:57:07 +0000269 except (CompileError, LinkError, DistutilsExecError):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000270 ok = False
Greg Ward28a5f442000-06-06 02:57:07 +0000271
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000272 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000273 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000274 return ok
275
Greg Ward59ac7092000-06-21 03:00:50 +0000276
277 # -- High-level methods --------------------------------------------
278 # (these are the ones that are actually likely to be useful
279 # when implementing a real-world config command!)
280
Collin Winter5b7e9d72007-08-30 03:52:21 +0000281 def check_func(self, func, headers=None, include_dirs=None,
282 libraries=None, library_dirs=None, decl=0, call=0):
Greg Ward59ac7092000-06-21 03:00:50 +0000283 """Determine if function 'func' is available by constructing a
284 source file that refers to 'func', and compiles and links it.
285 If everything succeeds, returns true; otherwise returns false.
286
287 The constructed source file starts out by including the header
288 files listed in 'headers'. If 'decl' is true, it then declares
289 'func' (as "int func()"); you probably shouldn't supply 'headers'
290 and set 'decl' true in the same call, or you might get errors about
291 a conflicting declarations for 'func'. Finally, the constructed
292 'main()' function either references 'func' or (if 'call' is true)
293 calls it. 'libraries' and 'library_dirs' are used when
294 linking.
295 """
Greg Ward59ac7092000-06-21 03:00:50 +0000296 self._check_compiler()
297 body = []
298 if decl:
299 body.append("int %s ();" % func)
300 body.append("int main () {")
301 if call:
302 body.append(" %s();" % func)
303 else:
304 body.append(" %s;" % func)
305 body.append("}")
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000306 body = "\n".join(body) + "\n"
Greg Ward59ac7092000-06-21 03:00:50 +0000307
Greg Ward855dab92000-06-27 01:21:22 +0000308 return self.try_link(body, headers, include_dirs,
309 libraries, library_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000310
Collin Winter5b7e9d72007-08-30 03:52:21 +0000311 def check_lib(self, library, library_dirs=None, headers=None,
312 include_dirs=None, other_libraries=[]):
Greg Ward855dab92000-06-27 01:21:22 +0000313 """Determine if 'library' is available to be linked against,
314 without actually checking that any particular symbols are provided
315 by it. 'headers' will be used in constructing the source file to
316 be compiled, but the only effect of this is to check if all the
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000317 header files listed are available. Any libraries listed in
318 'other_libraries' will be included in the link, in case 'library'
319 has symbols that depend on other libraries.
Greg Ward855dab92000-06-27 01:21:22 +0000320 """
321 self._check_compiler()
Collin Winter5b7e9d72007-08-30 03:52:21 +0000322 return self.try_link("int main (void) { }", headers, include_dirs,
323 [library] + other_libraries, library_dirs)
Greg Ward855dab92000-06-27 01:21:22 +0000324
Collin Winter5b7e9d72007-08-30 03:52:21 +0000325 def check_header(self, header, include_dirs=None, library_dirs=None,
326 lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000327 """Determine if the system header file named by 'header_file'
328 exists and can be found by the preprocessor; return true if so,
329 false otherwise.
330 """
Andrew M. Kuchling4013cbd2002-09-09 12:10:00 +0000331 return self.try_cpp(body="/* No body */", headers=[header],
332 include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000333
334
Collin Winter5b7e9d72007-08-30 03:52:21 +0000335def dump_file(filename, head=None):
Tarek Ziadé0eb13042009-04-12 14:57:46 +0000336 """Dumps a file content into log.info.
Greg Ward59ac7092000-06-21 03:00:50 +0000337
Tarek Ziadé0eb13042009-04-12 14:57:46 +0000338 If head is not None, will be dumped before the file content.
339 """
340 if head is None:
341 log.info('%s' % filename)
342 else:
343 log.info(head)
Greg Ward59ac7092000-06-21 03:00:50 +0000344 file = open(filename)
Tarek Ziadé0eb13042009-04-12 14:57:46 +0000345 try:
346 log.info(file.read())
347 finally:
348 file.close()