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