<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 11.3 通過PyPI發布使用CMake/CFFI構建C/Fortran/Python項目 **NOTE**:*此示例代碼可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-11/recipe-03 中找到,其中有一個C++和Fortran示例。該示例在CMake 3.5版(或更高版本)中是有效的,并且已經在GNU/Linux、macOS和Windows上進行過測試。* 基于第9章第6節的示例,我們將重用前一個示例中的構建塊,不過這次使用Python CFFI來提供Python接口,而不是pybind11。這個示例中,我們通過PyPI共享一個Fortran項目,這個項目可以是C或C++項目,也可以是任何公開C接口的語言,非Fortran就可以。 ## 準備工作 項目將使用如下的目錄結構: ```shell . ├── account │ ├── account.h │ ├── CMakeLists.txt │ ├── implementation │ │ └── fortran_implementation.f90 │ ├── __init__.py │ ├── interface_file_names.cfg.in │ ├── test.py │ └── version.py ├── CMakeLists.txt ├── MANIFEST.in ├── README.rst └── setup.py ``` 主`CMakeLists.txt`文件和`account`下面的所有源文件(`account/CMakeLists.txt`除外)與第9章中的使用方式相同。`README.rst`文件與前面的示例相同。`setup.py`腳本比上一個示例多了一行(包含`install_require =['cffi']`的那一行): ```python # ... up to this line the script is unchanged setup( name=_this_package, version=version['__version__'], description='Description in here.', long_description=long_description, author='Bruce Wayne', author_email='bruce.wayne@example.com', url='http://example.com', license='MIT', packages=[_this_package], install_requires=['cffi'], include_package_data=True, classifiers=[ 'Development Status :: 3 - Alpha', 'Intended Audience :: Science/Research', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.6' ], cmdclass={'build': extend_build()}) ``` `MANIFEST.in`應該與Python模塊和包一起安裝,并包含以下內容: ```txt include README.rst CMakeLists.txt recursive-include account *.h *.f90 CMakeLists.txt ``` `account`子目錄下,我們看到兩個新文件。一個`version.py`文件,其為`setup.py`保存項目的版本信息: ```python __version__ = '0.0.0' ``` 子目錄還包含`interface_file_names.cfg.in`文件: ```cmake [configuration] header_file_name = account.h library_file_name = $<TARGET_FILE_NAME:account> ``` ## 具體實施 討論一下實現打包的步驟: 1. 示例基于第9章第6節,使用Python CFFI擴展了`account/CMakeLists.txt`,增加以下指令: ```cmake file( GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/interface_file_names.cfg INPUT ${CMAKE_CURRENT_SOURCE_DIR}/interface_file_names.cfg.in ) set_target_properties(account PROPERTIES PUBLIC_HEADER "account.h;${CMAKE_CURRENT_BINARY_DIR}/account_export.h" RESOURCE "${CMAKE_CURRENT_BINARY_DIR}/interface_file_names.cfg" ) install( TARGETS account LIBRARY DESTINATION account/lib RUNTIME DESTINATION account/lib PUBLIC_HEADER DESTINATION account/include RESOURCE DESTINATION account ) ``` 安裝目標和附加文件準備好之后,就可以測試安裝了。為此,會在某處創建一個新目錄,我們將在那里測試安裝。 2. 新創建的目錄中,我們從本地路徑運行pipenv install。調整本地路徑,指向`setup.py`腳本保存的目錄: ```shell $ pipenv install /path/to/fortran-example ``` 3. 現在在Pipenv環境中生成一個Python shell: ```shell $ pipenv run python ``` 4. Python shell中,可以測試CMake包: ```shell >>> import account >>> account1 = account.new() >>> account.deposit(account1, 100.0) >>> account.deposit(account1, 100.0) >>> account.withdraw(account1, 50.0) >>> print(account.get_balance(account1)) 150.0 ``` ## 工作原理 使用Python CFFI和CMake安裝混合語言項目的擴展與第9章第6節的例子相對比,和使用Python CFFI的Python包多了兩個額外的步驟: 1. 需要`setup.py`s 2. 安裝目標時,CFFI所需的頭文件和動態庫文件,需要安裝在正確的路徑中,具體路徑取決于所選擇的Python環境 `setup.py`的結構與前面的示例幾乎一致,唯一的修改是包含`install_require =['cffi']`,以確保安裝示例包時,也獲取并安裝了所需的Python CFFI。`setup.py`腳本會自動安裝`__init__.py`和`version.py`。`MANIFEST.in `中的改變不僅有`README.rst`和CMake文件,還有頭文件和Fortran源文件: ```txt include README.rst CMakeLists.txt recursive-include account *.h *.f90 CMakeLists.txt ``` 這個示例中,使用Python CFFI和`setup.py`打包CMake項目時,我們會面臨三個挑戰: * 需要將`account.h`和`account_export.h`頭文件,以及動態庫復制到系統環境中Python模塊的位置。 * 需要告訴`__init__.py`,在哪里可以找到這些頭文件和庫。第9章第6節中,我們使用環境變量解決了這些問題,不過使用Python模塊時,不可能每次去都設置這些變量。 * Python方面,我們不知道動態庫文件的確切名稱(后綴),因為這取決于操作系統。 讓我們從最后一點開始說起:不知道確切的名稱,但在CMake生成構建系統時是知道的,因此我們在`interface_file_names.cfg,in`中使用生成器表達式,對占位符進行展開: ```txt [configuration] header_file_name = account.h library_file_name = $<TARGET_FILE_NAME:account> ``` 輸入文件用來生成`${CMAKE_CURRENT_BINARY_DIR}/interface_file_names.cfg`: ```cmake file( GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/interface_file_names.cfg INPUT ${CMAKE_CURRENT_SOURCE_DIR}/interface_file_names.cfg.in ) ``` 然后,將兩個頭文件定義為`PUBLIC_HEADER`(參見第10章),配置文件定義為`RESOURCE`: ```cmake set_target_properties(account PROPERTIES PUBLIC_HEADER "account.h;${CMAKE_CURRENT_BINARY_DIR}/account_export.h" RESOURCE "${CMAKE_CURRENT_BINARY_DIR}/interface_file_names.cfg" ) ``` 最后,將庫、頭文件和配置文件安裝到`setup.py`定義的安裝路徑中: ```cmake install( TARGETS account LIBRARY DESTINATION account/lib RUNTIME DESTINATION account/lib PUBLIC_HEADER DESTINATION account/include RESOURCE DESTINATION account ) ``` 注意,我們為庫和運行時都設置了指向`account/lib`的目標。這對于Windows很重要,因為動態庫具有可執行入口點,因此我們必須同時指定這兩個入口點。 Python包將能夠找到這些文件,要使用`account/__init__.py `來完成: ```python # this interface requires the header file and library file # and these can be either provided by interface_file_names.cfg # in the same path as this file # or if this is not found then using environment variables _this_path = Path(os.path.dirname(os.path.realpath(__file__))) _cfg_file = _this_path / 'interface_file_names.cfg' if _cfg_file.exists(): config = ConfigParser() config.read(_cfg_file) header_file_name = config.get('configuration', 'header_file_name') _header_file = _this_path / 'include' / header_file_name _header_file = str(_header_file) library_file_name = config.get('configuration', 'library_file_name') _library_file = _this_path / 'lib' / library_file_name _library_file = str(_library_file) else: _header_file = os.getenv('ACCOUNT_HEADER_FILE') assert _header_file is not None _library_file = os.getenv('ACCOUNT_LIBRARY_FILE') assert _library_file is not None ``` 本例中,將找到`_cfg_file`并進行解析,`setup.py`將找到`include`下的頭文件和`lib`下的庫,并將它們傳遞給CFFI,從而構造庫對象。這也是為什么,使用`lib`作為安裝目標`DESTINATION`,而不使用`CMAKE_INSTALL_LIBDIR`的原因(否則可能會讓`account/__init__.py `混淆)。 ## 更多信息 將包放到PyPI測試和生產實例中的后續步驟,因為有些步驟是類似的,所以可以直接參考前面的示例。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看