config.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517
  1. # Added Fortran compiler support to config. Currently useful only for
  2. # try_compile call. try_run works but is untested for most of Fortran
  3. # compilers (they must define linker_exe first).
  4. # Pearu Peterson
  5. import os
  6. import signal
  7. import subprocess
  8. import sys
  9. import textwrap
  10. import warnings
  11. from distutils.command.config import config as old_config
  12. from distutils.command.config import LANG_EXT
  13. from distutils import log
  14. from distutils.file_util import copy_file
  15. from distutils.ccompiler import CompileError, LinkError
  16. import distutils
  17. from numpy.distutils.exec_command import filepath_from_subprocess_output
  18. from numpy.distutils.mingw32ccompiler import generate_manifest
  19. from numpy.distutils.command.autodist import (check_gcc_function_attribute,
  20. check_gcc_function_attribute_with_intrinsics,
  21. check_gcc_variable_attribute,
  22. check_gcc_version_at_least,
  23. check_inline,
  24. check_restrict,
  25. check_compiler_gcc)
  26. LANG_EXT['f77'] = '.f'
  27. LANG_EXT['f90'] = '.f90'
  28. class config(old_config):
  29. old_config.user_options += [
  30. ('fcompiler=', None, "specify the Fortran compiler type"),
  31. ]
  32. def initialize_options(self):
  33. self.fcompiler = None
  34. old_config.initialize_options(self)
  35. def _check_compiler (self):
  36. old_config._check_compiler(self)
  37. from numpy.distutils.fcompiler import FCompiler, new_fcompiler
  38. if sys.platform == 'win32' and (self.compiler.compiler_type in
  39. ('msvc', 'intelw', 'intelemw')):
  40. # XXX: hack to circumvent a python 2.6 bug with msvc9compiler:
  41. # initialize call query_vcvarsall, which throws an IOError, and
  42. # causes an error along the way without much information. We try to
  43. # catch it here, hoping it is early enough, and print an helpful
  44. # message instead of Error: None.
  45. if not self.compiler.initialized:
  46. try:
  47. self.compiler.initialize()
  48. except IOError as e:
  49. msg = textwrap.dedent("""\
  50. Could not initialize compiler instance: do you have Visual Studio
  51. installed? If you are trying to build with MinGW, please use "python setup.py
  52. build -c mingw32" instead. If you have Visual Studio installed, check it is
  53. correctly installed, and the right version (VS 2008 for python 2.6, 2.7 and 3.2,
  54. VS 2010 for >= 3.3).
  55. Original exception was: %s, and the Compiler class was %s
  56. ============================================================================""") \
  57. % (e, self.compiler.__class__.__name__)
  58. print(textwrap.dedent("""\
  59. ============================================================================"""))
  60. raise distutils.errors.DistutilsPlatformError(msg) from e
  61. # After MSVC is initialized, add an explicit /MANIFEST to linker
  62. # flags. See issues gh-4245 and gh-4101 for details. Also
  63. # relevant are issues 4431 and 16296 on the Python bug tracker.
  64. from distutils import msvc9compiler
  65. if msvc9compiler.get_build_version() >= 10:
  66. for ldflags in [self.compiler.ldflags_shared,
  67. self.compiler.ldflags_shared_debug]:
  68. if '/MANIFEST' not in ldflags:
  69. ldflags.append('/MANIFEST')
  70. if not isinstance(self.fcompiler, FCompiler):
  71. self.fcompiler = new_fcompiler(compiler=self.fcompiler,
  72. dry_run=self.dry_run, force=1,
  73. c_compiler=self.compiler)
  74. if self.fcompiler is not None:
  75. self.fcompiler.customize(self.distribution)
  76. if self.fcompiler.get_version():
  77. self.fcompiler.customize_cmd(self)
  78. self.fcompiler.show_customization()
  79. def _wrap_method(self, mth, lang, args):
  80. from distutils.ccompiler import CompileError
  81. from distutils.errors import DistutilsExecError
  82. save_compiler = self.compiler
  83. if lang in ['f77', 'f90']:
  84. self.compiler = self.fcompiler
  85. if self.compiler is None:
  86. raise CompileError('%s compiler is not set' % (lang,))
  87. try:
  88. ret = mth(*((self,)+args))
  89. except (DistutilsExecError, CompileError) as e:
  90. self.compiler = save_compiler
  91. raise CompileError from e
  92. self.compiler = save_compiler
  93. return ret
  94. def _compile (self, body, headers, include_dirs, lang):
  95. src, obj = self._wrap_method(old_config._compile, lang,
  96. (body, headers, include_dirs, lang))
  97. # _compile in unixcompiler.py sometimes creates .d dependency files.
  98. # Clean them up.
  99. self.temp_files.append(obj + '.d')
  100. return src, obj
  101. def _link (self, body,
  102. headers, include_dirs,
  103. libraries, library_dirs, lang):
  104. if self.compiler.compiler_type=='msvc':
  105. libraries = (libraries or [])[:]
  106. library_dirs = (library_dirs or [])[:]
  107. if lang in ['f77', 'f90']:
  108. lang = 'c' # always use system linker when using MSVC compiler
  109. if self.fcompiler:
  110. for d in self.fcompiler.library_dirs or []:
  111. # correct path when compiling in Cygwin but with
  112. # normal Win Python
  113. if d.startswith('/usr/lib'):
  114. try:
  115. d = subprocess.check_output(['cygpath',
  116. '-w', d])
  117. except (OSError, subprocess.CalledProcessError):
  118. pass
  119. else:
  120. d = filepath_from_subprocess_output(d)
  121. library_dirs.append(d)
  122. for libname in self.fcompiler.libraries or []:
  123. if libname not in libraries:
  124. libraries.append(libname)
  125. for libname in libraries:
  126. if libname.startswith('msvc'): continue
  127. fileexists = False
  128. for libdir in library_dirs or []:
  129. libfile = os.path.join(libdir, '%s.lib' % (libname))
  130. if os.path.isfile(libfile):
  131. fileexists = True
  132. break
  133. if fileexists: continue
  134. # make g77-compiled static libs available to MSVC
  135. fileexists = False
  136. for libdir in library_dirs:
  137. libfile = os.path.join(libdir, 'lib%s.a' % (libname))
  138. if os.path.isfile(libfile):
  139. # copy libname.a file to name.lib so that MSVC linker
  140. # can find it
  141. libfile2 = os.path.join(libdir, '%s.lib' % (libname))
  142. copy_file(libfile, libfile2)
  143. self.temp_files.append(libfile2)
  144. fileexists = True
  145. break
  146. if fileexists: continue
  147. log.warn('could not find library %r in directories %s' \
  148. % (libname, library_dirs))
  149. elif self.compiler.compiler_type == 'mingw32':
  150. generate_manifest(self)
  151. return self._wrap_method(old_config._link, lang,
  152. (body, headers, include_dirs,
  153. libraries, library_dirs, lang))
  154. def check_header(self, header, include_dirs=None, library_dirs=None, lang='c'):
  155. self._check_compiler()
  156. return self.try_compile(
  157. "/* we need a dummy line to make distutils happy */",
  158. [header], include_dirs)
  159. def check_decl(self, symbol,
  160. headers=None, include_dirs=None):
  161. self._check_compiler()
  162. body = textwrap.dedent("""
  163. int main(void)
  164. {
  165. #ifndef %s
  166. (void) %s;
  167. #endif
  168. ;
  169. return 0;
  170. }""") % (symbol, symbol)
  171. return self.try_compile(body, headers, include_dirs)
  172. def check_macro_true(self, symbol,
  173. headers=None, include_dirs=None):
  174. self._check_compiler()
  175. body = textwrap.dedent("""
  176. int main(void)
  177. {
  178. #if %s
  179. #else
  180. #error false or undefined macro
  181. #endif
  182. ;
  183. return 0;
  184. }""") % (symbol,)
  185. return self.try_compile(body, headers, include_dirs)
  186. def check_type(self, type_name, headers=None, include_dirs=None,
  187. library_dirs=None):
  188. """Check type availability. Return True if the type can be compiled,
  189. False otherwise"""
  190. self._check_compiler()
  191. # First check the type can be compiled
  192. body = textwrap.dedent(r"""
  193. int main(void) {
  194. if ((%(name)s *) 0)
  195. return 0;
  196. if (sizeof (%(name)s))
  197. return 0;
  198. }
  199. """) % {'name': type_name}
  200. st = False
  201. try:
  202. try:
  203. self._compile(body % {'type': type_name},
  204. headers, include_dirs, 'c')
  205. st = True
  206. except distutils.errors.CompileError:
  207. st = False
  208. finally:
  209. self._clean()
  210. return st
  211. def check_type_size(self, type_name, headers=None, include_dirs=None, library_dirs=None, expected=None):
  212. """Check size of a given type."""
  213. self._check_compiler()
  214. # First check the type can be compiled
  215. body = textwrap.dedent(r"""
  216. typedef %(type)s npy_check_sizeof_type;
  217. int main (void)
  218. {
  219. static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) >= 0)];
  220. test_array [0] = 0
  221. ;
  222. return 0;
  223. }
  224. """)
  225. self._compile(body % {'type': type_name},
  226. headers, include_dirs, 'c')
  227. self._clean()
  228. if expected:
  229. body = textwrap.dedent(r"""
  230. typedef %(type)s npy_check_sizeof_type;
  231. int main (void)
  232. {
  233. static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) == %(size)s)];
  234. test_array [0] = 0
  235. ;
  236. return 0;
  237. }
  238. """)
  239. for size in expected:
  240. try:
  241. self._compile(body % {'type': type_name, 'size': size},
  242. headers, include_dirs, 'c')
  243. self._clean()
  244. return size
  245. except CompileError:
  246. pass
  247. # this fails to *compile* if size > sizeof(type)
  248. body = textwrap.dedent(r"""
  249. typedef %(type)s npy_check_sizeof_type;
  250. int main (void)
  251. {
  252. static int test_array [1 - 2 * !(((long) (sizeof (npy_check_sizeof_type))) <= %(size)s)];
  253. test_array [0] = 0
  254. ;
  255. return 0;
  256. }
  257. """)
  258. # The principle is simple: we first find low and high bounds of size
  259. # for the type, where low/high are looked up on a log scale. Then, we
  260. # do a binary search to find the exact size between low and high
  261. low = 0
  262. mid = 0
  263. while True:
  264. try:
  265. self._compile(body % {'type': type_name, 'size': mid},
  266. headers, include_dirs, 'c')
  267. self._clean()
  268. break
  269. except CompileError:
  270. #log.info("failure to test for bound %d" % mid)
  271. low = mid + 1
  272. mid = 2 * mid + 1
  273. high = mid
  274. # Binary search:
  275. while low != high:
  276. mid = (high - low) // 2 + low
  277. try:
  278. self._compile(body % {'type': type_name, 'size': mid},
  279. headers, include_dirs, 'c')
  280. self._clean()
  281. high = mid
  282. except CompileError:
  283. low = mid + 1
  284. return low
  285. def check_func(self, func,
  286. headers=None, include_dirs=None,
  287. libraries=None, library_dirs=None,
  288. decl=False, call=False, call_args=None):
  289. # clean up distutils's config a bit: add void to main(), and
  290. # return a value.
  291. self._check_compiler()
  292. body = []
  293. if decl:
  294. if type(decl) == str:
  295. body.append(decl)
  296. else:
  297. body.append("int %s (void);" % func)
  298. # Handle MSVC intrinsics: force MS compiler to make a function call.
  299. # Useful to test for some functions when built with optimization on, to
  300. # avoid build error because the intrinsic and our 'fake' test
  301. # declaration do not match.
  302. body.append("#ifdef _MSC_VER")
  303. body.append("#pragma function(%s)" % func)
  304. body.append("#endif")
  305. body.append("int main (void) {")
  306. if call:
  307. if call_args is None:
  308. call_args = ''
  309. body.append(" %s(%s);" % (func, call_args))
  310. else:
  311. body.append(" %s;" % func)
  312. body.append(" return 0;")
  313. body.append("}")
  314. body = '\n'.join(body) + "\n"
  315. return self.try_link(body, headers, include_dirs,
  316. libraries, library_dirs)
  317. def check_funcs_once(self, funcs,
  318. headers=None, include_dirs=None,
  319. libraries=None, library_dirs=None,
  320. decl=False, call=False, call_args=None):
  321. """Check a list of functions at once.
  322. This is useful to speed up things, since all the functions in the funcs
  323. list will be put in one compilation unit.
  324. Arguments
  325. ---------
  326. funcs : seq
  327. list of functions to test
  328. include_dirs : seq
  329. list of header paths
  330. libraries : seq
  331. list of libraries to link the code snippet to
  332. library_dirs : seq
  333. list of library paths
  334. decl : dict
  335. for every (key, value), the declaration in the value will be
  336. used for function in key. If a function is not in the
  337. dictionary, no declaration will be used.
  338. call : dict
  339. for every item (f, value), if the value is True, a call will be
  340. done to the function f.
  341. """
  342. self._check_compiler()
  343. body = []
  344. if decl:
  345. for f, v in decl.items():
  346. if v:
  347. body.append("int %s (void);" % f)
  348. # Handle MS intrinsics. See check_func for more info.
  349. body.append("#ifdef _MSC_VER")
  350. for func in funcs:
  351. body.append("#pragma function(%s)" % func)
  352. body.append("#endif")
  353. body.append("int main (void) {")
  354. if call:
  355. for f in funcs:
  356. if f in call and call[f]:
  357. if not (call_args and f in call_args and call_args[f]):
  358. args = ''
  359. else:
  360. args = call_args[f]
  361. body.append(" %s(%s);" % (f, args))
  362. else:
  363. body.append(" %s;" % f)
  364. else:
  365. for f in funcs:
  366. body.append(" %s;" % f)
  367. body.append(" return 0;")
  368. body.append("}")
  369. body = '\n'.join(body) + "\n"
  370. return self.try_link(body, headers, include_dirs,
  371. libraries, library_dirs)
  372. def check_inline(self):
  373. """Return the inline keyword recognized by the compiler, empty string
  374. otherwise."""
  375. return check_inline(self)
  376. def check_restrict(self):
  377. """Return the restrict keyword recognized by the compiler, empty string
  378. otherwise."""
  379. return check_restrict(self)
  380. def check_compiler_gcc(self):
  381. """Return True if the C compiler is gcc"""
  382. return check_compiler_gcc(self)
  383. def check_gcc_function_attribute(self, attribute, name):
  384. return check_gcc_function_attribute(self, attribute, name)
  385. def check_gcc_function_attribute_with_intrinsics(self, attribute, name,
  386. code, include):
  387. return check_gcc_function_attribute_with_intrinsics(self, attribute,
  388. name, code, include)
  389. def check_gcc_variable_attribute(self, attribute):
  390. return check_gcc_variable_attribute(self, attribute)
  391. def check_gcc_version_at_least(self, major, minor=0, patchlevel=0):
  392. """Return True if the GCC version is greater than or equal to the
  393. specified version."""
  394. return check_gcc_version_at_least(self, major, minor, patchlevel)
  395. def get_output(self, body, headers=None, include_dirs=None,
  396. libraries=None, library_dirs=None,
  397. lang="c", use_tee=None):
  398. """Try to compile, link to an executable, and run a program
  399. built from 'body' and 'headers'. Returns the exit status code
  400. of the program and its output.
  401. """
  402. # 2008-11-16, RemoveMe
  403. warnings.warn("\n+++++++++++++++++++++++++++++++++++++++++++++++++\n"
  404. "Usage of get_output is deprecated: please do not \n"
  405. "use it anymore, and avoid configuration checks \n"
  406. "involving running executable on the target machine.\n"
  407. "+++++++++++++++++++++++++++++++++++++++++++++++++\n",
  408. DeprecationWarning, stacklevel=2)
  409. self._check_compiler()
  410. exitcode, output = 255, ''
  411. try:
  412. grabber = GrabStdout()
  413. try:
  414. src, obj, exe = self._link(body, headers, include_dirs,
  415. libraries, library_dirs, lang)
  416. grabber.restore()
  417. except Exception:
  418. output = grabber.data
  419. grabber.restore()
  420. raise
  421. exe = os.path.join('.', exe)
  422. try:
  423. # specify cwd arg for consistency with
  424. # historic usage pattern of exec_command()
  425. # also, note that exe appears to be a string,
  426. # which exec_command() handled, but we now
  427. # use a list for check_output() -- this assumes
  428. # that exe is always a single command
  429. output = subprocess.check_output([exe], cwd='.')
  430. except subprocess.CalledProcessError as exc:
  431. exitstatus = exc.returncode
  432. output = ''
  433. except OSError:
  434. # preserve the EnvironmentError exit status
  435. # used historically in exec_command()
  436. exitstatus = 127
  437. output = ''
  438. else:
  439. output = filepath_from_subprocess_output(output)
  440. if hasattr(os, 'WEXITSTATUS'):
  441. exitcode = os.WEXITSTATUS(exitstatus)
  442. if os.WIFSIGNALED(exitstatus):
  443. sig = os.WTERMSIG(exitstatus)
  444. log.error('subprocess exited with signal %d' % (sig,))
  445. if sig == signal.SIGINT:
  446. # control-C
  447. raise KeyboardInterrupt
  448. else:
  449. exitcode = exitstatus
  450. log.info("success!")
  451. except (CompileError, LinkError):
  452. log.info("failure.")
  453. self._clean()
  454. return exitcode, output
  455. class GrabStdout:
  456. def __init__(self):
  457. self.sys_stdout = sys.stdout
  458. self.data = ''
  459. sys.stdout = self
  460. def write (self, data):
  461. self.sys_stdout.write(data)
  462. self.data += data
  463. def flush (self):
  464. self.sys_stdout.flush()
  465. def restore(self):
  466. sys.stdout = self.sys_stdout