C or Cython Extensions#

Astropy supports using C extensions for wrapping C libraries and Cython for speeding up computationally-intensive calculations. Both Cython and C extension building can be customized using the get_extensions function of the setup_package.py file. If defined, this function must return a list of setuptools.Extension objects. The creation process is left to the subpackage designer, and can be customized however is relevant for the extensions in the subpackage.

While C extensions must always be defined through the get_extensions mechanism, Cython files (ending in .pyx) are automatically located by extension-helpers and loaded in separate extensions if they are not in get_extensions. For Cython extensions located in this way, headers for numpy C functions are included in the build, but no other external headers are included. .pyx files present in the extensions returned by get_extensions are not included in the list of automatically generated extensions.


If a setuptools.Extension object is provided for Cython source files using the get_extensions mechanism, it is very important that the .pyx files be given as the source, rather than the .c files generated by Cython.

Using Numpy C headers#

If your C or Cython extensions uses numpy at the C level, you probably need access to the numpy C headers. When doing this, you should use numpy.get_include() to specify the include directory to use, for example:

from setuptools import Extension
import numpy

def get_extensions():
    return Extension(name='myextension', sources=['myext.c'],

Installing C header files#

If your C extension needs to be linked from other third-party C code, you probably want to install its header files along side the Python module.

  1. Create an include directory inside of your package for all of the header files.

  2. Use the [tool.setuptools.package_data] section in your pyproject.toml file to include those header files in the package. For example, the astropy.wcs package has the following entries in the [tool.setuptools.package_data] section:

    "astropy.wcs" = ["include/*/*.h"]

Preventing importing at build time#

It is important to make sure that setup_package.py files do not trigger an import of the package they are in - so they should be able to be executed without relying on imports to other parts of the package.

Speed up your builds with ccache#

ccache is a tool that caches compiled sources so that they don’t have to be recompiled (so long as they are unchanged) even if the outputs have been deleted. This means that if you switch branches or clean your source checkout you can save a lot of time by avoiding the majority of re-compiles from scratch.

Because installation and configuration of ccache varies from platform to platform, please consult the ccache documentation and/or Google to set up ccache on your system–this is strongly encouraged for anyone doing significant development of Astropy or scientific programming in general.