如何在Windows上使用CMake打包Qt程序?

5
我正在编写一个跨平台程序,希望在Windows上打包。我把三个DLL文件(Qt5Core、Qt5Widgets、Qt5Gui)放在构建目录中,然后制作了一个tarball并将其发送给另一个使用Windows的人,但是他的Windows电脑无法运行。我搜索了获取所需内容的方法,并找到了Nathan Osman关于windeployqt的帖子,所以我将windeployqt.cmake复制到cmake/Modules目录中,但是无法弄清如何使用它。是否有一种方法可以使用CPack制作一个包(即使只是tarball),其中包含在没有编译器或Qt安装的Windows箱上运行程序所需的所有内容?
这是CMakeLists.txt文件,已删除一些(希望不相关的)内容:
project(perfecttin)
cmake_minimum_required(VERSION 3.8.0)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_CXX_STANDARD 17) # appeared in CMake 3.8
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)
set(SHARE_DIR ${CMAKE_INSTALL_PREFIX}/share/perfecttin)
add_definitions(-DBOOST_ALL_NO_LIB)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(Boost_USE_STATIC_LIBS ON)
else ()
set(Boost_USE_STATIC_LIBS OFF)
endif ()

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
find_package(LibPLYXX)
find_package(Qt5 COMPONENTS Core Widgets Gui LinguistTools REQUIRED)
find_package(Boost COMPONENTS program_options)
find_package(Threads)

qt5_add_resources(lib_resources perfecttin.qrc)
qt5_add_translation(qm_files perfecttin_en.ts perfecttin_es.ts)
# To update translations, run "lupdate *.cpp -ts *.ts" in the source directory.

add_executable(perfecttin-gui adjelev.cpp angle.cpp binio.cpp
           <snip lots of source files>
               unitbutton.cpp ${lib_resources} ${qm_files})
target_link_libraries(perfecttin-gui ${CMAKE_THREAD_LIBS_INIT} Qt5::Widgets Qt5::Core)
target_link_libraries(fuzzptin ${CMAKE_THREAD_LIBS_INIT})
target_compile_definitions(fuzzptin PUBLIC _USE_MATH_DEFINES)
target_compile_definitions(perfecttin-gui PUBLIC _USE_MATH_DEFINES)
set_target_properties(perfecttin-gui PROPERTIES WIN32_EXECUTABLE TRUE)

install(TARGETS perfecttin-gui DESTINATION bin)
install(FILES ${qm_files} DESTINATION share/perfecttin)

include_directories(${PROJECT_BINARY_DIR})
configure_file (config.h.in config.h)

set(CPACK_PACKAGE_VERSION_MAJOR ${PERFECTTIN_MAJOR_VERSION})
set(CPACK_PACKAGE_VERSION_MINOR ${PERFECTTIN_MINOR_VERSION})
set(CPACK_PACKAGE_VERSION_PATCH ${PERFECTTIN_PATCH_VERSION})
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/COPYING)
set(CPACK_SOURCE_IGNORE_FILES /\\\\.git;.*~)
include(CPack)

include(CTest)

你能否提供链接到Nathan Osman关于windeployqt的帖子?听起来很有用! - Troyseph
3
https://blog.nathanosman.com/2017/11/24/using-windeployqt-with-cpack.html - Pierre Abbat
3个回答

2

我从这个答案中借鉴了很多内容,但它缺少必要的环境设置,导致出现警告:找不到GCC安装目录。g++.exe 必须在路径中。

Qt有以下文档介绍如何使用winddeployqt.exe.

The tool can be found in QTDIR/bin/windeployqt. It needs to be run within the build environment in order to function correctly.
When using Qt Installer, the script QTDIR/bin/qtenv2.bat should be used to set it up.

基本上,您需要在正确的环境中作为自定义命令运行windelpoyqt.exe。
# Retrieve the absolute path to qmake and then use that path to find
# the windeployqt executable
get_target_property(QMAKE_EXE Qt6::qmake IMPORTED_LOCATION)
get_filename_component(QT_BIN_DIR"${QMAKE_EXE }" DIRECTORY)

find_program(WINDEPLOYQT_ENV_SETUP qtenv2.bat HINTS "${QT_BIN_DIR}")
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${QT_BIN_DIR}")

# Run windeployqt immediately after build
add_custom_command(TARGET perfecttin-gui
    POST_BUILD
    COMMAND "${WINDEPLOYQT_ENV_SETUP}" && "${WINDEPLOYQT_EXECUTABLE}" \"$<TARGET_FILE:perfectin-gui>\"
)

