TODO: Things to remember to document or automate
* Properly handle symlinks in <<source>>/gmpy2 directory for:
  * gmpy2.h (all platforms)
  * gmpy2.pxd (all platforms)
  * various support DLLs (Windows)
* Force older versions of setuptools (probably not needed)
  * 47.1.0 seems to be okay (maybe) (probably not needed)
* Make MANIFEST.in include all dll files in gmpy2 sub-directory
  * Also, make sure to copy the dll
* pip install wheel
* Convert .egg format to .whl format
  * cd dist
  * py27 -m wheel convert *.egg


Building gmpy2 with MSYS2 and MinGW-w64
=======================================

High-level overview
-------------------

1.  Compile the GMP, MPFR, and MPC libraries
    1.  Install the MSYS2 environment
    2.  Install the MinGW-w64 compiler tools

        The MSYS2 version of MinGW-w64 or a version from winlibs.com can be used.

    3.  Dowload and compile GMP, MPFR, and MPC

2.  Prepare Windows environment
    1.  Install Python versions as needed
    2.  Update pip, setuptools, wheel, and (optionally) pytest
    3.  Replace cygwincompiler.py with patched version
    4.  Create def files for Python version that are installed

3.  Update build environment and compile gmpy2

Note: These instructions are a work in progress!

From the MSYS2 home page:

https://www.msys2.org/

MSYS2 is a Cygwin-derived Posix-like environment for Windows. The name is a
contraction of Minimal SYStem 2, and aims to provide support to facilitate
using the bash shell, Autotools, revision control systems and the like for
building native Windows applications using MinGW-w64 toolchains.

Installing MSYS2
================

Note: The following instructions assume MSYS2 and MinGW-w64 are installed as
      D:\msys2 and D:\mingw64, respectively. 

Detailed MSYS2 installation instructions can be found at:

https://www.msys2.org/wiki/MSYS2-installation/

The examples assume the 64-bit version of MSYS2 is installed.

The following additional packages should also be installed:

pacman -S patch m4 lzip wget tar make diffutils

Installing MinGW-w64
====================

MSYS2 follows a "rolling-release" model. New versions of applications,
including the MinGW-w64 compiler suite, are released frequently. The continual
release cycles makeit difficult to provide a reproducible compliler. We will 
be using MinGW-w64 as distributed by http://winlibs.com/. This documentation
was based on the following version:

https://github.com/brechtsanders/winlibs_mingw/releases/download/10.3.0-12.0.0-9.0.0-r2/winlibs-x86_64-posix-seh-gcc-10.3.0-llvm-12.0.0-mingw-w64-9.0.0-r2.7z

Unzip the downloaded file and copy the "mingw64" to the desired location.
The following documentation assumes the files are copied to D:\mingw64.

The build environment
=====================

The build process is split into two phases. During phase 1 we use the MSYS2
shell environment and winlibs.com MinGW-w64 compiler suite to build GMP, MPFR,
and MPC. Once those libraries are built, we will use the Windows command prompt
and the same compiler to build the actual gmpy2 extension (DLL). 

Commands that must be executed from an MSYS2 shell are preceded by "$".
Commands that must be executed from a Windows command prompt are preceded
by ">". You will need to run the commands *after* "$" or ">".

The MSYS2 environment provides different command line operating
environments. We will just use the generic "MSYS2 MSYS" environment.

 * MSYS2 MSYS
   This is the general-purpose MSYS shell but it does not provide
   access to the MinGW compiler suite. We will use this shell and
   manually add the location of the winlibs.com version.

MSYS2 does include versions of GMP, MPFR, and MPC but we will compile our
own version directly from the source. We do this so we can create reproducible
builds.

Compiling GMP, MPFR, and MPC
============================

# Start the appropriate shell: MSYS2 MSYS

# Add the MinGW-w64 compiler to the PATH.

  PATH="/c/mingw64/bin:"$PATH

