用于Qt应用程序的CMake MacOS X捆绑软件和BundleUtiliies [英] CMake MacOS X bundle with BundleUtiliies for Qt application
问题描述
我是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.
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()
.
注意:
- 我们创建并安装
qt.conf
文件,以便在应用程序启动时可以找到插件. -
APPS
变量指定捆绑包的路径,而不是其中的可执行文件. - 填充
DIRS
非常重要.请注意,它如何使用CMAKE_PREFIX_PATH. - 打印
APPS
,QT_PLUGINS
和DIRS
是可选的,但非常有用. - 仅应手动复制/安装未从应用程序引用的那些动态库(包括插件). Qt平台插件就是这样的动态库.
- We create and install
qt.conf
file, so plugin can be found, when application starts. APPS
variable specifies path to bundle, not to executable inside it.- Filling
DIRS
is very important. Note, how it uses CMAKE_PREFIX_PATH. - Printing
APPS
,QT_PLUGINS
andDIRS
is optional yet very useful. - 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屋!