blob: 134fa3892dd57fa2d519f6b0b8d20927144afa2c [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é3295eed2009-04-12 17:02:08 +000014import sys, os, re
Tarek Ziadée643bed2009-04-12 16:45:32 +000015
Greg Ward28a5f442000-06-06 02:57:07 +000016from distutils.core import Command
17from distutils.errors import DistutilsExecError
Andrew M. Kuchling679bc9f2003-02-18 01:28:51 +000018from distutils.sysconfig import customize_compiler
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +000019from distutils import log
Greg Ward28a5f442000-06-06 02:57:07 +000020
Tarek Ziadé7bea3442009-04-12 15:03:50 +000021LANG_EXT = {'c': '.c', 'c++': '.cxx'}
Greg Ward28a5f442000-06-06 02:57:07 +000022
Tarek Ziadé7bea3442009-04-12 15:03:50 +000023class config(Command):
Greg Ward28a5f442000-06-06 02:57:07 +000024
25 description = "prepare to build"
26
27 user_options = [
28 ('compiler=', None,
29 "specify the compiler type"),
30 ('cc=', None,
31 "specify the compiler executable"),
32 ('include-dirs=', 'I',
33 "list of directories to search for header files"),
34 ('define=', 'D',
35 "C preprocessor macros to define"),
36 ('undef=', 'U',
37 "C preprocessor macros to undefine"),
38 ('libraries=', 'l',
39 "external C libraries to link with"),
40 ('library-dirs=', 'L',
41 "directories to search for external C libraries"),
Greg Ward59ac7092000-06-21 03:00:50 +000042
43 ('noisy', None,
44 "show every action (compile, link, run, ...) taken"),
45 ('dump-source', None,
46 "dump generated source files before attempting to compile them"),
Greg Ward28a5f442000-06-06 02:57:07 +000047 ]
48
49
50 # The three standard command methods: since the "config" command
51 # does nothing by default, these are empty.
52
Tarek Ziadé7bea3442009-04-12 15:03:50 +000053 def initialize_options(self):
Greg Ward28a5f442000-06-06 02:57:07 +000054 self.compiler = None
55 self.cc = None
56 self.include_dirs = None
Greg Ward28a5f442000-06-06 02:57:07 +000057 self.libraries = None
58 self.library_dirs = None
59
Greg Ward59ac7092000-06-21 03:00:50 +000060 # maximal output for now
61 self.noisy = 1
62 self.dump_source = 1
63
64 # list of temporary files generated along-the-way that we have
65 # to clean at some point
66 self.temp_files = []
67
Tarek Ziadé7bea3442009-04-12 15:03:50 +000068 def finalize_options(self):
Greg Ward2e38a502000-10-14 03:40:20 +000069 if self.include_dirs is None:
70 self.include_dirs = self.distribution.include_dirs or []
Tarek Ziadée643bed2009-04-12 16:45:32 +000071 elif isinstance(self.include_dirs, str):
72 self.include_dirs = self.include_dirs.split(os.pathsep)
Greg Ward2e38a502000-10-14 03:40:20 +000073
74 if self.libraries is None:
75 self.libraries = []
Tarek Ziadée643bed2009-04-12 16:45:32 +000076 elif isinstance(self.libraries, str):
Greg Ward2e38a502000-10-14 03:40:20 +000077 self.libraries = [self.libraries]
78
79 if self.library_dirs is None:
80 self.library_dirs = []
Tarek Ziadée643bed2009-04-12 16:45:32 +000081 elif isinstance(self.library_dirs, str):
82 self.library_dirs = self.library_dirs.split(os.pathsep)
Greg Ward28a5f442000-06-06 02:57:07 +000083
Tarek Ziadé3295eed2009-04-12 17:02:08 +000084 def run(self):
Greg Ward28a5f442000-06-06 02:57:07 +000085 pass
86
87
88 # Utility methods for actual "config" commands. The interfaces are
89 # loosely based on Autoconf macros of similar names. Sub-classes
90 # may use these freely.
91
Tarek Ziadé7bea3442009-04-12 15:03:50 +000092 def _check_compiler(self):
Greg Ward28a5f442000-06-06 02:57:07 +000093 """Check that 'self.compiler' really is a CCompiler object;
94 if not, make it one.
95 """
96 # We do this late, and only on-demand, because this is an expensive
97 # import.
98 from distutils.ccompiler import CCompiler, new_compiler
99 if not isinstance(self.compiler, CCompiler):
Greg Wardcb1f4c42000-09-30 18:27:54 +0000100 self.compiler = new_compiler(compiler=self.compiler,
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000101 dry_run=self.dry_run, force=1)
Andrew M. Kuchling679bc9f2003-02-18 01:28:51 +0000102 customize_compiler(self.compiler)
Greg Ward28a5f442000-06-06 02:57:07 +0000103 if self.include_dirs:
104 self.compiler.set_include_dirs(self.include_dirs)
105 if self.libraries:
106 self.compiler.set_libraries(self.libraries)
107 if self.library_dirs:
108 self.compiler.set_library_dirs(self.library_dirs)
109
110
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000111 def _gen_temp_sourcefile(self, body, headers, lang):
Greg Ward28a5f442000-06-06 02:57:07 +0000112 filename = "_configtest" + LANG_EXT[lang]
113 file = open(filename, "w")
Greg Ward59ac7092000-06-21 03:00:50 +0000114 if headers:
115 for header in headers:
116 file.write("#include <%s>\n" % header)
117 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000118 file.write(body)
Greg Ward59ac7092000-06-21 03:00:50 +0000119 if body[-1] != "\n":
120 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000121 file.close()
122 return filename
123
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000124 def _preprocess(self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000125 src = self._gen_temp_sourcefile(body, headers, lang)
126 out = "_configtest.i"
127 self.temp_files.extend([src, out])
Greg Ward855dab92000-06-27 01:21:22 +0000128 self.compiler.preprocess(src, out, include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000129 return (src, out)
130
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000131 def _compile(self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000132 src = self._gen_temp_sourcefile(body, headers, lang)
133 if self.dump_source:
134 dump_file(src, "compiling '%s':" % src)
135 (obj,) = self.compiler.object_filenames([src])
136 self.temp_files.extend([src, obj])
Greg Ward855dab92000-06-27 01:21:22 +0000137 self.compiler.compile([src], include_dirs=include_dirs)
Greg Ward28a5f442000-06-06 02:57:07 +0000138 return (src, obj)
139
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000140 def _link(self, body, headers, include_dirs, libraries, library_dirs,
141 lang):
Greg Ward855dab92000-06-27 01:21:22 +0000142 (src, obj) = self._compile(body, headers, include_dirs, lang)
Fred Drake21d45352001-12-06 21:01:19 +0000143 prog = os.path.splitext(os.path.basename(src))[0]
Greg Ward59ac7092000-06-21 03:00:50 +0000144 self.compiler.link_executable([obj], prog,
145 libraries=libraries,
Gustavo Niemeyer6b016852002-11-05 16:12:02 +0000146 library_dirs=library_dirs,
147 target_lang=lang)
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000148
Just van Rossumca3fec72003-02-03 11:43:54 +0000149 if self.compiler.exe_extension is not None:
150 prog = prog + self.compiler.exe_extension
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000151 self.temp_files.append(prog)
152
Greg Ward59ac7092000-06-21 03:00:50 +0000153 return (src, obj, prog)
Greg Ward28a5f442000-06-06 02:57:07 +0000154
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000155 def _clean(self, *filenames):
Greg Ward59ac7092000-06-21 03:00:50 +0000156 if not filenames:
157 filenames = self.temp_files
158 self.temp_files = []
Tarek Ziadé3295eed2009-04-12 17:02:08 +0000159 log.info("removing: %s", ' '.join(filenames))
Greg Ward28a5f442000-06-06 02:57:07 +0000160 for filename in filenames:
161 try:
162 os.remove(filename)
163 except OSError:
164 pass
165
166
Greg Ward28a5f442000-06-06 02:57:07 +0000167 # XXX these ignore the dry-run flag: what to do, what to do? even if
168 # you want a dry-run build, you still need some sort of configuration
169 # info. My inclination is to make it up to the real config command to
170 # consult 'dry_run', and assume a default (minimal) configuration if
171 # true. The problem with trying to do it here is that you'd have to
172 # return either true or false from all the 'try' methods, neither of
173 # which is correct.
174
Greg Ward59ac7092000-06-21 03:00:50 +0000175 # XXX need access to the header search path and maybe default macros.
176
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000177 def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000178 """Construct a source file from 'body' (a string containing lines
179 of C/C++ code) and 'headers' (a list of header files to include)
180 and run it through the preprocessor. Return true if the
181 preprocessor succeeded, false if there were any errors.
182 ('body' probably isn't of much use, but what the heck.)
183 """
184 from distutils.ccompiler import CompileError
185 self._check_compiler()
186 ok = 1
187 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000188 self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000189 except CompileError:
190 ok = 0
191
192 self._clean()
193 return ok
194
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000195 def search_cpp(self, pattern, body=None, headers=None, include_dirs=None,
196 lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000197 """Construct a source file (just like 'try_cpp()'), run it through
198 the preprocessor, and return true if any line of the output matches
199 'pattern'. 'pattern' should either be a compiled regex object or a
200 string containing a regex. If both 'body' and 'headers' are None,
201 preprocesses an empty file -- which can be useful to determine the
202 symbols the preprocessor and compiler set by default.
203 """
Greg Ward59ac7092000-06-21 03:00:50 +0000204 self._check_compiler()
Tarek Ziadéf6f4b302009-04-12 16:31:24 +0000205 src, out = self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000206
Tarek Ziadéf6f4b302009-04-12 16:31:24 +0000207 if isinstance(pattern, str):
Greg Ward59ac7092000-06-21 03:00:50 +0000208 pattern = re.compile(pattern)
209
210 file = open(out)
211 match = 0
212 while 1:
213 line = file.readline()
214 if line == '':
215 break
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000216 if pattern.search(line):
Greg Ward59ac7092000-06-21 03:00:50 +0000217 match = 1
218 break
219
220 file.close()
221 self._clean()
222 return match
223
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000224 def try_compile(self, body, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000225 """Try to compile a source file built from 'body' and 'headers'.
226 Return true on success, false otherwise.
Greg Ward28a5f442000-06-06 02:57:07 +0000227 """
228 from distutils.ccompiler import CompileError
229 self._check_compiler()
230 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000231 self._compile(body, headers, include_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000232 ok = 1
233 except CompileError:
234 ok = 0
235
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000236 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000237 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000238 return ok
239
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000240 def try_link(self, body, headers=None, include_dirs=None, libraries=None,
241 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000242 """Try to compile and link a source file, built from 'body' and
243 'headers', to executable form. Return true on success, false
Greg Ward28a5f442000-06-06 02:57:07 +0000244 otherwise.
245 """
246 from distutils.ccompiler import CompileError, LinkError
247 self._check_compiler()
248 try:
Greg Ward855dab92000-06-27 01:21:22 +0000249 self._link(body, headers, include_dirs,
250 libraries, library_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000251 ok = 1
252 except (CompileError, LinkError):
253 ok = 0
254
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000255 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000256 self._clean()
257 return ok
Fred Drake21d45352001-12-06 21:01:19 +0000258
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000259 def try_run(self, body, headers=None, include_dirs=None, libraries=None,
260 library_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000261 """Try to compile, link to an executable, and run a program
262 built from 'body' and 'headers'. Return true on success, false
263 otherwise.
264 """
265 from distutils.ccompiler import CompileError, LinkError
266 self._check_compiler()
267 try:
Andrew M. Kuchling246c4252001-08-13 13:56:24 +0000268 src, obj, exe = self._link(body, headers, include_dirs,
269 libraries, library_dirs, lang)
Greg Ward28a5f442000-06-06 02:57:07 +0000270 self.spawn([exe])
271 ok = 1
272 except (CompileError, LinkError, DistutilsExecError):
273 ok = 0
274
Jeremy Hyltoncd8a1142002-06-04 20:14:43 +0000275 log.info(ok and "success!" or "failure.")
Greg Ward59ac7092000-06-21 03:00:50 +0000276 self._clean()
Greg Ward28a5f442000-06-06 02:57:07 +0000277 return ok
278
Greg Ward59ac7092000-06-21 03:00:50 +0000279
280 # -- High-level methods --------------------------------------------
281 # (these are the ones that are actually likely to be useful
282 # when implementing a real-world config command!)
283
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000284 def check_func(self, func, headers=None, include_dirs=None,
285 libraries=None, library_dirs=None, decl=0, call=0):
Greg Ward59ac7092000-06-21 03:00:50 +0000286
287 """Determine if function 'func' is available by constructing a
288 source file that refers to 'func', and compiles and links it.
289 If everything succeeds, returns true; otherwise returns false.
290
291 The constructed source file starts out by including the header
292 files listed in 'headers'. If 'decl' is true, it then declares
293 'func' (as "int func()"); you probably shouldn't supply 'headers'
294 and set 'decl' true in the same call, or you might get errors about
295 a conflicting declarations for 'func'. Finally, the constructed
296 'main()' function either references 'func' or (if 'call' is true)
297 calls it. 'libraries' and 'library_dirs' are used when
298 linking.
299 """
300
301 self._check_compiler()
302 body = []
303 if decl:
304 body.append("int %s ();" % func)
305 body.append("int main () {")
306 if call:
307 body.append(" %s();" % func)
308 else:
309 body.append(" %s;" % func)
310 body.append("}")
Tarek Ziadé3295eed2009-04-12 17:02:08 +0000311 body = "\n".join(body) + "\n"
Greg Ward59ac7092000-06-21 03:00:50 +0000312
Greg Ward855dab92000-06-27 01:21:22 +0000313 return self.try_link(body, headers, include_dirs,
314 libraries, library_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000315
316 # check_func ()
317
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000318 def check_lib(self, library, library_dirs=None, headers=None,
319 include_dirs=None, other_libraries=[]):
Greg Ward855dab92000-06-27 01:21:22 +0000320 """Determine if 'library' is available to be linked against,
321 without actually checking that any particular symbols are provided
322 by it. 'headers' will be used in constructing the source file to
323 be compiled, but the only effect of this is to check if all the
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000324 header files listed are available. Any libraries listed in
325 'other_libraries' will be included in the link, in case 'library'
326 has symbols that depend on other libraries.
Greg Ward855dab92000-06-27 01:21:22 +0000327 """
328 self._check_compiler()
329 return self.try_link("int main (void) { }",
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000330 headers, include_dirs,
331 [library]+other_libraries, library_dirs)
Greg Ward855dab92000-06-27 01:21:22 +0000332
Tarek Ziadé7bea3442009-04-12 15:03:50 +0000333 def check_header(self, header, include_dirs=None, library_dirs=None,
334 lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000335 """Determine if the system header file named by 'header_file'
336 exists and can be found by the preprocessor; return true if so,
337 false otherwise.
338 """
Andrew M. Kuchling4013cbd2002-09-09 12:10:00 +0000339 return self.try_cpp(body="/* No body */", headers=[header],
340 include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000341
342
Tarek Ziadéaa487982009-04-12 14:53:51 +0000343def dump_file(filename, head=None):
344 """Dumps a file content into log.info.
Greg Ward59ac7092000-06-21 03:00:50 +0000345
Tarek Ziadéaa487982009-04-12 14:53:51 +0000346 If head is not None, will be dumped before the file content.
347 """
Greg Ward59ac7092000-06-21 03:00:50 +0000348 if head is None:
Tarek Ziadéaa487982009-04-12 14:53:51 +0000349 log.info('%s' % filename)
Greg Ward59ac7092000-06-21 03:00:50 +0000350 else:
Tarek Ziadéaa487982009-04-12 14:53:51 +0000351 log.info(head)
Greg Ward59ac7092000-06-21 03:00:50 +0000352 file = open(filename)
Tarek Ziadéaa487982009-04-12 14:53:51 +0000353 try:
354 log.info(file.read())
355 finally:
356 file.close()