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