From 77712b78118aed710ef24002addd1bbdbcccb54e Mon Sep 17 00:00:00 2001
From: Gennady Pospelov <g.pospelov@fz-juelich.de>
Date: Fri, 4 Dec 2015 15:42:52 +0100
Subject: [PATCH] Custom Python framework is added to bundle machinery

---
 cmake/modules/FixAppleBundle.cmake.in | 170 --------------------------
 cmake/scripts/fix_apple_bundle.py     |  56 +++++++--
 2 files changed, 45 insertions(+), 181 deletions(-)

diff --git a/cmake/modules/FixAppleBundle.cmake.in b/cmake/modules/FixAppleBundle.cmake.in
index 971daaf2433..ba23514dd61 100644
--- a/cmake/modules/FixAppleBundle.cmake.in
+++ b/cmake/modules/FixAppleBundle.cmake.in
@@ -3,174 +3,4 @@
 ###############################################################################
 
 set(bundle ${CMAKE_INSTALL_PREFIX}/BornAgain.app )
-set(fix_bundle_command "@PYTHON_EXECUTABLE@ @CMAKE_SOURCE_DIR@/cmake/scripts/fix_apple_bundle.py ${bundle}")
-
-message(INFO "IIIII ${fix_bundle_command}")
-#execute_process(COMMAND @PYTHON_EXECUTABLE@ ${CMAKE_SOURCE_DIR}/cmake/scripts/ ${bundle})
-
 execute_process(COMMAND @PYTHON_EXECUTABLE@ @CMAKE_SOURCE_DIR@/cmake/scripts/fix_apple_bundle.py ${bundle})
