1037e7968Spatrick#!/usr/bin/env bash 2037e7968Spatrick#===----------------------------------------------------------------------===## 3037e7968Spatrick# 4037e7968Spatrick# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5037e7968Spatrick# See https://llvm.org/LICENSE.txt for license information. 6037e7968Spatrick# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7037e7968Spatrick# 8037e7968Spatrick#===----------------------------------------------------------------------===## 9037e7968Spatrick 10037e7968Spatrickset -e 11037e7968Spatrick 12037e7968SpatrickPROGNAME="$(basename "${0}")" 13037e7968Spatrick 14037e7968Spatrickfunction error() { printf "error: %s\n" "$*"; exit 1; } 15037e7968Spatrick 16037e7968Spatrickfunction usage() { 17037e7968Spatrickcat <<EOF 18037e7968SpatrickUsage: 19037e7968Spatrick${PROGNAME} [options] 20037e7968Spatrick 21037e7968Spatrick[-h|--help] Display this help and exit. 22037e7968Spatrick 2376d0caaeSpatrick--llvm-root <DIR> Path to the root of the LLVM monorepo. Only the libcxx 24037e7968Spatrick and libcxxabi directories are required. 25037e7968Spatrick 2676d0caaeSpatrick--build-dir <DIR> Path to the directory to use for building. This will 27037e7968Spatrick contain intermediate build products. 28037e7968Spatrick 2976d0caaeSpatrick--install-dir <DIR> Path to the directory to install the library to. 30037e7968Spatrick 3176d0caaeSpatrick--symbols-dir <DIR> Path to the directory to install the .dSYM bundle to. 32037e7968Spatrick 33037e7968Spatrick--architectures "<arch>..." A whitespace separated list of architectures to build for. 34037e7968Spatrick The library will be built for each architecture independently, 35037e7968Spatrick and a universal binary containing all architectures will be 36037e7968Spatrick created from that. 37037e7968Spatrick 38*4bdff4beSrobert--headers-only Only install the header part of the library -- don't actually 39*4bdff4beSrobert build the full library. 40*4bdff4beSrobert 41037e7968Spatrick--version X[.Y[.Z]] The version of the library to encode in the dylib. 42037e7968SpatrickEOF 43037e7968Spatrick} 44037e7968Spatrick 45037e7968Spatrickwhile [[ $# -gt 0 ]]; do 46037e7968Spatrick case ${1} in 47037e7968Spatrick -h|--help) 48037e7968Spatrick usage 49037e7968Spatrick exit 0 50037e7968Spatrick ;; 51037e7968Spatrick --llvm-root) 52037e7968Spatrick llvm_root="${2}" 53037e7968Spatrick shift; shift 54037e7968Spatrick ;; 55037e7968Spatrick --build-dir) 56037e7968Spatrick build_dir="${2}" 57037e7968Spatrick shift; shift 58037e7968Spatrick ;; 59037e7968Spatrick --symbols-dir) 60037e7968Spatrick symbols_dir="${2}" 61037e7968Spatrick shift; shift 62037e7968Spatrick ;; 63037e7968Spatrick --install-dir) 64037e7968Spatrick install_dir="${2}" 65037e7968Spatrick shift; shift 66037e7968Spatrick ;; 67037e7968Spatrick --architectures) 68037e7968Spatrick architectures="${2}" 69037e7968Spatrick shift; shift 70037e7968Spatrick ;; 71*4bdff4beSrobert --headers-only) 72*4bdff4beSrobert headers_only=true 73*4bdff4beSrobert shift 74*4bdff4beSrobert ;; 75037e7968Spatrick --version) 76037e7968Spatrick version="${2}" 77037e7968Spatrick shift; shift 78037e7968Spatrick ;; 79037e7968Spatrick *) 80037e7968Spatrick error "Unknown argument '${1}'" 81037e7968Spatrick ;; 82037e7968Spatrick esac 83037e7968Spatrickdone 84037e7968Spatrick 85*4bdff4beSrobertfor arg in llvm_root build_dir symbols_dir install_dir architectures version; do 86037e7968Spatrick if [ -z ${!arg+x} ]; then 87037e7968Spatrick error "Missing required argument '--${arg//_/-}'" 88037e7968Spatrick elif [ "${!arg}" == "" ]; then 89037e7968Spatrick error "Argument to --${arg//_/-} must not be empty" 90037e7968Spatrick fi 91037e7968Spatrickdone 92037e7968Spatrick 9376d0caaeSpatrick# Allow using relative paths 9476d0caaeSpatrickfunction realpath() { 9576d0caaeSpatrick if [[ $1 = /* ]]; then echo "$1"; else echo "$(pwd)/${1#./}"; fi 9676d0caaeSpatrick} 9776d0caaeSpatrickfor arg in llvm_root build_dir symbols_dir install_dir; do 9876d0caaeSpatrick path="$(realpath "${!arg}")" 9976d0caaeSpatrick eval "${arg}=\"${path}\"" 10076d0caaeSpatrickdone 10176d0caaeSpatrick 102037e7968Spatrickfunction step() { 103037e7968Spatrick separator="$(printf "%0.s-" $(seq 1 ${#1}))" 104037e7968Spatrick echo 105037e7968Spatrick echo "${separator}" 106037e7968Spatrick echo "${1}" 107037e7968Spatrick echo "${separator}" 108037e7968Spatrick} 109037e7968Spatrick 110037e7968Spatrickfor arch in ${architectures}; do 111037e7968Spatrick step "Building libc++.dylib and libc++abi.dylib for architecture ${arch}" 112037e7968Spatrick mkdir -p "${build_dir}/${arch}" 113*4bdff4beSrobert xcrun cmake -S "${llvm_root}/runtimes" \ 114*4bdff4beSrobert -B "${build_dir}/${arch}" \ 115037e7968Spatrick -GNinja \ 116*4bdff4beSrobert -DCMAKE_MAKE_PROGRAM="$(xcrun --find ninja)" \ 11776d0caaeSpatrick -C "${llvm_root}/libcxx/cmake/caches/Apple.cmake" \ 118*4bdff4beSrobert -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ 119037e7968Spatrick -DCMAKE_INSTALL_PREFIX="${build_dir}/${arch}-install" \ 12076d0caaeSpatrick -DCMAKE_INSTALL_NAME_DIR="/usr/lib" \ 121037e7968Spatrick -DCMAKE_OSX_ARCHITECTURES="${arch}" \ 122*4bdff4beSrobert -DLIBCXXABI_LIBRARY_VERSION="${version}" 123037e7968Spatrick 124*4bdff4beSrobert if [ "$headers_only" = true ]; then 125*4bdff4beSrobert xcrun cmake --build "${build_dir}/${arch}" --target install-cxx-headers install-cxxabi-headers -- -v 126*4bdff4beSrobert else 127*4bdff4beSrobert xcrun cmake --build "${build_dir}/${arch}" --target install-cxx install-cxxabi -- -v 128*4bdff4beSrobert fi 129037e7968Spatrickdone 130037e7968Spatrick 131037e7968Spatrickfunction universal_dylib() { 132037e7968Spatrick dylib=${1} 133037e7968Spatrick 134037e7968Spatrick inputs=$(for arch in ${architectures}; do echo "${build_dir}/${arch}-install/lib/${dylib}"; done) 135037e7968Spatrick 136037e7968Spatrick step "Creating a universal dylib ${dylib} from the dylibs for all architectures" 137*4bdff4beSrobert xcrun lipo -create ${inputs} -output "${build_dir}/${dylib}" 138037e7968Spatrick 139037e7968Spatrick step "Installing the (stripped) universal dylib to ${install_dir}/usr/lib" 140037e7968Spatrick mkdir -p "${install_dir}/usr/lib" 141037e7968Spatrick cp "${build_dir}/${dylib}" "${install_dir}/usr/lib/${dylib}" 142*4bdff4beSrobert xcrun strip -S "${install_dir}/usr/lib/${dylib}" 143037e7968Spatrick 144037e7968Spatrick step "Installing the unstripped dylib and the dSYM bundle to ${symbols_dir}" 145*4bdff4beSrobert xcrun dsymutil "${build_dir}/${dylib}" -o "${symbols_dir}/${dylib}.dSYM" 146037e7968Spatrick cp "${build_dir}/${dylib}" "${symbols_dir}/${dylib}" 147037e7968Spatrick} 148037e7968Spatrick 149*4bdff4beSrobertif [ "$headers_only" != true ]; then 15076d0caaeSpatrick universal_dylib libc++.1.dylib 151037e7968Spatrick universal_dylib libc++abi.dylib 15276d0caaeSpatrick (cd "${install_dir}/usr/lib" && ln -s "libc++.1.dylib" libc++.dylib) 153*4bdff4beSrobertfi 154037e7968Spatrick 155037e7968Spatrick# Install the headers by copying the headers from one of the built architectures 156037e7968Spatrick# into the install directory. Headers from all architectures should be the same. 15776d0caaeSpatrickstep "Installing the libc++ and libc++abi headers to ${install_dir}/usr/include" 158037e7968Spatrickany_arch=$(echo ${architectures} | cut -d ' ' -f 1) 15976d0caaeSpatrickmkdir -p "${install_dir}/usr/include" 16076d0caaeSpatrickditto "${build_dir}/${any_arch}-install/include" "${install_dir}/usr/include" 161037e7968Spatrickif [[ $EUID -eq 0 ]]; then # Only chown if we're running as root 16276d0caaeSpatrick chown -R root:wheel "${install_dir}/usr/include" 163037e7968Spatrickfi 164037e7968Spatrick 165*4bdff4beSrobertif [ "$headers_only" != true ]; then 166037e7968Spatrick step "Installing the libc++ and libc++abi licenses" 16776d0caaeSpatrick mkdir -p "${install_dir}/usr/local/OpenSourceLicenses" 16876d0caaeSpatrick cp "${llvm_root}/libcxx/LICENSE.TXT" "${install_dir}/usr/local/OpenSourceLicenses/libcxx.txt" 16976d0caaeSpatrick cp "${llvm_root}/libcxxabi/LICENSE.TXT" "${install_dir}/usr/local/OpenSourceLicenses/libcxxabi.txt" 170037e7968Spatrick 17176d0caaeSpatrick # Also install universal static archives for libc++ and libc++abi 17276d0caaeSpatrick libcxx_archives=$(for arch in ${architectures}; do echo "${build_dir}/${arch}-install/lib/libc++.a"; done) 173037e7968Spatrick libcxxabi_archives=$(for arch in ${architectures}; do echo "${build_dir}/${arch}-install/lib/libc++abi.a"; done) 17476d0caaeSpatrick step "Creating universal static archives for libc++ and libc++abi from the static archives for each architecture" 175037e7968Spatrick mkdir -p "${install_dir}/usr/local/lib/libcxx" 176*4bdff4beSrobert xcrun libtool -static ${libcxx_archives} -o "${install_dir}/usr/local/lib/libcxx/libc++-static.a" 177*4bdff4beSrobert xcrun libtool -static ${libcxxabi_archives} -o "${install_dir}/usr/local/lib/libcxx/libc++abi-static.a" 178*4bdff4beSrobertfi 179