第93章:使用Hunter:集成Hunter包管理器
说实话,C++的包管理一直是个让人头疼的问题。Python有pip,JavaScript有npm,Java有Maven,而我们C++开发者呢?还在手动下载源码、编译、配置路径。我早期做项目时,光折腾第三方库就能耗掉半天时间。后来接触到Hunter,才算是找到了一个比较顺手的解决方案。
Hunter是什么?
Hunter本质上是一个CMake的包管理框架。它基于CPM(CMake Package Manager)发展而来,但功能更完善。说白了,你只需要在CMakeLists.txt里声明依赖,Hunter就会自动帮你下载、编译、链接。
我个人习惯把Hunter看作「C++世界的apt-get」。你想想看,写个hunter_add_package(Boost),Boost库就自动配置好了,多省心。
核心优势:
- 无需手动下载源码包
- 自动处理依赖关系
- 支持版本锁定,保证构建可复现
- 与CMake深度集成,开箱即用
快速上手:第一个Hunter项目
我们先从一个最简单的例子开始。假设你的项目需要用到fmt库(格式化输出库)。
第一步,在项目根目录创建CMakeLists.txt:
cmake_minimum_required(VERSION 3.10)
# 启用Hunter
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.251.tar.gz"
SHA1 "5659b15dc0884d4b03dbd95710e6a1d0d0a9d3e7"
)
project(MyFirstHunterProject LANGUAGES CXX)
# 添加fmt包
hunter_add_package(fmt)
find_package(fmt CONFIG REQUIRED)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE fmt::fmt)
第二步,创建cmake/HunterGate.cmake文件。这个文件可以从Hunter的GitHub仓库下载,也可以直接用我下面这个精简版:
# Copyright (c) 2013-2019, Ruslan Baratov
# 从Hunter官方仓库获取最新版本
# https://raw.githubusercontent.com/cpp-pm/hunter/master/cmake/HunterGate.cmake
第三步,写个简单的main.cpp测试一下:
#include <fmt/core.h>
int main() {
fmt::print("Hello from Hunter!\n");
fmt::print("The answer is {}\n", 42);
return 0;
}
然后执行:
mkdir build && cd build
cmake ..
cmake --build .
./my_app
嗯,这里要注意:第一次构建时,Hunter会下载并编译所有依赖,所以会比较慢。但后续构建就快多了,因为缓存机制会起作用。
Hunter的工作流程
我画了一张图,帮你理解Hunter到底在背后做了什么:
流程其实不复杂:CMake解析你的项目 → HunterGate初始化 → 解析依赖 → 检查本地缓存 → 如果缓存未命中则下载编译 → 最终配置完成。
版本锁定:保证构建可复现
我在项目中遇到过最头疼的事:同事的机器上构建通过,我的机器上就报错。原因往往是第三方库版本不一致。
Hunter通过HunterGate的URL和SHA1来锁定版本。你还可以创建hunter/config.cmake文件来精细控制每个包的版本:
# hunter/config.cmake
hunter_config(fmt VERSION 8.1.1)
hunter_config(spdlog VERSION 1.10.0)
hunter_config(Boost VERSION 1.79.0)
这样团队里所有人都用完全相同的版本,再也不会出现「我这边能编译啊」的尴尬情况。
常用包一览
Hunter支持超过150个常用C++库。我整理了一些高频使用的:
| 包名 | 用途 | Hunter中的名称 |
|---|---|---|
| fmt | 格式化输出 | fmt |
| spdlog | 日志系统 | spdlog |
| Boost | 通用C++库 | Boost |
| nlohmann_json | JSON解析 | nlohmann_json |
| gtest | 单元测试 | GTest |
| OpenCV | 计算机视觉 | OpenCV |
| protobuf | 序列化 | protobuf |
小技巧:如果你不确定某个包在Hunter中的确切名称,可以查看Hunter的官方包列表:https://github.com/cpp-pm/hunter/tree/master/cmake/projects。每个子目录名就是包名。
实际项目中的配置示例
下面是一个更完整的例子,展示了如何在真实项目中使用Hunter:
cmake_minimum_required(VERSION 3.15)
include("cmake/HunterGate.cmake")
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.251.tar.gz"
SHA1 "5659b15dc0884d4b03dbd95710e6a1d0d0a9d3e7"
)
project(MyServer LANGUAGES CXX)
# 设置C++标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 添加依赖
hunter_add_package(spdlog)
hunter_add_package(nlohmann_json)
hunter_add_package(GTest)
find_package(spdlog CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
find_package(GTest CONFIG REQUIRED)
# 添加可执行文件
add_executable(my_server
src/main.cpp
src/server.cpp
src/handler.cpp
)
target_link_libraries(my_server
PRIVATE
spdlog::spdlog
nlohmann_json::nlohmann_json
)
# 添加测试
add_executable(my_tests
tests/test_server.cpp
tests/test_handler.cpp
)
target_link_libraries(my_tests
PRIVATE
GTest::GTest
GTest::Main
spdlog::spdlog
)
enable_testing()
add_test(NAME server_tests COMMAND my_tests)
注意事项:
- HunterGate的URL和SHA1必须匹配,否则会报错
- 第一次构建时网络必须通畅,因为需要下载Hunter框架和所有依赖
- 如果公司网络受限,可以配置代理或搭建本地Hunter缓存服务器
- 不要将
build目录提交到版本控制中
避坑指南
我曾经在一个项目里踩过一个坑:项目用了Hunter,但团队成员分布在不同的网络环境下。有人能正常构建,有人卡在下载步骤。后来我们统一搭建了一个内部的Hunter缓存服务器,才彻底解决这个问题。
另外,如果你发现某个包在Hunter中版本较旧,可以尝试在hunter/config.cmake中指定更新的版本。但要注意,不是所有版本都经过Hunter的完整测试,升级前最好先验证一下。
还有个常见问题:有些包(比如OpenCV)体积很大,编译时间很长。我的建议是,如果只是用OpenCV的某个模块,可以考虑只引入需要的组件,或者使用预编译版本。
总结
Hunter让C++的包管理变得简单多了。你不需要再手动下载源码、配置路径、处理依赖。写一行hunter_add_package,剩下的交给Hunter就好。
我个人觉得,对于中小型项目,Hunter是个非常不错的选择。它没有Conan那么重,也没有纯手动管理那么累。如果你还在为C++的依赖管理发愁,不妨试试Hunter。
公众号:蓝海资料掘金营,微信deep3321