diff options
author | Armin Rigo <arigo@tunes.org> | 2016-01-12 16:57:52 +0100 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2016-01-12 16:57:52 +0100 |
commit | 21c013dc94d2113da5e4941e6dde608f2fd20c29 (patch) | |
tree | 1475b2ce524cfa5d3d5d371450662dad3509acfa | |
parent | e7e824c3561171361743b9af89a795811cfdd430 (diff) | |
download | cffi-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.py | 14 | ||||
-rw-r--r-- | cffi/ffiplatform.py | 33 | ||||
-rw-r--r-- | cffi/recompiler.py | 10 |
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 |