[CMake] CMake 2.8.1 + Qt/Cocoa + OS X Problem -- qt_menu.nib not getting copied

Michael Jackson mike.jackson at bluequartz.net
Fri Apr 16 10:36:43 EDT 2010


Lets take a deeper look at what is needed for an OS X bundle, cmake  
and Qt.

  The issues with making an OS X app bundle "relocatable" are well  
known (those following along at home can Google search..). If you are  
including libraries into the bundle then the "install_name" of those  
libraries/frameworks need to be something like "@executable_path...."  
and placed correctly into the app bundle. This is what  
"BundleUtilities.cmake" does for you. Nothing More.

    The nib file that Qt-Cocoa needs is particular to Qt-Cocoa builds.  
It has NOTHING to do with CMake at all. I, like everyone else, has a  
shell script template and CMake template file that they use to create  
their Qt/Cocoa bundles and we forget that BundleUtilities does NOT  
actually take care of some of this for us. Now, CMake _could_ offer a  
bit better support for Qt/Cocoa by maybe explicitly offering a  
"DeployQtApplication" cmake function that would "do the right thing"  
based on the type of Qt being used (Carbon vs Cocoa), copying plugins,  
copying the nib file, creating a qt.conf file if needed. That would be  
an excellent feature request to submit to the bug tracker.

   If you are interested you are welcome to pull some apps from my git  
repo and take a look at how I am generating the app bundle.

   So, I agree with your philosophical concerns that CMake _could_  
offer some convenience functions to more explicitly deal with Qt/Cocoa.

  Hope that helps.
___________________________________________________________
Mike Jackson                      www.bluequartz.net
Principal Software Engineer       mike.jackson at bluequartz.net
BlueQuartz Software               Dayton, Ohio


On Apr 16, 2010, at 10:13 AM, kent williams wrote:

