go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

xcframeworkbuild.sh (9812B)


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