# *** IMPORTANT ***

# Build Prerequisite requirements for Python 3.11.3 on macOS 10.13 Sierra and later users:
#
#     First make sure you are using the latest XCode for your version of Mac OSX
#     Then make sure you have the command line tools (CLT) installed (via xcode-select --install)
#
#
#     For Python's pip3 and lzma module, and other Python functionality you will need to
#     compile and install the headers and static library versions of liblzma.a (xz),
#     libssl.a (libopenssl), and libcrypto.a (libopenssl), along side
#     static versions of sqlite, and a specially built internal TclTk library
#

# Create a build folder where all of the work will be done

cd 
mkdir devpython
cd devpython


# If you are using XCode 10.X on MacOSX 10.14.X, remember to install the command line tools 
# and their headers!  The headers are now not installed by default.  An installer package
# for the headers can be found here:
# 
# /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg

# First build the main prerequisites

# Download openssl-1.1.1t.tar.gz or later into sources from https://www.openssl.org/source

export MACOSX_DEPLOYMENT_TARGET=10.13
export LDFLAGS="-Wl,-macosx_version_min,10.13"

tar -zxvf ../sources/openssl-1.1.1t.tar.gz
cd openssl-1.1.1t
./config no-shared --prefix=/usr/local
make -j4
sudo make install


# Download xz-5.4.2.tar.gz or later into sources from https://tukaani.org/xz/  (via sourceforge)

export MACOSX_DEPLOYMENT_TARGET=10.13
export LDFLAGS="-Wl,-macosx_version_min,10.13"
export CFLAGS="-mmacosx-version-min=10.13 -Werror=partial-availability"

tar -zxvf ../sources/xz-5.4.2.tar.gz
cd xz-5.4.2
./configure --disable-shared --prefix=/usr/local
make -j4
sudo make install


# Download sqlite-autoconf-3410200.tar.gz into sources from 
# https://sqlite.org/2021/sqlite-autoconf-3410200.tar.gz"

export MACOSX_DEPLOYMENT_TARGET=10.13
export LDFLAGS="-Wl,-macosx_version_min,10.13"
export CFLAGS="-mmacosx-version-min=10.13 -Werror=partial-availability -Os -DSQLITE_ENABLE_FTS5 \
            -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_JSON1 \
            -DSQLITE_ENABLE_RTREE -DSQLITE_TCL=0 "
tar -zxvf ../sources/sqlite-autoconf-3410200.tar.gz
cd sqlite-autoconf-3410200
./configure --enable-threadsafe --enable-shared=no --enable-static=yes --disable-readline --disable-dependency-tracking
make -j4
sudo make install


# Specify the future home for the Python.framework and interim tcltk pieces

mkdir libraries
cd libraries
export MYLIBS=`pwd`
mkdir Frameworks
cd Frameworks
export MYDEST=`pwd`
cd ../../

# To enable the Tk / tkinter graphical ui for Python we will need to make a special 
# combined build of tcl and tk and build it right "in place" for the future 
# Python.framework to install around

# Download tcl8.6.12-src.tar.gz into sources from ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tcl8.6.12-src.tar.gz
# Download tk8.6.12-src.tar.gz into sources from ftp://ftp.tcl.tk/pub/tcl//tcl8_6/tk8.6.12-src.tar.gz

mkdir tcltk
cd tcltk
tar -zxvf ../../sources/tcl8.6.12-src.tar.gz
tar -zxvf ../../sources/tk8.6.12-src.tar.gz

# Note: TCL_LIBRARY and TK_LIBRARY and libdir are appended to DESTDIR to get actual paths

export MACOSX_DEPLOYMENT_TARGET=10.13
export CFLAGS="-arch x86_64 -mmacosx-version-min=10.13"
cd tcl8.6.12/unix
./configure --enable-shared --enable-threads --libdir=/Frameworks/Python.framework/Versions/3.11/lib
make TCL_LIBRARY=/Frameworks/Python.framework/Versions/3.11/lib/tcl8.6 DESTDIR=${MYLIBS}
make install TCL_LIBRARY=/Frameworks/Python.framework/Versions/3.11/lib/tcl8.6 DESTDIR=${MYLIBS}
cd ../../
cd tk8.6.12/unix
./configure --libdir=/Frameworks/Python.framework/Versions/3.11/lib --enable-aqua --enable-shared --enable-threads

