Visual Studio 2022编译VTK + Qt

1. 下载和安装VTK

  1. 下载源码包, 保存到工作目录中. 比如, 我自己的目录为c:/libs/vtk.
  2. 解压缩vtk的源码包. 默认解压缩当当前目录后是VTK-9.3.0, 我打算将这个目录用于构建后的版本目录, 因此将它改一下名字, VTK-9.3.0-src
  3. 建立两个同级的目录, VTK-9.3.0-buildVTK-9.3.0, 第一个是构建时的工作目录, 这样cmake的所有生成文件都放在这里, 不会破坏源代码目录VTK-9.3.0-src. 而VTK-9.3.0用于安装VTK的目录. 将这些目录都和安装目录隔离开, 避免万一构建出了什么问题后清理起来麻烦.

1.1 修改bug

VTK9.3有一个bug, 会导致Debug模式下编译失败. 我们先修改一下.

打开Common\Core\vtkConstantImplicitBackend.h,

VTK_ABI_NAMESPACE_BEGIN
template <typename ValueType>
struct VTKCOMMONCORE_EXPORT vtkConstantImplicitBackend final
{
  /**
   * A non-trivially contructible constructor
   *
   * \param val the constant value to return for all indeces
   */
  vtkConstantImplicitBackend(ValueType val)
    : Value(val)
  {
  }
  ...

我们需要将VTKCOMMONCORE_EXPORT给删掉. 不然会重复导出符号.

1.2 配置CMake

  1. 启动CMAKE, 指定源目录为C:/libs/vtk/VTK-9.3.0-src, build目录为c:/libs/vtk/VTK-9.3.0-build.

  2. 按下Configure按钮. 此时, 也可以将GroupedAdvanced两个复选框勾上. 此时会弹出对话框, 选择工具. 在里面选择Visual Studio 17 2022x64.

Qt6 编译使用的是Visual Studio 16 2019, 可能选择它是更好的做法. 我的电脑里面只有2022, 因此只能选择这个. 不过, 我们可以为Visual Studio 2022安装2019的生成工具使用. 如下所示:

  1. 确认之后, CMAKE会进行配置分析. 取决于你的电脑, 这是一个很漫长的过程, 等完成后, 要进行下面的修改:

    • 注意选中BUILD_SHARED_LIBS, 这个一定要选中 (默认是选中的, 要检查一下不要弄没了).

    • 寻找VTK_LEGACY_REMOVE, 选中它会禁用deprecated api. 我们会使用最新的API接口, 不会盲目抄网上的老东西, 所以这个最好是选中它.

    • 检查一下VTK_MODULE_ENABLE_VTK_iossVTK_MODULE_ENABLE_VTK_IOIOSS, 据说要设置为NO, 以前的版本会编译失败. 不过, 如果你打算生成测试数据, 那么这个最终还是要打开的, 而且也能编译通过. 所以网上的东西不一定是对的.

    • 寻找CMAKE_INSTALL_PREFIX, 把它设置为我们前面创建的目录C:/libs/vtk/VTK-9.3.0. 这个一定要慎重, 一旦确定了就不要以后再乱动了.

    • 最后, 寻找Qt, 将VTK_GROUP_ENABLE_QT给勾选上, 然后将其他几个都设置为WANT. 我因为不用QML, 就没有选中Quick的这一项. 注意的是, Qt6的新版本的目录结构有变化, 和VTK不怎么兼容, 如果选择了quick, 需要自己去修改几个目录的位置.

  2. 选择了之后, 就可以再次按下Configure按钮了. 这个时候还会有错误. 我们要如下修改:

    • 设置Qt5_DIRQt6_DIR. 对于Qt6, 默认位置在C:\Qt\6.7.0\msvc2019_64\lib\cmake\Qt6下面. Qt5也一样.
    • 确认一下VTK_QTVERSION的值, 因为这台电脑只装了Qt6, 我也只会在Qt6上面用VTK, 我就设置为6了. 注意, 我没有选择Quick, 因为我不用QML. 如果你打开了, 又会有一堆错误出来. 还是找不到qt的目录, 手工一个个去修改就是了. 反正用qt6就会有这些烂事, 不知道是qt6烂还是vtk适配的不好.
  3. 再次按下Configure按钮, 结果如下图所示. 红色的是给你确认的. 因为这台电脑上没有装vulkan, 所以会有警告. 我们不用它, 所以不用关心. 等以后需要的时候再重新安装Vulkan SDK就是了. 然后确认一下没问题了. 就可以按下Generate按钮生成VC工程了.

  4. 按下Generate, 会在build目录中生成VTK.sln文件. 然后我们可以关闭CMAKE了.

1.3 编译VLK和安装

用Visual Studio打开VTK.sln工程. 选择ALL BUILD项目, 打开工程属性页:

