简体   繁体   中英

Using Sphinx with a distutils-built C extension

I have written a Python module including a submodule written in C: the module itself is called foo and the C part is foo._bar . The structure looks like:

src/ 
  foo/__init__.py   <- contains the public stuff 
  foo/_bar/bar.c    <- the C extension
doc/                <- Sphinx configuration
  conf.py
  ...

foo/__init__.py imports _bar to augment it, and the useful stuff is exposed in the foo module. This works fine when it's built, but obviously won't work in uncompiled form, since _bar doesn't exist until it's built.

I'd like to use Sphinx to document the project, and use the autodoc extension on the foo module. This means I need to build the project before I can build the documentation.

Since I build with distutils, the built module ends up in some variably named dir build/lib.linux-ARCH-PYVERSION — which means I can't just hard-code the directory into a Sphinx' conf.py .

So how do I configure my distutils setup.py script to run the Sphinx builder over the built module?

For completeness, here's the call to setup (the 'fake' things are custom builders that subclass build and build_ext ):

setup(cmdclass = {
        'fake': fake,
        'build_ext_fake' : build_ext_fake
      },
      package_dir = {'': 'src'},
      packages = ['foo'],
      name = 'foo',
      version = '0.1',
      description = desc,
      ext_modules = [module_real])

Since distutils has a way of figuring out the variable build path, why not just use it?

import distutils.command.build
from distutils.dist import Distribution

b = distutils.command.build.build(Distribution())
b.initialize_options()
b.finalize_options()

print b.build_temp

# If you're building a library, you might need:
print b.build_lib

# Other values of interest are:
b.build_purelib
b.build_platlib
b.build_scripts
b.build_base

Even thought the distutils docs are sparse, here you'll find one-liners about what kinds of build are there.

There are simpler ways to get the build dir name:

>>> from distutils.util import get_platform
>>> get_platform()
'linux-x86_64'

I'll let you finish the string concatenation :)

Another way to solve your problem is to create a setup.cfg file alongside your setup.py with this content:

[build_ext]
inplace = 1

This will build your extension modules in its parent package directory. Sphinx should see it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM