
简介这是一套基于Visual Studio 2017 64位环境编译完成的VTK 8.2.0库文件包面向需要快速集成三维可视化与数据处理功能的C开发者可避免从源码自行编译的漫长等待。VTK作为开源图形可视化库内置了丰富的渲染管线、数据结构和交互算法。整个rar压缩包约34.39MB内部按include、lib、bin、share目录归类include存放全部头文件lib目录区分Debug和Release提供静态链接库bin目录放置运行所需的dll动态库share则附带部分共享资源。静态库适合生成体积较大但免依赖的可执行程序动态库则利于缩减部署包体积。该资源已有1346人学习下载拿到后只需在VS2017中配置好包含目录、库目录及链接器输入即可直接调用3D建模、图像处理、体绘制等VTK核心能力适合科学计算、工程仿真与可视化应用开发人员作为基础研发工具。1. 不是库不够用VS2017 下重新编译 VTK-8.2.0 的真实需求很多做医学影像、点云可视化或者三维网格处理的人最开始都是直接下载 VTK-8.2.0 的官方预编译包。拿到手以后才发现里面只有动态库和对应的导入库Debug 缺一套静态链接缺一套甚至连自己想要的模块都没被编译进去。等项目跑到 VS2017 的 64 位环境下一旦你需要单步调试 VTK 内部、把某个模块裁剪掉、或者把整个渲染管线以静态库方式嵌入到自己的软件里预编译包就成了一条死路。这个标题想讲的就是完整走一遍用 VS2017 编译 VTK-8.2.0 源码手动生成静态库和动态库把 lib 文件和 dll 文件都握在手里。适合谁已经被 CMake 选项绕晕的 C 开发者被 Release/Debug 混用折磨的老项目维护者以及准备把 VTK 集成进自己产品的架构师。2. 编译前的环境匹配VS2017 与 VTK-8.2.0 的兼容边界2.1 先弄明白为什么不是下载预编译包而是自己编译预编译包不是不好而是它的产物形状是固定的。VTK 官方在 Windows 上默认发布的是 Release 动态库装完以后你会得到一堆 dll、一堆导入 lib、若干头文件以及一个用来被 find_package(VTK) 调用的 VTKConfig.cmake。这套东西对大多数普通开发者是够用的。但当你进入部署阶段问题就来了。第一预编译包没有 Debug 库你想调试 VTK 内部的某个算法时只能停在调用层进不了 VTK 源码第二预编译包几乎都开了所有组生成的 dll 数量巨大释放到用户机器上动不动就是几百 MB对体积敏感的产品根本没法用第三官方构建使用的第三方依赖版本是固定的你想把 VTK 的 IO 模块接到自编译的 TIFF、PNG 或者 HDF5 上预编译包直接不支持。自己编译等于把这些控制权全部拿回来。你可以选择 BUILD_SHARED_LIBS 让 VTK 生成动态库也就是 dll 加少量导入 lib也可以关掉它生成静态库得到一堆体积很大的 .lib 静态库文件。对于 VS2017 用户来说VTK-8.2.0 恰好是支持得比较自然的版本社区里大量的老项目都停在这个组合上。稳定是一方面更重要的是网上可查的踩坑记录足够多。2.2 工具链匹配VS2017 的 MSVC 版本与 CMake 生成器VTK-8.2.0 是 2019 年发布的版本它对 Visual Studio 的支持范围是 2015 到 2019。VS2017 对应的编译器工具集是 MSVC 15.x生成的二进制接口和 VS2015 是二进制兼容的所以如果你机器上只有 VS2017没有任何问题。这里最容易翻车的点不是 VS 版本而是 CMake 生成器。很多人直接在 CMake 里选 “Visual Studio 15 2017”却没有注意后面有没有 Win64 后缀。VTK 是科学计算库绝大多数场景都是 64 位程序如果你生成的是 Win32 工程后续链接任何第三方库都会遇到入口点位数不匹配的问题。正确做法是选择Visual Studio 15 2017 Win64这个生成器代表 x64 平台。另外CMake 版本太低也会很痛苦。VTK-8.2.0 本身要求 CMake 3.5 以上但如果你要用 CMake 的模块依赖管理功能建议直接用 CMake 3.15 之后的版本。太老的 CMake 可能会在读取 VTK 模块描述文件时出现解析错误花很长时间排查才发现是 CMake 版本问题不划算。2.3 源码和依赖准备版本校验与离线环境在开始编译之前先整理好三样东西VTK 源码、CMake、VS2017 的 C 组件。源码我建议从官方 GitLab 打 tag 下载版本号要精确到v8.2.0不要下载 master 分支。master 上的代码可能已经引入了新特性API 和 8.2 不兼容会把你打到怀疑人生。下载完成后把压缩包解压到一个纯英文路径下比如D:/src/VTK-8.2.0整个编译过程中不要出现中文目录名或空格否则 CMake 的很多外部项目文件会因为路径带空格而无法下载。如果你的开发机是离线的需要在有网的机器上提前把依赖准备好。最常见的是 Qt 5如果你不打算用 VTK 的 Qt 窗口交互完全可以在 CMake 里把 Qt 相关组关掉。离线环境下关掉它的成本远远低于尝试手动配置 Qt 路径的成本。还有一个容易漏的东西是vtkSpyDerivedData这类下载型测试数据只要关闭 VTK[bu]ILD_TESTING就不会触发这些数据下载也就不依赖外网了。最后VS2017 的安装包本身也存在离线安装的需求。在线安装器经常装到一半提示下载失败如果你是在内网机器上编译提前准备好离线安装包并勾选“使用 C 的桌面开发”工作负载会省掉后续大量时间。注意这里要确认勾选了 Windows SDK 组件因为 VTK 编译时很多头文件依赖 SDK 里的系统 API。3. 用 CMake 配置 VTK-8.2.0静态库、动态库的选择与参数解析3.1 先定大方向BUILD_SHARED_LIBS 与库文件形态VTK 编译时最核心的开关就是BUILD_SHARED_LIBS。这个变量决定整个 VTK 是生成动态库还是静态库没有中间态而且它会影响所有 VTK 模块的编译形式。把BUILD_SHARED_LIBS设为 ON编译后每个 VTK 模块比如 vtkCommonCore、vtkRenderingOpenGL2都会生成一个 dll 文件同时生成一个导入 lib 文件。这个导入 lib 只在链接时用运行时还需要带上同名的 dll。动态库模式下VTK 内部各模块也是通过 dll 相互引用的所以最终整个 bin 目录里会有几十个甚至上百个 dll这在部署时要整套带走。把BUILD_SHARED_LIBS设为 OFFVTK 的每个模块会编译成一个静态库最终你得到的是大量.lib文件。这种模式下所有 VTK 代码会被直接打进你的可执行文件里运行时不需要再带任何 VTK 的 dll。代价是第一你的 exe 体积会显著增大第二链接时间变长第三VTK 头文件里通过__declspec(dllimport)控制导入导出的部分需要额外处理这就是后面要说的VTK_STATIC宏。我的建议是如果是给内部工具用直接用动态库调试方便如果是做产品交付且你对体积和依赖安装有硬性要求才考虑静态库。不要想当然地认为静态库一定比动态库好Windows 上 VTK 静态库经常因为第三方库的静态运行时配置问题把人折磨疯。3.2 必看的编译选项分组VTK 的 CMake 选项中除了 BUILD_SHARED_LIBS真正值得手动调的其实是下面这几个。第一次编译时不要看到几百个选项就想全部看懂只盯这几项就足够跑通。选项推荐值作用BUILD_SHARED_LIBSON 或 OFF动态库 / 静态库主开关CMAKE_INSTALL_PREFIXD:/Libs/VTK-8.2.0-install最终安装位置也就是头文件、lib、dll 的汇总目录VTK_BUILD_TESTINGOFF关闭测试避免下载 2GB 测试数据VTK_GROUP_ENABLE_QtOFF 或 WANT是否需要 Qt 相关模块不需要就 OFFVTK_GROUP_ENABLE_ViewsWANT2D 视图相关一般默认可留VTK_GROUP_ENABLE_ImagingWANT图像处理模块做医学影像通常需要VTK_GROUP_ENABLE_RenderingWANT渲染必备VTK_BUILD_EXAMPLESOFF关闭样例编译节省大量时间还有两个在高级阶段才用得多的VTK_REQUIRED_OBJCXX_FLAGS和VTK_USE_64BIT_IDS。后者默认是 ON它让 vtkIdType 在 64 位下占 8 字节如果你的数据量不会超过 20 亿个点保持 ON 没毛病改掉它反而会让 VTK 和第三方库的接口错位。VTK_GROUP_ENABLE_QtOFF是我个人比较推荐的初选。VTK-8.2.0 里 Qt 模块需要额外指定 Qt5 安装路径一旦路径匹配不上编译时会出现一堆Qt5::Core找不到的错误。对不依赖 Qt 界面的用户来说关掉它能让整个编译过程从“抽奖”变成“确定”。3.3 命令行配置一套可复现的 CMake 命令用 CMake GUI 点开关更直观但如果你需要多次重配或者想在文档里记录配置命令行方式更可靠。下面这套命令是针对动态库的完整 CMake 配置过程cmake -G Visual Studio 15 2017 Win64 ^ -DCMAKE_INSTALL_PREFIXD:/Libs/VTK-8.2.0-install ^ -DBUILD_SHARED_LIBSON ^ -DVTK_BUILD_TESTINGOFF ^ -DVTK_BUILD_EXAMPLESOFF ^ -DVTK_GROUP_ENABLE_QtOFF ^ -DVTK_GROUP_ENABLE_ViewsWANT ^ -DVTK_GROUP_ENABLE_RenderingWANT ^ -DVTK_GROUP_ENABLE_ImagingWANT ^ -DCMAKE_CONFIGURATION_TYPESRelease;Debug ^ ../VTK-8.2.0这里每个参数背后都有讲究。-G Visual Studio 15 2017 Win64对应的是 VS2017 的 x64 生成器注意是“Win64”不是空配置。-DBUILD_SHARED_LIBSON明确告诉 CMake 生成动态库这样最终产物就是 dll 加导入 lib。VTK_BUILD_TESTINGOFF和VTK_BUILD_EXAMPLESOFF是避免编译时间从 2 小时变成 8 小时的关键。CMAKE_CONFIGURATION_TYPES显式列出 Release 和 Debug这样在 VS 里切换配置时两个配置都会生成不会出现只做了 Release 却找不到 Debug 库的情况。如果你想要静态库只需要把-DBUILD_SHARED_LIBSON改成-DBUILD_SHARED_LIBSOFF其他参数可以不变。但此时要注意输出目录里不再有 dll而是大量直接链接用的 .lib并且这些 .lib 的体积会非常大。3.4 配置后检查CMakeCache.txt 里的关键变量CMake 配置完成后你不需要急着打开 VS。先打开构建目录下的CMakeCache.txt检查三个关键地方。第一个是CMAKE_CXX_COMPILER:STRING它应该指向 VS2017 的 MSVC 编译器路径具体是vcvars64.bat所在的工具集目录。如果这里显示的不是 VS2017而是系统里残留的其他编译器说明 CMake 生成器选错了。第二个是BUILD_SHARED_LIBS:BOOL确认它的值和你预期一致。这个变量在 CMake 配置阶段就被写死后续在 VS 里改是没用的。第三个是CMAKE_INSTALL_PREFIX:PATH确认安装路径存在。很多人最后 INSTALL 的时候报错就是因为忘了创建这个目录或者路径里带了空格。确认完这三个变量再回来看CMakeCache.txt里的VTK_USE_QVTK是否为 0。如果是说明 Qt 相关模块已经被正确关闭。这样你的 CMake 配置阶段就稳定结束了。4. 在 VS2017 中编译生成库ALL_BUILD 到 INSTALL 的完整流程4.1 用 VS2017 打开解决方案并切换 64 位配置CMake 配置成功后构建目录下会生成VTK.sln。用 VS2017 双击打开后第一件事不是直接点生成而是检查配置管理器。在 VS 菜单栏找到“生成 → 配置管理器”确认活动解决方案平台是x64如果不是点下拉框新建一个 x64 平台。这一步对应的是第 2 章里说到的 CMake 生成器选择如果这里显示的是 Win32说明你配置阶段选错了生成器返回去重跑一遍 CMake 吧。然后切换解决方案配置。我强烈建议你先做 Release再做 Debug因为 Release 编译速度快得多先验证整个流程能跑通再花几个小时跑 Debug。如果你在 3.3 里设置了CMAKE_CONFIGURATION_TYPES这里的 Release 和 Debug 都会出现在下拉框里。4.2 编译 ALL_BUILD生成 lib 与 dll 的中间产物解决方案资源管理器里有很多项目最上面的是ALL_BUILD它相当于一个总入口依赖并编译所有启用的 VTK 模块。右键 ALL_BUILD选择“生成”。第一次编译时建议先在 VS 的“工具 → 选项 → 项目和解决方案 → VC 目录”里别乱改保持默认。直接开始生成即可。VTK-8.2.0 全部模块编译下来Release 在一台普通 i7 机器上大概需要 40 到 90 分钟Debug 减半取决于磁盘。期间你会看到输出窗口里不断创建 .dll、.lib、.pdb 文件这些就是你的核心产物。编译完成后到构建目录下的bin\Release或bin\Debug看一下。里面满是 dll 和对应的 pdb而在lib\Release、lib\Debug下则能看到导入 lib 文件。注意 VTK 8.2 在生成文件名上会带版本号比如vtkCommonCore-8.2.dll、vtkCommonCore-8.2.libDebug 下还会多一个字母 d类似vtkCommonCore-8.2d.lib。如果你选择了静态库模式bin 目录下是空的所有 .lib 都在 lib 目录里文件数量比动态库模式还要多。此时不要急着手动拷这些文件让 INSTALL 来做。4.3 执行 INSTALL把头文件、库和 CMake 配置归位ALL_BUILD 生成完还没完。VTK 编译出的产物散落在很多子目录如果直接把这些文件拷到自己的项目里你会漏掉头文件还会漏掉最关键的VTKConfig.cmake。幸运的是 VTK 自带 INSTALL 工程CMake 配置完成后解决方案里有一个名为INSTALL的项目。右键 INSTALL点击“生成”。这个操作会把所有需要的产物复制到你在 3.3 里指定的CMAKE_INSTALL_PREFIX路径下包括include/vtk-8.2/全部头文件lib/cmake/vtk-8.2/各种 VTKConfig.cmake 以及模块目标文件bin/全部 dll动态库模式lib/导入 lib 或静态 lib安装完成后你的对外交付目录就是D:/Libs/VTK-8.2.0-install后续所有项目都只需要引用这个目录不用再碰构建目录。顺便推荐一个习惯INSTALL 完成之后把构建目录整个复制到移动硬盘上或者直接把CMAKE_INSTALL_PREFIX设置到 D 盘。因为 VS 生成文件分散随时可能因清理而误删留下安装目录就等于买了后悔药。4.4 生成物清单哪些文件是你要的哪些不用拷很多人安装完以后对着目录发懵不知道哪些该拷到项目里。这里给你一个清单。自己写 CMake 的find_package(VTK)时只依赖lib/cmake/vtk-8.2下的文件手动配工程时需要include/vtk-8.2的头文件、lib下的 lib 文件、bin下的 dll 文件。特别提醒一点动态库模式下lib目录里的 .lib 是导入库体积通常只有几十 KB别以为那是冗余文件就删掉。链接阶段它负责把你 exe 里的头文件声明和 dll 导出符号对上删了之后链接会报一大堆找不到符号的错误。静态库模式下 lib 目录里才是真正的全部代码体积非常大和动态库模式的导入库完全是两回事。5. VTK 编译避坑与常见问题排查5 个反复踩的坑5.1 静态链接报大量 unresolved external symbol忘定义 VTK_STATIC现象你把BUILD_SHARED_LIBS设为 OFF 编译出了静态库然后在自己的项目里链接结果链接器报几百个unresolved external symbol而且很多符号都是 vtk 开头。原因VTK 头文件里的类声明带有__declspec(dllexport)/__declspec(dllimport)逻辑默认情况下它认为自己被编译成 dll所以对外都是导出声明。当 VTK 被编译成静态库时这些导入导出机制必须被关闭而关闭的开关就是一个叫VTK_STATIC的宏。解决在自己的项目编译选项里加上VTK_STATIC。在 VS 里打开“C/C → 预处理器 → 预处理器定义”添加一个VTK_STATIC条目。如果你用 CMake可以在自己的 CMakeLists 里写target_compile_definitions(vtk_test PRIVATE VTK_STATIC)加完这条重新编译那些 unresolved external symbol 会立刻消失一大半。这是我见过最多人栽跟头的地方因为 VTK 官方文档把这行写得很隐蔽。5.2 Debug 库链接到 Release 工程_ITERATOR_DEBUG_LEVEL 冲突现象你自己的工程是 Release 模式链接了 VTK 的 Debug 静态库编译时突然报错内容里有_ITERATOR_DEBUG_LEVEL不匹配或者static library ... vs ... mismatch。原因MSVC 在 Debug 和 Release 下使用的 STL 实现不同Debug 下_ITERATOR_DEBUG_LEVEL是 2Release 下是 0。静态库模式把 STL 相关符号也编了进去如果你的 exe 是 ReleaseVTK 库是 Debug链接器就会检测到这两个宏不一致直接拒绝链接。解决严格保证 VTK 库的配置和你的工程配置一致。Debug 工程只链接*d.libRelease 工程只链接不带 d 的 lib。在配置 VTK 时我建议直接把CMAKE_CONFIGURATION_TYPES设置为Release;Debug两套都生成避免缺配置时随手乱配。还有一个隐蔽问题如果你的工程使用动态库模式运行时还需要对应的 DLL 带不带调试信息无所谓但 dll 本身必须和 exe 是同一配置否则会出现奇怪的堆损坏。5.3 编译期间 C2086 或内存耗尽并行度与编译选项的真正关系现象VTK 编译到一半VS 突然崩溃或者报一堆 C2086 重复定义错误但并不在同一个文件上。原因这是典型的编译并行度过高导致的编译器崩溃。VTK-8.2.0 的模块很多C 模板实例化严重如果 VS 的 MSBuild 并行项目数开得太大默认是 CPU 核数多个项目同时跑内存占用轻松达到 4GB 以上老一点的机器直接崩。解决右键 ALL_BUILD选择“并行运行的最大数目”把它调到 4 或者 8不要选无穷。同时检查 Windows 虚拟内存设置C 盘至少留 20GB 剩余空间。另外不要在编译的同时开着多个 VS 实例VTK 的中间目录很大磁盘 IO 也会成为瓶颈。5.4 INSTALL 失败权限与路径混淆现象ALL_BUILD 编译成功但右键 INSTALL 生成时立刻报错错误信息通常是“拒绝访问”或者“系统找不到指定的路径”。原因两种常见情况。第一CMAKE_INSTALL_PREFIX设置到了系统盘如C:/Program Files下VS 没有管理员权限无法写入。第二安装路径目录不存在而且该路径的上层目录也不存在CMake 的file(INSTALL)在某些版本下不会自动创建完整多级目录。解决把CMAKE_INSTALL_PREFIX改成用户目录或 D 盘比如D:/Libs/VTK-8.2.0-install。如果你必须安装到 Program Files就右键 VS 选择“以管理员身份运行”然后重新生成 INSTALL。注意改了CMAKE_INSTALL_PREFIX后不要直接在当前 INSTALL 项目上再生成先重新运行 CMake 配置让新的安装路径生效。5.5 生成的 dll 在旧系统上报“无法定位程序输入点 GetSystemTimePreciseAsFileTime”现象你把 VTK 的 dll 和 exe 拷贝到一台旧 Windows 7 或 Windows Server 2008 机器上程序启动时弹窗无法定位程序输入点 GetSystemTimePreciseAsFileTime 于动态链接库 KERNEL32.dll。原因VS2017 默认使用 Windows SDK 10用这个 SDK 编译出的 exe 或 dll在运行时会调用某些 Windows 10 才新有的 API。旧系统里 kernel32 没有这个函数所以动态链接失败。这和使用 VTK 本身无关是你的整个构建链选择的 SDK 版本决定的。解决如果你必须支持旧系统在 VS2017 的工程里把目标 SDK 版本改成8.1同时把平台工具集改成v141_xp对应 Windows XP 支持。对于 VTK 编译你也需要在 CMake 里额外指定这个工具集或者干脆在部署时把需要的 Universal C Runtime 预处理安装到目标机器。这种问题在工业现场特别常见做交付的人一定要提前确认客户系统的版本等到现场弹框就晚了。6. 验证与运行时配置用最小 C 工程确认 lib 和 dll 可用到这里你已经把静态库和动态库都编译出来了下一步是验证它们真的能用。写一个最小 C 工程调用 VTK 的版本接口确认头文件、lib、dll 三者正确匹配。先用 CMake 创建这个验证工程cmake_minimum_required(VERSION 3.10) project(vtk_check) find_package(VTK REQUIRED) include(${VTK_USE_FILE}) add_executable(vtk_check main.cpp) target_link_libraries(vtk_check PRIVATE ${VTK_LIBRARIES})如果你的 VTK 是静态库在target_link_libraries之前加上target_compile_definitions(vtk_check PRIVATE VTK_STATIC)main.cpp 只需要做两件事输出版本号创建一个 VTK 对象。#include vtkVersion.h #include vtkSmartPointer.h #include vtkObject.h #include iostream int main() { std::cout VTK version: VTK_VERSION std::endl; vtkSmartPointervtkObject obj vtkSmartPointervtkObject::New(); std::cout Created object: obj-GetClassName() std::endl; return 0; }配置 CMake 时指定VTK_DIR为你的安装目录下的lib/cmake/vtk-8.2然后生成 VS2017 工程编译运行。如果程序正常输出4.10.0之类的版本号说明链接成功。如果你是动态库模式运行时会提示缺 dll把D:/Libs/VTK-8.2.0-install/bin加入 PATH 环境变量或者在 VS 调试属性里设置“环境”为PATHD:/Libs/VTK-8.2.0-install/bin;%PATH%。最后再教一个检查依赖的办法。用 VS2017 自带的 dumpbin 工具查看一个 VTK dll 依赖了哪些其他 dll在命令行下执行dumpbin /dependents vtkCommonCore-8.2.dll这个命令会打印出这个 dll 导入的所有外部 dll。如果里面出现了不是你预期的系统库说明你的 VTK 模块配置串了。这个方法也能帮你验证发布时到底要带哪些 dll。我自己的习惯是每次编译完 VTK都先跑这个最小验证工程然后立刻把安装目录用压缩软件备份一份。这样后面再配置新项目时直接从备份里取不用再等三个月的编译时间。希望这个套路能让你少走一次弯路也希望你对得起自己等的那一个编译夜晚。本文还有配套的精品资源点击获取