#!/bin/bash function initialize { CMAKE_BUILD_DIR="../../cmake_build" BINARIES="${CMAKE_BUILD_DIR}/bin/x64/${MODE}" IO_BINARIES="${BINARIES}/CorePlugins" PACKAGE="${BINARIES}/${TARGET}.app" PLUGINS="${PACKAGE}/Contents/CorePlugins" APPLICATION_DIR="${PACKAGE}/Contents/MacOS" FRAMEWORKS="${PACKAGE}/Contents/Frameworks" OUTPUTDMG="dmg/${DMG_NAME}.dmg" LIBS="libvideostitch.dylib calibrationimport ptvb2ptv videostitch-cmd" EXT_DEPS="../external_deps" # work in the root directory cd .. QT_PATH="${QT_INSTALL}/$(cat qt.version)/clang_64/bin" } function package { # strip the symbols from the lib strip -x -u -r -arch all $1 # for every non-system dependency local dylib for dylib in `otool -L $1 | sed '1d' | egrep -v "/usr/lib/|/System/|Qt|CUDA.framework" | awk '{print $1}'` ; do echo "$1 : dependency ${dylib}" # find its location fullname="${dylib}" fullname="${fullname/@rpath\/libHalf/${EXT_DEPS}/lib/openexr/libHalf}" fullname="${fullname/@rpath\/libIex/${EXT_DEPS}/lib/openexr/libIex}" fullname="${fullname/@rpath\/libIlm/${EXT_DEPS}/lib/openexr/libIlm}" fullname="${fullname/@rpath\/libImath/${EXT_DEPS}/lib/openexr/libImath}" fullname="${fullname/@rpath\/libglfw/${EXT_DEPS}/lib/glfw/libglfw}" fullname="${fullname/@rpath\/libceres/${EXT_DEPS}/lib/ceres/libceres}" fullname="${fullname/@rpath\/libopencv/${EXT_DEPS}/lib/opencv2/lib/libopencv}" fullname="${fullname/@rpath\/libcu//usr/local/cuda-8.0/lib/libcu}" fullname="${fullname/@rpath\/libturbojpeg/${EXT_DEPS}/lib/libjpeg-turbo/libturbojpeg}" fullname="${fullname/@rpath\/libjpeg/${EXT_DEPS}/lib/libjpeg-turbo/libjpeg}" fullname="${fullname/@rpath\/libav/${EXT_DEPS}/lib/ffmpeg/libav}" fullname="${fullname/@rpath\/libx264/${EXT_DEPS}/lib/ffmpeg/libx264}" fullname="${fullname/@rpath\/libmp3/${EXT_DEPS}/lib/ffmpeg/libmp3}" fullname="${fullname/@rpath\/libclang_rt.tsan_osx_dynamic.dylib//Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/8.0.0/lib/darwin/libclang_rt.tsan_osx_dynamic.dylib}" fullname="${fullname/@rpath/.//}" fullname="${fullname/@loader_path\/..//Applications/VLC.app/Contents/MacOS}" fullname="${fullname/@loader_path//Applications/VLC.app/Contents/MacOS}" fullname="${fullname/@executable_path\/..\/Frameworks/$BINARIES}" basefile="$(basename ${fullname})" # package it if needed if [ ! -f "${FRAMEWORKS}/${basefile}" ] && [ ! -f "${PLUGINS}/${basefile}" ] ; then echo "packaging ${basefile}" #Substitution needed because libvideostitch- have id without full path cp "${fullname/libvideostitch/$BINARIES/libvideostitch}" "${FRAMEWORKS}" chmod u+rwx "${FRAMEWORKS}/${basefile}" install_name_tool -id "@executable_path/../Frameworks/${basefile}" "${FRAMEWORKS}/${basefile}" # recursively package its non-system dependencies package "${FRAMEWORKS}/${basefile}" else echo "${basefile} has already been packaged" fi # the dynamic shared library is now in Frameworks echo "install_name_tool -change ${dylib} @executable_path/../Frameworks/$(basename ${dylib}) $1" install_name_tool -change "${dylib}" "@executable_path/../Frameworks/$(basename ${dylib})" "$1" done regex="path (.+) \(offset [0-9]+\)" otool -l "${1}" | grep "path /" | while read -r line ; do if [[ ${line} =~ ${regex} ]]; then path="${BASH_REMATCH[1]}" install_name_tool -delete_rpath "${path}" "${1}" else echo "something went wrong" echo "${line}" exit 1 fi done } function package_apps { if [ ! -e "${PACKAGE}" ] ; then echo "Fatal error: the ${PACKAGE} doesn't exist!" exit 1 fi if [ ! -e "${FRAMEWORKS}" ] ; then mkdir "${FRAMEWORKS}" fi # do what we can't do on Linux: change the dependency paths for elt in ${APPS[@]} ; do if [ -e ${elt} ] ; then if [[ "${elt}" != *"${APPLICATION_DIR}"* ]] ; then tmp="${elt}" elt="${elt/$BINARIES/$APPLICATION_DIR}" cp "${tmp}" "${elt}" fi package "${elt}" else echo "Warning : ${elt} has not been built" fi done LIBCUDA="libvideostitch_cuda.dylib" LIBOPENCL="libvideostitch_opencl.dylib" if [ -f "${BINARIES}/${LIBCUDA}" ] ; then cp "${BINARIES}/${LIBCUDA}" "${FRAMEWORKS}" package "${FRAMEWORKS}/${LIBCUDA}" fi if [ -f "${BINARIES}/${LIBOPENCL}" ] ; then cp "${BINARIES}/${LIBOPENCL}" "${FRAMEWORKS}" package "${FRAMEWORKS}/${LIBOPENCL}" fi libvideostitch="${FRAMEWORKS}/libvideostitch.dylib" libvideostitch_cuda="${FRAMEWORKS}/${LIBCUDA}" libvideostitch_opencl="${FRAMEWORKS}/${LIBOPENCL}" if [ ! -f "${libvideostitch_cuda}" ] && [ ! -f "${libvideostitch_opencl}" ] ; then echo "Fatal error: no libvideostitch backend found!" exit 1 fi if [ -f "${libvideostitch}" ] ; then rm -f "${libvideostitch}" fi if [ -f "${libvideostitch_opencl}" ] ; then ln -s "libvideostitch_opencl.dylib" "${libvideostitch}" else ln -s "libvideostitch_cuda.dylib" "${libvideostitch}" fi } function package_qt { if [ -f "${PACKAGE}/Contents/MacOs/VideoStitch-Studio" ]; then mv "${PACKAGE}/Contents/MacOs/VideoStitch-Studio" "${PACKAGE}/Contents/MacOs/VideoStitch Studio" fi "${QT_PATH}/macdeployqt" "${PACKAGE}" # fix QT Frameworks path elt="${APPLICATION_DIR}/Videostitch Studio" echo "QT for ${elt}" for qtlib in $(otool -L "${elt}" | grep Qt | awk '{print $1}'); do echo "installing ${qtlib}" install_name_tool -change "${qtlib}" "${qtlib/@rpath/@executable_path/../Frameworks}" "${elt}" lib="$(dirname "${elt}")/${qtlib/@rpath/../Frameworks}" install_name_tool -id "${qtlib/@rpath/@executable_path/../Frameworks}" "${lib}" for qtlib2 in $(otool -L ${lib} | grep @rpath | grep Qt | awk '{print $1}'); do install_name_tool -change "${qtlib2}" "${qtlib2/@rpath/@executable_path/../Frameworks}" "${lib}" done done for vs_lib in ${APPLICATION_DIR}/../Frameworks/libvideostitch-base.dylib ${APPLICATION_DIR}/../Frameworks/libvideostitch-gui.dylib ${APPLICATION_DIR}/batchstitcher; do echo "QT for ${vs_lib}" for qtlib in $(otool -L "${vs_lib}" | grep Qt | awk '{print $1}'); do install_name_tool -change "${qtlib}" "${qtlib/@rpath/@executable_path/../Frameworks}" "${vs_lib}" done done for qt_plugin in ${APPLICATION_DIR}/../PlugIns/*/*.dylib; do echo "changing ${qt_plugin}" for qtlib in $(otool -L "${qt_plugin}" | grep Qt | awk '{print $1}'); do install_name_tool -change "${qtlib}" "${qtlib/@rpath/@executable_path/../Frameworks}" "${qt_plugin}" done done } function package_plugins { if [ ! -e "${PACKAGE}" ] ; then echo "Fatal error: the ${PACKAGE} doesn't exist!" exit 1 fi if [ ! -e "${FRAMEWORKS}" ] ; then mkdir "${FRAMEWORKS}" fi if [ ! -e "${PLUGINS}" ] ; then mkdir "${PLUGINS}" fi for plugin in ${PLUGINS_LIB}; do basefile=$(basename ${plugin}) echo "packaging plugin: ${basefile}" # this is the code from package() with different arguments, but I feel introducing new variables # would make it harder to understand what's actually going on for future readers cp "${IO_BINARIES}/${plugin}" "${PLUGINS}" chmod u+rwx "${PLUGINS}/${basefile}" install_name_tool -id "@executable_path/../CorePlugins/${basefile}" "${PLUGINS}/${basefile}" # recursively package its non-system dependencies package "${PLUGINS}/${basefile}" done } function make_dmg { #handle meta + version echo "version is ${VERSION}" gsed 's/<string>9.9.9<\/string>/<string>'"${VERSION}"'<\/string>/' "dmg/${APP}.plist" > "${PACKAGE}/Contents/Info.plist" # temporary fix for umount error: kill squish binaries accessing the disk image pkill videostitch-studio || true # $TARGET makes it easier to handle version numbers in the future if [ -d "/Volumes/${TARGET}" ]; then hdiutil detach -verbose "/Volumes/${TARGET}" fi # give all users read and execute access to the .app, recursively chmod -R og+rx "${PACKAGE}" # codesign --deep --force --verify --verbose=4 --sign "VIDEOSTITCH" "${PACKAGE}" # codesign --deep --verify --verbose=4 "${PACKAGE}" TMP="dmg/videostitch_tmp.dmg" hdiutil create "${TMP}" -volname "${TARGET}" -srcfolder "${PACKAGE}" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -ov #we need to mount the dmg to set the alias to /Applications #and sleep because of MacOS bullshitness sleep 2 device=$(hdiutil attach -readwrite -noverify -noautoopen "${TMP}" | egrep '^/dev/' | sed 1q | awk '{print $1}') trap "hdiutil detach $device; exit" INT TERM EXIT sleep 5 echo "Device: $device" DMG_MOUNT="/Volumes/${TARGET}" # give the package a name with spaces # would need to change nearly every line of this script to escape spaces if done from beginning mv "${DMG_MOUNT}/${TARGET}.app" "${DMG_MOUNT}/${APPLICATION_BUNDLE}.app" #copy the background image in mkdir "${DMG_MOUNT}/.background" cp "dmg/logo_background.png" "${DMG_MOUNT}/.background/" #create an alias to Applications ln -sf /Applications "${DMG_MOUNT}/Applications" #dmg window dimensions dmg_width=522 dmg_height=445 dmg_topleft_x=100 dmg_topleft_y=100 dmg_bottomright_x=$(expr ${dmg_topleft_x} + ${dmg_width}) dmg_bottomright_y=$(expr ${dmg_topleft_y} + ${dmg_height}) #set the background image and icon location echo ' tell application "Finder" tell disk "'${TARGET}'" open tell container window set toolbar visible to false set statusbar visible to false set current view to icon view delay 1 -- sync set the bounds to {'${dmg_topleft_x}', '${dmg_topleft_y}', '${dmg_bottomright_x}', '${dmg_bottomright_y}'} end tell delay 1 -- sync set theViewOptions to the icon view options of container window set arrangement of theViewOptions to not arranged set icon size of theViewOptions to 104 set background picture of theViewOptions to file ".background:'logo_background.png'" set position of item "'${APPLICATION_BUNDLE}.app'" of container window to {120, 125} set position of item "'Applications'" of container window to {385, 125} close open update without registering applications delay 5 end tell end tell ' | osascript trap - INT TERM EXIT echo "Detaching device ${device}" hdiutil detach ${device} #convert to compressed image, delete temp image hdiutil convert "${TMP}" -format UDZO -imagekey zlib-level=9 -o "${OUTPUTDMG}" -ov if [ -f "${TMP}" ] ; then rm -f "${TMP}" fi chmod og+rx "${OUTPUTDMG}" }