2
如果您已经在${CMAKE_SOURCE_DIR}/cmake/Modules/目录中有文件Windeployqt.cmake,则可以按照以下方式使用它:
install(TARGETS perfecttin-gui 
    DESTINATION "${INSTALL_BIN_PATH}"
)

if(WIN32)
    include(Windeployqt)
    windeployqt(nitroshare-cli ${INSTALL_BIN_PATH})
endif()

这里 是完整的示例。


你需要为你的项目定义INSTALL_BIN_PATH变量的值,使用set(INSTALL_BIN_PATH "bin")或其他方式。这里是相关文档 - Former contributor
那个页面上没有提到INSTALL_BIN_PATH。我一直在Linux和BSD上使用bin没有问题;我不知道Windows。 - Pierre Abbat
INSTALL_BIN_PATH只是一个变量的名称。您可以创建并给您的变量任何您喜欢的名称。这个名称没有什么特别之处。如果您在CMakeLists.txt中包含(GNUInstallDirs),它将为您提供一个名为CMAKE_INSTALL_BINDIR且默认值为bin的变量。该变量在文档中有提到:对于常规可执行文件、静态库和共享库,不需要DESTINATION参数... - Former contributor
我刚刚在Windows上构建了它。首先,我得到了windeployqt Function invoked with incorrect arguments for function。然后我用"bin"替换了变量,windeployqt(perfecttin-gui bin),并在MinGW上构建,生成了目录iconenginesimageformatsplatformsstylestranslations。然而,在MSVC上失败了,显示C:\Users\phma\build\perfecttin\vs\dbg\perfecttin.exe does not seem to be a Qt executable.。下一步是什么? - Pierre Abbat
https://github.com/phma/perfecttin/blob/master/CMakeLists.txt - Pierre Abbat
显示剩余2条评论

1
自从6.3版本以来,Qt提供了一种定义额外部署步骤的方式,在安装时执行。
- https://www.qt.io/blog/cmake-deployment-api

除其他功能外,现在已经包含了一个*deploy实用脚本生成器。

install(TARGETS perfecttin-gui DESTINATION bin)

qt_generate_deploy_app_script(
    TARGET perfecttin-gui
    FILENAME_VARIABLE deploy_script
    NO_UNSUPPORTED_PLATFORM_ERROR
)
install(SCRIPT ${deploy_script})

文档位于:generate-deploy-app-script
根据目前的文档,这在Linux上不起作用

如果需要更多选项,可以使用上述方便版本实际调用的函数:qt-deploy-runtime-dependencies

例如,qt_generate_deploy_app_script() 将 Qt 插件放在目标“bin”目录之外,每个插件都放在自己的文件夹中,但我不喜欢这样(我希望它们都在“bin”下)。因此,我必须使用完整版本(这基本上都是来自上面链接的 Qt 文档):

set(MY_APP perfecttin-gui)

if(APPLE)
  set(executable_path "$<TARGET_FILE_NAME:${MY_APP}>.app")
else()
  set(executable_path "\${QT_DEPLOY_BIN_DIR}/$<TARGET_FILE_NAME:${MY_APP}>")
endif()

set(deploy_script "${CMAKE_CURRENT_BINARY_DIR}/deploy_${MY_APP}.cmake")

file(GENERATE OUTPUT ${deploy_script} CONTENT "
include(\"${QT_DEPLOY_SUPPORT}\")
qt_deploy_runtime_dependencies(
    EXECUTABLE \"${executable_path}\"
    PLUGINS_DIR bin
)"
)

install(TARGETS ${MY_APP} DESTINATION bin)
install(SCRIPT ${deploy_script})

有关部署的更多详细信息,请参阅https://www.qt.io/blog/cmake-deployment-api

已添加:
找到了qt_deploy_runtime_dependencies()的源码
看起来下一个版本会增加一个NO_TRANSLATIONS选项,但在我的6.4.1版本中没有。
但我找到了一个通过附加选项传递给部署工具的方法...
如果你在代码中搜索__qt_deploy_tool_extra_options,你会看到关于它可能会消失的警告。但作为一种解决方法...

我的file(GENERATE OUTPUT)现在看起来像这样(可能需要根据平台进行调整):

file(GENERATE OUTPUT ${deploy_script} CONTENT "
include(\"${QT_DEPLOY_SUPPORT}\")
set(__qt_deploy_tool_extra_options --no-compiler-runtime --no-translations)
qt_deploy_runtime_dependencies(
    EXECUTABLE \"${executable_path}\"
    PLUGINS_DIR bin
#    NO_TRANSLATIONS
)
")

如果有人感兴趣,还有qt_generate_deploy_app_script()源代码


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接