【C++实战(70)】C++ 跨平台开发:CMake构建实战指南
目录
- 一、CMake 的基础概念
- 1.1 CMake 的作用
- 1.2 CMake 环境搭建
- 1.3 CMake 的核心语法
- 二、CMake 基础项目构建
- 2.1 单文件项目的 CMakeLists.txt 编写
- 2.2 多文件项目的构建
- 2.3 头文件路径与链接库配置
- 三、CMake 高级特性实战
- 3.1 条件编译与平台差异化处理
- 3.2 编译选项配置
- 3.3 安装与打包
- 四、实战项目:跨平台计算器(CMake 构建)
- 4.1 项目需求
- 4.2 编写跨平台 CMakeLists.txt 与平台差异化代码
- 4.3 双平台编译测试与安装包生成
一、CMake 的基础概念
1.1 CMake 的作用
在 C++ 跨平台开发中,CMake 是一个至关重要的工具。它是一个跨平台的自动化构建系统,旨在简化软件项目的构建过程,使其能够在不同的操作系统和编译器环境下顺利进行编译和部署。
CMake 的主要作用之一是作为跨平台构建工具,能够生成不同平台所需的构建文件。例如,在 Windows 平台上,它可以生成 Visual Studio 项目文件(.sln 和.vcxproj),让开发者可以在 Visual Studio 集成开发环境中方便地进行项目管理和编译;而在 Linux 和 macOS 等基于 Unix 的系统上,CMake 则可以生成 Makefile 文件,通过 make 命令来完成项目的构建。这一特性极大地解决了跨平台开发中构建过程不一致的难题,使得开发者无需针对每个平台编写不同的构建脚本,大大提高了开发效率。
1.2 CMake 环境搭建
-
CMake 安装:
- Windows 系统:可以从 CMake 官方网站(https://cmake.org/download/ )下载 Windows 版本的安装包,通常是.msi 文件。下载完成后,双击安装包,按照安装向导的提示进行安装。在安装过程中,建议勾选将 CMake 添加到系统的 PATH 环境变量中,这样在命令行中就可以直接使用 cmake 命令。安装完成后,打开命令提示符(CMD)或 PowerShell,输入cmake --version,如果能正确显示 CMake 的版本信息,则说明安装成功。
- Linux 系统:对于大多数 Linux 发行版,可以通过包管理器进行安装。例如,在 Ubuntu 或 Debian 系统中,打开终端,输入sudo apt-get install cmake;在 Fedora 系统中,输入sudo dnf install cmake;在 Arch Linux 系统中,输入sudo pacman -S cmake。如果需要安装特定版本或从源码编译安装,可以从官网下载源码包,解压后进入目录,依次执行./bootstrap、make、sudo make install命令。
- macOS 系统:可以通过 Homebrew 进行安装,打开终端,执行brew install cmake命令即可。也可以从 CMake 官方网站下载适用于 macOS 的.dmg 文件,下载并运行该文件,将 CMake 图标拖动到应用程序文件夹。安装成功后,需要将环境变量添加到.bash_profile 文件中,使用 vim 进行编辑:vim ~/.bash_profile,将export PATH=“/Applications/CMake.app/Contents/bin”:"$PATH"添加到文件末尾,然后执行source ~/.bash_profile或者重新启动终端。同样,通过cmake --version命令验证安装是否成功。
-
CMake GUI 使用:
- 在 Windows 中,通常可以从开始菜单启动 CMake GUI。在 macOS 和 Linux 中,使用终端命令cmake -gui启动。
- 启动后,在 CMake GUI 界面中,首先设置源代码目录(Source Code Directory),指向包含CMakeLists.txt文件的目录;然后设置构建目录(Build Directory),用于存放生成的构建文件,建议使用独立的目录以保持源代码的整洁。
- 点击 “Configure” 按钮,选择编译器和构建选项,CMake 会检查依赖项并生成配置。如果配置过程中出现错误,需要根据提示进行相应的调整,比如缺少某些依赖库等。
- 配置完成后,点击 “Generate” 按钮,CMake 会生成适合当前平台的构建文件,如 Visual Studio 项目文件或 Makefile 文件等。
-
命令行操作:在命令行中使用 CMake,首先进入项目所在目录,确保该目录下存在CMakeLists.txt文件。然后执行cmake.命令(注意命令末尾有一个点,表示当前目录),该命令会读取CMakeLists.txt文件并生成构建文件。如果需要指定生成的构建文件类型,可以使用-G参数,例如cmake -G “Visual Studio 16 2019”.表示生成 Visual Studio 2019 的项目文件。生成构建文件后,在 Windows 下可以使用msbuild命令进行编译,在 Linux 下使用make命令进行编译。
1.3 CMake 的核心语法
- 命令格式:CMake 的命令格式为命令名(参数1 参数2 …),例如project(MyProject),这里project是命令名,MyProject是参数,表示项目名称。常见的命令还有add_executable用于添加可执行文件,add_library用于添加库文件等。例如,add_executable(MyApp main.cpp)表示将main.cpp文件编译成名为MyApp的可执行文件。
- 变量:在 CMake 中,可以使用set命令定义变量,例如set(SOURCE_FILES main.cpp utils.cpp),这里定义了一个名为SOURCE_FILES的变量,其值为main.cpp和utils.cpp。在后续的命令中可以通过${变量名}的方式引用变量,如add_executable(MyApp ${SOURCE_FILES})。CMake 还预定义了一些变量,如CMAKE_CURRENT_SOURCE_DIR表示当前源文件目录,CMAKE_CURRENT_BINARY_DIR表示当前二进制文件目录等。
- 注释:CMake 中使用#进行注释,从#开始到行末的内容都会被视为注释,不会被 CMake 解析执行。例如:# 这是一个注释,用于说明下面的命令。
- 条件判断:条件判断的语法结构为if(条件表达式),条件表达式可以是各种比较表达式或逻辑表达式。例如,通过if(WIN32)可以判断当前是否是 Windows 平台,if(UNIX)判断是否是 Unix 类平台(包括 Linux 和 macOS)。在条件判断块中,可以根据不同的条件执行不同的命令,如下所示:
if(WIN32)# Windows平台下的命令,比如添加特定的链接库target_link_libraries(MyApp winmm.lib)
elseif(UNIX)# Unix类平台下的命令,比如添加不同的链接库target_link_libraries(MyApp pthread)
else()# 其他平台的处理message(WARNING "Unsupported platform!")
endif()
二、CMake 基础项目构建
2.1 单文件项目的 CMakeLists.txt 编写
假设我们有一个简单的 C++ 程序main.cpp,内容如下:
#include <iostream>int main() {std::cout << "Hello, CMake!" << std::endl;return 0;
}
为了使用 CMake 构建这个单文件项目,我们需要在同一目录下创建一个CMakeLists.txt文件,其内容如下:
# 指定CMake的最低版本要求,这里要求至少为3.10版本,以确保项目构建脚本的兼容性,避免因使用过时的CMake命令而导致错误
cmake_minimum_required(VERSION 3.10)
# 定义项目名称为HelloCMake,可指定项目版本、描述和支持的语言等,这里暂未指定其他信息
project(HelloCMake)
# 添加可执行文件,将main.cpp编译成名为HelloCMake的可执行文件
add_executable(HelloCMake main.cpp)
在这个CMakeLists.txt文件中:
- cmake_minimum_required指定了构建该项目所需的 CMake 最低版本。如果用户使用的 CMake 版本低于这个要求,将会报错。
- project命令定义了项目的名称为HelloCMake,它会自动处理一些默认变量的初始化工作,方便后续构建过程的管理。
- add_executable命令用于将指定的源文件(这里是main.cpp)编译成一个可执行文件,第一个参数是生成的可执行文件的名称,第二个参数是源文件的名称。
2.2 多文件项目的构建
- aux_source_directory:当项目中源文件较多时,手动列出所有源文件较为繁琐。例如在一个包含多个源文件的项目中,有如下结构:
MyProject/
├── CMakeLists.txt
├── main.cpp
├── utils.cpp
├── utils.h
我们可以使用aux_source_directory命令查找指定目录下的所有源文件,并将它们存入一个变量。CMakeLists.txt文件内容可如下编写:
cmake_minimum_required(VERSION 3.10)
project(MyProject)
# 查找当前目录下的所有源文件并存入DIR_SRCS变量
aux_source_directory(. DIR_SRCS)
# 将这些源文件添加到可执行文件中,生成名为MyProject的可执行文件
add_executable(MyProject ${DIR_SRCS})
这里aux_source_directory(. DIR_SRCS)表示查找当前目录(.)下的所有源文件,并将结果存储在DIR_SRCS变量中,然后在add_executable命令中使用该变量来指定源文件。不过需要注意的是,官方不推荐使用此命令,因为它不会在添加新文件时自动触发 CMake 重新运行,容易导致新文件未被编译,但对于快速原型或简单项目,它仍然很方便。
- target_sources:对于更复杂的项目结构,比如有多个子目录,每个子目录下有不同功能的源文件,如下结构:
MyBigProject/
├── CMakeLists.txt
├── main.cpp
├── math/
│ ├── math_utils.cpp
│ └── math_utils.h
├── io/
│ ├── io_utils.cpp
│ └── io_utils.h
可以使用target_sources命令更灵活地添加源文件到目标。CMakeLists.txt文件内容如下:
cmake_minimum_required(VERSION 3.10)
project(MyBigProject)
# 添加可执行文件MyBigProject
add_executable(MyBigProject main.cpp)
# 将math目录下的math_utils.cpp添加到MyBigProject目标中
target_sources(MyBigProject PRIVATE math/math_utils.cpp)
# 将io目录下的io_utils.cpp添加到MyBigProject目标中
target_sources(MyBigProject PRIVATE io/io_utils.cpp)
target_sources命令可以多次使用,将不同的源文件添加到指定的目标(这里是MyBigProject可执行文件),PRIVATE表示这些源文件仅对当前目标可见,其他链接到该目标的目标无法直接访问这些源文件。
- add_subdirectory:当项目规模进一步扩大,可能会将不同功能模块放在不同的子目录中,并且每个子目录都有自己的CMakeLists.txt文件来管理该模块的构建。例如项目结构如下:
MyComplexProject/
├── CMakeLists.txt
├── main.cpp
├── module1/
│ ├── CMakeLists.txt
│ ├── module1.cpp
│ └── module1.h
├── module2/
│ ├── CMakeLists.txt
│ ├── module2.cpp
│ └── module2.h
在根目录的CMakeLists.txt中,可以使用add_subdirectory命令添加子目录到构建系统中:
cmake_minimum_required(VERSION 3.10)
project(MyComplexProject)
# 添加可执行文件MyComplexProject
add_executable(MyComplexProject main.cpp)
# 添加module1子目录到构建系统
add_subdirectory(module1)
# 添加module2子目录到构建系统
add_subdirectory(module2)
在module1和module2子目录的CMakeLists.txt文件中,分别定义各自模块的构建规则,比如module1目录下的CMakeLists.txt可以是:
# 定义module1模块生成的库文件,这里生成静态库libmodule1.a
add_library(module1 STATIC module1.cpp)
# 将module1库链接到MyComplexProject可执行文件,MyComplexProject的代码可以直接使用module1中定义的函数
target_link_libraries(MyComplexProject PRIVATE module1)
add_subdirectory命令会使 CMake 进入指定的子目录,读取并执行该子目录下的CMakeLists.txt文件,从而实现对子模块的独立构建和管理,并且方便项目的模块化开发和维护。
2.3 头文件路径与链接库配置
- include_directories:在项目中,当源文件包含头文件时,需要告诉编译器在哪里查找这些头文件。假设项目结构如下:
MyProject/
├── CMakeLists.txt
├── main.cpp
├── include/
│ └── myheader.h
在main.cpp中包含了myheader.h,如#include “myheader.h”,为了让编译器能够找到这个头文件,需要在CMakeLists.txt中使用include_directories命令设置头文件路径:
cmake_minimum_required(VERSION 3.10)
project(MyProject)
# 设置全局头文件路径,将include目录添加到头文件搜索路径中
include_directories(include)
# 添加可执行文件MyProject
add_executable(MyProject main.cpp)
include_directories(include)表示将include目录添加到头文件搜索路径中,这样编译器在处理#include "myheader.h"时,就会到include目录中查找myheader.h文件。此命令设置的路径对整个项目有效,即所有目标(可执行文件或库)在查找头文件时都会搜索这个路径。
- link_directories与target_link_libraries:当项目依赖外部库时,需要指定库文件的路径和链接库。假设项目依赖一个名为mylib的库,库文件位于lib目录下,项目结构如下:
MyProject/
├── CMakeLists.txt
├── main.cpp
├── lib/
│ └── libmylib.a
首先使用link_directories命令指定链接库的搜索路径:
cmake_minimum_required(VERSION 3.10)
project(MyProject)
# 指定链接库的搜索路径,将lib目录添加到链接库搜索路径中
link_directories(lib)
# 添加可执行文件MyProject
add_executable(MyProject main.cpp)
# 将mylib库链接到MyProject可执行文件
target_link_libraries(MyProject mylib)
link_directories(lib)表示将lib目录添加到链接库搜索路径中,这样在链接阶段,链接器会到lib目录中查找需要链接的库文件。target_link_libraries(MyProject mylib)则是将名为mylib的库链接到MyProject可执行文件上,使MyProject在运行时能够找到并使用mylib库中的函数和资源。
target_link_libraries命令还可以指定链接库的可见性,如PRIVATE、PUBLIC和INTERFACE。PRIVATE表示依赖项仅对当前目标内部可见;PUBLIC表示依赖项对当前目标和链接到当前目标的其他目标都可见;INTERFACE表示依赖项仅对链接到当前目标的其他目标可见 。例如,如果有一个库mylib,它依赖另一个库dependency,并且mylib被链接到MyProject可执行文件,当mylib以PUBLIC方式链接dependency时,MyProject也可以使用dependency库的功能;而以PRIVATE方式链接时,MyProject无法直接使用dependency库的功能,只能使用mylib库暴露出来的接口 。这样可以更精细地控制项目中各个模块之间的依赖关系和库的使用范围,提高项目的可维护性和可扩展性。
三、CMake 高级特性实战
3.1 条件编译与平台差异化处理
在实际的跨平台开发中,不同的操作系统可能有不同的 API、库依赖或者编译选项。通过if (WIN32)和if (UNIX)等条件判断语句,我们可以在CMakeLists.txt文件中针对不同平台进行差异化的代码编译和配置。
例如,在 Windows 平台上,我们可能需要链接一些 Windows 特有的库,如user32.lib用于窗口操作,gdi32.lib用于图形设备接口操作等;而在 Linux 平台上,我们可能需要链接pthread库来支持多线程编程,链接m库来支持数学函数等。以下是一个示例:
if (WIN32)# Windows平台特有的配置target_link_libraries(MyApp PRIVATE user32.lib gdi32.lib)add_definitions(-D_WIN32) # 定义一个预处理器宏,方便在代码中进行条件编译
elseif (UNIX)# Linux和macOS等Unix类平台特有的配置target_link_libraries(MyApp PRIVATE pthread m)add_definitions(-D_UNIX)
else()message(WARNING "Unsupported platform!")
endif()
在代码中,我们也可以使用预处理器指令进行条件编译,例如:
#ifdef _WIN32
#include <windows.h>
#elif defined(_UNIX)
#include <pthread.h>
#include <math.h>
#else
#error "Unsupported platform"
#endif
这样,当在不同平台上编译时,代码会根据平台特性包含不同的头文件和链接不同的库,从而实现平台差异化处理。
3.2 编译选项配置
- add_compile_options:该命令用于向源文件的编译添加选项。例如,我们可以添加一些通用的编译选项来提高代码的可读性和可维护性,如开启所有警告并将警告视为错误,以确保代码的质量。示例如下:
add_compile_options(-Wall -Wextra -pedantic -Werror)
-Wall表示开启所有常用的警告信息;-Wextra会开启一些额外的警告,帮助发现更多潜在的问题;-pedantic用于检查代码是否遵循标准 C++ 规范;-Werror则将所有警告视为错误,这样如果代码中有任何警告,编译过程就会失败,迫使开发者及时修复问题。
在实际项目中,如果项目对性能要求较高,可能会添加优化选项,如-O3表示最高级别的优化,它会尝试各种优化策略来提高代码的执行速度,但可能会增加编译时间。
add_compile_options(-O3)
- target_compile_features:此命令用于指定目标(可执行文件或库)所需的编译器特性,从而支持特定的 C++ 标准。例如,要指定某个可执行文件使用 C++17 标准进行编译,可以这样写:
add_executable(MyApp main.cpp)
target_compile_features(MyApp PRIVATE cxx_std_17)
这里的PRIVATE表示该特性仅对MyApp目标本身有效。如果有多个目标,并且它们依赖的 C++ 标准不同,可以分别为每个目标指定相应的特性。例如,有一个库MyLib使用 C++14 标准,而MyApp使用 C++17 标准:
add_library(MyLib STATIC lib.cpp)
add_executable(MyApp main.cpp)
target_compile_features(MyLib PUBLIC cxx_std_14)
target_compile_features(MyApp PRIVATE cxx_std_17)
通过这种方式,我们可以精确地控制每个目标所使用的 C++ 标准和编译器特性,确保项目在不同的编译器环境下都能正确编译和运行。
3.3 安装与打包
- install命令:install命令用于定义编译完成后如何安装目标文件(如可执行文件、库)、头文件、配置文件等到指定位置,是构建安装流程的核心指令。该命令不会在构建阶段执行,而是在用户显式调用cmake --install时生效。例如,将可执行文件安装到系统的bin目录,将库文件安装到lib目录,将头文件安装到include目录:
# 安装可执行文件
install(TARGETS MyAppRUNTIME DESTINATION bin
)
# 安装库文件
install(TARGETS MyLibLIBRARY DESTINATION libARCHIVE DESTINATION lib
)
# 安装头文件
install(DIRECTORY include/DESTINATION include
)
- CPack 生成安装包:CPack 是一个与 CMake 紧密集成的打包工具,能够生成各种格式的安装包,包括 DEB、RPM、NSIS、ZIP 等,极大简化了软件的分发过程。首先,在CMakeLists.txt文件中进行 CPack 的基本配置,例如:
# 设置CPack生成器类型为DEB和ZIP,这样可以同时生成Debian包和压缩包
set(CPACK_GENERATOR "DEB;ZIP")
# 设置包维护者信息
set(CPACK_PACKAGE_CONTACT "your_email@example.com")
# 设置包版本,这里假设项目已经定义了PROJECT_VERSION变量
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
# 设置包描述
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "My cross - platform application")
# 包含CPack模块
include(CPack)
配置完成后,在构建目录下执行make package命令,就会根据配置生成相应的安装包。如果需要更高级的定制,比如添加自定义的安装前后脚本、设置包的依赖关系等,CPack 也提供了丰富的配置选项来满足这些需求。例如,添加自定义的安装前脚本preinst.sh和安装后脚本postinst.sh:
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA"${CMAKE_CURRENT_SOURCE_DIR}/preinst.sh""${CMAKE_CURRENT_SOURCE_DIR}/postinst.sh"
)
这样,在生成的 Debian 包安装过程中,就会执行这些自定义脚本,从而实现更灵活的安装和部署逻辑。
四、实战项目:跨平台计算器(CMake 构建)
4.1 项目需求
在实际的软件开发中,跨平台应用的需求日益增长。我们将通过一个跨平台计算器项目来深入实践 CMake 构建工具在跨平台开发中的应用。这个跨平台计算器项目旨在实现以下功能:
- Windows/Linux 双平台支持:确保计算器程序能够在 Windows 和 Linux 操作系统上顺利编译和运行,为不同平台的用户提供一致的计算服务。无论是在 Windows 系统的办公环境中,还是在 Linux 系统的开发环境下,用户都能方便地使用该计算器。
- CMake 构建:利用 CMake 构建工具进行项目的构建和管理。通过编写CMakeLists.txt文件,实现项目的自动化构建过程,包括源文件的编译、链接库的配置等。这样可以简化项目的构建流程,提高开发效率,并且方便在不同平台上进行项目的部署。
- 命令行交互:采用命令行交互方式,用户通过在命令行中输入算式,计算器接收输入并计算结果,然后将结果输出到命令行。这种交互方式简洁高效,适用于各种场景,特别是对于习惯使用命令行的开发者和用户来说,能够快速完成计算任务。
4.2 编写跨平台 CMakeLists.txt 与平台差异化代码
- 跨平台 CMakeLists.txt 编写要点:首先,在项目根目录下创建CMakeLists.txt文件。在文件开头,指定 CMake 的最低版本要求和项目名称,例如:
cmake_minimum_required(VERSION 3.10)
project(CrossPlatformCalculator)
接着,设置 C++ 标准,这里以 C++17 为例:
set(CMAKE_CXX_STANDARD 17)
然后,添加可执行文件,假设计算器的主要源文件为main.cpp:
add_executable(CrossPlatformCalculator main.cpp)
对于可能存在的其他源文件,如实现计算逻辑的calculator.cpp,可以使用target_sources命令添加:
target_sources(CrossPlatformCalculator PRIVATE calculator.cpp)
- 平台差异化代码实现思路:在代码中,可能会存在一些与平台相关的操作,比如获取系统时间用于记录计算日志等。可以通过条件编译来实现平台差异化代码。例如,在main.cpp中:
#include <iostream>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endifint main() {// 平台差异化代码示例
#ifdef _WIN32SYSTEMTIME st;GetSystemTime(&st);std::cout << "Current time in Windows: " << st.wYear << "-" << st.wMonth << "-" << st.wDay << " " << st.wHour << ":" << st.wMinute << ":" << st.wSecond << std::endl;
#elsetime_t now = time(nullptr);struct tm *tm_info = localtime(&now);std::cout << "Current time in Linux: " << 1900 + tm_info->tm_year << "-" << 1 + tm_info->tm_mon << "-" << tm_info->tm_mday << " " << tm_info->tm_hour << ":" << tm_info->tm_min << ":" << tm_info->tm_sec << std::endl;
#endif// 计算器核心计算逻辑代码//...return 0;
}
在CMakeLists.txt中,也可以根据平台进行差异化配置,比如链接不同平台特有的库:
if (WIN32)target_link_libraries(CrossPlatformCalculator PRIVATE winmm.lib)
elseif (UNIX)target_link_libraries(CrossPlatformCalculator PRIVATE pthread m)
else()message(WARNING "Unsupported platform!")
endif()
4.3 双平台编译测试与安装包生成
- Windows 平台编译测试:在 Windows 平台上,打开命令提示符或 PowerShell,进入项目所在目录。首先创建一个构建目录,例如build,然后进入该目录:
mkdir build
cd build
在build目录下,执行 CMake 命令生成 Visual Studio 项目文件:
cmake -G "Visual Studio 16 2019"..
这里假设使用 Visual Studio 2019 进行编译,根据实际安装的 Visual Studio 版本进行调整。生成项目文件后,使用msbuild命令进行编译:
msbuild CrossPlatformCalculator.sln /p:Configuration=Release
编译完成后,在build\Release目录下可以找到生成的可执行文件CrossPlatformCalculator.exe。运行该可执行文件,在命令行中输入算式进行测试,检查计算器功能是否正常。
- Linux 平台编译测试:在 Linux 平台上,同样先进入项目目录,创建并进入构建目录:
mkdir build
cd build
在build目录下,执行 CMake 命令生成 Makefile 文件:
cmake..
生成 Makefile 后,使用make命令进行编译:
make
编译完成后,在build目录下可以找到生成的可执行文件CrossPlatformCalculator。运行该可执行文件进行测试:
./CrossPlatformCalculator
输入算式,检查计算结果是否正确。
- 安装包生成:为了方便用户安装和使用跨平台计算器,我们使用 CPack 生成安装包。在CMakeLists.txt文件中添加 CPack 相关配置:
# 设置CPack生成器类型为DEB和ZIP,这样可以同时生成Debian包和压缩包
set(CPACK_GENERATOR "DEB;ZIP")
# 设置包维护者信息
set(CPACK_PACKAGE_CONTACT "your_email@example.com")
# 设置包版本,这里假设项目已经定义了PROJECT_VERSION变量
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
# 设置包描述
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Cross - platform calculator application")
# 包含CPack模块
include(CPack)
配置完成后,在构建目录下执行make package命令,就会根据配置生成相应的安装包。在 Windows 平台上会生成CrossPlatformCalculator - {version}.zip压缩包,在 Linux 平台上会生成CrossPlatformCalculator - {version}.deb安装包。用户可以使用这些安装包在相应平台上进行安装和使用。