1#!/usr/bin/env bash 2#===-- test-release.sh - Test the LLVM release candidates ------------------===# 3# 4# The LLVM Compiler Infrastructure 5# 6# This file is distributed under the University of Illinois Open Source 7# License. 8# 9#===------------------------------------------------------------------------===# 10# 11# Download, build, and test the release candidate for an LLVM release. 12# 13#===------------------------------------------------------------------------===# 14 15System=`uname -s` 16if [ "$System" = "FreeBSD" ]; then 17 MAKE=gmake 18else 19 MAKE=make 20fi 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_libunwind="yes" 37do_test_suite="yes" 38do_openmp="yes" 39do_lldb="no" 40BuildDir="`pwd`" 41use_autoconf="no" 42ExtraConfigureFlags="" 43ExportBranch="" 44 45function usage() { 46 echo "usage: `basename $0` -release X.Y.Z -rc NUM [OPTIONS]" 47 echo "" 48 echo " -release X.Y.Z The release version to test." 49 echo " -rc NUM The pre-release candidate number." 50 echo " -final The final release candidate." 51 echo " -triple TRIPLE The target triple for this machine." 52 echo " -j NUM Number of compile jobs to run. [default: 3]" 53 echo " -build-dir DIR Directory to perform testing in. [default: pwd]" 54 echo " -no-checkout Don't checkout the sources from SVN." 55 echo " -test-debug Test the debug build. [default: no]" 56 echo " -test-asserts Test with asserts on. [default: no]" 57 echo " -no-compare-files Don't test that phase 2 and 3 files are identical." 58 echo " -use-gzip Use gzip instead of xz." 59 echo " -configure-flags FLAGS Extra flags to pass to the configure step." 60 echo " -use-autoconf Use autoconf instead of cmake" 61 echo " -svn-path DIR Use the specified DIR instead of a release." 62 echo " For example -svn-path trunk or -svn-path branches/release_37" 63 echo " -no-rt Disable check-out & build Compiler-RT" 64 echo " -no-libs Disable check-out & build libcxx/libcxxabi/libunwind" 65 echo " -no-libunwind Disable check-out & build libunwind" 66 echo " -no-test-suite Disable check-out & build test-suite" 67 echo " -no-openmp Disable check-out & build libomp" 68 echo " -lldb Enable check-out & build lldb" 69 echo " -no-lldb Disable check-out & build lldb (default)" 70} 71 72while [ $# -gt 0 ]; do 73 case $1 in 74 -release | --release ) 75 shift 76 Release="$1" 77 Release_no_dot="`echo $1 | sed -e 's,\.,,g'`" 78 ;; 79 -rc | --rc | -RC | --RC ) 80 shift 81 RC="rc$1" 82 ;; 83 -final | --final ) 84 RC=final 85 ;; 86 -svn-path | --svn-path ) 87 shift 88 Release="test" 89 Release_no_dot="test" 90 ExportBranch="$1" 91 RC="`echo $ExportBranch | sed -e 's,/,_,g'`" 92 echo "WARNING: Using the branch $ExportBranch instead of a release tag" 93 echo " This is intended to aid new packagers in trialing " 94 echo " builds without requiring a tag to be created first" 95 ;; 96 -triple | --triple ) 97 shift 98 Triple="$1" 99 ;; 100 -configure-flags | --configure-flags ) 101 shift 102 ExtraConfigureFlags="$1" 103 ;; 104 -j* ) 105 NumJobs="`echo $1 | sed -e 's,-j\([0-9]*\),\1,g'`" 106 if [ -z "$NumJobs" ]; then 107 shift 108 NumJobs="$1" 109 fi 110 ;; 111 -build-dir | --build-dir | -builddir | --builddir ) 112 shift 113 BuildDir="$1" 114 ;; 115 -no-checkout | --no-checkout ) 116 do_checkout="no" 117 ;; 118 -test-debug | --test-debug ) 119 do_debug="yes" 120 ;; 121 -test-asserts | --test-asserts ) 122 do_asserts="yes" 123 ;; 124 -no-compare-files | --no-compare-files ) 125 do_compare="no" 126 ;; 127 -use-gzip | --use-gzip ) 128 use_gzip="yes" 129 ;; 130 -use-autoconf | --use-autoconf ) 131 use_autoconf="yes" 132 ;; 133 -no-rt ) 134 do_rt="no" 135 ;; 136 -no-libs ) 137 do_libs="no" 138 ;; 139 -no-libunwind ) 140 do_libunwind="no" 141 ;; 142 -no-test-suite ) 143 do_test_suite="no" 144 ;; 145 -no-openmp ) 146 do_openmp="no" 147 ;; 148 -lldb ) 149 do_lldb="yes" 150 ;; 151 -no-lldb ) 152 do_lldb="no" 153 ;; 154 -help | --help | -h | --h | -\? ) 155 usage 156 exit 0 157 ;; 158 * ) 159 echo "unknown option: $1" 160 usage 161 exit 1 162 ;; 163 esac 164 shift 165done 166 167if [ "$use_autoconf" = "no" ]; then 168 if [ "$do_test_suite" = "yes" ]; then 169 # See llvm.org/PR26146. 170 echo Skipping test-suite build when using CMake. 171 echo It will still be exported. 172 do_test_suite="export-only" 173 fi 174fi 175 176# Check required arguments. 177if [ -z "$Release" ]; then 178 echo "error: no release number specified" 179 exit 1 180fi 181if [ -z "$RC" ]; then 182 echo "error: no release candidate number specified" 183 exit 1 184fi 185if [ -z "$ExportBranch" ]; then 186 ExportBranch="tags/RELEASE_$Release_no_dot/$RC" 187fi 188if [ -z "$Triple" ]; then 189 echo "error: no target triple specified" 190 exit 1 191fi 192 193# Figure out how many make processes to run. 194if [ -z "$NumJobs" ]; then 195 NumJobs=`sysctl -n hw.activecpu 2> /dev/null || true` 196fi 197if [ -z "$NumJobs" ]; then 198 NumJobs=`sysctl -n hw.ncpu 2> /dev/null || true` 199fi 200if [ -z "$NumJobs" ]; then 201 NumJobs=`grep -c processor /proc/cpuinfo 2> /dev/null || true` 202fi 203if [ -z "$NumJobs" ]; then 204 NumJobs=3 205fi 206 207# Projects list 208projects="llvm cfe clang-tools-extra" 209if [ $do_rt = "yes" ]; then 210 projects="$projects compiler-rt" 211fi 212if [ $do_libs = "yes" ]; then 213 projects="$projects libcxx libcxxabi" 214 if [ $do_libunwind = "yes" ]; then 215 projects="$projects libunwind" 216 fi 217fi 218case $do_test_suite in 219 yes|export-only) 220 projects="$projects test-suite" 221 ;; 222esac 223if [ $do_openmp = "yes" ]; then 224 projects="$projects openmp" 225fi 226if [ $do_lldb = "yes" ]; then 227 projects="$projects lldb" 228fi 229 230# Go to the build directory (may be different from CWD) 231BuildDir=$BuildDir/$RC 232mkdir -p $BuildDir 233cd $BuildDir 234 235# Location of log files. 236LogDir=$BuildDir/logs 237mkdir -p $LogDir 238 239# Final package name. 240Package=clang+llvm-$Release 241if [ $RC != "final" ]; then 242 Package=$Package-$RC 243fi 244Package=$Package-$Triple 245 246# Errors to be highlighted at the end are written to this file. 247echo -n > $LogDir/deferred_errors.log 248 249function deferred_error() { 250 Phase="$1" 251 Flavor="$2" 252 Msg="$3" 253 echo "[${Flavor} Phase${Phase}] ${Msg}" | tee -a $LogDir/deferred_errors.log 254} 255 256# Make sure that a required program is available 257function check_program_exists() { 258 local program="$1" 259 if ! type -P $program > /dev/null 2>&1 ; then 260 echo "program '$1' not found !" 261 exit 1 262 fi 263} 264 265if [ "$System" != "Darwin" ]; then 266 check_program_exists 'chrpath' 267 check_program_exists 'file' 268 check_program_exists 'objdump' 269fi 270 271# Make sure that the URLs are valid. 272function check_valid_urls() { 273 for proj in $projects ; do 274 echo "# Validating $proj SVN URL" 275 276 if ! svn ls $Base_url/$proj/$ExportBranch > /dev/null 2>&1 ; then 277 echo "$proj does not have a $ExportBranch branch/tag!" 278 exit 1 279 fi 280 done 281} 282 283# Export sources to the build directory. 284function export_sources() { 285 check_valid_urls 286 287 for proj in $projects ; do 288 case $proj in 289 llvm) 290 projsrc=$proj.src 291 ;; 292 cfe) 293 projsrc=llvm.src/tools/clang 294 ;; 295 lldb) 296 projsrc=llvm.src/tools/$proj 297 ;; 298 clang-tools-extra) 299 projsrc=llvm.src/tools/clang/tools/extra 300 ;; 301 compiler-rt|libcxx|libcxxabi|libunwind|openmp) 302 projsrc=llvm.src/projects/$proj 303 ;; 304 test-suite) 305 if [ $do_test_suite = 'yes' ]; then 306 projsrc=llvm.src/projects/$proj 307 else 308 projsrc=$proj.src 309 fi 310 ;; 311 *) 312 echo "error: unknown project $proj" 313 exit 1 314 ;; 315 esac 316 317 if [ -d $projsrc ]; then 318 echo "# Reusing $proj $Release-$RC sources in $projsrc" 319 continue 320 fi 321 echo "# Exporting $proj $Release-$RC sources to $projsrc" 322 if ! svn export -q $Base_url/$proj/$ExportBranch $projsrc ; then 323 echo "error: failed to export $proj project" 324 exit 1 325 fi 326 done 327 328 cd $BuildDir 329} 330 331function configure_llvmCore() { 332 Phase="$1" 333 Flavor="$2" 334 ObjDir="$3" 335 336 case $Flavor in 337 Release ) 338 BuildType="Release" 339 Assertions="OFF" 340 ConfigureFlags="--enable-optimized --disable-assertions" 341 ;; 342 Release+Asserts ) 343 BuildType="Release" 344 Assertions="ON" 345 ConfigureFlags="--enable-optimized --enable-assertions" 346 ;; 347 Debug ) 348 BuildType="Debug" 349 Assertions="ON" 350 ConfigureFlags="--disable-optimized --enable-assertions" 351 ;; 352 * ) 353 echo "# Invalid flavor '$Flavor'" 354 echo "" 355 return 356 ;; 357 esac 358 359 echo "# Using C compiler: $c_compiler" 360 echo "# Using C++ compiler: $cxx_compiler" 361 362 cd $ObjDir 363 echo "# Configuring llvm $Release-$RC $Flavor" 364 365 if [ "$use_autoconf" = "yes" ]; then 366 echo "#" env CC="$c_compiler" CXX="$cxx_compiler" \ 367 $BuildDir/llvm.src/configure \ 368 $ConfigureFlags --disable-timestamps $ExtraConfigureFlags \ 369 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log 370 env CC="$c_compiler" CXX="$cxx_compiler" \ 371 $BuildDir/llvm.src/configure \ 372 $ConfigureFlags --disable-timestamps $ExtraConfigureFlags \ 373 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log 374 else 375 echo "#" env CC="$c_compiler" CXX="$cxx_compiler" \ 376 cmake -G "Unix Makefiles" \ 377 -DCMAKE_BUILD_TYPE=$BuildType -DLLVM_ENABLE_ASSERTIONS=$Assertions \ 378 -DLLVM_CONFIGTIME="(timestamp not enabled)" \ 379 $ExtraConfigureFlags $BuildDir/llvm.src \ 380 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log 381 env CC="$c_compiler" CXX="$cxx_compiler" \ 382 cmake -G "Unix Makefiles" \ 383 -DCMAKE_BUILD_TYPE=$BuildType -DLLVM_ENABLE_ASSERTIONS=$Assertions \ 384 -DLLVM_CONFIGTIME="(timestamp not enabled)" \ 385 $ExtraConfigureFlags $BuildDir/llvm.src \ 386 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log 387 fi 388 389 cd $BuildDir 390} 391 392function build_llvmCore() { 393 Phase="$1" 394 Flavor="$2" 395 ObjDir="$3" 396 DestDir="$4" 397 398 cd $ObjDir 399 echo "# Compiling llvm $Release-$RC $Flavor" 400 echo "# ${MAKE} -j $NumJobs VERBOSE=1" 401 ${MAKE} -j $NumJobs VERBOSE=1 \ 402 2>&1 | tee $LogDir/llvm.make-Phase$Phase-$Flavor.log 403 404 echo "# Installing llvm $Release-$RC $Flavor" 405 echo "# ${MAKE} install" 406 ${MAKE} install \ 407 DESTDIR="${DestDir}" \ 408 2>&1 | tee $LogDir/llvm.install-Phase$Phase-$Flavor.log 409 cd $BuildDir 410} 411 412function test_llvmCore() { 413 Phase="$1" 414 Flavor="$2" 415 ObjDir="$3" 416 417 cd $ObjDir 418 if ! ( ${MAKE} -j $NumJobs -k check-all \ 419 2>&1 | tee $LogDir/llvm.check-Phase$Phase-$Flavor.log ) ; then 420 deferred_error $Phase $Flavor "check-all failed" 421 fi 422 423 if [ "$use_autoconf" = "yes" ]; then 424 # In the cmake build, unit tests are run as part of check-all. 425 if ! ( ${MAKE} -k unittests 2>&1 | \ 426 tee $LogDir/llvm.unittests-Phase$Phase-$Flavor.log ) ; then 427 deferred_error $Phase $Flavor "unittests failed" 428 fi 429 fi 430 431 cd $BuildDir 432} 433 434# Clean RPATH. Libtool adds the build directory to the search path, which is 435# not necessary --- and even harmful --- for the binary packages we release. 436function clean_RPATH() { 437 if [ "$System" = "Darwin" ]; then 438 return 439 fi 440 local InstallPath="$1" 441 for Candidate in `find $InstallPath/{bin,lib} -type f`; do 442 if file $Candidate | grep ELF | egrep 'executable|shared object' > /dev/null 2>&1 ; then 443 if rpath=`objdump -x $Candidate | grep 'RPATH'` ; then 444 rpath=`echo $rpath | sed -e's/^ *RPATH *//'` 445 if [ -n "$rpath" ]; then 446 newrpath=`echo $rpath | sed -e's/.*\(\$ORIGIN[^:]*\).*/\1/'` 447 chrpath -r $newrpath $Candidate 2>&1 > /dev/null 2>&1 448 fi 449 fi 450 fi 451 done 452} 453 454# Create a package of the release binaries. 455function package_release() { 456 cwd=`pwd` 457 cd $BuildDir/Phase3/Release 458 mv llvmCore-$Release-$RC.install/usr/local $Package 459 if [ "$use_gzip" = "yes" ]; then 460 tar cfz $BuildDir/$Package.tar.gz $Package 461 else 462 tar cfJ $BuildDir/$Package.tar.xz $Package 463 fi 464 mv $Package llvmCore-$Release-$RC.install/usr/local 465 cd $cwd 466} 467 468# Exit if any command fails 469# Note: pipefail is necessary for running build commands through 470# a pipe (i.e. it changes the output of ``false | tee /dev/null ; echo $?``) 471set -e 472set -o pipefail 473 474if [ "$do_checkout" = "yes" ]; then 475 export_sources 476fi 477 478( 479Flavors="Release" 480if [ "$do_debug" = "yes" ]; then 481 Flavors="Debug $Flavors" 482fi 483if [ "$do_asserts" = "yes" ]; then 484 Flavors="$Flavors Release+Asserts" 485fi 486 487for Flavor in $Flavors ; do 488 echo "" 489 echo "" 490 echo "********************************************************************************" 491 echo " Release: $Release-$RC" 492 echo " Build: $Flavor" 493 echo " System Info: " 494 echo " `uname -a`" 495 echo "********************************************************************************" 496 echo "" 497 498 c_compiler="$CC" 499 cxx_compiler="$CXX" 500 llvmCore_phase1_objdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.obj 501 llvmCore_phase1_destdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.install 502 503 llvmCore_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.obj 504 llvmCore_phase2_destdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.install 505 506 llvmCore_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.obj 507 llvmCore_phase3_destdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.install 508 509 rm -rf $llvmCore_phase1_objdir 510 rm -rf $llvmCore_phase1_destdir 511 512 rm -rf $llvmCore_phase2_objdir 513 rm -rf $llvmCore_phase2_destdir 514 515 rm -rf $llvmCore_phase3_objdir 516 rm -rf $llvmCore_phase3_destdir 517 518 mkdir -p $llvmCore_phase1_objdir 519 mkdir -p $llvmCore_phase1_destdir 520 521 mkdir -p $llvmCore_phase2_objdir 522 mkdir -p $llvmCore_phase2_destdir 523 524 mkdir -p $llvmCore_phase3_objdir 525 mkdir -p $llvmCore_phase3_destdir 526 527 ############################################################################ 528 # Phase 1: Build llvmCore and clang 529 echo "# Phase 1: Building llvmCore" 530 configure_llvmCore 1 $Flavor $llvmCore_phase1_objdir 531 build_llvmCore 1 $Flavor \ 532 $llvmCore_phase1_objdir $llvmCore_phase1_destdir 533 clean_RPATH $llvmCore_phase1_destdir/usr/local 534 535 ######################################################################## 536 # Phase 2: Build llvmCore with newly built clang from phase 1. 537 c_compiler=$llvmCore_phase1_destdir/usr/local/bin/clang 538 cxx_compiler=$llvmCore_phase1_destdir/usr/local/bin/clang++ 539 echo "# Phase 2: Building llvmCore" 540 configure_llvmCore 2 $Flavor $llvmCore_phase2_objdir 541 build_llvmCore 2 $Flavor \ 542 $llvmCore_phase2_objdir $llvmCore_phase2_destdir 543 clean_RPATH $llvmCore_phase2_destdir/usr/local 544 545 ######################################################################## 546 # Phase 3: Build llvmCore with newly built clang from phase 2. 547 c_compiler=$llvmCore_phase2_destdir/usr/local/bin/clang 548 cxx_compiler=$llvmCore_phase2_destdir/usr/local/bin/clang++ 549 echo "# Phase 3: Building llvmCore" 550 configure_llvmCore 3 $Flavor $llvmCore_phase3_objdir 551 build_llvmCore 3 $Flavor \ 552 $llvmCore_phase3_objdir $llvmCore_phase3_destdir 553 clean_RPATH $llvmCore_phase3_destdir/usr/local 554 555 ######################################################################## 556 # Testing: Test phase 3 557 echo "# Testing - built with clang" 558 test_llvmCore 3 $Flavor $llvmCore_phase3_objdir 559 560 ######################################################################## 561 # Compare .o files between Phase2 and Phase3 and report which ones 562 # differ. 563 if [ "$do_compare" = "yes" ]; then 564 echo 565 echo "# Comparing Phase 2 and Phase 3 files" 566 for p2 in `find $llvmCore_phase2_objdir -name '*.o'` ; do 567 p3=`echo $p2 | sed -e 's,Phase2,Phase3,'` 568 # Substitute 'Phase2' for 'Phase3' in the Phase 2 object file in 569 # case there are build paths in the debug info. On some systems, 570 # sed adds a newline to the output, so pass $p3 through sed too. 571 if ! cmp -s \ 572 <(env LC_CTYPE=C sed -e 's,Phase2,Phase3,g' $p2) \ 573 <(env LC_CTYPE=C sed -e '' $p3) 16 16; then 574 echo "file `basename $p2` differs between phase 2 and phase 3" 575 fi 576 done 577 fi 578done 579 580) 2>&1 | tee $LogDir/testing.$Release-$RC.log 581 582package_release 583 584set +e 585 586# Woo hoo! 587echo "### Testing Finished ###" 588if [ "$use_gzip" = "yes" ]; then 589 echo "### Package: $Package.tar.gz" 590else 591 echo "### Package: $Package.tar.xz" 592fi 593echo "### Logs: $LogDir" 594 595echo "### Errors:" 596if [ -s "$LogDir/deferred_errors.log" ]; then 597 cat "$LogDir/deferred_errors.log" 598 exit 1 599else 600 echo "None." 601fi 602 603exit 0 604