-
-
-#set(bornagain_libs ${CMAKE_INSTALL_PREFIX}/@destination_lib@)
-#set(thirdparty_libs ${bundle}/Contents/lib/ThirdParty)
-
-#set(BU_CHMOD_BUNDLE_ITEMS True)
-#set(BU_COPY_FULL_FRAMEWORK_CONTENTS False)
-#include (@CMAKE_SOURCE_DIR@/cmake/modules/BundleUtilitiesWithRPath.cmake)
-
-
-#####################################################
-## gp_resolved_file_type_override
-#####################################################
-#function(gp_resolved_file_type_override resolved_file type_var)
-
-#    if(file MATCHES "Qt")
-#        message("XXX_Qt resolving file as _embedded : ${file}")
-#        set(${type_var} embedded PARENT_SCOPE)
-
-#    elseif(item MATCHES "PlugIns/platforms")
-#        message("XXX_Plugins  resolving file as _embedded : ${file}")
-#        set(${type_var} embedded PARENT_SCOPE)
-
-#    elseif(file MATCHES "Python.framework")
-#        message("XXX_Python  resolving file as system : ${file}")
-#        set(${type_var} system PARENT_SCOPE)
-
-#    elseif(file MATCHES "@cmake_prefix_path1@")
-#        message("XXX_PREFFIX  resolving file as _embedded : ${file}")
-#        set(${type_var} embedded PARENT_SCOPE)
-
-#    elseif(file MATCHES "@cmake_prefix_path2@")
-#        message("XXX_PREFFIX  resolving file as _embedded : ${file}")
-#        set(${type_var} embedded PARENT_SCOPE)
-
-#    elseif(file MATCHES "libBornAgain")
-#        message("XXX_libBornAgain  resolving file as _embedded : ${file}")
-#        set(${type_var} embedded PARENT_SCOPE)
-
-#    else()
-#        message("XXX_System  resolving file as _system   : ${file}")
-#        set(${type_var} system PARENT_SCOPE)
-#    endif()
-#endfunction()
-
-
-#####################################################
-## gp_item_default_embedded_path_override item default_embedded_path_var
-#####################################################
-#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")
-
-#    elseif(item MATCHES "PlugIns/platforms")
-#        set(path "@fixup_path@/PlugIns/platforms")
-
-#    elseif(item MATCHES "libBornAgain")
-#        set(path "@fixup_path@/lib/BornAgain-@BornAgain_VERSION_MAJOR@.@BornAgain_VERSION_MINOR@")
-
-#    elseif(item MATCHES "\\.(dylib|so)$")
-#        set(path "@fixup_path@/lib/ThirdParty")
-
-#    endif()
-
-#  set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
-#endfunction(gp_item_default_embedded_path_override)
-
-
-#####################################################
-## 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()
-
-
-#####################################################
-## Function to tweak Python dependencies
-#####################################################
-#function(fix_python_framework items_to_fix)
-#    message(STATUS "Tweaking Python library dependencies")
-#    foreach(item ${items_to_fix})
-#        message(STATUS "   -> fixing item ${item}")
-#        get_prerequisites(${item} prereqs 0 0 "" "")
-#        foreach(pr ${prereqs})
-#            if(pr MATCHES "Python.framework")
-##            change_bundle_dep( ${pr} "@rpath/lib/ThirdParty/libpython2.7.dylib" ${item})
-#            change_bundle_dep( ${pr} "@rpath/libpython2.7.dylib" ${item})
-#            endif()
-#        endforeach()
-#    endforeach()
-#endfunction()
-
-
-## --- installing Qt plugins
-#file(GLOB_RECURSE QTPLUGINS
-#      "${bundle}/Contents/PlugIns/*@CMAKE_SHARED_LIBRARY_SUFFIX@")
-
-#  set(qtconf_text "
-#[Paths]
-#Plugins = PlugIns
-#  ")
-
-#file(WRITE "${bundle}/Contents/Resources/qt.conf" "${qtconf_text}")
-
-
-#set(dirs
-#    "@CMAKE_BINARY_DIR@/lib"
-#    "$ENV{QTDIR}/plugins"
-#    "$ENV{QTDIR}/lib/QtCore.framework/Versions/Current"
-#    "$ENV{QTDIR}/lib/QtDesigner.framework/Versions/Current"
-#    "$ENV{QTDIR}/lib/QtGui.framework/Versions/Current"
-#    "$ENV{QTDIR}/lib/QtPrintSupport.framework/Versions/Current"
-#    "$ENV{QTDIR}/lib/QtWidgets.framework/Versions/Current"
-#    "$ENV{QTDIR}/lib/QtXml.framework/Versions/Current"
-#    "$ENV{QTDIR}/lib/QtDBus.framework/Versions/Current"
-# )
-
-#set(other_libs ${QTPLUGINS}
-#    "$ENV{QTDIR}/lib/QtCore.framework/Versions/Curent/QtCore"
-#    "$ENV{QTDIR}/lib/QtDesigner.framework/Versions/Curent/QtDesigner"
-#    "$ENV{QTDIR}/lib/QtGui.framework/Versions/Curent/QtGui"
-#    "$ENV{QTDIR}/lib/QtPrintSupport.framework/Versions/Curent/QtPrintSupport"
-#    "$ENV{QTDIR}/lib/QtWidgets.framework/Versions/Curent/QtWidgets"
-#    "$ENV{QTDIR}/lib/QtXml.framework/Versions/Curent/QtXml"
-#    "$ENV{QTDIR}/lib/QtDBus.framework/Versions/Curent/QtDBus"
-#)
-
-#fixup_bundle ( "${bundle}" "${other_libs}" "${dirs}" ) # This will fix up the dependencies for the hard dependencies: MantidKernel etc
-
-
-## --- fixing dependencies from Python libraries ---------
-#set(items_to_fix "${bundle}/Contents/MacOS/BornAgain")
-#file (GLOB items ${bornagain_libs}/*.so)
-#list(APPEND items_to_fix ${items})
-#file (GLOB items ${thirdparty_libs}/*.dylib)
-#list(APPEND items_to_fix ${items})
-
-#fix_python_framework("${items_to_fix}")
-
-
-## --- copying python library ------
-#FILE(MAKE_DIRECTORY "${bundle}/Contents/lib/LibPython")
-#execute_process(COMMAND ${CMAKE_COMMAND} -E copy "@PYTHON_LIBRARIES@" "${bundle}/Contents/lib/LibPython/libpython2.7.dylib")
-
-
-## --- fixing bin directory with thisbornagain.sh links ---------
-#FILE(MAKE_DIRECTORY "${CMAKE_INSTALL_PREFIX}/@destination_bin@")
-
-#execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
-#"../libexec/@destination_suffix@/frombin_setup_paths.sh" "thisbornagain.sh"
-#WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}/@destination_bin@")
-
-#execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
-#"../libexec/@destination_suffix@/frombin_setup_paths.csh" "thisbornagain.csh"
-#WORKING_DIRECTORY "${CMAKE_INSTALL_PREFIX}/@destination_bin@")
-
diff --git a/cmake/scripts/fix_apple_bundle.py b/cmake/scripts/fix_apple_bundle.py
index 8cdeae3e473..aa2fdac5025 100644
--- a/cmake/scripts/fix_apple_bundle.py
+++ b/cmake/scripts/fix_apple_bundle.py
@@ -4,6 +4,7 @@ import platform
 import shutil
 import subprocess
 import glob
