1#!/usr/bin/env bash 2 3# ==================================================================== 4# Sets the cross compile environment for Xcode/iOS 5# 6# Based upon OpenSSL's setenv-ios.sh by TH, JW, and SM. 7# Heavily modified by JWW for Crypto++. 8# Modified by JWW for Unbound. 9# ==================================================================== 10 11######################################### 12##### Some validation ##### 13######################################### 14 15# In the past we could mostly infer arch or cpu from the SDK (and 16# mostly vice-versa). Nowadays we need it set for us because Apple 17# platforms can be either 32-bit or 64-bit. 18 19if [ -z "$IOS_SDK" ]; then 20 echo "IOS_SDK is not set. Please set it" 21 [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1 22fi 23 24if [ -z "$IOS_CPU" ]; then 25 echo "IOS_CPU is not set. Please set it" 26 [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1 27fi 28 29# cryptest-ios.sh may run this script without sourcing. 30if [ "$0" = "${BASH_SOURCE[0]}" ]; then 31 echo "setenv-ios.sh is usually sourced, but not this time." 32fi 33 34######################################### 35##### Small Fixups, if needed ##### 36######################################### 37 38if [[ "$IOS_SDK" == "iPhone" ]]; then 39 IOS_SDK=iPhoneOS 40fi 41 42if [[ "$IOS_SDK" == "iPhoneOSSimulator" ]]; then 43 IOS_SDK=iPhoneSimulator 44fi 45 46if [[ "$IOS_SDK" == "TV" || "$IOS_SDK" == "AppleTV" ]]; then 47 IOS_SDK=AppleTVOS 48fi 49 50if [[ "$IOS_SDK" == "Watch" || "$IOS_SDK" == "AppleWatch" ]]; then 51 IOS_SDK=WatchOS 52fi 53 54if [[ "$IOS_CPU" == "aarch64" || "$IOS_CPU" == "armv8"* ]] ; then 55 IOS_CPU=arm64 56fi 57 58######################################## 59##### Environment ##### 60######################################## 61 62# The flags below were tested with Xcode 8 on Travis. If 63# you use downlevel versions of Xcode, then you can push 64# xxx-version-min=n lower. For example, Xcode 6 can use 65# -miphoneos-version-min=5. 66 67# iPhones can be either 32-bit or 64-bit 68if [[ "$IOS_SDK" == "iPhoneOS" && "$IOS_CPU" == "armv7"* ]]; then 69 MIN_VER=-miphoneos-version-min=6 70elif [[ "$IOS_SDK" == "iPhoneOS" && "$IOS_CPU" == "arm64" ]]; then 71 MIN_VER=-miphoneos-version-min=6 72 73# Fixups for convenience 74elif [[ "$IOS_SDK" == "iPhoneOS" && "$IOS_CPU" == "i386" ]]; then 75 IOS_SDK=iPhoneSimulator 76 # MIN_VER=-miphoneos-version-min=6 77 MIN_VER=-miphonesimulator-version-min=6 78elif [[ "$IOS_SDK" == "iPhoneOS" && "$IOS_CPU" == "x86_64" ]]; then 79 IOS_SDK=iPhoneSimulator 80 # MIN_VER=-miphoneos-version-min=6 81 MIN_VER=-miphonesimulator-version-min=6 82 83# Simulator builds 84elif [[ "$IOS_SDK" == "iPhoneSimulator" && "$IOS_CPU" == "i386" ]]; then 85 MIN_VER=-miphonesimulator-version-min=6 86elif [[ "$IOS_SDK" == "iPhoneSimulator" && "$IOS_CPU" == "x86_64" ]]; then 87 MIN_VER=-miphonesimulator-version-min=6 88 89# Apple TV can be 32-bit Intel (1st gen), 32-bit ARM (2nd, 3rd gen) or 64-bit ARM (4th gen) 90elif [[ "$IOS_SDK" == "AppleTVOS" && "$IOS_CPU" == "i386" ]]; then 91 MIN_VER=-mappletvos-version-min=6 92elif [[ "$IOS_SDK" == "AppleTVOS" && "$IOS_CPU" == "armv7"* ]]; then 93 MIN_VER=-mappletvos-version-min=6 94elif [[ "$IOS_SDK" == "AppleTVOS" && "$IOS_CPU" == "arm64" ]]; then 95 MIN_VER=-mappletvos-version-min=6 96 97# Simulator builds 98elif [[ "$IOS_SDK" == "AppleTVSimulator" && "$IOS_CPU" == "i386" ]]; then 99 MIN_VER=-mappletvsimulator-version-min=6 100elif [[ "$IOS_SDK" == "AppleTVSimulator" && "$IOS_CPU" == "x86_64" ]]; then 101 MIN_VER=-mappletvsimulator-version-min=6 102 103# Watch can be either 32-bit or 64-bit ARM. TODO: figure out which 104# -mwatchos-version-min=n is needed for arm64. 9 is not enough. 105elif [[ "$IOS_SDK" == "WatchOS" && "$IOS_CPU" == "armv7"* ]]; then 106 MIN_VER=-mwatchos-version-min=6 107elif [[ "$IOS_SDK" == "WatchOS" && "$IOS_CPU" == "arm64" ]]; then 108 MIN_VER=-mwatchos-version-min=10 109 110# Simulator builds. TODO: figure out which -watchos-version-min=n 111# is needed for arm64. 6 compiles and links, but is it correct? 112elif [[ "$IOS_SDK" == "WatchSimulator" && "$IOS_CPU" == "i386" ]]; then 113 MIN_VER=-mwatchsimulator-version-min=6 114elif [[ "$IOS_SDK" == "WatchSimulator" && "$IOS_CPU" == "x86_64" ]]; then 115 MIN_VER=-mwatchsimulator-version-min=6 116 117# And the final catch-all 118else 119 echo "IOS_SDK and IOS_CPU are not valid. Please fix them" 120 [[ "$0" = "${BASH_SOURCE[0]}" ]] && exit 1 || return 1 121fi 122 123##################################################################### 124 125# Xcode 6 and below cannot handle -miphonesimulator-version-min 126# Fix it so the simulator will compile as expected. This trick 127# may work on other SDKs, but it was not tested. 128 129if [ -n "$(command -v xcodebuild 2>/dev/null)" ]; then 130 # Output of xcodebuild is similar to "Xcode 6.2". The first cut gets 131 # the dotted decimal value. The second cut gets the major version. 132 XCODE_VERSION=$(xcodebuild -version 2>/dev/null | head -n 1 | cut -f2 -d" " | cut -f1 -d".") 133 if [ -z "$XCODE_VERSION" ]; then XCODE_VERSION=100; fi 134 135 if [ "$XCODE_VERSION" -le 6 ]; then 136 MIN_VER="${MIN_VER//iphonesimulator/iphoneos}" 137 fi 138fi 139 140##################################################################### 141 142# Allow a user override? I think we should be doing this. The use case is, 143# move /Applications/Xcode somewhere else for a side-by-side installation. 144if [ -z "${XCODE_DEVELOPER-}" ]; then 145 XCODE_DEVELOPER=$(xcode-select -print-path 2>/dev/null) 146fi 147 148if [ ! -d "$XCODE_DEVELOPER" ]; then 149 echo "ERROR: unable to find XCODE_DEVELOPER directory." 150 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 151fi 152 153# XCODE_DEVELOPER_SDK is the SDK location. 154XCODE_DEVELOPER_SDK="$XCODE_DEVELOPER/Platforms/$IOS_SDK.platform" 155 156if [ ! -d "$XCODE_DEVELOPER_SDK" ]; then 157 echo "ERROR: unable to find XCODE_DEVELOPER_SDK directory." 158 echo " Is the SDK supported by Xcode and installed?" 159 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 160fi 161 162# XCODE_TOOLCHAIN is the location of the actual compiler tools. 163if [ -d "$XCODE_DEVELOPER/Toolchains/XcodeDefault.xctoolchain/usr/bin/" ]; then 164 XCODE_TOOLCHAIN="$XCODE_DEVELOPER/Toolchains/XcodeDefault.xctoolchain/usr/bin/" 165elif [ -d "$XCODE_DEVELOPER_SDK/Developer/usr/bin/" ]; then 166 XCODE_TOOLCHAIN="$XCODE_DEVELOPER_SDK/Developer/usr/bin/" 167fi 168 169if [ -z "$XCODE_TOOLCHAIN" ] || [ ! -d "$XCODE_TOOLCHAIN" ]; then 170 echo "ERROR: unable to find Xcode cross-compiler tools." 171 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 172fi 173 174# XCODE_SDK is the SDK name/version being used - adjust the list as appropriate. 175# For example, remove 4.3, 6.2, and 6.1 if they are not installed. We go back to 176# the 1.0 SDKs because Apple WatchOS uses low numbers, like 2.0 and 2.1. 177XCODE_SDK= 178for i in $(seq -f "%.1f" 30.0 -0.1 1.0) 179do 180 if [ -d "$XCODE_DEVELOPER_SDK/Developer/SDKs/$IOS_SDK$i.sdk" ]; then 181 XCODE_SDK="$IOS_SDK$i.sdk" 182 break 183 fi 184done 185 186# Error checking 187if [ -z "$XCODE_SDK" ]; then 188 echo "ERROR: unable to find a SDK." 189 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 190fi 191 192IOS_SYSROOT="$XCODE_DEVELOPER_SDK/Developer/SDKs/$XCODE_SDK" 193 194if [ -z "$IOS_SYSROOT" ] || [ ! -d "$IOS_SYSROOT" ]; then 195 echo "ERROR: unable to find IOS_SYSROOT directory." 196 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 197fi 198 199##################################################################### 200 201# We want to set AR=libtool and ARFLAGS="-static -o", 202# but I am not sure Autotools can handle it. 203CPP=cpp; CC=clang; CXX=clang++; LD=ld 204AS=as; AR=ar; RANLIB=ranlib; STRIP=strip 205 206# Error checking 207if [ ! -e "$XCODE_TOOLCHAIN/$CC" ]; then 208 echo "ERROR: Failed to find iOS clang. Please edit this script." 209 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 210fi 211 212# Error checking 213if [ ! -e "$XCODE_TOOLCHAIN/$CXX" ]; then 214 echo "ERROR: Failed to find iOS clang++. Please edit this script." 215 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 216fi 217 218# Error checking 219if [ ! -e "$XCODE_TOOLCHAIN/$RANLIB" ]; then 220 echo "ERROR: Failed to find iOS ranlib. Please edit this script." 221 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 222fi 223 224# Error checking 225if [ ! -e "$XCODE_TOOLCHAIN/$AR" ]; then 226 echo "ERROR: Failed to find iOS ar. Please edit this script." 227 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 228fi 229 230# Error checking 231if [ ! -e "$XCODE_TOOLCHAIN/$AS" ]; then 232 echo "ERROR: Failed to find iOS as. Please edit this script." 233 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 234fi 235 236# Error checking 237if [ ! -e "$XCODE_TOOLCHAIN/$LD" ]; then 238 echo "ERROR: Failed to find iOS ld. Please edit this script." 239 [ "$0" = "${BASH_SOURCE[0]}" ] && exit 1 || return 1 240fi 241 242##################################################################### 243 244LENGTH=${#XCODE_TOOLCHAIN} 245SUBSTR=${PATH:0:$LENGTH} 246if [ "$SUBSTR" != "$XCODE_TOOLCHAIN" ]; then 247 export PATH="$XCODE_TOOLCHAIN":"$PATH" 248fi 249 250##################################################################### 251 252export CPP CC CXX LD AS AR RANLIB STRIP 253export IOS_SYSROOT 254export CFLAGS="-arch $IOS_CPU $MIN_VER --sysroot=$IOS_SYSROOT" 255export CXXFLAGS="-arch $IOS_CPU $MIN_VER -stdlib-libc++ --sysroot=$IOS_SYSROOT" 256 257##################################################################### 258 259echo "XCODE_TOOLCHAIN: $XCODE_TOOLCHAIN" 260 261echo "CPP: $(command -v "$CPP")" 262echo "CC: $(command -v "$CC")" 263echo "CXX: $(command -v "$CXX")" 264echo "LD: $(command -v "$LD")" 265echo "AS: $(command -v "$AS")" 266echo "AR: $(command -v "$AR")" 267 268echo "IOS_SYSROOT: $IOS_SYSROOT" 269 270echo "CPPFLAGS: $CPPFLAGS" 271echo "CFLAGS: $CFLAGS" 272echo "CXXFLAGS: $CXXFLAGS" 273 274[ "$0" = "${BASH_SOURCE[0]}" ] && exit 0 || return 0 275