2016-02-24 52 views
4

我是一名CMake初學者,並且爲Mac OS X創建Qt應用程序包時遇到了問題。讓我們考慮一個簡單的小部件「helloworld」應用程序,只有一個main.cpp文件。CMake MacOS X捆綁包與BundleUtiliies Qt應用程序

// 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和它在Bundle目錄中填充了Framework和PlugIns文件夾中的大量文件,並且應用程序能夠運行並重定位到另一個系統。

它部分解決了這個問題,但我想使用CMake和BundleUtilities以及沒有macdeployqt工具來填充軟件包。

不幸的是我沒有找到任何使用BundleUtilities進行Qt5部署的很好和簡單的例子。

有人可以幫我修改我的'helloworld'的例子,CMake自動創建可以隨時部署的軟件包嗎?

在此先感謝。

主要問題:如何使用CMake BundleUtilities獲取可重定位應用程序?

+0

我也在尋找答案。你有沒有設法解決這個問題?我發現的一切都是來自以前的時代,或者描述得不好,也沒有顯示出來。 – light2yellow

+0

@ light2yellow不,我不使用BundleUtilities,而是使用macdeployqt並在安裝步驟中使用cmake複製必要的文件,並使用Packages製作包。有用。 –

+0

無論如何,我找到了一個很好的例子。看看avogadro或其他kitware項目。 – light2yellow

回答

1

將以下代碼添加到CMakeLists.txt。最具挑戰性的是弄清楚,你需要什麼插件,找到他們的名字,然後爲BundleUtilities'fixup_bundle()正確指定路徑。

install_qt5_plugin()宏按名稱查找插件。它只會找到已經找到的Qt模塊的插件。在這種情況下,Qt5 :: QCocoaIntegrationPlugin是Qt5Gui模塊中的插件,可以通過find_package(Qt5 COMPONENTS Widgets REQUIRED)發現它作爲Qt5Widgets的依賴項。宏爲插件生成install()命令並計算安裝插件的完整路徑。後者我們會通過(見QT_PLUGIN變量)到fixup_bundle()

注:

  1. 我們創建和安裝qt.conf文件,這樣的插件可以發現,應用程序啓動時。
  2. APPS變量指定要綁定的路徑,而不是其中的可執行文件。
  3. 填充DIRS非常重要。請注意,它如何使用CMAKE_PREFIX_PATH。
  4. 印刷APPS,QT_PLUGINSDIRS是可選的,但非常有用。
  5. 應該手動複製/安裝那些沒有從應用程序引用的動態庫(包括插件)。 Qt平臺插件就是這樣的動態庫。

依賴查找和修復發生在安裝上。要在必要的位置獲得可重定位的包,可以使用指向該位置的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 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)