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