diff --git a/08-项目实战与工具链/README.md b/08-项目实战与工具链/README.md index 8b13789..b68e6bc 100644 --- a/08-项目实战与工具链/README.md +++ b/08-项目实战与工具链/README.md @@ -1 +1,848 @@ +# 📦 第八层:项目实战与工具链 +## ✅ 工程管理 + +### 🔹 Git 版本控制 + +#### 1. **Git 分支策略** +- **主干分支(main/master)**: + 永远代表可发布的稳定版本,仅接受通过CI/CD验证的代码。 +- **开发分支(develop)**: + 集成所有新功能的开发,是日常开发的基础分支。 +- **特性分支(feature/*)**: + 从develop分支创建,用于开发单个新功能或修复问题,完成后合并回develop。 +- **发布分支(release/*)**: + 从develop分支创建,用于准备发布版本,进行最后的测试和Bug修复。 +- **热修复分支(hotfix/*)**: + 从main分支创建,用于紧急修复生产环境问题,修复后合并回main和develop。 + +#### 2. **提交规范** +采用Conventional Commits规范: +``` +<类型>[可选范围]: <描述> + +[可选正文] + +[可选脚注] +``` +- **常见类型**: + - `feat`:新功能 + - `fix`:修复Bug + - `docs`:文档更新 + - `style`:代码格式调整(不影响功能) + - `refactor`:代码重构 + - `test`:添加或修改测试 + - `chore`:构建或辅助工具的变动 + +#### 3. **标签管理** +使用语义化版本(SemVer)打标签: +```bash +# 创建标签 +git tag v1.0.0 + +# 推送标签到远程 +git push origin v1.0.0 + +# 查看所有标签 +git tag -l +``` + + +### 🔹 Makefile、CMake 构建工具 + +#### 1. **Makefile 基础** +- **简单示例**: + ```makefile + CC = arm-none-eabi-gcc + CFLAGS = -Wall -O2 -mcpu=cortex-m4 -mthumb + LDFLAGS = -Tstm32f4.ld + + SRCS = $(wildcard *.c) + OBJS = $(SRCS:.c=.o) + TARGET = firmware.elf + + all: $(TARGET) + + $(TARGET): $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -o $@ + + %.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + + clean: + rm -f $(OBJS) $(TARGET) + ``` + +#### 2. **CMake 高级应用** +- **跨平台配置**: + ```cmake + cmake_minimum_required(VERSION 3.10) + project(EmbeddedProject C) + + # 设置交叉编译工具链 + set(CMAKE_SYSTEM_NAME Generic) + set(CMAKE_C_COMPILER arm-none-eabi-gcc) + set(CMAKE_CXX_COMPILER arm-none-eabi-g++) + set(CMAKE_ASM_COMPILER arm-none-eabi-gcc) + set(CMAKE_OBJCOPY arm-none-eabi-objcopy) + + # 添加编译选项 + add_compile_options( + -mcpu=cortex-m4 + -mthumb + -mfloat-abi=hard + -mfpu=fpv4-sp-d16 + -Wall + -Wextra + -Os + ) + + # 添加链接选项 + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T${CMAKE_SOURCE_DIR}/STM32F407VGTx_FLASH.ld") + + # 添加源文件 + file(GLOB_RECURSE SOURCES "src/*.c" "drivers/*.c") + + # 添加可执行文件 + add_executable(${PROJECT_NAME}.elf ${SOURCES}) + + # 添加目标文件 + add_custom_target(${PROJECT_NAME}.bin + COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin + DEPENDS ${PROJECT_NAME}.elf + ) + ``` + + +### 🔹 Jenkins/GitHub Actions CI 流水线 + +#### 1. **GitHub Actions 配置** +- **编译与测试工作流**: + ```yaml + name: Build and Test + + on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + + jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y gcc-arm-none-eabi cmake ninja-build + + - name: Configure CMake + run: cmake -B build -G Ninja + + - name: Build + run: cmake --build build + + - name: Run tests + run: | + cd build + ctest --output-on-failure + ``` + +#### 2. **Jenkins 集成** +- **构建脚本示例**: + ```groovy + pipeline { + agent any + + stages { + stage('Checkout') { + steps { + checkout scm + } + } + + stage('Build') { + steps { + sh 'make clean all' + } + } + + stage('Test') { + steps { + sh 'make test' + } + } + + stage('Code Coverage') { + steps { + sh 'make coverage' + } + post { + always { + junit 'build/test-results/*.xml' + publishCoverage adapters: [coberturaAdapter('build/coverage/coverage.xml')] + } + } + } + + stage('Deploy') { + when { + branch 'main' + } + steps { + sh 'make deploy' + } + } + } + } + ``` + + +## ✅ 项目实践 + +### 🔹 嵌入式应用框架设计 + +#### 1. **分层架构** +``` ++----------------------+ +| 应用层 | +| (业务逻辑、算法) | ++----------------------+ +| 服务层 | +| (任务管理、事件) | ++----------------------+ +| 驱动层 | +| (硬件抽象、BSP) | ++----------------------+ +| 硬件层 | +| (MCU、外设) | ++----------------------+ +``` + +#### 2. **组件化设计** +- **核心组件**: + - 任务管理器:负责任务创建、调度和通信。 + - 事件系统:处理异步事件和回调。 + - 配置管理:加载和保存系统配置。 + - 日志系统:分级日志记录和输出。 + +#### 3. **代码结构示例** +``` +project/ +├── app/ # 应用层 +│ ├── main.c # 主程序入口 +│ ├── modules/ # 功能模块 +│ │ ├── sensor/ # 传感器处理 +│ │ ├── comm/ # 通信处理 +│ │ └── control/ # 控制逻辑 +│ └── config/ # 配置文件 +├── services/ # 服务层 +│ ├── task_mgr/ # 任务管理器 +│ ├── event/ # 事件系统 +│ └── utils/ # 工具函数 +├── drivers/ # 驱动层 +│ ├── bsp/ # 板级支持包 +│ ├── hal/ # 硬件抽象层 +│ └── periph/ # 外设驱动 +└── build/ # 构建系统 + ├── cmake/ # CMake配置 + └── Makefile # Makefile +``` + + +### 🔹 通用 BSP 构建 + +#### 1. **设计原则** +- **硬件无关性**:上层代码不直接访问硬件寄存器。 +- **可移植性**:相同功能代码可在不同硬件平台复用。 +- **配置化**:通过配置文件而非修改代码适配不同硬件。 + +#### 2. **BSP 实现示例** +```c +// bsp_led.h +#ifndef BSP_LED_H +#define BSP_LED_H + +#include + +typedef enum { + LED_RED, + LED_GREEN, + LED_BLUE +} led_t; + +typedef enum { + LED_OFF, + LED_ON, + LED_TOGGLE +} led_state_t; + +// 初始化LED +void bsp_led_init(void); + +// 设置LED状态 +void bsp_led_set(led_t led, led_state_t state); + +#endif + +// bsp_led.c (STM32实现) +#include "bsp_led.h" +#include "stm32f4xx_hal.h" + +// LED GPIO定义 +#define LED_RED_PIN GPIO_PIN_14 +#define LED_RED_PORT GPIOG +#define LED_GREEN_PIN GPIO_PIN_13 +#define LED_GREEN_PORT GPIOG +#define LED_BLUE_PIN GPIO_PIN_15 +#define LED_BLUE_PORT GPIOG + +void bsp_led_init(void) { + GPIO_InitTypeDef GPIO_InitStruct = {0}; + + // 使能GPIO时钟 + __HAL_RCC_GPIOG_CLK_ENABLE(); + + // 配置GPIO引脚 + GPIO_InitStruct.Pin = LED_RED_PIN | LED_GREEN_PIN | LED_BLUE_PIN; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(GPIOG, &GPIO_InitStruct); + + // 默认关闭所有LED + HAL_GPIO_WritePin(LED_RED_PORT, LED_RED_PIN, GPIO_PIN_RESET); + HAL_GPIO_WritePin(LED_GREEN_PORT, LED_GREEN_PIN, GPIO_PIN_RESET); + HAL_GPIO_WritePin(LED_BLUE_PORT, LED_BLUE_PIN, GPIO_PIN_RESET); +} + +void bsp_led_set(led_t led, led_state_t state) { + GPIO_TypeDef *port; + uint16_t pin; + + // 根据LED类型选择GPIO + switch (led) { + case LED_RED: + port = LED_RED_PORT; + pin = LED_RED_PIN; + break; + case LED_GREEN: + port = LED_GREEN_PORT; + pin = LED_GREEN_PIN; + break; + case LED_BLUE: + port = LED_BLUE_PORT; + pin = LED_BLUE_PIN; + break; + default: + return; + } + + // 设置LED状态 + switch (state) { + case LED_OFF: + HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET); + break; + case LED_ON: + HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET); + break; + case LED_TOGGLE: + HAL_GPIO_TogglePin(port, pin); + break; + } +} +``` + + +### 🔹 模块化驱动结构 + +#### 1. **驱动分层** +- **硬件层**:直接操作寄存器的低级驱动。 +- **抽象层**:提供统一接口的高级驱动。 +- **适配层**:连接抽象层和硬件层的中间层。 + +#### 2. **SPI驱动示例** +```c +// spi_interface.h (抽象接口) +#ifndef SPI_INTERFACE_H +#define SPI_INTERFACE_H + +#include + +typedef struct { + // 初始化SPI + void (*init)(uint32_t baudrate); + + // 发送数据 + void (*send)(const uint8_t *data, uint32_t length); + + // 接收数据 + void (*receive)(uint8_t *data, uint32_t length); + + // 发送并接收数据 + void (*transfer)(const uint8_t *tx_data, uint8_t *rx_data, uint32_t length); +} spi_interface_t; + +// 获取SPI接口实例 +const spi_interface_t* spi_get_interface(void); + +#endif + +// spi_stm32.c (STM32实现) +#include "spi_interface.h" +#include "stm32f4xx_hal.h" + +static SPI_HandleTypeDef hspi1; + +static void spi_init(uint32_t baudrate) { + // 配置SPI参数 + hspi1.Instance = SPI1; + hspi1.Init.Mode = SPI_MODE_MASTER; + hspi1.Init.Direction = SPI_DIRECTION_2LINES; + hspi1.Init.DataSize = SPI_DATASIZE_8BIT; + hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; + hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; + hspi1.Init.NSS = SPI_NSS_SOFT; + + // 根据波特率计算分频系数 + uint32_t prescaler = SPI_BAUDRATEPRESCALER_2; + if (baudrate < 1000000) prescaler = SPI_BAUDRATEPRESCALER_128; + else if (baudrate < 2000000) prescaler = SPI_BAUDRATEPRESCALER_64; + else if (baudrate < 4000000) prescaler = SPI_BAUDRATEPRESCALER_32; + else if (baudrate < 8000000) prescaler = SPI_BAUDRATEPRESCALER_16; + else if (baudrate < 16000000) prescaler = SPI_BAUDRATEPRESCALER_8; + else if (baudrate < 32000000) prescaler = SPI_BAUDRATEPRESCALER_4; + + hspi1.Init.BaudRatePrescaler = prescaler; + hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi1.Init.TIMode = SPI_TIMODE_DISABLE; + hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + hspi1.Init.CRCPolynomial = 10; + + // 初始化SPI + HAL_SPI_Init(&hspi1); +} + +static void spi_send(const uint8_t *data, uint32_t length) { + HAL_SPI_Transmit(&hspi1, (uint8_t*)data, length, 1000); +} + +static void spi_receive(uint8_t *data, uint32_t length) { + HAL_SPI_Receive(&hspi1, data, length, 1000); +} + +static void spi_transfer(const uint8_t *tx_data, uint8_t *rx_data, uint32_t length) { + HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)tx_data, rx_data, length, 1000); +} + +// SPI接口实现 +static const spi_interface_t spi_impl = { + .init = spi_init, + .send = spi_send, + .receive = spi_receive, + .transfer = spi_transfer +}; + +// 获取SPI接口实例 +const spi_interface_t* spi_get_interface(void) { + return &spi_impl; +} +``` + + +### 🔹 OTA 升级方案设计 + +#### 1. **双分区架构** +``` +Flash布局: ++-------------------+ 0x08000000 +| Bootloader | (80KB) ++-------------------+ 0x08014000 +| Application A | (448KB) ++-------------------+ 0x08084000 +| Application B | (448KB) ++-------------------+ 0x08104000 +| Configuration | (16KB) ++-------------------+ +``` + +#### 2. **OTA状态机** +```c +typedef enum { + OTA_IDLE, // 空闲状态 + OTA_CHECKING, // 检查更新 + OTA_DOWNLOADING, // 下载中 + OTA_DOWNLOAD_PAUSED, // 下载暂停 + OTA_VERIFYING, // 校验中 + OTA_READY, // 准备重启 + OTA_UPGRADING, // 升级中 + OTA_FAILED // 升级失败 +} ota_state_t; + +typedef struct { + ota_state_t state; + uint32_t total_size; + uint32_t downloaded_size; + uint8_t progress; + char error_msg[64]; + uint8_t firmware_hash[32]; +} ota_context_t; +``` + +#### 3. **OTA流程** +1. **检查更新**: + ```c + bool ota_check_update(void) { + // 从服务器获取版本信息 + http_response_t response = http_get(UPDATE_SERVER_URL "/version"); + if (response.status != 200) { + return false; + } + + // 解析服务器版本 + uint32_t server_version = parse_version(response.body); + uint32_t current_version = get_current_version(); + + // 比较版本 + return (server_version > current_version); + } + ``` + +2. **下载固件**: + ```c + void ota_download_firmware(void) { + // 打开固件下载URL + http_client_t client = http_open(UPDATE_SERVER_URL "/firmware.bin"); + if (!client) { + ota_set_state(OTA_FAILED, "Failed to open URL"); + return; + } + + // 获取文件大小 + uint32_t file_size = http_get_content_length(client); + ota_set_total_size(file_size); + + // 开始下载 + uint8_t buffer[512]; + uint32_t bytes_received = 0; + uint32_t bytes_written = 0; + + while ((bytes_received = http_read(client, buffer, 512)) > 0) { + // 写入到备份区 + if (!flash_write(APPLICATION_B_ADDRESS + bytes_written, buffer, bytes_received)) { + ota_set_state(OTA_FAILED, "Flash write failed"); + http_close(client); + return; + } + + bytes_written += bytes_received; + ota_update_progress(bytes_written * 100 / file_size); + + // 检查是否需要暂停 + if (ota_should_pause()) { + http_close(client); + ota_set_state(OTA_DOWNLOAD_PAUSED, "Download paused"); + return; + } + } + + http_close(client); + ota_set_state(OTA_VERIFYING, "Verifying firmware"); + } + ``` + +3. **验证与应用**: + ```c + bool ota_verify_firmware(void) { + // 计算下载固件的哈希值 + uint8_t calculated_hash[32]; + calculate_firmware_hash(APPLICATION_B_ADDRESS, APPLICATION_SIZE, calculated_hash); + + // 与服务器提供的哈希值比较 + if (memcmp(calculated_hash, ota_get_expected_hash(), 32) != 0) { + return false; + } + + // 验证向量表 + uint32_t *vector_table = (uint32_t*)APPLICATION_B_ADDRESS; + if (vector_table[0] == 0 || vector_table[1] == 0) { + return false; + } + + return true; + } + + void ota_apply_update(void) { + // 设置升级标志 + set_update_flag(1); + + // 保存新固件版本 + save_new_version(get_server_version()); + + // 重启系统 + NVIC_SystemReset(); + } + ``` + +# 开发工具链安装指南 +## 1. **IDE推荐** + +### VS Code + PlatformIO + +**官网链接**: +- [VS Code](https://code.visualstudio.com/) +- [PlatformIO](https://platformio.org/) + +**安装步骤**: +1. 下载并安装 [VS Code](https://code.visualstudio.com/Download) +2. 打开VS Code,点击左侧扩展图标(或按 `Ctrl+Shift+X`) +3. 搜索并安装 **PlatformIO IDE** 扩展 +4. 安装完成后,重启VS Code +5. PlatformIO会自动安装所需的工具链和依赖 + +**验证安装**: +打开VS Code,点击左下角的 **PlatformIO Home** 图标,若能正常打开则安装成功。 + + +### STM32CubeIDE + +**官网链接**: +- [STM32CubeIDE](https://www.st.com/en/development-tools/stm32cubeide.html) + +**安装步骤**: +1. 访问官网,点击 **Get Software** 下载对应操作系统的安装包 +2. 运行安装程序,按照向导完成安装 +3. 安装过程中会自动下载并配置STM32CubeMX + +**验证安装**: +启动STM32CubeIDE,创建一个新的STM32项目,若能正常编译则安装成功。 + + +### CLion + +**官网链接**: +- [CLion](https://www.jetbrains.com/clion/) + +**安装步骤**: +1. 下载并安装 [CLion](https://www.jetbrains.com/clion/download/) +2. 安装CMake和MinGW(Windows用户需要): + - CMake:从 [官网](https://cmake.org/download/) 下载并安装 + - MinGW:推荐使用 [MSYS2](https://www.msys2.org/) 安装 + +**验证安装**: +启动CLion,创建一个新的C/C++项目,选择CMake工具链,若能正常编译则安装成功。 + + +## 2. **调试工具** + +### OpenOCD + +**官网链接**: +- [OpenOCD](http://openocd.org/) + +**安装步骤**: +- **Windows**: + 1. 从 [GNU MCU Eclipse](https://github.com/gnu-mcu-eclipse/openocd/releases) 下载预编译二进制包 + 2. 解压到指定目录(如 `C:\openocd`) + 3. 将 `bin` 目录添加到系统环境变量 + +- **Linux**: + ```bash + sudo apt-get install openocd # Ubuntu/Debian + sudo yum install openocd # CentOS/RHEL + ``` + +- **macOS**: + ```bash + brew install open-ocd + ``` + +**验证安装**: +在终端中运行 `openocd --version`,若显示版本信息则安装成功。 + + +### GDB + +**官网链接**: +- [GDB](https://www.gnu.org/software/gdb/) +- [ARM GCC Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm) + +**安装步骤**: +1. 下载并安装 [ARM GCC Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) +2. 将 `bin` 目录添加到系统环境变量 + +**验证安装**: +在终端中运行 `arm-none-eabi-gdb --version`,若显示版本信息则安装成功。 + + +### ST-Link/V2 + +**官网链接**: +- [ST-Link](https://www.st.com/en/development-tools/st-link-v2.html) + +**安装步骤**: +- **Windows**: + 1. 从 [ST官网](https://www.st.com/en/development-tools/stsw-link004.html) 下载并安装ST-Link驱动 + 2. 安装完成后,将ST-Link/V2调试器连接到电脑 + +- **Linux**: + ```bash + sudo apt-get install stlink-tools # Ubuntu/Debian + ``` + +**验证安装**: +在终端中运行 `st-info --version`,若显示版本信息则安装成功。 + + +## 3. **静态代码分析** + +### CppCheck + +**官网链接**: +- [CppCheck](https://cppcheck.sourceforge.io/) + +**安装步骤**: +- **Windows**: + 1. 从 [官网](https://cppcheck.sourceforge.io/) 下载安装包 + 2. 运行安装程序,按照向导完成安装 + +- **Linux**: + ```bash + sudo apt-get install cppcheck # Ubuntu/Debian + sudo yum install cppcheck # CentOS/RHEL + ``` + +- **macOS**: + ```bash + brew install cppcheck + ``` + +**验证安装**: +在终端中运行 `cppcheck --version`,若显示版本信息则安装成功。 + + +### Clang-Tidy + +**官网链接**: +- [Clang-Tidy](https://clang.llvm.org/extra/clang-tidy/) + +**安装步骤**: +- **Windows**: + 1. 安装 [LLVM](https://releases.llvm.org/download.html) + 2. Clang-Tidy会随LLVM一起安装 + +- **Linux**: + ```bash + sudo apt-get install clang-tidy # Ubuntu/Debian + ``` + +- **macOS**: + ```bash + brew install llvm + ``` + +**验证安装**: +在终端中运行 `clang-tidy --version`,若显示版本信息则安装成功。 + + +### SonarQube + +**官网链接**: +- [SonarQube](https://www.sonarqube.org/) + +**安装步骤**: +1. 下载并安装 [Docker](https://www.docker.com/get-started) +2. 运行SonarQube容器: + ```bash + docker run -d --name sonarqube -p 9000:9000 sonarqube + ``` +3. 访问 [http://localhost:9000](http://localhost:9000),使用默认账号(admin/admin)登录 + +**验证安装**: +在浏览器中打开 [http://localhost:9000](http://localhost:9000),若能看到SonarQube界面则安装成功。 + + +## 4. **单元测试** + +### Unity + +**官网链接**: +- [Unity](https://github.com/ThrowTheSwitch/Unity) + +**安装步骤**: +1. 从GitHub下载Unity源码: + ```bash + git clone https://github.com/ThrowTheSwitch/Unity.git + ``` +2. 将 `src` 目录添加到项目的头文件搜索路径 + +**验证安装**: +创建一个简单的测试文件,包含Unity头文件,若能正常编译则安装成功。 + + +### CMock + +**官网链接**: +- [CMock](https://github.com/ThrowTheSwitch/CMock) + +**安装步骤**: +1. 从GitHub下载CMock源码: + ```bash + git clone https://github.com/ThrowTheSwitch/CMock.git + ``` +2. 将 `src` 目录添加到项目的头文件搜索路径 + +**验证安装**: +创建一个简单的测试文件,包含CMock头文件,若能正常编译则安装成功。 + + +### Google Test + +**官网链接**: +- [Google Test](https://github.com/google/googletest) + +**安装步骤**: +1. 从GitHub下载Google Test源码: + ```bash + git clone https://github.com/google/googletest.git + ``` +2. 使用CMake构建并安装: + ```bash + cd googletest + mkdir build + cd build + cmake .. + make + sudo make install + ``` + +**验证安装**: +创建一个简单的测试文件,包含Google Test头文件,若能正常编译则安装成功。 + + +## 📚 资源汇总 + +| **工具** | **官网链接** | **安装指南** | +|------------------|---------------------------------------------|-------------------------------------------| +| VS Code | https://code.visualstudio.com/ | 直接下载安装包 | +| PlatformIO | https://platformio.org/ | VS Code扩展市场安装 | +| STM32CubeIDE | https://www.st.com/en/development-tools/stm32cubeide.html | 官网下载安装包 | +| CLion | https://www.jetbrains.com/clion/ | 官网下载安装包 | +| OpenOCD | http://openocd.org/ | 包管理器或预编译二进制包 | +| GDB | https://www.gnu.org/software/gdb/ | 随ARM GCC Toolchain安装 | +| ST-Link/V2 | https://www.st.com/en/development-tools/st-link-v2.html | 官网下载驱动 | +| CppCheck | https://cppcheck.sourceforge.io/ | 包管理器或安装包 | +| Clang-Tidy | https://clang.llvm.org/extra/clang-tidy/ | 随LLVM安装 | +| SonarQube | https://www.sonarqube.org/ | Docker容器或独立安装 | +| Unity | https://github.com/ThrowTheSwitch/Unity | 从GitHub下载源码 | +| CMock | https://github.com/ThrowTheSwitch/CMock | 从GitHub下载源码 | +| Google Test | https://github.com/google/googletest | CMake构建并安装 |