1beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# -*- coding: ascii -*-
2beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik#
3beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# Copyright 2007, 2008, 2009, 2010, 2011
4beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# Andr\xe9 Malo or his licensors, as applicable
5beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik#
6beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# Licensed under the Apache License, Version 2.0 (the "License");
7beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# you may not use this file except in compliance with the License.
8beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# You may obtain a copy of the License at
9beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik#
10beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik#     http://www.apache.org/licenses/LICENSE-2.0
11beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik#
12beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# Unless required by applicable law or agreed to in writing, software
13beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# distributed under the License is distributed on an "AS IS" BASIS,
14beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# See the License for the specific language governing permissions and
16beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik# limitations under the License.
17beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik"""
18beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik===================
19beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik C extension tools
20beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik===================
21beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
22beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris CraikC extension tools.
23beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik"""
24beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik__author__ = "Andr\xe9 Malo"
25beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik__docformat__ = "restructuredtext en"
26beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik__test__ = False
27beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
28beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikfrom distutils import core as _core
29beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikfrom distutils import errors as _distutils_errors
30beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikfrom distutils import log
31beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikimport os as _os
32beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikimport posixpath as _posixpath
33beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikimport shutil as _shutil
34beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikimport tempfile as _tempfile
35beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
36beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikfrom _setup import commands as _commands
37beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
38beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikdef _install_finalizer(installer):
39beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    if installer.without_c_extensions:
40beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        installer.distribution.ext_modules = []
41beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
42beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikdef _build_finalizer(builder):
43beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    if builder.without_c_extensions:
44beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        builder.extensions = []
45beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
46beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
47beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikclass Extension(_core.Extension):
48beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    """
49beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    Extension with prerequisite check interface
50beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
51beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    If your check is cacheable (during the setup run), override
52beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    `cached_check_prerequisites`, `check_prerequisites` otherwise.
53beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
54beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    :IVariables:
55beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik      `cached_check` : ``bool``
56beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        The cached check result
57beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    """
58beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    cached_check = None
59beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
60beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    def __init__(self, *args, **kwargs):
61beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """ Initialization """
62beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        if 'depends' in kwargs:
63beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            self.depends = kwargs['depends'] or []
64beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        else:
65beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            self.depends = []
66beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        _core.Extension.__init__(self, *args, **kwargs)
67beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
68beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        # add include path
69beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        included = _posixpath.join('_setup', 'include')
70beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        if included not in self.include_dirs:
71beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            self.include_dirs.append(included)
72beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
73beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        # add cext.h to the dependencies
74beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        cext_h = _posixpath.join(included, 'cext.h')
75beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        if cext_h not in self.depends:
76beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            self.depends.append(cext_h)
77beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
78beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        _commands.add_option('install_lib', 'without-c-extensions',
79beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            help_text='Don\'t install C extensions',
80beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            inherit='install',
81beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        )
82beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        _commands.add_finalizer('install_lib', 'c-extensions',
83beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            _install_finalizer
84beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        )
85beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        _commands.add_option('build_ext', 'without-c-extensions',
86beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            help_text='Don\'t build C extensions',
87beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            inherit=('build', 'install_lib'),
88beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        )
89beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        _commands.add_finalizer('build_ext', 'c-extensions', _build_finalizer)
90beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
91beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    def check_prerequisites(self, build):
92beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
93beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Check prerequisites
94beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
95beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        The check should cover all dependencies needed for the extension to
96beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        be built and run. The method can do the following:
97beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
98beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        - return a false value: the extension will be built
99beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        - return a true value: the extension will be skipped. This is useful
100beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik          for optional extensions
101beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        - raise an exception. This is useful for mandatory extensions
102beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
103beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        If the check result is cacheable (during the setup run), override
104beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        `cached_check_prerequisites` instead.
105beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
106beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Parameters:
107beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik          `build` : `BuildExt`
108beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            The extension builder
109beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
110beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Return: Skip the extension?
111beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Rtype: ``bool``
112beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
113beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        if self.cached_check is None:
114beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            log.debug("PREREQ check for %s" % self.name)
115beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            self.cached_check = self.cached_check_prerequisites(build)
116beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        else:
117beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            log.debug("PREREQ check for %s (cached)" % self.name)
118beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        return self.cached_check
119beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
120beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    def cached_check_prerequisites(self, build):
121beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
122beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Check prerequisites
123beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
124beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        The check should cover all dependencies needed for the extension to
125beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        be built and run. The method can do the following:
126beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
127beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        - return a false value: the extension will be built
128beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        - return a true value: the extension will be skipped. This is useful
129beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik          for optional extensions
130beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        - raise an exception. This is useful for mandatory extensions
131beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
132beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        If the check result is *not* cacheable (during the setup run),
133beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        override `check_prerequisites` instead.
134beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
135beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Parameters:
136beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik          `build` : `BuildExt`
137beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            The extension builder
138beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
139beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Return: Skip the extension?
140beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Rtype: ``bool``
141beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
142beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        # pylint: disable = W0613
143beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        log.debug("Nothing to check for %s!" % self.name)
144beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        return False
145beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
146beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
147beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craikclass ConfTest(object):
148beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    """
149beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    Single conftest abstraction
150beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
151beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    :IVariables:
152beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik      `_tempdir` : ``str``
153beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        The tempdir created for this test
154beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
155beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik      `src` : ``str``
156beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Name of the source file
157beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
158beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik      `target` : ``str``
159beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Target filename
160beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
161beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik      `compiler` : ``CCompiler``
162beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        compiler instance
163beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
164beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik      `obj` : ``list``
165beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        List of object filenames (``[str, ...]``)
166beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    """
167beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    _tempdir = None
168beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
169beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    def __init__(self, build, source):
170beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
171beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Initialization
172beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
173beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Parameters:
174beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik          `build` : ``distuils.command.build_ext.build_ext``
175beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            builder instance
176beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
177beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik          `source` : ``str``
178beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            Source of the file to compile
179beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
180beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        self._tempdir = tempdir = _tempfile.mkdtemp()
181beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        src = _os.path.join(tempdir, 'conftest.c')
182beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        fp = open(src, 'w', encoding='utf-8')
183beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        try:
184beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            fp.write(source)
185beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        finally:
186beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            fp.close()
187beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        self.src = src
188beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        self.compiler = compiler = build.compiler
189beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        self.target = _os.path.join(tempdir, 'conftest')
190beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        self.obj = compiler.object_filenames([src], output_dir=tempdir)
191beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
192beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    def __del__(self):
193beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """ Destruction """
194beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        self.destroy()
195beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
196beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    def destroy(self):
197beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """ Destroy the conftest leftovers on disk """
198beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        tempdir, self._tempdir = self._tempdir, None
199beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        if tempdir is not None:
200beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            _shutil.rmtree(tempdir)
201beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
202beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    def compile(self, **kwargs):
203beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
204beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Compile the conftest
205beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
206beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Parameters:
207beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik          `kwargs` : ``dict``
208beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            Optional keyword parameters for the compiler call
209beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
210beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Return: Was the compilation successful?
211beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Rtype: ``bool``
212beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
213beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        kwargs['output_dir'] = self._tempdir
214beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        try:
215beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            self.compiler.compile([self.src], **kwargs)
216beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        except _distutils_errors.CompileError:
217beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            return False
218beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        return True
219beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
220beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    def link(self, **kwargs):
221beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        r"""
222beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Link the conftest
223beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
224beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Before you can link the conftest objects they need to be `compile`\d.
225beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
226beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Parameters:
227beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik          `kwargs` : ``dict``
228beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            Optional keyword parameters for the linker call
229beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
230beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Return: Was the linking successful?
231beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Rtype: ``bool``
232beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
233beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        try:
234beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            self.compiler.link_executable(self.obj, self.target, **kwargs)
235beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        except _distutils_errors.LinkError:
236beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            return False
237beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        return True
238beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
239beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik    def pipe(self, mode="r"):
240beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        r"""
241beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Execute the conftest binary and connect to it using a pipe
242beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
243beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        Before you can pipe to or from the conftest binary it needs to
244beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        be `link`\ed.
245beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
246beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Parameters:
247beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik          `mode` : ``str``
248beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik            Pipe mode - r/w
249beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik
250beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Return: The open pipe
251beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        :Rtype: ``file``
252beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        """
253beca7ae1f35e7f6605f4a21b5f4edeaa72000e39Chris Craik        return _os.popen(self.compiler.executable_filename(self.target), mode)
254