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 15 if [ `uname -s` = "FreeBSD" ]; then 16 MAKE=gmake 17 else 18 MAKE=make 19 fi 20 21 projects="llvm cfe dragonegg compiler-rt test-suite" 22 23 # Base SVN URL for the sources. 24 Base_url="http://llvm.org/svn/llvm-project" 25 26 Release="" 27 Release_no_dot="" 28 RC="" 29 do_checkout="yes" 30 do_ada="no" 31 do_clang="yes" 32 do_dragonegg="no" 33 do_fortran="no" 34 do_objc="yes" 35 do_64bit="yes" 36 do_debug="no" 37 do_asserts="no" 38 do_compare="yes" 39 BuildDir="`pwd`" 40 41 function usage() { 42 echo "usage: `basename $0` -release X.Y -rc NUM [OPTIONS]" 43 echo "" 44 echo " -release X.Y The release number to test." 45 echo " -rc NUM The pre-release candidate number." 46 echo " -final The final release candidate." 47 echo " -j NUM Number of compile jobs to run. [default: 3]" 48 echo " -build-dir DIR Directory to perform testing in. [default: pwd]" 49 echo " -no-checkout Don't checkout the sources from SVN." 50 echo " -no-64bit Don't test the 64-bit version. [default: yes]" 51 echo " -enable-ada Build Ada. [default: disable]" 52 echo " -disable-clang Do not test clang. [default: enable]" 53 echo " -enable-dragonegg Test dragonegg. [default: disable]" 54 echo " -enable-fortran Enable Fortran build. [default: disable]" 55 echo " -disable-objc Disable ObjC build. [default: enable]" 56 echo " -test-debug Test the debug build. [default: no]" 57 echo " -test-asserts Test with asserts on. [default: no]" 58 echo " -no-compare-files Don't test that phase 2 and 3 files are identical." 59 } 60 61 while [ $# -gt 0 ]; do 62 case $1 in 63 -release | --release ) 64 shift 65 Release="$1" 66 Release_no_dot="`echo $1 | sed -e 's,\.,,'`" 67 ;; 68 -rc | --rc | -RC | --RC ) 69 shift 70 RC="rc$1" 71 ;; 72 -final | --final ) 73 RC=final 74 ;; 75 -j* ) 76 NumJobs="`echo $1 | sed -e 's,-j\([0-9]*\),\1,g'`" 77 if [ -z "$NumJobs" ]; then 78 shift 79 NumJobs="$1" 80 fi 81 ;; 82 -build-dir | --build-dir | -builddir | --builddir ) 83 shift 84 BuildDir="$1" 85 ;; 86 -no-checkout | --no-checkout ) 87 do_checkout="no" 88 ;; 89 -no-64bit | --no-64bit ) 90 do_64bit="no" 91 ;; 92 -enable-ada | --enable-ada ) 93 do_ada="yes" 94 ;; 95 -disable-clang | --disable-clang ) 96 do_clang="no" 97 ;; 98 -enable-dragonegg | --enable-dragonegg ) 99 do_dragonegg="yes" 100 ;; 101 -enable-fortran | --enable-fortran ) 102 do_fortran="yes" 103 ;; 104 -disable-objc | --disable-objc ) 105 do_objc="no" 106 ;; 107 -test-debug | --test-debug ) 108 do_debug="yes" 109 ;; 110 -test-asserts | --test-asserts ) 111 do_asserts="yes" 112 ;; 113 -no-compare-files | --no-compare-files ) 114 do_compare="no" 115 ;; 116 -help | --help | -h | --h | -\? ) 117 usage 118 exit 0 119 ;; 120 * ) 121 echo "unknown option: $1" 122 usage 123 exit 1 124 ;; 125 esac 126 shift 127 done 128 129 # Check required arguments. 130 if [ -z "$Release" ]; then 131 echo "error: no release number specified" 132 exit 1 133 fi 134 if [ -z "$RC" ]; then 135 echo "error: no release candidate number specified" 136 exit 1 137 fi 138 139 # Figure out how many make processes to run. 140 if [ -z "$NumJobs" ]; then 141 NumJobs=`sysctl -n hw.activecpu 2> /dev/null || true` 142 fi 143 if [ -z "$NumJobs" ]; then 144 NumJobs=`sysctl -n hw.ncpu 2> /dev/null || true` 145 fi 146 if [ -z "$NumJobs" ]; then 147 NumJobs=`grep -c processor /proc/cpuinfo 2> /dev/null || true` 148 fi 149 if [ -z "$NumJobs" ]; then 150 NumJobs=3 151 fi 152 153 # Go to the build directory (may be different from CWD) 154 BuildDir=$BuildDir/$RC 155 mkdir -p $BuildDir 156 cd $BuildDir 157 158 # Location of log files. 159 LogDir=$BuildDir/logs 160 mkdir -p $LogDir 161 162 # Find compilers. 163 if [ "$do_dragonegg" = "yes" ]; then 164 gcc_compiler="$GCC" 165 if [ -z "$gcc_compiler" ]; then 166 gcc_compiler="`which gcc`" 167 if [ -z "$gcc_compiler" ]; then 168 echo "error: cannot find gcc to use with dragonegg" 169 exit 1 170 fi 171 fi 172 173 gxx_compiler="$GXX" 174 if [ -z "$gxx_compiler" ]; then 175 gxx_compiler="`which g++`" 176 if [ -z "$gxx_compiler" ]; then 177 echo "error: cannot find g++ to use with dragonegg" 178 exit 1 179 fi 180 fi 181 fi 182 183 184 # Make sure that the URLs are valid. 185 function check_valid_urls() { 186 for proj in $projects ; do 187 echo "# Validating $proj SVN URL" 188 189 if ! svn ls $Base_url/$proj/tags/RELEASE_$Release_no_dot/$RC > /dev/null 2>&1 ; then 190 echo "llvm $Release release candidate $RC doesn't exist!" 191 exit 1 192 fi 193 done 194 } 195 196 # Export sources to the build directory. 197 function export_sources() { 198 check_valid_urls 199 200 for proj in $projects ; do 201 echo "# Exporting $proj $Release-RC$RC sources" 202 if ! svn export -q $Base_url/$proj/tags/RELEASE_$Release_no_dot/$RC $proj.src ; then 203 echo "error: failed to export $proj project" 204 exit 1 205 fi 206 done 207 208 echo "# Creating symlinks" 209 cd $BuildDir/llvm.src/tools 210 if [ ! -h clang ]; then 211 ln -s ../../cfe.src clang 212 fi 213 cd $BuildDir/llvm.src/projects 214 if [ ! -h llvm-test ]; then 215 ln -s ../../test-suite.src llvm-test 216 fi 217 if [ ! -h compiler-rt ]; then 218 ln -s ../../compiler-rt.src compiler-rt 219 fi 220 cd $BuildDir 221 } 222 223 function configure_llvmCore() { 224 Phase="$1" 225 Flavor="$2" 226 ObjDir="$3" 227 InstallDir="$4" 228 229 case $Flavor in 230 Release | Release-64 ) 231 Optimized="yes" 232 Assertions="no" 233 ;; 234 Release+Asserts ) 235 Optimized="yes" 236 Assertions="yes" 237 ;; 238 Debug ) 239 Optimized="no" 240 Assertions="yes" 241 ;; 242 * ) 243 echo "# Invalid flavor '$Flavor'" 244 echo "" 245 return 246 ;; 247 esac 248 249 echo "# Using C compiler: $c_compiler" 250 echo "# Using C++ compiler: $cxx_compiler" 251 252 cd $ObjDir 253 echo "# Configuring llvm $Release-$RC $Flavor" 254 echo "# $BuildDir/llvm.src/configure --prefix=$InstallDir \ 255 --enable-optimized=$Optimized \ 256 --enable-assertions=$Assertions" 257 env CC="$c_compiler" CXX="$cxx_compiler" \ 258 $BuildDir/llvm.src/configure --prefix=$InstallDir \ 259 --enable-optimized=$Optimized \ 260 --enable-assertions=$Assertions \ 261 --disable-timestamps \ 262 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log 263 cd $BuildDir 264 } 265 266 function build_llvmCore() { 267 Phase="$1" 268 Flavor="$2" 269 ObjDir="$3" 270 ExtraOpts="" 271 272 if [ "$Flavor" = "Release-64" ]; then 273 ExtraOpts="EXTRA_OPTIONS=-m64" 274 fi 275 276 cd $ObjDir 277 echo "# Compiling llvm $Release-$RC $Flavor" 278 echo "# ${MAKE} -j $NumJobs VERBOSE=1 $ExtraOpts" 279 ${MAKE} -j $NumJobs VERBOSE=1 $ExtraOpts \ 280 2>&1 | tee $LogDir/llvm.make-Phase$Phase-$Flavor.log 281 282 echo "# Installing llvm $Release-$RC $Flavor" 283 echo "# ${MAKE} install" 284 ${MAKE} install \ 285 2>&1 | tee $LogDir/llvm.install-Phase$Phase-$Flavor.log 286 cd $BuildDir 287 } 288 289 function build_dragonegg() { 290 Phase="$1" 291 Flavor="$2" 292 LLVMInstallDir="$3" 293 DragonEggObjDir="$4" 294 LLVM_CONFIG=$LLVMInstallDir/bin/llvm-config 295 TOP_DIR=$BuildDir/dragonegg.src 296 297 echo "# Targeted compiler: $gcc_compiler" 298 299 cd $DragonEggObjDir 300 echo "# Compiling phase $Phase dragonegg $Release-$RC $Flavor" 301 echo -n "# CXX=$cxx_compiler TOP_DIR=$TOP_DIR GCC=$gcc_compiler " 302 echo -n "LLVM_CONFIG=$LLVM_CONFIG ${MAKE} -f $TOP_DIR/Makefile " 303 echo "-j $NumJobs VERBOSE=1" 304 CXX="$cxx_compiler" TOP_DIR="$TOP_DIR" GCC="$gcc_compiler" \ 305 LLVM_CONFIG="$LLVM_CONFIG" ${MAKE} -f $TOP_DIR/Makefile \ 306 -j $NumJobs VERBOSE=1 \ 307 2>&1 | tee $LogDir/dragonegg-Phase$Phase-$Flavor.log 308 cd $BuildDir 309 } 310 311 function test_llvmCore() { 312 Phase="$1" 313 Flavor="$2" 314 ObjDir="$3" 315 316 cd $ObjDir 317 ${MAKE} -k check-all \ 318 2>&1 | tee $LogDir/llvm.check-Phase$Phase-$Flavor.log 319 ${MAKE} -k unittests \ 320 2>&1 | tee $LogDir/llvm.unittests-Phase$Phase-$Flavor.log 321 cd $BuildDir 322 } 323 324 set -e # Exit if any command fails 325 326 if [ "$do_checkout" = "yes" ]; then 327 export_sources 328 fi 329 330 ( 331 Flavors="Release" 332 if [ "$do_debug" = "yes" ]; then 333 Flavors="Debug $Flavors" 334 fi 335 if [ "$do_asserts" = "yes" ]; then 336 Flavors="$Flavors Release+Asserts" 337 fi 338 if [ "$do_64bit" = "yes" ]; then 339 Flavors="$Flavors Release-64" 340 fi 341 342 for Flavor in $Flavors ; do 343 echo "" 344 echo "" 345 echo "********************************************************************************" 346 echo " Release: $Release-$RC" 347 echo " Build: $Flavor" 348 echo " System Info: " 349 echo " `uname -a`" 350 echo "********************************************************************************" 351 echo "" 352 353 c_compiler="$CC" 354 cxx_compiler="$CXX" 355 356 llvmCore_phase1_objdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.obj 357 llvmCore_phase1_installdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.install 358 dragonegg_phase1_objdir=$BuildDir/Phase1/$Flavor/DragonEgg-$Release-$RC.obj 359 360 llvmCore_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.obj 361 llvmCore_phase2_installdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.install 362 llvmCore_de_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-DragonEgg-$Release-$RC.obj 363 llvmCore_de_phase2_installdir=$BuildDir/Phase2/$Flavor/llvmCore-DragonEgg-$Release-$RC.install 364 dragonegg_phase2_objdir=$BuildDir/Phase2/$Flavor/DragonEgg-$Release-$RC.obj 365 366 llvmCore_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.obj 367 llvmCore_phase3_installdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.install 368 llvmCore_de_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-DragonEgg-$Release-$RC.obj 369 llvmCore_de_phase3_installdir=$BuildDir/Phase3/$Flavor/llvmCore-DragonEgg-$Release-$RC.install 370 dragonegg_phase3_objdir=$BuildDir/Phase3/$Flavor/DragonEgg-$Release-$RC.obj 371 372 rm -rf $llvmCore_phase1_objdir 373 rm -rf $llvmCore_phase1_installdir 374 rm -rf $dragonegg_phase1_objdir 375 376 rm -rf $llvmCore_phase2_objdir 377 rm -rf $llvmCore_phase2_installdir 378 rm -rf $llvmCore_de_phase2_objdir 379 rm -rf $llvmCore_de_phase2_installdir 380 rm -rf $dragonegg_phase2_objdir 381 382 rm -rf $llvmCore_phase3_objdir 383 rm -rf $llvmCore_phase3_installdir 384 rm -rf $llvmCore_de_phase3_objdir 385 rm -rf $llvmCore_de_phase3_installdir 386 rm -rf $dragonegg_phase3_objdir 387 388 mkdir -p $llvmCore_phase1_objdir 389 mkdir -p $llvmCore_phase1_installdir 390 mkdir -p $dragonegg_phase1_objdir 391 392 mkdir -p $llvmCore_phase2_objdir 393 mkdir -p $llvmCore_phase2_installdir 394 mkdir -p $llvmCore_de_phase2_objdir 395 mkdir -p $llvmCore_de_phase2_installdir 396 mkdir -p $dragonegg_phase2_objdir 397 398 mkdir -p $llvmCore_phase3_objdir 399 mkdir -p $llvmCore_phase3_installdir 400 mkdir -p $llvmCore_de_phase3_objdir 401 mkdir -p $llvmCore_de_phase3_installdir 402 mkdir -p $dragonegg_phase3_objdir 403 404 ############################################################################ 405 # Phase 1: Build llvmCore and clang 406 echo "# Phase 1: Building llvmCore" 407 configure_llvmCore 1 $Flavor \ 408 $llvmCore_phase1_objdir $llvmCore_phase1_installdir 409 build_llvmCore 1 $Flavor \ 410 $llvmCore_phase1_objdir 411 412 # Test clang 413 if [ "$do_clang" = "yes" ]; then 414 ######################################################################## 415 # Phase 2: Build llvmCore with newly built clang from phase 1. 416 c_compiler=$llvmCore_phase1_installdir/bin/clang 417 cxx_compiler=$llvmCore_phase1_installdir/bin/clang++ 418 echo "# Phase 2: Building llvmCore" 419 configure_llvmCore 2 $Flavor \ 420 $llvmCore_phase2_objdir $llvmCore_phase2_installdir 421 build_llvmCore 2 $Flavor \ 422 $llvmCore_phase2_objdir 423 424 ######################################################################## 425 # Phase 3: Build llvmCore with newly built clang from phase 2. 426 c_compiler=$llvmCore_phase2_installdir/bin/clang 427 cxx_compiler=$llvmCore_phase2_installdir/bin/clang++ 428 echo "# Phase 3: Building llvmCore" 429 configure_llvmCore 3 $Flavor \ 430 $llvmCore_phase3_objdir $llvmCore_phase3_installdir 431 build_llvmCore 3 $Flavor \ 432 $llvmCore_phase3_objdir 433 434 ######################################################################## 435 # Testing: Test phase 3 436 echo "# Testing - built with clang" 437 test_llvmCore 3 $Flavor $llvmCore_phase3_objdir 438 439 ######################################################################## 440 # Compare .o files between Phase2 and Phase3 and report which ones 441 # differ. 442 if [ "$do_compare" = "yes" ]; then 443 echo 444 echo "# Comparing Phase 2 and Phase 3 files" 445 for o in `find $llvmCore_phase2_objdir -name '*.o'` ; do 446 p3=`echo $o | sed -e 's,Phase2,Phase3,'` 447 if ! cmp --ignore-initial=16 $o $p3 > /dev/null 2>&1 ; then 448 echo "file `basename $o` differs between phase 2 and phase 3" 449 fi 450 done 451 fi 452 fi 453 454 # Test dragonegg 455 if [ "$do_dragonegg" = "yes" ]; then 456 # Build dragonegg using the targeted gcc. This isn't necessary, but 457 # helps avoid using broken versions of gcc (which are legion), tests 458 # that the targeted gcc is basically sane and is consistent with the 459 # later phases in which the targeted gcc + dragonegg are used. 460 c_compiler="$gcc_compiler" 461 cxx_compiler="$gxx_compiler" 462 build_dragonegg 1 $Flavor $llvmCore_phase1_installdir $dragonegg_phase1_objdir 463 464 ######################################################################## 465 # Phase 2: Build llvmCore with newly built dragonegg from phase 1. 466 c_compiler="$gcc_compiler -fplugin=$dragonegg_phase1_objdir/dragonegg.so" 467 cxx_compiler="$gxx_compiler -fplugin=$dragonegg_phase1_objdir/dragonegg.so" 468 echo "# Phase 2: Building llvmCore with dragonegg" 469 configure_llvmCore 2 $Flavor \ 470 $llvmCore_de_phase2_objdir $llvmCore_de_phase2_installdir 471 build_llvmCore 2 $Flavor \ 472 $llvmCore_de_phase2_objdir 473 build_dragonegg 2 $Flavor $llvmCore_de_phase2_installdir $dragonegg_phase2_objdir 474 475 ######################################################################## 476 # Phase 3: Build llvmCore with newly built clang from phase 2. 477 c_compiler="$gcc_compiler -fplugin=$dragonegg_phase2_objdir/dragonegg.so" 478 cxx_compiler="$gxx_compiler -fplugin=$dragonegg_phase2_objdir/dragonegg.so" 479 echo "# Phase 3: Building llvmCore with dragonegg" 480 configure_llvmCore 3 $Flavor \ 481 $llvmCore_de_phase3_objdir $llvmCore_de_phase3_installdir 482 build_llvmCore 3 $Flavor \ 483 $llvmCore_de_phase3_objdir 484 build_dragonegg 3 $Flavor $llvmCore_de_phase3_installdir $dragonegg_phase3_objdir 485 486 ######################################################################## 487 # Testing: Test phase 3 488 c_compiler="$gcc_compiler -fplugin=$dragonegg_phase3_objdir/dragonegg.so" 489 cxx_compiler="$gxx_compiler -fplugin=$dragonegg_phase3_objdir/dragonegg.so" 490 echo "# Testing - built with dragonegg" 491 test_llvmCore 3 $Flavor $llvmCore_de_phase3_objdir 492 493 ######################################################################## 494 # Compare .o files between Phase2 and Phase3 and report which ones differ. 495 echo 496 echo "# Comparing Phase 2 and Phase 3 files" 497 for o in `find $llvmCore_de_phase2_objdir -name '*.o'` \ 498 `find $dragonegg_phase2_objdir -name '*.o'` ; do 499 p3=`echo $o | sed -e 's,Phase2,Phase3,'` 500 if ! cmp --ignore-initial=16 $o $p3 > /dev/null 2>&1 ; then 501 echo "file `basename $o` differs between dragonegg phase 2 and phase 3" 502 fi 503 done 504 fi 505 506 # Otherwise just test the core. 507 if [ "$do_clang" != "yes" -a "$do_dragonegg" != "yes" ]; then 508 echo "# Testing - built with system compiler" 509 test_llvmCore 1 $Flavor $llvmCore_phase1_objdir 510 fi 511 done 512 ) 2>&1 | tee $LogDir/testing.$Release-$RC.log 513 514 set +e 515 516 # Woo hoo! 517 echo "### Testing Finished ###" 518 echo "### Logs: $LogDir" 519 exit 0 520