Changing Cython Naming Rules for .so Files

I use Cython to create a shared object from a Python module. The compilation output is written to build/lib.linux-x86_64-3.5/<Package>/<module>.cpython-35m-x86_64-linux-gnu.so . Is it possible to change the naming rule? I want the file to be named <module>.so without an interpreter or <module>.so version.

+7
source share
3 answers

setuptools does not seem to provide the ability to completely change or completely get rid of the suffix. The magic happens in distutils/command/build_ext.py :

 def get_ext_filename(self, ext_name): from distutils.sysconfig import get_config_var ext_path = ext_name.split('.') ext_suffix = get_config_var('EXT_SUFFIX') return os.path.join(*ext_path) + ext_suffix 

It looks like I will need to add a rename action after the build.


Update from 12/08/2016:

Ok, I forgot to actually post the solution. In fact, I performed the rename action by overloading the built-in install_lib command. Here's the logic:

 from distutils.command.install_lib import install_lib as _install_lib def batch_rename(src, dst, src_dir_fd=None, dst_dir_fd=None): '''Same as os.rename, but returns the renaming result.''' os.rename(src, dst, src_dir_fd=src_dir_fd, dst_dir_fd=dst_dir_fd) return dst class _CommandInstallCythonized(_install_lib): def __init__(self, *args, **kwargs): _install_lib.__init__(self, *args, **kwargs) def install(self): # let the distutils' install_lib do the hard work outfiles = _install_lib.install(self) # batch rename the outfiles: # for each file, match string between # second last and last dot and trim it matcher = re.compile('\.([^.]+)\.so$') return [batch_rename(file, re.sub(matcher, '.so', file)) for file in outfiles] 

Now all you have to do is reload the command in the setup function:

 setup( ... cmdclass={ 'install_lib': _CommandInstallCythonized, }, ... ) 

However, I am not happy with the overload of standard commands; If you find a better solution, post it and I will accept your answer.

+7
source

This behavior was defined in the distutils package. distutils uses the sysconfig and EXT_SUFFIX configurations:

 # Lib\distutils\command\build_ext.py def get_ext_filename(self, ext_name): r"""Convert the name of an extension (eg. "foo.bar") into the name of the file from which it will be loaded (eg. "foo/bar.so", or "foo\bar.pyd"). """ from distutils.sysconfig import get_config_var ext_path = ext_name.split('.') ext_suffix = get_config_var('EXT_SUFFIX') return os.path.join(*ext_path) + ext_suffix 

Starting with Python 3.5, the "EXT_SUFFIX" variable contains platform information, such as ".cp35-win_amd64".

I wrote the following function:

 def get_ext_filename_without_platform_suffix(filename): name, ext = os.path.splitext(filename) ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') if ext_suffix == ext: return filename ext_suffix = ext_suffix.replace(ext, '') idx = name.find(ext_suffix) if idx == -1: return filename else: return name[:idx] + ext 

And the custom build_ext command:

 from Cython.Distutils import build_ext class BuildExtWithoutPlatformSuffix(build_ext): def get_ext_filename(self, ext_name): filename = super().get_ext_filename(ext_name) return get_ext_filename_without_platform_suffix(filename) 

Using:

 setup( ... cmdclass={'build_ext': BuildExtWithoutPlatformSuffix}, ... ) 
+4
source

The solution is very simple, just change one line in build_ext.py in

  def get_ext_filename(self, ext_name): from distutils.sysconfig import get_config_var ext_path = ext_name.split('.') ext_suffix = get_config_var('EXT_SUFFIX') return os.path.join(*ext_path) + ext_suffix 

change ext_suffix = get_config_var('EXT_SUFFIX') to ext_suffix = ".so" or ".pyd" on Windows

that you no longer need to worry about the output name

0
source

All Articles