1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
# 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, copy
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
from numpy.distutils.fcompiler import FCompiler, new_fcompiler
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)
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'))
self._fcompiler = None
def run(self):
self._check_compiler()
def _check_compiler(self):
old_config._check_compiler(self)
def get_fcompiler(self):
if self._fcompiler is None:
fc = self.fcompiler.fortran()
fc.force = 1
fc.dry_run = self.dry_run
fc.customize(self.distribution)
fc.customize_cmd(self)
fc.show_customization()
self._fcompiler = fc
return self._fcompiler
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.get_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='.')
if hasattr(os, 'WEXITSTATUS'):
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
else:
exitcode = exitstatus
log.info("success!")
except (CompileError, LinkError):
log.info("failure.")
self._clean()
return exitcode, output
|