# In you home directory, create directories for the various files that
# are created.

  mkdir $HOME/64
  mkdir $HOME/64/src
  mkdir $HOME/64/static
  mkdir $HOME/64/shared

# Download and uncompress GMP, MPFR, and MPC

  The following instructions build GMP, MPFR, and MPC shared libraries that are redistributed with gmpy2.

  cd $HOME/64/src

# Download GMP
  wget https://gmplib.org/download/gmp/gmp-6.2.1.tar.lz
  tar xf gmp-6.2.1.tar.lz

# Download MPFR and any patches
  wget http://www.mpfr.org/mpfr-current/mpfr-4.1.0.tar.bz2
  tar xf mpfr-4.1.0.tar.bz2
  cd mpfr-4.1.0/
  wget http://www.mpfr.org/mpfr-current/allpatches
  patch -N -Z -p1 < allpatches
  cd ..

# Download MPC
  wget ftp://ftp.gnu.org/gnu/mpc/mpc-1.2.0.tar.gz
  tar xf mpc-1.2.0.tar.gz

# Compile GMP
  cd gmp-6.2.1/
  ./configure --build=x86_64-pc-mingw64 --host=x86_64-pc-mingw64 --prefix=$HOME/64/static --enable-shared --disable-static --enable-fat --with-pic
  make
  make check
  make install
  cd ..

# Compile MPFR
  cd mpfr-4.1.0/
  ./configure --build=x86_64-pc-mingw64 --host=x86_64-pc-mingw64 --prefix=$HOME/64/static --enable-static --disable-shared --disable-decimal-float --disable-float128 --with-pic --with-gmp=$HOME/64/static
  make
  make check
  make install
  cd ..

# Compile MPC
  cd mpc-1.2.0/
  ./configure --build=x86_64-pc-mingw64 --host=x86_64-pc-mingw64 --prefix=$HOME/64/static --enable-static --disable-shared --with-pic --with-gmp=$HOME/64/static --with-mpfr=$HOME/64/static
  make
  make check
  make install
  cd ..

The Windows build environment
=============================

# Configure Windows command prompt - GCC

  Note: The following command is automatically run by the 64bit.bat file
        documented below.

  > set Path=D:\mingw64\bin;%Path%

  To verfiy the MinGW toolchain is accessible, the command "gcc -v" should
  return information about the gcc compiler.

  Note: All the remaining instructions assume this step has been completed and
        that "gcc -v" returns information for the correct version of gcc.

# Configure Windows command prompt - Python

  The Python interpreter does not need to be accessible via the path. You can
  specify the full path name to start a particular version. To simplify the
  compilation of multiple versions of gmpy2, I have adopted the following
  approach:

  # 64-bit versions of Python are installed in D:\64
  # Aliases are defined to create shortcuts for invoking a Python interpreter

  I use the following batch file to configure a command prompt for 64-bit builds:

  @echo off
  doskey py27=D:\64\Python27\python.exe $*
  doskey py35=D:\64\Python35\python.exe $*
  doskey py36=D:\64\Python36\python.exe $*
  doskey py37=D:\64\Python37\python.exe $*
  doskey py38=D:\64\Python38\python.exe $*
  doskey py39=D:\64\Python39\python.exe $*
  doskey py310=D:\64\Python310\python.exe $*
  set Path=D:\mingw64\bin;%Path%

  A copy of the batch file can be found in <<gmpy2 source>>\mingw64\64bit.bat

# Upgrade pip and setuptools

  Repeat as needed for different versions of Python

  py36 -m pip install --upgrade pip
  py36 -m pip install --upgrade setuptools
  py36 -m pip install pytest wheel

