Commit 4e2b1b56 authored by Ivan Yossi's avatar Ivan Yossi 👌

packaging osx: Add Python as Framework

a Python.Framework install precompiles all python files and
also behaves better with code signing process.

To migrate:
- rebuild ext_python ext_sip ext_pyqt
- remove from BUILDROOT/i/lib python3.5 directory
parent c36fae1d
......@@ -5,12 +5,20 @@ if (UNIX)
message("WARNING: using system python3!")
SET(PYTHON_EXECUTABLE_PATH python3)
endif()
list(APPEND _PYQT_conf
--confirm-license
--qmake ${PREFIX_ext_pyqt}/bin/qmake
--sip ${PREFIX_ext_pyqt}/bin/sip
--sip-incdir ${PREFIX_ext_pyqt}/include
--sipdir ${PREFIX_ext_pyqt}/share/sip
)
ExternalProject_Add( ext_pyqt
DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR}
URL https://www.riverbankcomputing.com/static/Downloads/PyQt5/5.12.1/PyQt5_gpl-5.12.1.tar.gz
URL_MD5 67508b652098d2e05c4c2b5baeb170cc
CONFIGURE_COMMAND ${PYTHON_EXECUTABLE_PATH} <SOURCE_DIR>/configure.py --confirm-license --qmake ${PREFIX_ext_pyqt}/bin/qmake --sip ${PREFIX_ext_pyqt}/bin/sip --sip-incdir ${PREFIX_ext_pyqt}/include --sipdir ${PREFIX_ext_pyqt}/share/sip
CONFIGURE_COMMAND ${PYTHON_EXECUTABLE_PATH} <SOURCE_DIR>/configure.py ${_PYQT_conf}
BUILD_COMMAND make
INSTALL_COMMAND make install
......
SET(PREFIX_ext_python "${EXTPREFIX}" )
if (UNIX)
if (APPLE)
set(PYTHON_VERSION "3.5")
ExternalProject_Add( ext_python
DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR}
URL http://files.kde.org/krita/build/dependencies/Python-3.5.2.tar.gz
URL_MD5 ea334d398990037a4b8be324bd475c83
PATCH_COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/pyport_osx.diff
COMMAND ${PATCH_COMMAND} -p1 -i ${CMAKE_CURRENT_SOURCE_DIR}/osx_fixappinstall.diff
CONFIGURE_COMMAND <SOURCE_DIR>/configure MACOSX_DEPLOYMENT_TARGET=10.11 -prefix=${PREFIX_ext_python} --with-cxx-main=/usr/bin/g++ --without-ensurepip --without-gcc --enable-shared
CONFIGURE_COMMAND <SOURCE_DIR>/configure MACOSX_DEPLOYMENT_TARGET=10.11 -prefix=${PREFIX_ext_python} ${GLOBAL_AUTOMAKE_PROFILE}
--with-cxx-main=/usr/bin/g++ --without-ensurepip --disable-tests --without-test --without-tests --enable-framework=${PREFIX_ext_python}/lib
BUILD_COMMAND make
INSTALL_COMMAND make install
COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_python}/bin/python3 ${PREFIX_ext_python}/bin/python
COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_python}/bin/python3 ${PREFIX_ext_python}/bin/python
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/sitecustomize.py ${PREFIX_ext_python}/lib/Python.framework/Versions/Current/lib/python${PYTHON_VERSION}/
COMMAND ${CMAKE_COMMAND} -E create_symlink ./lib/python${PYTHON_VERSION}/site-packages ${PREFIX_ext_python}/lib/Python.framework/Versions/Current/site-packages
# CMake FindPythonLib can't find framework libraries, lack of mantainer for Python
COMMAND find ${PREFIX_ext_python}/lib/Python.framework/Versions/Current/lib -type l -d 1
| grep -o "[^/]*$"
| xargs -I FILE ${CMAKE_COMMAND} -E create_symlink ./Python.framework/Python ${PREFIX_ext_python}/lib/FILE
UPDATE_COMMAND ""
ALWAYS 0
......
diff --git a/configure b/configure
old mode 100755
new mode 100644
index c892a99..97c8f0d
--- a/configure
+++ b/configure
@@ -3207,7 +3207,7 @@ if test "${enable_framework+set}" = set; then :
FRAMEWORKINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkinstallunixtools"
FRAMEWORKALTINSTALLLAST="frameworkinstallmaclib frameworkinstallapps frameworkaltinstallunixtools"
FRAMEWORKPYTHONW="frameworkpythonw"
- FRAMEWORKINSTALLAPPSPREFIX="/Applications"
+ FRAMEWORKINSTALLAPPSPREFIX="${prefix}/Applications"
if test "x${prefix}" = "xNONE" ; then
FRAMEWORKUNIXTOOLSPREFIX="${ac_default_prefix}"
@@ -3218,7 +3218,7 @@ if test "${enable_framework+set}" = set; then :
case "${enableval}" in
/System*)
- FRAMEWORKINSTALLAPPSPREFIX="/Applications"
+ FRAMEWORKINSTALLAPPSPREFIX="${prefix}/Applications"
if test "${prefix}" = "NONE" ; then
# See below
FRAMEWORKUNIXTOOLSPREFIX="/usr"
@@ -3226,13 +3226,13 @@ if test "${enable_framework+set}" = set; then :
;;
/Library*)
- FRAMEWORKINSTALLAPPSPREFIX="/Applications"
+ FRAMEWORKINSTALLAPPSPREFIX="${prefix}/Applications"
;;
*/Library/Frameworks)
MDIR="`dirname "${enableval}"`"
MDIR="`dirname "${MDIR}"`"
- FRAMEWORKINSTALLAPPSPREFIX="${MDIR}/Applications"
+ FRAMEWORKINSTALLAPPSPREFIX="${MDIR}${prefix}/Applications"
if test "${prefix}" = "NONE"; then
# User hasn't specified the
@@ -3246,7 +3246,7 @@ if test "${enable_framework+set}" = set; then :
;;
*)
- FRAMEWORKINSTALLAPPSPREFIX="/Applications"
+ FRAMEWORKINSTALLAPPSPREFIX="${prefix}/Applications"
;;
esac
import os
import site
framework_path = os.path.dirname(os.path.abspath(__file__))
site.addsitedir(os.path.join(framework_path,'site-packages'))
site.addsitedir(os.path.join(framework_path,'site-packages', 'PyQt5'))
......@@ -233,7 +233,8 @@ else( APPLE )
endif()
ExternalProject_Add(ext_qt
ExternalProject_Add(
ext_qt
DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR}
LOG_DOWNLOAD ON
......
......@@ -21,32 +21,27 @@ if (UNIX)
UPDATE_COMMAND ""
)
else(APPLE)
find_package(PythonInterp 3.5)
if(NOT PYTHONINTERP_FOUND)
SET(PYTHON_EXECUTABLE ${PREFIX_ext_sip}/bin/python3)
if(NOT EXISTS "${PYTHON_EXECUTABLE}")
message("WARNING: using system python3!")
SET(PYTHON_EXECUTABLE python3)
endif()
# Get PYTHONVERSION
execute_process(COMMAND ${PYTHON_EXECUTABLE} -V COMMAND awk "{print $2}" OUTPUT_VARIABLE PYTHON_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE "." ";" PYTHON_VERSION_LIST ${PYTHON_VERSION})
list(GET PYTHON_VERSION_LIST 0 PYTHON_VERSION_MAJOR)
list(GET PYTHON_VERSION_LIST 1 PYTHON_VERSION_MINOR)
endif()
set(PY_VER "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}")
ExternalProject_Add( ext_sip
DOWNLOAD_DIR ${EXTERNALS_DOWNLOAD_DIR}
URL https://www.riverbankcomputing.com/static/Downloads/sip/sip-4.19.14.tar.gz
URL_MD5 bba62b2ea7e16193c7dfcfadb8dd0d05
URL https://www.riverbankcomputing.com/static/Downloads/sip/sip-4.19.15.zip
URL_MD5 4a1a4760cfabef15d68f45a6920974c2
CONFIGURE_COMMAND ${PYTHON_EXECUTABLE} <SOURCE_DIR>/configure.py -b ${PREFIX_ext_sip}/bin -d ${PREFIX_ext_sip}/sip -e ${PREFIX_ext_sip}/include --sipdir ${PREFIX_ext_sip}/sip --target-py-version ${PY_VER} --sip-module PyQt5.sip
CMAKE_ARGS -DPYTHON_INCLUDE_DIR=${PREFIX_ext_sip}/lib/Python.framework/Headers
CONFIGURE_COMMAND ${PYTHON_EXECUTABLE} <SOURCE_DIR>/configure.py --deployment-target=10.11
-b ${PREFIX_ext_sip}/bin -d ${PREFIX_ext_sip}/lib/Python.framework/Versions/Current/site-packages/
-e ${PREFIX_ext_sip}/include --sipdir ${PREFIX_ext_sip}/share/sip --target-py-version 3.5 --sip-module PyQt5.sip
BUILD_COMMAND make
INSTALL_COMMAND make install
COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_sip}/sip/PyQt5/sip.so ${PREFIX_ext_sip}/lib/python${PY_VER}/site-packages/PyQt5/sip.so
COMMAND ${CMAKE_COMMAND} -E copy ${PREFIX_ext_sip}/sip/PyQt5/sip.pyi ${PREFIX_ext_sip}/lib/python${PY_VER}/site-packages/PyQt5/sip.pyi
# COMMAND ${CMAKE_COMMAND} -E create_symlink ./PyQt5/sip.so ${PREFIX_ext_sip}/lib/Python.framework/Versions/Current/site-packages/sip.so
# COMMAND ${CMAKE_COMMAND} -E create_symlink ./PyQt5/sip.pyi ${PREFIX_ext_sip}/lib/Python.framework/Versions/Current/site-packages/sip.pyi
BUILD_IN_SOURCE 1
......
......@@ -65,6 +65,7 @@ export CPLUS_INCLUDE_PATH=${KIS_INSTALL_DIR}/include:/usr/include:${CPLUS_INCLUD
export LIBRARY_PATH=${KIS_INSTALL_DIR}/lib:/usr/lib:${LIBRARY_PATH}
# export CPPFLAGS=-I${KIS_INSTALL_DIR}/include
# export LDFLAGS=-L${KIS_INSTALL_DIR}/lib
export FRAMEWORK_PATH=${KIS_INSTALL_DIR}/lib/
# export PYTHONHOME=${KIS_INSTALL_DIR}
# export PYTHONPATH=${KIS_INSTALL_DIR}/sip:${KIS_INSTALL_DIR}/lib/python3.5/site-packages:${KIS_INSTALL_DIR}/lib/python3.5
......@@ -324,6 +325,7 @@ set_krita_dirs() {
# build_krita
# run cmake krita
build_krita () {
export DYLD_FRAMEWORK_PATH=${FRAMEWORK_PATH}
set_krita_dirs ${1}
echo ${KIS_BUILD_DIR}
echo ${KIS_INSTALL_DIR}
......@@ -337,9 +339,10 @@ build_krita () {
-DBUILD_TESTING=OFF \
-DHIDE_SAFE_ASSERTS=ON \
-DKDE_INSTALL_BUNDLEDIR=${KIS_INSTALL_DIR}/bin \
-DPYQT_SIP_DIR_OVERRIDE=$KIS_INSTALL_DIR/share/sip/ \
-DPYQT_SIP_DIR_OVERRIDE=${KIS_INSTALL_DIR}/share/sip/ \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.11
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 \
-DPYTHON_INCLUDE_DIR=${KIS_INSTALL_DIR}/lib/Python.framework/Headers
# copiling phase
make -j${MAKE_THREADS}
......@@ -364,6 +367,8 @@ install_krita () {
fi
}
# Runs all fixes for path and packages.
# Historically only fixed boost @rpath
fix_boost_rpath () {
set_krita_dirs ${1}
# install_name_tool -add_rpath ${KIS_INSTALL_DIR}/lib $BUILDROOT/$KRITA_INSTALL/bin/krita.app/Contents/MacOS/gmic_krita_qt
......@@ -380,6 +385,26 @@ fix_boost_rpath () {
install_name_tool -change libboost_system.dylib @rpath/libboost_system.dylib $FILE
fi
done
# site-packages is not added to path in Framework
# we create sitecustomize.py to add it on FrameworkPython start
# local py_mayor_version=$(python -c "import sys; print(sys.version_info[0])")
# if [[ ${py_mayor_version} -eq 3 ]]; then
# echo "Adding sitecustomize.py to Python.framework"
# local py_minor_version=$(python -c "import sys; print(sys.version_info[1])")
# local py_version="${py_mayor_version}.${py_minor_version}"
# local PythonLibDir="${KIS_INSTALL_DIR}/lib/Python.framework/Versions/Current/lib/python${py_version}/"
# printf "%s\n" \
# "import os
# import site
# framework_path = os.path.dirname(os.path.abspath(__file__))
# site.addsitedir(os.path.join(framework_path,'site-packages'))
# site.addsitedir(os.path.join(framework_path,'site-packages', 'PyQt5'))
# " \
# > ${PythonLibDir}/sitecustomize.py
# fi
}
print_usage () {
......
......@@ -70,6 +70,12 @@ export PATH=${KIS_INSTALL_DIR}/bin:$PATH
export MACOSX_DEPLOYMENT_TARGET=10.11
export QMAKE_MACOSX_DEPLOYMENT_TARGET=10.11
# Attempt to find python_version
local_PY_MAYOR_VERSION=$(python -c "import sys; print(sys.version_info[0])")
local_PY_MINOR_VERSION=$(python -c "import sys; print(sys.version_info[1])")
PY_VERSION="${local_PY_MAYOR_VERSION}.${local_PY_MINOR_VERSION}"
echo "Detected Python ${PY_VERSION}"
print_usage () {
echo "USAGE: osxdeploy.sh [-s=<identity>] <background-image>"
echo "\t -s Code sign identity for codesign"
......@@ -236,6 +242,43 @@ krita_findmissinglibs() {
fi
}
strip_python_dmginstall() {
# reduce size of framework python
# Removes tests, installers, pyenv, distutils
echo "Removing unnecesary files from Python.Framework to be packaged..."
PythonFrameworkBase="${KRITA_DMG}/krita.app/Contents/Frameworks/Python.framework"
cd ${PythonFrameworkBase}
find . -name "test*" -type d | xargs rm -rf
find "${PythonFrameworkBase}/Versions/${PY_VERSION}/bin" -not -name "python*" | xargs rm -f
cd "${PythonFrameworkBase}/Versions/${PY_VERSION}/lib/python${PY_VERSION}"
rm -rf distutils tkinter ensurepip venv lib2to3 idlelib
}
fix_python_framework() {
# Fix python.framework rpath and slims down installation
# fix library LD_RPATH excutable_path and loader_path.
# It is intended to be used for Libraries inside Frameworks.
fix_framework_library() {
xargs -P4 -I FILE sh -c "
install_name_tool -rpath ${KIS_INSTALL_DIR}/lib @loader_path/Frameworks \"${libFile}\" 2> /dev/null
install_name_tool -add_rpath @loader_path/../../../ \"${libFile}\" 2> /dev/null
"
}
# Start fixing all executables
PythonFrameworkBase="${KRITA_DMG}/krita.app/Contents/Frameworks/Python.framework"
install_name_tool -change @loader_path/../../../../libintl.9.dylib @loader_path/../../../libintl.9.dylib "${PythonFrameworkBase}/Python"
install_name_tool -add_rpath @executable_path/../../../../../../../ "${PythonFrameworkBase}/Versions/Current/Resources/Python.app/Contents/MacOS/Python"
install_name_tool -add_rpath @executable_path/../../../../ "${PythonFrameworkBase}/Versions/Current/bin/python${PY_VERSION}"
install_name_tool -add_rpath @executable_path/../../../../ "${PythonFrameworkBase}/Versions/Current/bin/python${PY_VERSION}m"
# Fix rpaths from Python.Framework
# install_name_tool change @loader_path/../../../libz.1.dylib
# Fix main library
printf ${PythonFrameworkBase}/Python | fix_framework_library
# find ${PythonFrameworkBase} -name "*.so" -not -type l | fix_framework_library
}
krita_deploy () {
# fix_boost_rpath
......@@ -254,8 +297,6 @@ krita_deploy () {
mkdir -p ${KRITA_DMG}/krita.app/Contents/PlugIns
mkdir -p ${KRITA_DMG}/krita.app/Contents/Frameworks
mkdir -p ${KRITA_DMG}/krita.app/Contents/Frameworks
echo "Copying share..."
# Deletes old copies of translation and qml to be recreated
cd ${KIS_INSTALL_DIR}/share/
......@@ -307,18 +348,6 @@ krita_deploy () {
# rsync -prul {KIS_INSTALL_DIR}/lib/libkrita* Frameworks/
# activate for python enabled Krita
echo "Copying python..."
# folders with period in name are treated as Frameworks for codesign
# there cant be empty files
rsync -prul ${KIS_INSTALL_DIR}/lib/python3.5/ ${KRITA_DMG}/krita.app/Contents/Frameworks/python
ln -s python ${KRITA_DMG}/krita.app/Contents/Frameworks/python3.5
rsync -prul ${KIS_INSTALL_DIR}/lib/krita-python-libs ${KRITA_DMG}/krita.app/Contents/Frameworks/
# XXX: fix rpath for krita.so
# echo "Copying sip..."
# rsync -Prvul ${KIS_INSTALL_DIR}/sip Frameworks/
# To avoid errors macdeployqt must be run from bin location
# ext_qt will not build macdeployqt by default so it must be build manually
# cd ${BUILDROOT}/depbuild/ext_qt/ext_qt-prefix/src/ext_qt/qttools/src
......@@ -338,6 +367,25 @@ krita_deploy () {
cd ${BUILDROOT}
echo "macdeployqt done!"
echo "Copying python..."
# Copy this framework last!
# It is best that macdeployqt does not modify Python.framework
# folders with period in name are treated as Frameworks for codesign
rsync -prul ${KIS_INSTALL_DIR}/lib/Python.framework ${KRITA_DMG}/krita.app/Contents/Frameworks/
rsync -prul ${KIS_INSTALL_DIR}/lib/krita-python-libs ${KRITA_DMG}/krita.app/Contents/Frameworks/
# change perms on Python to allow header change
chmod +w ${KRITA_DMG}/krita.app/Contents/Frameworks/Python.framework/Python
fix_python_framework
strip_python_dmginstall
# fix python pyc
# precompile all pyc so the dont alter signature
echo "Precompiling all python files..."
cd ${KRITA_DMG}/krita.app
${KIS_INSTALL_DIR}/bin/python -m compileall . &> /dev/null
install_name_tool -delete_rpath @loader_path/../../../../lib ${KRITA_DMG}/krita.app/Contents/MacOS/krita
rm -rf ${KRITA_DMG}/krita.app/Contents/PlugIns/kf5/org.kde.kwindowsystem.platforms
......@@ -346,11 +394,6 @@ krita_deploy () {
krita_findmissinglibs $(find ${KRITA_DMG}/krita.app/Contents -type f -name "*.dylib" -or -name "*.so" -or -perm u+x)
echo "Done!"
# fix python
# precompile all pyc so the dont alter signature
cd ${KRITA_DMG}/krita.app
${KIS_INSTALL_DIR}/bin/python -m compileall .
}
# helper to define function only once
......@@ -365,12 +408,12 @@ signBundle() {
cd ${KRITA_DMG}/krita.app/Contents/Frameworks
# remove debug version as both versions cant be signed.
rm ${KRITA_DMG}/krita.app/Contents/Frameworks/QtScript.framework/Versions/Current/QtScript_debug
find . -type d -name "*.framework" | xargs printf "%s/Versions/Current\n" | batch_codesign
find . -type f -name "*.dylib" -or -name "*.so" | batch_codesign
find . -type d -name "*.framework" | xargs printf "%s/Versions/Current\n" | batch_codesign
# Sign all other files in Framework (needed)
# there are many files in pyton do we need to sign them? TODO
# find krita-python-libs -type f | batch_codesign
# there are many files in python do we need to sign them all?
find krita-python-libs -type f | batch_codesign
# find python -type f | batch_codesign
# Sing only libraries and plugins
......@@ -392,7 +435,7 @@ signBundle() {
createDMG () {
printf "Creating of dmg with contents of %s...\n" "${KRITA_DMG}"
cd ${BUILDROOT}
DMG_size=500
DMG_size=700
## Build dmg from folder
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment