blob: b084913563a3e234521a746be24b4fb2b4837c4a [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
Tarek Ziadé2b66da72009-12-21 01:22:46 +000014import os
15import re
Tarek Ziadée643bed2009-04-12 16:45:32 +000016
Greg Ward28a5f442000-06-06 02:57:07 +000017from distutils.core import Command
18from distutils.errors import DistutilsExecError
Ned Deilyc47a4592012-02-11 20:40:24 +010019from distutils.sysconfig import customize_compiler
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000020from distutils import log
Greg Ward28a5f442000-06-06 02:57:07 +000021
Tarek Ziadé7bea3442009-04-12 15:03:50 +000022LANG_EXT = {'c': '.c', 'c++': '.cxx'}
Greg Ward28a5f442000-06-06 02:57:07 +000023
Tarek Ziadé7bea3442009-04-12 15:03:50 +000024class config(Command):
Greg Ward28a5f442000-06-06 02:57:07 +000025
26 description = "prepare to build"
27
28 user_options = [
29 ('compiler=', None,
30 "specify the compiler type"),
31 ('cc=', None,
32 "specify the compiler executable"),
33 ('include-dirs=', 'I',
34 "list of directories to search for header files"),
35 ('define=', 'D',
36 "C preprocessor macros to define"),
37 ('undef=', 'U',
38 "C preprocessor macros to undefine"),
39 ('libraries=', 'l',
40 "external C libraries to link with"),
41 ('library-dirs=', 'L',
42 "directories to search for external C libraries"),
Greg Ward59ac7092000-06-21 03:00:50 +000043
44 ('noisy', None,
45 "show every action (compile, link, run, ...) taken"),
46 ('dump-source', None,
47 "dump generated source files before attempting to compile them"),
Greg Ward28a5f442000-06-06 02:57:07 +000048 ]
49
50
51 # The three standard command methods: since the "config" command
52 # does nothing by default, these are empty.
53
Tarek Ziadé7bea3442009-04-12 15:03:50 +000054 def initialize_options(self):
Greg Ward28a5f442000-06-06 02:57:07 +000055 self.compiler = None
56 self.cc = None
57 self.include_dirs = None
Greg Ward28a5f442000-06-06 02:57:07 +000058 self.libraries = None
59 self.library_dirs = None
60
Greg Ward59ac7092000-06-21 03:00:50 +000061 # maximal output for now
62 self.noisy = 1
63 self.dump_source = 1
64
65 # list of temporary files generated along-the-way that we have
66 # to clean at some point
67 self.temp_files = []
68
Tarek Ziadé7bea3442009-04-12 15:03:50 +000069 def finalize_options(self):
Greg Ward2e38a502000-10-14 03:40:20 +000070 if self.include_dirs is None:
71 self.include_dirs = self.distribution.include_dirs or []
Tarek Ziadée643bed2009-04-12 16:45:32 +000072 elif isinstance(self.include_dirs, str):
73 self.include_dirs = self.include_dirs.split(os.pathsep)
Greg Ward2e38a502000-10-14 03:40:20 +000074
75 if self.libraries is None:
76 self.libraries = []
Tarek Ziadée643bed2009-04-12 16:45:32 +000077 elif isinstance(self.libraries, str):
Greg Ward2e38a502000-10-14 03:40:20 +000078 self.libraries = [self.libraries]
79
80 if self.library_dirs is None:
81 self.library_dirs = []
Tarek Ziadée643bed2009-04-12 16:45:32 +000082 elif isinstance(self.library_dirs, str):
83 self.library_dirs = self.library_dirs.split(os.pathsep)
Greg Ward28a5f442000-06-06 02:57:07 +000084
Tarek Ziadé3295eed2009-04-12 17:02:08 +000085 def run(self):
Greg Ward28a5f442000-06-06 02:57:07 +000086 pass
87
88
89 # Utility methods for actual "config" commands. The interfaces are
90 # loosely based on Autoconf macros of similar names. Sub-classes
91 # may use these freely.
92
Tarek Ziadé7bea3442009-04-12 15:03:50 +000093 def _check_compiler(self):
Greg Ward28a5f442000-06-06 02:57:07 +000094 """Check that 'self.compiler' really is a CCompiler object;
95 if not, make it one.
96 """
97 # We do this late, and only on-demand, because this is an expensive
98 # import.
99 from distutils.ccompiler import CCompiler, new_compiler
100 if not isinstance(self.compiler, CCompiler):
Greg Wardcb1f4c42000-09-30 18:27:54 +0000101 self.compiler = new_compiler(compiler=self.compiler,
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000102 dry_run=self.dry_run, force=1)
Andrew M. Kuchling679bc9f2003-02-18 01:28:51 +0000103 customize_compiler(self.compiler)
Greg Ward28a5f442000-06-06 02:57:07 +0000104 if self.include_dirs:
105 self.compiler.set_include_dirs(self.include_dirs)
106 if self.libraries:
107 self.compiler.set_libraries(self.libraries)
108 if self.library_dirs:
109 self.compiler.set_library_dirs(self.library_dirs)
110
111
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000112 def _gen_temp_sourcefile(self, body, headers, lang):
Greg Ward28a5f442000-06-06 02:57:07 +0000113 filename = "_configtest" + LANG_EXT[lang]
114 file = open(filename, "w")
Greg Ward59ac7092000-06-21 03:00:50 +0000115 if headers:
116 for header in headers:
117 file.write("#include <%s>\n" % header)
118 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000119 file.write(body)
Greg Ward59ac7092000-06-21 03:00:50 +0000120 if body[-1] != "\n":
121 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000122 file.close()
123 return filename
124
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000125 def _preprocess(self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000126 src = self._gen_temp_sourcefile(body, headers, lang)
127 out = "_configtest.i"
128 self.temp_files.extend([src, out])
Greg Ward855dab92000-06-27 01:21:22 +0000129 self.compiler.preprocess(src, out, include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000130 return (src, out)
131
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000132 def _compile(self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000133 src = self._gen_temp_sourcefile(body, headers, lang)
134 if self.dump_source:
135 dump_file(src, "compiling '%s':" % src)
136 (obj,) = self.compiler.object_filenames([src])
137 self.temp_files.extend([src, obj])
Greg Ward855dab92000-06-27 01:21:22 +0000138 self.compiler.compile([src], include_dirs=include_dirs)
Greg Ward28a5f442000-06-06 02:57:07 +0000139 return (src, obj)
140
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000141 def _link(self, body, headers, include_dirs, libraries, library_dirs,
142 lang):
Greg Ward855dab92000-06-27 01:21:22 +0000143 (src, obj) = self._compile(body, headers, include_dirs, lang)
Fred Drake21d45352001-12-06 21:01:19 +0000144 prog = os.path.splitext(os.path.basename(src))[0]
Greg Ward59ac7092000-06-21 03:00:50 +0000145 self.compiler.link_executable([obj], prog,
146 libraries=libraries,
Gustavo Niemeyer6b016852002-11-05 16:12:02 +0000147 library_dirs=library_dirs,
148 target_lang=lang)
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000149
Just van Rossumca3fec72003-02-03 11:43:54 +0000150 if self.compiler.exe_extension is not None:
151 prog = prog + self.compiler.exe_extension
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000152 self.temp_files.append(prog)
153
Greg Ward59ac7092000-06-21 03:00:50 +0000154 return (src, obj, prog)
Greg Ward28a5f442000-06-06 02:57:07 +0000155
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000156 def _clean(self, *filenames):
Greg Ward59ac7092000-06-21 03:00:50 +0000157 if not filenames:
158 filenames = self.temp_files
159 self.temp_files = []
Tarek Ziadé3295eed2009-04-12 17:02:08 +0000160 log.info("removing: %s", ' '.join(filenames))
Greg Ward28a5f442000-06-06 02:57:07 +0000161 for filename in filenames:
162 try:
163 os.remove(filename)
164 except OSError:
165 pass
166
167
Greg Ward28a5f442000-06-06 02:57:07 +0000168 # XXX these ignore the dry-run flag: what to do, what to do? even if
169 # you want a dry-run build, you still need some sort of configuration
170 # info. My inclination is to make it up to the real config command to
171 # consult 'dry_run', and assume a default (minimal) configuration if
172 # true. The problem with trying to do it here is that you'd have to
173 # return either true or false from all the 'try' methods, neither of
174 # which is correct.
175
Greg Ward59ac7092000-06-21 03:00:50 +0000176 # XXX need access to the header search path and maybe default macros.
177
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000178 def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000179 """Construct a source file from 'body' (a string containing lines
180 of C/C++ code) and 'headers' (a list of header files to include)
181 and run it through the preprocessor. Return true if the
182 preprocessor succeeded, false if there were any errors.
183 ('body' probably isn't of much use, but what the heck.)
184 """
185 from distutils.ccompiler import CompileError
186 self._check_compiler()
187 ok = 1
188 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000189 self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000190 except CompileError:
191 ok = 0
192
193 self._clean()
194 return ok
195
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000196 def search_cpp(self, pattern, body=None, headers=None, include_dirs=None,
197 lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000198 """Construct a source file (just like 'try_cpp()'), run it through
199 the preprocessor, and return true if any line of the output matches
200 'pattern'. 'pattern' should either be a compiled regex object or a
201 string containing a regex. If both 'body' and 'headers' are None,
202 preprocesses an empty file -- which can be useful to determine the
203 symbols the preprocessor and compiler set by default.
204 """
Greg Ward59ac7092000-06-21 03:00:50 +0000205 self._check_compiler()
Tarek Ziadéf6f4b302009-04-12 16:31:24 +0000206 src, out = self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000207
Tarek Ziadéf6f4b302009-04-12 16:31:24 +0000208 if isinstance(pattern, str):
Greg Ward59ac7092000-06-21 03:00:50 +0000209 pattern = re.compile(pattern)
210
211 file = open(out)
212 match = 0
213 while 1:
214 line = file.readline()
215 if line == '':
216 break
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000217 if pattern.search(line):
Greg Ward59ac7092000-06-21 03:00:50 +0000218 match = 1
219 break
220
221 file.close()
222 self._clean()
223 return match
224
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000225 def try_compile(self, body, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000226 """Try to compile a source file built from 'body' and 'headers'.
227 Return true on success, false otherwise.
Greg Ward28a5f442000-06-06 02:57:07 +0000228 """
229 from distutils.ccompiler import CompileError
230 self._check_compiler()
231 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000232 self._compile(body, headers, include_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000233 ok = 1
234 except CompileError:
235 ok = 0
236
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000237 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000238 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000239 return ok
240
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000241 def try_link(self, body, headers=None, include_dirs=None, libraries=None,
242 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000243 """Try to compile and link a source file, built from 'body' and
244 'headers', to executable form. Return true on success, false
Greg Ward28a5f442000-06-06 02:57:07 +0000245 otherwise.
246 """
247 from distutils.ccompiler import CompileError, LinkError
248 self._check_compiler()
249 try:
Greg Ward855dab92000-06-27 01:21:22 +0000250 self._link(body, headers, include_dirs,
251 libraries, library_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000252 ok = 1
253 except (CompileError, LinkError):
254 ok = 0
255
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000256 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000257 self._clean()
258 return ok
Fred Drake21d45352001-12-06 21:01:19 +0000259
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000260 def try_run(self, body, headers=None, include_dirs=None, libraries=None,
261 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000262 """Try to compile, link to an executable, and run a program
263 built from 'body' and 'headers'. Return true on success, false
264 otherwise.
265 """
266 from distutils.ccompiler import CompileError, LinkError
267 self._check_compiler()
268 try:
Andrew M. Kuchling246c4252001-08-13 13:56:24 +0000269 src, obj, exe = self._link(body, headers, include_dirs,
270 libraries, library_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000271 self.spawn([exe])
272 ok = 1
273 except (CompileError, LinkError, DistutilsExecError):
274 ok = 0
275
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000276 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000277 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000278 return ok
279
Greg Ward59ac7092000-06-21 03:00:50 +0000280
281 # -- High-level methods --------------------------------------------
282 # (these are the ones that are actually likely to be useful
283 # when implementing a real-world config command!)
284
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000285 def check_func(self, func, headers=None, include_dirs=None,
286 libraries=None, library_dirs=None, decl=0, call=0):
Greg Ward59ac7092000-06-21 03:00:50 +0000287
288 """Determine if function 'func' is available by constructing a
289 source file that refers to 'func', and compiles and links it.
290 If everything succeeds, returns true; otherwise returns false.
291
292 The constructed source file starts out by including the header
293 files listed in 'headers'. If 'decl' is true, it then declares
294 'func' (as "int func()"); you probably shouldn't supply 'headers'
295 and set 'decl' true in the same call, or you might get errors about
296 a conflicting declarations for 'func'. Finally, the constructed
297 'main()' function either references 'func' or (if 'call' is true)
298 calls it. 'libraries' and 'library_dirs' are used when
299 linking.
300 """
301
302 self._check_compiler()
303 body = []
304 if decl:
305 body.append("int %s ();" % func)
306 body.append("int main () {")
307 if call:
308 body.append(" %s();" % func)
309 else:
310 body.append(" %s;" % func)
311 body.append("}")
Tarek Ziadé3295eed2009-04-12 17:02:08 +0000312 body = "\n".join(body) + "\n"
Greg Ward59ac7092000-06-21 03:00:50 +0000313
Greg Ward855dab92000-06-27 01:21:22 +0000314 return self.try_link(body, headers, include_dirs,
315 libraries, library_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000316
317 # check_func ()
318
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000319 def check_lib(self, library, library_dirs=None, headers=None,
320 include_dirs=None, other_libraries=[]):
Greg Ward855dab92000-06-27 01:21:22 +0000321 """Determine if 'library' is available to be linked against,
322 without actually checking that any particular symbols are provided
323 by it. 'headers' will be used in constructing the source file to
324 be compiled, but the only effect of this is to check if all the
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000325 header files listed are available. Any libraries listed in
326 'other_libraries' will be included in the link, in case 'library'
327 has symbols that depend on other libraries.
Greg Ward855dab92000-06-27 01:21:22 +0000328 """
329 self._check_compiler()
330 return self.try_link("int main (void) { }",
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000331 headers, include_dirs,
332 [library]+other_libraries, library_dirs)
Greg Ward855dab92000-06-27 01:21:22 +0000333
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000334 def check_header(self, header, include_dirs=None, library_dirs=None,
335 lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000336 """Determine if the system header file named by 'header_file'
337 exists and can be found by the preprocessor; return true if so,
338 false otherwise.
339 """
Andrew M. Kuchling4013cbd2002-09-09 12:10:00 +0000340 return self.try_cpp(body="/* No body */", headers=[header],
341 include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000342
343
Tarek Ziadéaa487982009-04-12 14:53:51 +0000344def dump_file(filename, head=None):
345 """Dumps a file content into log.info.
Greg Ward59ac7092000-06-21 03:00:50 +0000346
Tarek Ziadéaa487982009-04-12 14:53:51 +0000347 If head is not None, will be dumped before the file content.
348 """
Greg Ward59ac7092000-06-21 03:00:50 +0000349 if head is None:
Tarek Ziadéaa487982009-04-12 14:53:51 +0000350 log.info('%s' % filename)
Greg Ward59ac7092000-06-21 03:00:50 +0000351 else:
Tarek Ziadéaa487982009-04-12 14:53:51 +0000352 log.info(head)
Greg Ward59ac7092000-06-21 03:00:50 +0000353 file = open(filename)
Tarek Ziadéaa487982009-04-12 14:53:51 +0000354 try:
355 log.info(file.read())
356 finally:
357 file.close()