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 10 set -ex 11 set -o pipefail 12 unset LANG 13 unset LC_ALL 14 unset LC_COLLATE 15 16 PROGNAME="$(basename "${0}")" 17 18 function usage() { 19 cat <<EOF 20 Usage: 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. 35 EOF 36 } 37 38 while [[ $# -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 61 done 62 63 MONOREPO_ROOT="${MONOREPO_ROOT:="$(git rev-parse --show-toplevel)"}" 64 BUILD_DIR="${BUILD_DIR:=${MONOREPO_ROOT}/build/${BUILDER}}" 65 INSTALL_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). 71 if xcrun --find ninja &>/dev/null; then NINJA="$(xcrun --find ninja)"; else NINJA="ninja"; fi 72 if xcrun --find cmake &>/dev/null; then CMAKE="$(xcrun --find cmake)"; else CMAKE="cmake"; fi 73 74 function clean() { 75 rm -rf "${BUILD_DIR}" 76 } 77 78 function 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 89 function 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 97 function 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 116 function 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. 129 function 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 138 function 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 147 case "${BUILDER}" in 148 check-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 ;; 163 check-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 ;; 182 generic-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 ;; 191 generic-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 ;; 200 generic-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 ;; 209 generic-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 ;; 218 generic-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 ;; 227 generic-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 ;; 236 generic-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 ;; 244 generic-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 ;; 251 generic-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 ;; 259 generic-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 ;; 266 generic-gcc) 267 export CC=gcc 268 export CXX=g++ 269 clean 270 generate-cmake 271 check-cxx-cxxabi 272 ;; 273 generic-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 ;; 280 generic-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 ;; 287 generic-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 ;; 294 generic-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 ;; 301 generic-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 ;; 308 generic-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 ;; 315 generic-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 ;; 322 generic-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 ;; 329 generic-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 ;; 336 generic-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 ;; 343 x86_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 ;; 350 x86_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 ;; 359 x86_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 ;; 390 benchmarks) 391 export CC=clang 392 export CXX=clang++ 393 clean 394 generate-cmake 395 check-cxx-benchmarks 396 ;; 397 documentation) 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 ;; 406 unified-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 ;; 423 runtimes-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 ;; 446 legacy-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 ;; 453 legacy-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 ;; 497 aarch64) 498 clean 499 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/AArch64.cmake" 500 check-cxx-cxxabi 501 ;; 502 aarch64-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 510 armv8) 511 clean 512 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Armv8Arm.cmake" 513 check-cxx-cxxabi 514 ;; 515 armv8-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. 521 armv7) 522 clean 523 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Armv7Arm.cmake" 524 check-cxx-cxxabi 525 ;; 526 armv7-noexceptions) 527 clean 528 generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Armv7Thumb-noexceptions.cmake" 529 check-cxx-cxxabi 530 ;; 531 windows-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 ;; 543 windows-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 ;; 553 esac 554