make TCL_LIBRARY=/Frameworks/Python.framework/Versions/3.11/lib/tcl8.6 \
     TK_LIBRARY=/Frameworks/Python.framework/Versions/3.11/lib/tk8.6 \
     DESTDIR=${MYLIBS}

make install TCL_LIBRARY=/Frameworks/Python.framework/Versions/3.11/lib/tcl8.6 \
     TK_LIBRARY=/Frameworks/Python.framework/Versions/3.11/lib/tk8.6 \
     DESTDIR=${MYLIBS}

# As a last step fixup the dylib official names to properly reflect their new home

cd ${MYDEST}/Python.framework/Versions/3.11/lib
chmod u+w libtk8.6.dylib
chmod u+w libtcl8.6.dylib
install_name_tool -id ${MYDEST}/Python.framework/Versions/3.11/lib/libtcl8.6.dylib ./libtcl8.6.dylib
install_name_tool -id ${MYDEST}/Python.framework/Versions/3.11/lib/libtk8.6.dylib ./libtk8.6.dylib

#     And finally:
#     if you are using Qt5,  we will be building a required PyQt5 python module, 
#     you will need to have built or
#         downloaded prebuilt versions of Qt 5.15.X or later first
#          So see Building_Qt5_From_Source_on_MacOSX.txt
#
#     if you are using Qt6, we will building the required PySide6 module, you will need to have built
#         or downloaded prebuilt versions of Qt 6.2.2 or later

# Building Python 3.11.3 to be fully relocatable for macOS 10.13 and later

# Before building remember to rename any /Applications/Python 3.11.app to save it and 
# replace it afterwards as the damn python installation from source always overwrites
# it no matter the configure prefix used

# Download Python-3.11.3.tgz into sources from www.python.org

cd ${MYDEST}
cd ../../

export MACOSX_DEPLOYMENT_TARGET=10.13

# now build Python 3.11.3 as a framework
# no need to worry about what symbols exist in what version of 
# macOS any longer, since Python 3.9.1 and later use and test for weak symbols

tar -xvf ../sources/Python-3.11.3.tgz
cd Python-3.11.3

export LDFLAGS="-Wl,-macosx_version_min,10.13" 
export CFLAGS="-mmacosx-version-min=10.13" 
./configure --prefix=${MYDEST} --enable-framework=${MYDEST} --with-ensurepip \
    TCLTK_CFLAGS="-I${MYLIBS}/usr/local/include" \
    TCLTK_LIBS="-L${MYDEST}/Python.framework/Versions/3.11/lib -ltcl8.6 -ltk8.6"

make -j4
make frameworkinstall


# Now due to changes in Python3 since 3.9, the places it looks for the tcl8.6 and
# tk8.6 folders moves if Python3 is NOT installed in the standard framework
# location (not in /Library/Framework/Python.framework).
# So Python3 can not find its platform independent tcltk (tkinter) libraries
# on macOS if moved.   Because an "app" is needed for gui activity, these libraries
# must be found relative to the internal Python.app

# To allow our Python to fully moveable we must move these tcltk platform 
# independent files to a new lib folder placed in Python.app/Contents/
# so that they can always be found as follows:

cd ${MYDEST}/Python.framework/Versions/3.11/Resources/Python.app/Contents
mkdir lib
cd lib
mv ${MYDEST}/Python.framework/Versions/3.11/lib/tcl8.6 ./
mv ${MYDEST}/Python.framework/Versions/3.11/lib/tk8.6 ./

cd ${MYDEST}
cd ../../

# next update path in order to use the newly built/installed Python.framework's
# and then use pip3 to install all other required python packages to its site-packages

