1 """distutils.command.config
3 Implements the Distutils 'config' command, a (mostly) empty command class
4 that exists mainly to be sub-classed by specific module distributions and
5 applications. The idea is that while every "config" command is different,
6 at least they're all named the same, and users always see "config" in the
7 list of standard commands. Also, this is a good place to put common
8 configure-like tasks: "try to compile this C code", or "figure out where
9 this header file lives".
17 from distutils
.core
import Command
18 from distutils
.errors
import DistutilsExecError
19 from distutils
.ccompiler
import customize_compiler
20 from distutils
import log
22 LANG_EXT
= {'c': '.c', 'c++': '.cxx'}
24 class config(Command
):
26 description
= "prepare to build"
30 "specify the compiler type"),
32 "specify the compiler executable"),
33 ('include-dirs=', 'I',
34 "list of directories to search for header files"),
36 "C preprocessor macros to define"),
38 "C preprocessor macros to undefine"),
40 "external C libraries to link with"),
41 ('library-dirs=', 'L',
42 "directories to search for external C libraries"),
45 "show every action (compile, link, run, ...) taken"),
47 "dump generated source files before attempting to compile them"),
51 # The three standard command methods: since the "config" command
52 # does nothing by default, these are empty.
54 def initialize_options(self
):
57 self
.include_dirs
= None
59 self
.library_dirs
= None
61 # maximal output for now
65 # list of temporary files generated along-the-way that we have
66 # to clean at some point
69 def finalize_options(self
):
70 if self
.include_dirs
is None:
71 self
.include_dirs
= self
.distribution
.include_dirs
or []
72 elif isinstance(self
.include_dirs
, str):
73 self
.include_dirs
= self
.include_dirs
.split(os
.pathsep
)
75 if self
.libraries
is None:
77 elif isinstance(self
.libraries
, str):
78 self
.libraries
= [self
.libraries
]
80 if self
.library_dirs
is None:
81 self
.library_dirs
= []
82 elif isinstance(self
.library_dirs
, str):
83 self
.library_dirs
= self
.library_dirs
.split(os
.pathsep
)
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.
93 def _check_compiler(self
):
94 """Check that 'self.compiler' really is a CCompiler object;
97 # We do this late, and only on-demand, because this is an expensive
99 from distutils
.ccompiler
import CCompiler
, new_compiler
100 if not isinstance(self
.compiler
, CCompiler
):
101 self
.compiler
= new_compiler(compiler
=self
.compiler
,
102 dry_run
=self
.dry_run
, force
=1)
103 customize_compiler(self
.compiler
)
104 if self
.include_dirs
:
105 self
.compiler
.set_include_dirs(self
.include_dirs
)
107 self
.compiler
.set_libraries(self
.libraries
)
108 if self
.library_dirs
:
109 self
.compiler
.set_library_dirs(self
.library_dirs
)
112 def _gen_temp_sourcefile(self
, body
, headers
, lang
):
113 filename
= "_configtest" + LANG_EXT
[lang
]
114 file = open(filename
, "w")
116 for header
in headers
:
117 file.write("#include <%s>\n" % header
)
125 def _preprocess(self
, body
, headers
, include_dirs
, lang
):
126 src
= self
._gen
_temp
_sourcefile
(body
, headers
, lang
)
127 out
= "_configtest.i"
128 self
.temp_files
.extend([src
, out
])
129 self
.compiler
.preprocess(src
, out
, include_dirs
=include_dirs
)
132 def _compile(self
, body
, headers
, include_dirs
, lang
):
133 src
= self
._gen
_temp
_sourcefile
(body
, headers
, lang
)
135 dump_file(src
, "compiling '%s':" % src
)
136 (obj
,) = self
.compiler
.object_filenames([src
])
137 self
.temp_files
.extend([src
, obj
])
138 self
.compiler
.compile([src
], include_dirs
=include_dirs
)
141 def _link(self
, body
, headers
, include_dirs
, libraries
, library_dirs
,
143 (src
, obj
) = self
._compile
(body
, headers
, include_dirs
, lang
)
144 prog
= os
.path
.splitext(os
.path
.basename(src
))[0]
145 self
.compiler
.link_executable([obj
], prog
,
147 library_dirs
=library_dirs
,
150 if self
.compiler
.exe_extension
is not None:
151 prog
= prog
+ self
.compiler
.exe_extension
152 self
.temp_files
.append(prog
)
154 return (src
, obj
, prog
)
156 def _clean(self
, *filenames
):
158 filenames
= self
.temp_files
160 log
.info("removing: %s", ' '.join(filenames
))
161 for filename
in filenames
:
168 # 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
176 # XXX need access to the header search path and maybe default macros.
178 def try_cpp(self
, body
=None, headers
=None, include_dirs
=None, lang
="c"):
179 """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.)
185 from distutils
.ccompiler
import CompileError
186 self
._check
_compiler
()
189 self
._preprocess
(body
, headers
, include_dirs
, lang
)
196 def search_cpp(self
, pattern
, body
=None, headers
=None, include_dirs
=None,
198 """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.
205 self
._check
_compiler
()
206 src
, out
= self
._preprocess
(body
, headers
, include_dirs
, lang
)
208 if isinstance(pattern
, str):
209 pattern
= re
.compile(pattern
)
214 line
= file.readline()
217 if pattern
.search(line
):
225 def try_compile(self
, body
, headers
=None, include_dirs
=None, lang
="c"):
226 """Try to compile a source file built from 'body' and 'headers'.
227 Return true on success, false otherwise.
229 from distutils
.ccompiler
import CompileError
230 self
._check
_compiler
()
232 self
._compile
(body
, headers
, include_dirs
, lang
)
237 log
.info(ok
and "success!" or "failure.")
241 def try_link(self
, body
, headers
=None, include_dirs
=None, libraries
=None,
242 library_dirs
=None, lang
="c"):
243 """Try to compile and link a source file, built from 'body' and
244 'headers', to executable form. Return true on success, false
247 from distutils
.ccompiler
import CompileError
, LinkError
248 self
._check
_compiler
()
250 self
._link
(body
, headers
, include_dirs
,
251 libraries
, library_dirs
, lang
)
253 except (CompileError
, LinkError
):
256 log
.info(ok
and "success!" or "failure.")
260 def try_run(self
, body
, headers
=None, include_dirs
=None, libraries
=None,
261 library_dirs
=None, lang
="c"):
262 """Try to compile, link to an executable, and run a program
263 built from 'body' and 'headers'. Return true on success, false
266 from distutils
.ccompiler
import CompileError
, LinkError
267 self
._check
_compiler
()
269 src
, obj
, exe
= self
._link
(body
, headers
, include_dirs
,
270 libraries
, library_dirs
, lang
)
273 except (CompileError
, LinkError
, DistutilsExecError
):
276 log
.info(ok
and "success!" or "failure.")
281 # -- High-level methods --------------------------------------------
282 # (these are the ones that are actually likely to be useful
283 # when implementing a real-world config command!)
285 def check_func(self
, func
, headers
=None, include_dirs
=None,
286 libraries
=None, library_dirs
=None, decl
=0, call
=0):
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.
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
302 self
._check
_compiler
()
305 body
.append("int %s ();" % func
)
306 body
.append("int main () {")
308 body
.append(" %s();" % func
)
310 body
.append(" %s;" % func
)
312 body
= "\n".join(body
) + "\n"
314 return self
.try_link(body
, headers
, include_dirs
,
315 libraries
, library_dirs
)
319 def check_lib(self
, library
, library_dirs
=None, headers
=None,
320 include_dirs
=None, other_libraries
=[]):
321 """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
325 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.
329 self
._check
_compiler
()
330 return self
.try_link("int main (void) { }",
331 headers
, include_dirs
,
332 [library
]+other_libraries
, library_dirs
)
334 def check_header(self
, header
, include_dirs
=None, library_dirs
=None,
336 """Determine if the system header file named by 'header_file'
337 exists and can be found by the preprocessor; return true if so,
340 return self
.try_cpp(body
="/* No body */", headers
=[header
],
341 include_dirs
=include_dirs
)
344 def dump_file(filename
, head
=None):
345 """Dumps a file content into log.info.
347 If head is not None, will be dumped before the file content.
350 log
.info('%s' % filename
)
353 file = open(filename
)
355 log
.info(file.read())