summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2016-01-12 16:57:52 +0100
committerArmin Rigo <arigo@tunes.org>2016-01-12 16:57:52 +0100
commit21c013dc94d2113da5e4941e6dde608f2fd20c29 (patch)
tree1475b2ce524cfa5d3d5d371450662dad3509acfa
parente7e824c3561171361743b9af89a795811cfdd430 (diff)
downloadcffi-21c013dc94d2113da5e4941e6dde608f2fd20c29.tar.gz
Found out how to control the extension of distutils-built libraries.
Use a more suitable value by default when building embedded libraries.
-rw-r--r--cffi/api.py14
-rw-r--r--cffi/ffiplatform.py33
-rw-r--r--cffi/recompiler.py10
3 files changed, 51 insertions, 6 deletions
diff --git a/cffi/api.py b/cffi/api.py
index 49b70a0..9f218a7 100644
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -620,13 +620,25 @@ class FFI(object):
recompile(self, module_name, source,
c_file=filename, call_c_compiler=False, **kwds)
- def compile(self, tmpdir='.', verbose=0):
+ def compile(self, tmpdir='.', verbose=0, ext=None):
+ """Values recognized for the ext parameter:
+
+ - 'capi': use distutils' default to build CPython C API extensions
+ - 'system': use the system's default for dynamic libraries (.so/.dll)
+ - '.FOO': exactly .FOO
+
+ The default is 'capi' when building a non-embedded C API extension,
+ and 'system' when building an embedded library.
+ """
from .recompiler import recompile
#
if not hasattr(self, '_assigned_source'):
raise ValueError("set_source() must be called before compile()")
+ if ext not in (None, 'capi', 'system') and '.' not in ext:
+ raise ValueError("bad value for 'ext' argument: %r" % (ext,))
module_name, source, source_extension, kwds = self._assigned_source
return recompile(self, module_name, source, tmpdir=tmpdir,
+ target_extention=ext,
source_extension=source_extension,
compiler_verbose=verbose, **kwds)
diff --git a/cffi/ffiplatform.py b/cffi/ffiplatform.py
index da2f5a5..039885b 100644
--- a/cffi/ffiplatform.py
+++ b/cffi/ffiplatform.py
@@ -21,12 +21,13 @@ def get_extension(srcfilename, modname, sources=(), **kwds):
allsources.append(os.path.normpath(src))
return Extension(name=modname, sources=allsources, **kwds)
-def compile(tmpdir, ext, compiler_verbose=0):
+def compile(tmpdir, ext, compiler_verbose=0, target_extention='capi'):
"""Compile a C extension module using distutils."""
saved_environ = os.environ.copy()
try:
- outputfilename = _build(tmpdir, ext, compiler_verbose)
+ outputfilename = _build(tmpdir, ext, compiler_verbose,
+ target_extention)
outputfilename = os.path.abspath(outputfilename)
finally:
# workaround for a distutils bugs where some env vars can
@@ -36,7 +37,19 @@ def compile(tmpdir, ext, compiler_verbose=0):
os.environ[key] = value
return outputfilename
-def _build(tmpdir, ext, compiler_verbose=0):
+def _save_val(name):
+ import distutils.sysconfig
+ config_vars = distutils.sysconfig.get_config_vars()
+ return config_vars.get(name, Ellipsis)
+
+def _restore_val(name, value):
+ import distutils.sysconfig
+ config_vars = distutils.sysconfig.get_config_vars()
+ config_vars[name] = value
+ if value is Ellipsis:
+ del config_vars[name]
+
+def _build(tmpdir, ext, compiler_verbose=0, target_extention='capi'):
# XXX compact but horrible :-(
from distutils.core import Distribution
import distutils.errors, distutils.log
@@ -50,11 +63,25 @@ def _build(tmpdir, ext, compiler_verbose=0):
#
try:
old_level = distutils.log.set_threshold(0) or 0
+ old_SO = _save_val('SO')
+ old_EXT_SUFFIX = _save_val('EXT_SUFFIX')
try:
+ if target_extention == 'capi':
+ pass # keep the values already in 'SO' and 'EXT_SUFFIX'
+ else:
+ if target_extention == 'system':
+ if sys.platform == 'win32':
+ target_extention = '.dll'
+ else:
+ target_extention = '.so'
+ _restore_val('SO', target_extention)
+ _restore_val('EXT_SUFFIX', target_extention)
distutils.log.set_verbosity(compiler_verbose)
dist.run_command('build_ext')
finally:
distutils.log.set_threshold(old_level)
+ _restore_val('SO', old_SO)
+ _restore_val('EXT_SUFFIX', old_EXT_SUFFIX)
except (distutils.errors.CompileError,
distutils.errors.LinkError) as e:
raise VerificationError('%s: %s' % (e.__class__.__name__, e))
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
index aaca566..8916a34 100644
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -1359,7 +1359,7 @@ def _modname_to_file(outputdir, modname, extension):
def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True,
c_file=None, source_extension='.c', extradir=None,
- compiler_verbose=1, **kwds):
+ compiler_verbose=1, target_extention=None, **kwds):
if not isinstance(module_name, str):
module_name = module_name.encode('ascii')
if ffi._windows_unicode:
@@ -1378,10 +1378,16 @@ def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True,
ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds)
updated = make_c_source(ffi, module_name, preamble, c_file)
if call_c_compiler:
+ if target_extention is None:
+ if ffi._embedding is None:
+ target_extention = 'capi'
+ else:
+ target_extention = 'system'
cwd = os.getcwd()
try:
os.chdir(tmpdir)
- outputfilename = ffiplatform.compile('.', ext, compiler_verbose)
+ outputfilename = ffiplatform.compile('.', ext, compiler_verbose,
+ target_extention)
finally:
os.chdir(cwd)
return outputfilename