blob: 34f91884d8f9590e28ea60bba07ddc3a7c0f887e [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
56 #self.define = None
57 #self.undef = None
58 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
Collin Winter5b7e9d72007-08-30 03:52:21 +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 []
Guido van Rossum3172c5d2007-10-16 18:12:55 +000072 elif isinstance(self.include_dirs, str):
Neal Norwitz9d72bb42007-04-17 08:48:32 +000073 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 = []
Guido van Rossum3172c5d2007-10-16 18:12:55 +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 = []
Guido van Rossum3172c5d2007-10-16 18:12:55 +000082 elif isinstance(self.library_dirs, str):
Neal Norwitz9d72bb42007-04-17 08:48:32 +000083 self.library_dirs = self.library_dirs.split(os.pathsep)
Greg Ward2e38a502000-10-14 03:40:20 +000084
Collin Winter5b7e9d72007-08-30 03:52:21 +000085 def run(self):
Greg Ward28a5f442000-06-06 02:57:07 +000086 pass
87
Greg Ward28a5f442000-06-06 02:57:07 +000088 # 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
Collin Winter5b7e9d72007-08-30 03:52:21 +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
Collin Winter5b7e9d72007-08-30 03:52:21 +0000110 def _gen_temp_sourcefile(self, body, headers, lang):
Greg Ward28a5f442000-06-06 02:57:07 +0000111 filename = "_configtest" + LANG_EXT[lang]
112 file = open(filename, "w")
Greg Ward59ac7092000-06-21 03:00:50 +0000113 if headers:
114 for header in headers:
115 file.write("#include <%s>\n" % header)
116 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000117 file.write(body)
Greg Ward59ac7092000-06-21 03:00:50 +0000118 if body[-1] != "\n":
119 file.write("\n")
Greg Ward28a5f442000-06-06 02:57:07 +0000120 file.close()
121 return filename
122
Collin Winter5b7e9d72007-08-30 03:52:21 +0000123 def _preprocess(self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000124 src = self._gen_temp_sourcefile(body, headers, lang)
125 out = "_configtest.i"
126 self.temp_files.extend([src, out])
Greg Ward855dab92000-06-27 01:21:22 +0000127 self.compiler.preprocess(src, out, include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000128 return (src, out)
129
Collin Winter5b7e9d72007-08-30 03:52:21 +0000130 def _compile(self, body, headers, include_dirs, lang):
Greg Ward59ac7092000-06-21 03:00:50 +0000131 src = self._gen_temp_sourcefile(body, headers, lang)
132 if self.dump_source:
133 dump_file(src, "compiling '%s':" % src)
134 (obj,) = self.compiler.object_filenames([src])
135 self.temp_files.extend([src, obj])
Greg Ward855dab92000-06-27 01:21:22 +0000136 self.compiler.compile([src], include_dirs=include_dirs)
Greg Ward28a5f442000-06-06 02:57:07 +0000137 return (src, obj)
138
Collin Winter5b7e9d72007-08-30 03:52:21 +0000139 def _link(self, body, headers, include_dirs, libraries,
140 library_dirs, lang):
Greg Ward855dab92000-06-27 01:21:22 +0000141 (src, obj) = self._compile(body, headers, include_dirs, lang)
Fred Drake21d45352001-12-06 21:01:19 +0000142 prog = os.path.splitext(os.path.basename(src))[0]
Greg Ward59ac7092000-06-21 03:00:50 +0000143 self.compiler.link_executable([obj], prog,
144 libraries=libraries,
Gustavo Niemeyer6b016852002-11-05 16:12:02 +0000145 library_dirs=library_dirs,
146 target_lang=lang)
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000147
Just van Rossumca3fec72003-02-03 11:43:54 +0000148 if self.compiler.exe_extension is not None:
149 prog = prog + self.compiler.exe_extension
Andrew M. Kuchlingb1d60292001-08-16 14:08:02 +0000150 self.temp_files.append(prog)
151
Greg Ward59ac7092000-06-21 03:00:50 +0000152 return (src, obj, prog)
Greg Ward28a5f442000-06-06 02:57:07 +0000153
Collin Winter5b7e9d72007-08-30 03:52:21 +0000154 def _clean(self, *filenames):
Greg Ward59ac7092000-06-21 03:00:50 +0000155 if not filenames:
156 filenames = self.temp_files
157 self.temp_files = []
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000158 log.info("removing: %s", ' '.join(filenames))
Greg Ward28a5f442000-06-06 02:57:07 +0000159 for filename in filenames:
160 try:
161 os.remove(filename)
162 except OSError:
163 pass
164
165
Greg Ward28a5f442000-06-06 02:57:07 +0000166 # XXX these ignore the dry-run flag: what to do, what to do? even if
167 # you want a dry-run build, you still need some sort of configuration
168 # info. My inclination is to make it up to the real config command to
169 # consult 'dry_run', and assume a default (minimal) configuration if
170 # true. The problem with trying to do it here is that you'd have to
171 # return either true or false from all the 'try' methods, neither of
172 # which is correct.
173
Greg Ward59ac7092000-06-21 03:00:50 +0000174 # XXX need access to the header search path and maybe default macros.
175
Collin Winter5b7e9d72007-08-30 03:52:21 +0000176 def try_cpp(self, body=None, headers=None, include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000177 """Construct a source file from 'body' (a string containing lines
178 of C/C++ code) and 'headers' (a list of header files to include)
179 and run it through the preprocessor. Return true if the
180 preprocessor succeeded, false if there were any errors.
181 ('body' probably isn't of much use, but what the heck.)
182 """
183 from distutils.ccompiler import CompileError
184 self._check_compiler()
Collin Winter5b7e9d72007-08-30 03:52:21 +0000185 ok = True
Greg Ward59ac7092000-06-21 03:00:50 +0000186 try:
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000187 self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000188 except CompileError:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000189 ok = False
Greg Ward59ac7092000-06-21 03:00:50 +0000190
191 self._clean()
192 return ok
193
Collin Winter5b7e9d72007-08-30 03:52:21 +0000194 def search_cpp(self, pattern, body=None, headers=None,
195 include_dirs=None, lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000196 """Construct a source file (just like 'try_cpp()'), run it through
197 the preprocessor, and return true if any line of the output matches
198 'pattern'. 'pattern' should either be a compiled regex object or a
199 string containing a regex. If both 'body' and 'headers' are None,
200 preprocesses an empty file -- which can be useful to determine the
201 symbols the preprocessor and compiler set by default.
202 """
203
204 self._check_compiler()
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000205 (src, out) = self._preprocess(body, headers, include_dirs, lang)
Greg Ward59ac7092000-06-21 03:00:50 +0000206
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000207 if isinstance(pattern, str):
Greg Ward59ac7092000-06-21 03:00:50 +0000208 pattern = re.compile(pattern)
209
210 file = open(out)
Collin Winter5b7e9d72007-08-30 03:52:21 +0000211 match = False
212 while True:
Greg Ward59ac7092000-06-21 03:00:50 +0000213 line = file.readline()
214 if line == '':
215 break
Andrew M. Kuchling6fb8d3a2001-08-16 13:56:40 +0000216 if pattern.search(line):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000217 match = True
Greg Ward59ac7092000-06-21 03:00:50 +0000218 break
219
220 file.close()
221 self._clean()
222 return match
223
Collin Winter5b7e9d72007-08-30 03:52:21 +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)
Collin Winter5b7e9d72007-08-30 03:52:21 +0000232 ok = True
Greg Ward28a5f442000-06-06 02:57:07 +0000233 except CompileError:
Collin Winter5b7e9d72007-08-30 03:52:21 +0000234 ok = False
Greg Ward28a5f442000-06-06 02:57:07 +0000235
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
Collin Winter5b7e9d72007-08-30 03:52:21 +0000240 def try_link(self, body, headers=None, include_dirs=None,
241 libraries=None, 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)
Collin Winter5b7e9d72007-08-30 03:52:21 +0000251 ok = True
Greg Ward59ac7092000-06-21 03:00:50 +0000252 except (CompileError, LinkError):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000253 ok = False
Greg Ward59ac7092000-06-21 03:00:50 +0000254
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
Collin Winter5b7e9d72007-08-30 03:52:21 +0000259 def try_run(self, body, headers=None, include_dirs=None,
260 libraries=None, 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])
Collin Winter5b7e9d72007-08-30 03:52:21 +0000271 ok = True
Greg Ward28a5f442000-06-06 02:57:07 +0000272 except (CompileError, LinkError, DistutilsExecError):
Collin Winter5b7e9d72007-08-30 03:52:21 +0000273 ok = False
Greg Ward28a5f442000-06-06 02:57:07 +0000274
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
Collin Winter5b7e9d72007-08-30 03:52:21 +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 """Determine if function 'func' is available by constructing a
287 source file that refers to 'func', and compiles and links it.
288 If everything succeeds, returns true; otherwise returns false.
289
290 The constructed source file starts out by including the header
291 files listed in 'headers'. If 'decl' is true, it then declares
292 'func' (as "int func()"); you probably shouldn't supply 'headers'
293 and set 'decl' true in the same call, or you might get errors about
294 a conflicting declarations for 'func'. Finally, the constructed
295 'main()' function either references 'func' or (if 'call' is true)
296 calls it. 'libraries' and 'library_dirs' are used when
297 linking.
298 """
Greg Ward59ac7092000-06-21 03:00:50 +0000299 self._check_compiler()
300 body = []
301 if decl:
302 body.append("int %s ();" % func)
303 body.append("int main () {")
304 if call:
305 body.append(" %s();" % func)
306 else:
307 body.append(" %s;" % func)
308 body.append("}")
Neal Norwitz9d72bb42007-04-17 08:48:32 +0000309 body = "\n".join(body) + "\n"
Greg Ward59ac7092000-06-21 03:00:50 +0000310
Greg Ward855dab92000-06-27 01:21:22 +0000311 return self.try_link(body, headers, include_dirs,
312 libraries, library_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000313
Collin Winter5b7e9d72007-08-30 03:52:21 +0000314 def check_lib(self, library, library_dirs=None, headers=None,
315 include_dirs=None, other_libraries=[]):
Greg Ward855dab92000-06-27 01:21:22 +0000316 """Determine if 'library' is available to be linked against,
317 without actually checking that any particular symbols are provided
318 by it. 'headers' will be used in constructing the source file to
319 be compiled, but the only effect of this is to check if all the
Greg Ward4cd6f2a2000-10-14 03:56:42 +0000320 header files listed are available. Any libraries listed in
321 'other_libraries' will be included in the link, in case 'library'
322 has symbols that depend on other libraries.
Greg Ward855dab92000-06-27 01:21:22 +0000323 """
324 self._check_compiler()
Collin Winter5b7e9d72007-08-30 03:52:21 +0000325 return self.try_link("int main (void) { }", headers, include_dirs,
326 [library] + other_libraries, library_dirs)
Greg Ward855dab92000-06-27 01:21:22 +0000327
Collin Winter5b7e9d72007-08-30 03:52:21 +0000328 def check_header(self, header, include_dirs=None, library_dirs=None,
329 lang="c"):
Greg Ward59ac7092000-06-21 03:00:50 +0000330 """Determine if the system header file named by 'header_file'
331 exists and can be found by the preprocessor; return true if so,
332 false otherwise.
333 """
Andrew M. Kuchling4013cbd2002-09-09 12:10:00 +0000334 return self.try_cpp(body="/* No body */", headers=[header],
335 include_dirs=include_dirs)
Greg Ward59ac7092000-06-21 03:00:50 +0000336
337
Collin Winter5b7e9d72007-08-30 03:52:21 +0000338def dump_file(filename, head=None):
Greg Ward59ac7092000-06-21 03:00:50 +0000339 if head is None:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000340 print(filename + ":")
Greg Ward59ac7092000-06-21 03:00:50 +0000341 else:
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000342 print(head)
Greg Ward59ac7092000-06-21 03:00:50 +0000343
344 file = open(filename)
345 sys.stdout.write(file.read())
346 file.close()