export PATH=${MYDEST}/Python.framework/Versions/3.11/bin:${PATH}
which pip3

pip3 install six
pip3 install html5lib
pip3 install lxml
pip3 install Pillow
pip3 install regex
pip3 install css-parser
pip3 install cssselect
pip3 install chardet
pip3 install certifi
pip3 install urllib3
pip3 install dulwich


# Now a complete Python.framework has been built in ${MYDEST}
# But we still need to make it a relocatable framework

# To make it relocatable we need to use otool and install_name_tool to change
# the dylib name and path to it from all executables in the Python.framework

# A Quick Guide: On Mac OS X, one may use:
#     "otool -D <file>" to view the install name of a dylib
#     "otool -L <file>" to view the dependencies
#     "otool -l <file> | grep LC_RPATH -A2" to view the RPATHs
#     "install_name_tool -id ..." to change an install name
#     "install_name_tool -change ..." to change the dependencies
#     "install_name_tool -rpath ... -add_rpath ... -delete_rpath ..." to change RPATHs
 
# Make the framework's main dylib relocatable using rpath

cd ${MYDEST}/Python.framework/Versions/3.11/
chmod u+w Python
otool -D ./Python
install_name_tool -id @rpath/Python ./Python

# Change the dependencies of the executable files in bin to point to the relocatable 
# framework in a relative way and add the proper rpath to find the Python (renamed dylib)

cd bin
install_name_tool -change ${MYDEST}/Python.framework/Versions/3.11/Python @rpath/Python python3.11
install_name_tool -add_rpath @executable_path/../ ./python3.11


# so that python3 can find the Qt Frameworks and proper plugins for PyQt5

install_name_tool -add_rpath @executable_path/../../../../ ./python3.11

# now do the same for the Python.app stored inside the Python.framework Resources 
# This app is needed to allow gui use by python for plugins

cd ${MYDEST}/Python.framework/Versions/3.11/Resources/Python.app/Contents/MacOS
install_name_tool -change ${MYDEST}/Python.framework/Versions/3.11/Python @rpath/Python ./Python
install_name_tool -add_rpath @executable_path/../../../../ ./Python

# And finally we need to change the name id on the libtk and libtcl to be rpath based
# and fix the _tkinter*.so to have an rpath with a @loader_path back up to the lib dir 
# where they live

cd ${MYDEST}/Python.framework/Versions/3.11/lib
otool -D libtk8.6.dylib
otool -D libtcl8.6.dylib
install_name_tool -id @rpath/libtcl8.6.dylib ./libtcl8.6.dylib
install_name_tool -id @rpath/libtk8.6.dylib ./libtk8.6.dylib
cd ${MYDEST}/Python.framework/Versions/3.11/lib/python3.11/lib-dynload
install_name_tool -add_rpath @loader_path/../.. _tkinter.cpython-311-darwin.so
install_name_tool -change ${MYDEST}/Python.framework/Versions/3.11/lib/libtcl8.6.dylib @rpath/libtcl8.6.dylib _tkinter.cpython-311-darwin.so
install_name_tool -change ${MYDEST}/Python.framework/Versions/3.11/lib/libtk8.6.dylib @rpath/libtk8.6.dylib _tkinter.cpython-311-darwin.so


# We should now have a fully relocatable Python.framework


# We will now use this just-built Python3.11 interpreter to install PyQt5, PyQtWebEngine and sip
# for Qt 5.15.X or PySide6 for Qt 6.X


# ***** IF USING QT5 ******

# **** Important: versions of PyQt5 and sip must be selected to match with the Qt version
# **** In these instructions we are using Qt 5.15.X and therefore need:
# **** sip-6.7.8 and PyQt5-5.15.9 and PyQtWebEngine-5.15.6 and PyQtS-sip

# First Build sip
# Building sip-6.7.8 from source and installing it into your Python Interpreter

# From https://www.riverbankcomputing.com/software/pyqt/download5
# Download sip-6.7.8.tar.gz