> If you have the URL of this example, I'd love to look at it. I have
> been poring over the CMake wiki without finding anything.
>
> But that's not what I was concerned about. What bothers me is that:
>
> 1, If you build against Qt-Carbon, this isn't a problem.
> 2. if qtmenu.nib is needed, and it isn't being fixed by
> BundleUtilities::fixup_bundle, then fixup_bundle isn't actually fixing
> up the bundle.
>
> The bug 10000 I found in the CMake bug tracker actually is
> specifically about working around this problem in the specific case of
> building the Qt CMake client.
>
> My broader philosophical concern is that actually making a proper OS X
> bundle with CMake is a process with too many moving parts.  The whole
> point of CMake is to eliminate boilerplate by dealing with the build
> process at a higher level, and this strikes me as definitely something
> that has to happen every time you build a bundle for OSX
>
> On Thu, Apr 15, 2010 at 9:07 PM, Mike Jackson
> <mike.jackson at bluequartz.net> wrote:
>> I do not see any where in your code commands to actually copy the nib
>> file from the qtgui framework into your app bundle. I know thatbthe
>> way I set up my installation code I explicitly put a command to copy
>> the nib file. I believe there is a qt example on the cmake wiki that
>> shows how to do that.
>>
>> -----
>> Mike Jackson                      www.bluequartz.net
>> Principal Software Engineer       mike.jackson at bluequartz.net
>> BlueQuartz Software               Dayton, Ohio
>>
>>
>> On Apr 15, 2010, at 17:06, kent williams <nkwmailinglists at gmail.com>
>> wrote:
>>
>>> I'll include my CMakeLists.txt at the end of this message, but the
>>> long and the short of it is this: My ApplicationBundle crashes  
>>> when I
>>> try and open it with this classic error message:
>>>
>>> Qt internal error: qt_menu.nib could not be loaded. The .nib file
>>> should be placed in QtGui.framework/Versions/Current/Resources/   
>>> or in
>>> the resources directory of your application bundle.
>>>
>>> This is supposed to be fixed, as documented in this bug:
>>>
>>> http://public.kitware.com/Bug/view.php?id=10000
>>>
>>> I checked out the latest GIT CMake and verified that the file in
>>> question is the same in 2.8.1 and current GIT trunk.
>>>
>>> So is there some magical extra step I need to get my bundle properly
>>> fixed up?
>>>
>>> project( BRAINSTracerQT )
>>> cmake_minimum_required(VERSION 2.8)
>>> cmake_policy(VERSION 2.8)
>>>
>>> find_package( VTK REQUIRED )
>>> include(${VTK_USE_FILE})
>>>
>>> find_package( ITK REQUIRED )
>>> include(${ITK_USE_FILE})
>>>
>>> find_package( Qt4 REQUIRED )
>>> if(QT_USE_FILE)
>>>  include(${QT_USE_FILE})
>>>  set(QT_USE_QTXML 1)
>>> else(QT_USE_FILE)
>>>  set( QT_LIBRARIES   ${QT_QT_LIBRARY})
>>> endif(QT_USE_FILE)
>>>
>>> find_package(ModuledescriptionParser REQUIRED)
>>> include(${ModuleDescriptionParser_USE_FILE})
>>>
>>> find_package(TCL REQUIRED)
>>>
>>> find_package( VTK REQUIRED )
>>> include(${VTK_USE_FILE})
>>>
>>> find_package( ITK REQUIRED )
>>> include(${ITK_USE_FILE})
>>> include_directories(
>>>  ${BRAINSTracerQT_SOURCE_DIR}
>>>  ${BRAINSTracerQT_BINARY_DIR}
>>> )
>>>
>>> configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ExecutablePath.h.in
>>>        ${CMAKE_BINARY_DIR}/ExecutablePath.h IMMEDIATE @ONLY)
>>>
>>> add_subdirectory(vtkRenderingAddOn)
>>> include_directories(${BRAINSTracerQT_SOURCE_DIR}/vtkRenderingAddOn)
>>>
>>> set(BRAINSTracerQT_SRCS
>>> main.cxx
>>> BTMainWindow.cxx
>>> vtkKWImage.cxx
>>> vtkKWImage2D.cxx
>>> QVtkImageViewer.cxx
>>> vtkMultiWidgetBase.cxx
>>> vtkMultiContourWidget.cxx
>>> vtkBTPointSetWidget.cxx
>>> vtkBTPointWidget.cxx
>>> PolyDataUtils.cxx
>>> BTContour.cxx
>>> BTPolygon.cxx
>>> DiscreteParticleFilter.cxx
>>> PolygonFill.cxx
>>> LoadMaskImage.cxx
>>> qtcolorpicker.cxx
>>> QVtkPropertyDialog.cxx
>>> QModuleParameterWidget.cxx
>>> QImageParameterWidget.cxx
>>> QFileBrowserParameterWidget.cxx
>>> )
>>>
>>> set(BRAINSTracerQT_HDRS
>>> BTMainWindow.h
>>> QVtkImageViewer.h
>>> qtcolorpicker.h
>>> QVtkPropertyDialog.h
>>> QModuleParameterWidget.h
>>> QImageParameterWidget.h
>>> QFileBrowserParameterWidget.h
>>> )
>>>
>>> set(BRAINSTracerQT_RCCS
>>> BRAINSTracerQT.qrc)
>>>
>>> set(BRAINSTracerQT_UIS
>>> qvtkpropertydialog.ui)
>>>
>>> QT4_WRAP_CPP( MOCSrcs ${BRAINSTracerQT_HDRS} )
>>>
>>> QT4_ADD_RESOURCES(RCC_SRCS ${BRAINSTracerQT_RCCS})
>>>
>>> QT4_WRAP_UI(UIHeaders ${BRAINSTracerQT_UIS} )
>>>
>>> set_source_files_properties(${BRAINSTracerQT_SRCS}
>>> PROPERTIES OBJECT_DEPENDS ${UIHeaders})
>>>
>>> add_definitions(-DQT_GUI_LIBS -DQT_CORE_LIB -DQT3_SUPPORT)
>>>
>>> #set_source_files_properties(${BRAINSTracerQT_SRCS} PROPERTIES
>>> #  OBJECT_DEPENDS "${UIHeaders}")
>>>
>>> add_executable( BRAINSTracerQT
>>>               MACOSX_BUNDLE
>>>               WIN32
>>>               ${BRAINSTracerQT_SRCS}
>>>               ${MOCSrcs}
>>>               ${RCC_SRCS}
>>> )
>>> target_link_libraries( BRAINSTracerQT
>>>  QVTK
>>>  ${QT_LIBRARIES}
>>>  ${ITK_LIBRARIES}
>>>  vtkRenderingAddOn
>>>  vtkRendering
>>>  vtkFiltering
>>>  vtkVolumeRendering
>>>  ${TCL_LIBRARY}
>>>  ModuleDescriptionParser
>>> )
>>>
>>> GET_TARget_property(TARGET_EXEC_DIR BRAINSTracerQT
>>> RUNTIME_OUTPUT_DIRECTORY)
>>> set(TARGET_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/bin")
>>>
>>> set(DEFAULT_MODULE_SEARCH_PATH
>>>        "${TARGET_EXEC_DIR}/Modules")
>>>
>>> #--
>>> ---
>>> ---
>>> ---
>>> ---------------------------------------------------------------------
>>> # Now the installation stuff below
>>> #--
>>> ---
>>> ---
>>> ---
>>> ---------------------------------------------------------------------
>>> SET(plugin_dest_dir bin)
>>> SET(qtconf_dest_dir bin)
>>> SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/BRAINSTracerQT")
>>> IF(APPLE)
>>>  SET(plugin_dest_dir BRAINSTracerQT.app/Contents/MacOS)
>>>  SET(qtconf_dest_dir BRAINSTracerQT.app/Contents/Resources)
>>>  SET(APPS "\${CMAKE_INSTALL_PREFIX}/BRAINSTracerQT.app")
>>> ENDIF(APPLE)
>>> IF(WIN32)
>>>  SET(APPS "\${CMAKE_INSTALL_PREFIX}/bin/BRAINSTracerQT.exe")
>>> ENDIF(WIN32)
>>>
>>> #--
>>> ---
>>> ---
>>> ---
>>> ---------------------------------------------------------------------
>>> # Install the BRAINSTracerQT application, on Apple, the bundle is at
>>> the root of the
>>> # install tree, and on other platforms it'll go into the bin
>>> directory.
>>> INSTALL(TARGETS BRAINSTracerQT
>>>    BUNDLE DESTINATION . COMPONENT Runtime
>>>    RUNTIME DESTINATION bin COMPONENT Runtime
>>>    )
>>>
>>> #--
>>> ---
>>> ---
>>> ---
>>> ---------------------------------------------------------------------
>>> # Install needed Qt plugins by copying directories from the qt
>>> installation
>>> # One can cull what gets copied by using 'REGEX "..." EXCLUDE'
>>> INSTALL(DIRECTORY "${QT_PLUGINS_DIR}/imageformats" DESTINATION
>>> ${plugin_dest_dir}/plugins COMPONENT Runtime)
>>>
>>> #--
>>> ---
>>> ---
>>> ---
>>> ---------------------------------------------------------------------
>>> # install a qt.conf file
>>> # this inserts some cmake code into the install script to write the
>>> file
>>> INSTALL(CODE "
>>>    file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf
>>> \" \"\")
>>>    " COMPONENT Runtime)
>>>
>>>
>>> #--
>>> ---
>>> ---
>>> ---
>>> ---------------------------------------------------------------------
>>> # Use BundleUtilities to get all other dependencies for the
>>> application to work.
>>> # It takes a bundle or executable along with possible plugins and
>>> inspects it
>>> # for dependencies.  If they are not system dependencies, they are
>>> copied.
>>>
>>> # directories to look for dependencies
>>> SET(DIRS
>>> ${QT_LIBRARY_DIRS}
>>> ${ITK_DIR}
>>> ${VTK_DIR}
>>> ${CMAKE_INSTALL_PREFIX}/lib
>>> ${ModuledescriptionParser_DIR}
>>> ${BRAINSTracerQT_BINARY_DIR}/lib
>>> )
>>> MESSAGE(status QT_LIBRARY_DIRS ${QT_LIBRARY_DIRS} ${QT_PLUGINS_DIR})
>>> # Now the work of copying dependencies into the bundle/package
>>> # The quotes are escaped and variables to use at install time have
>>> their $ escaped
>>> # An alternative is the do a configure_file() on a script and use
>>> install(SCRIPT  ...).
>>> # Note that the image plugins depend on QtSvg and QtXml, and it got
>>> those copied
>>> # over.
>>> INSTALL(CODE "
>>>    file(GLOB_RECURSE QTPLUGINS
>>>      \"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/plugins/*$
>>> {CMAKE_SHARED_LIBRARY_SUFFIX}\")
>>>    include(BundleUtilities)
>>>    fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\")
>>>    " COMPONENT Runtime)
>>>
>>>
>>> # To Create a package, one can run "cpack -G DragNDrop
>>> CPackConfig.cmake" on Mac OS X
>>> # where CPackConfig.cmake is created by including CPack
>>> # And then there's ways to customize this as well
>>> set(CPACK_BINARY_DRAGNDROP ON)
>>> include(CPack)
>>> _______________________________________________
>>> Powered by www.kitware.com
>>>
>>> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>>>
>>> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>>>
>>> Follow this link to subscribe/unsubscribe:
>>> http://www.cmake.org/mailman/listinfo/cmake
>>
> _______________________________________________
> Powered by www.kitware.com
>
> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>
> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>
> Follow this link to subscribe/unsubscribe:
> http://www.cmake.org/mailman/listinfo/cmake



More information about the CMake mailing list