• <tfoot id='2IOuf'></tfoot>

    <small id='2IOuf'></small><noframes id='2IOuf'>

  • <legend id='2IOuf'><style id='2IOuf'><dir id='2IOuf'><q id='2IOuf'></q></dir></style></legend>

      <bdo id='2IOuf'></bdo><ul id='2IOuf'></ul>

      1. <i id='2IOuf'><tr id='2IOuf'><dt id='2IOuf'><q id='2IOuf'><span id='2IOuf'><b id='2IOuf'><form id='2IOuf'><ins id='2IOuf'></ins><ul id='2IOuf'></ul><sub id='2IOuf'></sub></form><legend id='2IOuf'></legend><bdo id='2IOuf'><pre id='2IOuf'><center id='2IOuf'></center></pre></bdo></b><th id='2IOuf'></th></span></q></dt></tr></i><div id='2IOuf'><tfoot id='2IOuf'></tfoot><dl id='2IOuf'><fieldset id='2IOuf'></fieldset></dl></div>

        扩展 setuptools 扩展以在 setup.py 中使用 CMake?

        时间:2023-08-28

        • <tfoot id='k3Pn7'></tfoot>

          <legend id='k3Pn7'><style id='k3Pn7'><dir id='k3Pn7'><q id='k3Pn7'></q></dir></style></legend>
            <tbody id='k3Pn7'></tbody>

          1. <i id='k3Pn7'><tr id='k3Pn7'><dt id='k3Pn7'><q id='k3Pn7'><span id='k3Pn7'><b id='k3Pn7'><form id='k3Pn7'><ins id='k3Pn7'></ins><ul id='k3Pn7'></ul><sub id='k3Pn7'></sub></form><legend id='k3Pn7'></legend><bdo id='k3Pn7'><pre id='k3Pn7'><center id='k3Pn7'></center></pre></bdo></b><th id='k3Pn7'></th></span></q></dt></tr></i><div id='k3Pn7'><tfoot id='k3Pn7'></tfoot><dl id='k3Pn7'><fieldset id='k3Pn7'></fieldset></dl></div>

              <bdo id='k3Pn7'></bdo><ul id='k3Pn7'></ul>
              • <small id='k3Pn7'></small><noframes id='k3Pn7'>

                1. 本文介绍了扩展 setuptools 扩展以在 setup.py 中使用 CMake?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我正在编写一个链接 C++ 库的 Python 扩展,我正在使用 cmake 来帮助构建过程.这意味着现在,我知道如何捆绑它的唯一方法,我必须先用 cmake 编译它们,然后才能运行 setup.py bdist_wheel.一定有更好的方法.

                  I'm writing a Python extension that links a C++ library and I'm using cmake to help with the build process. This means that right now, the only way I know how to bundle it, I have to first compile them with cmake before I can run setup.py bdist_wheel. There must be a better way.

                  我想知道是否有可能(或有人尝试过)在 setup.py ext_modules 构建过程中调用 CMake?我猜有一种方法可以创建某个东西的子类,但我不确定在哪里看.

                  I was wondering if it's possible (or anybody has tried) to invoke CMake as part of the setup.py ext_modules build process? I'm guessing there is a way to create a subclass of something but I'm not sure where to look.

                  我使用 CMake 是因为它给了我更多的控制权,可以完全按照我的需要使用复杂的构建步骤构建 c 和 c++ 库扩展.另外,我可以使用 findPythonLibs.cmake 中的 PYTHON_ADD_MODULE() 命令直接使用 cmake 轻松构建 Python 扩展.我只是希望这只是一步.

                  I'm using CMake because it gives me so much more control for building c and c++ libraries extensions with complex build steps exactly as I want it. Plus, I can easily build Python extensions directly with cmake with the PYTHON_ADD_MODULE() command in the findPythonLibs.cmake. I just wish this was all one step.

                  推荐答案

                  您基本上需要做的是覆盖 setup.py 中的 build_ext 命令类和在命令类中注册它.在您的 build_ext 自定义实现中,配置并调用 cmake 来配置和构建扩展模块.不幸的是,官方文档对于如何实现自定义 distutils 命令相当简洁(参见 扩展 Distutils);我发现直接研究命令代码更有帮助.例如,这里是 的源代码build_ext 命令.

                  What you basically need to do is to override the build_ext command class in your setup.py and register it in the command classes. In your custom impl of build_ext, configure and call cmake to configure and then build the extension modules. Unfortunately, the official docs are rather laconic about how to implement custom distutils commands (see Extending Distutils); I find it much more helpful to study the commands code directly. For example, here is the source code for the build_ext command.

                  我准备了一个简单的项目,由一个 C 扩展 foo 和一个 python 模块 spam.eggs 组成:

                  I have prepared a simple project consisting out of a single C extension foo and a python module spam.eggs:

                  so-42585210/
                  ├── spam
                  │   ├── __init__.py  # empty
                  │   ├── eggs.py
                  │   ├── foo.c
                  │   └── foo.h
                  ├── CMakeLists.txt
                  └── setup.py
                  

                  用于测试设置的文件

                  这些只是我为测试设置脚本而编写的一些简单存根.

                  Files for testing the setup

                  These are just some simple stubs I wrote to test the setup script.

                  spam/eggs.py(仅用于测试库调用):

                  spam/eggs.py (only for testing the library calls):

                  from ctypes import cdll
                  import pathlib
                  
                  
                  def wrap_bar():
                      foo = cdll.LoadLibrary(str(pathlib.Path(__file__).with_name('libfoo.dylib')))
                      return foo.bar()
                  

                  spam/foo.c:

                  #include "foo.h"
                  
                  int bar() {
                      return 42;
                  }
                  

                  spam/foo.h:

                  #ifndef __FOO_H__
                  #define __FOO_H__
                  
                  int bar();
                  
                  #endif
                  

                  CMakeLists.txt:

                  cmake_minimum_required(VERSION 3.10.1)
                  project(spam)
                  set(src "spam")
                  set(foo_src "spam/foo.c")
                  add_library(foo SHARED ${foo_src})
                  

                  设置脚本

                  这就是魔法发生的地方.当然,还有很大的改进空间 - 如果需要,您可以将其他选项传递给 CMakeExtension 类(有关扩展的更多信息,请参阅 构建 C 和 C++ 扩展),通过覆盖方法 setup.cfg 使 CMake 选项可配置 initialize_optionsfinalize_options

                  Setup script

                  This is where the magic happens. Of course, there is a lot of room for improvements - you could pass additional options to CMakeExtension class if you need to (for more info on the extensions, see Building C and C++ Extensions), make the CMake options configurable via setup.cfg by overriding methods initialize_options and finalize_options etc.

                  import os
                  import pathlib
                  
                  from setuptools import setup, Extension
                  from setuptools.command.build_ext import build_ext as build_ext_orig
                  
                  
                  class CMakeExtension(Extension):
                  
                      def __init__(self, name):
                          # don't invoke the original build_ext for this special extension
                          super().__init__(name, sources=[])
                  
                  
                  class build_ext(build_ext_orig):
                  
                      def run(self):
                          for ext in self.extensions:
                              self.build_cmake(ext)
                          super().run()
                  
                      def build_cmake(self, ext):
                          cwd = pathlib.Path().absolute()
                  
                          # these dirs will be created in build_py, so if you don't have
                          # any python sources to bundle, the dirs will be missing
                          build_temp = pathlib.Path(self.build_temp)
                          build_temp.mkdir(parents=True, exist_ok=True)
                          extdir = pathlib.Path(self.get_ext_fullpath(ext.name))
                          extdir.mkdir(parents=True, exist_ok=True)
                  
                          # example of cmake args
                          config = 'Debug' if self.debug else 'Release'
                          cmake_args = [
                              '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + str(extdir.parent.absolute()),
                              '-DCMAKE_BUILD_TYPE=' + config
                          ]
                  
                          # example of build args
                          build_args = [
                              '--config', config,
                              '--', '-j4'
                          ]
                  
                          os.chdir(str(build_temp))
                          self.spawn(['cmake', str(cwd)] + cmake_args)
                          if not self.dry_run:
                              self.spawn(['cmake', '--build', '.'] + build_args)
                          # Troubleshooting: if fail on line above then delete all possible 
                          # temporary CMake files including "CMakeCache.txt" in top level dir.
                          os.chdir(str(cwd))
                  
                  
                  setup(
                      name='spam',
                      version='0.1',
                      packages=['spam'],
                      ext_modules=[CMakeExtension('spam/foo')],
                      cmdclass={
                          'build_ext': build_ext,
                      }
                  )
                  

                  测试

                  构建项目的轮子,安装它.测试库是否安装:

                  Testing

                  Build the project's wheel, install it. Test the library is installed:

                  $ pip show -f spam
                  Name: spam
                  Version: 0.1
                  Summary: UNKNOWN
                  Home-page: UNKNOWN
                  Author: UNKNOWN
                  Author-email: UNKNOWN
                  License: UNKNOWN
                  Location: /Users/hoefling/.virtualenvs/stackoverflow/lib/python3.6/site-packages
                  Requires: 
                  Files:
                    spam-0.1.dist-info/DESCRIPTION.rst
                    spam-0.1.dist-info/INSTALLER
                    spam-0.1.dist-info/METADATA
                    spam-0.1.dist-info/RECORD
                    spam-0.1.dist-info/WHEEL
                    spam-0.1.dist-info/metadata.json
                    spam-0.1.dist-info/top_level.txt
                    spam/__init__.py
                    spam/__pycache__/__init__.cpython-36.pyc
                    spam/__pycache__/eggs.cpython-36.pyc
                    spam/eggs.py
                    spam/libfoo.dylib
                  

                  spam.eggs 模块运行包装函数:

                  Run the wrapper function from spam.eggs module:

                  $ python -c "from spam import eggs; print(eggs.wrap_bar())"
                  42
                  

                  这篇关于扩展 setuptools 扩展以在 setup.py 中使用 CMake?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:如何在 cmake 中使用 SDL2 和 SDL_image 下一篇:在跨平台 cmake 项目中设置编译器标志的现代方法

                  相关文章

                2. <legend id='zYlrG'><style id='zYlrG'><dir id='zYlrG'><q id='zYlrG'></q></dir></style></legend>

                      <i id='zYlrG'><tr id='zYlrG'><dt id='zYlrG'><q id='zYlrG'><span id='zYlrG'><b id='zYlrG'><form id='zYlrG'><ins id='zYlrG'></ins><ul id='zYlrG'></ul><sub id='zYlrG'></sub></form><legend id='zYlrG'></legend><bdo id='zYlrG'><pre id='zYlrG'><center id='zYlrG'></center></pre></bdo></b><th id='zYlrG'></th></span></q></dt></tr></i><div id='zYlrG'><tfoot id='zYlrG'></tfoot><dl id='zYlrG'><fieldset id='zYlrG'></fieldset></dl></div>

                    1. <tfoot id='zYlrG'></tfoot>
                    2. <small id='zYlrG'></small><noframes id='zYlrG'>

                        <bdo id='zYlrG'></bdo><ul id='zYlrG'></ul>