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