mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-26 16:09:54 +03:00
391 lines
15 KiB
Bash
Executable File
391 lines
15 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Safety check - Pillow builds require that CIBW_ARCHS is set, and that it only
|
|
# contains a single value (even though cibuildwheel allows multiple values in
|
|
# CIBW_ARCHS). This check doesn't work on Linux because of how the CIBW_ARCHS
|
|
# variable is exposed.
|
|
function check_cibw_archs {
|
|
if [[ -z "$CIBW_ARCHS" ]]; then
|
|
echo "ERROR: Pillow builds require CIBW_ARCHS be defined."
|
|
exit 1
|
|
fi
|
|
if [[ "$CIBW_ARCHS" == *" "* ]]; then
|
|
echo "ERROR: Pillow builds only support a single architecture in CIBW_ARCHS."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Setup that needs to be done before multibuild utils are invoked. Process
|
|
# potential cross-build platforms before native platforms to ensure that we pick
|
|
# up the cross environment.
|
|
PROJECTDIR=$(pwd)
|
|
if [[ "$CIBW_PLATFORM" == "ios" ]]; then
|
|
check_cibw_archs
|
|
# On iOS, CIBW_ARCHS is actually a multi-arch - arm64_iphoneos,
|
|
# arm64_iphonesimulator or x86_64_iphonesimulator. Split into the CPU
|
|
# platform, and the iOS SDK.
|
|
PLAT=$(echo $CIBW_ARCHS | sed "s/\(.*\)_\(.*\)/\1/")
|
|
IOS_SDK=$(echo $CIBW_ARCHS | sed "s/\(.*\)_\(.*\)/\2/")
|
|
|
|
# Build iOS builds in `build/iphoneos` or `build/iphonesimulator`
|
|
# (depending on the build target). Install them into `build/deps/iphoneos`
|
|
# or `build/deps/iphonesimulator`
|
|
WORKDIR=$(pwd)/build/$IOS_SDK
|
|
BUILD_PREFIX=$(pwd)/build/deps/$IOS_SDK
|
|
PATCH_DIR=$(pwd)/patches/iOS
|
|
|
|
# GNU tooling insists on using aarch64 rather than arm64
|
|
if [[ $PLAT == "arm64" ]]; then
|
|
GNU_ARCH=aarch64
|
|
else
|
|
GNU_ARCH=x86_64
|
|
fi
|
|
|
|
IOS_SDK_PATH=$(xcrun --sdk $IOS_SDK --show-sdk-path)
|
|
CMAKE_SYSTEM_NAME=iOS
|
|
IOS_HOST_TRIPLE=$PLAT-apple-ios$IPHONEOS_DEPLOYMENT_TARGET
|
|
if [[ "$IOS_SDK" == "iphonesimulator" ]]; then
|
|
IOS_HOST_TRIPLE=$IOS_HOST_TRIPLE-simulator
|
|
fi
|
|
|
|
# GNU Autotools doesn't recognize the existence of arm64-apple-ios-simulator
|
|
# as a valid host. However, the only difference between arm64-apple-ios and
|
|
# arm64-apple-ios-simulator is the choice of sysroot, and that is
|
|
# coordinated by CC, CFLAGS etc. From the perspective of configure, the two
|
|
# platforms are identical, so we can use arm64-apple-ios consistently.
|
|
# This (mostly) avoids us needing to patch config.sub in dependency sources.
|
|
HOST_CONFIGURE_FLAGS="--disable-shared --enable-static --host=$GNU_ARCH-apple-ios --build=$GNU_ARCH-apple-darwin"
|
|
|
|
# CMake has native support for iOS. However, most of that support is based
|
|
# on using the Xcode builder, which isn't very helpful for most of Pillow's
|
|
# dependencies. Therefore, we lean on the OSX configurations, plus CC, CFLAGS
|
|
# etc. to ensure the right sysroot is selected.
|
|
HOST_CMAKE_FLAGS="-DCMAKE_SYSTEM_NAME=$CMAKE_SYSTEM_NAME -DCMAKE_SYSTEM_PROCESSOR=$GNU_ARCH -DCMAKE_OSX_DEPLOYMENT_TARGET=$IPHONEOS_DEPLOYMENT_TARGET -DCMAKE_OSX_SYSROOT=$IOS_SDK_PATH -DBUILD_SHARED_LIBS=NO"
|
|
|
|
# Meson needs to be pointed at a cross-platform configuration file
|
|
# This will be generated once CC etc. have been evaluated.
|
|
HOST_MESON_FLAGS="--cross-file $WORKDIR/meson-cross.txt -Dprefer_static=true -Ddefault_library=static"
|
|
|
|
elif [[ "$(uname -s)" == "Darwin" ]]; then
|
|
check_cibw_archs
|
|
# Build macOS dependencies in `build/darwin`
|
|
# Install them into `build/deps/darwin`
|
|
PLAT=$CIBW_ARCHS
|
|
WORKDIR=$(pwd)/build/darwin
|
|
BUILD_PREFIX=$(pwd)/build/deps/darwin
|
|
else
|
|
# Build prefix will default to /usr/local
|
|
PLAT="${CIBW_ARCHS:-$AUDITWHEEL_ARCH}"
|
|
WORKDIR=$(pwd)/build
|
|
MB_ML_LIBC=${AUDITWHEEL_POLICY::9}
|
|
MB_ML_VER=${AUDITWHEEL_POLICY:9}
|
|
fi
|
|
|
|
# Define custom utilities
|
|
source wheels/multibuild/common_utils.sh
|
|
source wheels/multibuild/library_builders.sh
|
|
if [[ -z "$IS_MACOS" ]]; then
|
|
source wheels/multibuild/manylinux_utils.sh
|
|
fi
|
|
|
|
ARCHIVE_SDIR=pillow-depends-main
|
|
|
|
# Package versions for fresh source builds. Version numbers with "Patched"
|
|
# annotations have a source code patch that is required for some platforms. If
|
|
# you change those versions, ensure the patch is also updated.
|
|
FREETYPE_VERSION=2.13.3
|
|
HARFBUZZ_VERSION=11.2.1
|
|
LIBPNG_VERSION=1.6.49
|
|
JPEGTURBO_VERSION=3.1.1
|
|
OPENJPEG_VERSION=2.5.3
|
|
XZ_VERSION=5.8.1
|
|
TIFF_VERSION=4.7.0
|
|
LCMS2_VERSION=2.17
|
|
ZLIB_VERSION=1.3.1
|
|
ZLIB_NG_VERSION=2.2.4
|
|
LIBWEBP_VERSION=1.5.0 # Patched; next release won't need patching. See patch file.
|
|
BZIP2_VERSION=1.0.8
|
|
LIBXCB_VERSION=1.17.0
|
|
BROTLI_VERSION=1.1.0 # Patched; next release won't need patching. See patch file.
|
|
LIBAVIF_VERSION=1.3.0
|
|
|
|
function build_pkg_config {
|
|
if [ -e pkg-config-stamp ]; then return; fi
|
|
# This essentially duplicates the Homebrew recipe.
|
|
# On iOS, we need a binary that can be executed on the build machine; but we
|
|
# can create a host-specific pc-path to store iOS .pc files. To ensure a
|
|
# macOS-compatible build, we temporarily clear environment flags that set
|
|
# iOS-specific values.
|
|
if [[ -n "$IOS_SDK" ]]; then
|
|
ORIGINAL_HOST_CONFIGURE_FLAGS=$HOST_CONFIGURE_FLAGS
|
|
ORIGINAL_IPHONEOS_DEPLOYMENT_TARGET=$IPHONEOS_DEPLOYMENT_TARGET
|
|
unset HOST_CONFIGURE_FLAGS
|
|
unset IPHONEOS_DEPLOYMENT_TARGET
|
|
fi
|
|
|
|
CFLAGS="$CFLAGS -Wno-int-conversion" CPPFLAGS="" build_simple pkg-config 0.29.2 https://pkg-config.freedesktop.org/releases tar.gz \
|
|
--disable-debug --disable-host-tool --with-internal-glib \
|
|
--with-pc-path=$BUILD_PREFIX/share/pkgconfig:$BUILD_PREFIX/lib/pkgconfig \
|
|
--with-system-include-path=$(xcrun --show-sdk-path --sdk macosx)/usr/include
|
|
|
|
if [[ -n "$IOS_SDK" ]]; then
|
|
HOST_CONFIGURE_FLAGS=$ORIGINAL_HOST_CONFIGURE_FLAGS
|
|
IPHONEOS_DEPLOYMENT_TARGET=$ORIGINAL_IPHONEOS_DEPLOYMENT_TARGET
|
|
fi;
|
|
|
|
export PKG_CONFIG=$BUILD_PREFIX/bin/pkg-config
|
|
touch pkg-config-stamp
|
|
}
|
|
|
|
function build_zlib_ng {
|
|
if [ -e zlib-stamp ]; then return; fi
|
|
# zlib-ng uses a "configure" script, but it's not a GNU autotools script, so
|
|
# it doesn't honor the usual flags. Temporarily disable any
|
|
# cross-compilation flags.
|
|
ORIGINAL_HOST_CONFIGURE_FLAGS=$HOST_CONFIGURE_FLAGS
|
|
unset HOST_CONFIGURE_FLAGS
|
|
|
|
build_github zlib-ng/zlib-ng $ZLIB_NG_VERSION --zlib-compat
|
|
|
|
HOST_CONFIGURE_FLAGS=$ORIGINAL_HOST_CONFIGURE_FLAGS
|
|
|
|
if [[ -n "$IS_MACOS" ]] && [[ -z "$IOS_SDK" ]]; then
|
|
# Ensure that on macOS, the library name is an absolute path, not an
|
|
# @rpath, so that delocate picks up the right library (and doesn't need
|
|
# DYLD_LIBRARY_PATH to be set). The default Makefile doesn't have an
|
|
# option to control the install_name. This isn't needed on iOS, as iOS
|
|
# only builds the static library.
|
|
install_name_tool -id $BUILD_PREFIX/lib/libz.1.dylib $BUILD_PREFIX/lib/libz.1.dylib
|
|
fi
|
|
touch zlib-stamp
|
|
}
|
|
|
|
function build_brotli {
|
|
if [ -e brotli-stamp ]; then return; fi
|
|
local out_dir=$(fetch_unpack https://github.com/google/brotli/archive/v$BROTLI_VERSION.tar.gz brotli-$BROTLI_VERSION.tar.gz)
|
|
(cd $out_dir \
|
|
&& cmake -DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX -DCMAKE_INSTALL_LIBDIR=$BUILD_PREFIX/lib -DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib $HOST_CMAKE_FLAGS . \
|
|
&& make install)
|
|
touch brotli-stamp
|
|
}
|
|
|
|
function build_harfbuzz {
|
|
if [ -e harfbuzz-stamp ]; then return; fi
|
|
python3 -m pip install meson ninja
|
|
|
|
local out_dir=$(fetch_unpack https://github.com/harfbuzz/harfbuzz/releases/download/$HARFBUZZ_VERSION/harfbuzz-$HARFBUZZ_VERSION.tar.xz harfbuzz-$HARFBUZZ_VERSION.tar.xz)
|
|
(cd $out_dir \
|
|
&& meson setup build --prefix=$BUILD_PREFIX --libdir=$BUILD_PREFIX/lib --buildtype=minsize -Dfreetype=enabled -Dglib=disabled -Dtests=disabled $HOST_MESON_FLAGS)
|
|
(cd $out_dir/build \
|
|
&& meson install)
|
|
touch harfbuzz-stamp
|
|
}
|
|
|
|
function build_libavif {
|
|
if [ -e libavif-stamp ]; then return; fi
|
|
|
|
python3 -m pip install meson ninja
|
|
|
|
if [[ "$PLAT" == "x86_64" ]] || [ -n "$SANITIZER" ]; then
|
|
build_simple nasm 2.16.03 https://www.nasm.us/pub/nasm/releasebuilds/2.16.03
|
|
fi
|
|
|
|
local build_type=MinSizeRel
|
|
local lto=ON
|
|
|
|
local libavif_cmake_flags
|
|
|
|
if [ -n "$IS_MACOS" ]; then
|
|
lto=OFF
|
|
libavif_cmake_flags=(
|
|
-DCMAKE_C_FLAGS_MINSIZEREL="-Oz -DNDEBUG -flto" \
|
|
-DCMAKE_CXX_FLAGS_MINSIZEREL="-Oz -DNDEBUG -flto" \
|
|
-DCMAKE_SHARED_LINKER_FLAGS_INIT="-Wl,-S,-x,-dead_strip_dylibs" \
|
|
)
|
|
else
|
|
if [[ "$MB_ML_VER" == 2014 ]] && [[ "$PLAT" == "x86_64" ]]; then
|
|
build_type=Release
|
|
fi
|
|
libavif_cmake_flags=(-DCMAKE_SHARED_LINKER_FLAGS_INIT="-Wl,--strip-all,-z,relro,-z,now")
|
|
fi
|
|
|
|
local out_dir=$(fetch_unpack https://github.com/AOMediaCodec/libavif/archive/refs/tags/v$LIBAVIF_VERSION.tar.gz libavif-$LIBAVIF_VERSION.tar.gz)
|
|
# CONFIG_AV1_HIGHBITDEPTH=0 is a flag for libaom (included as a subproject
|
|
# of libavif) that disables support for encoding high bit depth images.
|
|
(cd $out_dir \
|
|
&& cmake \
|
|
-DCMAKE_INSTALL_PREFIX=$BUILD_PREFIX \
|
|
-DCMAKE_INSTALL_LIBDIR=$BUILD_PREFIX/lib \
|
|
-DCMAKE_INSTALL_NAME_DIR=$BUILD_PREFIX/lib \
|
|
-DBUILD_SHARED_LIBS=ON \
|
|
-DAVIF_LIBSHARPYUV=LOCAL \
|
|
-DAVIF_LIBYUV=LOCAL \
|
|
-DAVIF_CODEC_AOM=LOCAL \
|
|
-DCONFIG_AV1_HIGHBITDEPTH=0 \
|
|
-DAVIF_CODEC_AOM_DECODE=OFF \
|
|
-DAVIF_CODEC_DAV1D=LOCAL \
|
|
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=$lto \
|
|
-DCMAKE_C_VISIBILITY_PRESET=hidden \
|
|
-DCMAKE_CXX_VISIBILITY_PRESET=hidden \
|
|
-DCMAKE_BUILD_TYPE=$build_type \
|
|
"${libavif_cmake_flags[@]}" \
|
|
. \
|
|
&& make install)
|
|
touch libavif-stamp
|
|
}
|
|
|
|
function build {
|
|
build_xz
|
|
if [ -z "$IS_ALPINE" ] && [ -z "$SANITIZER" ] && [ -z "$IS_MACOS" ]; then
|
|
yum remove -y zlib-devel
|
|
fi
|
|
if [[ -n "$IS_MACOS" ]] && [[ "$MACOSX_DEPLOYMENT_TARGET" == "10.10" || "$MACOSX_DEPLOYMENT_TARGET" == "10.13" ]]; then
|
|
build_new_zlib
|
|
else
|
|
build_zlib_ng
|
|
fi
|
|
|
|
build_simple xcb-proto 1.17.0 https://xorg.freedesktop.org/archive/individual/proto
|
|
if [[ -n "$IS_MACOS" ]]; then
|
|
build_simple xorgproto 2024.1 https://www.x.org/pub/individual/proto
|
|
build_simple libXau 1.0.12 https://www.x.org/pub/individual/lib
|
|
build_simple libpthread-stubs 0.5 https://xcb.freedesktop.org/dist
|
|
else
|
|
sed "s/\${pc_sysrootdir\}//" $BUILD_PREFIX/share/pkgconfig/xcb-proto.pc > $BUILD_PREFIX/lib/pkgconfig/xcb-proto.pc
|
|
fi
|
|
build_simple libxcb $LIBXCB_VERSION https://www.x.org/releases/individual/lib
|
|
|
|
build_libjpeg_turbo
|
|
if [[ -n "$IS_MACOS" ]]; then
|
|
# Custom tiff build to include jpeg; by default, configure won't include
|
|
# headers/libs in the custom macOS/iOS prefix. Explicitly disable webp,
|
|
# libdeflate and zstd, because on x86_64 macs, it will pick up the
|
|
# Homebrew versions of those libraries from /usr/local.
|
|
build_simple tiff $TIFF_VERSION https://download.osgeo.org/libtiff tar.gz \
|
|
--with-jpeg-include-dir=$BUILD_PREFIX/include --with-jpeg-lib-dir=$BUILD_PREFIX/lib \
|
|
--disable-webp --disable-libdeflate --disable-zstd
|
|
else
|
|
build_tiff
|
|
fi
|
|
|
|
if [[ -z "$IOS_SDK" ]]; then
|
|
# Short term workaround; don't build libavif on iOS
|
|
build_libavif
|
|
fi
|
|
build_libpng
|
|
build_lcms2
|
|
build_openjpeg
|
|
|
|
webp_cflags="-O3 -DNDEBUG"
|
|
if [[ -n "$IS_MACOS" ]]; then
|
|
webp_cflags="$webp_cflags -Wl,-headerpad_max_install_names"
|
|
fi
|
|
CFLAGS="$CFLAGS $webp_cflags" build_simple libwebp $LIBWEBP_VERSION \
|
|
https://storage.googleapis.com/downloads.webmproject.org/releases/webp tar.gz \
|
|
--enable-libwebpmux --enable-libwebpdemux
|
|
|
|
build_brotli
|
|
|
|
if [[ -n "$IS_MACOS" ]]; then
|
|
# Custom freetype build
|
|
build_simple freetype $FREETYPE_VERSION https://download.savannah.gnu.org/releases/freetype tar.gz --with-harfbuzz=no
|
|
else
|
|
build_freetype
|
|
fi
|
|
|
|
if [[ -z "$IOS_SDK" ]]; then
|
|
# On iOS, there's no vendor-provided raqm, and we can't ship it due to
|
|
# licensing, so there's no point building harfbuzz.
|
|
build_harfbuzz
|
|
fi
|
|
}
|
|
|
|
function create_meson_cross_config {
|
|
cat << EOF > $WORKDIR/meson-cross.txt
|
|
[binaries]
|
|
pkg-config = '$BUILD_PREFIX/bin/pkg-config'
|
|
cmake = '$(which cmake)'
|
|
c = '$CC'
|
|
cpp = '$CXX'
|
|
strip = '$STRIP'
|
|
|
|
[built-in options]
|
|
c_args = '$CFLAGS -I$BUILD_PREFIX/include'
|
|
cpp_args = '$CXXFLAGS -I$BUILD_PREFIX/include'
|
|
c_link_args = '$CFLAGS -L$BUILD_PREFIX/lib'
|
|
cpp_link_args = '$CFLAGS -L$BUILD_PREFIX/lib'
|
|
|
|
[host_machine]
|
|
system = 'darwin'
|
|
subsystem = 'ios'
|
|
kernel = 'xnu'
|
|
cpu_family = '$(uname -m)'
|
|
cpu = '$(uname -m)'
|
|
endian = 'little'
|
|
|
|
EOF
|
|
}
|
|
|
|
# Perform all dependency builds in the build subfolder.
|
|
mkdir -p $WORKDIR
|
|
pushd $WORKDIR > /dev/null
|
|
|
|
# Any stuff that you need to do before you start building the wheels
|
|
# Runs in the root directory of this repository.
|
|
if [[ ! -d $WORKDIR/pillow-depends-main ]]; then
|
|
if [[ ! -f $PROJECTDIR/pillow-depends-main.zip ]]; then
|
|
echo "Download pillow dependency sources..."
|
|
curl -fSL -o $PROJECTDIR/pillow-depends-main.zip https://github.com/python-pillow/pillow-depends/archive/main.zip
|
|
fi
|
|
echo "Unpacking pillow dependency sources..."
|
|
untar $PROJECTDIR/pillow-depends-main.zip
|
|
fi
|
|
|
|
if [[ -n "$IS_MACOS" ]]; then
|
|
# Ensure the basic structure of the build prefix directory exists.
|
|
mkdir -p "$BUILD_PREFIX/bin"
|
|
mkdir -p "$BUILD_PREFIX/lib"
|
|
|
|
# Ensure pkg-config is available. This is done *before* setting CC, CFLAGS
|
|
# etc. to ensure that the build is *always* a macOS build, even when building
|
|
# for iOS.
|
|
build_pkg_config
|
|
|
|
# Ensure cmake is available, and that the default prefix used by CMake is
|
|
# the build prefix
|
|
python3 -m pip install cmake
|
|
export CMAKE_PREFIX_PATH=$BUILD_PREFIX
|
|
|
|
if [[ -n "$IOS_SDK" ]]; then
|
|
export AR="$(xcrun --find --sdk $IOS_SDK ar)"
|
|
export CPP="$(xcrun --find --sdk $IOS_SDK clang) -E"
|
|
export CC=$(xcrun --find --sdk $IOS_SDK clang)
|
|
export CXX=$(xcrun --find --sdk $IOS_SDK clang++)
|
|
export LD=$(xcrun --find --sdk $IOS_SDK ld)
|
|
export STRIP=$(xcrun --find --sdk $IOS_SDK strip)
|
|
|
|
CPPFLAGS="$CPPFLAGS --sysroot=$IOS_SDK_PATH"
|
|
CFLAGS="-target $IOS_HOST_TRIPLE --sysroot=$IOS_SDK_PATH -mios-version-min=$IPHONEOS_DEPLOYMENT_TARGET"
|
|
CXXFLAGS="-target $IOS_HOST_TRIPLE --sysroot=$IOS_SDK_PATH -mios-version-min=$IPHONEOS_DEPLOYMENT_TARGET"
|
|
|
|
# Having IPHONEOS_DEPLOYMENT_TARGET in the environment causes problems
|
|
# with some cross-building toolchains, because it introduces implicit
|
|
# behavior into clang.
|
|
unset IPHONEOS_DEPLOYMENT_TARGET
|
|
|
|
# Now that we know CC etc., we can create a meson cross-configuration file
|
|
create_meson_cross_config
|
|
fi
|
|
fi
|
|
|
|
wrap_wheel_builder build
|
|
|
|
# Return to the project root to finish the build
|
|
popd > /dev/null
|
|
|
|
# Append licenses
|
|
for filename in wheels/dependency_licenses/*; do
|
|
echo -e "\n\n----\n\n$(basename $filename | cut -f 1 -d '.')\n" | cat >> LICENSE
|
|
cat $filename >> LICENSE
|
|
done
|