1#!/usr/bin/env bash 2#===----------------------------------------------------------------------===## 3# 4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5# See https://llvm.org/LICENSE.txt for license information. 6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7# 8#===----------------------------------------------------------------------===## 9 10set -ex 11set -o pipefail 12unset LANG 13unset LC_ALL 14unset LC_COLLATE 15 16PROGNAME="$(basename "${0}")" 17 18function usage() { 19cat <<EOF 20Usage: 21${PROGNAME} [options] <BUILDER> 22 23[-h|--help] Display this help and exit. 24 25--llvm-root <DIR> Path to the root of the LLVM monorepo. By default, we try 26 to figure it out based on the current working directory. 27 28--build-dir <DIR> The directory to use for building the library. By default, 29 this is '<llvm-root>/build/<builder>'. 30 31--osx-roots <DIR> Path to pre-downloaded macOS dylibs. By default, we download 32 them from Green Dragon. This is only relevant at all when 33 running back-deployment testing if one wants to override 34 the old dylibs we use to run the tests with different ones. 35EOF 36} 37 38while [[ $# -gt 0 ]]; do 39 case ${1} in 40 -h|--help) 41 usage 42 exit 0 43 ;; 44 --llvm-root) 45 MONOREPO_ROOT="${2}" 46 shift; shift 47 ;; 48 --build-dir) 49 BUILD_DIR="${2}" 50 shift; shift 51 ;; 52 --osx-roots) 53 OSX_ROOTS="${2}" 54 shift; shift 55 ;; 56 *) 57 BUILDER="${1}" 58 shift 59 ;; 60 esac 61done 62 63MONOREPO_ROOT="${MONOREPO_ROOT:="$(git rev-parse --show-toplevel)"}" 64BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build/${BUILDER}}" 65INSTALL_DIR="${BUILD_DIR}/install" 66 67# If we can find Ninja/CMake provided by Xcode, use those since we know their 68# version will generally work with the Clang shipped in Xcode (e.g. if Clang 69# knows about -std=c++20, the CMake bundled in Xcode will probably know about 70# that flag too). 71if xcrun --find ninja &>/dev/null; then NINJA="$(xcrun --find ninja)"; else NINJA="ninja"; fi 72if xcrun --find cmake &>/dev/null; then CMAKE="$(xcrun --find cmake)"; else CMAKE="cmake"; fi 73 74function clean() { 75 rm -rf "${BUILD_DIR}" 76} 77 78function generate-cmake-base() { 79 echo "--- Generating CMake" 80 ${CMAKE} \ 81 -B "${BUILD_DIR}" \ 82 -GNinja -DCMAKE_MAKE_PROGRAM="${NINJA}" \ 83 -DCMAKE_BUILD_TYPE=RelWithDebInfo \ 84 -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ 85 -DLLVM_LIT_ARGS="-sv --show-unsupported --xunit-xml-output test-results.xml" \ 86 "${@}" 87} 88 89function generate-cmake() { 90 generate-cmake-base \ 91 -S "${MONOREPO_ROOT}/llvm" \ 92 -DLLVM_ENABLE_PROJECTS="libcxx;libunwind;libcxxabi" \ 93 -DLIBCXX_CXX_ABI=libcxxabi \ 94 "${@}" 95} 96 97function generate-cmake-libcxx-win() { 98 # TODO: Clang-cl in MSVC configurations don't have access to compiler_rt 99 # builtins helpers for int128 division. See 100 # https://reviews.llvm.org/D91139#2429595 for a comment about longterm 101 # intent for handling the issue. In the meantime, define 102 # -D_LIBCPP_HAS_NO_INT128 (both when building the library itself and 103 # when building tests) to allow enabling filesystem for running tests, 104 # even if it uses a non-permanent ABI. 105 106 generate-cmake-base \ 107 -S "${MONOREPO_ROOT}/libcxx" \ 108 -DCMAKE_C_COMPILER=clang-cl \ 109 -DCMAKE_CXX_COMPILER=clang-cl \ 110 -DLIBCXX_ENABLE_FILESYSTEM=YES \ 111 -DCMAKE_CXX_FLAGS="-D_LIBCPP_HAS_NO_INT128" \ 112 -DLIBCXX_TEST_COMPILER_FLAGS="-D_LIBCPP_HAS_NO_INT128" \ 113 "${@}" 114} 115 116function check-cxx-cxxabi() { 117 echo "--- Installing libc++ and libc++abi to a fake location" 118 ${NINJA} -vC "${BUILD_DIR}" install-cxx install-cxxabi 119 120 echo "+++ Running the libc++ tests" 121 ${NINJA} -vC "${BUILD_DIR}" check-cxx 122 123 echo "+++ Running the libc++abi tests" 124 ${NINJA} -vC "${BUILD_DIR}" check-cxxabi 125} 126 127# TODO: The goal is to test this against all configurations. We should also move 128# this to the Lit test suite instead of being a separate CMake target. 129function check-abi-list() { 130 echo "+++ Running the libc++ ABI list test" 131 ${NINJA} -vC "${BUILD_DIR}" check-cxx-abilist || ( 132 echo "+++ Generating the libc++ ABI list after failed check" 133 ${NINJA} -vC "${BUILD_DIR}" generate-cxx-abilist 134 false 135 ) 136} 137 138function check-cxx-benchmarks() { 139 echo "--- Running the benchmarks" 140 ${NINJA} -vC "${BUILD_DIR}" check-cxx-benchmarks 141} 142 143# Print the version of a few tools to aid diagnostics in some cases 144${CMAKE} --version 145${NINJA} --version 146 147case "${BUILDER}" in 148check-format) 149 clean 150 echo "+++ Checking formatting" 151 # We need to set --extensions so that clang-format checks extensionless files. 152 mkdir -p ${BUILD_DIR} 153 git-clang-format \ 154 --binary /usr/bin/clang-format --diff \ 155 --extensions ',h,hh,hpp,hxx,c,cc,cxx,cpp' HEAD~1 \ 156 -- \ 157 libcxx/{benchmarks,include,src,test} \ 158 libcxxabi/{fuzz,include,src,test} \ 159 | tee ${BUILD_DIR}/clang-format.patch 160 # Check if the diff is empty, fail otherwise. 161 ! grep -q '^--- a' ${BUILD_DIR}/clang-format.patch 162;; 163check-generated-output) 164 # `! foo` doesn't work properly with `set -e`, use `! foo || false` instead. 165 # https://stackoverflow.com/questions/57681955/set-e-does-not-respect-logical-not 166 clean 167 echo "+++ Checking the output of the generator scripts" 168 mkdir -p ${BUILD_DIR} 169 # Reject patches that don't update the generated output correctly. 170 python3 libcxx/utils/generate_feature_test_macro_components.py 171 python3 libcxx/utils/generate_header_inclusion_tests.py 172 python3 libcxx/utils/generate_header_tests.py 173 git diff | tee ${BUILD_DIR}/generated_output.patch 174 # Check if the diffs are empty, fail otherwise. 175 ! grep -q '^--- a' ${BUILD_DIR}/generated_output.patch || false 176 # Reject patches that introduce non-ASCII characters or hard tabs. 177 # Depends on LC_COLLATE set at the top of this script. 178 ! grep -rn '[^ -~]' libcxx/include/ || false 179 # Check that no dependency cycles have been introduced. 180 python3 libcxx/utils/graph_header_deps.py >/dev/null 181;; 182generic-cxx03) 183 export CC=clang 184 export CXX=clang++ 185 clean 186 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-cxx03.cmake" \ 187 -DLIBCXX_TEST_CONFIG="${MONOREPO_ROOT}/libcxx/test/configs/libcxx-trunk-shared.cfg.in" 188 check-cxx-cxxabi 189 check-abi-list 190;; 191generic-cxx11) 192 export CC=clang 193 export CXX=clang++ 194 clean 195 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-cxx11.cmake" \ 196 -DLIBCXX_TEST_CONFIG="${MONOREPO_ROOT}/libcxx/test/configs/libcxx-trunk-shared.cfg.in" 197 check-cxx-cxxabi 198 check-abi-list 199;; 200generic-cxx14) 201 export CC=clang 202 export CXX=clang++ 203 clean 204 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-cxx14.cmake" \ 205 -DLIBCXX_TEST_CONFIG="${MONOREPO_ROOT}/libcxx/test/configs/libcxx-trunk-shared.cfg.in" 206 check-cxx-cxxabi 207 check-abi-list 208;; 209generic-cxx17) 210 export CC=clang 211 export CXX=clang++ 212 clean 213 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-cxx17.cmake" \ 214 -DLIBCXX_TEST_CONFIG="${MONOREPO_ROOT}/libcxx/test/configs/libcxx-trunk-shared.cfg.in" 215 check-cxx-cxxabi 216 check-abi-list 217;; 218generic-cxx20) 219 export CC=clang 220 export CXX=clang++ 221 clean 222 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-cxx20.cmake" \ 223 -DLIBCXX_TEST_CONFIG="${MONOREPO_ROOT}/libcxx/test/configs/libcxx-trunk-shared.cfg.in" 224 check-cxx-cxxabi 225 check-abi-list 226;; 227generic-cxx2b) 228 export CC=clang-tot 229 export CXX=clang++-tot 230 clean 231 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-cxx2b.cmake" \ 232 -DLIBCXX_TEST_CONFIG="${MONOREPO_ROOT}/libcxx/test/configs/libcxx-trunk-shared.cfg.in" 233 check-cxx-cxxabi 234 check-abi-list 235;; 236generic-debug-iterators) 237 export CC=clang-tot 238 export CXX=clang++-tot 239 clean 240 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-debug-iterators.cmake" 241 check-cxx-cxxabi 242 check-abi-list 243;; 244generic-noexceptions) 245 export CC=clang 246 export CXX=clang++ 247 clean 248 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-noexceptions.cmake" 249 check-cxx-cxxabi 250;; 251generic-static) 252 export CC=clang 253 export CXX=clang++ 254 clean 255 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-static.cmake" \ 256 -DLIBCXX_TEST_CONFIG="${MONOREPO_ROOT}/libcxx/test/configs/libcxx-trunk-static.cfg.in" 257 check-cxx-cxxabi 258;; 259generic-32bit) 260 export CC=clang 261 export CXX=clang++ 262 clean 263 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-32bits.cmake" 264 check-cxx-cxxabi 265;; 266generic-gcc) 267 export CC=gcc 268 export CXX=g++ 269 clean 270 generate-cmake 271 check-cxx-cxxabi 272;; 273generic-asan) 274 export CC=clang 275 export CXX=clang++ 276 clean 277 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-asan.cmake" 278 check-cxx-cxxabi 279;; 280generic-msan) 281 export CC=clang 282 export CXX=clang++ 283 clean 284 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-msan.cmake" 285 check-cxx-cxxabi 286;; 287generic-tsan) 288 export CC=clang 289 export CXX=clang++ 290 clean 291 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-tsan.cmake" 292 check-cxx-cxxabi 293;; 294generic-ubsan) 295 export CC=clang 296 export CXX=clang++ 297 clean 298 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-ubsan.cmake" 299 check-cxx-cxxabi 300;; 301generic-with_llvm_unwinder) 302 export CC=clang 303 export CXX=clang++ 304 clean 305 generate-cmake -DLIBCXXABI_USE_LLVM_UNWINDER=ON 306 check-cxx-cxxabi 307;; 308generic-singlethreaded) 309 export CC=clang 310 export CXX=clang++ 311 clean 312 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-singlethreaded.cmake" 313 check-cxx-cxxabi 314;; 315generic-no-debug) 316 export CC=clang 317 export CXX=clang++ 318 clean 319 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-debug.cmake" 320 check-cxx-cxxabi 321;; 322generic-no-filesystem) 323 export CC=clang 324 export CXX=clang++ 325 clean 326 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-filesystem.cmake" 327 check-cxx-cxxabi 328;; 329generic-no-random_device) 330 export CC=clang 331 export CXX=clang++ 332 clean 333 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-random_device.cmake" 334 check-cxx-cxxabi 335;; 336generic-no-localization) 337 export CC=clang 338 export CXX=clang++ 339 clean 340 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-no-localization.cmake" 341 check-cxx-cxxabi 342;; 343x86_64-apple-system) 344 export CC=clang 345 export CXX=clang++ 346 clean 347 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Apple.cmake" 348 check-cxx-cxxabi 349;; 350x86_64-apple-system-noexceptions) 351 export CC=clang 352 export CXX=clang++ 353 clean 354 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Apple.cmake" \ 355 -DLIBCXX_ENABLE_EXCEPTIONS=OFF \ 356 -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF 357 check-cxx-cxxabi 358;; 359x86_64-apple-system-backdeployment-*) 360 clean 361 362 if [[ "${OSX_ROOTS}" == "" ]]; then 363 echo "--- Downloading previous macOS dylibs" 364 PREVIOUS_DYLIBS_URL="https://dl.dropboxusercontent.com/s/liu4fmc53qzlfly/libcxx-roots.tar.gz" 365 OSX_ROOTS="${BUILD_DIR}/macos-roots" 366 mkdir -p "${OSX_ROOTS}" 367 curl "${PREVIOUS_DYLIBS_URL}" | tar -xz --strip-components=1 -C "${OSX_ROOTS}" 368 fi 369 370 DEPLOYMENT_TARGET="${BUILDER#x86_64-apple-system-backdeployment-}" 371 372 # TODO: On Apple platforms, we never produce libc++abi.1.dylib, always libc++abi.dylib. 373 # Fix that in the build so that the tests stop searching for @rpath/libc++abi.1.dylib. 374 cp "${OSX_ROOTS}/macOS/libc++abi/${DEPLOYMENT_TARGET}/libc++abi.dylib" \ 375 "${OSX_ROOTS}/macOS/libc++abi/${DEPLOYMENT_TARGET}/libc++abi.1.dylib" 376 377 PARAMS="target_triple=x86_64-apple-macosx${DEPLOYMENT_TARGET}" 378 PARAMS+=";cxx_runtime_root=${OSX_ROOTS}/macOS/libc++/${DEPLOYMENT_TARGET}" 379 PARAMS+=";abi_runtime_root=${OSX_ROOTS}/macOS/libc++abi/${DEPLOYMENT_TARGET}" 380 PARAMS+=";use_system_cxx_lib=True" 381 382 export CC=clang 383 export CXX=clang++ 384 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Apple.cmake" \ 385 -DLIBCXX_TEST_PARAMS="${PARAMS}" \ 386 -DLIBCXXABI_TEST_PARAMS="${PARAMS}" 387 388 check-cxx-cxxabi 389;; 390benchmarks) 391 export CC=clang 392 export CXX=clang++ 393 clean 394 generate-cmake 395 check-cxx-benchmarks 396;; 397documentation) 398 export CC=clang 399 export CXX=clang++ 400 clean 401 generate-cmake -DLLVM_ENABLE_SPHINX=ON 402 403 echo "+++ Generating documentation" 404 ${NINJA} -vC "${BUILD_DIR}" docs-libcxx-html 405;; 406unified-standalone) 407 export CC=clang 408 export CXX=clang++ 409 410 clean 411 412 echo "--- Generating CMake" 413 ${CMAKE} \ 414 -S "${MONOREPO_ROOT}/libcxx/utils/ci/runtimes" \ 415 -B "${BUILD_DIR}" \ 416 -GNinja -DCMAKE_MAKE_PROGRAM="${NINJA}" \ 417 -DCMAKE_BUILD_TYPE=RelWithDebInfo \ 418 -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ 419 -DLLVM_ENABLE_PROJECTS="libcxx;libcxxabi;libunwind" 420 421 check-cxx-cxxabi 422;; 423runtimes-build) 424 export CC=clang 425 export CXX=clang++ 426 427 clean 428 429 echo "--- Generating CMake" 430 ${CMAKE} \ 431 -S "${MONOREPO_ROOT}/llvm" \ 432 -B "${BUILD_DIR}" \ 433 -GNinja -DCMAKE_MAKE_PROGRAM="${NINJA}" \ 434 -DCMAKE_BUILD_TYPE=RelWithDebInfo \ 435 -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ 436 -DLLVM_ENABLE_PROJECTS="clang" \ 437 -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" \ 438 -DLLVM_RUNTIME_TARGETS="x86_64-unknown-linux-gnu" 439 440 echo "+++ Running the libc++ and libc++abi tests" 441 ${NINJA} -C "${BUILD_DIR}" check-runtimes 442 443 echo "--- Installing libc++ and libc++abi to a fake location" 444 ${NINJA} -C "${BUILD_DIR}" install-cxx install-cxxabi 445;; 446legacy-test-config) 447 export CC=clang 448 export CXX=clang++ 449 clean 450 generate-cmake -DLIBCXX_TEST_CONFIG="${MONOREPO_ROOT}/libcxx/test/configs/legacy.cfg.in" 451 check-cxx-cxxabi 452;; 453legacy-standalone) 454 export CC=clang 455 export CXX=clang++ 456 457 clean 458 459 echo "--- Generating CMake" 460 ${CMAKE} \ 461 -S "${MONOREPO_ROOT}/libcxx" \ 462 -B "${BUILD_DIR}/libcxx" \ 463 -GNinja -DCMAKE_MAKE_PROGRAM="${NINJA}" \ 464 -DCMAKE_BUILD_TYPE=RelWithDebInfo \ 465 -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ 466 -DLLVM_PATH="${MONOREPO_ROOT}/llvm" \ 467 -DLIBCXX_CXX_ABI=libcxxabi \ 468 -DLIBCXX_CXX_ABI_INCLUDE_PATHS="${MONOREPO_ROOT}/libcxxabi/include" \ 469 -DLIBCXX_CXX_ABI_LIBRARY_PATH="${BUILD_DIR}/libcxxabi/lib" 470 471 ${CMAKE} \ 472 -S "${MONOREPO_ROOT}/libcxxabi" \ 473 -B "${BUILD_DIR}/libcxxabi" \ 474 -GNinja -DCMAKE_MAKE_PROGRAM="${NINJA}" \ 475 -DCMAKE_BUILD_TYPE=RelWithDebInfo \ 476 -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \ 477 -DLLVM_PATH="${MONOREPO_ROOT}/llvm" \ 478 -DLIBCXXABI_LIBCXX_PATH="${MONOREPO_ROOT}/libcxx" \ 479 -DLIBCXXABI_LIBCXX_INCLUDES="${BUILD_DIR}/libcxx/include/c++/v1" \ 480 -DLIBCXXABI_LIBCXX_LIBRARY_PATH="${BUILD_DIR}/libcxx/lib" 481 482 echo "+++ Generating libc++ headers" 483 ${NINJA} -vC "${BUILD_DIR}/libcxx" generate-cxx-headers 484 485 echo "+++ Building libc++abi" 486 ${NINJA} -vC "${BUILD_DIR}/libcxxabi" cxxabi 487 488 echo "+++ Building libc++" 489 ${NINJA} -vC "${BUILD_DIR}/libcxx" cxx 490 491 echo "+++ Running the libc++ tests" 492 ${NINJA} -vC "${BUILD_DIR}/libcxx" check-cxx 493 494 echo "+++ Running the libc++abi tests" 495 ${NINJA} -vC "${BUILD_DIR}/libcxxabi" check-cxxabi 496;; 497aarch64) 498 clean 499 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/AArch64.cmake" 500 check-cxx-cxxabi 501;; 502aarch64-noexceptions) 503 clean 504 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/AArch64.cmake" \ 505 -DLIBCXX_ENABLE_EXCEPTIONS=OFF \ 506 -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF 507 check-cxx-cxxabi 508;; 509# Aka Armv8 32 bit 510armv8) 511 clean 512 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Armv8Arm.cmake" 513 check-cxx-cxxabi 514;; 515armv8-noexceptions) 516 clean 517 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Armv8Thumb-noexceptions.cmake" 518 check-cxx-cxxabi 519;; 520# Armv7 32 bit. One building Arm only one Thumb only code. 521armv7) 522 clean 523 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Armv7Arm.cmake" 524 check-cxx-cxxabi 525;; 526armv7-noexceptions) 527 clean 528 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Armv7Thumb-noexceptions.cmake" 529 check-cxx-cxxabi 530;; 531windows-dll) 532 clean 533 # TODO: Currently, building with the experimental library breaks running 534 # tests (the test linking look for the c++experimental library with the 535 # wrong name, and the statically linked c++experimental can't be linked 536 # correctly when libc++ visibility attributes indicate dllimport linkage 537 # anyway), thus just disable the experimental library. Remove this 538 # setting when cmake and the test driver does the right thing automatically. 539 generate-cmake-libcxx-win -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF 540 echo "+++ Running the libc++ tests" 541 ${NINJA} -vC "${BUILD_DIR}" check-cxx 542;; 543windows-static) 544 clean 545 generate-cmake-libcxx-win -DLIBCXX_ENABLE_SHARED=OFF 546 echo "+++ Running the libc++ tests" 547 ${NINJA} -vC "${BUILD_DIR}" check-cxx 548;; 549*) 550 echo "${BUILDER} is not a known configuration" 551 exit 1 552;; 553esac 554