# Replace Python's cygwinccompiler.py with the numpy.distutils verion
# located in the <<gmpy2 source>>\ming64\distutils directory.

  copy /y mingw64\distutils\cygwinccompiler.py D:\64\Python27\Lib\distutils\.
  copy /y mingw64\distutils\cygwinccompiler.py D:\64\Python35\Lib\distutils\.
  copy /y mingw64\distutils\cygwinccompiler.py D:\64\Python36\Lib\distutils\.
  copy /y mingw64\distutils\cygwinccompiler.py D:\64\Python37\Lib\distutils\.
  copy /y mingw64\distutils\cygwinccompiler.py D:\64\Python38\Lib\distutils\.
  copy /y mingw64\distutils\cygwinccompiler.py D:\64\Python39\Lib\distutils\.
  copy /y mingw64\distutils\cygwinccompiler.py D:\64\Python310\Lib\site-packages\setuptools\_distutils\.
  copy /y mingw64\distutils\cygwinccompiler.py D:\64\Python311\Lib\site-packages\setuptools\_distutils\.

# Create the appropriate libpythonNN.a files. See gendef64.bat

cd D:\64\Python27\libs
gendef C:\Windows\System32\python27.dll
dlltool --dllname C:\Windows\System32\python27.dll --def python27.def --output-lib libpython27.a

cd D:\64\Python35\libs
gendef D:\64\Python35\python35.dll
dlltool --dllname D:\64\Python35\python35.dll --def python35.def --output-lib libpython35.a

cd D:\64\Python36\libs
gendef D:\64\Python36\python36.dll
dlltool --dllname D:\64\Python36\python36.dll --def python36.def --output-lib libpython36.a

cd D:\64\Python37\libs
gendef D:\64\Python37\python37.dll
dlltool --dllname D:\64\Python37\python37.dll --def python37.def --output-lib libpython37.a

cd D:\64\Python38\libs
gendef D:\64\Python38\python38.dll
dlltool --dllname D:\64\Python38\python38.dll --def python38.def --output-lib libpython38.a

cd D:\64\Python39\libs
gendef D:\64\Python39\python39.dll
dlltool --dllname D:\64\Python39\python39.dll --def python39.def --output-lib libpython39.a

cd D:\64\Python310\libs
gendef D:\64\Python310\python310.dll
dlltool --dllname D:\64\Python310\python310.dll --def python310.def --output-lib libpython310.a

# Copy the result of the compilation to the <<gmpy2 source>>\mingw64\shared directory

xcopy /s /y D:\64\shared D:\64\gmpy2\mingw64\shared

# Copy the libgcc_s_seh-1.dll file from the mingw64 distribution to the
# <<gmpy2 source>>\mingw64\shared\bin directory.

copy /y D:\mingw64\bin\libgcc_s_seh-1.dll D:\64\gmpy2\mingw64\shared\bin

# Copy the libwinpthread-1.dll file from the mingw64 distribution to the 
# <<gmpy2 source>>\mingw64\shared\bin directory.

copy /y D:\mingw64\bin\libwinpthread-1.dll D:\64\gmpy2\mingw64\shared\bin

# To compile gmpy2

# Copy the additional DLL files to <<gmpy2 source>>\gmpy2

xcopy /y D:\64\gmpy2\mingw64\shared\bin\. D:\64\gmpy2\gmpy2\

# Complile and create a binary wheel.

py27 setup.py build_ext -cmingw32 -Imingw64\shared\include -Lmingw64\shared\lib -f bdist_wheel
py35 setup.py build_ext -cmingw32 -Imingw64\shared\include -Lmingw64\shared\lib -f bdist_wheel
py36 setup.py build_ext -cmingw32 -Imingw64\shared\include -Lmingw64\shared\lib -f bdist_wheel
py37 setup.py build_ext -cmingw32 -Imingw64\shared\include -Lmingw64\shared\lib -f bdist_wheel
py38 setup.py build_ext -cmingw32 -Imingw64\shared\include -Lmingw64\shared\lib -f bdist_wheel
py39 setup.py build_ext -cmingw32 -Imingw64\shared\include -Lmingw64\shared\lib -f bdist_wheel
py310 setup.py build_ext -cmingw32 -Imingw64\shared\include -Lmingw64\shared\lib -f bdist_wheel
py311 setup.py build_ext -cmingw32 -Imingw64\shared\include -Lmingw64\shared\lib -f bdist_wheel