# Must have the python interpreter you want to install PyQt5 into in the PATH to be found first

export PATH=${MYDEST}/Python.framework/Versions/3.11/bin:${PATH}
which python3

# but first we need a few support modules

pip3 install packaging
pip3 install ply
pip3 install PyQt-builder

# to build sip

tar -zxvf ../sources/sip-6.7.8.tar.gz
cd sip-6.7.8
python3 ./setup.py build
python3 ./setup.py install
cd ..


# Must have the Qt5.15.9 bin directory in the path to specify which Qt to use
# See Building_Qt5_From_Source_on_MacOSX.txt

export PATH=/Users/${USER}/Qt5159/bin:${PATH}
which qmake

export MACOSX_DEPLOYMENT_TARGET=10.13


# Next Build PyQt5 for Qt-5.15.9 from source and installing it into your Python Interpreter
# From https://www.riverbankcomputing.com/software/pyqt/download5
# Download PyQt5-5.15.9.tar.gz

tar -zxvf ../sources/PyQt5-5.15.9.tar.gz
cd PyQt5-5.15.9
sip-install

# And Next build PyQtWebEngine (again with the destination python3 and qmake in your path)
# From https://sourceforge.net/projects/pyqtwebengine/
# Download: PyQtWebEngine-5.15.6.tar.gz

export MACOSX_DEPLOYMENT_TARGET=10.13

tar -zxvf ../sources/PyQtWebEngine-5.15.6.tar.gz
cd PyQtWebEngine-5.15.6/
sip-install


# And finally build PyQt5_sip and install it from source using PyQt5_sip-12.12.0
# Or use pip3 to install the latest PyQt5-sip
# pip3 install PyQt5-sip

tar -zxvf ../sources/PyQt5_sip-12.12.0.tar.gz
cd PyQt5_sip-12.12.0
python3 setup.py build
python3 setup.py install

# And of course, the damn PyQt5_sip source build puts the pieces inside a
# damn egg and not where they truly belong inside site-packages/PyQt5.
# So fix it with the following:

cd ${MYDEST}/Python.framework/Versions/3.11/lib/python3.11/site-packages
cd PyQt5_sip-12.12.0-py3.11-macosx-10.13-x86_64.egg/PyQt5
cp *.so ../../PyQt5/
cp *.py ../../PyQt5/

 


# ***** IF USING QT6 *****

# Download pyside-setup-opensource-src-6.2.2.tar.xz from
# https://download.qt.io/official_releases/QtForPython/

export MACOSX_DEPLOYMENT_TARGET=10.14

export MYQTHOME=~/Qt624
export PATH=${PATH}:${MYQTHOME}/bin
export PATH=${MYDEST}/Python.framework/Versions/3.11/bin:${PATH}

which qmake
which python3

# Prerequisites

# Your will need to have the packaging module installed on your python3

pip3 install --upgrade --force-reinstall packaging

# As well as a recent version of setuptools 
# (some newer versions have broken compatibility)
# pip3 install setuptools==59.8.0

# You will need libclang (although macOS has this lib pre-installed, it can *not* 
# be found by Qt's cmake.  Qt has pre-build binaries ready to be used for each platform.
# I recommend storing it someplace *outside* the normal path such as /opt to help 
# prevent future any name clash issues.
# Download  libclang-release_130-based-macos-universal.7z from:
#       https://download.qt.io/development_releases/prebuilt/libclang/

cd /opt
# and unpack libclang-release_130-based-macos-universal.7z in /opt to create /opt/libclang

# Tell the pyside6 build where to find it

export CLANG_INSTALL_DIR=/opt/libclang


# You should now be ready to build pyside6

unxz ./sources/pyside-setup-opensource-src-6.2.4.tar.xz
tar -xvf ./sources/pyside-setup-opensource-src-6.2.4.tar
cd pyside-setup-opensource-src-6.2.4

python3 setup.py install --parallel=8 --build-tests


# Once complete you will have properly built a Python 3.11 interpreter to be embedded inside
# of Sigil
