将 C 源文件与 Python 包一起打包

Package C source files along with a Python package

我正在编写一个 C 库,我的目标是能够通过 PyPI 上的 python 包打包和分发该 C 库。这个概念是,它是 Python 代码、扩展模块和 C 库的组合。我希望用户能够在 运行 时间通过使用 distutils.ccompiler 的特定 Python 函数安装和构建 C 库。但是,我 运行 遇到了一个问题,即即使 C 源文件列在 MANIFEST.in 中,当我 运行 命令 python setup.py build 时它们也不会出现。

这是我的目录布局

home -
     setup.py
     MANIFEST.in
     package -
             ctools  -
                     __init__.py
             src     -
                     some_funcs.c
             include -
                     some_funcs.h
     pyext -
            pymain.c

我的 MANIFEST.in 文件看起来像这样

recursive-include package *.c *.h
include LICENSE.txt
include README.md

我的 distutils 设置看起来像

macro_defs = []

if os.name == 'nt':
  macro_defs.append(('_CRT_SECURE_NO_WARNINGS', '1'))

# This goes under the main package
# Will be linked with the C library later on 
core_module = distutils.core.Extension('package.core',
                    define_macros = macro_defs,
                    include_dirs = ['include'],
                    sources = ['pyext/pymain.c'])

distutils.core.setup(name='package',
      version='0.0.1',
      description='A library for searching and analyzing  data',
      author='Me',
      author_email='me@home.come',
      url='https://github.com/some/repo',
      download_url='https://github.com/some/repo/archive/master.zip',
      license = 'MIT',
      keywords = keyword_list,
      classifiers = classifers_list,
      long_description = open('README.md').read(),
      packages=['package', 'package.ctools'],
      ext_modules=[core_module],
     )

python setup.py sdist 按预期工作正常,但是当我 运行 build 命令时,它不会复制 package/src 或 [=20] 下的文件=].

当用户从 pip 安装我的包时,我希望将那些 C 源文件和头文件嵌入到他们安装的 python 包中。我怎样才能让它工作?

明确地说,我希望我的 build 命令的结果创建与我的源 package 相同的布局。

这可以通过 distutils.core.setup 函数的 data_files 参数来完成。此关键字参数采用元组列表,其中每个元组的第一个参数是安装位置的所需部分路径,第二个参数是第一个元素的目录名称下希望安装的文件的最后一个路径。尽管名称为 data_files,但可以使用它来安装任何未参与正在分发的 python 包的构建过程的文件。

例如,data_files 的用法可能类似于

from distutils.core import setup

setup(
   ...,
   data_files=[("csrc", ["src/main.c", 
                         "src/helper.c"]),
               ("cinclude", ["include/helper.h"])]
)

data_files 下指定的目录和文件将安装在 sys.prefix or under the site.USER_BASE 位置下。例如在 windows 的情况下,这些可能看起来像下面的

>>> import sys
>>> sys.prefix
'C:\Users\foobar\AppData\Local\Programs\Python\Python37'
>>> import site
>>> site.USER_BASE
'C:\Users\foobar\AppData\Roaming\Python'

安装 data_files 中的哪一个取决于在使用 pip 时是否指定了 --user 选项。