十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ITK与VTK的Windows源码编译:VS2019生成Debug/Release SDK全流程

ITK与VTK的Windows源码编译:VS2019生成Debug/Release SDK全流程 简介本资源是面向医学图像处理开发者与科研人员的ITK-VTK联合开发SDK包专为解决最新算法库编译门槛高、环境配置复杂等痛点而设计适用于需在VS2019中快速开展图像分割、配准及3D可视化二次开发的中高级用户。压缩包共2000个文件140.1MB主体为1998个头文件.h涵盖ITK5.3.0核心算法模块与VTK9.3.1接口定义另含2个说明文档.md完整组织了x64平台下Debug/Release双版本的库结构、CMake配置支持及跨模块依赖关系便于直接集成至新项目或调试已有代码。目前已有265人学习下载可免去耗时数日的源码编译与链接排错过程开箱即用同时配套详细编译博客含CMake选项配置、VTK集成要点、常见LNK2019错误解析助力用户深入理解构建逻辑并实现定制化扩展。 最近正好有朋友在折腾医学图像处理相关的开发问到我一个特别实际的问题ITK和VTK这两个库怎么在Windows下用VS2019编译出一套能直接用的SDK而且要同时带debug和release两份结果。说实话这个活儿听起来简单实际做起来能劝退不少人。ITK 5.3.0和VTK 9.3.1都不是小体量的项目源码编译一次少说几十分钟多则两三个小时加上debug和release双版本都得过一遍整个过程有没有摸清门道体验完全是两回事。这还不算中间碰到的CMake配置坑、依赖库缺失、路径带空格导致诡异报错这些幺蛾子。这篇就把我实测过的一条完整路线写出来从源码下载、CMake配置、MSBuild编译到打包成SDK附带一路踩过的坑和排查思路。无论你是要做医学影像分割配准、三维可视化还是想在现有项目里集成这两个库做开发照着这份流程走一遍结果就是一份直接可以用的x64版SDK。1. 为什么非要自己编译这套SDK1.1 官方预编译包和源码编译的取舍先说一个很多人没搞清楚的问题ITK和VTK官方其实都提供预编译的二进制包但不是所有人都适合直接用。ITK官方发布的预编译版通常只覆盖基础功能而且历史上有段时间Windows版本的二进制包更新并不算及时导致你拿到手的版本可能比自己想要的旧不少或者缺少某些非默认模块。VTK的情况类似官方主要提供面向Python的wheel包C层面的SDK更多是靠用户自己构建或者第三方社区分享。说到第三方分享的编译包问题就更多了。不知道你注意过没有网上流传的ITKVTK编译包很多是几个版本以前的东西要么没有debug版本要么编译时用的编译器和你手上的VS版本不匹配。一旦链接阶段碰上运行库不一致那一堆LNK2038、LNK2005报错会让你怀疑人生。综合看下来自己动手编译虽然不是最省事的路却是最可控、最不会在关键时候掉链子的路。自己编译一次后续不管开发调试还是交付部署心里都有底出了问题也知道根源在哪。1.2 Debug和Release双版本为什么必不可少这可能是整篇里最值得先讲清楚的一件事。很多人第一次编译SDK时只编一个Release版本觉得够用了直到写代码调bug时才发现麻烦大了。正常开发流程里你要在VS里断点调试需要一个带调试符号的debug库。Release库在优化过的情况下变量被内联、函数被重排断点落不到你期望的位置变量面板里全是optimized away那种体验基本等于盲人摸象。反过来如果你把debug版程序去链release库编译器会直接拒绝因为运行库模式对不上宏定义也对不上。所以一份真正能支撑日常开发的SDK必须同时包含debug和release两份库文件。这也是我这次强调x64位下的debugrelease编辑结果的原因——没有双版本后面开发调试寸步难行。2. 编译前的准备与版本选型2.1 工具链和依赖清单动手编译之前先把环境准备清单过一遍。我用的是下面这套组合实测下来兼容性没问题Visual Studio 201916.x版本都可以需要安装使用C的桌面开发工作负载以及Windows 10 SDK组件CMake 3.20以上版本ITK 5.3.0要求CMake最低版本是3.16VTK 9.3.1要求更高一些实测3.22.0以上最稳妥Git拉取源码或者签出指定tag用可选Qt 5.15或Qt 6.x如果你的项目需要VTK的QVTKOpenGLNativeWidget渲染窗口这一步一定不能省有个容易忽略的点VS2019的C编译工具链要确保勾选MSVC v142生成工具以及对应的Windows SDK版本。如果只装了VS Build Tools没有装完整IDE在cmake-gui里选择生成器时容易找不到对应的工具集这一点后面排查时会提。提示建议把下载的源码放一个没有空格、没有中文的路径下比如D:\dev\src\ITK-5.3.0。CMake对路径里的空格支持其实已经算不错了但ITK和VTK里某些第三方模块的历史遗留问题依旧会让你踩坑。2.2 源码获取与版本对应关系既然标题写明了ITK 5.3.0和VTK 9.3.1那你最好下载对应tag的源码不要随便拉master分支。master分支是开发版API可能正处在变化中今天编译能用明天可能就换了头文件这会导致你SDK里的类库接口不稳定。ITK 5.3.0版本在官方仓库的tag就是v5.3.0VTK对应v9.3.1。下载方式有两个GitHub页面直接下载zip包用Git签出比如git clone --branch v5.3.0 --depth 1 https://github.com/InsightSoftwareConsortium/ITK.git git clone --branch v9.3.1 --depth 1 https://github.com/Kitware/VTK.git--depth 1可以只拉最新一次提交省流量也省时间。如果你要配套第三方模块比如ITK的Elastix、VTK的额外插件再考虑full clone。这里补充一句为什么选这两个版本配对ITK 5.3.0是5.x系列里比较稳定的版本内部API已经全面走向Modern C和VTK 9.3.1配合使用时ITKVtkGlue模块的兼容性最好。VTK 9.3.1在渲染后端上做了大量重构对OpenGL2的支持也更成熟。这不是随意选的版本号是社区里验证过的组合。3. CMake配置关键参数逐项拆解3.1 千千万万不要用默认配置不少人第一次编译大型C库时直接在cmake-gui里选择源码目录、选择VS2019生成器然后Configure、Generate一气呵成点完就去泡咖啡了。结果几小时后回来发现整个build目录几百GB编译还卡在某个测试用例上。ITK和VTK的CMake默认配置里BUILD_TESTING默认是ON的这意味着你会把几千个测试程序全部编译一遍。虽然测试代码对库本身的校验有好处但对一个只想拿SDK来做应用开发的人来说这是纯纯的时间黑洞。正确做法是什么第一次Configure之前就把下面这些开关想清楚一次性配置到位。3.2 ITK编译的关键CMake开关ITK的配置其实比VTK要复杂一些因为它的模块体系非常庞大。你不需要全部编译按需开启即可。我这次的配置如下在cmake-gui中设置或命令行传参都可以BUILD_SHARED_LIBS建议ON生成DLL。静态库在链接阶段耗时更长而且后续开发调试时不方便换配置还需要重新编译一遍。BUILD_TESTINGOFF除非你要给ITK贡献代码否则不需要测试程序。CMAKE_INSTALL_PREFIX设置成你的SDK输出目录比如D:\SDK\ITK-5.3.0不要用默认的C:\Program Files\ITK后面打包时会省很多权限相关的麻烦。ITK_USE_64BITS_IDSON。现代医学图像尺寸动不动就超过2GB内存映射范围64位ID是必要的。Module_ITKVtkGlueON。这是连接ITK图像数据和VTK渲染管道的桥梁。如果你要把ITK分割结果交给VTK做三维显示这个模块必开。Module_ITKReview推荐开。这个模块包含很多实验性但实用的滤波器和分割算法部分常用功能依赖它。ITK_USE_SYSTEM_*系列除非你有明确需求保持默认即可ITK会自行拷贝并编译它需要的第三方库。ITK_WRAP_PYTHONOFF。除非你要开发ITK的Python扩展否则开这个会拖长编译时间并且引入很多Python依赖。有一个细节特别容易忽略ITK默认会开启将近180个模块的编译。如果你希望SDK尽量精简可以先用cmake-gui的Grouped方式查看模块列表把不用的模块手动勾选掉。但要注意ITK模块之间是有依赖关系的你关掉某个模块时CMake会自动调整依赖它的模块不要去硬关。实际经验是保留默认模块再加上必要的VTK Glue结果通常是最稳的。3.3 VTK编译的关键CMake开关VTK 9.3.1的CMake配置比ITK要友好一点但有一个大坑默认的渲染模块分组导致很多人编出来的VTK缺少OpenGL渲染支持或者QVTK窗口组件缺失。我这次用到的核心配置CMAKE_BUILD_TYPE第一次编译时填Release第二次编译debug时改成Debug。注意这个变量只在用单配置生成器时有效VS2019是多配置生成器所以它更多是一个归档标记真正决定编译类型的是你后面调用MSBuild时选的/p:ConfigurationDebug|Release。BUILD_SHARED_LIBSON同样为了DLL和后续调试。BUILD_TESTINGOFF。VTK_GROUP_ENABLE_RENDERING这里有个专有视图建议设置为WANT_ALL或按需开启。如果设为DONT_WANT你会失去几乎全部三维渲染能力。VTK_GROUP_ENABLE_QT如果你需要Qt集成必须把这一项打开否则QVTKOpenGLNativeWidget不会编译出来。默认情况下这个选项可能为NO需要手动切换成YES或WANT。VTK_BUILD_ALL_MODULES默认OFF保持OFF即可。全部模块编译时间和磁盘占用会非常惊人。VTK_USE_SYSTEM_*系列第三方库除非你想全部用系统的比如系统已有Eigen、jsoncpp一般保持默认让VTK自己管理第三方依赖相关性更简单。VTK_ENABLE_WRAPPING这个是给生成Python等其他语言绑定用的做纯C开发直接OFF能省很多时间。还是那句话VTK 9.x版本以后模块依赖关系很复杂最稳妥的就是按官方分组配置来不要手动去抠单个模块。分组里如果某个组件你不需要关掉它时CMake会告诉你哪些依赖它的模块会被连带关闭按提示来别硬刚。3.4 从CMake生成VS2019工程的过程与常见报错配置完上述选项之后在cmake-gui里点Configure第一次会弹出生成器选择窗口选择Visual Studio 16 2019平台Platform选x64下面Optional platform for generator选x64不要默认的Win32这一步非常关键。很多人忽略了这个下拉框默认生成的是Win32平台后面编译出来的库是32位的和标题要求的x64完全不搭。一旦生成错平台整个源码目录里的CMake缓存都混着32位信息想改回来还得清空build目录重新配一遍非常浪费时间。点开Optional platform for generator并选择x64然后重新Configure。Configure过程中的红色报错大多是路径不存在、Qt找不到、依赖库版本不匹配。把报错信息发给搜索引擎基本都能找到答案但有一个非常典型的问题值得单独说如果Configure阶段提示找不到Qt5相关组件但你确认Qt装好了十有八九是因为Qt的CMake模块目录没有自动被识别。此时在CMake变量里手动设置Qt5_DIR指向你安装目录下lib/cmake/Qt5Qt6则指向lib/cmake/Qt6重新Configure就好了。顺利Configure后点Generate会在build目录生成ITK.sln和VTK.sln。到这里真正的编译才刚刚开始。4. MSBuild批量编译与长任务管理4.1 为什么用MSBuild而不是打开IDEITK和VTK的解决方案文件里包含了上百个项目用Visual Studio IDE直接打开编译也不是不行但有两个坏处IDE本身占用内存大编译期间界面还容易卡死而且IDE的Build输出窗口在批量构建时日志刷新太快遇到错误不好回溯。我个人的习惯是用MSBuild命令行编译。好处一是可以重定向完整日志方便出错后grep关键行二是可以开控制台并行编译比IDE里那个并行项目生成更直观可控。在VS2019安装目录下打开Developer PowerShell for VS 2019或者x64 Native Tools Command Prompt for VS 2019然后执行MSBuild命令。项目名ALL_BUILD就是负责编译整个解决方案所有项目的入口。4.2 Debug和Release分次编译的高效姿势这里有一个值得注意的点ITK和VTK虽然是VS2019多配置生成器生成的解决方案同一套工程文件可以编译出debug或release但在实际执行时我强烈建议你把debug和release分到两个不同的build目录进行CMake配置和编译而不是在同一个目录里编译两次。之所以这么建议有两个原因第一第三方依赖库在不同配置下的链接路径、宏定义不同同一个build目录反复切换Configuration容易出现缓存混乱导致的问题。分成两个目录ITK-build-release和ITK-build-debug各自独立互不影响。第二后续增量编译时单独目录的逻辑更清晰你不会因为某次忘记切换配置导致链接到错误的库。我实际编译时的操作顺序是先把ITK和VTK的Release版本都编完确认能通过再回到CMake重新配置debug。注意CMAKE_BUILD_TYPE在debug目录里要设置为Debug这样一些条件编译的逻辑比如_DEBUG宏和调试标识符才会正确生效。4.3 编译耗时的心理预期与并行参数直接给经验数据在8核16线程的机器上ITK Release全量编译大约需要40到60分钟debug版本时间会更长大约多20%左右。VTK Release全量编译大约需要30到50分钟。如果机器是4核老设备时间基本翻倍做好心理预期。按需关闭不必要的模块之后这个时间能显著缩短。比如ITK如果只保留基础模块加VtkGlue可能20分钟就能过一遍RELEASE编译。我通常的做法是先完整编译一遍验证SDK没问题再去精简模块避免一开始就裁剪导致漏掉某个隐藏依赖。MSBuild并行编译参数/m后面对应线程数。不是越大越好因为ITK和VTK的某些大项目本身编译时就会占满所有核心并行层数开太高反而容易内存不足。我的建议是msbuild ITK.sln /m:8 /p:ConfigurationRelease /p:Platformx64 /flp:logfileITK_build_release.log/flp是file log parameter会把完整输出写到指定的日志文件里。编译VTK时同理msbuild VTK.sln /m:8 /p:ConfigurationRelease /p:Platformx64 /flp:logfileVTK_build_release.log编完Release后再把Configuration换成Debug重复一遍。debug编译如果发现某个项目报错不要急着重来先看日志里是哪个模块的问题大概率是依赖库没找到或者源码版本冲突。注意MSBuild编译大型解决方案时如果内存不足报C1083之类的问题优先降低/m并行数同时关闭占内存的应用而不是去改编译选项。5. 安装打包整理出可直接引用的SDK5.1 使用INSTALL工程还是手工拷贝编译结束后每个解决方案里都有一个INSTALL项目很多人不知道这个项目的价值喜欢自己手动从各模块目录里挑include和lib。这个做法非常容易漏文件因为ITK和VTK的头文件和库文件分散在几十个目录里手工拷贝漏掉一个子目录后面项目编译时就会报找不到头文件。正确的做法是编译并运行INSTALL项目它会按照CMake中设定的CMAKE_INSTALL_PREFIX把所有需要发布的头文件、库文件、CMake配置脚本统一拷贝到目标目录。执行命令如下msbuild ITK.sln /p:ConfigurationRelease /p:Platformx64 /t:INSTALL msbuild ITK.sln /p:ConfigurationDebug /p:Platformx64 /t:INSTALL msbuild VTK.sln /p:ConfigurationRelease /p:Platformx64 /t:INSTALL msbuild VTK.sln /p:ConfigurationDebug /p:Platformx64 /t:INSTALL这里有个顺序问题需要注意先Release后Debug或者反过来都可以但一定要把两个配置的INSTALL都执行完否则SDK里会缺其中一种库。有些人只执行了Release的INSTALL结果SDK的lib目录下只有release库debug工程链接时怎么都找不到对应的.lib文件。5.2 SDK目录结构设计与随手可用的文件清单INSTALL执行完毕后D:\SDK\ITK-5.3.0和D:\SDK\VTK-9.3.1目录下会各自生成include、lib、bin、cmake等子目录。这两个目录做点整理就可以作为项目的SDK引用了。推荐的做法是把它们归档成一个统一的SDK根目录比如D:\SDK\medimg内部再分ITK和VTK两个子目录。这样在CMake工程里往CMAKE_PREFIX_PATH里添加时一条路径就能覆盖两个库写起来清爽很多。一个标准目录结构长这样D:\SDK\medimg ├── ITK │ ├── bin (ITK运行DLL) │ ├── include (ITK头文件) │ ├── lib (ITK导入库包含debug/release) │ └── cmake (ITKConfig.cmake等) └── VTK ├── bin (VTK运行DLL) ├── include (VTK头文件) ├── lib (VTK导入库) └── cmake (VTKConfig.cmake等)记得检查bin目录下是否完整。ITK和VTK很多DLL带后缀比如ITKIOImageBase-5.3.dll、vtkRenderingOpenGL2-9.3.dll这些都是运行时需要的。发布你的应用程序时需要把这堆DLL和你的exe放在一起或者加入系统PATH环境变量。补充一个Windows下运行时环境的细节只有bin目录里的DLL被依赖lib里的.lib文件只是编译链接时用来解析符号的导入库运行时不需要它们。所以交付SDK给别人时bin目录一定要打包完整否则对方程序一启动就报找不到itkCommon-5.3.dll。这个坑我见过太多次了。5.3 验证SDK是否正确的三个小测试SDK整理出来之后别急着往大项目里集成先写几个最小测试工程验证一下编译链接和运行三条链路是否畅通。第一个测试一个最简单的ITK读取图像程序读取一张DICOM或PNG图片输出尺寸信息。主要验证头文件能否包含成功、itkCommon库是否链接正常、DLL能否被找到。第二个测试一个VTK渲染程序创建一个标准立方体网格并渲染窗口显示。主要验证VTK的渲染模块、交互模块、OpenGL2模块是否齐全。第三个测试ITK和VTK的Glue桥接测试。把一张ITK的itk::Image转成VTK的vtkImageData并显示主要验证ITKVtkGlue模块和VTK的图像数据结构是否对接成功。这三个测试如果全部通过基本可以断定这份SDK是可用的后续项目集成时碰到的绝大多数问题都是自己工程配置的问题而不是库本身的问题。6. 常见问题与排查技巧实录这份编译流程里有几类问题是我和周围人反复踩过的归结成一个速查表按出现频率排序。6.1 链接阶段报LNK2038或LNK2005基本逃不过症状使用SDK编译自己的CMake工程时链接器报LNK2038: mismatch detected for _ITERATOR_DEBUG_LEVEL或者LNK2005: xxx already defined。原因你当前编译的是Debug配置但链接到了Release库或者反之。_ITERATOR_DEBUG_LEVEL这个宏在不同的配置下值不同混在一起必然报错。排查方法打开你的项目项目属性 → C/C → 预处理器查看_DEBUG、NDEBUG、_ITERATOR_DEBUG_LEVEL是否和库的配置一致。同时确认CMake里find_package(ITK)之后target_link_libraries里链接的是ITKCommon还是ITKCommon-5.3两个命名规则在不同配置下对应的导入库文件是同一个关键看目录里的.lib文件指向哪个配置版本。另一个隐蔽来源是运行库设置不一致你的项目用的是/MT静态运行时而SDK库编译时用的是/MD动态运行时。这种不匹配也会导致LNK2038而且报错信息不会直接告诉你运行库不匹配需要你自己在项目属性里把运行库改成/MD或者重新编译一套静态运行时的SDK。我自己的经验是Windows下用动态运行时/MD最省心跨模块传递C对象时的ABI兼容性更好。6.2 运行时提示找不到zlib.dll、tbb.dll等症状程序编译通过但一运行就报找不到zlib.dll、找不到tbb.dll、找不到libpng16.dll等情况。原因ITK和VTK内部依赖一批第三方开源库其中不少在编译时以子模块形式编译进了DLL但仍有相当一部分以独立动态库的形式输出到bin目录。这些DLL没有被拷贝到你的程序运行目录或者没有加入PATH。排查方法打开你的D:\SDK\medimg\ITK\bin和VTK\bin目录挨个看里面的DLL然后把它们全部拷贝到你的exe同目录。如果DLL数量太多不想手动复制也可以在CMake里加一个POST_BUILD的copy_if_different命令让构建完成后自动同步DLL。判断DLL是否缺失可以直接用VS自带的dumpbin /dependents your_app.exe查看依赖列表或者用Dependencies这个开源工具一眼就能看出缺哪些。6.3 CMake工程引用SDK时总是自动下载或跑到原Git仓库去症状自己写的CMakeLists里写了find_package(ITK REQUIRED)但CMake总是去GitHub拉源码或者找到的版本是系统PATH里某个旧版本而不是你刚编译的SDK。原因find_package的搜索路径优先级里如果没有显式指定CMAKE_PREFIX_PATHCMake会先搜索系统路径和当前工程路径然后才尝试从远程获取fetch。旧版本SDK如果还残留在系统路径里优先级反而比你新编译的更高。排查方法在你项目的CMakeLists.txt最前面加上一行set(CMAKE_PREFIX_PATH D:/SDK/medimg CACHE PATH SDK path)这行之后再进行find_package(ITK REQUIRED)和find_package(VTK REQUIRED)CMake就会优先去D:\SDK\medimg\ITK\cmake和D:\SDK\medimg\VTK\cmake目录下寻找Config文件。如果还是找不到就在CMake Cache里直接指定ITK_DIR和VTK_DIR为cmake目录的完整路径这招基本能解决百分之百的情况。6.4 使用体验中的杂项问题速查表症状原因解决方式cmake-gui配置后点Generate闪退源码目录或build目录存在中文/特殊字符换纯英文路径重建build目录MSBuild报error MSB8036找不到Windows SDK版本VS安装时没勾选对应Windows SDK打开VS Installer补充安装Windows 10 SDK编译到中途内存溢出并行项目数过高或系统内存不足降低/m并行数关闭浏览器等大内存应用VTK链接时找不到OpenGL相关符号渲染模块未正确开启回到CMake确认VTK_GROUP_ENABLE_RENDERING设置debug版程序跑起来后有些变量显示不出来优化导致的信息丢失不是SDK损坏确认链接的确实是debug版库检查导入库路径INSTALL执行后bin目录很小部分DLL没被collect检查各模块是否有独立COPY命令手动从build目录补齐Release下运行正常、Debug下闪退混用了不同版本的第三方库核对所有依赖库的debug/release版本一一对应还有一类问题值得单独提醒如果你同时安装了VS2019和VS2022MSBuild命令行默认可能指向的是VS2022的版本编译时它会用V143工具集去编译V142工程虽然多数情况下能兼容但偶尔会有第三方模块的不兼容报错。最简单的办法是确保在x64 Native Tools Command Prompt for VS 2019里执行MSBuild这样用的就是配套的工具集不会串版本。说实话ITK和VTK这套组合在Windows下的编译一旦成功之后你会发现收益远超成本。SDK里不仅包含了编译好的库还天然带有CMake的配置脚本后续在多个项目里反复复用特别顺手。我也是折腾了两次之后才摸索出开模块、分目录、命令行并行编译这套组合拳现在再在新机器上搭环境基本就是一小时搞定的事情。这套流程里最值得花时间的其实是第一步的CMake配置配置想明白了后面编译、打包、引用都是水到渠成的。如果你也准备动手编译建议先把这篇文章里的参数过一遍再动手。最后一点个人的心得编译大型库时保存好每个版本的CMake配置记录或者直接在Git里维护一份备份因为几个月后你再想编译的时候大概率已经忘了当初哪些开关是干什么用的了。本文还有配套的精品资源点击获取
返回列表