From 958f6626afe3ee0f1a035b9b9ed57a1c65a38028 Mon Sep 17 00:00:00 2001
From: Gennady Pospelov <g.pospelov@fz-juelich.de>
Date: Tue, 11 Nov 2014 23:35:52 +0100
Subject: [PATCH] Refactoring in cmake::FixAppleBundle

---
 CMakeLists.txt                                |   3 +
 GUI/main/CMakeLists.txt                       |  64 ++-
 ...s.cmake => BundleUtilitiesWithRPath.cmake} | 445 ++++++++----------
 cmake/modules/FixBundle.cmake.in              | 109 +++++
 ....cmake => GetPrerequisitesWithRPath.cmake} | 306 ++++++------
 cmake/modules/bundle.cmake.in                 |  21 +
 6 files changed, 535 insertions(+), 413 deletions(-)
 rename cmake/modules/{BABundleUtilities.cmake => BundleUtilitiesWithRPath.cmake} (73%)
 create mode 100644 cmake/modules/FixBundle.cmake.in
 rename cmake/modules/{GetPrerequisites.cmake => GetPrerequisitesWithRPath.cmake} (77%)
 create mode 100644 cmake/modules/bundle.cmake.in

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 80bf158f677..27c07ac1b5e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,6 +24,7 @@ option(BORNAGAIN_RELEASE "Special option for making release" OFF)
 option(BORNAGAIN_CRASHHADLER "Additional machinery to send crash reports" OFF)
 
 
+
 #--- Including macros ---
 set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
 include(BornAgainMacros)
@@ -38,6 +39,8 @@ if(BORNAGAIN_MAN)
     add_subdirectory(Doc/UserManual)
 endif()
 
+set(CMAKE_MACOSX_RPATH 1)
+
 add_subdirectory(Core)
 add_subdirectory(ThirdParty/gtest)
 add_subdirectory(Tests/UnitTests/TestCore)
diff --git a/GUI/main/CMakeLists.txt b/GUI/main/CMakeLists.txt
index d3316322abe..6c600d8c066 100644
--- a/GUI/main/CMakeLists.txt
+++ b/GUI/main/CMakeLists.txt
@@ -107,15 +107,18 @@ IF(APPLE AND CREATE_BUNDLE)
   get_filename_component(qcustomplot_LIBRARY_DIR "${qcustomplot_LIBRARY}" REALPATH)
   get_filename_component(qtpropertybrowser_LIBRARY_DIR "${qtpropertybrowser_LIBRARY}" REALPATH)
   get_filename_component(Boost_Real_LIBRARY_DIR "${Boost_LIBRARY_DIR}" REALPATH)
-#  get_filename_component(PYTHON_LIBRARY_DIR "${PYTHON_REAL_LIBRARY}" PATH)
+#  get_filename_component(PYTHON_LIBRARY_DIR "${PYTHON_LIBRARIES}" REALPATH)
+  get_filename_component(PYTHON_REAL_LIBRARY_DIR "${PYTHON_LIBRARY}" REALPATH)
 
-#  message("PYTHON_LIBRARY_DIR: ${PYTHON_LIBRARY_DIR}")
+  message("OOO PYTHON_LIBRARY_DIR: ${PYTHON_LIBRARY_DIR}  PYTHON_LIBRARY:${PYTHON_LIBRARY}  PYTHON_LIBRARIES:${PYTHON_LIBRARIES}")
+  message("OOO2 PYTHON_REAL_LIBRARY_DIR:${PYTHON_REAL_LIBRARY_DIR}")
+  message("OOO3 CMAKE_LIBRARY_OUTPUT_DIRECTORY:${CMAKE_LIBRARY_OUTPUT_DIRECTORY} CMAKE_LIBRARY_PATH:${CMAKE_LIBRARY_PATH}")
 
   set(DIRS
-    ${ManhattanStyle_LIBRARY_DIR}
-    ${qcustomplot_LIBRARY_DIR}
-    ${qtpropertybrowser_LIBRARY_DIR}
-#    ${PYTHON_LIBRARY_DIR}
+#    ${ManhattanStyle_LIBRARY_DIR}
+#    ${qcustomplot_LIBRARY_DIR}
+#    ${qtpropertybrowser_LIBRARY_DIR}
+    ${PYTHON_REAL_LIBRARY_DIR}
     ${Boost_Real_LIBRARY_DIR}
     "${CMAKE_BINARY_DIR}/lib"
     "$ENV{QTDIR}"
@@ -127,25 +130,36 @@ IF(APPLE AND CREATE_BUNDLE)
     BUNDLE DESTINATION  . COMPONENT Applications
     RUNTIME DESTINATION ${destination_bin} COMPONENT Runtime)
 
