1#!/usr/bin/env bash 2#===-- test-release.sh - Test the LLVM release candidates ------------------===# 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# Download, build, and test the release candidate for an LLVM release. 11# 12#===------------------------------------------------------------------------===# 13 14System=`uname -s` 15if [ "$System" = "FreeBSD" ]; then 16 MAKE=gmake 17else 18 MAKE=make 19fi 20generator="Unix Makefiles" 21 22Release="" 23Release_no_dot="" 24RC="" 25Triple="" 26use_gzip="no" 27do_checkout="yes" 28do_debug="no" 29do_asserts="no" 30do_compare="yes" 31do_rt="yes" 32do_clang_tools="yes" 33do_libs="yes" 34do_libcxxabi="yes" 35do_libunwind="yes" 36do_test_suite="yes" 37do_openmp="yes" 38do_lld="yes" 39do_lldb="yes" 40do_polly="yes" 41do_mlir="yes" 42do_flang="yes" 43do_silent_log="no" 44BuildDir="`pwd`" 45ExtraConfigureFlags="" 46ExportBranch="" 47git_ref="" 48 49function usage() { 50 echo "usage: `basename $0` -release X.Y.Z -rc NUM [OPTIONS]" 51 echo "" 52 echo " -release X.Y.Z The release version to test." 53 echo " -rc NUM The pre-release candidate number." 54 echo " -final The final release candidate." 55 echo " -triple TRIPLE The target triple for this machine." 56 echo " -j NUM Number of compile jobs to run. [default: 3]" 57 echo " -build-dir DIR Directory to perform testing in. [default: pwd]" 58 echo " -no-checkout Don't checkout the sources from SVN." 59 echo " -test-debug Test the debug build. [default: no]" 60 echo " -test-asserts Test with asserts on. [default: no]" 61 echo " -no-compare-files Don't test that phase 2 and 3 files are identical." 62 echo " -use-gzip Use gzip instead of xz." 63 echo " -use-ninja Use ninja instead of make/gmake." 64 echo " -configure-flags FLAGS Extra flags to pass to the configure step." 65 echo " -git-ref sha Use the specified git ref for testing instead of a release." 66 echo " -no-rt Disable check-out & build Compiler-RT" 67 echo " -no-clang-tools Disable check-out & build clang-tools-extra" 68 echo " -no-libs Disable check-out & build libcxx/libcxxabi/libunwind" 69 echo " -no-libcxxabi Disable check-out & build libcxxabi" 70 echo " -no-libunwind Disable check-out & build libunwind" 71 echo " -no-test-suite Disable check-out & build test-suite" 72 echo " -no-openmp Disable check-out & build libomp" 73 echo " -no-lld Disable check-out & build lld" 74 echo " -lldb Enable check-out & build lldb" 75 echo " -no-lldb Disable check-out & build lldb (default)" 76 echo " -no-polly Disable check-out & build Polly" 77 echo " -no-mlir Disable check-out & build MLIR" 78 echo " -no-flang Disable check-out & build Flang" 79 echo " -silent-log Don't output build logs to stdout" 80} 81 82while [ $# -gt 0 ]; do 83 case $1 in 84 -release | --release ) 85 shift 86 Release="$1" 87 Release_no_dot="`echo $1 | sed -e 's,\.,,g'`" 88 ;; 89 -rc | --rc | -RC | --RC ) 90 shift 91 RC="rc$1" 92 ;; 93 -final | --final ) 94 RC=final 95 ;; 96 -git-ref | --git-ref ) 97 shift 98 Release="test" 99 Release_no_dot="test" 100 ExportBranch="$1" 101 RC="`echo $ExportBranch | sed -e 's,/,_,g'`" 102 git_ref="$1" 103 echo "WARNING: Using the ref $git_ref instead of a release tag" 104 echo " This is intended to aid new packagers in trialing " 105 echo " builds without requiring a tag to be created first" 106 ;; 107 -triple | --triple ) 108 shift 109 Triple="$1" 110 ;; 111 -configure-flags | --configure-flags ) 112 shift 113 ExtraConfigureFlags="$1" 114 ;; 115 -j* ) 116 NumJobs="`echo $1 | sed -e 's,-j\([0-9]*\),\1,g'`" 117 if [ -z "$NumJobs" ]; then 118 shift 119 NumJobs="$1" 120 fi 121 ;; 122 -use-ninja ) 123 MAKE=ninja 124 generator=Ninja 125 ;; 126 -build-dir | --build-dir | -builddir | --builddir ) 127 shift 128 BuildDir="$1" 129 ;; 130 -no-checkout | --no-checkout ) 131 do_checkout="no" 132 ;; 133 -test-debug | --test-debug ) 134 do_debug="yes" 135 ;; 136 -test-asserts | --test-asserts ) 137 do_asserts="yes" 138 ;; 139 -no-compare-files | --no-compare-files ) 140 do_compare="no" 141 ;; 142 -use-gzip | --use-gzip ) 143 use_gzip="yes" 144 ;; 145 -no-rt ) 146 do_rt="no" 147 ;; 148 -no-libs ) 149 do_libs="no" 150 ;; 151 -no-clang-tools ) 152 do_clang_tools="no" 153 ;; 154 -no-libcxxabi ) 155 do_libcxxabi="no" 156 ;; 157 -no-libunwind ) 158 do_libunwind="no" 159 ;; 160 -no-test-suite ) 161 do_test_suite="no" 162 ;; 163 -no-openmp ) 164 do_openmp="no" 165 ;; 166 -no-lld ) 167 do_lld="no" 168 ;; 169 -lldb ) 170 do_lldb="yes" 171 ;; 172 -no-lldb ) 173 do_lldb="no" 174 ;; 175 -no-polly ) 176 do_polly="no" 177 ;; 178 -no-mlir ) 179 do_mlir="no" 180 ;; 181 -no-flang ) 182 do_flang="no" 183 ;; 184 -silent-log ) 185 do_silent_log="yes" 186 ;; 187 -help | --help | -h | --h | -\? ) 188 usage 189 exit 0 190 ;; 191 * ) 192 echo "unknown option: $1" 193 usage 194 exit 1 195 ;; 196 esac 197 shift 198done 199 200if [ $do_mlir = "no" ] && [ $do_flang = "yes" ]; then 201 echo "error: cannot build Flang without MLIR" 202 exit 1 203fi 204 205# Check required arguments. 206if [ -z "$Release" ]; then 207 echo "error: no release number specified" 208 exit 1 209fi 210if [ -z "$RC" ]; then 211 echo "error: no release candidate number specified" 212 exit 1 213fi 214if [ -z "$ExportBranch" ]; then 215 ExportBranch="tags/RELEASE_$Release_no_dot/$RC" 216fi 217if [ -z "$Triple" ]; then 218 echo "error: no target triple specified" 219 exit 1 220fi 221 222if [ "$Release" != "test" ]; then 223 if [ -n "$git_ref" ]; then 224 echo "error: can't specify both -release and -git-ref" 225 exit 1 226 fi 227 git_ref=llvmorg-$Release 228 if [ "$RC" != "final" ]; then 229 git_ref="$git_ref-$RC" 230 fi 231fi 232 233# Figure out how many make processes to run. 234if [ -z "$NumJobs" ]; then 235 NumJobs=`sysctl -n hw.activecpu 2> /dev/null || true` 236fi 237if [ -z "$NumJobs" ]; then 238 NumJobs=`sysctl -n hw.ncpu 2> /dev/null || true` 239fi 240if [ -z "$NumJobs" ]; then 241 NumJobs=`grep -c processor /proc/cpuinfo 2> /dev/null || true` 242fi 243if [ -z "$NumJobs" ]; then 244 NumJobs=3 245fi 246 247# Projects list 248projects="llvm clang" 249if [ $do_clang_tools = "yes" ]; then 250 projects="$projects clang-tools-extra" 251fi 252runtimes="" 253if [ $do_rt = "yes" ]; then 254 runtimes="$runtimes compiler-rt" 255fi 256if [ $do_libs = "yes" ]; then 257 runtimes="$runtimes libcxx" 258 if [ $do_libcxxabi = "yes" ]; then 259 runtimes="$runtimes libcxxabi" 260 fi 261 if [ $do_libunwind = "yes" ]; then 262 runtimes="$runtimes libunwind" 263 fi 264fi 265if [ $do_openmp = "yes" ]; then 266 projects="$projects openmp" 267fi 268if [ $do_lld = "yes" ]; then 269 projects="$projects lld" 270fi 271if [ $do_lldb = "yes" ]; then 272 projects="$projects lldb" 273fi 274if [ $do_polly = "yes" ]; then 275 projects="$projects polly" 276fi 277if [ $do_mlir = "yes" ]; then 278 projects="$projects mlir" 279fi 280if [ $do_flang = "yes" ]; then 281 projects="$projects flang" 282fi 283 284# Go to the build directory (may be different from CWD) 285BuildDir=$BuildDir/$RC 286mkdir -p $BuildDir 287cd $BuildDir 288 289# Location of log files. 290LogDir=$BuildDir/logs 291mkdir -p $LogDir 292 293# Final package name. 294Package=clang+llvm-$Release 295if [ $RC != "final" ]; then 296 Package=$Package-$RC 297fi 298Package=$Package-$Triple 299 300# Errors to be highlighted at the end are written to this file. 301echo -n > $LogDir/deferred_errors.log 302 303function deferred_error() { 304 Phase="$1" 305 Flavor="$2" 306 Msg="$3" 307 echo "[${Flavor} Phase${Phase}] ${Msg}" | tee -a $LogDir/deferred_errors.log 308} 309 310# Make sure that a required program is available 311function check_program_exists() { 312 local program="$1" 313 if ! type -P $program > /dev/null 2>&1 ; then 314 echo "program '$1' not found !" 315 exit 1 316 fi 317} 318 319if [ "$System" != "Darwin" ] && [ "$System" != "SunOS" ] && [ "$System" != "AIX" ]; then 320 check_program_exists 'chrpath' 321fi 322 323if [ "$System" != "Darwin" ]; then 324 check_program_exists 'file' 325 check_program_exists 'objdump' 326fi 327 328check_program_exists ${MAKE} 329 330# Export sources to the build directory. 331function export_sources() { 332 SrcDir=$BuildDir/llvm-project 333 mkdir -p $SrcDir 334 echo "# Using git ref: $git_ref" 335 336 # GitHub allows you to download a tarball of any commit using the URL: 337 # https://github.com/$organization/$repo/archive/$ref.tar.gz 338 curl -L https://github.com/llvm/llvm-project/archive/$git_ref.tar.gz | \ 339 tar -C $SrcDir --strip-components=1 -xzf - 340 341 if [ "$do_test_suite" = "yes" ]; then 342 TestSuiteSrcDir=$BuildDir/llvm-test-suite 343 mkdir -p $TestSuiteSrcDir 344 345 # We can only use named refs, like branches and tags, that exist in 346 # both the llvm-project and test-suite repos if we want to run the 347 # test suite. 348 # If the test-suite fails to download assume we are using a ref that 349 # doesn't exist in the test suite and disable it. 350 set +e 351 curl -L https://github.com/llvm/test-suite/archive/$git_ref.tar.gz | \ 352 tar -C $TestSuiteSrcDir --strip-components=1 -xzf - 353 if [ $? -ne -0 ]; then 354 echo "$git_ref not found in test-suite repo, test-suite disabled." 355 do_test_suite="no" 356 fi 357 set -e 358 fi 359 360 cd $BuildDir 361} 362 363function configure_llvmCore() { 364 Phase="$1" 365 Flavor="$2" 366 ObjDir="$3" 367 368 case $Flavor in 369 Release ) 370 BuildType="Release" 371 Assertions="OFF" 372 ;; 373 Release+Asserts ) 374 BuildType="Release" 375 Assertions="ON" 376 ;; 377 Debug ) 378 BuildType="Debug" 379 Assertions="ON" 380 ;; 381 * ) 382 echo "# Invalid flavor '$Flavor'" 383 echo "" 384 return 385 ;; 386 esac 387 388 project_list=${projects// /;} 389 runtime_list=${runtimes// /;} 390 echo "# Using C compiler: $c_compiler" 391 echo "# Using C++ compiler: $cxx_compiler" 392 393 cd $ObjDir 394 echo "# Configuring llvm $Release-$RC $Flavor" 395 396 echo "#" env CC="$c_compiler" CXX="$cxx_compiler" \ 397 cmake -G "$generator" \ 398 -DCMAKE_BUILD_TYPE=$BuildType -DLLVM_ENABLE_ASSERTIONS=$Assertions \ 399 -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ 400 -DLLVM_ENABLE_PROJECTS="$project_list" \ 401 -DLLVM_LIT_ARGS="-j $NumJobs" \ 402 -DLLVM_ENABLE_RUNTIMES="$runtime_list" \ 403 $ExtraConfigureFlags $BuildDir/llvm-project/llvm \ 404 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log 405 env CC="$c_compiler" CXX="$cxx_compiler" \ 406 cmake -G "$generator" \ 407 -DCMAKE_BUILD_TYPE=$BuildType -DLLVM_ENABLE_ASSERTIONS=$Assertions \ 408 -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ 409 -DLLVM_ENABLE_PROJECTS="$project_list" \ 410 -DLLVM_LIT_ARGS="-j $NumJobs" \ 411 -DLLVM_ENABLE_RUNTIMES="$runtime_list" \ 412 $ExtraConfigureFlags $BuildDir/llvm-project/llvm \ 413 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log 414 415 cd $BuildDir 416} 417 418function build_llvmCore() { 419 Phase="$1" 420 Flavor="$2" 421 ObjDir="$3" 422 DestDir="$4" 423 424 Verbose="VERBOSE=1" 425 if [ ${MAKE} = 'ninja' ]; then 426 Verbose="-v" 427 fi 428 429 redir="/dev/stdout" 430 if [ $do_silent_log == "yes" ]; then 431 echo "# Silencing build logs because of -silent-log flag..." 432 redir="/dev/null" 433 fi 434 435 cd $ObjDir 436 echo "# Compiling llvm $Release-$RC $Flavor" 437 echo "# ${MAKE} -j $NumJobs $Verbose" 438 ${MAKE} -j $NumJobs $Verbose \ 439 2>&1 | tee $LogDir/llvm.make-Phase$Phase-$Flavor.log > $redir 440 441 echo "# Installing llvm $Release-$RC $Flavor" 442 echo "# ${MAKE} install" 443 DESTDIR="${DestDir}" ${MAKE} install \ 444 2>&1 | tee $LogDir/llvm.install-Phase$Phase-$Flavor.log > $redir 445 cd $BuildDir 446} 447 448function test_llvmCore() { 449 Phase="$1" 450 Flavor="$2" 451 ObjDir="$3" 452 453 KeepGoing="-k" 454 if [ ${MAKE} = 'ninja' ]; then 455 # Ninja doesn't have a documented "keep-going-forever" mode, we need to 456 # set a limit on how many jobs can fail before we give up. 457 KeepGoing="-k 100" 458 fi 459 460 cd $ObjDir 461 if ! ( ${MAKE} -j $NumJobs $KeepGoing check-all \ 462 2>&1 | tee $LogDir/llvm.check-Phase$Phase-$Flavor.log ) ; then 463 deferred_error $Phase $Flavor "check-all failed" 464 fi 465 466 if [ $do_test_suite = 'yes' ]; then 467 cd $TestSuiteBuildDir 468 env CC="$c_compiler" CXX="$cxx_compiler" \ 469 cmake $TestSuiteSrcDir -G "$generator" -DTEST_SUITE_LIT=$Lit \ 470 -DTEST_SUITE_HOST_CC=$build_compiler 471 472 if ! ( ${MAKE} -j $NumJobs $KeepGoing check \ 473 2>&1 | tee $LogDir/llvm.check-Phase$Phase-$Flavor.log ) ; then 474 deferred_error $Phase $Flavor "test suite failed" 475 fi 476 fi 477 cd $BuildDir 478} 479 480# Clean RPATH. Libtool adds the build directory to the search path, which is 481# not necessary --- and even harmful --- for the binary packages we release. 482function clean_RPATH() { 483 if [ "$System" = "Darwin" ] || [ "$System" = "SunOS" ] || [ "$System" = "AIX" ]; then 484 return 485 fi 486 local InstallPath="$1" 487 for Candidate in `find $InstallPath/{bin,lib} -type f`; do 488 if file $Candidate | grep ELF | egrep 'executable|shared object' > /dev/null 2>&1 ; then 489 if rpath=`objdump -x $Candidate | grep 'RPATH'` ; then 490 rpath=`echo $rpath | sed -e's/^ *RPATH *//'` 491 if [ -n "$rpath" ]; then 492 newrpath=`echo $rpath | sed -e's/.*\(\$ORIGIN[^:]*\).*/\1/'` 493 chrpath -r $newrpath $Candidate 2>&1 > /dev/null 2>&1 494 fi 495 fi 496 fi 497 done 498} 499 500# Create a package of the release binaries. 501function package_release() { 502 cwd=`pwd` 503 cd $BuildDir/Phase3/Release 504 mv llvmCore-$Release-$RC.install/usr/local $Package 505 if [ "$use_gzip" = "yes" ]; then 506 tar cf - $Package | gzip -9c > $BuildDir/$Package.tar.gz 507 else 508 tar cf - $Package | xz -9ce > $BuildDir/$Package.tar.xz 509 fi 510 mv $Package llvmCore-$Release-$RC.install/usr/local 511 cd $cwd 512} 513 514# Exit if any command fails 515# Note: pipefail is necessary for running build commands through 516# a pipe (i.e. it changes the output of ``false | tee /dev/null ; echo $?``) 517set -e 518set -o pipefail 519 520# Turn off core dumps, as some test cases can easily fill up even the largest 521# file systems. 522ulimit -c 0 523 524if [ "$do_checkout" = "yes" ]; then 525 export_sources 526fi 527 528# Setup the test-suite. Do this early so we can catch failures before 529# we do the full 3 stage build. 530if [ $do_test_suite = "yes" ]; then 531 check_program_exists 'python3' 532 venv="python3 -m venv" 533 534 SandboxDir="$BuildDir/sandbox" 535 Lit=$SandboxDir/bin/lit 536 TestSuiteBuildDir="$BuildDir/test-suite-build" 537 TestSuiteSrcDir="$BuildDir/llvm-test-suite" 538 539 ${venv} $SandboxDir 540 $SandboxDir/bin/python $BuildDir/llvm-project/llvm/utils/lit/setup.py install 541 mkdir -p $TestSuiteBuildDir 542fi 543 544( 545Flavors="Release" 546if [ "$do_debug" = "yes" ]; then 547 Flavors="Debug $Flavors" 548fi 549if [ "$do_asserts" = "yes" ]; then 550 Flavors="$Flavors Release+Asserts" 551fi 552 553for Flavor in $Flavors ; do 554 echo "" 555 echo "" 556 echo "********************************************************************************" 557 echo " Release: $Release-$RC" 558 echo " Build: $Flavor" 559 echo " System Info: " 560 echo " `uname -a`" 561 echo "********************************************************************************" 562 echo "" 563 564 c_compiler="$CC" 565 cxx_compiler="$CXX" 566 build_compiler="$CC" 567 [[ -z "$build_compiler" ]] && build_compiler="cc" 568 llvmCore_phase1_objdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.obj 569 llvmCore_phase1_destdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.install 570 571 llvmCore_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.obj 572 llvmCore_phase2_destdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.install 573 574 llvmCore_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.obj 575 llvmCore_phase3_destdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.install 576 577 rm -rf $llvmCore_phase1_objdir 578 rm -rf $llvmCore_phase1_destdir 579 580 rm -rf $llvmCore_phase2_objdir 581 rm -rf $llvmCore_phase2_destdir 582 583 rm -rf $llvmCore_phase3_objdir 584 rm -rf $llvmCore_phase3_destdir 585 586 mkdir -p $llvmCore_phase1_objdir 587 mkdir -p $llvmCore_phase1_destdir 588 589 mkdir -p $llvmCore_phase2_objdir 590 mkdir -p $llvmCore_phase2_destdir 591 592 mkdir -p $llvmCore_phase3_objdir 593 mkdir -p $llvmCore_phase3_destdir 594 595 ############################################################################ 596 # Phase 1: Build llvmCore and clang 597 echo "# Phase 1: Building llvmCore" 598 configure_llvmCore 1 $Flavor $llvmCore_phase1_objdir 599 build_llvmCore 1 $Flavor \ 600 $llvmCore_phase1_objdir $llvmCore_phase1_destdir 601 clean_RPATH $llvmCore_phase1_destdir/usr/local 602 603 ######################################################################## 604 # Phase 2: Build llvmCore with newly built clang from phase 1. 605 c_compiler=$llvmCore_phase1_destdir/usr/local/bin/clang 606 cxx_compiler=$llvmCore_phase1_destdir/usr/local/bin/clang++ 607 echo "# Phase 2: Building llvmCore" 608 configure_llvmCore 2 $Flavor $llvmCore_phase2_objdir 609 build_llvmCore 2 $Flavor \ 610 $llvmCore_phase2_objdir $llvmCore_phase2_destdir 611 clean_RPATH $llvmCore_phase2_destdir/usr/local 612 613 ######################################################################## 614 # Phase 3: Build llvmCore with newly built clang from phase 2. 615 c_compiler=$llvmCore_phase2_destdir/usr/local/bin/clang 616 cxx_compiler=$llvmCore_phase2_destdir/usr/local/bin/clang++ 617 echo "# Phase 3: Building llvmCore" 618 configure_llvmCore 3 $Flavor $llvmCore_phase3_objdir 619 build_llvmCore 3 $Flavor \ 620 $llvmCore_phase3_objdir $llvmCore_phase3_destdir 621 clean_RPATH $llvmCore_phase3_destdir/usr/local 622 623 ######################################################################## 624 # Testing: Test phase 3 625 c_compiler=$llvmCore_phase3_destdir/usr/local/bin/clang 626 cxx_compiler=$llvmCore_phase3_destdir/usr/local/bin/clang++ 627 echo "# Testing - built with clang" 628 test_llvmCore 3 $Flavor $llvmCore_phase3_objdir 629 630 ######################################################################## 631 # Compare .o files between Phase2 and Phase3 and report which ones 632 # differ. 633 if [ "$do_compare" = "yes" ]; then 634 echo 635 echo "# Comparing Phase 2 and Phase 3 files" 636 for p2 in `find $llvmCore_phase2_objdir -name '*.o'` ; do 637 p3=`echo $p2 | sed -e 's,Phase2,Phase3,'` 638 # Substitute 'Phase2' for 'Phase3' in the Phase 2 object file in 639 # case there are build paths in the debug info. Do the same sub- 640 # stitution on both files in case the string occurrs naturally. 641 if ! cmp -s \ 642 <(env LC_CTYPE=C sed -e 's,Phase1,Phase2,g' -e 's,Phase2,Phase3,g' $p2) \ 643 <(env LC_CTYPE=C sed -e 's,Phase1,Phase2,g' -e 's,Phase2,Phase3,g' $p3) \ 644 16 16; then 645 echo "file `basename $p2` differs between phase 2 and phase 3" 646 fi 647 done 648 fi 649done 650 651) 2>&1 | tee $LogDir/testing.$Release-$RC.log 652 653if [ "$use_gzip" = "yes" ]; then 654 echo "# Packaging the release as $Package.tar.gz" 655else 656 echo "# Packaging the release as $Package.tar.xz" 657fi 658package_release 659 660set +e 661 662# Woo hoo! 663echo "### Testing Finished ###" 664echo "### Logs: $LogDir" 665 666echo "### Errors:" 667if [ -s "$LogDir/deferred_errors.log" ]; then 668 cat "$LogDir/deferred_errors.log" 669 exit 1 670else 671 echo "None." 672fi 673 674exit 0 675