用于Qt应用程序的CMake MacOS X捆绑软件和BundleUtiliies [英] CMake MacOS X bundle with BundleUtiliies for Qt application

查看:96
本文介绍了用于Qt应用程序的CMake MacOS X捆绑软件和BundleUtiliies的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是CMake初学者,在为MacOS X创建Qt应用程序捆绑包时遇到问题.让我们考虑一个仅包含在main.cpp文件中的简单小部件"helloworld"应用程序.

I am a CMake beginner and have an issue with creation of an Qt application bundle for MacOS X. Let's consider a simple widget "helloworld" app in only one main.cpp file.

// main.cpp
#include <QApplication>
#include <QLabel>

int main(int argc, char** argv)
{
    QApplication app(argc,argv);
    QLabel lbl("Hello");
    lbl.show();
    return app.exec();
}

CMakeLists.txt文件也很简单.

# CMakeLists.txt
cmake_minimum_required( VERSION 3.0 )
project( QtBundle )    
set( CMAKE_INCLUDE_CURRENT_DIR ON )
set( CMAKE_AUTOMOC ON )

set( SOURCES main.cpp )    
find_package( Qt5Widgets REQUIRED )

add_executable( ${PROJECT_NAME} MACOSX_BUNDLE ${SOURCES} )    
qt5_use_modules( ${PROJECT_NAME} Widgets )

我运行cmake .. -DCMAKE_PREFIX_PATH=/path/to/Qt5.5.1/,它会在build目录中生成Makefile.

I run cmake .. -DCMAKE_PREFIX_PATH=/path/to/Qt5.5.1/ and it generates Makefile in the build directory.

然后我运行make,并根据需要具有QtBundle.app目录和QtBundle.app/Contents/MacOS/QtBundle可执行文件,确定.

Then I run make and have QtBundle.app directory as I wanted and QtBundle.app/Contents/MacOS/QtBundle executable, OK.

但是当我启动它时,我得到:

But when I launch it I get:

This application failed to start because it could not find or load the Qt platform plugin "cocoa".

Reinstalling the application may fix this problem.
Abort trap: 6 

据我所知发生错误是因为应用程序捆绑包没有任何Qt东西(框架库和插件),所以我运行macdeployqt,它将在框架和PlugIns文件夹中填充很多文件的捆绑目录并且该应用程序可以运行并重新定位到另一个系统.

As far as I understand that error is occurred because application bundle doesn't have any Qt stuffs (Framework libs and plugins), so I run macdeployqt and it populates bundles directory with a lot of files in Framework and PlugIns folders and application is able to run and relocate to another system.

它部分解决了问题,但我想用CMake和

It partially solves the problem but I want to populate bundle with CMake and BundleUtilities and without macdeployqt tool.

不幸的是,我没有找到任何通过BundleUtilities部署Qt5的简单好例子.

Unfortunately I didn't find any good and simple example for Qt5 deployment with BundleUtilities.

有人可以帮助我修改我的"helloworld"示例,以使CMake自动创建准备部署的捆绑包吗?

先谢谢了.

推荐答案

将以下代码添加到CMakeLists.txt.最具挑战性的事情是弄清楚您需要哪些插件,找到它们的名称,然后为BundleUtilities的fixup_bundle()正确指定路径.

Add the code below to CMakeLists.txt. The most challenging thing is to figure out, what plugins do you need, find their names and then properly specify paths for BundleUtilities' fixup_bundle().

install_qt5_plugin()宏按名称查找插件.它只会找到已经找到的Qt模块的插件.在这种情况下,Qt5 :: QCocoaIntegrationPlugin是Qt5Gui模块中的插件,由find_package(Qt5 COMPONENTS Widgets REQUIRED)发现它是Qt5Widgets的依赖项.宏会为插件生成install()命令,并计算已安装插件的完整路径.后者我们将传递给(参见QT_PLUGIN变量)到fixup_bundle().

install_qt5_plugin() macro locates plugin by name. It will only find plugin for Qt module already found. In this case Qt5::QCocoaIntegrationPlugin is plugin in Qt5Gui module, which is found as dependency for Qt5Widgets by find_package(Qt5 COMPONENTS Widgets REQUIRED). Macro generates install() command for plugin and calculates full path to installed plugin. The latter we'll pass (see QT_PLUGIN variable) to fixup_bundle().

