Skip to Main Content
CMake Lib Manager Back to Top

CMake Lib Manager

5 minutes

C++ 第三方类库本地管理

面向本机(macOS / Homebrew / vcpkg)的三种主流方式:

  1. 系统包管理器(Homebrew、vcpkg)
  2. 仅有源码:CPM / FetchContent
  3. Git submodule

原则:钉版本、可复现、优先项目内声明依赖,少往 /usr/local 全局乱装。


0. 本机路径速查

用途路径
Homebrew 前缀/opt/homebrew
vcpkg 根目录$HOME/vcpkg(即 /Users/songhoujin/vcpkg
vcpkg 安装前缀(给 CMake 用)$HOME/vcpkg/installed/arm64-osx
vcpkg 构建暂存$HOME/vcpkg/packages/<pkg>_arm64-osx
vcpkg toolchain$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake
归档工具AR=/usr/bin/ar(勿用 binutils 的 GNU ar
HTTP 代理(Clash)http://127.0.0.1:17890http_proxy/https_proxy/all_proxy 均用 http://,勿对 17890 使用 socks5://
export AR=/usr/bin/ar
export VCPKG_ROOT=$HOME/vcpkg
export http_proxy=http://127.0.0.1:17890
export https_proxy=http://127.0.0.1:17890
export HTTP_PROXY=$http_proxy HTTPS_PROXY=$https_proxy
export all_proxy=http://127.0.0.1:17890 ALL_PROXY=$all_proxy

1. 系统包管理器:Homebrew / vcpkg

有 formula / port 时优先用包管理器:多项目共用、升级清晰、find_package 友好。

1.1 Homebrew

brew install fmt ftxui entt
brew --prefix fmt          # 查看单包前缀
ls "$(brew --prefix)/lib/cmake"

CMake 使用:

cmake -S . -B build -DCMAKE_PREFIX_PATH="$(brew --prefix)"
cmake --build build
cmake_minimum_required(VERSION 3.20)
project(demo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)

find_package(fmt CONFIG REQUIRED)
add_executable(demo main.cpp)
target_link_libraries(demo PRIVATE fmt::fmt)

安装位置: /opt/homebrew/{include,lib,lib/cmake,share}(Apple Silicon)。

1.2 vcpkg

export AR=/usr/bin/ar VCPKG_ROOT=$HOME/vcpkg
# 代理见上文;确认:env | grep -i proxy 中不应出现 socks5://127.0.0.1:17890

vcpkg install libassert unordered-dense mp-units
vcpkg list

CMake 使用(推荐带 toolchain):

cmake -S . -B build \
  -DCMAKE_TOOLCHAIN_FILE=$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build build
cmake_minimum_required(VERSION 3.20)
project(demo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)

find_package(libassert CONFIG REQUIRED)
add_executable(demo main.cpp)
target_link_libraries(demo PRIVATE libassert::assert)

安装位置:

1.3 何时用 brew、何时用 vcpkg

情况建议
有 brew formula,且要系统级共用Homebrew
无 brew / 要与 CMake 深度集成 / 钉 tripletvcpkg
macOS 预发布导致 bottle 异常可改 vcpkg,或 brew install --build-from-source(视公式而定)

2. 仅有源码:CPM / FetchContent

无 brew、无 vcpkg port(或故意跟 git)时,在 本项目 CMake 里拉取源码。默认只进当前 build/,不污染系统。

典型库:NVIDIA/stdexecalibaba/yalantinglibs 等。

2.1 原生 FetchContent

cmake_minimum_required(VERSION 3.24)
project(demo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)

include(FetchContent)
FetchContent_Declare(
  stdexec
  GIT_REPOSITORY https://github.com/NVIDIA/stdexec.git
  GIT_TAG        <钉死的 tag 或 commit>   # 勿长期裸追 main
)
FetchContent_MakeAvailable(stdexec)

add_executable(demo main.cpp)
target_link_libraries(demo PRIVATE STDEXEC::stdexec)  # 目标名以该库文档为准

落盘位置(配置后):

路径内容
build/_deps/<name>-src/下载的源码
build/_deps/<name>-build/该依赖的构建目录
build/_deps/<name>-subbuild/下载用子工程

删除 build/ 即清除缓存;换机器需重新 cmake -B build(需能访问 Git 仓库)。

2.2 CPM.cmake(推荐封装)

一次引入 CPM,之后一行加依赖:

mkdir -p cmake
curl -fsSL -o cmake/CPM.cmake \
  https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/CPM.cmake
cmake_minimum_required(VERSION 3.24)
project(demo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)

include(cmake/CPM.cmake)

# 形式:gh:owner/repo#tag_or_commit
CPMAddPackage("gh:NVIDIA/stdexec#<钉死的版本>")

add_executable(demo main.cpp)
target_link_libraries(demo PRIVATE STDEXEC::stdexec)

CPM 仍基于 FetchContent,缓存同样在 build/_deps/(也可设 CPM_SOURCE_CACHE 指向如 $HOME/.cache/CPM 跨项目复用下载)。

cmake -S . -B build -DCPM_SOURCE_CACHE=$HOME/.cache/CPM
cmake --build build

2.3 可选:安装到用户前缀(多玩具项目共用)

cmake -S /path/to/stdexec -B /tmp/stdexec-build \
  -DCMAKE_INSTALL_PREFIX=$HOME/.local \
  -DCMAKE_BUILD_TYPE=Release
cmake --build /tmp/stdexec-build
cmake --install /tmp/stdexec-build
# 其它项目:
cmake -S . -B build -DCMAKE_PREFIX_PATH=$HOME/.local

落盘: $HOME/.local/{include,lib,lib/cmake}。正式项目仍更推荐 FetchContent/CPM 钉在仓库内。


3. Git submodule

需要源码进仓库、可审计、可离线构建时使用。

3.1 添加与更新

cd /path/to/your-project
git submodule add https://github.com/NVIDIA/stdexec.git third_party/stdexec
# 钉到具体提交
cd third_party/stdexec && git checkout <commit> && cd -
git add third_party/stdexec
git commit -m "Pin stdexec to <commit>"

# 新克隆机器:
git clone --recurse-submodules <your-repo-url>
# 或已克隆后:
git submodule update --init --recursive

3.2 CMake 接入

cmake_minimum_required(VERSION 3.20)
project(demo LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)

add_subdirectory(third_party/stdexec)

add_executable(demo main.cpp)
target_link_libraries(demo PRIVATE STDEXEC::stdexec)

若上游不是「可 add_subdirectory 的 CMake 工程」,可改为:

target_include_directories(demo PRIVATE third_party/some_header_only/include)

3.3 落盘位置

路径内容
<项目>/third_party/<库>/源码(随 submodule 提交指针版本)
build/你自己工程的构建树(依赖若被 add_subdirectory,对象文件也在 build 里)

4. 三种方式怎么选

场景
有 brew / vcpkg,多项目共用§1 包管理器
无发行包、跟上游、单项目§2 CPM / FetchContent
要进 git、审计、离线 CI§3 submodule
仅本机随便玩$HOME/.local~/src/...(非正式)

共同要求:


5. 最小可粘贴工程骨架

myapp/
  CMakeLists.txt
  cmake/CPM.cmake          # 若用 CPM
  third_party/...          # 若用 submodule
  src/main.cpp

CMakeLists.txt 混合示例(包管理器 + CPM):

cmake_minimum_required(VERSION 3.24)
project(myapp LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)

# 来自 brew / vcpkg(需 CMAKE_PREFIX_PATH 或 vcpkg toolchain)
find_package(fmt CONFIG REQUIRED)

# 仅有源码
include(cmake/CPM.cmake)
CPMAddPackage("gh:NVIDIA/stdexec#<version>")

add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE fmt::fmt STDEXEC::stdexec)

配置示例:

# 只用 brew
cmake -S . -B build -DCMAKE_PREFIX_PATH="$(brew --prefix)"

# 只用 vcpkg
cmake -S . -B build \
  -DCMAKE_TOOLCHAIN_FILE=$HOME/vcpkg/scripts/buildsystems/vcpkg.cmake

# brew + vcpkg 同时找包时,toolchain + PREFIX 可一起设(注意别重复链接同一库的两套)

6. 排错速记

现象处理
vcpkg curl 35 / SSL timeout检查代理:all_proxy 勿对 Clash HTTP 口用 socks5://;统一 http://127.0.0.1:17890
vcpkg archive member '/' not a mach-oexport AR=/usr/bin/ar,并从 PATH 去掉 binutilsar
find_package 找不到CMAKE_TOOLCHAIN_FILE / CMAKE_PREFIX_PATH;vcpkg 用 installed/arm64-osx 而非 packages/
FetchContent 每次重下CPM_SOURCE_CACHE,或改用 submodule

文档用途:本机第三方 C++ 库管理备忘。可按项目需要删减示例中的库名与版本钉点。