• QT转型Visual Studio(qmake项目到cmake项目的移植)


    前言

    由于工作需要,同时也为了方便以后的集成升级,希望将之前用Qt creator qmake开发的项目移植到cmake项目中,并使用Visual Studio 进行后续开发,本文主要用以记录该过程中的常规步骤和遇到的特殊情况。

    qmake项目

    在一开始,为了降低开发难度以及快速完成业务开发,我们使用Qt Creator原生编译器以及qmake来进行软件界面研发。编写pro文件来生成makefile,makefile将用于指导后续的各种编译器生成可执行文件。(关于makefile的介绍可以参考这篇文章添加链接描述
    下面我们大致介绍一下该项目原本的pro文件。其中我删减了部分无关紧要的内容,只保留将被转换为cmake工程所需要的东西。

    QT += core gui
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    # 添加xml文件读写功能
    QT+=xml
    CONFIG += c++11
    include(D:/software/QT5.14.0/package/VTK-8.2.0/VTK-8.2.0.pri)
    # 如果要使用VTKACtorToOSG功能 需要引入 osg库
    INCLUDEPATH +=D:/BaiduNetdiskDownload/install/include
    win32:CONFIG(release, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losg
    else:win32:CONFIG(debug, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgd
    ​
    win32:CONFIG(release, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgViewer
    else:win32:CONFIG(debug, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgViewerd
    ​
    win32:CONFIG(release, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgDB
    else:win32:CONFIG(debug, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgDBd
    win32:CONFIG(release, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -lOpenThreads
    else:win32:CONFIG(debug, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -lOpenThreads
    SOURCES += \
        customUnit/dockwidget.cpp \
        customUnit/mycustomslider.cpp \
        ...
    HEADERS += \
        customUnit/dockwidget.h \
        customUnit/mycustomslider.h \
        ...
    FORMS += \
        customUnit/dockwidget.ui \
       ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    其中包含了Qt的几个模块功能库,vtk库,以及osg库中的几个模块。
    VTK库中仅包含了MSVC编译的release版本。
    OSG库也是用的MSVC编译的release版本。
    Qt库使用MSVC编译的包含debug版本和release版本。
    编译器使用对应的MSVC 编译器。
    这里有个遗留问题,开发设备上原本的Qt creator只有Mingw的编译器,为了让其支持MSVC编译,我们在Visual Studio 中下载了MSVC2017版本来使用,但Qtcreator无法自动识别该编译器,我们手动配置一个自定义的编译器选项去查找到它(这个问题在后续的移植工作中会在导入库的时候再次出现)。

    到cmake工程的移植

    为了方便,我们先使用Qtcreator创建了一个cmake工程,让它帮我们先生成一部分cmakelist.txt代码。

    cmake_minimum_required(VERSION 3.5)
    set(CMAKE_CXX COMPILER WORKS 1)
    project(Window_cmake_version )
    
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    
    set(CMAKE_AUTOUIC ON)
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTORCC ON)
    
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    find_package(Qt5 COMPONENTS Widgets REQUIRED)
    
    if(ANDROID)
      add_library(Window_cmake_version SHARED
        main.cpp
        mainwindow.cpp
        mainwindow.h
        mainwindow.ui
      )
    else()
      add_executable(Window_cmake_version 
        main.cpp
        mainwindow.cpp
        mainwindow.h
        mainwindow.ui
      )
    endif()
    
    target_link_libraries(Window_cmake_version PRIVATE Qt5::Widgets)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    其中自动包含了Qt的库的引入。
    我们一一对应将pro中的内容转为cmakelist.txt中的内容。
    qmake

    QT += core gui
    QT += widgets
    QT+=xml
    
    • 1
    • 2
    • 3

    cmake

    find_package(Qt5 COMPONENTS Widgets REQUIRED)
    find_package(Qt5 COMPONENTS Xml REQUIRED)
    find_package(Qt5 COMPONENTS Gui REQUIRED)
    target_link_libraries(Window_cmake_version PRIVATE Qt5::Widgets)
    target_link_libraries(Window_cmake_version PRIVATE Qt5::Xml)
    target_link_libraries(Window_cmake_version PRIVATE Qt5::Gui)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    qmake

    //为了便于引入库,我们在vtk库中编写了pri文件,实际上它只是简化了导入lib和头文件的过程
    include(D:/software/QT5.14.0/package/VTK-8.2.0/VTK-8.2.0.pri)
    
    • 1
    • 2

    cmake

    //这里我们使用cmake查找包的方式来导入vtk库
    find_package(VTK REQUIRED)
    if(VTK_FOUND)
      message(STATUS "found VTK_DIR")
    else(VTK_FOUND)
      message(FATAL_ERROR "VTK not found. Please set VTK_DIR")
    endif(VTK_FOUND)
    include(${VTK_USE_FILE})
    target_link_libraries(Window_cmake_version
            PRIVATE optimized ${VTK_LIBRARIES})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    qmake

    # 如果要使用VTKACtorToOSG功能 需要引入 osg库(只使用部分库,不需要全引入) 这里实际上只用到了release版本
    INCLUDEPATH +=D:/BaiduNetdiskDownload/install/include
    win32:CONFIG(release, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losg
    else:win32:CONFIG(debug, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgd
    ​
    win32:CONFIG(release, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgViewer
    else:win32:CONFIG(debug, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgViewerd
    ​
    win32:CONFIG(release, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgDB
    else:win32:CONFIG(debug, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -losgDBd
    win32:CONFIG(release, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -lOpenThreads
    else:win32:CONFIG(debug, debug|release): LIBS += -LD:/BaiduNetdiskDownload/install/lib/ -lOpenThreads
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    cmake

    # 查找OSG 库  该方式也适用于vtk库的导入
    target_include_directories(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/include)
    target_link_libraries(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/lib/osg.lib)
    target_link_libraries(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/lib/osgViewer.lib)
    target_link_libraries(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/lib/osgDB.lib)
    target_link_libraries(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/lib/OpenThreads.lib)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    qmake

    SOURCES += \
        customUnit/dockwidget.cpp \
        customUnit/mycustomslider.cpp \
        ...
    HEADERS += \
        customUnit/dockwidget.h \
        customUnit/mycustomslider.h \
        ...
    FORMS += \
        customUnit/dockwidget.ui \
       ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    cmake

    set(HEADERS 
        customUnit/dockwidget.h 
        customUnit/mycustomslider.h 
     	...
    )
    set(UI 
        customUnit/dockwidget.ui 
      	...
    
    )
    set(SOURCES
        customUnit/dockwidget.cpp 
        customUnit/mycustomslider.cpp 
    	...
    )
    add_executable(Window_cmake_version 
        ${SOURCES} ${UI} ${HEADERS} )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    到这里我们大致上就实现了pro文件到cmakelist.txt文件的迁移。
    最终生成的cmakelist.txt文件

    cmake_minimum_required(VERSION 3.5)
    #set(CMAKE_PREFIX_PATH "D:/software/QT5.14.0/5.14.0/mingw73_64") 
    project(Window_cmake_version)
    set(CMAKE_INCLUDE_CURRENT_DIR ON)
    #set (CMAKE_CXX COMPILER WORKS 1)
    set(CMAKE_AUTOUIC ON)
    set(CMAKE_AUTOMOC ON)
    set(CMAKE_AUTORCC ON)
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    find_package(Qt5 COMPONENTS Widgets REQUIRED)
    find_package(Qt5 COMPONENTS Xml REQUIRED)
    find_package(Qt5 COMPONENTS Gui REQUIRED)
    set(HEADERS 
        customUnit/dockwidget.h 
        customUnit/mycustomslider.h 
    	...
    )
    set(UI 
        customUnit/dockwidget.ui 
    	...
    
    )
    set(SOURCES
        customUnit/dockwidget.cpp 
        customUnit/mycustomslider.cpp 
    	...
    )
    # 查找 VTK 库
    #find_package(VTK REQUIRED PATHS D:/software/QT5.14.0/package/VTK-8.2.0/lib/cmake/vtk-8.2)
    find_package(VTK REQUIRED)
    if(VTK_FOUND)
      message(STATUS "found VTK_DIR")
    else(VTK_FOUND)
      message(FATAL_ERROR "VTK not found. Please set VTK_DIR")
    endif(VTK_FOUND)
     include(${VTK_USE_FILE})
    add_executable(Window_cmake_version 
        ${SOURCES} ${UI} ${HEADERS} )
    # 查找OSG 库
    target_include_directories(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/include)
    #add_executable(untitled11)
    #add_executable(untitled11 main.cpp )
    target_link_libraries(Window_cmake_version PRIVATE Qt5::Widgets)
    target_link_libraries(Window_cmake_version PRIVATE Qt5::Xml)
    target_link_libraries(Window_cmake_version PRIVATE Qt5::Gui)
    target_link_libraries(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/lib/osg.lib)
    target_link_libraries(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/lib/osgViewer.lib)
    target_link_libraries(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/lib/osgDB.lib)
    target_link_libraries(Window_cmake_version PRIVATE D:/BaiduNetdiskDownload/install/lib/OpenThreads.lib)
    target_link_libraries(Window_cmake_version
            PRIVATE optimized ${VTK_LIBRARIES})
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    实际运行后我们遇到了几个问题:

    1. cmakelist find_find_package() 方式找包机制找到了环境中的vtk8.1的包,这并不是我们想要的8.2的包,同样qt库也出现了一样的问题,找到了Mingw的版本库,这必然是无法接受的,目前的解决方案是去CMakeSettings.json中手动修改它自动寻找填充的项。应该有更好的解决方案,希望不吝赐教。
      在这里插入图片描述

    2. 使用MSVC release版本编译后,dll链接错误(无法定义到入口xxx等问题),这和qt打包应用程序类似,需要把相关dll都收集过来扔到可执行程序目录下即可解决,如果有更好的解决方案,也希望评论留言交流一下。

    3. 相关库dll都收集完后依然运行时报错:

      This application failed to start because it could not find or load the Qt platform plugin “windows”

      Reinstalling the application may fix this problem.

      解决办法:

      QT为了简化生成发布版本,特别提供了工具 “windeployqt.exe”,这个工具在 "…\Qt5.8.0\5.8\msvc2017_64\bin"的 目录下,通过该命令,可以解决上述错误。
      打开控制台窗口
      设置搜索路径以便系统可以搜索到 “windeployqt.exe”
      在windeployqt.exe目录下,运行 “windeployqt.exe sample.exe”, 所需要的QT运行库就自动拷贝到目标程序目录了。如果运行报错,重新输入为:./windeployqt.exe sample.exe

  • 相关阅读:
    本地搭建http模拟服务
    spacy教程(持续更新ing...)
    Docker安装MinIO遇到的问题汇总——持续更新中
    nginx中一个请求匹配到多个location时的优先级问题,马失前蹄了
    windows本地搭建mmlspark分布式机器平台流程
    安装PYG
    javaee 事务的传播行为
    java计算机毕业设计员工信息管理系统源码+mysql数据库+系统+lw文档+部署
    GIS工具maptalks开发手册(五)01-用JSON载入地图——json格式绘制多个面之基础版
    Spring MVC
  • 原文地址:https://blog.csdn.net/TOPthemaster/article/details/132700067