File indexing completed on 2024-05-12 16:02:32

0001 #!/usr/bin/env bash
0002 #
0003 #  SPDX-License-Identifier: GPL-3.0-or-later
0004 #
0005 
0006 # osxbuild.sh automates building and installing of krita and krita dependencies
0007 # for OSX, the script only needs you to set BUILDROOT environment to work
0008 # properly.
0009 #
0010 
0011 # Run with no args for a short help about each command.
0012 
0013 # builddeps: Attempts to build krita dependencies in the necessary order,
0014 #     intermediate steps for creating symlinks and fixing rpath of some
0015 #     packages midway is also managed. Order goes from top to bottom, to add
0016 #     new steps just place them in the proper place.
0017 
0018 # build: Runs cmake build and make step for krita sources. It always run cmake step, so
0019 #     it might take a bit longer than a pure <make> on the source tree. The script tries
0020 #     to set the make flag -jN to a proper N.
0021 
0022 # install: Runs install step for krita sources.
0023 
0024 # fixboost: Search for all libraries using boost and sets a proper @rpath for boost as by
0025 #     default it fails to set a proper @rpath
0026 
0027 # buildinstall: Runs build, install and fixboost steps.#
0028 
0029 if test -z $BUILDROOT; then
0030     echo "ERROR: BUILDROOT env not set, exiting!"
0031     echo "\t Must point to the root of the buildfiles as stated in 3rdparty Readme"
0032     exit 1
0033 fi
0034 
0035 BUILDROOT="${BUILDROOT%/}"
0036 echo "BUILDROOT set to ${BUILDROOT}"
0037 
0038 # global options
0039 set -o pipefail
0040 
0041 # Check cmake in path.
0042 if test -z $(which cmake); then
0043     echo "WARNING: no cmake in PATH... adding default /Applications location"
0044     export PATH=/Applications/CMake.app/Contents/bin:${PATH}
0045     if test -z $(which cmake); then
0046         echo "ERROR: cmake not found, exiting!"
0047         exit 1
0048     fi
0049 fi
0050 echo "$(cmake --version | head -n 1)"
0051 
0052 # Set some global variables.
0053 OSXBUILD_TYPE="RelWithDebInfo"
0054 OSXBUILD_TESTING="OFF"
0055 OSXBUILD_HIDE_SAFEASSERTS="ON"
0056 
0057 # -- Parse input args
0058 for arg in "${@}"; do
0059     if [[ "${arg}" = --dirty ]]; then
0060         OSXBUILD_CLEAN="keep dirty"
0061     elif [[ "${arg}" = --debug ]]; then
0062         OSXBUILD_TYPE="Debug"
0063     elif [[ "${arg}" = --tests ]]; then
0064         OSXBUILD_TESTING="ON"
0065     elif [[ "${arg}" = --install_tarball ]]; then
0066         OSXBUILD_TARBALLINSTALL="TRUE"
0067     elif [[ "${arg}" = --universal ]]; then
0068         OSXBUILD_UNIVERSAL="TRUE"
0069     elif [[ "${arg}" = --showasserts ]]; then
0070         OSXBUILD_HIDE_SAFEASSERTS="OFF"
0071     else
0072         parsed_args="${parsed_args} ${arg}"
0073     fi
0074 done
0075 
0076 export KIS_SRC_DIR=${BUILDROOT}/krita
0077 export KIS_TBUILD_DIR=${BUILDROOT}/depbuild
0078 export KIS_TDEPINSTALL_DIR=${BUILDROOT}/depinstall
0079 export KIS_DOWN_DIR=${BUILDROOT}/down
0080 export KIS_BUILD_DIR=${BUILDROOT}/kisbuild
0081 export KIS_PLUGIN_BUILD_DIR=${BUILDROOT}/plugins_build
0082 export KIS_INSTALL_DIR=${BUILDROOT}/i
0083 
0084 # flags for OSX environment
0085 # Qt only supports from 10.12 up, and https://doc.qt.io/qt-5/macos.html#target-platforms warns against setting it lower
0086 export MACOSX_DEPLOYMENT_TARGET=10.13
0087 export QMAKE_MACOSX_DEPLOYMENT_TARGET=10.13
0088 
0089 
0090 export PATH=${KIS_INSTALL_DIR}/bin:$PATH
0091 export PKG_CONFIG_PATH=${KIS_INSTALL_DIR}/share/pkgconfig:${KIS_INSTALL_DIR}/lib/pkgconfig
0092 export CMAKE_PREFIX_PATH=${KIS_INSTALL_DIR}
0093 export C_INCLUDE_PATH=${KIS_INSTALL_DIR}/include:/usr/include:${C_INCLUDE_PATH}
0094 export CPLUS_INCLUDE_PATH=${KIS_INSTALL_DIR}/include:/usr/include:${CPLUS_INCLUDE_PATH}
0095 export LIBRARY_PATH=${KIS_INSTALL_DIR}/lib:/usr/lib:${LIBRARY_PATH}
0096 # export CPPFLAGS=-I${KIS_INSTALL_DIR}/include
0097 # export LDFLAGS=-L${KIS_INSTALL_DIR}/lib
0098 export FRAMEWORK_PATH=${KIS_INSTALL_DIR}/lib/
0099 
0100 # export PYTHONHOME=${KIS_INSTALL_DIR}
0101 # export PYTHONPATH=${PYTHONPATH}:${KIS_INSTALL_DIR}/lib/Python.framework/Versions/Current/lib/python3.9/site-packages
0102 
0103 # This will make the debug output prettier
0104 export KDE_COLOR_DEBUG=1
0105 export QTEST_COLORED=1
0106 
0107 export OUPUT_LOG="${BUILDROOT}/osxbuild.log"
0108 printf "" > "${OUPUT_LOG}"
0109 
0110 # configure max core for make compile
0111 ((MAKE_THREADS=1))
0112 if [[ "${OSTYPE}" == "darwin"* ]]; then
0113     ((MAKE_THREADS = $(sysctl -n hw.logicalcpu)))
0114 fi
0115 
0116 OSXBUILD_X86_64_BUILD=$(sysctl -n hw.optional.x86_64)
0117 
0118 if [[ $(arch) = "arm64" ]]; then
0119     OSX_ARCHITECTURES="arm64"
0120 else
0121     OSX_ARCHITECTURES="x86_64"
0122 fi
0123 
0124 if [[ ${OSXBUILD_UNIVERSAL} ]]; then
0125     OSX_ARCHITECTURES="x86_64\;arm64"
0126 fi
0127 
0128 OSXBUILD_GENERATOR="Unix Makefiles"
0129 if [[ -e $(which ninja) ]]; then
0130     OSXBUILD_GENERATOR="Ninja"
0131 fi
0132 
0133 # Prints stderr and stdout to log files
0134 # >(tee) works but breaks sigint
0135 log_cmd () {
0136     "$@" 2>&1 | tee -a ${OUPUT_LOG}
0137     osxbuild_error="${?}"
0138 }
0139 
0140 # Log messages to logfile
0141 log () {
0142     printf "%s\n" "${@}"  | tee -a ${OUPUT_LOG}
0143 }
0144 
0145 # if previous command gives error
0146 # print msg
0147 # if a 2nd arg is given it stops execution
0148 print_if_error() {
0149     if [ "${osxbuild_error}" -ne 0 ]; then
0150         printf "\e[31m%s %s\e[0m\n" "Error:" "Printing last lines of log output"
0151         tail ${OUPUT_LOG}
0152         printf "\e[31m%s %s\e[0m\n" "Error:" "${1}"
0153         if [ -n "${2}" ]; then
0154             exit 1
0155         fi
0156     fi
0157 }
0158 
0159 # print status messages
0160 print_msg() {
0161     printf "\e[32m%s\e[0m\n" "${1}"
0162     printf "%s\n" "${1}" >> ${OUPUT_LOG}
0163 }
0164 
0165 check_dir_path () {
0166     printf "%s" "Checking if ${1} exists and is dir... "
0167     if test -d ${1}; then
0168         echo -e "OK"
0169 
0170     elif test -e ${1}; then
0171         echo -e "\n\tERROR: file ${1} exists but is not a directory!" >&2
0172         return 1
0173     else
0174         echo -e "Creating ${1}"
0175         mkdir ${1}
0176     fi
0177     return 0
0178 }
0179 
0180 waiting_fixed() {
0181     local message="${1}"
0182     local waitTime=${2}
0183 
0184     for i in $(seq ${waitTime}); do
0185         sleep 1
0186         printf -v dots '%*s' ${i}
0187         printf -v spaces '%*s' $((${waitTime} - $i))
0188         printf "\r%s [%s%s]" "${message}" "${dots// /.}" "${spaces}"
0189     done
0190     printf "\n"
0191 }
0192 
0193 dir_clean() {
0194     if [[ -d "${1}" ]]; then
0195         log "Default cleaning build dirs, use --dirty to keep them..."
0196         waiting_fixed "Erase of ${1} in 5 sec" 5
0197         rm -rf "${1}"
0198     fi
0199 }
0200 
0201 # builds dependencies for the first time
0202 cmake_3rdparty () {
0203     cd ${KIS_TBUILD_DIR}
0204 
0205     local build_pkgs=("${@}") # convert to array
0206     local error="false"
0207 
0208     if [[ ${2} = "1" ]]; then
0209         local nofix="true"
0210         local build_pkgs=(${build_pkgs[@]:0:1})
0211     fi
0212 
0213     for package in ${build_pkgs[@]} ; do
0214         if [[ ${package:0:3} != "ext" ]]; then
0215             continue
0216         fi
0217         print_msg "Building ${package}"
0218         log_cmd cmake --build . --config RelWithDebInfo -j${MAKE_THREADS} --target ${package}
0219 
0220         print_if_error "Failed build ${package}"
0221         if [[ ! ${osxbuild_error} -ne 0 ]]; then
0222             print_msg "Build Success! ${package}"
0223         else
0224             log "${pkg} build fail, attempting known fixes..."
0225             error="true"
0226         fi
0227         # fixes does not depend on failure
0228         if [[ ! ${nofix} ]]; then
0229             build_3rdparty_fixes ${package} ${error}
0230         elif [[ "${error}" = "true" ]]; then
0231             log "ERROR: ${pkg} failed a second time, please check pkg logs"
0232             log "stopping..."
0233         fi
0234     done
0235 }
0236 
0237 cmake_3rdparty_plugins () {
0238     cd ${KIS_PLUGIN_BUILD_DIR}
0239 
0240     local build_pkgs=("${@}") # convert to array
0241     local error="false"
0242 
0243     if [[ ${2} = "1" ]]; then
0244         local build_pkgs=(${build_pkgs[@]:0:1})
0245     fi
0246 
0247     for package in ${build_pkgs[@]} ; do
0248         if [[ ${package:0:3} != "ext" ]]; then
0249             continue
0250         fi
0251         print_msg "Building ${package}"
0252         log_cmd cmake --build . --config RelWithDebInfo -j${MAKE_THREADS} --target ${package}
0253 
0254         print_if_error "Failed build ${package}"
0255         if [[ ! ${osxbuild_error} -ne 0 ]]; then
0256             print_msg "Build Success! ${package}"
0257         else
0258             log "${pkg} build fail, stopping..."
0259             exit 1
0260         fi
0261     done
0262 }
0263 
0264 build_3rdparty_fixes(){
0265     local pkg=${1}
0266     local error=${2}
0267 
0268     if [[ "${pkg}" = "ext_qt" && -e "${KIS_INSTALL_DIR}/bin/qmake" ]]; then
0269         ln -sf qmake "${KIS_INSTALL_DIR}/bin/qmake-qt5"
0270         # build macdeployqt
0271         log_cmd cd "${BUILDROOT}/depbuild/ext_qt/ext_qt-prefix/src/ext_qt/qttools/src"
0272         print_if_error "macdeployqt source dir was not found, it will be missing for deployment!"
0273 
0274         if [[ ! ${osxbuild_error} -ne 0 && ! -e "${KIS_INSTALL_DIR}/bin/macdeployqt" ]]; then
0275             make sub-macdeployqt-all
0276             make sub-macdeployqt-install_subtargets
0277             make install
0278         fi
0279         cd "${KIS_TBUILD_DIR}"
0280         error="false"
0281 
0282     elif [[ "${pkg}" = "ext_openexr" ]]; then
0283         # open exr will fail the first time is called
0284         # rpath needs to be fixed an build rerun
0285         log "Fixing rpath on openexr file: b44ExpLogTable"
0286         log "Fixing rpath on openexr file: dwaLookups"
0287         log_cmd install_name_tool -add_rpath ${KIS_INSTALL_DIR}/lib $(find ${KIS_TBUILD_DIR}/ext_openexr/ext_openexr-prefix/src/ext_openexr-build -name b44ExpLogTable)
0288         log_cmd install_name_tool -add_rpath ${KIS_INSTALL_DIR}/lib $(find ${KIS_TBUILD_DIR}/ext_openexr/ext_openexr-prefix/src/ext_openexr-build -name dwaLookups)
0289         # we must rerun build!
0290         cmake_3rdparty ext_openexr "1"
0291         error="false"
0292 
0293     elif [[ "${pkg}" = "ext_fontconfig" ]]; then
0294         log "fixing rpath on fc-cache"
0295         log_cmd install_name_tool -add_rpath ${KIS_INSTALL_DIR}/lib ${KIS_TBUILD_DIR}/ext_fontconfig/ext_fontconfig-prefix/src/ext_fontconfig-build/fc-cache/.libs/fc-cache
0296         # rerun rebuild
0297         if [[ ${OSXBUILD_X86_64_BUILD} -ne 1 && ${osxbuild_error} -ne 0 ]]; then
0298             print_msg "Build Success! ${pkg}"
0299         else
0300             cmake_3rdparty ext_fontconfig "1"
0301         fi
0302         error="false"
0303 
0304     elif [[ "${pkg}" = "ext_poppler" && "${error}" = "true" ]]; then
0305         log "re-running poppler to avoid possible glitch"
0306         cmake_3rdparty ext_poppler "1"
0307         error="false"
0308     fi
0309 
0310     if [[ "${error}" = "true" ]]; then
0311         log "Error building package ${pkg}, stopping..."
0312         exit 1
0313     fi
0314 }
0315 
0316 build_3rdparty () {
0317     print_msg "building in ${KIS_TBUILD_DIR}"
0318 
0319     log "$(check_dir_path ${KIS_TBUILD_DIR})"
0320     log "$(check_dir_path ${KIS_DOWN_DIR})"
0321     log "$(check_dir_path ${KIS_INSTALL_DIR})"
0322 
0323     cd ${KIS_TBUILD_DIR}
0324 
0325     log_cmd cmake ${KIS_SRC_DIR}/3rdparty/ \
0326         -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13 \
0327         -DCMAKE_INSTALL_PREFIX=${KIS_INSTALL_DIR} \
0328         -DCMAKE_PREFIX_PATH:PATH=${KIS_INSTALL_DIR} \
0329         -DEXTERNALS_DOWNLOAD_DIR=${KIS_DOWN_DIR} \
0330         -DINSTALL_ROOT=${KIS_INSTALL_DIR} \
0331         -DCMAKE_OSX_ARCHITECTURES=${OSX_ARCHITECTURES} \
0332         -DMACOS_UNIVERSAL=${OSXBUILD_UNIVERSAL}
0333 
0334         # -DCPPFLAGS=-I${KIS_INSTALL_DIR}/include \
0335         # -DLDFLAGS=-L${KIS_INSTALL_DIR}/lib
0336 
0337     print_msg "finished 3rdparty build setup"
0338 
0339     if [[ -n ${1} ]]; then
0340         cmake_3rdparty "${@}"
0341         # log "Syncing install backup..."
0342         # rsync -a --delete "${KIS_INSTALL_DIR}" "${KIS_INSTALL_DIR}.onlydeps"
0343         exit
0344     fi
0345 
0346     # build 3rdparty tools
0347     # The order must not be changed!
0348     cmake_3rdparty \
0349         ext_zlib \
0350         ext_iconv \
0351         ext_pkgconfig \
0352         ext_gettext \
0353         ext_openssl \
0354         ext_python \
0355         ext_qt \
0356         ext_boost \
0357         ext_eigen3 \
0358         ext_exiv2 \
0359         ext_fftw3 \
0360         ext_jpeg \
0361         ext_lcms2 \
0362         ext_ocio \
0363         ext_openexr
0364 
0365     cmake_3rdparty \
0366         ext_png \
0367         ext_tiff \
0368         ext_openjpeg \
0369         ext_gsl \
0370         ext_libraw \
0371         ext_giflib \
0372         ext_freetype \
0373         ext_fontconfig \
0374         ext_poppler
0375 
0376     # Stop if qmake link was not created
0377     # this meant qt build fail and further builds will
0378     # also fail.
0379     log_cmd test -L "${KIS_INSTALL_DIR}/bin/qmake-qt5"
0380 
0381     print_if_error "qmake link missing!"
0382     if [[ ${osxbuild_error} -ne 0 ]]; then
0383         printf "
0384     link: ${KIS_INSTALL_DIR}/bin/qmake-qt5 missing!
0385     It probably means ext_qt failed!!
0386     check, fix and rerun!\n"
0387         exit 1
0388     fi
0389 
0390     # for python
0391     cmake_3rdparty \
0392         ext_sip \
0393         ext_pyqt
0394 
0395     cmake_3rdparty ext_libheif
0396 
0397     cmake_3rdparty \
0398         ext_extra_cmake_modules \
0399         ext_kconfig \
0400         ext_kwidgetsaddons \
0401         ext_kcompletion \
0402         ext_kcoreaddons \
0403         ext_kguiaddons \
0404         ext_ki18n \
0405         ext_kitemmodels \
0406         ext_kitemviews \
0407         ext_kimageformats \
0408         ext_kwindowsystem \
0409         ext_quazip
0410 
0411     cmake_3rdparty ext_seexpr
0412     cmake_3rdparty ext_mypaint
0413     cmake_3rdparty ext_webp
0414     cmake_3rdparty ext_jpegxl
0415     cmake_3rdparty ext_xsimd
0416 
0417 
0418     ## All builds done, creating a new install onlydeps install dir
0419     dir_clean "${KIS_INSTALL_DIR}.onlydeps"
0420     log "Copying ${KIS_INSTALL_DIR} to ${KIS_INSTALL_DIR}.onlydeps"
0421     cp -aP "${KIS_INSTALL_DIR}" "${KIS_INSTALL_DIR}.onlydeps"
0422     print_msg "Build Finished!"
0423 }
0424 
0425 
0426 #not tested
0427 set_krita_dirs() {
0428     if [[ -n ${1} ]]; then
0429         KIS_BUILD_DIR=${BUILDROOT}/b_${1}
0430         KIS_INSTALL_DIR=${BUILDROOT}/i_${1}
0431         KIS_SRC_DIR=${BUILDROOT}/src_${1}
0432     fi
0433 }
0434 # build_krita
0435 # run cmake krita
0436 build_krita () {
0437     if [[ -z ${OSXBUILD_CLEAN} ]]; then
0438         log "Deleting ${KIS_BUILD_DIR}"
0439         dir_clean "${KIS_BUILD_DIR}"
0440     else
0441         if [[ -e "${KIS_INSTALL_DIR}.onlydeps" && -d "${KIS_INSTALL_DIR}.onlydeps" ]]; then
0442             print_msg "Found ${KIS_INSTALL_DIR}.onlydeps"
0443             log "==== manually copy onlydeps to ${KIS_INSTALL_DIR} if you need a fresh build"
0444         fi
0445     fi
0446 
0447     export DYLD_FRAMEWORK_PATH=${FRAMEWORK_PATH}
0448     echo ${KIS_BUILD_DIR}
0449     echo ${KIS_INSTALL_DIR}
0450     log_cmd check_dir_path ${KIS_BUILD_DIR}
0451     cd ${KIS_BUILD_DIR}
0452 
0453     if [ -z "${KRITA_BRANDING}" ]; then
0454         # determine the channel for branding
0455         if [ "${JOB_NAME}" == "Krita_Nightly_MacOS_Build" ]; then
0456             KRITA_BRANDING="Next"
0457         elif [ "${JOB_NAME}" == "Krita_Stable_MacOS_Build" ]; then
0458             KRITA_BRANDING="Plus"
0459         else
0460             KRITA_BRANDING=""
0461         fi
0462     fi
0463 
0464     declare -a CMAKE_CMD
0465     CMAKE_CMD=(cmake "${KIS_SRC_DIR}"
0466         -G "\"${OSXBUILD_GENERATOR}\""
0467         -DFOUNDATION_BUILD=ON
0468         -DBRANDING="${KRITA_BRANDING}"
0469         -DBoost_INCLUDE_DIR="${KIS_INSTALL_DIR}/include"
0470         -DCMAKE_INSTALL_PREFIX="${KIS_INSTALL_DIR}"
0471         -DCMAKE_PREFIX_PATH="${KIS_INSTALL_DIR}"
0472         -DDEFINE_NO_DEPRECATED=1
0473         -DBUILD_TESTING="${OSXBUILD_TESTING}"
0474         -DHIDE_SAFE_ASSERTS"=${OSXBUILD_HIDE_SAFEASSERTS}"
0475         -DKRITA_ENABLE_PCH=off
0476         -DKDE_INSTALL_BUNDLEDIR="${KIS_INSTALL_DIR}/bin"
0477         -DPYQT_SIP_DIR_OVERRIDE="${KIS_INSTALL_DIR}/share/sip/"
0478         -DCMAKE_BUILD_TYPE="${OSXBUILD_TYPE}"
0479         -DCMAKE_OSX_DEPLOYMENT_TARGET=10.13
0480         -DPYTHON_INCLUDE_DIR="${KIS_INSTALL_DIR}/lib/Python.framework/Headers"
0481         -DCMAKE_OSX_ARCHITECTURES="${OSX_ARCHITECTURES}"
0482         -DMACOS_UNIVERSAL="${OSXBUILD_UNIVERSAL}"
0483         )
0484 
0485     # hack:: Jenkins runs in x86_64 env, force run cmake in arm64 env.
0486     printf -v CMAKE_CMD_STRING '%s ' "${CMAKE_CMD[@]}"
0487     if [[ ${OSXBUILD_UNIVERSAL} ]]; then
0488         log_cmd env /usr/bin/arch -arm64 /bin/zsh -c "${CMAKE_CMD_STRING}"
0489     else
0490         log_cmd /bin/zsh -c "${CMAKE_CMD_STRING}"
0491     fi
0492 
0493     print_if_error "Configuration error! ${filename}" "exit"
0494 
0495     # copiling phase
0496     log_cmd cmake --build . -j${MAKE_THREADS}
0497     print_if_error "Krita compilation failed! ${filename}" "exit"
0498 
0499     # compile integrations
0500     if test "${OSTYPE}" == "darwin*"; then
0501         cd "${KIS_BUILD_DIR}/krita/integration/kritaquicklook"
0502         cmake --build . -j${MAKE_THREADS}
0503     fi
0504 }
0505 
0506 build_krita_tarball () {
0507     filename="$(basename ${1})"
0508     KIS_CUSTOM_BUILD="${BUILDROOT}/releases/${filename%.tar.gz}"
0509     print_msg "Tarball BUILDROOT is ${KIS_CUSTOM_BUILD}"
0510 
0511     filename_dir=$(dirname "${1}")
0512     cd "${filename_dir}"
0513     file_abspath="$(pwd)/${1##*/}"
0514 
0515     mkdir "${KIS_CUSTOM_BUILD}" 2> /dev/null
0516     cd "${KIS_CUSTOM_BUILD}"
0517 
0518     mkdir "src" "build" 2> /dev/null
0519     log_cmd tar -xzf "${file_abspath}" --strip-components=1 --directory "src"
0520 
0521     print_if_error "Failed untar of ${filename}" "exit"
0522 
0523     KIS_BUILD_DIR="${KIS_CUSTOM_BUILD}/build"
0524     KIS_SRC_DIR="${KIS_CUSTOM_BUILD}/src"
0525 
0526     build_krita
0527 
0528     print_msg "Build done!"
0529 }
0530 
0531 install_krita () {
0532     # custom install provided
0533     if [[ -n "${1}" ]]; then
0534         KIS_BUILD_DIR="${1}"
0535     fi
0536 
0537     # Delete any "krita" named file in install
0538     # this helps avoid double versioned libraries
0539     log "About to delete krita libs from ${KIS_INSTALL_DIR}"
0540     waiting_fixed "Deleting files in 5 seconds" 5
0541     find ${KIS_INSTALL_DIR} -type d -name "*krita*" | xargs -I FILE  rm -rf FILE
0542     find ${KIS_INSTALL_DIR}  \( -type f -or -type l \) -name "*krita*" | xargs -P4 -I FILE rm FILE
0543 
0544     print_msg "Install krita from ${KIS_BUILD_DIR}"
0545     log_cmd check_dir_path ${KIS_BUILD_DIR}
0546 
0547     cd "${KIS_BUILD_DIR}"
0548     osxbuild_error="${?}"
0549     print_if_error "could not cd to ${KIS_BUILD_DIR}" "exit"
0550 
0551     cmake --install .
0552 
0553     # compile integrations
0554     if test ${OSTYPE} == "darwin*"; then
0555         cd ${KIS_BUILD_DIR}/krita/integration
0556         cmake --install .
0557     fi
0558 }
0559 
0560 build_plugins () {
0561     if [[ -z ${OSXBUILD_CLEAN} ]]; then
0562         dir_clean "${KIS_PLUGIN_BUILD_DIR}"
0563     fi
0564 
0565     print_msg "building in ${KIS_PLUGIN_BUILD_DIR}"
0566 
0567     log "$(check_dir_path ${KIS_PLUGIN_BUILD_DIR})"
0568     log "$(check_dir_path ${KIS_DOWN_DIR})"
0569     log "$(check_dir_path ${KIS_INSTALL_DIR})"
0570 
0571     cd ${KIS_PLUGIN_BUILD_DIR}
0572 
0573     log_cmd cmake ${KIS_SRC_DIR}/3rdparty_plugins/ \
0574         -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 \
0575         -DCMAKE_INSTALL_PREFIX=${KIS_INSTALL_DIR} \
0576         -DCMAKE_PREFIX_PATH:PATH=${KIS_INSTALL_DIR} \
0577         -DEXTERNALS_DOWNLOAD_DIR=${KIS_DOWN_DIR} \
0578         -DINSTALL_ROOT=${KIS_INSTALL_DIR}
0579 
0580 
0581     print_msg "finished plugins build setup"
0582 
0583     cmake_3rdparty_plugins \
0584         ext_gmic \
0585 
0586     print_msg "Build Finished!"
0587 }
0588 
0589 # Runs all fixes for path and packages.
0590 # Historically only fixed boost @rpath
0591 fix_boost_rpath () {
0592     # helpers to define function only once
0593     fixboost_find () {
0594         for FILE in "${@}"; do
0595             if [[ -n "$(otool -L $FILE | grep boost)" ]]; then
0596                 log "Fixing -- $FILE"
0597                 log_cmd install_name_tool -change libboost_system.dylib @rpath/libboost_system.dylib $FILE
0598             fi
0599         done
0600     }
0601 
0602     batch_fixboost() {
0603         xargs -P4 -I FILE bash -c 'fixboost_find "FILE"'
0604     }
0605 
0606     export -f fixboost_find
0607     export -f log
0608     export -f log_cmd
0609 
0610     print_msg "Fixing boost in... ${KIS_INSTALL_DIR}"
0611     # log_cmd install_name_tool -add_rpath ${KIS_INSTALL_DIR}/lib ${KIS_INSTALL_DIR}/bin/krita.app/Contents/MacOS/krita
0612     # echo "Added rpath ${KIS_INSTALL_DIR}/lib to krita bin"
0613     # install_name_tool -add_rpath ${BUILDROOT}/deps/lib ${KIS_INSTALL_DIR}/bin/krita.app/Contents/MacOS/krita
0614     log_cmd install_name_tool -change libboost_system.dylib @rpath/libboost_system.dylib ${KIS_INSTALL_DIR}/bin/krita.app/Contents/MacOS/krita
0615 
0616     find -L "${KIS_INSTALL_DIR}" -name '*so' -o -name '*dylib' | batch_fixboost
0617 
0618     log "Fixing boost done!"
0619 }
0620 
0621 get_directory_fromargs() {
0622     local OSXBUILD_DIR=""
0623     for arg in "${@}"; do
0624         if [[ -d "${arg}" ]]; then
0625             OSXBUILD_DIR="${arg}"
0626             continue
0627         fi
0628     done
0629     echo "${OSXBUILD_DIR}"
0630 }
0631 
0632 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
0633 
0634 ####      Universal ARM x86_64 build functions and parameters     #####
0635 
0636 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
0637 
0638 DEPBUILD_X86_64_DIR="${BUILDROOT}/i.x86_64"
0639 DEPBUILD_ARM64_DIR="${BUILDROOT}/i.arm64"
0640 DEPBUILD_FATBIN_DIR="${BUILDROOT}/i.universal"
0641 
0642 build_x86_64 () {
0643     log "building builddeps_x86"
0644     # first set terminal to arch
0645     if [[ ${#@} > 0 ]]; then
0646         for pkg in ${@:1:${#@}}; do
0647             env /usr/bin/arch -x86_64 /bin/zsh -c "${BUILDROOT}/krita/packaging/macos/osxbuild.sh builddeps --dirty ${pkg}"
0648         done
0649     else
0650         env /usr/bin/arch -x86_64 /bin/zsh -c "${BUILDROOT}/krita/packaging/macos/osxbuild.sh builddeps"
0651     fi
0652     osxbuild_error="${?}"
0653     print_if_error "Error while building x86_64 deps" "exit"
0654 
0655     rsync -aq "${KIS_INSTALL_DIR}/" "${DEPBUILD_X86_64_DIR}"
0656 }
0657 
0658 
0659 build_arm64 () {
0660     log "building builddeps_arm64"
0661 
0662     # force arm64 build even in x86_64 envs 
0663     if [[ ${#@} > 0 ]]; then
0664         for pkg in ${@:1:${#@}}; do
0665             env /usr/bin/arch -arm64 /bin/zsh -c "${BUILDROOT}/krita/packaging/macos/osxbuild.sh builddeps --dirty ${pkg}"
0666         done
0667     else
0668         env /usr/bin/arch -arm64 /bin/zsh -c "${BUILDROOT}/krita/packaging/macos/osxbuild.sh builddeps"
0669     fi
0670     osxbuild_error="${?}"
0671     print_if_error "Error while building arm64 deps" "exit"
0672 
0673     rsync -aq "${KIS_INSTALL_DIR}/" "${DEPBUILD_ARM64_DIR}"
0674 }
0675 
0676 consolidate_universal_binaries () {
0677     for f in "${@}"; do
0678         # Only try to consolidate Mach-O and static libs
0679         if [[ -n $(file ${f} | grep "Mach-O") || "${f:(-2)}" = ".a" ]]; then
0680             # echo "${BUILDROOT}/${DEPBUILD_X86_64_DIR}/${f##*test-i/}"
0681             LIPO_OUTPUT=$(lipo -info ${f} | grep Non-fat 2> /dev/null)
0682             if [[ -n ${LIPO_OUTPUT} ]]; then
0683                 if [[ -f "${DEPBUILD_X86_64_DIR}/${f##*${DEPBUILD_FATBIN_DIR}/}" ]]; then
0684                     log "creating universal binary -- ${f##*${DEPBUILD_FATBIN_DIR}/}"
0685                     lipo -create "${f}" "${DEPBUILD_X86_64_DIR}/${f##*${DEPBUILD_FATBIN_DIR}/}" -output "${f}"
0686                 fi
0687             fi
0688             # log "ignoring ${f}"
0689         fi
0690     done
0691 
0692 }
0693 
0694 prebuild_cleanup() {
0695     # assume if an argument is given is a package name, do not erase install dir
0696     if [[ ${#@} > 0 ]]; then
0697         rsync -aq "${KIS_INSTALL_DIR}/" "${BUILDROOT}/i.temp"
0698     fi
0699     rm -rf "${DEPBUILD_FATBIN_DIR}" "${DEPBUILD_X86_64_DIR}" "${DEPBUILD_ARM64_DIR}"
0700 }
0701 
0702 postbuild_cleanup() {
0703     log "consolidating non-fat binaries and files"
0704     rsync -rlptgoq --ignore-existing "${DEPBUILD_X86_64_DIR}/" "${DEPBUILD_FATBIN_DIR}"
0705     rm -rf "${KIS_INSTALL_DIR}"
0706     rsync -aq "${DEPBUILD_FATBIN_DIR}/" "${KIS_INSTALL_DIR}"
0707     log "consolitating done! Build installed to ${KIS_INSTALL_DIR}"
0708 }
0709 
0710 universal_plugin_build() {
0711     DEPBUILD_X86_64_DIR="${BUILDROOT}/i_plug.x86_64"
0712     DEPBUILD_ARM64_DIR="${BUILDROOT}/i_plug.arm64"
0713     # DEPBUILD_FATBIN_DIR="${BUILDROOT}/i.universal"
0714 
0715     # assume i is universal but i.universal has to exist
0716     if [[ ! -d "${DEPBUILD_FATBIN_DIR}" ]]; then
0717         log "WARNING no i.universal install dir found! Make sure universal build finished properly"
0718         log "If you get errors building plugins this is likely the error."
0719     fi
0720 
0721     rsync -rlptgoq --ignore-existing "${KIS_INSTALL_DIR}/" "${DEPBUILD_FATBIN_DIR}/"
0722 
0723     log "building plugins_x86"
0724     env /usr/bin/arch -x86_64 /bin/zsh -c "${BUILDROOT}/krita/packaging/macos/osxbuild.sh buildplugins"
0725     osxbuild_error="${?}"
0726     print_if_error "Error while building x86_64 plugins" "exit"
0727     rsync -aq "${KIS_INSTALL_DIR}/" "${DEPBUILD_X86_64_DIR}"
0728 
0729     log "building plugins_arm64"
0730     # force arm64 build even in x86_64 envs
0731     env /usr/bin/arch -arm64 /bin/zsh -c "${BUILDROOT}/krita/packaging/macos/osxbuild.sh buildplugins"
0732     osxbuild_error="${?}"
0733     print_if_error "Error while building arm64 plugins" "exit"
0734     rsync -aq "${KIS_INSTALL_DIR}/" "${DEPBUILD_ARM64_DIR}"
0735 
0736     # sync files to universal install dir.
0737     rsync -aq "${DEPBUILD_ARM64_DIR}/" "${DEPBUILD_FATBIN_DIR}"
0738     consolidate_universal_binaries $(find "${DEPBUILD_FATBIN_DIR}" -type f)
0739     postbuild_cleanup
0740 
0741 }
0742 
0743 
0744 # # # # # # # # # # # # # # # # # # #
0745 
0746 ####     Script main routine    #####
0747 
0748 # # # # # # # # # # # # # # # # # # #
0749 print_usage () {
0750     printf "USAGE: osxbuild.sh <buildstep> [pkg|file]\n"
0751     printf "BUILDSTEPS:\t\t"
0752     printf "\n builddeps \t\t Run cmake step for 3rd party dependencies, optionally takes a [pkg] arg"
0753     printf "\n fixboost \t\t Fixes broken boost \@rpath on OSX"
0754     printf "\n build \t\t\t Builds krita"
0755     printf "\n buildtarball \t\t Builds krita from provided [file] tarball"
0756     printf "\n clean \t\t\t Removes build and install directories to start fresh"
0757     printf "\n install \t\t Installs krita. Optionally accepts a [build dir] as argument
0758     \t\t\t this will install krita from given directory"
0759     printf "\n buildinstall \t\t Build and Installs krita, running fixboost after installing"
0760     printf "\n"
0761     printf "OPTIONS:\t\t"
0762     printf "\n \t --dirty \t [build/install] (old default) Keep old build directories before build to start fresh"
0763     printf "\n \t --debug \t [build] Build in Debug mode"
0764     printf "\n \t --tests \t [build] Build tests"
0765     printf "\n \t --showasserts \t [build] Do not hide asserts"
0766     printf "\n \t --universal \t [build] (arm only) Build universal binary files."
0767     printf "\n"
0768     printf "\n \t --install_tarball \n \t\t\t [buildtarball] Install just built tarball file."
0769     printf "\n"
0770 }
0771 
0772 script_run() {
0773     if [[ ${#} -eq 0 ]]; then
0774         echo "ERROR: No option given!"
0775         print_usage
0776         exit 1
0777     fi
0778 
0779     if [[ ${1} = "builddeps" ]]; then
0780         if [[ ${OSXBUILD_UNIVERSAL} ]]; then
0781             prebuild_cleanup ${@:2}
0782             build_x86_64 ${@:2}
0783 
0784             build_arm64 "${@:2}"
0785 
0786             rsync -aq ${DEPBUILD_ARM64_DIR}/ ${DEPBUILD_FATBIN_DIR}
0787             consolidate_universal_binaries $(find "${DEPBUILD_FATBIN_DIR}" -type f)
0788 
0789             postbuild_cleanup
0790 
0791         else
0792             if [[ -z ${OSXBUILD_CLEAN} ]]; then
0793                 dir_clean "${KIS_INSTALL_DIR}"
0794                 dir_clean "${KIS_TBUILD_DIR}"
0795             fi
0796             build_3rdparty "${@:2}"
0797 
0798         fi
0799 
0800     elif [[ ${1} = "fixboost" ]]; then
0801         if [[ -d ${1} ]]; then
0802             KIS_BUILD_DIR="${1}"
0803         fi
0804         fix_boost_rpath
0805 
0806     elif [[ ${1} = "build" ]]; then
0807         OSXBUILD_DIR=$(get_directory_fromargs "${@:2}")
0808 
0809         build_krita "${OSXBUILD_DIR}"
0810         exit
0811 
0812     elif [[ ${1} = "buildplugins" ]]; then
0813         if [[ ${OSXBUILD_UNIVERSAL} ]]; then
0814             universal_plugin_build "${@:2}"
0815         else
0816             build_plugins "${@:2}"
0817         fi
0818         exit
0819 
0820     elif [[ ${1} = "buildtarball" ]]; then
0821         # uncomment line to optionally change
0822         # install directory providing a third argument
0823         # This is not on by default as build success requires all
0824         # deps installed in the given dir beforehand.
0825         # KIS_INSTALL_DIR=${3}
0826 
0827         if [[ -f "${2}" && "${2:(-7)}" == ".tar.gz" ]]; then
0828             TARBALL_FILE="${2}"
0829             build_krita_tarball "${TARBALL_FILE}"
0830 
0831             if [[ -n "${OSXBUILD_TARBALLINSTALL}" ]]; then
0832                 install_krita "${KIS_BUILD_DIR}"
0833             else
0834                 print_msg "to install run
0835 osxbuild.sh install ${KIS_BUILD_DIR}"
0836             fi
0837             exit
0838         else
0839             log "File not a tarball tar.gz file"
0840         fi
0841         
0842 
0843     elif [[ ${1} = "clean" ]]; then
0844         # remove all build and install directories to start
0845         # a fresh install. this no different than using rm directly
0846         dir_clean "${KIS_TBUILD_DIR}"
0847         dir_clean "${$KIS_BUILD_DIR}"
0848         dir_clean "${KIS_INSTALL_DIR}"
0849         exit
0850 
0851     elif [[ ${1} = "install" ]]; then
0852         OSXBUILD_DIR=$(get_directory_fromargs "${@:2}")
0853 
0854         install_krita "${OSXBUILD_DIR}"
0855         
0856         if [[ ${OSXBUILD_UNIVERSAL} ]]; then
0857             universal_plugin_build "${@:2}"
0858         else
0859             build_plugins "${OSXBUILD_DIR}"
0860         fi
0861 
0862         fix_boost_rpath
0863 
0864     elif [[ ${1} = "buildinstall" ]]; then
0865         OSXBUILD_DIR=$(get_directory_fromargs "${@:2}")
0866 
0867         build_krita "${OSXBUILD_DIR}"
0868         install_krita "${OSXBUILD_DIR}"
0869 
0870         if [[ ${OSXBUILD_UNIVERSAL} ]]; then
0871             universal_plugin_build "${@:2}"
0872         else
0873             build_plugins "${OSXBUILD_DIR}"
0874         fi
0875 
0876         fix_boost_rpath "${OSXBUILD_DIR}"
0877 
0878     elif [[ ${1} = "test" ]]; then
0879         ${KIS_INSTALL_DIR}/bin/krita.app/Contents/MacOS/krita
0880 
0881     else
0882         echo "Option ${1} not supported"
0883         print_usage
0884         exit 1
0885     fi
0886 }
0887 
0888 script_run ${parsed_args}