Since BSD cmp(1) does not support the --ignore-initial option, use the
[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       rpath=`objdump -x $Candidate | grep 'RPATH' | sed -e's/^ *RPATH *//'`
363       if [ -n "$rpath" ]; then
364         newrpath=`echo $rpath | sed -e's/.*\(\$ORIGIN[^:]*\).*/\1/'`
365         chrpath -r $newrpath $Candidate 2>&1 > /dev/null 2>&1
366       fi
367     fi
368   done
369 }
370
371 # Create a package of the release binaries.
372 function package_release() {
373     cwd=`pwd`
374     cd $BuildDir/Phase3/Release
375     mv llvmCore-$Release-$RC.install/usr/local $Package
376     if [ "$use_gzip" = "yes" ]; then
377       tar cfz $BuildDir/$Package.tar.gz $Package
378     else
379       tar cfJ $BuildDir/$Package.tar.xz $Package
380     fi
381     mv $Package llvmCore-$Release-$RC.install/usr/local
382     cd $cwd
383 }
384
385 # Exit if any command fails
386 # Note: pipefail is necessary for running build commands through
387 # a pipe (i.e. it changes the output of ``false | tee /dev/null ; echo $?``)
388 set -e
389 set -o pipefail
390
391 if [ "$do_checkout" = "yes" ]; then
392     export_sources
393 fi
394
395 (
396 Flavors="Release"
397 if [ "$do_debug" = "yes" ]; then
398     Flavors="Debug $Flavors"
399 fi
400 if [ "$do_asserts" = "yes" ]; then
401     Flavors="$Flavors Release+Asserts"
402 fi
403
404 for Flavor in $Flavors ; do
405     echo ""
406     echo ""
407     echo "********************************************************************************"
408     echo "  Release:     $Release-$RC"
409     echo "  Build:       $Flavor"
410     echo "  System Info: "
411     echo "    `uname -a`"
412     echo "********************************************************************************"
413     echo ""
414
415     c_compiler="$CC"
416     cxx_compiler="$CXX"
417
418     llvmCore_phase1_objdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.obj
419     llvmCore_phase1_destdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.install
420
421     llvmCore_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.obj
422     llvmCore_phase2_destdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.install
423
424     llvmCore_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.obj
425     llvmCore_phase3_destdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.install
426
427     rm -rf $llvmCore_phase1_objdir
428     rm -rf $llvmCore_phase1_destdir
429
430     rm -rf $llvmCore_phase2_objdir
431     rm -rf $llvmCore_phase2_destdir
432
433     rm -rf $llvmCore_phase3_objdir
434     rm -rf $llvmCore_phase3_destdir
435
436     mkdir -p $llvmCore_phase1_objdir
437     mkdir -p $llvmCore_phase1_destdir
438
439     mkdir -p $llvmCore_phase2_objdir
440     mkdir -p $llvmCore_phase2_destdir
441
442     mkdir -p $llvmCore_phase3_objdir
443     mkdir -p $llvmCore_phase3_destdir
444
445     ############################################################################
446     # Phase 1: Build llvmCore and clang
447     echo "# Phase 1: Building llvmCore"
448     configure_llvmCore 1 $Flavor $llvmCore_phase1_objdir
449     build_llvmCore 1 $Flavor \
450         $llvmCore_phase1_objdir $llvmCore_phase1_destdir
451     clean_RPATH $llvmCore_phase1_destdir/usr/local
452
453     ########################################################################
454     # Phase 2: Build llvmCore with newly built clang from phase 1.
455     c_compiler=$llvmCore_phase1_destdir/usr/local/bin/clang
456     cxx_compiler=$llvmCore_phase1_destdir/usr/local/bin/clang++
457     echo "# Phase 2: Building llvmCore"
458     configure_llvmCore 2 $Flavor $llvmCore_phase2_objdir
459     build_llvmCore 2 $Flavor \
460         $llvmCore_phase2_objdir $llvmCore_phase2_destdir
461     clean_RPATH $llvmCore_phase2_destdir/usr/local
462
463     ########################################################################
464     # Phase 3: Build llvmCore with newly built clang from phase 2.
465     c_compiler=$llvmCore_phase2_destdir/usr/local/bin/clang
466     cxx_compiler=$llvmCore_phase2_destdir/usr/local/bin/clang++
467     echo "# Phase 3: Building llvmCore"
468     configure_llvmCore 3 $Flavor $llvmCore_phase3_objdir
469     build_llvmCore 3 $Flavor \
470         $llvmCore_phase3_objdir $llvmCore_phase3_destdir
471     clean_RPATH $llvmCore_phase3_destdir/usr/local
472
473     ########################################################################
474     # Testing: Test phase 3
475     echo "# Testing - built with clang"
476     test_llvmCore 3 $Flavor $llvmCore_phase3_objdir
477
478     ########################################################################
479     # Compare .o files between Phase2 and Phase3 and report which ones
480     # differ.
481     if [ "$do_compare" = "yes" ]; then
482         echo
483         echo "# Comparing Phase 2 and Phase 3 files"
484         for p2 in `find $llvmCore_phase2_objdir -name '*.o'` ; do
485             p3=`echo $p2 | sed -e 's,Phase2,Phase3,'`
486             # Substitute 'Phase2' for 'Phase3' in the Phase 2 object file in
487             # case there are build paths in the debug info. On some systems,
488             # sed adds a newline to the output, so pass $p3 through sed too.
489             if ! cmp -s <(sed -e 's,Phase2,Phase3,g' $p2) <(sed -e '' $p3) \
490                     16 16 ; then
491                 echo "file `basename $p2` differs between phase 2 and phase 3"
492             fi
493         done
494     fi
495 done
496 ) 2>&1 | tee $LogDir/testing.$Release-$RC.log
497
498 package_release
499
500 set +e
501
502 # Woo hoo!
503 echo "### Testing Finished ###"
504 if [ "$use_gzip" = "yes" ]; then
505   echo "### Package: $Package.tar.gz"
506 else
507   echo "### Package: $Package.tar.xz"
508 fi
509 echo "### Logs: $LogDir"
510 exit 0