Wiki
Third-party library dependency declaration
Existing English translations were reused. 34 current source blocks remain in Simplified Chinese, without triggering paid translation.
本节专门讲第三方库如何安装、如何在 CMake 中查找、如何放到模板的 Third-party dependencies 区块里。
The principle of this template is:
# ========================
# Third-party dependencies
# ========================
find_package(Eigen3 REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PUBLIC
Eigen3::Eigen
)
That is:
- Whoever uses a third-party library writes the
find_package. - Third-party dependencies are centrally placed in this module's
Third-party dependenciessection. - Prefer linking modern CMake targets, such as
Eigen3::EigenandOpenCV::opencv_core. - Do not pile all third-party libraries into the top-level
CMakeLists.txt.
安装命令按系统选择:Linux 使用系统包管理器,Windows 本教程使用 MSYS2 UCRT64。pacman 命令在 UCRT64 终端执行,日常 CMake 命令可以在配置好 PATH 的 PowerShell 中执行。安装同一个库后,两种平台尽量复用下面的 target 写法。
1.find_package Basic syntax
find_package(<PackageName> [version] [REQUIRED] [COMPONENTS components...])
Common notation:
find_package(Eigen3 REQUIRED)
find_package(OpenCV REQUIRED)
find_package(Boost REQUIRED COMPONENTS system filesystem)
find_package(PCL REQUIRED COMPONENTS common io)
Parameter description:
| Parameter | Function |
|---|---|
<PackageName> |
Package name, for example Eigen3、OpenCV |
version |
Required minimum version or exact version |
REQUIRED |
If not found, report an error directly |
COMPONENTS |
Only search for certain components |
1.1.REQUIRED
find_package(Eigen3 REQUIRED)
If Eigen is not found, the CMake configure phase fails directly.
If not written:
find_package(Eigen3)
you need to determine it yourself:
if(Eigen3_FOUND)
target_link_libraries(my_target PUBLIC Eigen3::Eigen)
endif()
In engineering templates, REQUIRED is usually written, because the earlier an error is reported when a dependency is missing, the better.
1.2.COMPONENTS
Libraries such as OpenCV, Boost, and PCL usually have multiple modules.
For example:
find_package(OpenCV REQUIRED COMPONENTS core imgproc highgui)
Indicates that only the following is needed:
opencv_coreopencv_imgprocopencv_highgui
This is clearer than directly importing the entire OpenCV.
2.target_link_libraries dependency visibility in
When linking third-party libraries, also consider PUBLIC、PRIVATE、INTERFACE.
| Keywords | When to use |
|---|---|
PRIVATE |
Third-party libraries are only used in .cpp, and the header file does not expose it |
PUBLIC |
The header file includes third-party library types, and users also need to know about it |
INTERFACE |
The current target does not compile itself, and only propagates downstream |
For example,lib1 if the header file for is just like this:
#pragma once
namespace lib1 {
void run_eigen_vector_example();
}
The header file does not expose Eigen types, then Eigen can use PRIVATE:
target_link_libraries(${PREFIX}_src_lib
PRIVATE
Eigen3::Eigen
)
If the header file is written as:
#pragma once
#include <Eigen/Dense>
namespace lib1 {
Eigen::Vector3d make_vector();
}
At this point, when the downstream includes this header file, the Eigen include path is also required, so PUBLIC should be used:
target_link_libraries(${PREFIX}_src_lib
PUBLIC
Eigen3::Eigen
)
This template example uses PUBLIC to demonstrate dependency propagation; in actual projects, the choice can be made based on whether the header file exposes third-party types.
3.Eigen3
Eigen is a commonly used linear algebra library, mainly a header-only library.
3.1.Install
Ubuntu/Debian:
sudo apt install libeigen3-dev
Fedora:
sudo dnf install eigen3-devel
Windows,MSYS2 UCRT64:
pacman -S --needed mingw-w64-ucrt-x86_64-eigen3
软件包信息见 MSYS2 官方包页面。
Eigen 是头文件库,重点是让 CMake 找到头文件和 Eigen3Config.cmake。自行安装时,设置安装前缀 CMAKE_PREFIX_PATH,或把 Eigen3_DIR 指向配置文件目录;不需要为 GCC 和 MSVC 分别编译一份 Eigen。
3.2.CMake syntax
# ========================
# Third-party dependencies
# ========================
find_package(Eigen3 REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PUBLIC
Eigen3::Eigen
)
3.3.C++ Use
#include <Eigen/Dense>
Eigen::Vector3d v(1.0, 2.0, 3.0);
3.4.Visibility Recommendations
| 场景 | 链接方式 |
|---|---|
Eigen 只在 .cpp 中使用 |
PRIVATE Eigen3::Eigen |
头文件暴露 Eigen::Matrix、Eigen::Vector |
PUBLIC Eigen3::Eigen |
4.OpenCV4
OpenCV is a computer vision library with many modules; it is recommended to include it by component.
4.1.Install
Ubuntu/Debian:
sudo apt install libopencv-dev
Fedora:
sudo dnf install opencv-devel
4.2.Common components
| 组件 | 作用 |
|---|---|
core |
基础数据结构,例如 cv::Mat |
imgproc |
图像处理 |
imgcodecs |
读写图片 |
highgui |
简单窗口显示 |
videoio |
摄像头和视频读写 |
calib3d |
相机标定、几何 |
features2d |
特征点 |
dnn |
DNN 推理模块 |
Windows,MSYS2 UCRT64:
pacman -S --needed mingw-w64-ucrt-x86_64-opencv
软件包信息见 MSYS2 官方包页面。
MSYS2 软件包随仓库更新,不保证一直提供同一个 OpenCV 主版本。本节的 API 示例沿用 OpenCV 4 的用法;如果项目明确要求 4.x,应安装相应版本并检查 CMake 的版本要求。还要确认下载的 Windows 二进制库是否适合当前 MinGW 工具链,不能直接假定其他编译器生成的库可混用。
4.3.CMake style: recommended by component
# ========================
# Third-party dependencies
# ========================
find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs highgui)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
opencv_core
opencv_imgproc
opencv_imgcodecs
opencv_highgui
)
Some OpenCV installations provide the OpenCV::opencv_core imported target, so you can also write:
target_link_libraries(${PREFIX}_src_lib
PRIVATE
OpenCV::opencv_core
OpenCV::opencv_imgproc
OpenCV::opencv_imgcodecs
OpenCV::opencv_highgui
)
If your system does not have these OpenCV:: targets, use the previous opencv_core syntax.
4.4.CMake syntax: the simple and brutal version
find_package(OpenCV REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
${OpenCV_LIBS}
)
This approach works, but it is less clear than the component-based approach. For template teaching, it is recommended to prioritize writing it as components.
4.5.C++ Use
#include <opencv2/opencv.hpp>
cv::Mat image = cv::imread("test.png");
5.Boost
Boost is a large collection of C++ libraries. Here, system and filesystem are used as examples.
5.1.Install
Ubuntu/Debian:
sudo apt install libboost-all-dev
Fedora:
sudo dnf install boost-devel
If you only want to install a small number of components, Ubuntu/Debian can also be installed as needed, similar to:
sudo apt install libboost-system-dev libboost-filesystem-dev
Windows,MSYS2 UCRT64:
pacman -S --needed mingw-w64-ucrt-x86_64-boost
软件包信息见 MSYS2 官方包页面。
5.2.CMake syntax
# ========================
# Third-party dependencies
# ========================
find_package(Boost REQUIRED COMPONENTS system filesystem)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
Boost::system
Boost::filesystem
)
5.3.C++ Use
#include <boost/filesystem.hpp>
boost::filesystem::path p{"."};
Note: If using C++17's std::filesystem many scenarios no longer require Boost.Filesystem.
6.PCL
PCL is the Point Cloud Library, commonly used in robotics, 3D perception, and SLAM projects.
6.1.Install
Ubuntu/Debian:
sudo apt install libpcl-dev
Fedora:
sudo dnf install pcl-devel
6.2.Common components
| Component | Function |
|---|---|
common |
Point types, basic tools |
io |
PCD/PLY and other file reading and writing |
filters |
Filtering |
features |
Features |
registration |
Registration |
segmentation |
Segmentation |
visualization |
Visualization |
Windows:
PCL 的依赖较多,先确认是否有适合当前 MinGW-w64 / UCRT64 工具链的安装方式。可以在 UCRT64 中搜索:
pacman -Ss pcl
按搜索结果确认仓库、架构和实际包名,再决定是否安装;没有合适的包时,需要用匹配的工具链构建 PCL 及相关依赖。不要把某个 MSVC 预编译安装包直接当成 MinGW 库使用。源码构建的基本要求见 PCL 官方 Windows 构建说明,其中的编译器示例也要结合当前工具链判断。
6.3.CMake syntax
# ========================
# Third-party dependencies
# ========================
find_package(PCL REQUIRED COMPONENTS common io filters)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
${PCL_LIBRARIES}
)
target_include_directories(${PREFIX}_src_lib
PRIVATE
${PCL_INCLUDE_DIRS}
)
target_compile_definitions(${PREFIX}_src_lib
PRIVATE
${PCL_DEFINITIONS}
)
Some PCL versions also provide imported targets. If your environment supports it, you can preferentially use something like:
target_link_libraries(${PREFIX}_src_lib
PRIVATE
PCL::common
PCL::io
PCL::filters
)
The actual choice is subject to the result provided by your local find_package(PCL ...).
7.fmt
fmt is a formatted output library, C++20 std::format style also comes from it.
7.1.Install
Ubuntu/Debian:
sudo apt install libfmt-dev
Fedora:
sudo dnf install fmt-devel
Windows,MSYS2 UCRT64:
pacman -S --needed mingw-w64-ucrt-x86_64-fmt
软件包信息见 MSYS2 官方包页面。
7.2.CMake syntax
# ========================
# Third-party dependencies
# ========================
find_package(fmt REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
fmt::fmt
)
7.3.C++ Use
#include <fmt/core.h>
auto s = fmt::format("value = {}", 42);
8.spdlog
spdlog is a commonly used logging library.
8.1.Install
Ubuntu/Debian:
sudo apt install libspdlog-dev
Fedora:
sudo dnf install spdlog-devel
Windows,MSYS2 UCRT64:
pacman -S --needed mingw-w64-ucrt-x86_64-spdlog
软件包信息见 MSYS2 官方包页面。
8.2.CMake syntax
# ========================
# Third-party dependencies
# ========================
find_package(spdlog REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
spdlog::spdlog
)
8.3.C++ Use
#include <spdlog/spdlog.h>
spdlog::info("hello {}", "spdlog");
9.yaml-cpp
yaml-cpp Commonly used to read configuration files.
9.1.Install
Ubuntu/Debian:
sudo apt install libyaml-cpp-dev
Fedora:
sudo dnf install yaml-cpp-devel
Windows,MSYS2 UCRT64:
pacman -S --needed mingw-w64-ucrt-x86_64-yaml-cpp
软件包信息见 MSYS2 官方包页面。
9.2.CMake syntax
# ========================
# Third-party dependencies
# ========================
find_package(yaml-cpp REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
yaml-cpp::yaml-cpp
)
In some old environments, the target name may be yaml-cpp. If yaml-cpp::yaml-cpp does not exist, adjust again based on the error.
10.nlohmann_json
nlohmann_json is a commonly used JSON library, usually a header-only library.
10.1.Install
Ubuntu/Debian:
sudo apt install nlohmann-json3-dev
Fedora:
sudo dnf install json-devel
Windows,MSYS2 UCRT64:
pacman -S --needed mingw-w64-ucrt-x86_64-nlohmann-json
软件包信息见 MSYS2 官方包页面。
10.2.CMake syntax
# ========================
# Third-party dependencies
# ========================
find_package(nlohmann_json REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
nlohmann_json::nlohmann_json
)
10.3.C++ Use
#include <nlohmann/json.hpp>
nlohmann::json data;
data["name"] = "cmake_template";
11.Threads
C++ 标准线程库通常不需要安装额外包,但链接时建议用 CMake 的 Threads 包。
11.1.Install
Generally, it does not need to be installed separately.
If the compiler toolchain is missing:
Ubuntu/Debian:
sudo apt install build-essential
Fedora:
sudo dnf install gcc gcc-c++ make
11.2.CMake syntax
# ========================
# Third-party dependencies
# ========================
find_package(Threads REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
Threads::Threads
)
11.3.C++ Use
#include <thread>
std::thread worker([] {
// do work
});
worker.join();
12.OpenMP
OpenMP is used for multithreaded parallel computing.
12.1.Install
Ubuntu/Debian:
sudo apt install libomp-dev
Fedora:
sudo dnf install libgomp
12.2.CMake syntax
# ========================
# Third-party dependencies
# ========================
find_package(OpenMP REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
OpenMP::OpenMP_CXX
)
12.3.C++ Use
#include <omp.h>
#pragma omp parallel for
for (int i = 0; i < 100; ++i) {
// parallel work
}
13.Sophus
Sophus is a Lie group and Lie algebra library, commonly used in SLAM and robot pose computation.
13.1.Install
Many distribution repositories do not necessarily provide a suitable version; a common practice is to install from source, or rely on ROS / project dependency management.
If provided by the system repository, you can try searching:
apt search sophus
dnf search sophus
13.2.CMake syntax
If it is already installed and a CMake config is provided:
# ========================
# Third-party dependencies
# ========================
find_package(Sophus REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PRIVATE
Sophus::Sophus
)
Sophus often depends on Eigen. If your code also directly uses Eigen, you can also explicitly write:
find_package(Eigen3 REQUIRED)
find_package(Sophus REQUIRED)
target_link_libraries(${PREFIX}_src_lib
PUBLIC
Eigen3::Eigen
PRIVATE
Sophus::Sophus
)
14.Common Dependencies Quick Reference
| library | Ubuntu/Debian | Fedora | CMake find | Common link targets |
|---|---|---|---|---|
| Eigen3 | libeigen3-dev |
eigen3-devel |
find_package(Eigen3 REQUIRED) |
Eigen3::Eigen |
| OpenCV | libopencv-dev |
opencv-devel |
find_package(OpenCV REQUIRED COMPONENTS ...) |
opencv_core etc. |
| Boost | libboost-all-dev |
boost-devel |
find_package(Boost REQUIRED COMPONENTS ...) |
Boost::system etc. |
| PCL | libpcl-dev |
pcl-devel |
find_package(PCL REQUIRED COMPONENTS ...) |
${PCL_LIBRARIES} or PCL::common |
| fmt | libfmt-dev |
fmt-devel |
find_package(fmt REQUIRED) |
fmt::fmt |
| spdlog | libspdlog-dev |
spdlog-devel |
find_package(spdlog REQUIRED) |
spdlog::spdlog |
| yaml-cpp | libyaml-cpp-dev |
yaml-cpp-devel |
find_package(yaml-cpp REQUIRED) |
yaml-cpp::yaml-cpp |
| nlohmann_json | nlohmann-json3-dev |
json-devel |
find_package(nlohmann_json REQUIRED) |
nlohmann_json::nlohmann_json |
| Threads | Usually no separate installation is required | Usually no separate installation is required | find_package(Threads REQUIRED) |
Threads::Threads |
| OpenMP | libomp-dev |
libgomp |
find_package(OpenMP REQUIRED) |
OpenMP::OpenMP_CXX |
Package names may differ slightly across distributions and versions. If installation fails, first use:
apt search <关键字>
dnf search <关键字>
Confirm the package name.
14.1.Windows 常用安装包
在 UCRT64 终端中使用下表的软件包名称。具体版本以对应官方包页面为准。
| 库 | UCRT64 软件包 |
|---|---|
| Eigen | mingw-w64-ucrt-x86_64-eigen3 |
| OpenCV | mingw-w64-ucrt-x86_64-opencv |
| Boost | mingw-w64-ucrt-x86_64-boost |
| fmt | mingw-w64-ucrt-x86_64-fmt |
| spdlog | mingw-w64-ucrt-x86_64-spdlog |
| yaml-cpp | mingw-w64-ucrt-x86_64-yaml-cpp |
| nlohmann_json | mingw-w64-ucrt-x86_64-nlohmann-json |
Threads 优先使用工具链自带支持和 Threads::Threads。GCC 的 OpenMP 支持通常随工具链安装,先用 find_package(OpenMP) 检查;安装后还要验证 OpenMP 运行环境。PCL、Sophus 等按具体依赖和工具链单独确认,不在这里假设存在某个安装包。
15.A module imports both Eigen and OpenCV at the same time
For example lib1 Use Eigen and OpenCV together:
# ========================
# Third-party dependencies
# ========================
find_package(Eigen3 REQUIRED)
find_package(OpenCV REQUIRED COMPONENTS core imgproc imgcodecs)
target_link_libraries(${PREFIX}_src_lib
PUBLIC
Eigen3::Eigen
PRIVATE
opencv_core
opencv_imgproc
opencv_imgcodecs
)
如果头文件不暴露 Eigen 类型,也可以把 Eigen 改成 PRIVATE:
target_link_libraries(${PREFIX}_src_lib
PRIVATE
Eigen3::Eigen
opencv_core
opencv_imgproc
opencv_imgcodecs
)
16.Not recommended approach
16.1.Not recommended: Looking up all libraries centrally at the top level
# 顶层 CMakeLists.txt
find_package(Eigen3 REQUIRED)
find_package(OpenCV REQUIRED)
find_package(PCL REQUIRED)
Question:
- The upper layers are becoming increasingly chaotic.
- It is unclear which module actually uses which library.
- When deleting a module, it is easy to miss deleting dependencies.
- When newcomers read the project, the dependency relationships are unclear.
16.2.Not recommended: global include
include_directories(${OpenCV_INCLUDE_DIRS})
link_libraries(${OpenCV_LIBS})
Question:
- Affects all targets.
- Dependency relationships are unclear.
- May introduce unexpected include order issues.
Modern CMake recommends:
target_link_libraries(my_target
PRIVATE
opencv_core
)
If the library provides an imported target, the include paths and linked libraries will automatically propagate with the target.
17.Troubleshoot find_package Library not found
17.1.Step 1: Confirm whether the system package is installed
dpkg -l | grep eigen
rpm -qa | grep eigen
17.2.Step 2: Confirm that CMake can see the config file
Common file names:
Eigen3Config.cmake
OpenCVConfig.cmake
PCLConfig.cmake
fmtConfig.cmake
17.3.Step 3: Manually specify the search path
If the library is installed in a non-standard directory, you can add this when running configure:
cmake --preset linux-debug -DCMAKE_PREFIX_PATH=/opt/some_library
Or add it in the preset:
"CMAKE_PREFIX_PATH": "/opt/some_library"
Multiple paths can be separated by semicolons:
"CMAKE_PREFIX_PATH": "/opt/lib_a;/opt/lib_b"
17.4.Step 4: Check the CMake error information
CMake usually tells you which config file is missing, for example:
Could not find a package configuration file provided by "OpenCV"
In this case, prioritize checking:
- Whether the development package is installed.
- Whether the package name is correct.
- Whether it is installed to a non-standard path.
18.Windows 的查找路径和运行环境
已经安装库但 CMake 仍然找不到时,可以在 PowerShell 中指定安装前缀:
$env:CMAKE_PREFIX_PATH = "C:/deps/eigen;C:/deps/opencv"
cmake --preset windows-debug
这里填安装根目录,多个 Windows 前缀用分号分隔。也可以使用本地 CMakeUserPresets.json 保存这些路径。项目包配置仍应优先提供可复用的 imported target。
find_package 成功后,还要实际运行程序。开发时可以把依赖的 bin/ 加入 PATH;验证安装结果时,按所用第三方库的安装要求准备运行环境。
模板只处理自己的目标和常用 GCC 运行库。添加新的第三方依赖后,还要补齐相应安装步骤,并检查安装后的程序能否运行。