注意:

  1. 我们创建并安装qt.conf文件,以便在应用程序启动时可以找到插件.
  2. APPS变量指定捆绑包的路径,而不是其中的可执行文件.
  3. 填充DIRS非常重要.请注意,它如何使用CMAKE_PREFIX_PATH.
  4. 打印APPSQT_PLUGINSDIRS是可选的,但非常有用.
  5. 仅应手动复制/安装未从应用程序引用的那些动态库(包括插件). Qt平台插件就是这样的动态库.
  1. We create and install qt.conf file, so plugin can be found, when application starts.
  2. APPS variable specifies path to bundle, not to executable inside it.
  3. Filling DIRS is very important. Note, how it uses CMAKE_PREFIX_PATH.
  4. Printing APPS, QT_PLUGINS and DIRS is optional yet very useful.
  5. One should manually copy/install only those dynamic libraries (including plugins), that aren't referenced from app. Qt platform plugin is such dynamic library.

依赖关系查找和修复在安装时发生.为了在需要的位置获得可重定位的捆绑包,可以使用指向该位置的CMAKE_INSTALL_PREFIX进行配置,然后构建install目标.

Dependencies lookup and fixing happens on installation. To get relocatable bundle in necessary location one may configure with CMAKE_INSTALL_PREFIX pointing to that location and then build install target.

我更喜欢使用.pmg创建.dmg文件

I prefer creating .dmg file with

mkdir build
cd build
cmake ..
cpack -G DragNDrop

要添加到CMakeLists.txt中的内容来自此处:

Contents to add to CMakeLists.txt is from here:

set(prefix "${PROJECT_NAME}.app/Contents")
set(INSTALL_RUNTIME_DIR "${prefix}/MacOS")
set(INSTALL_CMAKE_DIR "${prefix}/Resources")

# based on code from CMake's QtDialog/CMakeLists.txt
macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var _prefix)
    get_target_property(_qt_plugin_path "${_qt_plugin_name}" LOCATION)
    if(EXISTS "${_qt_plugin_path}")
        get_filename_component(_qt_plugin_file "${_qt_plugin_path}" NAME)
        get_filename_component(_qt_plugin_type "${_qt_plugin_path}" PATH)
        get_filename_component(_qt_plugin_type "${_qt_plugin_type}" NAME)
        set(_qt_plugin_dest "${_prefix}/PlugIns/${_qt_plugin_type}")
        install(FILES "${_qt_plugin_path}"
            DESTINATION "${_qt_plugin_dest}")
        set(${_qt_plugins_var}
            "${${_qt_plugins_var}};\$ENV{DEST_DIR}\${CMAKE_INSTALL_PREFIX}/${_qt_plugin_dest}/${_qt_plugin_file}")
    else()
        message(FATAL_ERROR "QT plugin ${_qt_plugin_name} not found")
    endif()
endmacro()

install_qt5_plugin("Qt5::QCocoaIntegrationPlugin" QT_PLUGINS ${prefix})
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
    "[Paths]\nPlugins = ${_qt_plugin_dir}\n")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf"
    DESTINATION "${INSTALL_CMAKE_DIR}")

# Destination paths below are relative to ${CMAKE_INSTALL_PREFIX}
install(TARGETS ${PROJECT_NAME}
    BUNDLE DESTINATION . COMPONENT Runtime
    RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR} COMPONENT Runtime
    )

# Note Mac specific extension .app
set(APPS "\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}.app")

# Directories to look for dependencies
set(DIRS "${CMAKE_BINARY_DIR}")

# Path used for searching by FIND_XXX(), with appropriate suffixes added
if(CMAKE_PREFIX_PATH)
    foreach(dir ${CMAKE_PREFIX_PATH})
        list(APPEND DIRS "${dir}/bin" "${dir}/lib")
    endforeach()
endif()

# Append Qt's lib folder which is two levels above Qt5Widgets_DIR
list(APPEND DIRS "${Qt5Widgets_DIR}/../..")

include(InstallRequiredSystemLibraries)

message(STATUS "APPS: ${APPS}")
message(STATUS "QT_PLUGINS: ${QT_PLUGINS}")
message(STATUS "DIRS: ${DIRS}")

install(CODE "include(BundleUtilities)
    fixup_bundle(\"${APPS}\" \"${QT_PLUGINS}\" \"${DIRS}\")")

set(CPACK_GENERATOR "DRAGNDROP")
include(CPack)

这篇关于用于Qt应用程序的CMake MacOS X捆绑软件和BundleUtiliies的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