#!/usr/bin/env bash set -euo pipefail repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" tdlib_version="${TDLIB_VERSION:-1.8.29}" tdlib_commit="${TDLIB_COMMIT:-af69dd4397b6dc1bf23ba0fd0bf429fcba6454f6}" tdlib_repo="${TDLIB_REPO:-https://github.com/tdlib/td.git}" source_dir="${TDLIB_SOURCE_DIR:-${repo_root}/.build/tdlib-src}" build_root="${TDLIB_BUILD_ROOT:-${repo_root}/.build/tdlib-ios-build}" output_root="${TDLIB_OUTPUT_ROOT:-${repo_root}/.build/tdlib-ios}" platforms="${TDLIB_IOS_PLATFORMS:-iOS iOS-simulator}" openssl_platforms="${TDLIB_OPENSSL_PLATFORMS:-iOS iOS-simulator}" ios_deployment_target="${TDLIB_IOS_DEPLOYMENT_TARGET:-17.0}" jobs="${TDLIB_BUILD_JOBS:-3}" if [[ -z "${DEVELOPER_DIR:-}" && -d /Applications/Xcode.app/Contents/Developer ]]; then export DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer fi require_tool() { if ! command -v "$1" >/dev/null 2>&1; then printf 'Required tool not found: %s\n' "$1" >&2 return 1 fi } missing=0 for tool in git cmake c++ gperf make perl rsync xcodebuild xcrun install_name_tool; do require_tool "${tool}" || missing=1 done if [[ "${missing}" -ne 0 ]]; then printf '\nInstall missing TDLib build dependencies on macOS with:\n' >&2 printf ' brew install cmake gperf coreutils\n' >&2 exit 1 fi if ! xcrun --sdk iphoneos --show-sdk-path >/dev/null; then printf 'The iphoneos SDK is unavailable through xcrun.\n' >&2 printf 'Set DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer and install the iOS platform in Xcode.\n' >&2 exit 1 fi mkdir -p "$(dirname "${source_dir}")" "${build_root}" "${output_root}" if [[ ! -d "${source_dir}/.git" ]]; then git clone "${tdlib_repo}" "${source_dir}" fi git -C "${source_dir}" fetch --depth 1 origin "${tdlib_commit}" git -C "${source_dir}" checkout --detach "${tdlib_commit}" openssl_root="${source_dir}/example/ios/third_party/openssl" python_apple_support_dir="${source_dir}/example/ios/Python-Apple-support" prepare_python_apple_support() { if [[ ! -d "${python_apple_support_dir}/.git" ]]; then git clone https://github.com/beeware/Python-Apple-support "${python_apple_support_dir}" fi git -C "${python_apple_support_dir}" checkout 6f43aba0ddd5a9f52f39775d0141bd4363614020 git -C "${python_apple_support_dir}" reset --hard ( cd "${python_apple_support_dir}" git apply ../Python-Apple-support.patch # Python-Apple-support at this revision emits apple-ios-simulator-simulator # under newer Xcode SDK naming. Use the base OS name before appending # "-simulator" to the target triple. perl -pi -e 's/apple-\$\$\(OS_LOWER-\$\(target\)\)-simulator/apple-\$\$\(patsubst %-simulator,%,\$\$\(OS_LOWER-\$\(target\)\)\)-simulator/' Makefile ) } prepare_td_auto_sources() { local host_build_dir="${build_root}/build-host-generate" local td_auto_dir="${source_dir}/td/generate/auto/td/telegram" local mime_auto_dir="${source_dir}/tdutils/generate/auto" if [[ -f "${td_auto_dir}/td_api.cpp" \ && -f "${td_auto_dir}/td_api_json.cpp" \ && -f "${mime_auto_dir}/mime_type_to_extension.cpp" \ && -f "${mime_auto_dir}/extension_to_mime_type.cpp" ]]; then return 0 fi ZERO_AR_DATE=1 cmake -S "${source_dir}" -B "${host_build_dir}" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_MAKE_PROGRAM=make cmake --build "${host_build_dir}" --target prepare_cross_compiling -- -j"${jobs}" } prepare_openssl_platform() { local platform="$1" local output_dir="${openssl_root}/${platform}" if [[ -f "${output_dir}/lib/libcrypto.a" && -f "${output_dir}/lib/libssl.a" ]]; then return 0 fi prepare_python_apple_support ( cd "${python_apple_support_dir}" rm -rf "build/${platform}" "install/${platform}" "merge/${platform}" make "OpenSSL-${platform}" ) rm -rf "${output_dir}" mkdir -p "${output_dir}/lib" cp "${python_apple_support_dir}/merge/${platform}/openssl/lib/libcrypto.a" "${output_dir}/lib/" cp "${python_apple_support_dir}/merge/${platform}/openssl/lib/libssl.a" "${output_dir}/lib/" cp -R "${python_apple_support_dir}/merge/${platform}/openssl/include" "${output_dir}/include" } if [[ ! -f "${openssl_root}/iOS/lib/libcrypto.a" || ! -f "${openssl_root}/iOS-simulator/lib/libcrypto.a" ]]; then printf 'OpenSSL for iOS was not found under %s.\n' "${openssl_root}" >&2 printf 'Building only required OpenSSL platforms: %s\n' "${openssl_platforms}" for platform in ${openssl_platforms}; do prepare_openssl_platform "${platform}" done fi prepare_td_auto_sources build_platform() { local td_platform="$1" local ios_platform local out_platform case "${td_platform}" in iOS) ios_platform="OS" out_platform="iphoneos" ;; iOS-simulator) ios_platform="SIMULATOR" out_platform="iphonesimulator" ;; *) printf 'Unsupported TDLib iOS platform: %s\n' "${td_platform}" >&2 return 1 ;; esac local openssl_path="${openssl_root}/${td_platform}" local openssl_crypto_library="${openssl_path}/lib/libcrypto.a" local openssl_ssl_library="${openssl_path}/lib/libssl.a" local build_dir="${build_root}/build-${td_platform}" local install_dir="${build_root}/install-${td_platform}" local output_dir="${output_root}/${out_platform}" if [[ ! -f "${openssl_crypto_library}" || ! -f "${openssl_ssl_library}" ]]; then printf 'OpenSSL libraries are missing for %s under %s\n' "${td_platform}" "${openssl_path}" >&2 return 1 fi rm -rf "${build_dir}" "${install_dir}" "${output_dir}" mkdir -p "${build_dir}" "${install_dir}" "${output_dir}/include" "${output_dir}/lib" ZERO_AR_DATE=1 cmake -S "${source_dir}" -B "${build_dir}" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ -DCMAKE_INSTALL_PREFIX="${install_dir}" \ -DCMAKE_TOOLCHAIN_FILE="${source_dir}/CMake/iOS.cmake" \ -DIOS_PLATFORM="${ios_platform}" \ -DIOS_DEPLOYMENT_TARGET="${ios_deployment_target}" \ -DCMAKE_MAKE_PROGRAM=make \ -DOPENSSL_FOUND=1 \ -DOPENSSL_CRYPTO_LIBRARY="${openssl_crypto_library}" \ -DOPENSSL_SSL_LIBRARY="${openssl_ssl_library}" \ -DOPENSSL_INCLUDE_DIR="${openssl_path}/include" \ -DOPENSSL_LIBRARIES="${openssl_crypto_library};${openssl_ssl_library}" cmake --build "${build_dir}" --target install -- -j"${jobs}" install_name_tool -id @rpath/libtdjson.dylib "${install_dir}/lib/libtdjson.dylib" rsync -a "${install_dir}/include/" "${output_dir}/include/" cp "${install_dir}/lib/libtdjson.dylib" "${output_dir}/lib/libtdjson.dylib" cp "${install_dir}/lib/libtdjson.dylib" "${output_dir}/lib/libtdjson.${tdlib_version}.dylib" printf 'Installed TDLib %s for %s at %s\n' "${tdlib_version}" "${td_platform}" "${output_dir}" } for platform in ${platforms}; do build_platform "${platform}" done