Skip to content Skip to sidebar Skip to footer

Change Cython's Naming Rules For .so Files

I'm using Cython to generate a shared object out of Python module. The compilation output is written to build/lib.linux-x86_64-3.5//.cpython-35m-x86_64

Solution 1:

Seems like setuptools provides no option to change or get rid of the suffix completely. The magic happens in distutils/command/build_ext.py:

defget_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

Seems like I will need to add a post-build renaming action.


Update from 08/12/2016:

Ok, I forgot to actually post the solution. Actually, I implemented a renaming action by overloading the built-in install_lib command. Here's the logic:

from distutils.command.install_lib import install_lib as _install_lib

defbatch_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)

    definstall(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 to overload the command in the setup function:

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

Still, I'm not happy with overloading standard commands; if you find a better solution, post it and I will accept your answer.

Solution 2:

This behavior has been defined in distutils package. distutils uses sysconfig and "EXT_SUFFIX" config variable:

# Lib\distutils\command\build_ext.pydefget_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 "EXT_SUFFIX" variable contains platform information, for example ".cp35-win_amd64".

I have written 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')

    ifext_suffix== ext:
        returnfilenameext_suffix= ext_suffix.replace(ext, '')
    idx = name.find(ext_suffix)

    ifidx== -1:
        return filename
    else:
        return name[:idx] + ext

And custom build_ext command:

from Cython.Distutils import build_ext

classBuildExtWithoutPlatformSuffix(build_ext):
    defget_ext_filename(self, ext_name):
        filename = super().get_ext_filename(ext_name)
        return get_ext_filename_without_platform_suffix(filename)

Usage:

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

Solution 3:

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

defget_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 to ".pyd" on Windows

that's it, you don't have to worry about the output name ever again

Post a Comment for "Change Cython's Naming Rules For .so Files"