1*4d6fc14bSjoerg#!/usr/bin/env bash 2*4d6fc14bSjoerg#===----------------------------------------------------------------------===## 3*4d6fc14bSjoerg# 4*4d6fc14bSjoerg# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5*4d6fc14bSjoerg# See https://llvm.org/LICENSE.txt for license information. 6*4d6fc14bSjoerg# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7*4d6fc14bSjoerg# 8*4d6fc14bSjoerg#===----------------------------------------------------------------------===## 9*4d6fc14bSjoerg 10*4d6fc14bSjoergset -e 11*4d6fc14bSjoerg 12*4d6fc14bSjoergPROGNAME="$(basename "${0}")" 13*4d6fc14bSjoerg 14*4d6fc14bSjoergfunction error() { printf "error: %s\n" "$*"; exit 1; } 15*4d6fc14bSjoerg 16*4d6fc14bSjoergfunction usage() { 17*4d6fc14bSjoergcat <<EOF 18*4d6fc14bSjoergUsage: 19*4d6fc14bSjoerg${PROGNAME} [options] 20*4d6fc14bSjoerg 21*4d6fc14bSjoerg[-h|--help] Display this help and exit. 22*4d6fc14bSjoerg 23*4d6fc14bSjoerg--llvm-root <DIR> Path to the root of the LLVM monorepo. Only the libcxx 24*4d6fc14bSjoerg and libcxxabi directories are required. 25*4d6fc14bSjoerg 26*4d6fc14bSjoerg--build-dir <DIR> Path to the directory to use for building. This will 27*4d6fc14bSjoerg contain intermediate build products. 28*4d6fc14bSjoerg 29*4d6fc14bSjoerg--install-dir <DIR> Path to the directory to install the library to. 30*4d6fc14bSjoerg 31*4d6fc14bSjoerg--symbols-dir <DIR> Path to the directory to install the .dSYM bundle to. 32*4d6fc14bSjoerg 33*4d6fc14bSjoerg--sdk <SDK> SDK used for building the library. This represents 34*4d6fc14bSjoerg the target platform that the library will run on. 35*4d6fc14bSjoerg You can get a list of SDKs with \`xcodebuild -showsdks\`. 36*4d6fc14bSjoerg 37*4d6fc14bSjoerg--architectures "<arch>..." A whitespace separated list of architectures to build for. 38*4d6fc14bSjoerg The library will be built for each architecture independently, 39*4d6fc14bSjoerg and a universal binary containing all architectures will be 40*4d6fc14bSjoerg created from that. 41*4d6fc14bSjoerg 42*4d6fc14bSjoerg--version X[.Y[.Z]] The version of the library to encode in the dylib. 43*4d6fc14bSjoerg 44*4d6fc14bSjoerg--cache <PATH> The CMake cache to use to control how the library gets built. 45*4d6fc14bSjoergEOF 46*4d6fc14bSjoerg} 47*4d6fc14bSjoerg 48*4d6fc14bSjoergwhile [[ $# -gt 0 ]]; do 49*4d6fc14bSjoerg case ${1} in 50*4d6fc14bSjoerg -h|--help) 51*4d6fc14bSjoerg usage 52*4d6fc14bSjoerg exit 0 53*4d6fc14bSjoerg ;; 54*4d6fc14bSjoerg --llvm-root) 55*4d6fc14bSjoerg llvm_root="${2}" 56*4d6fc14bSjoerg shift; shift 57*4d6fc14bSjoerg ;; 58*4d6fc14bSjoerg --build-dir) 59*4d6fc14bSjoerg build_dir="${2}" 60*4d6fc14bSjoerg shift; shift 61*4d6fc14bSjoerg ;; 62*4d6fc14bSjoerg --symbols-dir) 63*4d6fc14bSjoerg symbols_dir="${2}" 64*4d6fc14bSjoerg shift; shift 65*4d6fc14bSjoerg ;; 66*4d6fc14bSjoerg --install-dir) 67*4d6fc14bSjoerg install_dir="${2}" 68*4d6fc14bSjoerg shift; shift 69*4d6fc14bSjoerg ;; 70*4d6fc14bSjoerg --sdk) 71*4d6fc14bSjoerg sdk="${2}" 72*4d6fc14bSjoerg shift; shift 73*4d6fc14bSjoerg ;; 74*4d6fc14bSjoerg --architectures) 75*4d6fc14bSjoerg architectures="${2}" 76*4d6fc14bSjoerg shift; shift 77*4d6fc14bSjoerg ;; 78*4d6fc14bSjoerg --version) 79*4d6fc14bSjoerg version="${2}" 80*4d6fc14bSjoerg shift; shift 81*4d6fc14bSjoerg ;; 82*4d6fc14bSjoerg --cache) 83*4d6fc14bSjoerg cache="${2}" 84*4d6fc14bSjoerg shift; shift 85*4d6fc14bSjoerg ;; 86*4d6fc14bSjoerg *) 87*4d6fc14bSjoerg error "Unknown argument '${1}'" 88*4d6fc14bSjoerg ;; 89*4d6fc14bSjoerg esac 90*4d6fc14bSjoergdone 91*4d6fc14bSjoerg 92*4d6fc14bSjoergfor arg in llvm_root build_dir symbols_dir install_dir sdk architectures version cache; do 93*4d6fc14bSjoerg if [ -z ${!arg+x} ]; then 94*4d6fc14bSjoerg error "Missing required argument '--${arg//_/-}'" 95*4d6fc14bSjoerg elif [ "${!arg}" == "" ]; then 96*4d6fc14bSjoerg error "Argument to --${arg//_/-} must not be empty" 97*4d6fc14bSjoerg fi 98*4d6fc14bSjoergdone 99*4d6fc14bSjoerg 100*4d6fc14bSjoerg# Allow using relative paths 101*4d6fc14bSjoergfunction realpath() { 102*4d6fc14bSjoerg if [[ $1 = /* ]]; then echo "$1"; else echo "$(pwd)/${1#./}"; fi 103*4d6fc14bSjoerg} 104*4d6fc14bSjoergfor arg in llvm_root build_dir symbols_dir install_dir cache; do 105*4d6fc14bSjoerg path="$(realpath "${!arg}")" 106*4d6fc14bSjoerg eval "${arg}=\"${path}\"" 107*4d6fc14bSjoergdone 108*4d6fc14bSjoerg 109*4d6fc14bSjoergfunction step() { 110*4d6fc14bSjoerg separator="$(printf "%0.s-" $(seq 1 ${#1}))" 111*4d6fc14bSjoerg echo 112*4d6fc14bSjoerg echo "${separator}" 113*4d6fc14bSjoerg echo "${1}" 114*4d6fc14bSjoerg echo "${separator}" 115*4d6fc14bSjoerg} 116*4d6fc14bSjoerg 117*4d6fc14bSjoerginstall_name_dir="/usr/lib" 118*4d6fc14bSjoergdylib_name="libc++.1.dylib" 119*4d6fc14bSjoergmake_symlink="yes" 120*4d6fc14bSjoergheaders_prefix="${install_dir}" 121*4d6fc14bSjoerg 122*4d6fc14bSjoergfor arch in ${architectures}; do 123*4d6fc14bSjoerg step "Building libc++.dylib and libc++abi.dylib for architecture ${arch}" 124*4d6fc14bSjoerg mkdir -p "${build_dir}/${arch}" 125*4d6fc14bSjoerg (cd "${build_dir}/${arch}" && 126*4d6fc14bSjoerg xcrun --sdk "${sdk}" cmake "${llvm_root}/libcxx/utils/ci/runtimes" \ 127*4d6fc14bSjoerg -GNinja \ 128*4d6fc14bSjoerg -DCMAKE_MAKE_PROGRAM="$(xcrun --sdk "${sdk}" --find ninja)" \ 129*4d6fc14bSjoerg -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi" \ 130*4d6fc14bSjoerg -C "${cache}" \ 131*4d6fc14bSjoerg -DCMAKE_INSTALL_PREFIX="${build_dir}/${arch}-install" \ 132*4d6fc14bSjoerg -DCMAKE_INSTALL_NAME_DIR="${install_name_dir}" \ 133*4d6fc14bSjoerg -DCMAKE_OSX_ARCHITECTURES="${arch}" \ 134*4d6fc14bSjoerg -DLIBCXXABI_LIBRARY_VERSION="${version}" \ 135*4d6fc14bSjoerg -DLIBCXX_INCLUDE_BENCHMARKS=OFF \ 136*4d6fc14bSjoerg -DLIBCXX_INCLUDE_TESTS=OFF 137*4d6fc14bSjoerg ) 138*4d6fc14bSjoerg 139*4d6fc14bSjoerg xcrun --sdk "${sdk}" cmake --build "${build_dir}/${arch}" --target install-cxx install-cxxabi -- -v 140*4d6fc14bSjoergdone 141*4d6fc14bSjoerg 142*4d6fc14bSjoergfunction universal_dylib() { 143*4d6fc14bSjoerg dylib=${1} 144*4d6fc14bSjoerg 145*4d6fc14bSjoerg inputs=$(for arch in ${architectures}; do echo "${build_dir}/${arch}-install/lib/${dylib}"; done) 146*4d6fc14bSjoerg 147*4d6fc14bSjoerg step "Creating a universal dylib ${dylib} from the dylibs for all architectures" 148*4d6fc14bSjoerg xcrun --sdk "${sdk}" lipo -create ${inputs} -output "${build_dir}/${dylib}" 149*4d6fc14bSjoerg 150*4d6fc14bSjoerg step "Installing the (stripped) universal dylib to ${install_dir}/usr/lib" 151*4d6fc14bSjoerg mkdir -p "${install_dir}/usr/lib" 152*4d6fc14bSjoerg cp "${build_dir}/${dylib}" "${install_dir}/usr/lib/${dylib}" 153*4d6fc14bSjoerg xcrun --sdk "${sdk}" strip -S "${install_dir}/usr/lib/${dylib}" 154*4d6fc14bSjoerg 155*4d6fc14bSjoerg step "Installing the unstripped dylib and the dSYM bundle to ${symbols_dir}" 156*4d6fc14bSjoerg xcrun --sdk "${sdk}" dsymutil "${build_dir}/${dylib}" -o "${symbols_dir}/${dylib}.dSYM" 157*4d6fc14bSjoerg cp "${build_dir}/${dylib}" "${symbols_dir}/${dylib}" 158*4d6fc14bSjoerg} 159*4d6fc14bSjoerg 160*4d6fc14bSjoerguniversal_dylib ${dylib_name} 161*4d6fc14bSjoerguniversal_dylib libc++abi.dylib 162*4d6fc14bSjoerg 163*4d6fc14bSjoergif [[ "${make_symlink}" == "yes" ]]; then 164*4d6fc14bSjoerg (cd "${install_dir}/usr/lib" && ln -s "${dylib_name}" libc++.dylib) 165*4d6fc14bSjoergfi 166*4d6fc14bSjoerg 167*4d6fc14bSjoerg# Install the headers by copying the headers from one of the built architectures 168*4d6fc14bSjoerg# into the install directory. Headers from all architectures should be the same. 169*4d6fc14bSjoergstep "Installing the libc++ and libc++abi headers to ${headers_prefix}/usr/include" 170*4d6fc14bSjoergany_arch=$(echo ${architectures} | cut -d ' ' -f 1) 171*4d6fc14bSjoergmkdir -p "${headers_prefix}/usr/include" 172*4d6fc14bSjoergditto "${build_dir}/${any_arch}-install/include" "${headers_prefix}/usr/include" 173*4d6fc14bSjoergditto "${llvm_root}/libcxxabi/include" "${headers_prefix}/usr/include" # TODO: libcxxabi should install its headers in CMake 174*4d6fc14bSjoergif [[ $EUID -eq 0 ]]; then # Only chown if we're running as root 175*4d6fc14bSjoerg chown -R root:wheel "${headers_prefix}/usr/include" 176*4d6fc14bSjoergfi 177*4d6fc14bSjoerg 178*4d6fc14bSjoergstep "Installing the libc++ and libc++abi licenses" 179*4d6fc14bSjoergmkdir -p "${headers_prefix}/usr/local/OpenSourceLicenses" 180*4d6fc14bSjoergcp "${llvm_root}/libcxx/LICENSE.TXT" "${headers_prefix}/usr/local/OpenSourceLicenses/libcxx.txt" 181*4d6fc14bSjoergcp "${llvm_root}/libcxxabi/LICENSE.TXT" "${headers_prefix}/usr/local/OpenSourceLicenses/libcxxabi.txt" 182*4d6fc14bSjoerg 183*4d6fc14bSjoerg# Also install a static archive for libc++abi 184*4d6fc14bSjoerglibcxxabi_archives=$(for arch in ${architectures}; do echo "${build_dir}/${arch}-install/lib/libc++abi.a"; done) 185*4d6fc14bSjoergstep "Creating a universal libc++abi static archive from the static archives for each architecture" 186*4d6fc14bSjoergmkdir -p "${install_dir}/usr/local/lib/libcxx" 187*4d6fc14bSjoergxcrun --sdk "${sdk}" libtool -static ${libcxxabi_archives} -o "${install_dir}/usr/local/lib/libcxx/libc++abi-static.a" 188