  • 选择所有配置, 然后选择常规/C++标准, 将其改为C++17或更新的版本.
  • 如果担心和Qt的版本不一致, 可以修改平台工具集, 改为2019的v142版本. 据说这个版本不一致会影响plugin, 但是我基本上不拖拉控件, 所以也就不想改了.

然后, 激活Release, 并开始Build. 这个过程很漫长, 我的11代i5的笔记本, 估计会跑上1个多小时.

编译完成后, 选择INSTALL项目, 选择仅生成INSTALL.

然后, 将配置切换到Debug, 并重新做一轮. 编译和安装就完成了.

修改完毕之后, 注意将VTK_DIR放到环境变量里面去.

2. 在Qt的qmake项目中使用VTK

使用qmake,无法利用cmake,使用起来很麻烦,需要人工将库一个个地添加到工程里面。例如:

修改.pro文件, 在文件按末尾增加vtk库:

INCLUDEPATH += /path/to/VTK/include/vtk-<version>
LIBS += -L/path/to/VTK/lib \
        -lvtkCommonCore-<version> \
        -lvtkFiltersSources-<version> \
        -lvtkInteractionStyle-<version> \
        -lvtkRenderingOpenGL2-<version> \
        -lvtkGUISupportQt-<version>

这种做法太麻烦,尝试一次就不会再有做第二次的兴趣了。除非是在已有的qmake工程中增加VTK,否则还是不主张使用。

3. 在Qt的cmake项目中使用VTK

相对于Visual Studio, 我更喜欢使用QtCreator. 所以下面是针对的是使用QtCreator的方法.

3.1 创建一个纯Qt项目的CMake文件

首先注意一点的是,比较新的QtCreator自动创建的widget项目的cmake文件是有问题的,而且里面有很多做Windows用不到的东西,如果不跨平台,只做Windows上位机程序,还是按照它的文档手工写文件比较好,做出来的cmake文件更干净一些。

下面是一个支持GUI的CMakeLists.txt文件:

# GUI和Console都需要的部分
cmake_minimum_required(VERSION 3.16)
project(exam01 VERSION 1.0.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Console项目只需要Core组件.
find_package(Qt6 REQUIRED COMPONENTS Core)
#如果是GUI, 至少要将Widgets加进去. Widgets自动包含Core了
find_package(Qt6 REQUIRED COMPONENTS Widgets)
# 如果需要添加多语种支持, 加入LinguistTools
find_package(Qt6 REQUIRED COMPONENTS LinguistTools)
# QtCreator模板生成的项目不再使用这个函数了. 但是文档中还是这个
qt_standard_project_setup()
# 我们可以自己定义多个变量来对源码自己做分类. 模板是直接加到qt_add_executable()里面. 
# 我们自己分组分类更便于维护
# 按照cmake的说法, 不需要将.h文件加到makelist里面. 但是加进去也没啥. 
set(PROJECT_SOURCES
        main.cpp
        mainwindow.cpp
        mainwindow.h
        mainwindow.ui
)
qt_add_executable(exam01
    MANUAL_FINALIZATION
    ${PROJECT_SOURCES}
)
# 添加语言资源文件. 模板生成的也不用这个了. 感觉Qt团队做事情太随意了.
qt_add_translations(${PROJECT_NAME} TS_FILES exam01_zh_CN.ts)
    
# 如果是Core项目, 则使用Qt6::Core代替这里的Qt6::Widgets
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets
)
# Console项目不需要这个一段. 
set_target_properties(${PROJECT_NAME} PROPERTIES
    WIN32_EXECUTABLE ON
    MACOSX_BUNDLE ON
)

3.2 添加VTK

然后, 要支持VTK,我们只需要将下面几行加到里面去:

# 添加对VTK的引用. 也可以使用COMPONENTS指定具体的组件. 对新手来说, 这个有点困难. 
find_package(VTK REQUIRED)
    
# 在target_link_libraries里面加入${VTK_LIBRARIES}
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Widgets
    ${VTK_LIBRARIES}
)

# 加入下面
vtk_module_autoinit(
    TARGETS ${PROJECT_NAME}
    MODULES ${VTK_LIBRARIES}
)

这样,CMake工程文件就完成了。

接下来,我们还需要找个地方实现auto_init。这个活动需要在使用::New()的前面进行,个人建议就放到main.cpp里面。这样不管是Console还是GUI程序,都能利用它。比如:

...
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingContextOpenGL2);
...
int main()
{
    ...
}

3.3 其他改进

接下来,我们可以考虑利用预编译头文件。这一点上,cmake做的比qmake,比VC都差了很多。尤其是VTK的头文件多如牛毛,好像也没有一个如OpenCV的opencv.hpp这样的打包头文件,用起来很不友好。个人的建议是把你自己经常用到的头文件都定义在一起, 打包放到预编译里面, 这样自己的代码里面也用不着时不时跑到前面添加一行include了。反正预编译嘛, 头文件再多也不是什么大问题.

比如,下面我定义了一个变量PCH_FILES,里面包含了经常用到的头文件,然后用target_precompile_headers来声明它。如果是多子工程的项目,可以将PCH_FILES定义到顶层文件中,每个子目录项目的cmakelists文件中使用target_precompile_headers来引用它。

set(PCH_FILES
    <QDebug>
    #...
    <vtkActor.h>
    <vtkBMPReader.h>
    <vtkImageActor.h>
    <vtkJPEGReader.h>
    <vtkMetaImageReader.h>
    <vtkNamedColors.h>
    <vtkPolyDataMapper.h>
    <vtkProperty.h>
    <vtkRenderer.h>
    <vtkRenderWindow.h>
	#...
)

target_precompile_headers(${PROJECT_NAME} PUBLIC
    ${PCH_FILES}
)
  • 25
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值