xref: /aosp_15_r20/external/webp/xcframeworkbuild.sh (revision b2055c353e87c8814eb2b6b1b11112a1562253bd)
1*b2055c35SXin Li#!/bin/bash
2*b2055c35SXin Li#
3*b2055c35SXin Li# This script generates 'WebP.xcframework', 'WebPDecoder.xcframework',
4*b2055c35SXin Li# 'WebPDemux.xcframework' and 'WebPMux.xcframework'.
5*b2055c35SXin Li# An iOS, Mac or Mac Catalyst app can decode WebP images by including
6*b2055c35SXin Li# 'WebPDecoder.xcframework' and both encode and decode WebP images by including
7*b2055c35SXin Li# 'WebP.xcframework'.
8*b2055c35SXin Li#
9*b2055c35SXin Li# Run ./xcframeworkbuild.sh to generate the frameworks under the current
10*b2055c35SXin Li# directory (the previous build will be erased if it exists).
11*b2055c35SXin Li#
12*b2055c35SXin Li
13*b2055c35SXin Liset -e
14*b2055c35SXin Li
15*b2055c35SXin Li# Set these variables based on the desired minimum deployment target.
16*b2055c35SXin Lireadonly IOS_MIN_VERSION=6.0
17*b2055c35SXin Lireadonly MACOSX_MIN_VERSION=10.15
18*b2055c35SXin Lireadonly MACOSX_CATALYST_MIN_VERSION=14.0
19*b2055c35SXin Li
20*b2055c35SXin Li# Extract Xcode version.
21*b2055c35SXin Lireadonly XCODE=$(xcodebuild -version | grep Xcode | cut -d " " -f2)
22*b2055c35SXin Liif [[ -z "${XCODE}" ]] || [[ "${XCODE%%.*}" -lt 11 ]]; then
23*b2055c35SXin Li  echo "Xcode 11.0 or higher is required!"
24*b2055c35SXin Li  exit 1
25*b2055c35SXin Lifi
26*b2055c35SXin Li
27*b2055c35SXin Li# Extract the latest SDK version from the final field of the form: iphoneosX.Y
28*b2055c35SXin Li# / macosxX.Y
29*b2055c35SXin Lireadonly SDK=($(
30*b2055c35SXin Li  xcodebuild -showsdks \
31*b2055c35SXin Li    | grep iphoneos | sort | tail -n 1 | awk '{print substr($NF, 9)}'
32*b2055c35SXin Li  xcodebuild -showsdks \
33*b2055c35SXin Li    | grep macosx | sort | tail -n 1 | awk '{print substr($NF, 7)}'
34*b2055c35SXin Li))
35*b2055c35SXin Lireadonly IOS=0
36*b2055c35SXin Lireadonly MACOS=1
37*b2055c35SXin Lireadonly IOS_SIMULATOR=2
38*b2055c35SXin Lireadonly MACOS_CATALYST=3
39*b2055c35SXin Lireadonly NUM_PLATFORMS=4
40*b2055c35SXin Li
41*b2055c35SXin Lireadonly OLDPATH=${PATH}
42*b2055c35SXin Li
43*b2055c35SXin Li# Names should be of the form '<platform>-[<variant>-]<architecture>'.
44*b2055c35SXin LiPLATFORMS[$IOS]="iPhoneOS-armv7 iPhoneOS-armv7s iPhoneOS-arm64"
45*b2055c35SXin LiPLATFORMS[$IOS_SIMULATOR]="iPhoneSimulator-i386 iPhoneSimulator-x86_64"
46*b2055c35SXin LiPLATFORMS[$MACOS]="MacOSX-x86_64"
47*b2055c35SXin LiPLATFORMS[$MACOS_CATALYST]="MacOSX-Catalyst-x86_64"
48*b2055c35SXin Liif [[ "${XCODE%%.*}" -ge 12 ]]; then
49*b2055c35SXin Li  PLATFORMS[$MACOS]+=" MacOSX-arm64"
50*b2055c35SXin Li  PLATFORMS[$MACOS_CATALYST]+=" MacOSX-Catalyst-arm64"
51*b2055c35SXin Li  PLATFORMS[$IOS_SIMULATOR]+=" iPhoneSimulator-arm64"
52*b2055c35SXin Lielif [[ "${XCODE%%.*}" -eq 11 ]]; then
53*b2055c35SXin Li  cat << EOF
54*b2055c35SXin LiWARNING: Xcode 12.0 or higher is required to build targets for
55*b2055c35SXin LiWARNING: Apple Silicon (arm64). The XCFrameworks generated with Xcode 11 will
56*b2055c35SXin LiWARNING: contain libraries for MacOS & Catalyst supporting x86_64 only.
57*b2055c35SXin LiWARNING: The build will continue in 5 seconds...
58*b2055c35SXin LiEOF
59*b2055c35SXin Li  sleep 5
60*b2055c35SXin Lielse
61*b2055c35SXin Li  echo "Xcode 11.0 or higher is required!"
62*b2055c35SXin Li  exit 1
63*b2055c35SXin Lifi
64*b2055c35SXin Lireadonly PLATFORMS
65*b2055c35SXin Lireadonly SRCDIR=$(dirname $0)
66*b2055c35SXin Lireadonly TOPDIR=$(pwd)
67*b2055c35SXin Lireadonly BUILDDIR="${TOPDIR}/xcframeworkbuild"
68*b2055c35SXin Lireadonly TARGETDIR="${TOPDIR}/WebP.xcframework"
69*b2055c35SXin Lireadonly DECTARGETDIR="${TOPDIR}/WebPDecoder.xcframework"
70*b2055c35SXin Lireadonly MUXTARGETDIR="${TOPDIR}/WebPMux.xcframework"
71*b2055c35SXin Lireadonly DEMUXTARGETDIR="${TOPDIR}/WebPDemux.xcframework"
72*b2055c35SXin Lireadonly SHARPYUVTARGETDIR="${TOPDIR}/SharpYuv.xcframework"
73*b2055c35SXin Lireadonly DEVELOPER=$(xcode-select --print-path)
74*b2055c35SXin Lireadonly DEVROOT="${DEVELOPER}/Toolchains/XcodeDefault.xctoolchain"
75*b2055c35SXin Lireadonly PLATFORMSROOT="${DEVELOPER}/Platforms"
76*b2055c35SXin Lireadonly LIPO=$(xcrun -sdk iphoneos${SDK[$IOS]} -find lipo)
77*b2055c35SXin Li
78*b2055c35SXin Liif [[ -z "${SDK[$IOS]}" ]] || [[ ${SDK[$IOS]%%.*} -lt 8 ]]; then
79*b2055c35SXin Li  echo "iOS SDK version 8.0 or higher is required!"
80*b2055c35SXin Li  exit 1
81*b2055c35SXin Lifi
82*b2055c35SXin Li
83*b2055c35SXin Li#######################################
84*b2055c35SXin Li# Moves Headers/*.h to Headers/<framework>/
85*b2055c35SXin Li#
86*b2055c35SXin Li# Places framework headers in a subdirectory to avoid Xcode errors when using
87*b2055c35SXin Li# multiple frameworks:
88*b2055c35SXin Li#   error: Multiple commands produce
89*b2055c35SXin Li#     '.../Build/Products/Debug-iphoneos/include/types.h'
90*b2055c35SXin Li# Arguments:
91*b2055c35SXin Li#   $1 - path to framework
92*b2055c35SXin Li#######################################
93*b2055c35SXin Liupdate_headers_path() {
94*b2055c35SXin Li  local framework_name="$(basename ${1%.xcframework})"
95*b2055c35SXin Li  local subdir
96*b2055c35SXin Li  for d in $(find "$1" -path "*/Headers"); do
97*b2055c35SXin Li    subdir="$d/$framework_name"
98*b2055c35SXin Li    if [[ -d "$subdir" ]]; then
99*b2055c35SXin Li      # SharpYuv will have a sharpyuv subdirectory. macOS is case insensitive,
100*b2055c35SXin Li      # but for consistency with the other frameworks, rename the directory to
101*b2055c35SXin Li      # match the case of the framework name.
102*b2055c35SXin Li      mv "$(echo ${subdir} | tr 'A-Z' 'a-z')" "$subdir"
103*b2055c35SXin Li    else
104*b2055c35SXin Li      mkdir "$subdir"
105*b2055c35SXin Li      mv "$d/"*.h "$subdir"
106*b2055c35SXin Li    fi
107*b2055c35SXin Li  done
108*b2055c35SXin Li}
109*b2055c35SXin Li
110*b2055c35SXin Liecho "Xcode Version: ${XCODE}"
111*b2055c35SXin Liecho "iOS SDK Version: ${SDK[$IOS]}"
112*b2055c35SXin Liecho "MacOS SDK Version: ${SDK[$MACOS]}"
113*b2055c35SXin Li
114*b2055c35SXin Liif [[ -e "${BUILDDIR}" || -e "${TARGETDIR}" || -e "${DECTARGETDIR}" \
115*b2055c35SXin Li      || -e "${MUXTARGETDIR}" || -e "${DEMUXTARGETDIR}" \
116*b2055c35SXin Li      || -e "${SHARPYUVTARGETDIR}" ]]; then
117*b2055c35SXin Li  cat << EOF
118*b2055c35SXin LiWARNING: The following directories will be deleted:
119*b2055c35SXin LiWARNING:   ${BUILDDIR}
120*b2055c35SXin LiWARNING:   ${TARGETDIR}
121*b2055c35SXin LiWARNING:   ${DECTARGETDIR}
122*b2055c35SXin LiWARNING:   ${MUXTARGETDIR}
123*b2055c35SXin LiWARNING:   ${DEMUXTARGETDIR}
124*b2055c35SXin LiWARNING:   ${SHARPYUVTARGETDIR}
125*b2055c35SXin LiWARNING: The build will continue in 5 seconds...
126*b2055c35SXin LiEOF
127*b2055c35SXin Li  sleep 5
128*b2055c35SXin Lifi
129*b2055c35SXin Lirm -rf ${BUILDDIR} ${TARGETDIR} ${DECTARGETDIR} \
130*b2055c35SXin Li  ${MUXTARGETDIR} ${DEMUXTARGETDIR} ${SHARPYUVTARGETDIR}
131*b2055c35SXin Li
132*b2055c35SXin Liif [[ ! -e ${SRCDIR}/configure ]]; then
133*b2055c35SXin Li  if ! (cd ${SRCDIR} && sh autogen.sh); then
134*b2055c35SXin Li    cat << EOF
135*b2055c35SXin LiError creating configure script!
136*b2055c35SXin LiThis script requires the autoconf/automake and libtool to build. MacPorts or
137*b2055c35SXin LiHomebrew can be used to obtain these:
138*b2055c35SXin Lihttps://www.macports.org/install.php
139*b2055c35SXin Lihttps://brew.sh/
140*b2055c35SXin LiEOF
141*b2055c35SXin Li    exit 1
142*b2055c35SXin Li  fi
143*b2055c35SXin Lifi
144*b2055c35SXin Li
145*b2055c35SXin Lifor (( i = 0; i < $NUM_PLATFORMS; ++i )); do
146*b2055c35SXin Li  LIBLIST=()
147*b2055c35SXin Li  DECLIBLIST=()
148*b2055c35SXin Li  MUXLIBLIST=()
149*b2055c35SXin Li  DEMUXLIBLIST=()
150*b2055c35SXin Li  SHARPYUVLIBLIST=()
151*b2055c35SXin Li
152*b2055c35SXin Li  for PLATFORM in ${PLATFORMS[$i]}; do
153*b2055c35SXin Li    ROOTDIR="${BUILDDIR}/${PLATFORM}"
154*b2055c35SXin Li    mkdir -p "${ROOTDIR}"
155*b2055c35SXin Li
156*b2055c35SXin Li    ARCH="${PLATFORM##*-}"
157*b2055c35SXin Li    case "${PLATFORM}" in
158*b2055c35SXin Li      iPhone*)
159*b2055c35SXin Li        sdk="${SDK[$IOS]}"
160*b2055c35SXin Li        ;;
161*b2055c35SXin Li      MacOS*)
162*b2055c35SXin Li        sdk="${SDK[$MACOS]}"
163*b2055c35SXin Li        ;;
164*b2055c35SXin Li      *)
165*b2055c35SXin Li        echo "Unrecognized platform: ${PLATFORM}!"
166*b2055c35SXin Li        exit 1
167*b2055c35SXin Li        ;;
168*b2055c35SXin Li    esac
169*b2055c35SXin Li
170*b2055c35SXin Li    SDKROOT="${PLATFORMSROOT}/${PLATFORM%%-*}.platform/"
171*b2055c35SXin Li    SDKROOT+="Developer/SDKs/${PLATFORM%%-*}${sdk}.sdk/"
172*b2055c35SXin Li    CFLAGS="-pipe -isysroot ${SDKROOT} -O3 -DNDEBUG"
173*b2055c35SXin Li    case "${PLATFORM}" in
174*b2055c35SXin Li      iPhone*)
175*b2055c35SXin Li        CFLAGS+=" -fembed-bitcode"
176*b2055c35SXin Li        CFLAGS+=" -target ${ARCH}-apple-ios${IOS_MIN_VERSION}"
177*b2055c35SXin Li        [[ "${PLATFORM}" == *Simulator* ]] && CFLAGS+="-simulator"
178*b2055c35SXin Li        ;;
179*b2055c35SXin Li      MacOSX-Catalyst*)
180*b2055c35SXin Li        CFLAGS+=" -target"
181*b2055c35SXin Li        CFLAGS+=" ${ARCH}-apple-ios${MACOSX_CATALYST_MIN_VERSION}-macabi"
182*b2055c35SXin Li        ;;
183*b2055c35SXin Li      MacOSX*)
184*b2055c35SXin Li        CFLAGS+=" -mmacosx-version-min=${MACOSX_MIN_VERSION}"
185*b2055c35SXin Li        ;;
186*b2055c35SXin Li    esac
187*b2055c35SXin Li
188*b2055c35SXin Li    set -x
189*b2055c35SXin Li    export PATH="${DEVROOT}/usr/bin:${OLDPATH}"
190*b2055c35SXin Li    ${SRCDIR}/configure --host=${ARCH/arm64/aarch64}-apple-darwin \
191*b2055c35SXin Li      --build=$(${SRCDIR}/config.guess) \
192*b2055c35SXin Li      --prefix=${ROOTDIR} \
193*b2055c35SXin Li      --disable-shared --enable-static \
194*b2055c35SXin Li      --enable-libwebpdecoder --enable-swap-16bit-csp \
195*b2055c35SXin Li      --enable-libwebpmux \
196*b2055c35SXin Li      CC="clang -arch ${ARCH}" \
197*b2055c35SXin Li      CFLAGS="${CFLAGS}"
198*b2055c35SXin Li    set +x
199*b2055c35SXin Li
200*b2055c35SXin Li    # Build only the libraries, skip the examples.
201*b2055c35SXin Li    make V=0 -C sharpyuv install
202*b2055c35SXin Li    make V=0 -C src install
203*b2055c35SXin Li
204*b2055c35SXin Li    LIBLIST+=("${ROOTDIR}/lib/libwebp.a")
205*b2055c35SXin Li    DECLIBLIST+=("${ROOTDIR}/lib/libwebpdecoder.a")
206*b2055c35SXin Li    MUXLIBLIST+=("${ROOTDIR}/lib/libwebpmux.a")
207*b2055c35SXin Li    DEMUXLIBLIST+=("${ROOTDIR}/lib/libwebpdemux.a")
208*b2055c35SXin Li    SHARPYUVLIBLIST+=("${ROOTDIR}/lib/libsharpyuv.a")
209*b2055c35SXin Li    # xcodebuild requires a directory for the -headers option, these will match
210*b2055c35SXin Li    # for all builds.
211*b2055c35SXin Li    make -C src install-data DESTDIR="${ROOTDIR}/lib-headers"
212*b2055c35SXin Li    make -C src install-commonHEADERS DESTDIR="${ROOTDIR}/dec-headers"
213*b2055c35SXin Li    make -C src/demux install-data DESTDIR="${ROOTDIR}/demux-headers"
214*b2055c35SXin Li    make -C src/mux install-data DESTDIR="${ROOTDIR}/mux-headers"
215*b2055c35SXin Li    make -C sharpyuv install-data DESTDIR="${ROOTDIR}/sharpyuv-headers"
216*b2055c35SXin Li    LIB_HEADERS="${ROOTDIR}/lib-headers/${ROOTDIR}/include/webp"
217*b2055c35SXin Li    DEC_HEADERS="${ROOTDIR}/dec-headers/${ROOTDIR}/include/webp"
218*b2055c35SXin Li    DEMUX_HEADERS="${ROOTDIR}/demux-headers/${ROOTDIR}/include/webp"
219*b2055c35SXin Li    MUX_HEADERS="${ROOTDIR}/mux-headers/${ROOTDIR}/include/webp"
220*b2055c35SXin Li    SHARPYUV_HEADERS="${ROOTDIR}/sharpyuv-headers/${ROOTDIR}/include/webp"
221*b2055c35SXin Li
222*b2055c35SXin Li    make distclean
223*b2055c35SXin Li
224*b2055c35SXin Li    export PATH=${OLDPATH}
225*b2055c35SXin Li  done
226*b2055c35SXin Li
227*b2055c35SXin Li  [[ -z "${LIBLIST[@]}" ]] && continue
228*b2055c35SXin Li
229*b2055c35SXin Li  # Create a temporary target directory for each <platform>[-<variant>].
230*b2055c35SXin Li  target_dir="${BUILDDIR}/${PLATFORMS[$i]}"
231*b2055c35SXin Li  target_dir="${target_dir%% *}"
232*b2055c35SXin Li  target_dir="${target_dir%-*}"
233*b2055c35SXin Li  target_lib="${target_dir}/$(basename ${LIBLIST[0]})"
234*b2055c35SXin Li  target_declib="${target_dir}/$(basename ${DECLIBLIST[0]})"
235*b2055c35SXin Li  target_demuxlib="${target_dir}/$(basename ${DEMUXLIBLIST[0]})"
236*b2055c35SXin Li  target_muxlib="${target_dir}/$(basename ${MUXLIBLIST[0]})"
237*b2055c35SXin Li  target_sharpyuvlib="${target_dir}/$(basename ${SHARPYUVLIBLIST[0]})"
238*b2055c35SXin Li
239*b2055c35SXin Li  mkdir -p "${target_dir}"
240*b2055c35SXin Li  ${LIPO} -create ${LIBLIST[@]} -output "${target_lib}"
241*b2055c35SXin Li  ${LIPO} -create ${DECLIBLIST[@]} -output "${target_declib}"
242*b2055c35SXin Li  ${LIPO} -create ${DEMUXLIBLIST[@]} -output "${target_demuxlib}"
243*b2055c35SXin Li  ${LIPO} -create ${MUXLIBLIST[@]} -output "${target_muxlib}"
244*b2055c35SXin Li  ${LIPO} -create ${SHARPYUVLIBLIST[@]} -output "${target_sharpyuvlib}"
245*b2055c35SXin Li  FAT_LIBLIST+=(-library "${target_lib}" -headers "${LIB_HEADERS}")
246*b2055c35SXin Li  FAT_DECLIBLIST+=(-library "${target_declib}" -headers "${DEC_HEADERS}")
247*b2055c35SXin Li  FAT_DEMUXLIBLIST+=(-library "${target_demuxlib}" -headers "${DEMUX_HEADERS}")
248*b2055c35SXin Li  FAT_MUXLIBLIST+=(-library "${target_muxlib}" -headers "${MUX_HEADERS}")
249*b2055c35SXin Li  FAT_SHARPYUVLIBLIST+=(-library "${target_sharpyuvlib}")
250*b2055c35SXin Li  FAT_SHARPYUVLIBLIST+=(-headers "${SHARPYUV_HEADERS}")
251*b2055c35SXin Lidone
252*b2055c35SXin Li
253*b2055c35SXin Li# lipo will not put archives with the same architecture (e.g., x86_64
254*b2055c35SXin Li# iPhoneSimulator & MacOS) in the same fat output file. xcodebuild
255*b2055c35SXin Li# -create-xcframework requires universal archives to avoid e.g.:
256*b2055c35SXin Li#   Both ios-x86_64-maccatalyst and ios-arm64-maccatalyst represent two
257*b2055c35SXin Li#   equivalent library definitions
258*b2055c35SXin Liset -x
259*b2055c35SXin Lixcodebuild -create-xcframework "${FAT_LIBLIST[@]}" \
260*b2055c35SXin Li  -output ${TARGETDIR}
261*b2055c35SXin Lixcodebuild -create-xcframework "${FAT_DECLIBLIST[@]}" \
262*b2055c35SXin Li  -output ${DECTARGETDIR}
263*b2055c35SXin Lixcodebuild -create-xcframework "${FAT_DEMUXLIBLIST[@]}" \
264*b2055c35SXin Li  -output ${DEMUXTARGETDIR}
265*b2055c35SXin Lixcodebuild -create-xcframework "${FAT_MUXLIBLIST[@]}" \
266*b2055c35SXin Li  -output ${MUXTARGETDIR}
267*b2055c35SXin Lixcodebuild -create-xcframework "${FAT_SHARPYUVLIBLIST[@]}" \
268*b2055c35SXin Li  -output ${SHARPYUVTARGETDIR}
269*b2055c35SXin Liupdate_headers_path "${TARGETDIR}"
270*b2055c35SXin Liupdate_headers_path "${DECTARGETDIR}"
271*b2055c35SXin Liupdate_headers_path "${DEMUXTARGETDIR}"
272*b2055c35SXin Liupdate_headers_path "${MUXTARGETDIR}"
273*b2055c35SXin Liupdate_headers_path "${SHARPYUVTARGETDIR}"
274*b2055c35SXin Liset +x
275*b2055c35SXin Li
276*b2055c35SXin Liecho  "SUCCESS"
277