<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.1 生成源代碼和二進制包 **NOTE**:*此示例代碼可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-11/recipe-01 中找到。該示例在CMake 3.6版(或更高版本)中是有效的,并且已經在GNU/Linux、macOS和Windows上進行過測試。* 如果代碼是開源的,用戶將能夠下載項目的源代碼,并使用完全定制的CMake腳本自行構建。當然,打包操作也可以使用腳本完成,但是CPack提供了更簡單和可移植的替代方案。本示例將指導您創建一些包: * **源代碼包**:可以將源代碼直接壓縮成歸檔文件,進行發送。用戶將不必為特定的版本控制系統操心。 * **二進制包**:工具將新構建的目標以打包的方式到歸檔文件中。這個功能非常有用,但可能不夠健壯,無法發布庫和可執行程序。 * **平臺原生的二進制安裝**:CPack能夠以許多不同的格式生成二進制安裝程序,因此可以將軟件發布到不同的平臺。我們將展示如何生成安裝程序: * 基于Debian的GNU/Linux發行版的`.deb`格式: https://manpages.debian.org/unstable/dpkg-dev/deb.5.en.html * 基于Red Hat的GNU/Linux發行版的`.rpm`格式: http://rpm.org/ * macOS包的`.dmg`格式: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html * Windows的NSIS格式: http://nsis.sourceforge.net/Main_Page ## 準備工作 我們將使用第10章第3節的示例,項目樹由以下目錄和文件組成: ```shell . ├── cmake │ ├── coffee.icns │ ├── Info.plist.in │ └── messageConfig.cmake.in ├── CMakeCPack.cmake ├── CMakeLists.txt ├── INSTALL.md ├── LICENSE ├── src │ ├── CMakeLists.txt │ ├── hello-world.cpp │ ├── Message.cpp │ └── Message.hpp └── tests ├── CMakeLists.txt └── use_target ├── CMakeLists.txt └── use_message.cpp ``` 由于本示例的重點是使用CPack,所以不會討論源碼。我們只會在`CMakeCPack.cmake`中添加打包指令。此外,還添加了`INSTALL.md`和`LICENSE`文件:打包要求需要包含安裝說明和項目許可信息。 ## 具體實施 讓我們看看需要添加到這個項目中的打包指令。我們將在` CMakeCPack.cmake `中收集它們,并在在`CMakeLists.txt`的末尾包含這個模塊`include(cmakecpackage.cmake)`: 1. 我們聲明包的名稱,與項目的名稱相同,因此我們使用`PROJECT_NAME`的CMake變量: ```cmake set(CPACK_PACKAGE_NAME "${PROJECT_NAME}") ``` 2. 聲明包的供應商: ```cmake set(CPACK_PACKAGE_VENDOR "CMake Cookbook") ``` 3. 打包的源代碼將包括一個描述文件。這是帶有安裝說明的純文本文件: ```cmake set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/INSTALL.md") ``` 4. 還添加了一個包的描述: ```cmake set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "message: a small messaging library") ``` 5. 許可證文件也將包括在包中: ```cmake set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") ``` 6. 從發布包中安裝時,文件將放在`/opt/recipe-01`目錄下: ```cmake set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/${PROJECT_NAME}") ``` 7. CPack所需的主要、次要和補丁版本: ```cmake set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") ``` 8. 設置了在包裝的時候需要忽略的文件列表和目錄: ```cmake set(CPACK_SOURCE_IGNORE_FILES "${PROJECT_BINARY_DIR};/.git/;.gitignore") ``` 9. 列出了源代碼歸檔的打包生成器——在我們的例子中是`ZIP`,用于生成`.ZIP`歸檔,`TGZ`用于`.tar.gz`歸檔: ```cmake set(CPACK_SOURCE_GENERATOR "ZIP;TGZ") ``` 10. 我們還列出了二進制存檔生成器: ```cmake set(CPACK_GENERATOR "ZIP;TGZ") ``` 11. 現在也可聲明平臺原生二進制安裝程序,從DEB和RPM包生成器開始,不過只適用于GNU/Linux: ```cmake if(UNIX) if(CMAKE_SYSTEM_NAME MATCHES Linux) list(APPEND CPACK_GENERATOR "DEB") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "robertodr") set(CPACK_DEBIAN_PACKAGE_SECTION "devel") set(CPACK_DEBIAN_PACKAGE_DEPENDS "uuid-dev") list(APPEND CPACK_GENERATOR "RPM") set(CPACK_RPM_PACKAGE_RELEASE "1") set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_RPM_PACKAGE_REQUIRES "uuid-devel") endif() endif() ``` 12. 如果我們在Windows上,我們會想要生成一個NSIS安裝程序: ```cmake if(WIN32 OR MINGW) list(APPEND CPACK_GENERATOR "NSIS") set(CPACK_NSIS_PACKAGE_NAME "message") set(CPACK_NSIS_CONTACT "robertdr") set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) endif() ``` 13. 另一方面,在macOS上,bundle包是我們的安裝程序的選擇: ```cmake if(APPLE) list(APPEND CPACK_GENERATOR "Bundle") set(CPACK_BUNDLE_NAME "message") configure_file(${PROJECT_SOURCE_DIR}/cmake/Info.plist.in Info.plist @ONLY) set(CPACK_BUNDLE_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) set(CPACK_BUNDLE_ICON ${PROJECT_SOURCE_DIR}/cmake/coffee.icns) endif() ``` 14. 我們在現有系統的包裝生成器上,向用戶打印一條信息: ```cmake message(STATUS "CPack generators: ${CPACK_GENERATOR}") ``` 15. 最后,我們包括了`CPack.cmake`標準模塊。這將向構建系統添加一個包和一個`package_source`目標: ```cmake include(CPack) ``` 現在來配置這個項目: ```shell $ mkdir -p build $ cd build $ cmake .. ``` 使用下面的命令,我們可以列出可用的目標(示例輸出是在使用Unix Makefile作為生成器的GNU/Linux系統上獲得的): ```shell $ cmake --build . --target help The following are some of the valid targets for this Makefile: ... all (the default if no target is provided) ... clean ... depend ... install/strip ... install ... package_source ... package ... install/local ... test ... list_install_components ... edit_cache ... rebuild_cache ... hello- world ... message ``` 我們可以看到`package`和`package_source`目標是可用的。可以使用以下命令生成源包: ```shell $ cmake --build . --target package_source Run CPack packaging tool for source... CPack: Create package using ZIP CPack: Install projects CPack: - Install directory: /home/user/cmake-cookbook/chapter-11/recipe-01/cxx-example CPack: Create package CPack: - package: /home/user/cmake-cookbook/chapter- 11/recipe-01/cxx-example/build/recipe-01-1.0.0-Source.zip generated. CPack: Create package using TGZ CPack: Install projects CPack: - Install directory: /home/user/cmake-cookbook/chapter- 11/recipe-01/cxx-example CPack: Create package CPack: - package: /home/user/cmake-cookbook/chapter-11/recipe-01/cxx-example/build/recipe-01- 1.0.0-Source.tar.gz generated. ``` 同樣,也可以構建二進制包: ```shell $ cmake --build . --target package message-1.0.0-Linux.deb ``` 例子中,最后得到了以下二進制包: ```shell message-1.0.0-Linux.rpm message-1.0.0-Linux.tar.gz message-1.0.0-Linux.zip ``` ## 工作原理 CPack可用于生成用于分發的包。生成構建系統時,我們在`CMakeCPack.cmake`中列出了CPack指令,用于在構建目錄下生成` CPackConfig.cmake`。當運行以`package`或`package_source`目標的CMake命令時,CPack會自動調用,參數是自動生成的配置文件。實際上,這兩個新目標是對CPack簡單規則的使用。與CMake一樣,CPack也有生成器的概念。CMake上下文中的生成器是用于生成本地構建腳本的工具,例如Unix Makefile或Visual Studio項目文件,而CPack上下文中的生成器是用于打包的工具。我們列出了這些變量,并對不同的平臺進行了特別的關注,為源包和二進制包定義了`CPACK_SOURCE_GENERATOR`和`CPACK_GENERATOR`變量。因此,`DEB`包生成器將調用`Debian`打包實用程序,而`TGZ`生成器將調用給定平臺上的歸檔工具。我們可以直接在`build`目錄中調用CPack,并選擇要與`-G`命令行選項一起使用的生成器。`RPM`包可以通過以下步驟生成: ```shell $ cd build $ cpack -G RPM CPack: Create package using RPM CPack: Install projects CPack: - Run preinstall target for: recipe-01 CPack: - Install project: recipe-01 CPack: Create package CPackRPM: Will use GENERATED spec file: /home/user/cmake-cookbook/chapter-11/recipe-01/cxx-example/build/_CPack_Packages/Linux/RPM/SPECS/recipe-01.spec CPack: - package: /home/user/cmake-cookbook/chapter-11/recipe-01/cxx-example/build/recipe-01-1.0.0-Linux.rpm generated. ``` 對于任何發行版,無論是源代碼還是二進制文件,我們只需要打包用戶需要的內容,因此整個構建目錄和其他與版本控制相關的文件,都必須從要打包的文件列表中排除。我們的例子中,排除列表使用下面的命令聲明: ```cmake set(CPACK_SOURCE_IGNORE_FILES "${PROJECT_BINARY_DIR};/.git/;.gitignore") ``` 我們還需要指定包的基本信息,例如:名稱、簡短描述和版本。這個信息是通過CMake變量設置的,當包含相應的模塊時,CMake變量被傳遞給CPack。 **NOTE**:*由于CMake 3.9中的`project()`命令接受`DESCRIPTION`字段,該字段帶有一個描述項目的短字符串。CMake將設置一個`PROJECT_DESCRIPTION`,可以用它來重置`CPACK_PACKAGE_DESCRIPTION_SUMMARY`。* 讓我們詳細看看,可以為示例項目生成的不同類型包的說明。 ### 打包源碼 我們的示例中,決定對源存檔使用`TGZ`和`ZIP`生成器。這些文件將分別生成`.tar.gz`和`.zip`壓縮文件。我們可以檢查生成的`.tar.gz`文件的內容: ```shell $ tar tzf recipe-01-1.0.0-Source.tar.gz recipe-01-1.0.0-Source/opt/ recipe-01-1.0.0-Source/opt/recipe-01/ recipe-01-1.0.0-Source/opt/recipe-01/cmake/ recipe-01-1.0.0-Source/opt/recipe-01/cmake/coffee.icns recipe-01-1.0.0-Source/opt/recipe-01/cmake/Info.plist.in recipe-01-1.0.0-Source/opt/recipe-01/cmake/messageConfig.cmake.in recipe-01-1.0.0-Source/opt/recipe-01/CMakeLists.txt recipe-01-1.0.0-Source/opt/recipe-01/src/ recipe-01-1.0.0-Source/opt/recipe-01/src/Message.hpp recipe-01-1.0.0-Source/opt/recipe-01/src/CMakeLists.txt recipe-01-1.0.0-Source/opt/recipe-01/src/Message.cpp recipe-01-1.0.0-Source/opt/recipe-01/src/hello-world.cpp recipe-01-1.0.0-Source/opt/recipe-01/LICENSE recipe-01-1.0.0-Source/opt/recipe-01/tests/ recipe-01-1.0.0-Source/opt/recipe-01/tests/CMakeLists.txt recipe-01-1.0.0-Source/opt/recipe-01/tests/use_target/ recipe-01-1.0.0-Source/opt/recipe-01/tests/use_target/CMakeLists.txt recipe-01-1.0.0-Source/opt/recipe-01/tests/use_target/use_message.cpp recipe-01-1.0.0-Source/opt/recipe-01/INSTALL.md ``` 與預期相同,只包含源碼樹的內容。注意`INSTALL.md `和`LICENSE`文件也包括在內,可以通過`CPACK_PACKAGE_DESCRIPTION_FILE`和`CPACK_RESOURCE_FILE_LICENSE`變量指定。 **NOTE**:*Visual Studio生成器無法解析`package_source`目標:https://gitlab.kitware.com/cmake/cmake/issues/13058。* ### 二進制包 創建二進制存檔時,CPack將打包`CMakeCPack.cmake`中描述的目標的內容。因此,在我們的示例中,hello-world可執行文件、消息動態庫以及相應的頭文件都將以`.tar.gz`和`.zip`的格式打包。此外,還將打包CMake配置文件。這對于需要鏈接到我們的庫的其他項目非常有用。包中使用的安裝目錄可能與從構建樹中安裝項目時使用的前綴不同,可以使用`CPACK_PACKAGING_INSTALL_PREFIX`變量來實現這一點。我們的示例中,我們將它設置為系統上的特定位置:`/opt/recipe-01`。 ```shell $ tar tzf recipe-01-1.0.0-Linux.tar.gz recipe-01- 1.0.0-Linux/opt/ recipe-01-1.0.0-Linux/opt/recipe-01/ recipe-01-1.0.0- Linux/opt/recipe-01/bin/ recipe-01-1.0.0-Linux/opt/recipe-01/bin/hello- world recipe-01-1.0.0-Linux/opt/recipe-01/share/ recipe-01-1.0.0- Linux/opt/recipe-01/share/cmake/ recipe-01-1.0.0-Linux/opt/recipe- 01/share/cmake/recipe-01/ recipe-01-1.0.0-Linux/opt/recipe- 01/share/cmake/recipe-01/messageConfig.cmake recipe-01-1.0.0- Linux/opt/recipe-01/share/cmake/recipe-01/messageTargets-hello- world.cmake recipe-01-1.0.0-Linux/opt/recipe-01/share/cmake/recipe- 01/messageConfigVersion.cmake recipe-01-1.0.0-Linux/opt/recipe- 01/share/cmake/recipe-01/messageTargets-hello-world- release.cmake recipe-01-1.0.0-Linux/opt/recipe-01/share/cmake/recipe- 01/messageTargets-release.cmake recipe-01-1.0.0-Linux/opt/recipe- 01/share/cmake/recipe-01/messageTargets.cmake recipe-01-1.0.0- Linux/opt/recipe-01/include/ recipe-01-1.0.0-Linux/opt/recipe- 01/include/message/ recipe-01-1.0.0-Linux/opt/recipe- 01/include/message/Message.hpp recipe-01-1.0.0-Linux/opt/recipe- 01/include/message/messageExport.h recipe-01-1.0.0-Linux/opt/recipe- 01/lib64/ recipe-01-1.0.0-Linux/opt/recipe- 01/lib64/libmessage.so recipe-01-1.0.0-Linux/opt/recipe- 01/lib64/libmessage.so.1` ``` ### 平臺原生的二進制安裝 我們希望每個平臺原生二進制安裝程序的配置略有不同。可以在單個`CMakeCPack.cmake`中使用CPack管理這些差異,就像例子中做的那樣。 對于GNU/Linux系統,配置了`DEB`和`RPM`生成器: ```cmake if(UNIX) if(CMAKE_SYSTEM_NAME MATCHES Linux) list(APPEND CPACK_GENERATOR "DEB") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "robertodr") set(CPACK_DEBIAN_PACKAGE_SECTION "devel") set(CPACK_DEBIAN_PACKAGE_DEPENDS "uuid-dev") list(APPEND CPACK_GENERATOR "RPM") set(CPACK_RPM_PACKAGE_RELEASE "1") set(CPACK_RPM_PACKAGE_LICENSE "MIT") set(CPACK_RPM_PACKAGE_REQUIRES "uuid-devel") endif() endif() ``` 我們的示例依賴于UUID庫,`CPACK_DEBIAN_PACKAGE_DEPENDS`和`cpack_rpm_package_require`選項允許指定,包和數據庫中對其他包的依賴關系。可以使用dpkg和rpm程序分別分析生成的`.deb`和`.rpm`包的內容。 注意,`CPACK_PACKAGING_INSTALL_PREFIX`也會影響這些包生成器:我們的包將安裝到`/opt/recipe-01`。 CMake真正提供了跨平臺和可移植構建系統的支持。下面將使用Nullsoft腳本安裝系統(NSIS)創建一個安裝程序: ```cmake if(WIN32 OR MINGW) list(APPEND CPACK_GENERATOR "NSIS") set(CPACK_NSIS_PACKAGE_NAME "message") set(CPACK_NSIS_CONTACT "robertdr") set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) endif() ``` 如果在macOS上構建項目,將啟用`Bundle packager`: ```cmake if(APPLE) list(APPEND CPACK_GENERATOR "Bundle") set(CPACK_BUNDLE_NAME "message") configure_file(${PROJECT_SOURCE_DIR}/cmake/Info.plist.in Info.plist @ONLY) set(CPACK_BUNDLE_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) set(CPACK_BUNDLE_ICON ${PROJECT_SOURCE_DIR}/cmake/coffee.icns) endif() ``` macOS的示例中,需要為包配置屬性列表文件,這是通過`configure_file`實現的。`Info.plist`的位置和包的圖標,這些都可以通過CPack的變量進行設置。 **NOTE**:*可以在這里閱讀,關于屬性列表格式的更多信息:https://en.wikipedia.org/wiki/Property_list* ## 更多信息 對` CMakeCPack.cmake `進行設置,要比列出CPack的配置選項簡單的多,我們可以將`CPACK_*`變量的每個生成器設置放在單獨的文件中,比如`CMakeCPackOptions.cmake`,并將這些設置包含到`CMakeCPack.cmake`使用`set(CPACK_PROJECT_CONFIG_FILE "${PROJECT_SOUsRCE_DIR}/CMakeCPackOptions.cmake")`將設置包含入` CMakeCPack.cmake`中。還可以在CMake時配置該文件,然后在CPack時包含該文件,這為配置多格式包生成器提供了一種簡潔的方法(參見https://cmake.org/cmake/help/v3.6/module/CPack.html )。 與CMake中的所有工具一樣,CPack功能強大、功能多樣,并且提供了更多的靈活性和選項。感興趣的讀者應該看官方文檔的命令行界面CPack (https://cmake.org/cmake/help/v3.6/manual/cpack.1.html )手冊頁,如何使用CPack生成器打包相關項目的更多細節(https://cmake.org/cmake/help/v3.6/module/CPack.html )。
                  <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>

                              哎呀哎呀视频在线观看