1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
# This script creates a fixed an dragndroppable BALLView Bundle
IF(POLICY CMP0011)
CMAKE_POLICY(SET CMP0011 NEW)
ENDIF()
IF(POLICY CMP0012)
CMAKE_POLICY(SET CMP0012 NEW)
ENDIF()
# Fix install names in the given ITEM to match the Bundle installation
MACRO(FIX_BUNDLE_ITEM ITEM)
# This command line call does the following:
# - otool: print all dependencies linked into the dynamic library stored in ${ITEM}.
# - awk: skip first line; for the other lines print only the dependecy name (full path information).
# - grep: skip dependencies that already have @rpath, @executable_path, or @loader_path prefix.
# They (most likely) have already been fixed by macdeployqt.
# Also skip (estimated) system libraries, identified by the following prefixes: /usr/lib, /System
# - tr: convert multiline output into a ';'-separated, proper CMake list.
#
# With the exception of otool, everything else can be replaced by CMake functionality, however, this way it's much shorter.
EXECUTE_PROCESS(COMMAND bash -c "otool -L ${ITEM} | awk '{if (NR >= 2) print $1}' | grep -v -E '(^@|^/usr/lib|^/System)' | tr '\n' ';'"
OUTPUT_VARIABLE INSTALL_NAMES
WORKING_DIRECTORY ${BALLVIEW_BUNDLE_DIR})
# Iterate over all remaining dependencies that are stored in ${INSTALL_NAMES}.
FOREACH(INSTALL_NAME ${INSTALL_NAMES})
# Store file name (without path) in ${INSTALL_NAME_BASE}.
GET_FILENAME_COMPONENT(INSTALL_NAME_BASE ${INSTALL_NAME} NAME)
# Search its location in the Bundle relative to the Bundle's Contents path.
FILE(GLOB INSTALL_NAME_IN_BUNDLE RELATIVE ${BALLVIEW_BUNDLE_DIR_CONTENTS}
${BALLVIEW_BUNDLE_DIR_FRAMEWORKS}/*${INSTALL_NAME_BASE}
${BALLVIEW_BUNDLE_DIR_PLUGINS}/*${INSTALL_NAME_BASE})
IF("${ITEM}" MATCHES "^.*/${INSTALL_NAME_BASE}")
# Fix the install name of the item itself.
EXECUTE_PROCESS(COMMAND install_name_tool -id "@executable_path/../${INSTALL_NAME_IN_BUNDLE}" ${ITEM})
ELSE()
# Fix the install name of a dependency.
EXECUTE_PROCESS(COMMAND install_name_tool -change ${INSTALL_NAME} "@executable_path/../${INSTALL_NAME_IN_BUNDLE}" ${ITEM})
ENDIF()
IF(${INSTALL_NAME_BASE} MATCHES .*so )
EXECUTE_PROCESS(COMMAND install_name_tool -add_rpath "@executable_path/../Frameworks" ${ITEM})
ENDIF()
ENDFOREACH()
ENDMACRO()
# Define some useful variables
SET(BALLVIEW_BUNDLE_DIR ${CMAKE_INSTALL_PREFIX}/BALLView.app)
SET(BALLVIEW_BUNDLE_DIR_CONTENTS ${BALLVIEW_BUNDLE_DIR}/Contents)
SET(BALLVIEW_BUNDLE_DIR_FRAMEWORKS ${BALLVIEW_BUNDLE_DIR_CONTENTS}/Frameworks)
SET(BALLVIEW_BUNDLE_DIR_PLUGINS ${BALLVIEW_BUNDLE_DIR_CONTENTS}/plugins)
SET(ITEMS_TO_FIX "")
# First, install BALLView.app Bundle stub
FILE(INSTALL @CMAKE_RUNTIME_OUTPUT_DIRECTORY@/BALLView.app DESTINATION ${CMAKE_INSTALL_PREFIX} USE_SOURCE_PERMISSIONS)
# Manually install Python and SIP libraries and files
IF(@BALL_PYTHON_SUPPORT@)
FILE(INSTALL @SIP_LIBRARIES@ DESTINATION ${BALLVIEW_BUNDLE_DIR_FRAMEWORKS} USE_SOURCE_PERMISSIONS)
FILE(INSTALL @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/BALL.py DESTINATION ${BALLVIEW_BUNDLE_DIR_FRAMEWORKS} USE_SOURCE_PERMISSIONS)
FILE(INSTALL @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/BALLCore.so DESTINATION ${BALLVIEW_BUNDLE_DIR_FRAMEWORKS} USE_SOURCE_PERMISSIONS)
FILE(INSTALL @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/VIEW.so DESTINATION ${BALLVIEW_BUNDLE_DIR_FRAMEWORKS} USE_SOURCE_PERMISSIONS)
LIST(APPEND ITEMS_TO_FIX ${BALLVIEW_BUNDLE_DIR_FRAMEWORKS}/BALLCore.so ${BALLVIEW_BUNDLE_DIR_FRAMEWORKS}/VIEW.so)
ENDIF()
# Manually install plugins
IF(TARGET pluginBALLaxy)
FILE(INSTALL @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/pluginBALLaxy.dylib DESTINATION ${BALLVIEW_BUNDLE_DIR_PLUGINS} USE_SOURCE_PERMISSIONS)
LIST(APPEND ITEMS_TO_FIX ${BALLVIEW_BUNDLE_DIR_PLUGINS}/pluginBALLaxy.dylib)
ENDIF()
IF(TARGET pluginPresentaBALL)
FILE(INSTALL @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/pluginPresentaBALL.dylib DESTINATION ${BALLVIEW_BUNDLE_DIR_PLUGINS} USE_SOURCE_PERMISSIONS)
LIST(APPEND ITEMS_TO_FIX ${BALLVIEW_BUNDLE_DIR_PLUGINS}/pluginPresentaBALL.dylib)
ENDIF()
IF(TARGET pluginJupyter)
FILE(INSTALL @CMAKE_LIBRARY_OUTPUT_DIRECTORY@/pluginJupyter.dylib DESTINATION ${BALLVIEW_BUNDLE_DIR_PLUGINS} USE_SOURCE_PERMISSIONS)
LIST(APPEND ITEMS_TO_FIX ${BALLVIEW_BUNDLE_DIR_PLUGINS}/pluginJupyter.dylib)
ENDIF()
# Copy BALL data folder into the Bundle
FILE(INSTALL @CMAKE_SOURCE_DIR@/data DESTINATION ${BALLVIEW_BUNDLE_DIR_CONTENTS}/Resources USE_SOURCE_PERMISSIONS)
# Run macdeployqt on BALLView.app
EXECUTE_PROCESS(COMMAND @QT_DEPLOY_EXECUTABLE@ ${BALLVIEW_BUNDLE_DIR})
# Finally, apply manual fixes
FOREACH(ITEM_TO_FIX ${ITEMS_TO_FIX})
FIX_BUNDLE_ITEM(${ITEM_TO_FIX})
ENDFOREACH()
|