-  install(DIRECTORY "$ENV{QTDIR}/plugins/platforms" DESTINATION ${plugin_dest_dir} COMPONENT Runtime)
-
-  set(qtconf_text "
-[Paths]
-Plugins = PlugIns
-  ")
-
-  install(CODE "
-    file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"${qtconf_text}\")
-    " COMPONENT Runtime)
-
-  install(CODE "
-    file(GLOB_RECURSE QTPLUGINS
-      \"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
-    set(BU_CHMOD_BUNDLE_ITEMS True)
-    set(BU_COPY_FULL_FRAMEWORK_CONTENTS False)
-    include(${CMAKE_MODULE_PATH}/BABundleUtilities.cmake)
-    fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\")
-    " COMPONENT Runtime)
+
+#  install(DIRECTORY "$ENV{QTDIR}/plugins/platforms" DESTINATION ${plugin_dest_dir} COMPONENT Runtime)
+
+#  set(qtconf_text "
+#[Paths]
+#Plugins = PlugIns
+#  ")
+
+#  install(CODE "
+#    file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"${qtconf_text}\")
+#    " COMPONENT Runtime)
+
+#  install(CODE "
+#    file(GLOB_RECURSE QTPLUGINS
+#      \"\${CMAKE_INSTALL_PREFIX}/${plugin_dest_dir}/*${CMAKE_SHARED_LIBRARY_SUFFIX}\")
+#    set(BU_CHMOD_BUNDLE_ITEMS True)
+#    set(BU_COPY_FULL_FRAMEWORK_CONTENTS False)
+#    include(${CMAKE_MODULE_PATH}/BABundleUtilities.cmake)
+#    fixup_bundle(\"${APPS}\" \"\${QTPLUGINS}\" \"${DIRS}\")
+#    " COMPONENT Runtime)
+
+#    configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/bundle.cmake.in ${CMAKE_BINARY_DIR}/bundle.cmake @ONLY)
+#    install(SCRIPT ${CMAKE_BINARY_DIR}/bundle.cmake COMPONENT Runtime)
+
+    set(fixup_path @rpath)
+    configure_file(${CMAKE_SOURCE_DIR}/cmake/modules/FixBundle.cmake.in ${CMAKE_BINARY_DIR}/FixBundle.cmake @ONLY)
+    install(SCRIPT ${CMAKE_BINARY_DIR}/FixBundle.cmake COMPONENT Runtime)
+
+#    include(BundleUtilities)
+#    fixup_bundle(${CMAKE_INSTALL_PREFIX}/BornAgain.app "" "")
 
 else()
   install (TARGETS ${executable_name} DESTINATION ${destination_bin} COMPONENT Applications)
diff --git a/cmake/modules/BABundleUtilities.cmake b/cmake/modules/BundleUtilitiesWithRPath.cmake
similarity index 73%
rename from cmake/modules/BABundleUtilities.cmake
rename to cmake/modules/BundleUtilitiesWithRPath.cmake
index e9d5242d30a..9a7586590de 100644
--- a/cmake/modules/BABundleUtilities.cmake
+++ b/cmake/modules/BundleUtilitiesWithRPath.cmake
@@ -1,207 +1,154 @@
-#.rst:
-# BundleUtilities
-# ---------------
-#
-# Functions to help assemble a standalone bundle application.
-#
+# - Functions to help assemble a standalone bundle application.
 # A collection of CMake utility functions useful for dealing with .app
 # bundles on the Mac and bundle-like directories on any OS.
 #
 # The following functions are provided by this module:
-#
-# ::
-#
-#    fixup_bundle
-#    copy_and_fixup_bundle
-#    verify_app
-#    get_bundle_main_executable
-#    get_dotapp_dir
-#    get_bundle_and_executable
-#    get_bundle_all_executables
-#    get_item_key
-#    clear_bundle_keys
-#    set_bundle_key_values
-#    get_bundle_keys
-#    copy_resolved_item_into_bundle
-#    copy_resolved_framework_into_bundle
-#    fixup_bundle_item
-#    verify_bundle_prerequisites
-#    verify_bundle_symlinks
-#
+#   fixup_bundle
+#   copy_and_fixup_bundle
+#   verify_app
+#   get_bundle_main_executable
+#   get_dotapp_dir
+#   get_bundle_and_executable
+#   get_bundle_all_executables
+#   get_item_key
+#   clear_bundle_keys
+#   set_bundle_key_values
+#   get_bundle_keys
+#   copy_resolved_item_into_bundle
+#   copy_resolved_framework_into_bundle
+#   is_resolved_item_embedded
+#   fixup_bundle_item
+#   verify_bundle_prerequisites
+#   verify_bundle_symlinks
 # Requires CMake 2.6 or greater because it uses function, break and
-# PARENT_SCOPE.  Also depends on GetPrerequisites.cmake.
-#
-# ::
-#
-#   FIXUP_BUNDLE(<app> <libs> <dirs>)
+# PARENT_SCOPE. Also depends on GetPrerequisites.cmake.
 #
+#  FIXUP_BUNDLE(<app> <libs> <dirs>)
 # Fix up a bundle in-place and make it standalone, such that it can be
-# drag-n-drop copied to another machine and run on that machine as long
-# as all of the system libraries are compatible.
-#
-# If you pass plugins to fixup_bundle as the libs parameter, you should
-# install them or copy them into the bundle before calling fixup_bundle.
-# The "libs" parameter is a list of libraries that must be fixed up, but
-# that cannot be determined by otool output analysis.  (i.e., plugins)
-#
-# Gather all the keys for all the executables and libraries in a bundle,
-# and then, for each key, copy each prerequisite into the bundle.  Then
-# fix each one up according to its own list of prerequisites.
-#
-# Then clear all the keys and call verify_app on the final bundle to
-# ensure that it is truly standalone.
-#
-# ::
+# drag-n-drop copied to another machine and run on that machine as long as all
+# of the system libraries are compatible.
 #
-#   COPY_AND_FIXUP_BUNDLE(<src> <dst> <libs> <dirs>)
+# If you pass plugins to fixup_bundle as the libs parameter, you should install
+# them or copy them into the bundle before calling fixup_bundle. The "libs"
+# parameter is a list of libraries that must be fixed up, but that cannot be
+# determined by otool output analysis. (i.e., plugins)
 #
-# Makes a copy of the bundle <src> at location <dst> and then fixes up
-# the new copied bundle in-place at <dst>...
+# Gather all the keys for all the executables and libraries in a bundle, and
+# then, for each key, copy each prerequisite into the bundle. Then fix each one
+# up according to its own list of prerequisites.
 #
-# ::
+# Then clear all the keys and call verify_app on the final bundle to ensure
+# that it is truly standalone.
 #
-#   VERIFY_APP(<app>)
+#  COPY_AND_FIXUP_BUNDLE(<src> <dst> <libs> <dirs>)
+# Makes a copy of the bundle <src> at location <dst> and then fixes up the
+# new copied bundle in-place at <dst>...
 #
-# Verifies that an application <app> appears valid based on running
-# analysis tools on it.  Calls "message(FATAL_ERROR" if the application
-# is not verified.
+#  VERIFY_APP(<app>)
+# Verifies that an application <app> appears valid based on running analysis
+# tools on it. Calls "message(FATAL_ERROR" if the application is not verified.
 #
-# ::
+#  GET_BUNDLE_MAIN_EXECUTABLE(<bundle> <result_var>)
+# The result will be the full path name of the bundle's main executable file
+# or an "error:" prefixed string if it could not be determined.
 #
-#   GET_BUNDLE_MAIN_EXECUTABLE(<bundle> <result_var>)
-#
-# The result will be the full path name of the bundle's main executable
-# file or an "error:" prefixed string if it could not be determined.
-#
-# ::
-#
-#   GET_DOTAPP_DIR(<exe> <dotapp_dir_var>)
-#
-# Returns the nearest parent dir whose name ends with ".app" given the
-# full path to an executable.  If there is no such parent dir, then
-# simply return the dir containing the executable.
+#  GET_DOTAPP_DIR(<exe> <dotapp_dir_var>)
+# Returns the nearest parent dir whose name ends with ".app" given the full
+# path to an executable. If there is no such parent dir, then simply return
+# the dir containing the executable.
 #
 # The returned directory may or may not exist.
 #
-# ::
-#
-#   GET_BUNDLE_AND_EXECUTABLE(<app> <bundle_var> <executable_var> <valid_var>)
-#
+#  GET_BUNDLE_AND_EXECUTABLE(<app> <bundle_var> <executable_var> <valid_var>)
 # Takes either a ".app" directory name or the name of an executable
 # nested inside a ".app" directory and returns the path to the ".app"
 # directory in <bundle_var> and the path to its main executable in
 # <executable_var>
 #
-# ::
-#
-#   GET_BUNDLE_ALL_EXECUTABLES(<bundle> <exes_var>)
-#
-# Scans the given bundle recursively for all executable files and
-# accumulates them into a variable.
-#
-# ::
-#
-#   GET_ITEM_KEY(<item> <key_var>)
+#  GET_BUNDLE_ALL_EXECUTABLES(<bundle> <exes_var>)
+# Scans the given bundle recursively for all executable files and accumulates
+# them into a variable.
 #
-# Given a file (item) name, generate a key that should be unique
-# considering the set of libraries that need copying or fixing up to
-# make a bundle standalone.  This is essentially the file name including
-# extension with "." replaced by "_"
+#  GET_ITEM_KEY(<item> <key_var>)
+# Given a file (item) name, generate a key that should be unique considering
+# the set of libraries that need copying or fixing up to make a bundle
+# standalone. This is essentially the file name including extension with "."
+# replaced by "_"
 #
-# This key is used as a prefix for CMake variables so that we can
-# associate a set of variables with a given item based on its key.
+# This key is used as a prefix for CMake variables so that we can associate a
+# set of variables with a given item based on its key.
 #
-# ::
+#  CLEAR_BUNDLE_KEYS(<keys_var>)
+# Loop over the list of keys, clearing all the variables associated with each
+# key. After the loop, clear the list of keys itself.
 #
-#   CLEAR_BUNDLE_KEYS(<keys_var>)
+# Caller of get_bundle_keys should call clear_bundle_keys when done with list
+# of keys.
 #
-# Loop over the list of keys, clearing all the variables associated with
-# each key.  After the loop, clear the list of keys itself.
-#
-# Caller of get_bundle_keys should call clear_bundle_keys when done with
-# list of keys.
-#
-# ::
-#
-#   SET_BUNDLE_KEY_VALUES(<keys_var> <context> <item> <exepath> <dirs>
-#                         <copyflag>)
-#
-# Add a key to the list (if necessary) for the given item.  If added,
+#  SET_BUNDLE_KEY_VALUES(<keys_var> <context> <item> <exepath> <dirs>
+#                        <copyflag>)
+# Add a key to the list (if necessary) for the given item. If added,
 # also set all the variables associated with that key.
 #
-# ::
-#
-#   GET_BUNDLE_KEYS(<app> <libs> <dirs> <keys_var>)
-#
-# Loop over all the executable and library files within the bundle (and
-# given as extra <libs>) and accumulate a list of keys representing
-# them.  Set values associated with each key such that we can loop over
-# all of them and copy prerequisite libs into the bundle and then do
-# appropriate install_name_tool fixups.
-#
-# ::
-#
-#   COPY_RESOLVED_ITEM_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
-#
-# Copy a resolved item into the bundle if necessary.  Copy is not
-# necessary if the resolved_item is "the same as" the
-# resolved_embedded_item.
-#
-# ::
-#
-#   COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
-#
-# Copy a resolved framework into the bundle if necessary.  Copy is not
-# necessary if the resolved_item is "the same as" the
-# resolved_embedded_item.
-#
-# By default, BU_COPY_FULL_FRAMEWORK_CONTENTS is not set.  If you want
-# full frameworks embedded in your bundles, set
-# BU_COPY_FULL_FRAMEWORK_CONTENTS to ON before calling fixup_bundle.  By
-# default, COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE copies the framework
-# dylib itself plus the framework Resources directory.
-#
-# ::
-#
-#   FIXUP_BUNDLE_ITEM(<resolved_embedded_item> <exepath> <dirs>)
-#
-# Get the direct/non-system prerequisites of the resolved embedded item.
-# For each prerequisite, change the way it is referenced to the value of
-# the _EMBEDDED_ITEM keyed variable for that prerequisite.  (Most likely
-# changing to an "@executable_path" style reference.)
-#
-# This function requires that the resolved_embedded_item be "inside" the
-# bundle already.  In other words, if you pass plugins to fixup_bundle
-# as the libs parameter, you should install them or copy them into the
-# bundle before calling fixup_bundle.  The "libs" parameter is a list of
-# libraries that must be fixed up, but that cannot be determined by
-# otool output analysis.  (i.e., plugins)
-#
-# Also, change the id of the item being fixed up to its own
-# _EMBEDDED_ITEM value.
+#  GET_BUNDLE_KEYS(<app> <libs> <dirs> <keys_var>)
+# Loop over all the executable and library files within the bundle (and given
+# as extra <libs>) and accumulate a list of keys representing them. Set
+# values associated with each key such that we can loop over all of them and
+# copy prerequisite libs into the bundle and then do appropriate
+# install_name_tool fixups.
+#
+#  COPY_RESOLVED_ITEM_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
+# Copy a resolved item into the bundle if necessary. Copy is not necessary if
+# the resolved_item is "the same as" the resolved_embedded_item.
+#
+#  COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE(<resolved_item> <resolved_embedded_item>)
+# Copy a resolved framework into the bundle if necessary. Copy is not necessary
+# if the resolved_item is "the same as" the resolved_embedded_item.
+#
+# By default, BU_COPY_FULL_FRAMEWORK_CONTENTS is not set. If you want full
+# frameworks embedded in your bundles, set BU_COPY_FULL_FRAMEWORK_CONTENTS to
+# ON before calling fixup_bundle. By default,
+# COPY_RESOLVED_FRAMEWORK_INTO_BUNDLE copies the framework dylib itself plus
+# the framework Resources directory.
+#
+#  IS_RESOLVED_ITEM_EMBEDDED(<resolved_item> <exepath> <verbose> <is_embedded_var>)
+# Set variable <is_embedded_var> to True if the resolved item is
+# embedded into the bundle. The function does NOT check for the existence of the
+# item, instead if checks if the provided path would correspond to an embeddable
+# item. If <verbose> is True, extra information will be displayed in case the item
+# is not embedded.
+#
+#  FIXUP_BUNDLE_ITEM(<resolved_embedded_item> <exepath> <dirs>)
+# Get the direct/non-system prerequisites of the resolved embedded item. For
+# each prerequisite, change the way it is referenced to the value of the
+# _EMBEDDED_ITEM keyed variable for that prerequisite. (Most likely changing to
+# an "@executable_path" style reference.)
+#
+# This function requires that the resolved_embedded_item be "inside" the bundle
+# already. In other words, if you pass plugins to fixup_bundle as the libs
+# parameter, you should install them or copy them into the bundle before
+# calling fixup_bundle. The "libs" parameter is a list of libraries that must
+# be fixed up, but that cannot be determined by otool output analysis. (i.e.,
+# plugins)
+#
+# Also, change the id of the item being fixed up to its own _EMBEDDED_ITEM
+# value.
 #
 # Accumulate changes in a local variable and make *one* call to
-# install_name_tool at the end of the function with all the changes at
-# once.
+# install_name_tool at the end of the function with all the changes at once.
 #
 # If the BU_CHMOD_BUNDLE_ITEMS variable is set then bundle items will be
 # marked writable before install_name_tool tries to change them.
 #
-# ::
-#
-#   VERIFY_BUNDLE_PREREQUISITES(<bundle> <result_var> <info_var>)
-#
-# Verifies that the sum of all prerequisites of all files inside the
-# bundle are contained within the bundle or are "system" libraries,
-# presumed to exist everywhere.
+#  VERIFY_BUNDLE_PREREQUISITES(<bundle> <result_var> <info_var>)
+# Verifies that the sum of all prerequisites of all files inside the bundle
+# are contained within the bundle or are "system" libraries, presumed to exist
+# everywhere.
 #
-# ::
-#
-#   VERIFY_BUNDLE_SYMLINKS(<bundle> <result_var> <info_var>)
-#
-# Verifies that any symlinks found in the bundle point to other files
-# that are already also in the bundle...  Anything that points to an
-# external file causes this function to fail the verification.
+#  VERIFY_BUNDLE_SYMLINKS(<bundle> <result_var> <info_var>)
+# Verifies that any symlinks found in the bundle point to other files that are
+# already also in the bundle... Anything that points to an external file causes
+# this function to fail the verification.
 
 #=============================================================================
 # Copyright 2008-2009 Kitware, Inc.
@@ -220,7 +167,7 @@
 # (and possibly others) found in:
 #
 get_filename_component(BundleUtilities_cmake_dir "${CMAKE_CURRENT_LIST_FILE}" PATH)
-include("${BundleUtilities_cmake_dir}/GetPrerequisites.cmake")
+include("${BundleUtilities_cmake_dir}/GetPrerequisitesWithRPath.cmake")
 
 
 function(get_bundle_main_executable bundle result_var)
@@ -436,22 +383,52 @@ function(set_bundle_key_values keys_var context item exepath dirs copyflag)
       # embedded path:
       #
       set(embedded_item "${default_embedded_path}/${item_name}")
+
+      if(APPLE)
+        # For executables inside the bundle, extract the expected path.
+        # This remove the hack introduced in commit 6f8bdd27 consisting in
+        # reseting the value of 'resolved_embedded_item' with 'resolved_item'.
+        get_dotapp_dir("${exepath}" exe_dotapp_dir)
+        if(NOT DEFINED gp_bundle_executables)
+          get_bundle_all_executables("${exe_dotapp_dir}" gp_bundle_executables)
+        endif()
+        foreach(exe ${gp_bundle_executables})
+          get_item_key("${exe}" exe_key)
+          list(APPEND exe_keys ${exe_key})
+        endforeach()
+        list(FIND exe_keys ${key} is_executable)
+        if(NOT is_executable EQUAL "-1")
+          get_filename_component(resolved_item_path ${resolved_item} PATH)
+          file(RELATIVE_PATH exe_relative_path_from_dir ${exe_dotapp_dir} ${resolved_item_path})
+          # For example, if input variables are:
+          #   resolved_item:       /path/to/MyApp.app/Contents/bin/myapp
+          #   exe_dotapp_dir:      /path/to/MyApp.app
+          # Computed variables will be:
+          #   resolved_item_path:         /path/to/MyApp.app/Contents/bin
+          #   exe_relative_path_from_dir: Contents/bin
+          set(embedded_item "@executable_path/../../${exe_relative_path_from_dir}/${item_name}")
+          set(show_status 0)
+          if(show_status)
+            message(STATUS "resolved_item='${resolved_item}'")
+            message(STATUS "exe_dotapp_dir='${exe_dotapp_dir}'")
+            message(STATUS "exe_relative_path_from_dir='${exe_relative_path_from_dir}'")
+            message(STATUS "item_name='${item_name}'")
+            message(STATUS "embedded_item='${embedded_item}'")
+            message(STATUS "")
+          endif()
+        endif()
+      endif()
     endif()
 
-    # Replace @executable_path and resolve ".." references:
-    #
-    string(REPLACE "@executable_path" "${exepath}" resolved_embedded_item "${embedded_item}")
+    gp_resolve_embedded_item("${context}" "${embedded_item}" "${exepath}" resolved_embedded_item)
     get_filename_component(resolved_embedded_item "${resolved_embedded_item}" ABSOLUTE)
 
-    # *But* -- if we are not copying, then force resolved_embedded_item to be
-    # the same as resolved_item. In the case of multiple executables in the
-    # original bundle, using the default_embedded_path results in looking for
-    # the resolved executable next to the main bundle executable. This is here
-    # so that exes in the other sibling directories (like "bin") get fixed up
-    # properly...
-    #
-    if(NOT copyflag)
-      set(resolved_embedded_item "${resolved_item}")
+    # Do not copy already embedded item
+    set(verbose 0)
+    is_resolved_item_embedded("${resolved_embedded_item}" "${exepath}" "${verbose}" is_embedded)
+    if(EXISTS "${resolved_embedded_item}" AND is_embedded)
+      set(copyflag 0)
+      set(resolved_item "${resolved_embedded_item}")
     endif()
 
     set(${keys_var} ${${keys_var}} PARENT_SCOPE)
@@ -479,7 +456,7 @@ function(get_bundle_keys app libs dirs keys_var)
 
     # But do fixups on all executables in the bundle:
     #
-    get_bundle_all_executables("${bundle}" exes)
+    get_bundle_all_executables("${bundle}" gp_bundle_executables)
 
     # For each extra lib, accumulate a key as well and then also accumulate
     # any of its prerequisites. (Extra libs are typically dynamically loaded
@@ -500,7 +477,7 @@ function(get_bundle_keys app libs dirs keys_var)
     # The list of keys should be complete when all prerequisites of all
     # binaries in the bundle have been analyzed.
     #
-    foreach(exe ${exes})
+    foreach(exe ${gp_bundle_executables})
       # Add the exe itself to the keys:
       #
       set_bundle_key_values(${keys_var} "${exe}" "${exe}" "${exepath}" "${dirs}" 0)
@@ -593,36 +570,43 @@ function(copy_resolved_framework_into_bundle resolved_item resolved_embedded_ite
 
 endfunction()
 
-
-function(fixup_bundle_item resolved_embedded_item exepath dirs)
-  # This item's key is "ikey":
-  #
-  get_item_key("${resolved_embedded_item}" ikey)
-
-  # Ensure the item is "inside the .app bundle" -- it should not be fixed up if
-  # it is not in the .app bundle... Otherwise, we'll modify files in the build
-  # tree, or in other varied locations around the file system, with our call to
-  # install_name_tool. Make sure that doesn't happen here:
-  #
+function(is_resolved_item_embedded resolved_item exepath verbose is_embedded_var)
   get_dotapp_dir("${exepath}" exe_dotapp_dir)
   string(LENGTH "${exe_dotapp_dir}/" exe_dotapp_dir_length)
-  string(LENGTH "${resolved_embedded_item}" resolved_embedded_item_length)
+  string(LENGTH "${resolved_item}" resolved_item_length)
   set(path_too_short 0)
   set(is_embedded 0)
-  if(${resolved_embedded_item_length} LESS ${exe_dotapp_dir_length})
+  if(${resolved_item_length} LESS ${exe_dotapp_dir_length})
     set(path_too_short 1)
   endif()
   if(NOT path_too_short)
-    string(SUBSTRING "${resolved_embedded_item}" 0 ${exe_dotapp_dir_length} item_substring)
+    string(SUBSTRING "${resolved_item}" 0 ${exe_dotapp_dir_length} item_substring)
     if("${exe_dotapp_dir}/" STREQUAL "${item_substring}")
       set(is_embedded 1)
     endif()
   endif()
-  if(NOT is_embedded)
+  if(verbose AND NOT is_embedded)
     message("  exe_dotapp_dir/='${exe_dotapp_dir}/'")
     message("  item_substring='${item_substring}'")
-    message("  resolved_embedded_item='${resolved_embedded_item}'")
+    message("  resolved_item='${resolved_item}'")
     message("")
+  endif()
+  set(${is_embedded_var} ${is_embedded} PARENT_SCOPE)
+endfunction()
+
+function(fixup_bundle_item resolved_embedded_item exepath dirs)
+  # This item's key is "ikey":
+  #
+  get_item_key("${resolved_embedded_item}" ikey)
+
+  # Ensure the item is "inside the .app bundle" -- it should not be fixed up if
+  # it is not in the .app bundle... Otherwise, we'll modify files in the build
+  # tree, or in other varied locations around the file system, with our call to
+  # install_name_tool. Make sure that doesn't happen here:
+  #
+  set(verbose 1)
+  is_resolved_item_embedded("${resolved_embedded_item}" "${exepath}" "${verbose}" is_embedded)
+  if(NOT is_embedded)
     message("Install or copy the item into the bundle before calling fixup_bundle.")
     message("Or maybe there's a typo or incorrect path in one of the args to fixup_bundle?")
     message("")
@@ -658,48 +642,6 @@ function(fixup_bundle_item resolved_embedded_item exepath dirs)
   )
 endfunction()
 
-function(fixup_python_framework exepath dirs)
-  if(APPLE)
-        message(STATUS "Begin fixup python framework")
-        file(GLOB_RECURSE file_list "${exepath}/../Frameworks/Python.framework/*Python")
-        set(depends "")
-        set(file_need_fix "")
-        foreach(file ${file_list})
-               set(prereqs "")
-               get_prerequisites("${file}" prereqs 1 1 "${exepath}" "${dirs}")
-               if(prereqs)
-                        gp_append_unique(file_need_fix  "${file}")
-                        foreach(pr ${prereqs})
-                                gp_append_unique(depends  "${pr}")
-                        endforeach(pr)
-               endif(prereqs)
-        endforeach(file)
-        set(embed_deps "")
-        foreach(dep ${depends})
-                GET_FILENAME_COMPONENT(dep_name "${dep}" NAME)
-                if(NOT EXISTS "${exepath}/../MacOS/${dep_name}")        
-                        execute_process(COMMAND ${CMAKE_COMMAND} -E copy "${dep}" "${exepath}/../MacOS")
-                        gp_append_unique(embed_deps  "${exepath}/../MacOS/${dep_name}")
-                endif(NOT EXISTS "${exepath}/../MacOS/${dep_name}")
-        endforeach(dep)
-        set(file_list ${file_need_fix} ${embed_deps})
-        foreach(f ${file_list})
-                GET_FILENAME_COMPONENT(fname "${f}" NAME)
-                set(prereqs "")
-                get_prerequisites("${f}" prereqs 1 0 "${exepath}" "${dirs}")
-                set(changes "")
-                foreach(pr ${prereqs})
-                        GET_FILENAME_COMPONENT(pfname "${pr}" NAME)
-                        set(changes ${changes} "-change" "${pr}" "@executable_path/../MacOS/${pfname}")
-                endforeach(pr)
-                execute_process(COMMAND chmod u+w "${f}")
-                execute_process(COMMAND install_name_tool
-                ${changes} -id "@executable_path/../MacOS/${fname}" "${f}")
-        endforeach(f)
-        message(STATUS "end fixup python framework")
-  endif(APPLE)
-endfunction(fixup_python_framework)
-
 
 function(fixup_bundle app libs dirs)
   message(STATUS "fixup_bundle")
@@ -708,9 +650,17 @@ function(fixup_bundle app libs dirs)
   message(STATUS "  dirs='${dirs}'")
 
   get_bundle_and_executable("${app}" bundle executable valid)
+  message(STATUS "  bundle='${bundle}'")
+  message(STATUS "  executable='${executable}'")
   if(valid)
     get_filename_component(exepath "${executable}" PATH)
 
+    # TODO: Extract list of rpath dirs automatically. On MacOSX, the following could be
+    #       done: otool -l path/to/executable | grep -A 3 LC_RPATH | grep path
+    #       See http://www.mikeash.com/pyblog/friday-qa-2009-11-06-linking-and-install-names.html#comment-87ea054b4839586412727dcfc94c79d2
+    set(GP_RPATH_DIR ${bundle}/Contents)
+    message(STATUS "  GP_RPATH_DIR='${GP_RPATH_DIR}'")
+
     message(STATUS "fixup_bundle: preparing...")
     get_bundle_keys("${app}" "${libs}" "${dirs}" keys)
 
@@ -727,7 +677,7 @@ function(fixup_bundle app libs dirs)
         message(STATUS "${i}/${n}: *NOT* copying '${${key}_RESOLVED_ITEM}'")
       endif()
 
-      set(show_status 1)
+      set(show_status 0)
       if(show_status)
         message(STATUS "key='${key}'")
         message(STATUS "item='${${key}_ITEM}'")
@@ -765,14 +715,6 @@ function(fixup_bundle app libs dirs)
     message(STATUS "fixup_bundle: cleaning up...")
     clear_bundle_keys(keys)
 
-    message(STATUS "XXX ${exepath} ${dirs}")
-#    fixup_python_framework("${exepath}" "${dirs}")
-
-    set(install_name_tool_cmd "install_name_tool -change @executable_path/../Frameworks/Python.framework/Versions/2.7/Python @rpath/Python ${exepath}/libBornAgainCore.so")
-    message(STATUS "XXX ${install_name_tool_cmd}")
-    execute_process(COMMAND chmod u+w "${exepath}/libBornAgainCore.so")
-    execute_process(COMMAND ${install_name_tool_cmd})
-
     message(STATUS "fixup_bundle: verifying...")
     verify_app("${app}")
   else()
@@ -892,7 +834,6 @@ function(verify_app app)
   endif()
 
   if(NOT verified)
-#    message(FATAL_ERROR "error: verify_app failed")
-    message(WARNING "error: verify_app failed")
+    message(FATAL_ERROR "error: verify_app failed")
   endif()
 endfunction()
diff --git a/cmake/modules/FixBundle.cmake.in b/cmake/modules/FixBundle.cmake.in
new file mode 100644
index 00000000000..340394f4e5a
--- /dev/null
+++ b/cmake/modules/FixBundle.cmake.in
@@ -0,0 +1,109 @@
+
+set ( bundle ${CMAKE_INSTALL_PREFIX}/BornAgain.app )
+
+message("AAAAA @CMAKE_SOURCE_DIR@")
+
+file ( GLOB pyqt_libs ${bundle}/Contents/MacOS/PyQt4/*.so )
+file ( GLOB mantid_plugins ${bundle}/plugins/*.dylib )
+file ( GLOB_RECURSE qtplugins ${bundle}/Contents/Frameworks/plugins/*.dylib )
+file ( GLOB_RECURSE mtdqtplugins ${bundle}/plugins/*.dylib )
+file ( GLOB_RECURSE pvplugins ${bundle}/pvplugins/*.dylib )
+file ( GLOB vatesplugins ${bundle}/pvplugins/*.dylib ) # Find just the top level Vates plugins
+
+# gp_resolved_file_type_override
+#   Sets the type of the dependency. The options are: system, local, embedded, other
+#   For OS X, system & embedded dependencies are NOT copied in to the bundle
+function(gp_resolved_file_type_override resolved_file type_var)
+
+    if(file MATCHES "Qt")
+        message("XXX  resolving file as _embedded : ${file}")
+        set(${type_var} embedded PARENT_SCOPE)
+    elseif(file MATCHES "Python.framework")
+        message("XXX  resolving file as _embedded : ${file}")
+        set(${type_var} embedded PARENT_SCOPE)
+    else()
+        message("XXX  resolving file as _system   : ${file}")
+        set(${type_var} system PARENT_SCOPE)
+    endif()
+
+
+#  if(resolved_file MATCHES "^/usr(|/local)/lib")
+#    message(STATUS "resolving ${file} as system")
+#    set(${type_var} system PARENT_SCOPE)
+#  endif()
+#  # Copy Qt dependencies to bundle
+#  if(file MATCHES "libQt")
+#    message("resolving ${file} as embedded")
+#    set(${type_var} embedded PARENT_SCOPE)
+#  endif()
+#  # Don't copy ParaView into the bundle
+#  if(resolved_file MATCHES "^@ParaView_DIR@")
+#    message(STATUS "resolving ParaView dependency ${file} as system")
+#    set(${type_var} system PARENT_SCOPE)
+#  endif()
+endfunction()
+
+# gp_item_default_embedded_path_override item default_embedded_path_var
+#
+# Return the path that others should refer to the item by when the item
+# is embedded inside a bundle.
+#
+# This is a project-specific override of BundleUtilities.cmake's
+# gp_item_default_embedded_path
+#
+function(gp_item_default_embedded_path_override item default_embedded_path_var)
+
+    # By default, embed items as set by gp_item_default_embedded_path:
+    set(path "${${default_embedded_path_var}}")
+
+    if(item MATCHES "[^/]+\\.framework/")
+        set(path "@fixup_path@/Frameworks")
+    endif()
+
+
+#    if(item MATCHES "Python.framework")
+##        set( path "@rpath" )
+#        set(path "@fixup_path@")
+##        set( overridden 1 PARENT_SCOPE )
+#        message("YYY 1.1 path_override to ${path} item:${item}")
+#    else()
+#        set( path "@executable_path/../MacOS" )
+#        message("YYY  1.2 path_override to ${path} item:${item}")
+#    endif()
+
+  set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
+
+endfunction(gp_item_default_embedded_path_override)
+
+
+set(BU_CHMOD_BUNDLE_ITEMS True)
+set(BU_COPY_FULL_FRAMEWORK_CONTENTS False)
+
+#include (BundleUtilities)
+include (@CMAKE_SOURCE_DIR@/cmake/modules/BundleUtilitiesWithRPath.cmake)
+
+#set ( mantidpydir ${bundle}/Contents/MacOS/mantid )
+#set ( mantidpylibs ${mantidpydir}/kernel/_kernel.so
+#                   ${mantidpydir}/geometry/_geometry.so
+#                   ${mantidpydir}/api/_api.so )
+
+#set ( other_libs ${bundle}/Contents/MacOS/mantidqtpython.so
+#		 ${mantid_plugins}
+#                 ${pyqt_libs} ${qtplugins} ${pvplugins}
+#                 ${mantidpylibs} ${mtdqtplugins} )
+
+#set ( dirs "@CMAKE_LIBRARY_OUTPUT_DIRECTORY@" "@CMAKE_LIBRARY_PATH@" /Library/Frameworks /opt/intel/lib )
+
+fixup_bundle ( "${bundle}" "${other_libs}" "${dirs}" ) # This will fix up the dependencies for the hard dependencies: MantidKernel etc
+
+####################################################
+# Functions to change the dependency references
+####################################################
+function( change_bundle_id new_id sharedlib )
+  execute_process(COMMAND install_name_tool -id ${new_id} ${sharedlib})
+endfunction()
+
+function( change_bundle_dep old_dep new_dep sharedlib )
+  execute_process(COMMAND install_name_tool -change ${old_dep} ${new_dep} ${sharedlib})
+endfunction()
+
diff --git a/cmake/modules/GetPrerequisites.cmake b/cmake/modules/GetPrerequisitesWithRPath.cmake
similarity index 77%
rename from cmake/modules/GetPrerequisites.cmake
rename to cmake/modules/GetPrerequisitesWithRPath.cmake
index ac649e9af9c..528c540392f 100644
--- a/cmake/modules/GetPrerequisites.cmake
+++ b/cmake/modules/GetPrerequisitesWithRPath.cmake
@@ -1,164 +1,136 @@
-#.rst:
-# GetPrerequisites
-# ----------------
-#
-# Functions to analyze and list executable file prerequisites.
-#
-# This module provides functions to list the .dll, .dylib or .so files
-# that an executable or shared library file depends on.  (Its
+# - Functions to analyze and list executable file prerequisites.
+# This module provides functions to list the .dll, .dylib or .so
+# files that an executable or shared library file depends on. (Its
 # prerequisites.)
 #
-# It uses various tools to obtain the list of required shared library
-# files:
-#
-# ::
-#
-#    dumpbin (Windows)
-#    objdump (MinGW on Windows)
-#    ldd (Linux/Unix)
-#    otool (Mac OSX)
-#
+# It uses various tools to obtain the list of required shared library files:
+#   dumpbin (Windows)
+#   objdump (MinGW on Windows)
+#   ldd (Linux/Unix)
+#   otool (Mac OSX)
 # The following functions are provided by this module:
-#
-# ::
-#
-#    get_prerequisites
-#    list_prerequisites
-#    list_prerequisites_by_glob
-#    gp_append_unique
-#    is_file_executable
-#    gp_item_default_embedded_path
-#      (projects can override with gp_item_default_embedded_path_override)
-#    gp_resolve_item
-#      (projects can override with gp_resolve_item_override)
-#    gp_resolved_file_type
-#      (projects can override with gp_resolved_file_type_override)
-#    gp_file_type
-#
-# Requires CMake 2.6 or greater because it uses function, break, return
-# and PARENT_SCOPE.
-#
-# ::
-#
-#   GET_PREREQUISITES(<target> <prerequisites_var> <exclude_system> <recurse>
-#                     <exepath> <dirs>)
-#
-# Get the list of shared library files required by <target>.  The list
-# in the variable named <prerequisites_var> should be empty on first
-# entry to this function.  On exit, <prerequisites_var> will contain the
-# list of required shared library files.
-#
-# <target> is the full path to an executable file.  <prerequisites_var>
-# is the name of a CMake variable to contain the results.
-# <exclude_system> must be 0 or 1 indicating whether to include or
-# exclude "system" prerequisites.  If <recurse> is set to 1 all
-# prerequisites will be found recursively, if set to 0 only direct
-# prerequisites are listed.  <exepath> is the path to the top level
-# executable used for @executable_path replacment on the Mac.  <dirs> is
-# a list of paths where libraries might be found: these paths are
-# searched first when a target without any path info is given.  Then
-# standard system locations are also searched: PATH, Framework
-# locations, /usr/lib...
-#
-# ::
-#
-#   LIST_PREREQUISITES(<target> [<recurse> [<exclude_system> [<verbose>]]])
-#
+#   get_prerequisites
+#   list_prerequisites
+#   list_prerequisites_by_glob
+#   gp_append_unique
+#   is_file_executable
+#   gp_item_default_embedded_path
+#     (projects can override with gp_item_default_embedded_path_override)
+#   gp_resolve_item
+#     (projects can override with gp_resolve_item_override)
+#   gp_resolve_embedded_item
+#     (projects can override with gp_resolve_embedded_item_override)
+#   gp_resolved_file_type
+#     (projects can override with gp_resolved_file_type_override)
+#   gp_file_type
+# Requires CMake 2.6 or greater because it uses function, break, return and
+# PARENT_SCOPE.
+#
+#  GET_PREREQUISITES(<target> <prerequisites_var> <exclude_system> <recurse>
+#                    <exepath> <dirs>)
+# Get the list of shared library files required by <target>. The list in
+# the variable named <prerequisites_var> should be empty on first entry to
+# this function. On exit, <prerequisites_var> will contain the list of
+# required shared library files.
+#
+# <target> is the full path to an executable file. <prerequisites_var> is the
+# name of a CMake variable to contain the results. <exclude_system> must be 0
+# or 1 indicating whether to include or exclude "system" prerequisites. If
+# <recurse> is set to 1 all prerequisites will be found recursively, if set to
+# 0 only direct prerequisites are listed. <exepath> is the path to the top
+# level executable used for @executable_path replacment on the Mac. <dirs> is
+# a list of paths where libraries might be found: these paths are searched
+# first when a target without any path info is given. Then standard system
+# locations are also searched: PATH, Framework locations, /usr/lib...
+#
+#  LIST_PREREQUISITES(<target> [<recurse> [<exclude_system> [<verbose>]]])
 # Print a message listing the prerequisites of <target>.
 #
-# <target> is the name of a shared library or executable target or the
-# full path to a shared library or executable file.  If <recurse> is set
-# to 1 all prerequisites will be found recursively, if set to 0 only
-# direct prerequisites are listed.  <exclude_system> must be 0 or 1
-# indicating whether to include or exclude "system" prerequisites.  With
-# <verbose> set to 0 only the full path names of the prerequisites are
-# printed, set to 1 extra informatin will be displayed.
-#
-# ::
-#
-#   LIST_PREREQUISITES_BY_GLOB(<glob_arg> <glob_exp>)
-#
-# Print the prerequisites of shared library and executable files
-# matching a globbing pattern.  <glob_arg> is GLOB or GLOB_RECURSE and
-# <glob_exp> is a globbing expression used with "file(GLOB" or
-# "file(GLOB_RECURSE" to retrieve a list of matching files.  If a
-# matching file is executable, its prerequisites are listed.
+# <target> is the name of a shared library or executable target or the full
+# path to a shared library or executable file. If <recurse> is set to 1 all
+# prerequisites will be found recursively, if set to 0 only direct
+# prerequisites are listed. <exclude_system> must be 0 or 1 indicating whether
+# to include or exclude "system" prerequisites. With <verbose> set to 0 only
+# the full path names of the prerequisites are printed, set to 1 extra
+# informatin will be displayed.
+#
+#  LIST_PREREQUISITES_BY_GLOB(<glob_arg> <glob_exp>)
+# Print the prerequisites of shared library and executable files matching a
+# globbing pattern. <glob_arg> is GLOB or GLOB_RECURSE and <glob_exp> is a
+# globbing expression used with "file(GLOB" or "file(GLOB_RECURSE" to retrieve
+# a list of matching files. If a matching file is executable, its prerequisites
+# are listed.
 #
 # Any additional (optional) arguments provided are passed along as the
 # optional arguments to the list_prerequisites calls.
 #
-# ::
-#
-#   GP_APPEND_UNIQUE(<list_var> <value>)
-#
-# Append <value> to the list variable <list_var> only if the value is
-# not already in the list.
-#
-# ::
+#  GP_APPEND_UNIQUE(<list_var> <value>)
+# Append <value> to the list variable <list_var> only if the value is not
+# already in the list.
 #
-#   IS_FILE_EXECUTABLE(<file> <result_var>)
+#  IS_FILE_EXECUTABLE(<file> <result_var>)
+# Return 1 in <result_var> if <file> is a binary executable, 0 otherwise.
 #
-# Return 1 in <result_var> if <file> is a binary executable, 0
-# otherwise.
-#
-# ::
-#
-#   GP_ITEM_DEFAULT_EMBEDDED_PATH(<item> <default_embedded_path_var>)
+# GP_IS_FILE_EXECUTABLE_EXCLUDE_REGEX can be set to a regular expression used
+# to give a hint to identify more quickly if a given file is an executable or not.
+# This is particularly useful on unix platform where it can avoid a lot of
+# time-consuming call to "file" external process. For packages bundling hundreds
+# of libraries, executables, resources and data, it largely speeds up the function
+# "get_bundle_all_executables".
+# On unix, a convenient command line allowing to collect recursively all file extensions
+# useful to generate a regular expression like "\\.(dylib|py|pyc|so)$" is:
+#   find . -type f -name '*.*' | sed 's@.*/.*\.@@' | sort | uniq | tr "\\n" "|"
 #
+#  GP_ITEM_DEFAULT_EMBEDDED_PATH(<item> <default_embedded_path_var>)
 # Return the path that others should refer to the item by when the item
 # is embedded inside a bundle.
 #
 # Override on a per-project basis by providing a project-specific
 # gp_item_default_embedded_path_override function.
 #
-# ::
-#
-#   GP_RESOLVE_ITEM(<context> <item> <exepath> <dirs> <resolved_item_var>)
-#
+#  GP_RESOLVE_ITEM(<context> <item> <exepath> <dirs> <resolved_item_var>)
 # Resolve an item into an existing full path file.
 #
 # Override on a per-project basis by providing a project-specific
 # gp_resolve_item_override function.
 #
-# ::
+#  GP_RESOLVE_EMBEDDED_ITEM(<context> <embedded_item> <exepath> <resolved_embedded_item_var>)
+# Resolve an embedded item into the full path within the full path. Since the item can be
+# copied later, it doesn't have to exist when calling this function.
 #
-#   GP_RESOLVED_FILE_TYPE(<original_file> <file> <exepath> <dirs> <type_var>)
+# Override on a per-project basis by providing a project-specific
+# gp_resolve_embedded_item_override function.
+#
+# If GP_RPATH_DIR variable is set then item matching '@rpath' are
+# resolved using the provided directory. Currently setting this variable
+# has an effect only on MacOSX when fixing up application bundle. The directory
+# are also assumed to be located within the application bundle. It is
+# usually the directory passed to the 'rpath' linker option.
 #
-# Return the type of <file> with respect to <original_file>.  String
-# describing type of prerequisite is returned in variable named
-# <type_var>.
+#  GP_RESOLVED_FILE_TYPE(<original_file> <file> <exepath> <dirs> <type_var>)
+# Return the type of <file> with respect to <original_file>. String
+# describing type of prerequisite is returned in variable named <type_var>.
 #
 # Use <exepath> and <dirs> if necessary to resolve non-absolute <file>
 # values -- but only for non-embedded items.
 #
 # Possible types are:
-#
-# ::
-#
-#    system
-#    local
-#    embedded
-#    other
-#
+#   system
+#   local
+#   embedded
+#   other
 # Override on a per-project basis by providing a project-specific
 # gp_resolved_file_type_override function.
 #
-# ::
-#
-#   GP_FILE_TYPE(<original_file> <file> <type_var>)
-#
-# Return the type of <file> with respect to <original_file>.  String
-# describing type of prerequisite is returned in variable named
-# <type_var>.
+#  GP_FILE_TYPE(<original_file> <file> <type_var>)
+# Return the type of <file> with respect to <original_file>. String
+# describing type of prerequisite is returned in variable named <type_var>.
 #
 # Possible types are:
-#
-# ::
-#
-#    system
-#    local
-#    embedded
-#    other
+#   system
+#   local
+#   embedded
+#   other
 
 #=============================================================================
 # Copyright 2008-2009 Kitware, Inc.
@@ -220,6 +192,14 @@ function(is_file_executable file result_var)
   # via the get_prerequisites macro.
   #
   if(UNIX)
+
+    if(NOT "${GP_IS_FILE_EXECUTABLE_EXCLUDE_REGEX}" STREQUAL "")
+      if(${file_full} MATCHES "${GP_IS_FILE_EXECUTABLE_EXCLUDE_REGEX}")
+        set(${result_var} 0 PARENT_SCOPE)
+        return()
+      endif()
+    endif()
+
     if(NOT file_cmd)
       find_program(file_cmd "file")
       mark_as_advanced(file_cmd)
@@ -370,14 +350,29 @@ function(gp_resolve_item context item exepath dirs resolved_item_var)
     if(item MATCHES "@rpath")
       #
       # @rpath references are relative to the paths built into the binaries with -rpath
-      # We handle this case like we do for other Unixes
+      # We handle this case like we do for other Unixes.
+      #
+      # Two cases of item resolution are considered:
+      #
+      #  (1) item has been copied into the bundle
+      #
+      #  (2) item has NOT been copied into the bundle: Since the item can exist in a build or
+      #      install tree outside of the bundle, the item is resolved using its name and the
+      #      passed list of directories.
       #
       string(REPLACE "@rpath/" "" norpath_item "${item}")
 
       set(ri "ri-NOTFOUND")
-      find_file(ri "${norpath_item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
+      if(EXISTS ${GP_RPATH_DIR}/${norpath_item})
+        set(ri ${GP_RPATH_DIR}/${norpath_item})
+        set(_msg "'find_file' in GP_RPATH_DIR (${ri})")
+      else()
+        get_filename_component(norpath_item_name ${norpath_item} NAME)
+        find_file(ri "${norpath_item_name}" ${exepath} ${dirs} NO_DEFAULT_PATH)
+        set(_msg "'find_file' in exepath/dirs (${ri})")
+      endif()
       if(ri)
-        #message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
+        #message(STATUS "info: ${_msg}")
         set(resolved 1)
         set(resolved_item "${ri}")
         set(ri "ri-NOTFOUND")
@@ -469,6 +464,46 @@ warning: cannot resolve item '${item}'
   set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
 endfunction()
 
+function(gp_resolve_embedded_item context embedded_item exepath resolved_embedded_item_var)
+  #message(STATUS "**")
+  set(resolved 0)
+  set(resolved_embedded_item "${embedded_item}")
+
+  if(embedded_item MATCHES "@executable_path")
+    string(REPLACE "@executable_path" "${exepath}" resolved_embedded_item "${embedded_item}")
+    set(resolved 1)
+  endif()
+  if(EXISTS "${GP_RPATH_DIR}" AND embedded_item MATCHES "@rpath")
+    string(REPLACE "@rpath" "${GP_RPATH_DIR}" resolved_embedded_item "${embedded_item}")
+    set(resolved 1)
+  endif()
+
+  # Provide a hook so that projects can override embedded item resolution
+  # by whatever logic they choose:
+  #
+  if(COMMAND gp_resolve_embedded_item_override)
+    gp_resolve_embedded_item_override(
+      "${context}" "${embedded_item}" "${exepath}" resolved_embedded_item resolved)
+  endif()
+
+  if(NOT resolved)
+    message(STATUS "
+warning: cannot resolve embedded item '${embedded_item}'
+  possible problems:
+    need more directories?
+    need to use InstallRequiredSystemLibraries?
+    run in install tree instead of build tree?
+
+    context='${context}'
+    embedded_item='${embedded_item}'
+    GP_RPATH_DIR='${GP_RPATH_DIR}'
+    exepath='${exepath}'
+    resolved_embedded_item_var='${resolved_embedded_item_var}'
+")
+  endif()
+
+  set(${resolved_embedded_item_var} "${resolved_embedded_item}" PARENT_SCOPE)
+endfunction()
 
 function(gp_resolved_file_type original_file file exepath dirs type_var)
   #message(STATUS "**")
@@ -483,7 +518,7 @@ function(gp_resolved_file_type original_file file exepath dirs type_var)
 
   set(resolved_file "${file}")
 
-  if("${file}" MATCHES "^@(executable|loader)_path")
+  if("${file}" MATCHES "^@(executable_|loader_|r)path")
     set(is_embedded 1)
   endif()
 
@@ -496,13 +531,13 @@ function(gp_resolved_file_type original_file file exepath dirs type_var)
     string(TOLOWER "${resolved_file}" lower)
 
     if(UNIX)
-      if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/|/usr/bin/)")
+      if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11/|/usr/X11R6/|/usr/bin/|/usr/.*/lib/)")
         set(is_system 1)
       endif()
     endif()
 
     if(APPLE)
-      if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)")
+      if(resolved_file MATCHES "^(/System/Library/|/usr/lib/|/opt/X11/)")
         set(is_system 1)
       endif()
     endif()
@@ -688,6 +723,7 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa
     set(gp_regex_fallback "")
     set(gp_regex_cmp_count 1)
     set(gp_tool_known 1)
+    set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE.
   endif()
 
   if("${gp_tool}" STREQUAL "objdump")
@@ -738,11 +774,9 @@ function(get_prerequisites target prerequisites_var exclude_system recurse exepa
 
   if("${gp_tool}" STREQUAL "ldd")
     set(old_ld_env "$ENV{LD_LIBRARY_PATH}")
-    set(new_ld_env "${exepath}")
-    foreach(dir ${dirs})
-      set(new_ld_env "${new_ld_env}:${dir}")
+    foreach(dir ${exepath} ${dirs})
+      set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}")
     endforeach()
-    set(ENV{LD_LIBRARY_PATH} "${new_ld_env}:$ENV{LD_LIBRARY_PATH}")
   endif()
 
 
diff --git a/cmake/modules/bundle.cmake.in b/cmake/modules/bundle.cmake.in
new file mode 100644
index 00000000000..96d72efd312
--- /dev/null
+++ b/cmake/modules/bundle.cmake.in
@@ -0,0 +1,21 @@
+
+
+
+
+message(STATUS "aaaa @INBUNDLE@")
+
+set(BU_CHMOD_BUNDLE_ITEMS True)
+set(BU_COPY_FULL_FRAMEWORK_CONTENTS False)
+
+set(plugin_dest_dir @INBUNDLE@/Contents/PlugIns)
+set(qtconf_dest_dir @INBUNDLE@/Contents/Resources)
+set(APPS @CMAKE_INSTALL_PREFIX@/@INBUNDLE@)
+
+
+file(GLOB_RECURSE QTPLUGINS "@CMAKE_INSTALL_PREFIX@/${plugin_dest_dir}/*@CMAKE_SHARED_LIBRARY_SUFFIX@")
+message("AAAAA QTPLUGINS ${QTPLUGINS}")
+message("AAAAA QTPLUGINS ${QTPLUGINS}")
+
+include(BundleUtilities)
+fixup_bundle(${APPS} "${QTPLUGINS}" "@DIRS@")
+
-- 
GitLab