简介:Eigen 3.3.9 是 C++ 领域广泛使用的开源线性代数模板库,面向从事科学计算、图形学、机器学习与物理模拟的开发者,尤其适合需要在项目中高效完成矩阵与向量运算的中高级 C++ 程序员。资源包共 1611 个文件,以 714 个 cpp 源码、469 个 h 头文件、58 个 hh 与 58 个 dox 文档为主,另含 cmake 构建脚本、cu 与 c 示例、txt 说明及少量 py、sh 辅助文件,压缩包约 2.91MB,结构完整便于按模块查阅。目前已有 552 人学习下载。包内提供完整源码、Doxygen API 文档、示例代码与测试用例,覆盖矩阵乘法、逆、行列式、特征值、QR 与 SVD 分解、稀疏矩阵等操作,并展示表达式求值与内存管理机制,可帮助读者快速上手并深入理解库的设计思路,编写高性能、易维护的 C++ 数值代码。
1. 从一次编译失败说起:为什么我锁定了 Eigen 3.3.9
上周帮一个做机器人仿真的朋友排查编译错误,他的 CMake 工程在链接阶段报了一堆undefined reference to Eigen::internal::...,折腾了一下午才发现是系统里同时存在两个 Eigen 版本,头文件路径和库路径对不上。这种问题在 C++ 数值计算项目里太常见了——Eigen 是纯头文件库,看起来“解压就能用”,但版本混装、路径污染、编译器标准不匹配这三件事,随便踩中一个就够你查半天。Eigen 3.3.9 是 3.3 分支的最后一个稳定版,很多老项目、SLAM 框架、控制算法库至今仍然锁死在这个版本上,原因很简单:3.4 之后部分 API 有调整,老代码直接升上去大概率编译不过。如果你正在配一个需要长期维护的工程环境,或者接手了别人的代码仓库,这篇安装笔记就是按“装完能跑、跑完能查”的思路写的,适合刚接触 Eigen 的新手,也适合想理清版本差异的老手。
2. 装前准备:Eigen 3.3.9 的依赖、目录与版本选择
2.1 为什么是 3.3.9 而不是 3.4.x
Eigen 从 3.3 到 3.4 改了不少东西,最典型的是Eigen::aligned_allocator在部分容器里的行为变化,以及Tensor模块的接口调整。很多依赖 Eigen 的第三方库(比如某些版本的 PCL、Ceres Solver)在 CMake 里写死了find_package(Eigen3 3.3 REQUIRED),你装 3.4 它也能找到,但编译时可能因为 API 差异报错。我一般会先看项目根目录的CMakeLists.txt或README,如果里面明确写了Eigen 3.3.x,那就老老实实装 3.3.9,别想着“用新不用旧”。3.3.9 本身是纯头文件,不涉及动态库链接,所以安装过程其实就是把头文件放到编译器能找到的地方,再配一个 CMake 配置文件。
2.2 环境要求与依赖清单
Eigen 3.3.9 对系统要求很低,但有几个点必须提前确认:
| 项目 | 要求 | 说明 |
|---|---|---|
| C++ 标准 | C++11 及以上 | 3.3.9 大量使用 C++11 特性,C++98 编译会报错 |
| 编译器 | GCC 5+ / Clang 3.8+ / MSVC 2015+ | 太老的编译器对constexpr支持不全 |
| CMake | 3.5 及以上 | 用于生成Eigen3Config.cmake |
| 磁盘空间 | 约 20 MB | 纯头文件,解压后不大 |
| 其他依赖 | 无 | 不依赖 BLAS/LAPACK,但你可以手动开启 |
提示:如果你打算用 Eigen 做大规模矩阵运算,建议额外装一个 BLAS 实现(如 OpenBLAS),并在编译时定义
EIGEN_USE_BLAS,性能会有明显提升。但这不是安装 Eigen 本身必须的。
2.3 下载与校验:别从乱七八糟的镜像站拿包
官方发布地址是gitlab.com/libeigen/eigen,但国内直接 clone 可能很慢。我一般会去官方镜像或发行版源里找eigen-3.3.9.tar.gz。下载完先校验 SHA256,避免包损坏导致解压出一堆空文件。常见做法是:
# 下载源码包(以官方 GitLab 归档为例) wget https://gitlab.com/libeigen/eigen/-/archive/3.3.9/eigen-3.3.9.tar.gz # 校验文件完整性,官方页面会提供 SHA256 值 sha256sum eigen-3.3.9.tar.gz # 解压到临时目录 tar -xzf eigen-3.3.9.tar.gz -C /tmpsha256sum的输出要和官方发布页的哈希值一致,不一致就重新下载。解压后你会看到Eigen/、unsupported/、CMakeLists.txt等,这就是全部源码。注意不要直接把这个目录塞进/usr/include,后面我会讲为什么。
3. 三种安装方式:从源码编译到包管理器
3.1 源码编译安装:最稳但最慢
源码安装的好处是路径可控、版本明确。Eigen 3.3.9 用 CMake 构建,步骤不复杂:
# 进入解压后的源码目录 cd /tmp/eigen-3.3.9 # 创建构建目录,保持源码目录干净 mkdir build && cd build # 配置安装前缀,我习惯放到 /usr/local/eigen-3.3.9 cmake .. -DCMAKE_INSTALL_PREFIX=/usr/local/eigen-3.3.9 \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=OFF # 编译并安装(Eigen 是头文件库,编译阶段很快) make installCMAKE_INSTALL_PREFIX决定了头文件最终落在哪,我特意带上版本号,方便以后多版本共存。BUILD_TESTING=OFF跳过测试用例编译,能省几分钟。make install会把Eigen/和unsupported/复制到include/eigen3/下,同时生成share/eigen3/cmake/里的配置文件。装完后检查一下:
ls /usr/local/eigen-3.3.9/include/eigen3/Eigen/Core ls /usr/local/eigen-3.3.9/share/eigen3/cmake/Eigen3Config.cmake两个文件都在,说明安装成功。
3.2 包管理器安装:快但版本可能不对
Ubuntu/Debian 上直接apt install libeigen3-dev最省事,但仓库里的版本通常是 3.4.x 或 3.3.7,不一定是 3.3.9。如果你对版本要求不严格,可以用这个方式:
# 更新包列表并安装 sudo apt update sudo apt install libeigen3-dev # 查看安装的版本 grep -r "EIGEN_WORLD_VERSION" /usr/include/eigen3/Eigen/src/Core/util/Macros.h如果输出是3.3.9那最好,如果是别的版本,而你的项目又必须用 3.3.9,那就得走源码安装。macOS 上brew install eigen默认装最新版,想装 3.3.9 需要手动指定 formula 版本,比较麻烦,我一般直接源码编译。
3.3 手动指定头文件路径:最轻量的“安装”
如果你只是临时用一下,不想动系统目录,可以直接把解压出来的Eigen文件夹放到项目里,然后在编译时用-I指定路径:
# 假设 Eigen 源码在 /opt/eigen-3.3.9 g++ -std=c++11 -I/opt/eigen-3.3.9 my_program.cpp -o my_program这种方式不需要 CMake,也不需要make install,适合快速验证。但缺点是每个项目都要手动写路径,项目多了容易乱。我一般只在写小 demo 时这么干,正式工程还是走 CMake 配置。
4. CMake 配置:让 find_package 正确找到 3.3.9
4.1 设置 Eigen3_DIR 环境变量
源码安装后,CMake 默认不一定能找到你的自定义路径。最直接的办法是在CMakeLists.txt里指定Eigen3_DIR:
# 告诉 CMake 去哪里找 Eigen3Config.cmake set(Eigen3_DIR "/usr/local/eigen-3.3.9/share/eigen3/cmake") # 查找 Eigen3,要求最低版本 3.3 find_package(Eigen3 3.3 REQUIRED NO_MODULE) # 链接头文件目录 include_directories(${EIGEN3_INCLUDE_DIR}) # 或者用 target_link_libraries(Eigen 是头文件库,实际不链接库) add_executable(my_app main.cpp) target_link_libraries(my_app Eigen3::Eigen)NO_MODULE表示只用 CMake 配置文件模式,不走FindEigen3.cmake老模块。Eigen3::Eigen是导入目标,它会自动带上头文件路径和编译定义。如果你在CMakeLists.txt里写死了Eigen3_DIR,换机器时记得改,否则会报Could not find a package configuration file。
4.2 用 CMAKE_PREFIX_PATH 批量指定
不想在每个项目里改CMakeLists.txt,可以在配置时通过命令行传路径:
cmake .. -DCMAKE_PREFIX_PATH="/usr/local/eigen-3.3.9"CMake 会自动在${CMAKE_PREFIX_PATH}/share/eigen3/cmake下找Eigen3Config.cmake。这个方式适合 CI 环境,路径通过环境变量注入,不用改代码。我一般在.bashrc里加一行:
export Eigen3_DIR=/usr/local/eigen-3.3.9/share/eigen3/cmake这样所有新开的终端都能直接用find_package(Eigen3)。
4.3 验证 CMake 是否找对了版本
配置完成后,在CMakeCache.txt里搜Eigen3_DIR和EIGEN3_VERSION:
grep -i eigen CMakeCache.txt输出里应该能看到Eigen3_DIR:PATH=/usr/local/eigen-3.3.9/share/eigen3/cmake和EIGEN3_VERSION:STRING=3.3.9。如果版本不对,说明系统里还有别的 Eigen 路径被优先搜索了,这时候要检查/usr/include/eigen3和/usr/local/include/eigen3是否存在旧版本。
5. 避坑与排查:Eigen 3.3.9 安装常见问题
5.1 编译报错 “Eigen/Core: No such file or directory”
现象:g++或 CMake 编译时提示找不到Eigen/Core。 原因:头文件路径没加对,或者find_package没找到配置文件。 解决:先确认Eigen/Core文件确实存在,然后用-I手动指定路径测试。如果手动指定能过,说明 CMake 配置有问题,检查Eigen3_DIR是否指向share/eigen3/cmake而不是include/eigen3。
5.2 链接时报 “undefined reference to Eigen::internal::...”
现象:编译通过,链接阶段报大量 Eigen 内部符号未定义。 原因:通常是因为混用了不同版本的 Eigen 头文件,或者项目里同时 include 了系统 Eigen 和自定义 Eigen。 解决:用g++ -H或clang -H查看实际包含的头文件路径,确保所有Eigen/都来自同一个版本。清理 CMake 缓存重新配置。
5.3 运行时报 “invalid pointer” 或段错误
现象:程序运行到矩阵运算时崩溃,报free(): invalid pointer。 原因:Eigen 对内存对齐有要求,如果用了std::vector<Eigen::Vector4d>这类容器,需要加Eigen::aligned_allocator。 解决:改成std::vector<Eigen::Vector4d, Eigen::aligned_allocator<Eigen::Vector4d>>,或者用 C++17 的std::vector配合EIGEN_MAX_ALIGN_BYTES=0关闭对齐(不推荐,性能会降)。
5.4 CMake 找到 3.4 版本导致 API 不兼容
现象:find_package(Eigen3 3.3 REQUIRED)成功,但编译时报no member named 'something' in 'Eigen::...'。 原因:系统里装了 3.4,CMake 优先找到了它。 解决:在CMakeLists.txt里加set(Eigen3_DIR "...")强制指定 3.3.9 的配置文件路径,或者用find_package(Eigen3 3.3.9 EXACT REQUIRED)要求精确版本。
5.5 多版本共存时 include 顺序混乱
现象:同一台机器上装了 3.3.9 和 3.4,不同项目编译结果不一致。 原因:/usr/include/eigen3和/usr/local/include/eigen3同时存在,编译器按搜索顺序选。 解决:我一般会把非当前项目的 Eigen 路径从默认搜索路径里移走,或者用-isystem明确指定。更彻底的做法是每个项目用独立的CMAKE_PREFIX_PATH,不依赖系统默认路径。
6. 装完怎么验证:一个最小可跑通的测试用例
装完不验证,等于没装。我习惯写一个最小测试程序,覆盖矩阵乘法、线性求解和 CMake 查找三个环节。先建一个目录eigen_test,里面放两个文件:
// main.cpp #include <iostream> #include <Eigen/Dense> int main() { // 构造两个 3x3 矩阵 Eigen::Matrix3d A; A << 1, 2, 3, 4, 5, 6, 7, 8, 10; Eigen::Vector3d b(1, 2, 3); // 求解 Ax = b Eigen::Vector3d x = A.colPivHouseholderQr().solve(b); std::cout << "Matrix A:\n" << A << std::endl; std::cout << "Vector b:\n" << b << std::endl; std::cout << "Solution x:\n" << x << std::endl; // 验证 Ax - b 是否接近零 std::cout << "Residual: " << (A * x - b).norm() << std::endl; return 0; }# CMakeLists.txt cmake_minimum_required(VERSION 3.5) project(eigen_test) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 指定 Eigen 3.3.9 的配置文件路径 set(Eigen3_DIR "/usr/local/eigen-3.3.9/share/eigen3/cmake") find_package(Eigen3 3.3 REQUIRED NO_MODULE) add_executable(eigen_test main.cpp) target_link_libraries(eigen_test Eigen3::Eigen)编译并运行:
mkdir build && cd build cmake .. make ./eigen_test如果输出里Residual接近1e-15量级,说明 Eigen 安装、CMake 配置、编译链接全部正常。如果Residual很大或者程序崩溃,回头检查第 5 章的排查项。我还会额外确认一下版本:
# 在 main.cpp 里加一行打印版本 std::cout << "Eigen version: " << EIGEN_WORLD_VERSION << "." << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION << std::endl;输出应该是3.3.9。如果不是,说明 CMake 找到的还是别的版本,需要重新检查Eigen3_DIR和系统路径。从那以后我每次装完 Eigen 都强制走一遍这个最小测试,确认版本、路径、运行结果三件事都对得上,才敢往正式项目里接。希望帮到你。
本文还有配套的精品资源,点击获取