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