- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我是一名 CMake 初学者,在为 MacOS X 创建 Qt 应用程序包时遇到了问题。让我们考虑一个简单的小部件“helloworld”应用程序,它只包含一个 main.cpp
文件。
// 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
。
然后我运行 make
并得到我想要的 QtBundle.app
目录和 QtBundle.app/Contents/MacOS/QtBundle
可执行文件,OK .
但是当我启动它时我得到:
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
并使用大量文件填充包目录在 Framework 和 PlugIns 文件夹中,应用程序能够运行并迁移到另一个系统。
它部分解决了问题,但我想用 CMake 和 BundleUtilities 填充 bundle 并且没有 macdeployqt 工具。
不幸的是,我没有找到使用 BundleUtilities 部署 Qt5 的任何好的简单示例。
有人可以帮助我修改我的“helloworld”示例,使 CMake 自动创建准备部署的包吗?
提前致谢。
最佳答案
将下面的代码添加到 CMakeLists.txt
。最具挑战性的事情是弄清楚您需要什么插件,找到它们的名称,然后为 BundleUtilities 的 fixup_bundle()
正确指定路径。
install_qt5_plugin()
宏按名称定位插件。它只会找到已找到的 Qt 模块的插件。在这种情况下,Qt5::QCocoaIntegrationPlugin 是 Qt5Gui 模块中的插件,它被 find_package(Qt5 COMPONENTS Widgets REQUIRED)
发现为 Qt5Widgets 的依赖项。宏为插件生成 install() 命令并计算已安装插件的完整路径。我们会将后者(参见 QT_PLUGIN
变量)传递给 fixup_bundle()
。
注意事项:
qt.conf
文件,以便在应用程序启动时可以找到插件。APPS
变量指定包的路径,而不是其中的可执行文件。DIRS
非常重要。请注意,它如何使用 CMAKE_PREFIX_PATH。APPS
、QT_PLUGINS
和 DIRS
是可选的,但非常有用。依赖项查找和修复发生在安装时。要在必要的位置获得可重定位的包,可以使用指向该位置的 CMAKE_INSTALL_PREFIX 进行配置,然后构建 install
目标。
我更喜欢创建 .dmg 文件
mkdir build
cd build
cmake ..
cpack -G DragNDrop
要添加到 CMakeLists.txt 的内容来自 here :
set(prefix "${PROJECT_NAME}.app/Contents")
set(INSTALL_RUNTIME_DIR "${prefix}/MacOS")
set(INSTALL_CMAKE_DIR "${prefix}/Resources")
# based on code from CMakes 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)
关于c++ - CMake MacOS X bundle with BundleUtiliies for Qt application,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35612687/
这个问题已经有答案了: Difference between $Bundle install and $Bundle update (2 个回答) 已关闭 9 年前。 bundle 之间有什么区别,
我正在尝试加载 Nib ,但不断收到以下错误: -[NSViewController initWithCoder:] could not instantiate an NSViewController
bundle有什么区别& bundler命令? bundle有什么区别& bundle install ? 如果没有区别,为什么有多个命令做同样的事情? 最佳答案 可执行文件 bundle & bun
我们有托管在应用程序中的单元测试。要加载测试资源,我们使用:Bundle(for: TestClass.self).path(forResource: "some-file", ofType: "js
我刚刚克隆了一个新的 repo 并尝试运行 bundle install但出现以下错误 Fetching gem metadata from https://abcderepos.net/api/ge
我添加了一个共享框架来在应用程序和 watch 扩展之间共享代码。后来我删除了共享框架,因为它会导致很多问题。我可以 build 并在 iphone 上运行我的应用程序并观看。然而,当我提交到应用商店
这个问题有点类似于 this one ,但不完全是。我有一个 C# 游戏引擎,我正在与一些想要使用我的引擎的人一起工作。最初我设计了引擎,以便所有 Assets 都是外部的——非程序员可以创建艺术、音
我正在尝试使用 OSGi 实现客户端-服务器模型。服务器应用程序是在计算机中运行的 OSGi 框架,客户端应用程序远程连接到其控制台并通过 Java 套接字发送命令并接收正确的响应。每个客户端应用程序
我目前正在将我的 Angular 2 应用程序与 WebPack bundle 在一起。我们仍在快速循环,因此我们不想在构建和应用程序加载过程中增加延迟,而是希望包括很少更改的 Angular 2 U
基本上,我有一个捆绑软件,经常在其他 View 中使用,加上其他js文件,因此我可以在保留其顺序的同时将这些文件添加到现有捆绑软件中吗? 最佳答案 我到处都在查找它,但找不到将两个捆绑软件合并在一起的
我有一个大约 12GB 的巨大 mercurial 存储库。我需要在另一台机器上克隆它,但是从网络中提取它需要花费很多时间。当我尝试将所有变更集 bundle 到一个 bundle 文件中时,文件的大
我可以使用 Sonata User Bundle 将 FOS 包集成到 sonata Admin 包中。我的登录功能正常。现在我想添加 FOSUserBundle 中的更改密码等功能到 sonata
如果我检查使用 angular-cli 创建的 angular 2 项目的 index.html 文件,我可以看到该页面仅包含 dist 文件夹中的 3 个文件: inline.bundle.js v
我从程序包管理器http://localhost:4502/crx/packmgr/index.jsp中从正在运行的AEM实例下载了一个zip文件。提取后的zip文件包含jcr_root和META-I
已经提出了有关捆绑名称和捆绑显示名称的类似问题,例如: What's the difference between "bundle display name" and "bundle name" in
我正在尝试在 iTunes 上上传我的应用程序。为此,我创建了一个应用程序 ID 并保留了一个包标识符。在我的项目中,我更改了 info.plist 文件中的包标识符。但是,当我尝试在 itunes
我想从 OSGI 包启动 OSGI 包。正如您所看到的,此代码通过从目录部署它来启动 bundle : private void installStartBundle(BundleContext bc
所以这真的让我头疼,我终于放弃了,在这里发表了问题。我正在尝试更新iTune商店中的一个客户端应用程序,并且在上传到App Store时遇到以下错误。 因此,我已经尝试通过两次使用包sid id创建新
我在 typescript 中使用 aurelia,我想避免使用像这样的相对导入路径: import { DialogBox } from '../../resources/elements/dial
有什么区别 ResourceBundle.getBundle("Bundle") 还有这个 ResourceBundle.getBundle("/Bundle") 最佳答案 来自the Java do
我是一名优秀的程序员,十分优秀!