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