diff options
Diffstat (limited to 'command/config.py')
-rw-r--r-- | command/config.py | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/command/config.py b/command/config.py new file mode 100644 index 000000000..003f04aad --- /dev/null +++ b/command/config.py @@ -0,0 +1,123 @@ +# Added Fortran compiler support to config. Currently useful only for +# try_compile call. try_run works but is untested for most of Fortran +# compilers (they must define linker_exe first). +# Pearu Peterson + +import os, signal +from distutils.command.config import config as old_config +from distutils.command.config import LANG_EXT +from distutils import log +from numpy.distutils.exec_command import exec_command + +LANG_EXT['f77'] = '.f' +LANG_EXT['f90'] = '.f90' + +class config(old_config): + old_config.user_options += [ + ('fcompiler=', None, + "specify the Fortran compiler type"), + ] + + def initialize_options(self): + self.fcompiler = None + old_config.initialize_options(self) + return + + def finalize_options(self): + old_config.finalize_options(self) + f = self.distribution.get_command_obj('config_fc') + self.set_undefined_options('config_fc', + ('fcompiler', 'fcompiler')) + return + + def _check_compiler (self): + old_config._check_compiler(self) + from numpy.distutils.fcompiler import FCompiler, new_fcompiler + if not isinstance(self.fcompiler, FCompiler): + self.fcompiler = new_fcompiler(compiler=self.fcompiler, + dry_run=self.dry_run, force=1) + self.fcompiler.customize(self.distribution) + self.fcompiler.customize_cmd(self) + self.fcompiler.show_customization() + return + + def _wrap_method(self,mth,lang,args): + from distutils.ccompiler import CompileError + from distutils.errors import DistutilsExecError + save_compiler = self.compiler + if lang in ['f77','f90']: + self.compiler = self.fcompiler + try: + ret = mth(*((self,)+args)) + except (DistutilsExecError,CompileError),msg: + self.compiler = save_compiler + raise CompileError + self.compiler = save_compiler + return ret + + def _compile (self, body, headers, include_dirs, lang): + return self._wrap_method(old_config._compile,lang, + (body, headers, include_dirs, lang)) + + def _link (self, body, + headers, include_dirs, + libraries, library_dirs, lang): + return self._wrap_method(old_config._link,lang, + (body, headers, include_dirs, + libraries, library_dirs, lang)) + + def check_func(self, func, + headers=None, include_dirs=None, + libraries=None, library_dirs=None, + decl=False, call=False, call_args=None): + # clean up distutils's config a bit: add void to main(), and + # return a value. + self._check_compiler() + body = [] + if decl: + body.append("int %s ();" % func) + body.append("int main (void) {") + if call: + if call_args is None: + call_args = '' + body.append(" %s(%s);" % (func, call_args)) + else: + body.append(" %s;" % func) + body.append(" return 0;") + body.append("}") + body = '\n'.join(body) + "\n" + + return self.try_link(body, headers, include_dirs, + libraries, library_dirs) + + def get_output(self, body, headers=None, include_dirs=None, + libraries=None, library_dirs=None, + lang="c"): + """Try to compile, link to an executable, and run a program + built from 'body' and 'headers'. Returns the exit status code + of the program and its output. + """ + from distutils.ccompiler import CompileError, LinkError + self._check_compiler() + exitcode, output = 255, '' + try: + src, obj, exe = self._link(body, headers, include_dirs, + libraries, library_dirs, lang) + exe = os.path.join('.', exe) + exitstatus, output = exec_command(exe, execute_in='.') + exitcode = os.WEXITSTATUS(exitstatus) + if os.WIFSIGNALED(exitstatus): + sig = os.WTERMSIG(exitstatus) + log.error('subprocess exited with signal %d' % (sig,)) + if sig == signal.SIGINT: + # control-C + raise KeyboardInterrupt + ok = exitstatus == 0 + ok = 1 + except (CompileError, LinkError): + ok = 0 + + log.info(ok and "success!" or "failure.") + self._clean() + return exitcode, output + |