+from distutils import sysconfig
 
 BUNDLE_DIR = ""
 
@@ -36,6 +37,10 @@ def bundle_main_executable():
     return os.path.join(bundle_dir(), "Contents", "MacOS", "BornAgain")
 
 
+def bundle_python_library():
+    return os.path.join("Python.framework", "Versions", "2.7", "Python")
+
+
 def qtlibs_path():
     return os.path.join(os.environ['QTDIR'], "lib")
 
@@ -60,7 +65,7 @@ def make_dir(dirname):
         os.makedirs(dirname)
 
 
-def copy_file(file_name, dest_dir):
+def copy_file_to_dir(file_name, dest_dir):
     """
     Copies file to the destination directory. If destination doesn't exists, it will be created.
     """
@@ -100,10 +105,38 @@ def analyse_dependency(dependency_string):
     return file_name
 
 
+def get_python_library_location():
+    """
+    Returns location of Python library. The library is deduced from interpreter itself
+    """
+    for line in otool(sys.executable):
+        dependency = line.strip().split()[0]
+        if os.path.exists(dependency) and "Python.framework" in dependency:
+            return dependency
+    return None
+
+
 # -----------------------------------------------------------------------------
 # Actions
 # -----------------------------------------------------------------------------
 
+
+def copy_python_framework():
+    """
+    Copies Python library to the bundle. The name of the library will be deduced from the interpreter itself.
+    """
+    print "--> Copying Python framework"
+    python_lib = get_python_library_location()
+    destfile = os.path.join(bundle_frameworks_path(), bundle_python_library())
+    make_dir(os.path.dirname(destfile))
+    print "    From '{0}'\n    To '{1}'".format(python_lib, destfile)
+    if not os.path.exists(destfile):
+        shutil.copyfile(python_lib, destfile)
+        libId = "@rpath/" + bundle_python_library()
+        setId(destfile, libId)
+
+
+
 def copy_qt_libraries():
     print "--> Copying Qt libraries"
     libs = ['QtCore', 'QtDBus', 'QtDesigner', 'QtGui', 'QtPrintSupport', 'QtWidgets', 'QtXml', 'QtSvg']
@@ -111,7 +144,7 @@ def copy_qt_libraries():
         libpath = os.path.join(libname+".framework", "Versions", "5")
         srcfile = os.path.join(qtlibs_path(), libpath, libname)
         dstdir = os.path.join(bundle_frameworks_path(), libpath)
-        copy_file(srcfile, dstdir)
+        copy_file_to_dir(srcfile, dstdir)
 
 
 def copy_qt_plugins():
@@ -120,7 +153,7 @@ def copy_qt_plugins():
     for name in plugins:
         srcfile = os.path.join(qtplugins_path(), name)
         dstdir = os.path.join(bundle_plugins_path(), os.path.dirname(name))
-        copy_file(srcfile, dstdir)
+        copy_file_to_dir(srcfile, dstdir)
 
 
 def process_dependency(dependency):
@@ -135,19 +168,19 @@ def process_dependency(dependency):
         print "skipping dependency", dependency
         return libId, None
     print "copying dependency", dependency
-    copy_file(dependency, bundle_frameworks_path())
+    copy_file_to_dir(dependency, bundle_frameworks_path())
     setId(new_location, libId)
     return libId, new_location
 
 
-def get_file_dependencies(file_name, dependency_list = None):
+def walk_through_dependencies(file_name):
     for line in otool(file_name):
         dependency = analyse_dependency(line)
         if dependency:
             libId, new_location = process_dependency(dependency)
             setDependency(file_name, dependency, libId)
             if new_location:
-                get_file_dependencies(new_location)
+                walk_through_dependencies(new_location)
 
             # print "         dependency:", file_name, dependency, os.path.basename(dependency)
             # dependency_list.append(dependency)
@@ -156,14 +189,15 @@ def get_file_dependencies(file_name, dependency_list = None):
 
 def copy_dependencies():
     print "--> collecting dependencies"
-    for bin in iter(bornagain_binaries()):
-        get_file_dependencies(bin)
+    for binfile in iter(bornagain_binaries()):
+        walk_through_dependencies(binfile)
 
 
 def fix_apple_bundle():
-    copy_qt_libraries()
-    copy_qt_plugins()
-    copy_dependencies()
+    copy_python_framework()
+    # copy_qt_libraries()
+    # copy_qt_plugins()
+    # copy_dependencies()
 
 
 if __name__ == '__main__':
-- 
GitLab