File indexing completed on 2024-05-12 04:28:29
0001 #!/usr/bin/env zsh 0002 # 0003 # SPDX-License-Identifier: GPL-3.0-or-later 0004 # 0005 0006 # Krita tool to create dmg from installed source 0007 # Copies all files to a folder to be converted into the final dmg 0008 0009 # osxdeploy.sh automates the creation of the release DMG. 0010 # default background and style are used if none provided 0011 0012 # A short explanation of what it does: 0013 0014 # - Copies krita.app contents to kritadmg folder 0015 # - Copies i/share to Contents/Resources excluding unnecessary files 0016 # - Copies translations, qml and quicklook PlugIns 0017 # - Copies i/plugins and i/lib/plugins to Contents/PlugIns 0018 0019 # - Runs macdeployqt: macdeployqt is not built by default in ext_qt 0020 # build by: 0021 # cd ${BUILDROOT}/depbuild/ext_qt/ext_qt-prefix/src/ext_qt/qttools/src 0022 # make sub-macdeployqt-all 0023 # make sub-macdeployqt-install_subtargets 0024 # make install 0025 0026 # the script changes dir to installation/bin to run macdeployqt as it can be buggy 0027 # if not run from the same folder as the binary is on. 0028 0029 # - Fix rpath from krita bin 0030 # - Find missing libraries from plugins and copy to Frameworks or plugins. 0031 # This uses oTool iterative to find all unique libraries, then it searches each 0032 # library fond in <kritadmg> folder, and if not found attempts to copy contents 0033 # to the appropriate folder, either Frameworks (if frameworks is in namefile, or 0034 # library has plugin is not in path), or plugin if otherwise. 0035 0036 # - Builds DMG 0037 # Building DMG creates a new dmg with the contents of <kritadmg> 0038 # mounts the dmg and sets the style for dmg. 0039 # unmount 0040 # Compress resulting dmg into krita_nightly-<gitsha>.dmg 0041 # deletes temporary files. 0042 0043 if [[ -n "$ZSH_VERSION" ]]; then 0044 emulate -L ksh; 0045 fi 0046 0047 if [[ -z $BUILDROOT ]]; then 0048 echo "ERROR: BUILDROOT env not set!" 0049 echo "\t Must point to the root of the buildfiles as stated in 3rdparty Readme" 0050 echo "exiting..." 0051 exit 1 0052 fi 0053 0054 BUILDROOT="${BUILDROOT%/}" 0055 0056 # print status messages 0057 print_msg() { 0058 printf "\e[32m${1}\e[0m\n" "${@:2}" 0059 # printf "%s\n" "${1}" >> ${OUTPUT_LOG} 0060 } 0061 0062 # print error 0063 print_error() { 0064 printf "\e[31m%s %s\e[0m\n" "Error:" "${1}" 0065 } 0066 0067 get_script_dir() { 0068 if [[ -n "$ZSH_VERSION" ]]; then 0069 script_source="${(%):-%x}" 0070 else 0071 # transitional, macos should use ZSH 0072 script_source="${BASH_SOURCE[0]}" 0073 fi 0074 # go to target until finding root. 0075 while [ -L "${script_source}" ]; do 0076 script_target="$(readlink ${script_source})" 0077 if [[ "${script_source}" = /* ]]; then 0078 script_source="$script_target" 0079 else 0080 script_dir="$(dirname "${script_source}")" 0081 script_source="${script_dir}/${script_target}" 0082 fi 0083 done 0084 echo "$(dirname ${script_source})" 0085 } 0086 0087 DMG_title="krita" #if changed krita.temp.dmg must be deleted manually 0088 SCRIPT_SOURCE_DIR="$(get_script_dir)" 0089 0090 # There is some duplication between build and deploy scripts 0091 # a config env file could would be a nice idea. 0092 if [[ -z "${KIS_SRC_DIR}" ]]; then 0093 KIS_SRC_DIR=${BUILDROOT}/krita 0094 fi 0095 if [[ -z "${KIS_BUILD_DIR}" ]]; then 0096 KIS_BUILD_DIR=${BUILDROOT}/kisbuild 0097 fi 0098 KIS_INSTALL_DIR=${BUILDROOT}/i 0099 KRITA_DMG=${BUILDROOT}/kritadmg 0100 KRITA_DMG_TEMPLATE=${BUILDROOT}/kritadmg-template 0101 0102 export PATH=${KIS_INSTALL_DIR}/bin:$PATH 0103 0104 # flags for OSX environment 0105 # We only support from 10.13 up 0106 export MACOSX_DEPLOYMENT_TARGET=10.13 0107 export QMAKE_MACOSX_DEPLOYMENT_TARGET=10.13 0108 0109 KRITA_VERSION="$(${KIS_INSTALL_DIR}/bin/krita_version -v)" 0110 0111 0112 print_usage () { 0113 printf "USAGE: 0114 osxdeploy.sh [-s=<identity>] [-notarize-ac=<apple-account>] [-style=<style.txt>] [-bg=<background-image>] 0115 0116 -s \t\t\t Code sign identity for codesign 0117 0118 -notarize-ac \t Apple account name for notarization purposes 0119 \t\t\t script will attempt to get password from keychain, if fails provide one with 0120 \t\t\t the -notarize-pass option: To add a password run 0121 0122 \t\t\t security add-generic-password -a \"AC_USERNAME\" -w <secret_password> -s \"AC_PASSWORD\" 0123 0124 -notarize-pass \t If given, the Apple account password. Otherwise an attempt will be macdeployqt_exists 0125 \t\t\t to get the password from keychain using the account given in <notarize-ac> option. 0126 0127 -asc-provider \t some AppleIds might need this option pass the <shortname> 0128 0129 -style \t\t Style file defined from 'dmgstyle.sh' output 0130 0131 -bg \t\t Set a background image for dmg folder. 0132 0133 -name \t\t Set the DMG name output. 0134 0135 \t\t\t osxdeploy needs an input image to attach to the dmg background 0136 \t\t\t image recommended size is at least 950x500 0137 " 0138 } 0139 0140 # Attempt to detach previous mounted DMG 0141 if [[ -d "/Volumes/${DMG_title}" ]]; then 0142 echo "WARNING: Another Krita DMG is mounted!" 0143 echo "Attempting eject…" 0144 hdiutil detach "/Volumes/${DMG_title}" 0145 if [ $? -ne 0 ]; then 0146 exit 1 0147 fi 0148 echo "Success!" 0149 fi 0150 0151 # -- Parse input args 0152 for arg in "${@}"; do 0153 if [ "${arg}" = -bg=* -a -f "${arg#*=}" ]; then 0154 DMG_validBG=0 0155 bg_filename=${arg#*=} 0156 echo "attempting to check background is valid jpg or png..." 0157 BG_FORMAT=$(sips --getProperty format ${bg_filename} | awk '{printf $2}') 0158 0159 if [[ "png" = ${BG_FORMAT} || "jpeg" = ${BG_FORMAT} ]];then 0160 echo "valid image file" 0161 DMG_background=$(cd "$(dirname "${bg_filename}")"; pwd -P)/$(basename "${bg_filename}") 0162 DMG_validBG=1 0163 # check imageDPI 0164 BG_DPI=$(sips --getProperty dpiWidth ${DMG_background} | grep dpi | awk '{print $2}') 0165 if [[ $(echo "${BG_DPI} > 150" | bc -l) -eq 1 ]]; then 0166 printf "WARNING: image dpi has an effect on apparent size! 0167 Check dpi is adequate for screen display if image appears very small 0168 Current dpi is: %s\n" ${BG_DPI} 0169 fi 0170 fi 0171 fi 0172 # If string starts with -sign 0173 if [[ ${arg} = -s=* ]]; then 0174 CODE_SIGNATURE="${arg#*=}" 0175 fi 0176 0177 if [[ ${arg} = -name=* ]]; then 0178 DMG_NAME="${arg#*=}" 0179 fi 0180 0181 if [[ ${arg} = -notarize-ac=* ]]; then 0182 NOTARIZE_ACC="${arg#*=}" 0183 fi 0184 0185 if [[ ${arg} = -notarize-pass=* ]]; then 0186 NOTARIZE_PASS="${arg#*=}" 0187 fi 0188 0189 if [[ ${arg} = -style=* ]]; then 0190 style_filename="${arg#*=}" 0191 if [[ -f "${style_filename}" ]]; then 0192 DMG_STYLE="${style_filename}" 0193 fi 0194 fi 0195 0196 if [[ ${arg} = -asc-provider=* ]]; then 0197 APPLE_TEAMID="${arg#*=}" 0198 fi 0199 0200 if [[ ${arg} = "-h" || ${arg} = "--help" ]]; then 0201 print_usage 0202 exit 1 0203 fi 0204 done 0205 0206 # -- Checks and messages 0207 0208 ### PYTHONAttempt to find python_version 0209 local_PY_MAYOR_VERSION=$(python -c "import sys; print(sys.version_info[0])") 0210 local_PY_MINOR_VERSION=$(python -c "import sys; print(sys.version_info[1])") 0211 PY_VERSION="${local_PY_MAYOR_VERSION}.${local_PY_MINOR_VERSION}" 0212 0213 print_msg "Detected Python %s" "${PY_VERSION}" 0214 0215 ### Code Signature & NOTARIZATION 0216 NOTARIZE="false" 0217 if [[ -z "${CODE_SIGNATURE}" ]]; then 0218 echo "WARNING: No code signature provided, Code will not be signed" 0219 else 0220 print_msg "Code will be signed with %s" "${CODE_SIGNATURE}" 0221 ### NOTARIZATION 0222 # check if we can perform notarization using notarytool 0223 xcrun notarytool history --keychain-profile KritaNotarizeAccount 1> /dev/null 0224 if [[ ${?} -eq 0 ]]; then 0225 NOTARYTOOL="short" 0226 NOTARIZE="true" 0227 fi 0228 0229 if [[ ${NOTARIZE} = "false" && -n "${NOTARIZE_ACC}" ]]; then 0230 NOTARIZE="true" 0231 ASC_PROVIDER_OP="" 0232 0233 if [[ -z ${APPLE_TEAMID} ]]; then 0234 echo "No team id provided, extracting from signature" 0235 APPLE_TEAMID=${CODE_SIGNATURE[-11,-2]} 0236 fi 0237 0238 if [[ -n "${APPLE_TEAMID}" ]]; then 0239 ASC_PROVIDER_OP="--asc-provider ${APPLE_TEAMID}" 0240 fi 0241 0242 if [[ -z "${NOTARIZE_PASS}" ]]; then 0243 NOTARIZE_PASS="@keychain:AC_PASSWORD" 0244 KEYCHAIN_PASS="true" 0245 fi 0246 0247 # check if we can perform notarization 0248 0249 xcrun notarytool history --apple-id "${NOTARIZE_ACC}" --password "${NOTARIZE_PASS}" --team-id "${APPLE_TEAMID}" 1> /dev/null 0250 if [[ ${?} -ne 0 ]]; then 0251 echo "Unable to use notarytool: not setup/missing password, trying altool" 0252 ALTOOL="true" 0253 xcrun altool --notarization-history 0 --username "${NOTARIZE_ACC}" --password "${NOTARIZE_PASS}" ${ASC_PROVIDER_OP} 1> /dev/null 0254 0255 if [[ ${?} -ne 0 ]]; then 0256 NOTARIZE="false" 0257 echo "No password given for notarization or AC_PASSWORD missing in keychain" 0258 fi 0259 else 0260 NOTARYTOOL="long" 0261 fi 0262 fi 0263 fi 0264 0265 if [[ ${NOTARIZE} = "true" ]]; then 0266 print_msg "Notarization checks complete, This build will be notarized" 0267 else 0268 echo "WARNING: Account information missing, Notarization will not be performed" 0269 fi 0270 0271 0272 ### STYLE for DMG 0273 if [[ ! ${DMG_STYLE} ]]; then 0274 DMG_STYLE="${SCRIPT_SOURCE_DIR}/default.style" 0275 fi 0276 0277 print_msg "Using style from: %s" "${DMG_STYLE}" 0278 0279 ### Background for DMG 0280 if [[ ${DMG_validBG} -eq 0 ]]; then 0281 echo "No jpg or png valid file detected!!" 0282 echo "Using default style" 0283 DMG_background="${SCRIPT_SOURCE_DIR}/krita_dmgBG.jpg" 0284 fi 0285 0286 0287 0288 # Helper functions 0289 countArgs () { 0290 echo "${#}" 0291 } 0292 0293 stringContains () { 0294 echo "$(grep "${2}" <<< "${1}")" 0295 } 0296 0297 waiting_fixed() { 0298 local message="${1}" 0299 local waitTime=${2} 0300 0301 for i in $(seq ${waitTime}); do 0302 sleep 1 0303 printf -v dots '%*s' ${i} 0304 printf -v spaces '%*s' $((${waitTime} - $i)) 0305 printf "\r%s [%s%s]" "${message}" "${dots// /.}" "${spaces}" 0306 done 0307 printf "\n" 0308 } 0309 0310 add_lib_to_list() { 0311 local llist=${2} 0312 if [[ -z "$(grep ${1##*/} <<< ${llist})" ]]; then 0313 local llist="${llist} ${1##*/} " 0314 fi 0315 echo "${llist}" 0316 } 0317 0318 # Find all @rpath and Absolute to buildroot path libs 0319 # Add to libs_used 0320 # converts absolute buildroot path to @rpath 0321 find_needed_libs () { 0322 # echo "Analyzing libraries with oTool..." >&2 0323 local libs_used="" # input lib_lists founded 0324 0325 for libFile in ${@}; do 0326 if [[ -z "$(file ${libFile} | grep 'Mach-O')" ]]; then 0327 # echo "skipping ${libFile}" >&2 0328 continue 0329 fi 0330 0331 resultArray=($(otool -L ${libFile} | awk '{print $1","substr($2,2)}')) 0332 0333 printf "Fixing %s\n" "${libFile#${KRITA_DMG}/}" >&2 0334 for entry in ${resultArray[@]:1}; do 0335 # skip fat-bin file markers 0336 if [[ "${entry##*,}" = "architecture" ]]; then 0337 continue 0338 fi 0339 0340 lib="${entry%%,*}" 0341 0342 if [[ "${lib:0:1}" = "@" ]]; then 0343 local libs_used=$(add_lib_to_list "${lib}" "${libs_used}") 0344 fi 0345 0346 if [[ "${lib:0:${#BUILDROOT}}" = "${BUILDROOT}" ]]; then 0347 printf "\t%s\n" "${lib}" >&2 0348 if [[ "${lib##*/}" = "${libFile##*/}" ]]; then 0349 install_name_tool -id ${lib##*/} "${libFile}" 0350 else 0351 install_name_tool -change ${lib} "@rpath/${lib##*/i/lib/}" "${libFile}" 0352 local libs_used=$(add_lib_to_list "${lib}" "${libs_used}") 0353 fi 0354 fi 0355 done 0356 done 0357 echo "${libs_used}" # return updated list 0358 } 0359 0360 find_missing_libs (){ 0361 # echo "Searching for missing libs on deployment folders…" >&2 0362 local libs_missing="" 0363 for lib in ${@}; do 0364 if [[ -z "$(find ${KRITA_DMG}/krita.app/Contents/ -name ${lib})" ]]; then 0365 # echo "Adding ${lib} to missing libraries." >&2 0366 libs_missing="${libs_missing} ${lib}" 0367 fi 0368 done 0369 echo "${libs_missing}" 0370 } 0371 0372 copy_missing_libs () { 0373 for lib in ${@}; do 0374 result=$(find -L "${BUILDROOT}/i" -name "${lib}") 0375 0376 if [[ $(countArgs ${result}) -eq 1 ]]; then 0377 if [ "$(stringContains "${result}" "plugin")" ]; then 0378 cp -pv ${result} ${KRITA_DMG}/krita.app/Contents/PlugIns/ 0379 krita_findmissinglibs "${KRITA_DMG}/krita.app/Contents/PlugIns/${result##*/}" 0380 else 0381 cp -pv ${result} ${KRITA_DMG}/krita.app/Contents/Frameworks/ 0382 krita_findmissinglibs "${KRITA_DMG}/krita.app/Contents/Frameworks/${result##*/}" 0383 fi 0384 else 0385 echo "${lib} might be a missing framework" 0386 if [ "$(stringContains "${result}" "framework")" ]; then 0387 echo "copying framework ${BUILDROOT}/i/lib/${lib}.framework to dmg" 0388 # rsync only included ${lib} Resources Versions 0389 rsync -priul ${BUILDROOT}/i/lib/${lib}.framework/${lib} ${KRITA_DMG}/krita.app/Contents/Frameworks/${lib}.framework/ 0390 rsync -priul ${BUILDROOT}/i/lib/${lib}.framework/Resources ${KRITA_DMG}/krita.app/Contents/Frameworks/${lib}.framework/ 0391 rsync -priul ${BUILDROOT}/i/lib/${lib}.framework/Versions ${KRITA_DMG}/krita.app/Contents/Frameworks/${lib}.framework/ 0392 krita_findmissinglibs "$(find "${KRITA_DMG}/krita.app/Contents/Frameworks/${lib}.framework/" -type f -perm 755)" 0393 fi 0394 fi 0395 done 0396 } 0397 0398 krita_findmissinglibs() { 0399 neededLibs=$(find_needed_libs "${@}") 0400 missingLibs=$(find_missing_libs ${neededLibs}) 0401 0402 if [[ $(countArgs ${missingLibs}) -gt 0 ]]; then 0403 printf "Found missing libs: %s\n" "${missingLibs}" 0404 copy_missing_libs ${missingLibs} 0405 fi 0406 } 0407 0408 strip_python_dmginstall() { 0409 # reduce size of framework python 0410 # Removes tests, installers, pyenv, distutils 0411 echo "Removing unnecessary files from Python.Framework to be packaged..." 0412 PythonFrameworkBase="${KRITA_DMG}/krita.app/Contents/Frameworks/Python.framework" 0413 0414 cd "${PythonFrameworkBase}" 0415 find . -name "test*" -type d | xargs rm -rf 0416 find "${PythonFrameworkBase}/Versions/${PY_VERSION}/bin" -not -name "python*" \( -type f -or -type l \) | xargs rm -f 0417 cd "${PythonFrameworkBase}/Versions/${PY_VERSION}/lib/python${PY_VERSION}" 0418 rm -rf distutils tkinter ensurepip venv lib2to3 idlelib turtledemo 0419 # remove tkinter module 0420 rm "./lib-dynload/_tkinter.cpython-${local_PY_MAYOR_VERSION}${local_PY_MINOR_VERSION}-darwin.so" 0421 0422 cd "${PythonFrameworkBase}/Versions/${PY_VERSION}/lib/python${PY_VERSION}/site-packages" 0423 rm -rf pip* PyQt_builder* setuptools* sip* easy-install.pth 0424 0425 cd "${PythonFrameworkBase}/Versions/${PY_VERSION}/Resources" 0426 rm -rf Python.app 0427 } 0428 0429 # Remove any missing rpath pointing to BUILDROOT 0430 libs_clean_rpath () { 0431 for libFile in ${@}; do 0432 rpath=($(otool -l "${libFile}" | grep "path ${BUILDROOT}" | awk '{$1=$1;print $2}')) 0433 for lpath in "${rpath[@]}"; do 0434 echo "removed rpath _${lpath}_ from ${libFile}" 0435 install_name_tool -delete_rpath "${lpath}" "${libFile}" 2> /dev/null 0436 done 0437 done 0438 } 0439 0440 # Multithreaded version 0441 # of libs_clean_rpath, but makes assumptions 0442 delete_install_rpath() { 0443 xargs -P4 -I FILE install_name_tool -delete_rpath "${BUILDROOT}/i/lib" FILE 2> "${BUILDROOT}/deploy_error.log" 0444 } 0445 0446 fix_python_framework() { 0447 # Fix python.framework rpath and slims down installation 0448 PythonFrameworkBase="${KRITA_DMG}/krita.app/Contents/Frameworks/Python.framework" 0449 0450 # Fix permissions 0451 find "${PythonFrameworkBase}" -name "*.so" | xargs -P4 -I FILE chmod a+x FILE 2> "${BUILDROOT}/deploy_error.log" 0452 cd "${PythonFrameworkBase}/Versions/${PY_VERSION}/lib/python${PY_VERSION}" 0453 chmod a+x pydoc.py 0454 0455 # Fix main library 0456 pythonLib="${PythonFrameworkBase}/Python" 0457 install_name_tool -id "${pythonLib##*/}" "${pythonLib}" 0458 install_name_tool -add_rpath @loader_path/../../../ "${pythonLib}" 2> /dev/null 0459 install_name_tool -change @loader_path/../../../../libintl.9.dylib @loader_path/../../../libintl.9.dylib "${pythonLib}" 0460 0461 # Fix all executables 0462 install_name_tool -add_rpath @executable_path/../../../../../../../ "${PythonFrameworkBase}/Versions/Current/Resources/Python.app/Contents/MacOS/Python" 0463 install_name_tool -change "${KIS_INSTALL_DIR}/lib/Python.framework/Versions/${PY_VERSION}/Python" @executable_path/../../../../../../Python "${PythonFrameworkBase}/Versions/Current/Resources/Python.app/Contents/MacOS/Python" 0464 install_name_tool -add_rpath @executable_path/../../../../ "${PythonFrameworkBase}/Versions/Current/bin/python${PY_VERSION}" 0465 install_name_tool -add_rpath @executable_path/../../../../ "${PythonFrameworkBase}/Versions/Current/bin/python${PY_VERSION}m" 0466 0467 # Fix rpaths from Python.Framework 0468 find "${PythonFrameworkBase}" -type f -perm 755 | delete_install_rpath 0469 find "${PythonFrameworkBase}/Versions/Current/lib/python${PY_VERSION}/site-packages/PyQt5" -type f -name "*.so" | delete_install_rpath 0470 } 0471 0472 # Checks for macdeployqt 0473 # If not present attempts to install 0474 # If it fails shows an informative message 0475 # (For now, macdeployqt is fundamental to deploy) 0476 macdeployqt_exists() { 0477 printf "Checking for macdeployqt... " 0478 0479 if [[ ! -e "${KIS_INSTALL_DIR}/bin/macdeployqt" ]]; then 0480 printf "Not Found!\n" 0481 printf "Attempting to install macdeployqt\n" 0482 0483 cd "${BUILDROOT}/depbuild/ext_qt/ext_qt-prefix/src/ext_qt/qttools/src" 0484 make sub-macdeployqt-all 0485 make sub-macdeployqt-install_subtargets 0486 make install 0487 0488 if [[ ! -e "${KIS_INSTALL_DIR}/bin/macdeployqt" ]]; then 0489 printf " 0490 ERROR: Failed to install macdeployqt! 0491 0492 Compile and install from qt source directory 0493 Source code to build could be located in qttools/src in qt source dir: 0494 0495 ${BUILDROOT}/depbuild/ext_qt/ext_qt-prefix/src/ext_qt/qttools/src 0496 0497 From the source dir, build and install: 0498 0499 make sub-macdeployqt-all 0500 make sub-macdeployqt-install_subtargets 0501 make install 0502 " 0503 printf "\nexiting...\n" 0504 exit 1 0505 else 0506 echo "Done!" 0507 fi 0508 else 0509 echo "Found!" 0510 fi 0511 } 0512 0513 krita_deploy () { 0514 # check for macdeployqt 0515 macdeployqt_exists 0516 0517 cd ${BUILDROOT} 0518 # Update files in krita.app 0519 echo "Deleting previous kritadmg run..." 0520 rm -rf ./krita.dmg ${KRITA_DMG} 0521 # Copy new builtFiles 0522 echo "Preparing ${KRITA_DMG} for deployment..." 0523 0524 echo "Copying krita.app..." 0525 mkdir "${KRITA_DMG}" 0526 0527 rsync -prul ${KIS_INSTALL_DIR}/bin/krita.app ${KRITA_DMG} 0528 cp ${KIS_INSTALL_DIR}/bin/kritarunner ${KRITA_DMG}/krita.app/Contents/MacOS 0529 cp ${KIS_INSTALL_DIR}/bin/krita_version ${KRITA_DMG}/krita.app/Contents/MacOS 0530 0531 mkdir -p ${KRITA_DMG}/krita.app/Contents/PlugIns 0532 mkdir -p ${KRITA_DMG}/krita.app/Contents/Frameworks 0533 0534 echo "Copying share..." 0535 # Deletes old copies of translation and qml to be recreated 0536 cd ${KIS_INSTALL_DIR}/share/ 0537 rsync -prul --delete ./ \ 0538 --exclude krita_SRCS.icns \ 0539 --exclude aclocal \ 0540 --exclude doc \ 0541 --exclude ECM \ 0542 --exclude eigen3 \ 0543 --exclude emacs \ 0544 --exclude gettext \ 0545 --exclude gettext-0.19.8 \ 0546 --exclude info \ 0547 --exclude kf5 \ 0548 --exclude kservices5 \ 0549 --exclude man \ 0550 --exclude ocio \ 0551 --exclude pkgconfig \ 0552 --exclude mime \ 0553 --exclude translations \ 0554 --exclude qml \ 0555 ${KRITA_DMG}/krita.app/Contents/Resources 0556 0557 0558 # support localized system menu entries from MacOS, bug #432685. 0559 echo "Creating locale lproj directories for localization" 0560 LOCALE_FILES=$(find "${KRITA_DMG}/krita.app/Contents/Resources/locale" -type d -depth 1) 0561 cd "${KRITA_DMG}/krita.app/Contents/Resources/" 0562 for LOCALE in ${LOCALE_FILES} ; do 0563 BASE=$(basename ${LOCALE}) 0564 mkdir "$BASE.lproj" 0565 done 0566 0567 cd ${BUILDROOT} 0568 0569 echo "Copying translations..." 0570 rsync -prul ${KIS_INSTALL_DIR}/translations/ \ 0571 ${KRITA_DMG}/krita.app/Contents/Resources/translations 0572 0573 echo "Copying QuickLook plugin..." 0574 mkdir -p ${KRITA_DMG}/krita.app/Contents/Library/QuickLook 0575 rsync -prul ${KIS_INSTALL_DIR}/plugins/kritaquicklook.qlgenerator ${KRITA_DMG}/krita.app/Contents/Library/QuickLook 0576 echo "Copying Spotlight plugin..." 0577 mkdir -p ${KRITA_DMG}/krita.app/Contents/Library/Spotlight 0578 rsync -prul ${KIS_INSTALL_DIR}/plugins/kritaspotlight.mdimporter ${KRITA_DMG}/krita.app/Contents/Library/Spotlight 0579 # TODO fix and reenable - https://bugs.kde.org/show_bug.cgi?id=430553 0580 # echo "Copying QuickLook Thumbnailing extension..." 0581 # rsync -prul ${KIS_INSTALL_DIR}/plugins/kritaquicklookng.appex ${KRITA_DMG}/krita.app/Contents/PlugIns 0582 0583 cd ${KRITA_DMG}/krita.app/Contents 0584 ln -shF Resources share 0585 0586 echo "Copying qml..." 0587 rsync -prul ${KIS_INSTALL_DIR}/qml Resources/qml 0588 0589 echo "Copying plugins..." 0590 local KRITA_DMG_PLUGIN_DIR="${KRITA_DMG}/krita.app/Contents/PlugIns" 0591 # exclude kritaquicklook.qlgenerator/ 0592 cd ${KIS_INSTALL_DIR}/plugins/ 0593 rsync -prul --delete --delete-excluded ./ \ 0594 --exclude kritaquicklook.qlgenerator \ 0595 --exclude kritaspotlight.mdimporter \ 0596 ${KRITA_DMG_PLUGIN_DIR} 0597 0598 cd ${BUILDROOT} 0599 rsync -prul ${KIS_INSTALL_DIR}/lib/kritaplugins/* ${KRITA_DMG_PLUGIN_DIR} 0600 0601 rsync -prul ${KIS_INSTALL_DIR}/lib/mlt ${KRITA_DMG_PLUGIN_DIR} 0602 0603 echo "Adding ffmpeg to bundle" 0604 cd ${KRITA_DMG}/krita.app/Contents/MacOS 0605 cp ${KIS_INSTALL_DIR}/bin/ffmpeg . 0606 cp ${KIS_INSTALL_DIR}/bin/ffprobe . 0607 for bin in ffmpeg ffprobe; do 0608 cp ${KIS_INSTALL_DIR}/bin/${bin} 0609 install_name_tool -add_rpath @executable_path/../Frameworks/ ${bin} 0610 done 0611 0612 # rsync -prul {KIS_INSTALL_DIR}/lib/libkrita* Frameworks/ 0613 0614 # To avoid errors macdeployqt must be run from bin location 0615 # ext_qt will not build macdeployqt by default so it must be build manually 0616 # cd ${BUILDROOT}/depbuild/ext_qt/ext_qt-prefix/src/ext_qt/qttools/src 0617 # make sub-macdeployqt-all 0618 # make sub-macdeployqt-install_subtargets 0619 # make install 0620 echo "Running macdeployqt..." 0621 cd ${KIS_INSTALL_DIR}/bin 0622 ./macdeployqt ${KRITA_DMG}/krita.app \ 0623 -verbose=0 \ 0624 -executable=${KRITA_DMG}/krita.app/Contents/MacOS/krita \ 0625 -libpath=${KIS_INSTALL_DIR}/lib \ 0626 -qmldir=${KIS_INSTALL_DIR}/qml \ 0627 -appstore-compliant 0628 # -extra-plugins=${KIS_INSTALL_DIR}/lib/kritaplugins \ 0629 # -extra-plugins=${KIS_INSTALL_DIR}/lib/plugins \ 0630 # -extra-plugins=${KIS_INSTALL_DIR}/plugins 0631 0632 cd ${BUILDROOT} 0633 echo "macdeployqt done!" 0634 0635 echo "Copying python..." 0636 # Copy this framework last! 0637 # It is best that macdeployqt does not modify Python.framework 0638 # folders with period in name are treated as Frameworks for codesign 0639 rsync -prul ${KIS_INSTALL_DIR}/lib/Python.framework ${KRITA_DMG}/krita.app/Contents/Frameworks/ 0640 rsync -prul ${KIS_INSTALL_DIR}/lib/krita-python-libs ${KRITA_DMG}/krita.app/Contents/Frameworks/ 0641 # change perms on Python to allow header change 0642 chmod +w ${KRITA_DMG}/krita.app/Contents/Frameworks/Python.framework/Python 0643 0644 fix_python_framework 0645 strip_python_dmginstall 0646 0647 # fix python pyc 0648 # precompile all pyc so the dont alter signature 0649 echo "Precompiling all python files..." 0650 cd ${KRITA_DMG}/krita.app 0651 ${KIS_INSTALL_DIR}/bin/python -m compileall . &> /dev/null 0652 0653 # remove unnecessary rpaths 0654 install_name_tool -delete_rpath @executable_path/../lib ${KRITA_DMG}/krita.app/Contents/MacOS/krita_version 0655 install_name_tool -delete_rpath @executable_path/../lib ${KRITA_DMG}/krita.app/Contents/MacOS/kritarunner 0656 install_name_tool -delete_rpath @loader_path/../../../../lib ${KRITA_DMG}/krita.app/Contents/MacOS/krita 0657 rm -rf ${KRITA_DMG}/krita.app/Contents/PlugIns/kf5/org.kde.kwindowsystem.platforms 0658 0659 # Fix permissions 0660 find "${KRITA_DMG}/krita.app/Contents" -type f -name "*.dylib" -or -name "*.so" -or -path "*/Contents/MacOS/*" | xargs -P4 -I FILE chmod a+x FILE 0661 find "${KRITA_DMG}/krita.app/Contents/Resources/applications" -name "*.desktop" | xargs -P4 -I FILE chmod a-x FILE 0662 0663 # repair krita for plugins 0664 printf "Searching for missing libraries\n" 0665 krita_findmissinglibs $(find ${KRITA_DMG}/krita.app/Contents -type f -perm 755 -or -name "*.dylib" -or -name "*.so") 0666 0667 # Fix rpath for plugins 0668 # Uncomment if the Finder plugins (kritaquicklook, kritaspotlight) lack the rpath below 0669 # printf "Repairing rpath for Finder plugins\n" 0670 # find "${KRITA_DMG}/krita.app/Contents/Library" -type f -path "*/Contents/MacOS/*" -perm 755 | xargs -I FILE install_name_tool -add_rpath @loader_path/../../../../../Frameworks FILE 0671 0672 printf "removing absolute or broken linksys, if any\n" 0673 find "${KRITA_DMG}/krita.app/Contents" -type l \( -lname "/*" -or -not -exec test -e {} \; \) -print | xargs rm 0674 0675 printf "clean any left over rpath\n" 0676 libs_clean_rpath $(find "${KRITA_DMG}/krita.app/Contents" -type f -perm 755 -or -name "*.dylib" -or -name "*.so") 0677 # libs_clean_rpath $(find "${KRITA_DMG}/krita.app/Contents/" -type f -name "lib*") 0678 0679 echo "Done!" 0680 } 0681 0682 0683 # helper to define function only once 0684 batch_codesign() { 0685 local entitlements="${1}" 0686 if [[ -z "${1}" ]]; then 0687 entitlements="${KIS_SRC_DIR}/packaging/macos/entitlements.plist" 0688 fi 0689 xargs -P4 -I FILE codesign --options runtime --timestamp -f -s "${CODE_SIGNATURE}" --entitlements "${entitlements}" FILE 0690 } 0691 # Code sign must be done as recommended by apple "sign code inside out in individual stages" 0692 signBundle() { 0693 cd ${KRITA_DMG} 0694 0695 # sign Frameworks and libs 0696 cd ${KRITA_DMG}/krita.app/Contents/Frameworks 0697 # remove debug version as both versions can't be signed. 0698 rm ${KRITA_DMG}/krita.app/Contents/Frameworks/QtScript.framework/Versions/Current/QtScript_debug 0699 # Do not sign binaries inside frameworks except for Python's 0700 find . -type d -path "*.framework" -prune -false -o -perm +111 -not -type d | batch_codesign 0701 find Python.framework -type f -name "*.o" -or -name "*.so" -or -perm +111 -not -type d -not -type l | batch_codesign 0702 find . -type d -name "*.framework" | xargs printf "%s/Versions/Current\n" | batch_codesign 0703 0704 # Sign all other files in Framework (needed) 0705 # there are many files in python do we need to sign them all? 0706 find krita-python-libs -type f | batch_codesign 0707 # find python -type f | batch_codesign 0708 0709 # Sign only libraries and plugins 0710 cd ${KRITA_DMG}/krita.app/Contents/PlugIns 0711 find . -type f | batch_codesign 0712 0713 cd ${KRITA_DMG}/krita.app/Contents/Library/QuickLook 0714 printf "kritaquicklook.qlgenerator" | batch_codesign 0715 0716 cd ${KRITA_DMG}/krita.app/Contents/Library/Spotlight 0717 printf "kritaspotlight.mdimporter" | batch_codesign 0718 0719 # It is necessary to sign every binary Resource file 0720 cd ${KRITA_DMG}/krita.app/Contents/Resources 0721 find . -perm +111 -type f | batch_codesign 0722 0723 printf "${KRITA_DMG}/krita.app/Contents/MacOS/ffmpeg" | batch_codesign 0724 printf "${KRITA_DMG}/krita.app/Contents/MacOS/ffprobe" | batch_codesign 0725 0726 printf "${KRITA_DMG}/krita.app/Contents/MacOS/kritarunner" | batch_codesign 0727 printf "${KRITA_DMG}/krita.app/Contents/MacOS/krita_version" | batch_codesign 0728 0729 #Finally sign krita and krita.app 0730 printf "${KRITA_DMG}/krita.app/Contents/MacOS/krita" | batch_codesign 0731 printf "${KRITA_DMG}/krita.app" | batch_codesign 0732 } 0733 0734 sign_hasError() { 0735 local CODESIGN_STATUS=0 0736 for f in $(find "${KRITA_DMG}" -type f); do 0737 if [[ -z $(file ${f} | grep "Mach-O") ]]; then 0738 continue 0739 fi 0740 0741 CODESIGN_RESULT=$(codesign -vvv --strict ${f} 2>&1 | grep "not signed") 0742 0743 if [[ -n "${CODESIGN_RESULT}" ]]; then 0744 CODESIGN_STATUS=1 0745 printf "${f} not signed\n" >&2 0746 fi 0747 done 0748 echo ${CODESIGN_STATUS} 0749 } 0750 0751 # Notarize build on macOS servers 0752 # based on https://github.com/Beep6581/RawTherapee/blob/6fa533c40b34dec527f1176d47cc6c683422a73f/tools/osx/macosx_bundle.sh#L225-L250 0753 notarize_build() { 0754 local NOT_SRC_DIR=${1} 0755 local NOT_SRC_FILE=${2} 0756 0757 local notarization_complete="true" 0758 0759 if [[ ${NOTARIZE} = "true" ]]; then 0760 printf "performing notarization of %s\n" "${2}" 0761 cd "${NOT_SRC_DIR}" 0762 0763 ditto -c -k --sequesterRsrc --keepParent "${NOT_SRC_FILE}" "${BUILDROOT}/tmp_notarize/${NOT_SRC_FILE}.zip" 0764 0765 if [[ ${NOTARYTOOL} = "short" ]]; then 0766 xcrun notarytool submit "${BUILDROOT}/tmp_notarize/${NOT_SRC_FILE}.zip" --wait --keychain-profile KritaNotarizeAccount 0767 0768 elif [[ ${NOTARYTOOL} = "long" ]]; then 0769 xcrun notarytool submit "${BUILDROOT}/tmp_notarize/${NOT_SRC_FILE}.zip" --wait --apple-id "${NOTARIZE_ACC}" --password "${NOTARIZE_PASS}" --team-id "${APPLE_TEAMID}" 0770 0771 else 0772 # echo "xcrun altool --notarize-app --primary-bundle-id \"org.krita\" --username \"${NOTARIZE_ACC}\" --password \"${NOTARIZE_PASS}\" --file \"${BUILDROOT}/tmp_notarize/${NOT_SRC_FILE}.zip\"" 0773 local altoolResponse="$(xcrun altool --notarize-app --primary-bundle-id "org.krita" --username "${NOTARIZE_ACC}" --password "${NOTARIZE_PASS}" ${ASC_PROVIDER_OP} --file "${BUILDROOT}/tmp_notarize/${NOT_SRC_FILE}.zip" 2>&1)" 0774 0775 if [[ -n "$(grep 'Error' <<< ${altoolResponse})" ]]; then 0776 printf "ERROR: xcrun altool exited with the following error! \n\n%s\n\n" "${altoolResponse}" 0777 printf "This could mean there is an error in AppleID authentication!\n" 0778 printf "aborting notarization\n" 0779 NOTARIZE="false" 0780 return 0781 else 0782 printf "Response:\n\n%s\n\n" "${altoolResponse}" 0783 fi 0784 0785 local uuid="$(grep 'RequestUUID' <<< ${altoolResponse} | awk '{ print $NF }')" 0786 echo "RequestUUID = ${uuid}" # Display identifier string 0787 0788 waiting_fixed "Waiting to retrieve notarize status" 120 0789 0790 while true ; do 0791 fullstatus=$(xcrun altool --notarization-info "${uuid}" --username "${NOTARIZE_ACC}" --password "${NOTARIZE_PASS}" ${ASC_PROVIDER_OP} 2>&1) # get the status 0792 notarize_status=`echo "${fullstatus}" | grep 'Status\:' | awk '{ print $2 }'` 0793 echo "${fullstatus}" 0794 if [[ "${notarize_status}" = "success" ]]; then 0795 print_msg "Notarization success!" 0796 break 0797 elif [[ "${notarize_status}" = "in" ]]; then 0798 waiting_fixed "Notarization still in progress, wait before checking again" 60 0799 else 0800 notarization_complete="false" 0801 echo "Notarization failed! full status below" 0802 echo "${fullstatus}" 0803 exit 1 0804 fi 0805 done 0806 fi 0807 0808 if [[ "${notarization_complete}" = "true" ]]; then 0809 xcrun stapler staple "${NOT_SRC_FILE}" #staple the ticket 0810 xcrun stapler validate -v "${NOT_SRC_FILE}" 0811 fi 0812 fi 0813 } 0814 0815 createDMG () { 0816 printf "Creating of dmg with contents of %s...\n" "${KRITA_DMG}" 0817 cd ${BUILDROOT} 0818 DMG_size=1500 0819 0820 if [[ -z "${DMG_NAME}" ]]; then 0821 # Add git version number 0822 DMG_NAME="krita-${KRITA_VERSION// /_}.dmg" 0823 else 0824 DMG_NAME="${DMG_NAME}.dmg" 0825 fi 0826 0827 ## Build dmg from folder 0828 0829 # create dmg on local system 0830 # usage of -fsargs minimize gaps at front of filesystem (reduce size) 0831 hdiutil create -srcfolder "${KRITA_DMG}" -volname "${DMG_title}" -fs APFS \ 0832 -format UDIF -verbose -size ${DMG_size}m krita.temp.dmg 0833 0834 # Next line is only useful if we have a dmg as a template! 0835 # previous hdiutil must be uncommented 0836 # cp krita-template.dmg krita.dmg 0837 device=$(hdiutil attach -readwrite -noverify -noautoopen "krita.temp.dmg" | egrep '^/dev/' | sed 1q | awk '{print $1}') 0838 0839 # rsync -priul --delete ${KRITA_DMG}/krita.app "/Volumes/${DMG_title}" 0840 0841 # Set style for dmg 0842 if [[ ! -d "/Volumes/${DMG_title}/.background" ]]; then 0843 mkdir "/Volumes/${DMG_title}/.background" 0844 fi 0845 cp -v ${DMG_background} "/Volumes/${DMG_title}/.background/" 0846 0847 mkdir "/Volumes/${DMG_title}/Terms of Use" 0848 cp -v "${KIS_SRC_DIR}/packaging/macos/Terms_of_use.rtf" "/Volumes/${DMG_title}/Terms of Use/" 0849 ln -s "/Applications" "/Volumes/${DMG_title}/Applications" 0850 0851 ## Apple script to set style 0852 style="$(<"${DMG_STYLE}")" 0853 printf "${style}" "${DMG_title}" "${DMG_background##*/}" | osascript 0854 0855 #Set Icon for DMG 0856 cp -v "${SCRIPT_SOURCE_DIR}/KritaIcon.icns" "/Volumes/${DMG_title}/.VolumeIcon.icns" 0857 SetFile -a C "/Volumes/${DMG_title}" 0858 0859 chmod -Rf go-w "/Volumes/${DMG_title}" 0860 0861 # ensure all writing operations to dmg are over 0862 sync 0863 0864 hdiutil detach $device 0865 hdiutil convert "krita.temp.dmg" -format UDZO -imagekey -zlib-level=9 -o krita-out.dmg 0866 0867 0868 mv krita-out.dmg ${DMG_NAME} 0869 echo "moved krita-out.dmg to ${DMG_NAME}" 0870 rm krita.temp.dmg 0871 0872 if [[ -n "${CODE_SIGNATURE}" ]]; then 0873 printf "${DMG_NAME}" | batch_codesign 0874 fi 0875 0876 notarize_build "${BUILDROOT}" "${DMG_NAME}" 0877 0878 echo "dmg done!" 0879 } 0880 0881 ####################### 0882 # Program starts!! 0883 ######################## 0884 # Run deploy command, installation is assumed to exist in BUILDROOT/i 0885 krita_deploy 0886 0887 # Code sign krita.app if signature given 0888 if [[ -n "${CODE_SIGNATURE}" ]]; then 0889 signBundle 0890 fi 0891 0892 # Manually check every single Mach-O file for signature status 0893 if [[ "${NOTARIZE}" = "true" ]]; then 0894 print_msg "Checking if all files are signed before sending for notarization..." 0895 if [[ $(sign_hasError) -eq 1 ]]; then 0896 print_error "CodeSign errors cannot send to notarize!" 0897 echo "krita.app not sent to notarization, stopping...." 0898 exit 1 0899 fi 0900 print_msg "Done! all files appear to be correct." 0901 0902 # notarize apple 0903 notarize_build "${KRITA_DMG}" krita.app 0904 fi 0905 0906 # Create DMG from files inside ${KRITA_DMG} folder 0907 createDMG 0908 0909 if [[ "${NOTARIZE}" = "false" ]]; then 0910 macosVersion="$(sw_vers | grep ProductVersion | awk ' 0911 BEGIN { FS = "[ .\t]" } 0912 { print $3} 0913 ')" 0914 if (( ${macosVersion} == 15 )); then 0915 print_error "Build not notarized! Needed for macOS versions above 10.14" 0916 fi 0917 fi