Unverified Commit 5c09f800 authored by Andrew Murray's avatar Andrew Murray Committed by GitHub
Browse files

Merge branch 'devel' into order

parents 78ee115e 45d97819
......@@ -83,9 +83,9 @@ test_script:
- ps: .\install_python.ps1
- set PYTHON=C:\Python38-x64
- ps: .\install_python.ps1
- set PYTHON=C:\Python38rc1-x64
- ps: .\install_python.ps1
- set PYTHON=C:\Python38
- ps: .\install_python.ps1
- set PYTHON=C:\Python38rc1
- set PYTHON=C:\Python39rc1-x64
- ps: .\install_python.ps1
- set PYTHON=C:\Python39rc1
- ps: .\install_python.ps1
......@@ -9,24 +9,31 @@ cache:
env:
global:
# Always set Python version
- MB_PYTHON_VERSION=3.7
- MB_PYTHON_VERSION=3.9
matrix:
include:
- os: linux
dist: trusty
language: python
# 64-bit builds
- os: linux
dist: xenial
env:
- TEST_BUILDS=1
# 64-bit builds, manylinux2010
# 64-bit builds
- os: linux
dist: xenial
env:
- TEST_BUILDS=1
- MB_ML_VER=2010
- DOCKER_TEST_IMAGE=multibuild/xenial_{PLAT}
- os: linux
dist: xenial
env:
- TEST_BUILDS=1
- MB_ML_VER=_2_24
- DOCKER_TEST_IMAGE=multibuild/xenial_{PLAT}
# 32-bit builds
- os: linux
dist: xenial
......@@ -82,6 +89,13 @@ matrix:
env:
- MB_PYTHON_VERSION=3.5
- VENV=venv
# this is expected to fail
# 3.5 / 10.9 build doesn't exist
- os: osx
env:
- MB_PYTHON_VERSION=3.5
- MB_PYTHON_OSX_VER=10.9
- OSX_ENV_EXPECT_FAIL=true
- os: osx
env:
- MB_PYTHON_VERSION=3.6
......@@ -96,6 +110,7 @@ matrix:
- MB_PYTHON_VERSION=3.7
- VENV=venv
- os: osx
osx_image: xcode10.2
env:
- MB_PYTHON_VERSION=3.7
- VENV=venv
......@@ -104,6 +119,10 @@ matrix:
env:
- MB_PYTHON_VERSION=3.8
- VENV=venv
- os: osx
env:
- MB_PYTHON_VERSION=3.9
- VENV=venv
- os: osx
env:
- MB_PYTHON_VERSION=pypy-7.3
......@@ -130,6 +149,10 @@ matrix:
osx_image: xcode10
env:
- MB_PYTHON_VERSION=3.8
- os: osx
osx_image: xcode10
env:
- MB_PYTHON_VERSION=3.9
- os: osx
osx_image: xcode10.1
env:
......
......@@ -7,7 +7,7 @@ Copyright and License
The multibuild package, including all examples, code snippets and attached
documentation is covered by the 2-clause BSD license.
Copyright (c) 2013-2020, Matt Terry and Matthew Brett; all rights
Copyright (c) 2013-2021, Matt Terry and Matthew Brett; all rights
reserved.
Redistribution and use in source and binary forms, with or without
......
......@@ -41,10 +41,11 @@ The Travis CI scripts are designed to build *and test*:
* 64-bit macOS wheels built for macOS 10.9+
* 64/32-bit macOS wheels built for macOS 10.6+
* 64-bit ``manylinuxX_x86_64`` wheels, both narrow and wide Unicode builds, where `X` is any valid Manylinux version, such as `1`, or `2010`
* 64-bit ``manylinuxX_x86_64`` wheels, both narrow and wide Unicode builds,
where `X` is any valid Manylinux version: `1`, `2010`, `2014` or `_2_24`.
* 32-bit ``manylinuxX_i686`` wheels, both narrow and wide Unicode builds
You can currently build and test against Pythons 2.7, 3.5, 3.6, 3.7 and 3.8
You can currently build and test against Pythons 2.7, 3.5, 3.6, 3.7, 3.8 and 3.9
The small innovation here is that you can test against Linux 32-bit builds, both
wide and narrow Unicode Python 2 builds, which was not easy on the default
......@@ -55,7 +56,7 @@ The AppVeyor setup is designed to build *and test*:
* 64-bit Windows ``win_amd64`` wheels
* 32-bit Windows ``win32`` wheels
You can currently build and test against Pythons 2.7, 3.5, 3.6, 3.7, 3.8
You can currently build and test against Pythons 2.7, 3.5, 3.6, 3.7, 3.8, 3.9
*****************
How does it work?
......@@ -91,19 +92,35 @@ shell scripts listed above are available for your build and test.
Build options are controlled mainly by the following environment
variables:
* ``MB_PYTHON_VER`` sets the Python version targetted: ``major.minor.patch`` for CPython, or ``pypy-major.minor`` for PyPy.
* ``MB_PYTHON_OSX_VER`` sets the minimum macOS SDK version for any C extensions. For CPython targets it may be set to 10.6 or 10.9, provided a corresponding Python build is available at `python.org <https://www.python.org/downloads/mac-osx/>`_. It defaults to the highest version available. It's ignored for PyPy targets.
* ``PLAT`` sets the architectures built for any C extensions: ``x86_64`` or ``intel`` for 64-bit or 64/32-bit respectively. It defaults to the same arches as the target Python version: 64-bit for CPython macOS 10.9 or PyPy, and 64/32-bit for CPython 10.6.
In most cases it's best to rely on the defaults for ``MB_PYTHON_OSX_VER`` and ``PLAT``, rather than setting them explicitly. Examples of exceptions to this guideline include:
* setting ``MB_PYTHON_OSX_VER=10.6`` to build a 10.6 64/32-bit CPython wheel for Python 2.7 (default for 2.7 is 10.9 64-bit)
* setting ``MB_PYTHON_OSX_VER=10.6 and PLAT=x86_64`` to build a 10.6 64-bit only wheel (10.6 would normally be 64/32-bit). Such a wheel would still have a platform tag of ``macosx_10_6_intel`` , advertising support for both 64 and 32-bit, but wouldnt work in 32-bit mode. This may be OK given how unlikely it is that there is still anyone actually running Python on macOS in 32-bit mode.
* ``MB_PYTHON_VER`` sets the Python version targetted: ``major.minor.patch``
for CPython, or ``pypy-major.minor`` for PyPy.
* ``MB_PYTHON_OSX_VER`` sets the minimum macOS SDK version for any C
extensions. For CPython targets it may be set to 10.6 or 10.9, provided a
corresponding Python build is available at `python.org
<https://www.python.org/downloads/mac-osx/>`_. It defaults to the highest
version available. It's ignored for PyPy targets.
* ``PLAT`` sets the architectures built for any C extensions: ``x86_64`` or
``intel`` for 64-bit or 64/32-bit respectively. It defaults to the same
arches as the target Python version: 64-bit for CPython macOS 10.9 or PyPy,
and 64/32-bit for CPython 10.6.
In most cases it's best to rely on the defaults for ``MB_PYTHON_OSX_VER`` and
``PLAT``, rather than setting them explicitly. Examples of exceptions to this
guideline include:
* setting ``MB_PYTHON_OSX_VER=10.6`` to build a 10.6 64/32-bit CPython wheel
for Python 2.7 (default for 2.7 is 10.9 64-bit)
* setting ``MB_PYTHON_OSX_VER=10.6 and PLAT=x86_64`` to build a 10.6 64-bit
only wheel (10.6 would normally be 64/32-bit). Such a wheel would still have
a platform tag of ``macosx_10_6_intel`` , advertising support for both 64 and
32-bit, but wouldn't work in 32-bit mode. This may be OK given how unlikely it
is that there is still anyone actually running Python on macOS in 32-bit
mode.
The ``build_wheel`` function builds the wheel, and ``install_run``
function installs and tests it. Look in ``multibuild/common_utils.sh`` for
default definitions of these functions. See below for more details, many of which are common
to macOS and Linux.
default definitions of these functions. See below for more details, many of
which are common to macOS and Linux.
Manylinux
=========
......@@ -122,13 +139,21 @@ variable. The default version is ``1``. Versions that are currently valid are:
* ``2010`` corresponding to manylinux2010 (see `PEP 571 <https://www.python.org/dev/peps/pep-0571>`_).
* ``2014`` corresponding to manylinux2014 and adds more architectures to ``PLAT``
(see `PEP 599 <https://www.python.org/dev/peps/pep-0599>`_).
* ``_2_24`` corresponding to manylinux_2_24 (see `PEP 600 <https://www.python.org/dev/peps/pep-0600>`_).
The environment variable specified which Manylinux docker container you are building in.
The ``PLAT`` environment variable can be one of ``x86_64``, ``i686`` ``s390x``,
``ppc64le``, or ``aarch64``, specifying 64-bit x86, 32-bit x86, 64-bit s390x,
PowerPC, and ARM builds, respectively. The default is ``x86_64``. Only ``x86_64``
and ``i686`` are valid on manylinux1 and manylinux2010.
The ``PLAT`` environment variable can be one of
* ``x86_64``, for 64-bit x86
* ``i686``, for 32-bit x86
* ``s390x``, for 64-bit s390x
* ``ppc64le``, for PowerPC
* ``aarch64``, for ARM
* ``arm64``, for Apple silicon
* ``universal2``, for both Apple silicon and 64-bit x86
The default is ``x86_64``. Only ``x86_64`` and ``i686`` are valid on manylinux1 and manylinux2010.
``multibuild/travis_linux_steps.sh`` defines the ``build_wheel`` function,
which starts up the Manylinux1 Docker container to run a wrapper script
......@@ -272,6 +297,9 @@ To use these scripts
# and test containers, via docker.
dist: xenial
# osx image that enables building Apple silicon libraries
osx_image: xcode12.2
matrix:
include:
- os: linux
......@@ -326,6 +354,13 @@ To use these scripts
- os: osx
env:
- MB_PYTHON_VERSION=3.8
- os: osx
env:
- MB_PYTHON_VERSION=3.9
- PLAT="universal2"
- os: osx
env:
- MB_PYTHON_VERSION=3.9
- os: osx
language: generic
env:
......@@ -369,7 +404,7 @@ To use these scripts
You also need this file to specify how to run your tests::
# Define custom utilities
# Test for macOS with [ -n "$IS_OSX" ]
# Test for macOS with [ -n "$IS_MACOS" ]
function pre_build {
# Any stuff that you need to do before you start building the wheels
......@@ -416,6 +451,37 @@ To use these scripts
* Make sure your project is set up to build on AppVeyor, and you should now
be ready (for what could be another round of slow debugging).
* For Apple silicon support you can either create an ``arm64`` wheel or
a ``universal2`` wheel by supplying ``PLAT`` env variable.
``universal2`` builds work on both ``arm64`` and ``x86_64`` platforms
and also make it possible for the wheel code to work when switching the
architecture on Apple silicon machines where ``x86_64`` can be run
using Rosetta2 emulation.
There are two ways to build ``universal2`` builds.
1. Build with ``-arch x86_64 -arch arm64``.
These flags instruct the C/C++ compiler to compile twice and create a
fat object/executable/library. This is the easiest, but has several
drawbacks. If you are using C/C++ libraries that are built using
library_builders, it's highly likely that they don't build correctly
because most build systems and packages don't support building fat binaries.
We could possibly build them separately and fuse them, but the headers might
not be identical which is required when building the wheel as a ``universal2``
wheel. If you are using Fortran, ``gfortran`` doesn't support fat binaries.
2. Build ``arm64`` and ``x86_64`` wheels separately and fuse them.
For this to work, we need to build the C/C++ libraries twice. Therefore,
the library building is once called with ``BUILD_PREFIX=${BUILD_PREFIX:-/usr/local}``
for ``x86_64`` and then called again with ``BUILD_PREFIX=/opt/arm64-builds``.
Once the two wheels are created, these two are merged. Both the
``arm64`` and ``universal2`` wheels are outputs for this build.
In multibuild we are going with option 2. You can override this behaviour by
overriding the function ``wrap_wheel_builder``.
To build Apple silicon builds, you should use a CI service with Xcode 12 with
universal build support and make sure that xcode is the default.
If your project depends on NumPy, you will want to build against the earliest
NumPy that your project supports - see `forward, backward NumPy compatibility
<https://stackoverflow.com/questions/17709641/valueerror-numpy-dtype-has-the-wrong-size-try-recompiling/18369312#18369312>`_.
......
......@@ -14,6 +14,8 @@ set -e
MULTIBUILD_DIR=$(dirname "${BASH_SOURCE[0]}")
DOWNLOADS_SDIR=downloads
PYPY_URL=https://downloads.python.org/pypy
# For back-compatibility. We use the "ensurepip" module now
# instead of get-pip.py
GET_PIP_URL=https://bootstrap.pypa.io/get-pip.py
# Unicode width, default 32. Used here and in travis_linux_steps.sh
......@@ -22,7 +24,14 @@ GET_PIP_URL=https://bootstrap.pypa.io/get-pip.py
# with, so it is passed in when calling "docker run" for tests.
UNICODE_WIDTH=${UNICODE_WIDTH:-32}
if [ $(uname) == "Darwin" ]; then IS_OSX=1; fi
if [ $(uname) == "Darwin" ]; then
IS_MACOS=1; IS_OSX=1;
else
# In the manylinux_2_24 image, based on Debian9, "python" is not installed
# so link in something for the various system calls before PYTHON_EXE is set
which python || export PATH=/opt/python/cp39-cp39/bin:$PATH
fi
# Work round bug in travis xcode image described at
# https://github.com/direnv/direnv/issues/210
......@@ -141,6 +150,39 @@ function suppress {
return "$ret"
}
function expect_return {
# Run a command, succeeding (returning 0) only if the commend returns a specified code
# Parameters
# retcode expected return code (which may be zero)
# command the command called
#
# any further arguments are passed to the called command
#
# Returns 1 if called with less than 2 arguments
(( $# < 2 )) && echo "Must have at least 2 arguments" && return 1
local retcode=$1
local retval
( "${@:2}" ) || retval=$?
[[ $retcode == ${retval:-0} ]] && return 0
return ${retval:-1}
}
function cmd_notexit {
# wraps a command, capturing its return code and preventing it
# from exiting the shell. Handles -e / +e modes.
# Parameters
# cmd - command
# any further parameters are passed to the wrapped command
# If called without an argument, it will exit the shell with an error
local cmd=$1
if [ -z "$cmd" ];then echo "no command"; exit 1; fi
if [[ $- = *e* ]]; then errexit_set=true; fi
set +e
("${@:1}") ; retval=$?
[[ -n $errexit_set ]] && set -e
return $retval
}
function rm_mkdir {
# Remove directory if present, then make directory
local path=$1
......@@ -164,7 +206,15 @@ function untar {
}
function install_rsync {
if [ -z "$IS_OSX" ]; then
# install rsync via package manager
if [ -n "$IS_MACOS" ]; then
# macOS. The colon in the next line is the null command
:
elif [[ $MB_ML_VER == "_2_24" ]]; then
# debian:9 based distro
[[ $(type -P rsync) ]] || apt-get install -y rsync
else
# centos based distro
[[ $(type -P rsync) ]] || yum_install rsync
fi
}
......@@ -270,22 +320,27 @@ function bdist_wheel_cmd {
cp dist/*.whl $abs_wheelhouse
}
function wrap_wheel_builder {
# Wrapper for build commands, overwritten by macOS for universal2 or arm64 wheel building
$@
}
function build_pip_wheel {
# Standard wheel building command with pip wheel
build_wheel_cmd "pip_wheel_cmd" $@
wrap_wheel_builder build_wheel_cmd "pip_wheel_cmd" $@
}
function build_bdist_wheel {
# Wheel building with bdist_wheel. See bdist_wheel_cmd
build_wheel_cmd "bdist_wheel_cmd" $@
wrap_wheel_builder build_wheel_cmd "bdist_wheel_cmd" $@
}
function build_wheel {
# Set default building method to pip
build_pip_wheel $@
wrap_wheel_builder build_pip_wheel $@
}
function build_index_wheel {
function build_index_wheel_cmd {
# Builds wheel from some index, usually pypi
#
# Parameters:
......@@ -316,10 +371,20 @@ function build_index_wheel {
repair_wheelhouse $wheelhouse
}
function build_index_wheel {
wrap_wheel_builder build_index_wheel_cmd $@
}
function pip_opts {
[ -n "$MANYLINUX_URL" ] && echo "--find-links $MANYLINUX_URL"
}
function get_os {
# Report OS as given by uname
# Use any Python that comes to hand.
python -c 'import platform; print(platform.uname()[0])'
}
function get_platform {
# Report platform as given by uname
# Use any Python that comes to hand.
......@@ -392,7 +457,7 @@ function fill_submodule {
(cd "$repo_dir" && git remote set-url origin $origin_url)
}
# As of 2020-04-14, the latest verions of PyPy.
# The latest versions of PyPy.
LATEST_PP_5p0=5.0.1
LATEST_PP_5p1=5.1.1
LATEST_PP_5p3=5.3.1
......@@ -409,7 +474,7 @@ LATEST_PP_6=$LATEST_PP_6p0
LATEST_PP_7p0=7.0.0
LATEST_PP_7p1=7.1.1
LATEST_PP_7p2=7.2.0
LATEST_PP_7p3=7.3.1
LATEST_PP_7p3=7.3.3
LATEST_PP_7=$LATEST_PP_7p3
function unroll_version {
......@@ -441,7 +506,7 @@ function install_pypy {
local version=$1
case "$PLAT" in
"x86_64") if [ -n "$IS_OSX" ]; then
"x86_64") if [ -n "$IS_MACOS" ]; then
suffix="osx64";
else
suffix="linux64";
......@@ -533,6 +598,9 @@ retry () {
function install_pip {
# Generic install pip
echo "Deprecated - please see pip installs within the individual"
echo "install functions for each Python type."
echo "Multibuild itself no longer uses this function."
# Gets needed version from version implied by $PYTHON_EXE
# Installs pip into python given by $PYTHON_EXE
# Assumes pip will be installed into same directory as $PYTHON_EXE
......
# Find, load common utilities
# Defines IS_OSX, fetch_unpack
# Defines IS_MACOS, fetch_unpack
MULTIBUILD_DIR=$(dirname "${BASH_SOURCE[0]}")
source $MULTIBUILD_DIR/common_utils.sh
......@@ -12,8 +12,8 @@ CONFIGURE_BUILD_SOURCED=1
BUILD_PREFIX="${BUILD_PREFIX:-/usr/local}"
MB_ML_VER=${MB_ML_VER:-1}
# IS_OSX is defined in common_utils.sh
if [ -n "$IS_OSX" ]; then
# IS_MACOS is defined in common_utils.sh
if [ -n "$IS_MACOS" ]; then
# Default compilation flags for OSX
source $MULTIBUILD_DIR/osx_utils.sh
PLAT=${PLAT:-$(macpython_arch_for_version $MB_PYTHON_VERSION)}
......@@ -21,8 +21,13 @@ if [ -n "$IS_OSX" ]; then
ARCH_FLAGS=${ARCH_FLAGS:-"-arch i386 -arch x86_64"}
elif [[ $PLAT == x86_64 ]]; then
ARCH_FLAGS=${ARCH_FLAGS:-"-arch x86_64"}
elif [[ $PLAT == arm64 ]]; then
ARCH_FLAGS=${ARCH_FLAGS:-"-arch arm64"}
elif [[ $PLAT == universal2 ]]; then
# Do nothing as we are going with fusing wheels
ARCH_FLAGS=${ARCH_FLAGS:-}
else
echo "invalid platform = '$PLAT', supported values are 'intel' or 'x86_64'"
echo "Invalid platform = '$PLAT'. Supported values are 'intel', 'x86_64', 'arm64' or 'universal2'"
exit 1
fi
# Only set CFLAGS, FFLAGS if they are not already defined. Build functions
......@@ -42,20 +47,34 @@ else
export CFLAGS="${CFLAGS:-$STRIP_FLAGS}"
export CXXFLAGS="${CXXFLAGS:-$STRIP_FLAGS}"
export FFLAGS="${FFLAGS:-$STRIP_FLAGS}"
if [[ $MB_ML_VER == "1" ]]; then
if [[ $MB_ML_VER == "_2_24" ]]; then
# This is the first opportunity to distinguish between manylinuxes
apt update
if [ "${MB_PYTHON_VERSION:0:4}" == "pypy" ]; then
yum install -y libtool wget
else
yum install -y libtool
# debian:9 based distro
apt install -y wget
fi
elif [[ $MB_ML_VER == "1" ]]; then
# Need libtool, and for pypy need wget
# centos based distro
yum install -y libtool wget
elif [ "${MB_PYTHON_VERSION:0:4}" == "pypy" ]; then
# centos based distro
yum install -y wget
fi
fi
# Promote BUILD_PREFIX on search path to any newly built libs
export CPPFLAGS="-I$BUILD_PREFIX/include $CPPFLAGS"
export LIBRARY_PATH="$BUILD_PREFIX/lib:$LIBRARY_PATH"
export PKG_CONFIG_PATH="$BUILD_PREFIX/lib/pkgconfig/:$PKG_CONFIG_PATH"
# Add binary path for configure utils etc
export PATH="$BUILD_PREFIX/bin:$PATH"
export CPPFLAGS_BACKUP="$CPPFLAGS"
export LIBRARY_PATH_BACKUP="$LIBRARY_PATH"
export PKG_CONFIG_PATH_BACKUP="$PKG_CONFIG_PATH"
function update_env_for_build_prefix {
# Promote BUILD_PREFIX on search path to any newly built libs
export CPPFLAGS="-I$BUILD_PREFIX/include $CPPFLAGS_BACKUP"
export LIBRARY_PATH="$BUILD_PREFIX/lib:$LIBRARY_PATH_BACKUP"
export PKG_CONFIG_PATH="$BUILD_PREFIX/lib/pkgconfig/:$PKG_CONFIG_PATH_BACKUP"
# Add binary path for configure utils etc
export PATH="$BUILD_PREFIX/bin:$PATH"
}
update_env_for_build_prefix
......@@ -41,7 +41,9 @@ else
PYTHON_EXE=$(cpython_path $PYTHON_VERSION $UNICODE_WIDTH)/bin/python
ls $(dirname $PYTHON_EXE)
export PATH="$(dirname $PYTHON_EXE):$PATH"
install_pip
# We can assume ensurepip is available and up to date.
$PYTHON_EXE -m ensurepip
PIP_CMD="$PYTHON_EXE -m pip"
fi
# Configuration for this package, possibly overriding `build_wheel` defined in
......
......@@ -14,7 +14,7 @@ OPENBLAS_VERSION="${OPENBLAS_VERSION:-0.3.10}"
# We use system zlib by default - see build_new_zlib
ZLIB_VERSION="${ZLIB_VERSION:-1.2.10}"
LIBPNG_VERSION="${LIBPNG_VERSION:-1.6.21}"
BZIP2_VERSION="${BZIP2_VERSION:-1.0.6}"
BZIP2_VERSION="${BZIP2_VERSION:-1.0.7}"
FREETYPE_VERSION="${FREETYPE_VERSION:-2.6.3}"
TIFF_VERSION="${TIFF_VERSION:-4.1.0}"
JPEG_VERSION="${JPEG_VERSION:-9b}"
......@@ -117,7 +117,7 @@ function openblas_get {
function build_openblas {
if [ -e openblas-stamp ]; then return; fi
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
brew install openblas
brew link --force openblas
else
......@@ -131,9 +131,15 @@ function build_openblas {
function build_zlib {
# Gives an old but safe version
if [ -n "$IS_OSX" ]; then return; fi # OSX has zlib already
if [ -n "$IS_MACOS" ]; then return; fi # OSX has zlib already
if [ -e zlib-stamp ]; then return; fi
yum_install zlib-devel
if [[ $MB_ML_VER == "_2_24" ]]; then
# debian:9 based distro
apt-get install -y zlib1g-dev
else
#centos based distro
yum_install zlib-devel
fi
touch zlib-stamp
}
......@@ -159,7 +165,7 @@ function build_libpng {
}
function build_bzip2 {
if [ -n "$IS_OSX" ]; then return; fi # OSX has bzip2 libs already
if [ -n "$IS_MACOS" ]; then return; fi # OSX has bzip2 libs already
if [ -e bzip2-stamp ]; then return; fi
fetch_unpack https://sourceware.org/pub/bzip2/bzip2-${BZIP2_VERSION}.tar.gz
(cd bzip2-${BZIP2_VERSION} \
......@@ -178,12 +184,16 @@ function build_tiff {
function get_modern_cmake {
# Install cmake >= 2.8
local cmake=cmake
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
brew install cmake > /dev/null
elif [[ $MB_ML_VER == "_2_24" ]]; then
# debian:9 based distro
apt-get install -y cmake
else
if [ "`yum search cmake | grep ^cmake28\.`" ]; then
cmake=cmake28
fi
# centos based distro
yum_install $cmake > /dev/null
fi
echo $cmake
......@@ -267,6 +277,7 @@ function build_hdf5 {
local short=$(echo $HDF5_VERSION | awk -F "." '{printf "%d.%d", $1, $2}')
fetch_unpack $hdf5_url/hdf5-$short/hdf5-$HDF5_VERSION/src/hdf5-$HDF5_VERSION.tar.gz
(cd hdf5-$HDF5_VERSION \
&& export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$BUILD_PREFIX/lib \
&& ./configure --with-szlib=$BUILD_PREFIX --prefix=$BUILD_PREFIX \
--enable-threadsafe --enable-unsupported --with-pthread=yes \
&& make -j4 \
......@@ -294,7 +305,7 @@ function build_blosc {
(cd c-blosc-${BLOSC_VERSION} \
&& $cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX . \
&& make install)
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
# Fix blosc library id bug
for lib in $(ls ${BUILD_PREFIX}/lib/libblosc*.dylib); do
install_name_tool -id $lib $lib
......@@ -324,7 +335,7 @@ function build_lzf {
function build_curl {
if [ -e curl-stamp ]; then return; fi
local flags="--prefix=$BUILD_PREFIX"
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
flags="$flags --with-darwinssl"
else # manylinux
flags="$flags --with-ssl"
......@@ -332,7 +343,7 @@ function build_curl {
fi
fetch_unpack https://curl.haxx.se/download/curl-${CURL_VERSION}.tar.gz
(cd curl-${CURL_VERSION} \
&& if [ -z "$IS_OSX" ]; then \
&& if [ -z "$IS_MACOS" ]; then \
LIBS=-ldl ./configure $flags; else \
./configure $flags; fi\
&& make -j4 \
......@@ -346,7 +357,7 @@ function check_sha256sum {
local sha256=$2
if [ -z "$sha256" ]; then echo "Need SHA256 hash"; exit 1; fi
echo "${sha256} ${fname}" > ${fname}.sha256
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
shasum -a 256 -c ${fname}.sha256
else
sha256sum -c ${fname}.sha256
......@@ -383,7 +394,7 @@ function build_pcre {
function build_swig {
if [ -e swig-stamp ]; then return; fi
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
brew install swig > /dev/null
else
build_pcre
......@@ -394,9 +405,13 @@ function build_swig {
function build_suitesparse {
if [ -e suitesparse-stamp ]; then return; fi
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
brew install suite-sparse > /dev/null
elif [[ $MB_ML_VER == "_2_24" ]]; then
# debian:9 based distro
apt-get install -y libsuitesparse-dev > /dev/null
else
# centos based distro
yum_install suitesparse-devel > /dev/null
fi
touch suitesparse-stamp
......@@ -408,7 +423,7 @@ function build_libtool {
function build_ragel {
local htprefix=https
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
# Invalid certificate, when using macOS curl.
# https://security.stackexchange.com/questions/232445/https-connection-to-specific-sites-fail-with-curl-on-macos
# Cert will likely be removed by Safari update in due course.
......@@ -481,7 +496,7 @@ function build_fftw {
function build_cfitsio {
if [ -e cfitsio-stamp ]; then return; fi
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
brew install cfitsio
else
# cannot use build_simple because cfitsio has no dash between name and version
......
#!/bin/bash
# Useful utilities common across manylinux1 builds
# Useful utilities common across manylinux builds
MULTIBUILD_DIR=$(dirname "${BASH_SOURCE[0]}")
source $MULTIBUILD_DIR/common_utils.sh
......@@ -44,7 +44,13 @@ function activate_ccache {
ln -s /parent-home/.ccache $HOME/.ccache
# Now install ccache
suppress yum_install ccache
if [[ $MB_ML_VER == "_2_24" ]]; then
# debian:9 based distro
suppress apt-get install -y ccache
else
# centos based distro
suppress yum_install ccache
fi
# Create fake compilers and prepend them to the PATH
# Note that yum is supposed to create these for us,
......@@ -60,6 +66,7 @@ function activate_ccache {
# Prove to the developer that ccache is activated
echo "Using C compiler: $(which gcc)"
}
function yum_install {
# CentOS 5 yum doesn't fail in some cases, e.g. if package is not found
# https://serverfault.com/questions/694942/yum-should-error-when-a-package-is-not-available
......
......@@ -8,17 +8,17 @@ source $MULTIBUILD_DIR/common_utils.sh
MACPYTHON_URL=https://www.python.org/ftp/python
MACPYTHON_PY_PREFIX=/Library/Frameworks/Python.framework/Versions
GET_PIP_URL=https://bootstrap.pypa.io/get-pip.py
WORKING_SDIR=working
# As of 18 August 2020 - latest Python of each version with binary download
# As of 5 April 2021 - latest Python of each version with binary download
# available.
# See: https://www.python.org/downloads/mac-osx/
LATEST_2p7=2.7.18
LATEST_3p5=3.5.4
LATEST_3p6=3.6.8
LATEST_3p7=3.7.9
LATEST_3p8=3.8.5
LATEST_3p8=3.8.9
LATEST_3p9=3.9.4
function check_python {
......@@ -75,7 +75,9 @@ function fill_pyver {
echo $ver
elif [ $ver == 2 ] || [ $ver == "2.7" ]; then
echo $LATEST_2p7
elif [ $ver == 3 ] || [ $ver == "3.8" ]; then
elif [ $ver == 3 ] || [ $ver == "3.9" ]; then
echo $LATEST_3p9
elif [ $ver == "3.8" ]; then
echo $LATEST_3p8
elif [ $ver == "3.7" ]; then
echo $LATEST_3p7
......@@ -100,7 +102,9 @@ function macpython_sdk_list_for_version {
local _major=${_ver%%.*}
local _return
if [ "$_major" -eq "2" ]; then
if [ "${PLAT}" = "arm64" ]; then
_return="11.0"
elif [ "$_major" -eq "2" ]; then
[ $(lex_ver $_ver) -lt $(lex_ver 2.7.18) ] && _return="10.6"
[ $(lex_ver $_ver) -ge $(lex_ver 2.7.15) ] && _return="$_return 10.9"
elif [ "$_major" -eq "3" ]; then
......@@ -152,7 +156,15 @@ function pyinst_fname_for_version {
local py_version=$1
local py_osx_ver=${2:-$(macpython_sdk_for_version $py_version)}
local inst_ext=$(pyinst_ext_for_version $py_version)
echo "python-${py_version}-macosx${py_osx_ver}.${inst_ext}"
if [ "${PLAT:-}" == "arm64" ] || [ "${PLAT:-}" == "universal2" ]; then
if [ "$py_version" == "3.9.1" ]; then
echo "python-${py_version}-macos11.0.${inst_ext}"
else
echo "python-${py_version}-macos11.${inst_ext}"
fi
else
echo "python-${py_version}-macosx${py_osx_ver}.${inst_ext}"
fi
}
function get_macpython_arch {
......@@ -165,7 +177,7 @@ function get_macpython_arch {
# Note: MUST only be called after the version of Python used to build the
# target wheel has been installed and is on the path
local distutils_plat=${1:-$(get_distutils_platform)}
if [[ $distutils_plat =~ macosx-(10\.[0-9]+)-(.*) ]]; then
if [[ $distutils_plat =~ macosx-(1[0-9]\.[0-9]+)-(.*) ]]; then
echo ${BASH_REMATCH[2]}
else
echo "Error parsing macOS distutils platform '$distutils_plat'"
......@@ -183,7 +195,7 @@ function get_macpython_osx_ver {
# Note: MUST only be called after the version of Python used to build the
# target wheel has been installed and is on the path
local distutils_plat=${1:-$(get_distutils_platform)}
if [[ $distutils_plat =~ macosx-(10\.[0-9]+)-(.*) ]]; then
if [[ $distutils_plat =~ macosx-(1[0-9]\.[0-9]+)-(.*) ]]; then
echo ${BASH_REMATCH[1]}
else
echo "Error parsing macOS distutils platform '$distutils_plat'"
......@@ -287,8 +299,15 @@ function install_mac_cpython {
local py_stripped=$(strip_ver_suffix $py_version)
local py_inst=$(pyinst_fname_for_version $py_version $py_osx_ver)
local inst_path=$DOWNLOADS_SDIR/$py_inst
local retval=""
mkdir -p $DOWNLOADS_SDIR
curl $MACPYTHON_URL/$py_stripped/${py_inst} > $inst_path
# exit early on curl errors, but don't let it exit the shell
cmd_notexit curl -f $MACPYTHON_URL/$py_stripped/${py_inst} > $inst_path || retval=$?
if [ ${retval:-0} -ne 0 ]; then
echo "Python download failed! Check ${py_inst} exists on the server."
exit $retval
fi
if [ "${py_inst: -3}" == "dmg" ]; then
hdiutil attach $inst_path -mountpoint /Volumes/Python
inst_path=/Volumes/Python/Python.mpkg
......@@ -375,7 +394,17 @@ function get_macpython_environment {
remove_travis_ve_pip
install_macpython $version $py_osx_ver
install_pip
PIP_CMD="$PYTHON_EXE -m pip"
# Python 3.5 no longer compatible with latest pip
if [ "$(get_py_mm)" == "3.5" ]; then
# https://stackoverflow.com/a/29751768/1939576
curl -LO https://bootstrap.pypa.io/pip/3.5/get-pip.py
$PYTHON_EXE get-pip.py
rm get-pip.py
else
$PYTHON_EXE -m ensurepip
$PIP_CMD install --upgrade pip
fi
if [ -n "$venv_dir" ]; then
install_virtualenv
......@@ -414,3 +443,91 @@ function activate_ccache {
# Prove to the developer that ccache is activated
echo "Using C compiler: $(which clang)"
}
function macos_intel_native_build_setup {
# Setup native build for single arch x86_64 wheels
export PLAT="x86_64"
export _PYTHON_HOST_PLATFORM="macosx-${MB_PYTHON_OSX_VER}-x86_64"
export CFLAGS+=" -arch x86_64"
export CXXFLAGS+=" -arch x86_64"
export ARCHFLAGS+=" -arch x86_64"
export CPPFLAGS+=" -arch x86_64"
export LDFLAGS+=" -arch x86_64"
}
function macos_intel_cross_build_setup {
echo "universal2 builds on arm64 are not supported yet."
exit 1
}
function macos_arm64_cross_build_setup {
# Setup cross build for single arch arm_64 wheels
export PLAT="arm64"
export BUILD_PREFIX=/opt/arm64-builds
sudo mkdir -p $BUILD_PREFIX/lib $BUILD_PREFIX/include
sudo chown -R $USER $BUILD_PREFIX
update_env_for_build_prefix
export _PYTHON_HOST_PLATFORM="macosx-11.0-arm64"
export CFLAGS+=" -arch arm64"
export CXXFLAGS+=" -arch arm64"
export CPPFLAGS+=" -arch arm64"
export ARCHFLAGS+=" -arch arm64"
export FCFLAGS+=" -arch arm64"
export FC=$FC_ARM64
export MACOSX_DEPLOYMENT_TARGET="11.0"
export CROSS_COMPILING=1
export LDFLAGS+=" -arch arm64 -L$BUILD_PREFIX/lib -Wl,-rpath,$BUILD_PREFIX/lib ${FC_ARM64_LDFLAGS:-}"
# This would automatically let autoconf know that we are cross compiling for arm64 darwin
export host_alias="aarch64-apple-darwin20.0.0"
}
function macos_arm64_native_build_setup {
# Setup native build for single arch arm_64 wheels
export PLAT="arm64"
# We don't want universal2 builds and only want an arm64 build
export _PYTHON_HOST_PLATFORM="macosx-11.0-arm64"
export ARCHFLAGS+="-arch arm64"
$@
}
function fuse_macos_intel_arm64 {
local wheelhouse=$(abspath ${WHEEL_SDIR:-wheelhouse})
local py_osx_ver=$(echo ${MB_PYTHON_OSX_VER} | sed "s/\./_/g")
mkdir -p tmp_fused_wheelhouse
for whl in $wheelhouse/*.whl; do
if [[ "$whl" == *macosx_${py_osx_ver}_x86_64.whl ]]; then
whl_base=$(echo $whl | rev | cut -c 23- | rev)
if [[ -f "${whl_base}macosx_11_0_arm64.whl" ]]; then
delocate-fuse $whl "${whl_base}macosx_11_0_arm64.whl" -w tmp_fused_wheelhouse
mv tmp_fused_wheelhouse/$(basename $whl) $wheelhouse/$(basename ${whl_base})macosx_${py_osx_ver}_universal2.whl
# Since we want one wheel that's installable for testing we are deleting the *_x86_64 wheel.
# We are not deleting arm64 wheel because the size is lower and homebrew/conda-forge python
# will use them by default
rm $whl
fi
fi
done
}
function wrap_wheel_builder {
if [[ "${PLAT:-}" == "universal2" ]]; then
if [[ "$(uname -m)" == "arm64" ]]; then
(macos_intel_cross_build_setup && $@)
rm -rf *-stamp
(macos_arm64_native_build_setup && $@)
else
(macos_intel_native_build_setup && $@)
rm -rf *-stamp
(macos_arm64_cross_build_setup && $@)
fi
fuse_macos_intel_arm64
elif [[ "${PLAT:-}" == "arm64" ]]; then
if [[ "$(uname -m)" == "arm64" ]]; then
(macos_arm64_native_build_setup && $@)
else
(macos_arm64_cross_build_setup && $@)
fi
else
$@
fi
}
......@@ -88,6 +88,17 @@ actual="$(set -e; suppress bad_mid_cmd)"
# Reset options
set_opts $ORIG_OPTS
! expect_return 1 || ingest "Too few arguments"
! expect_return 1 good_cmd || ingest "unexpected success"
! expect_return 0 bad_cmd || ingest "unexpected failure"
expect_return 1 bad_cmd || ingest "fail with expected error 1"
! expect_return 2 bad_cmd || ingest "fail with unexpected error"
expect_return 0 good_cmd || ingest "succeed as expected"
cmd_notexit good_cmd || ingest
! cmd_notexit bad_cmd || ingest
! cmd_notexit exit 1 || ingest
# On Linux docker containers in travis, can be x86_64, i686, s390x, ppc64le, or
# aarch64
[ "$(get_platform)" == x86_64 ] || \
......
......@@ -2,7 +2,9 @@
[ "$(fill_pyver 2)" == $LATEST_2p7 ] || ingest
[ "$(fill_pyver 2.7)" == $LATEST_2p7 ] || ingest
[ "$(fill_pyver 2.7.8)" == "2.7.8" ] || ingest
[ "$(fill_pyver 3)" == $LATEST_3p8 ] || ingest
[ "$(fill_pyver 3)" == $LATEST_3p9 ] || ingest
[ "$(fill_pyver 3.9)" == $LATEST_3p9 ] || ingest
[ "$(fill_pyver 3.9.0)" == "3.9.0" ] || ingest
[ "$(fill_pyver 3.8)" == $LATEST_3p8 ] || ingest
[ "$(fill_pyver 3.8.0)" == "3.8.0" ] || ingest
[ "$(fill_pyver 3.7)" == $LATEST_3p7 ] || ingest
......
......@@ -3,7 +3,7 @@
# The environment
uname -a
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
# Building on macOS
export BUILD_PREFIX="${PWD}/builds"
rm_mkdir $BUILD_PREFIX
......@@ -31,26 +31,28 @@ suppress build_swig
# E.g. arb (below) requires a couple of other libraries.
# Run here just for the output, even though they fail.
(set +e ;
build_github fredrik-johansson/arb 2.18.1 ;
build_github fredrik-johansson/arb 2.19.0 ;
build_github glennrp/libpng v1.6.37 ;
build_github wbhart/mpir mpir-3.0.0
)
suppress build_flex
suppress build_openblas
if [[ $MB_ML_VER != "_2_24" ]]; then
suppress build_openblas
fi
suppress ensure_xz
suppress build_tiff
suppress build_libwebp
suppress build_lcms2
suppress build_freetype
suppress build_libyaml
if [ -z "$IS_OSX" ]; then
if [ -z "$IS_MACOS" ]; then
# Gives compiler conformance error on macOS Sierra:
# https://gist.github.com/5e20e137ea51fa8ca9fc443191f9d463
# https://gist.github.com/ad86c474f3c0b7ec74290bb13f9414af
suppress build_lzo
fi
suppress build_ragel
if [ -z "$IS_OSX" ]; then
if [ -z "$IS_MACOS" ]; then
# already installed in the macOS image, so `brew install cfitsio` fails
suppress build_cfitsio
fi
......
......@@ -3,8 +3,9 @@
source manylinux_utils.sh
source tests/utils.sh
suppress yum_install rsync && suppress yum erase -y rsync \
|| ingest "yum_install valid"
suppress bash -c '! yum_install nonexistent' || ingest "yum_install nonexistent"
barf
\ No newline at end of file
if [[ $MB_ML_VER != "_2_24" ]]; then
suppress yum_install rsync && suppress yum erase -y rsync \
|| ingest "yum_install valid"
suppress bash -c '! yum_install nonexistent' || ingest "yum_install nonexistent"
barf
fi
......@@ -16,12 +16,18 @@ source tests/test_fill_submodule.sh
# make sure it is set via one of the mechanisms above
unset PYTHON_EXE
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
source osx_utils.sh
MB_PYTHON_OSX_VER=${MB_PYTHON_OSX_VER:-$(macpython_sdk_for_version $MB_PYTHON_VERSION)}
PLAT=${PLAT:-$(macpython_arch_for_version $MB_PYTHON_VERSION)}
# exit early if this cmd is expected to fail (and does)
if [[ -n $OSX_ENV_EXPECT_FAIL ]]; then
expect_return 22 get_macpython_environment $MB_PYTHON_VERSION ${VENV:-""} $MB_PYTHON_OSX_VER
exit 0
fi
get_macpython_environment $MB_PYTHON_VERSION ${VENV:-""} $MB_PYTHON_OSX_VER
source tests/test_python_install.sh
source tests/test_fill_pyver.sh
source tests/test_fill_pypy_ver.sh
......@@ -32,7 +38,7 @@ else
fi
if [ -n "$TEST_BUILDS" ]; then
MB_PYTHON_VERSION=${MB_PYTHON_VERSION:-3.7}
if [ -n "$IS_OSX" ]; then
if [ -n "$IS_MACOS" ]; then
# This checked in test_library_builders.
# Will be set automatically by docker call in build_multilinux below.
PYTHON_VERSION=${MB_PYTHON_VERSION}
......
......@@ -57,6 +57,10 @@
[ "$(macpython_sdk_list_for_version 2.7.17)" == "10.6 10.9" ] || ingest
[ "$(macpython_sdk_list_for_version 2.7.18)" == "10.9" ] || ingest
(PLAT="arm64"; [ "$(macpython_sdk_for_version 3.9)" == "11.0" ] || ingest)
(PLAT="universal2"; [ "$(macpython_sdk_for_version 3.9)" == "10.9" ] || ingest)
(PLAT="x86_64"; [ "$(macpython_sdk_for_version 3.9)" == "10.9" ] || ingest)
[ "$(macpython_sdk_for_version 3.9)" == "10.9" ] || ingest
[ "$(macpython_sdk_for_version 3.8)" == "10.9" ] || ingest
[ "$(macpython_sdk_for_version 3.5)" == "10.6" ] || ingest
[ "$(macpython_sdk_for_version 2.7)" == "10.9" ] || ingest
......
......@@ -55,15 +55,19 @@ else # not virtualenv
if [[ $requested_impl == 'cp' ]]; then
macpie_bin="$MACPYTHON_PY_PREFIX/$python_mm/bin"
bin_name="python$python_mm"
else
else # pypy
macpie_bin="$PWD/pypy$python_mm-v$implementer_version-osx64/bin"
bin_name="pypy"
if [ "$(lex_ver $implementer_version)" -ge "$(lex_ver 7.3.2)" ]; then
bin_name="pypy3"
else
bin_name="pypy"
fi
fi
if [ "$PYTHON_EXE" != "$macpie_bin/$bin_name" ]; then
ingest "Wrong macpython python cmd '$PYTHON_EXE'"
fi
if [ "$PIP_CMD" != "sudo $macpie_bin/pip${python_mm}${expected_pip_args}" ]; then
ingest "Wrong macpython pip '$PIP_CMD'"
if [ "$PIP_CMD" != "$PYTHON_EXE -m pip" ]; then
ingest "Wrong macpython or pypy pip '$PIP_CMD'"
fi
fi
......
# Test supported wheels script
PYTHON_EXE=${PYTHON_EXE:-python}
if [ -z "$PIP_CMD" ]; then
pip_install="$PYTHON_EXE -m pip install --user"
pip_install="$PYTHON_EXE -m pip install"
else
pip_install="$PIP_CMD install"
fi
......
......@@ -2,6 +2,20 @@
# Wheel build, install, run test steps on OSX
set -e
if [ "$PLAT" == "arm64" ] || [ "$PLAT" == "universal2" ]; then
if [[ "$(xcrun --sdk macosx --show-sdk-version | cut -d '.' -f 1)" -lt 11 ]]; then
latestXcode=$(ls /Applications | grep Xcode[_0-9\.]*\.app | sort -V | tail -n 1)
if ([ "$GITHUB_WORKFLOW" != "" ] || [ "$PIPELINE_WORKSPACE" != "" ]) && [ $latestXcode ]; then
sudo xcode-select -switch /Applications/$latestXcode
fi
if [[ "$(xcrun --sdk macosx --show-sdk-version | cut -d '.' -f 1)" -lt 11 ]]; then
echo "Need SDK>=11 for arm64 builds. Please run xcode-select to select a newer SDK"
exit 1
fi
fi
export SDKROOT=${SDKROOT:-$(xcrun --sdk macosx --show-sdk-path)}
fi
# Get needed utilities
MULTIBUILD_DIR=$(dirname "${BASH_SOURCE[0]}")
MB_PYTHON_VERSION=${MB_PYTHON_VERSION:-$TRAVIS_PYTHON_VERSION}
......
......@@ -5,7 +5,7 @@ WHEEL_SDIR=${WHEEL_SDIR:-wheelhouse}
MULTIBUILD_DIR=$(dirname "${BASH_SOURCE[0]}")
if [ ! -d "$PWD/$WHEEL_SDIR" ]; then mkdir $PWD/$WHEEL_SDIR; fi
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
if [[ "$(uname)" == "Darwin" ]]; then
source $MULTIBUILD_DIR/travis_osx_steps.sh
else
source $MULTIBUILD_DIR/travis_linux_steps.sh
......
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