test-release.sh: Add ability to do a test build using the trunk or branches.
[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"
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     cd $BuildDir
248 }
249
250 function configure_llvmCore() {
251     Phase="$1"
252     Flavor="$2"
253     ObjDir="$3"
254
255     case $Flavor in
256         Release )
257             BuildType="Release"
258             Assertions="OFF"
259             ConfigureFlags="--enable-optimized --disable-assertions"
260             ;;
261         Release+Asserts )
262             BuildType="Release"
263             Assertions="ON"
264             ConfigureFlags="--enable-optimized --enable-assertions"
265             ;;
266         Debug )
267             BuildType="Debug"
268             Assertions="ON"
269             ConfigureFlags="--disable-optimized --enable-assertions"
270             ;;
271         * )
272             echo "# Invalid flavor '$Flavor'"
273             echo ""
274             return
275             ;;
276     esac
277
278     echo "# Using C compiler: $c_compiler"
279     echo "# Using C++ compiler: $cxx_compiler"
280
281     cd $ObjDir
282     echo "# Configuring llvm $Release-$RC $Flavor"
283
284     if [ "$use_autoconf" = "yes" ]; then
285         echo "#" env CC="$c_compiler" CXX="$cxx_compiler" \
286             $BuildDir/llvm.src/configure \
287             $ConfigureFlags --disable-timestamps $ExtraConfigureFlags \
288             2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log
289         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     else
294         echo "#" env CC="$c_compiler" CXX="$cxx_compiler" \
295             cmake -G "Unix Makefiles" \
296             -DCMAKE_BUILD_TYPE=$BuildType -DLLVM_ENABLE_ASSERTIONS=$Assertions \
297             -DLLVM_ENABLE_TIMESTAMPS=OFF -DLLVM_CONFIGTIME="(timestamp not enabled)" \
298             $ExtraConfigureFlags $BuildDir/llvm.src \
299             2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log
300         env CC="$c_compiler" CXX="$cxx_compiler" \
301             cmake -G "Unix Makefiles" \
302             -DCMAKE_BUILD_TYPE=$BuildType -DLLVM_ENABLE_ASSERTIONS=$Assertions \
303             -DLLVM_ENABLE_TIMESTAMPS=OFF -DLLVM_CONFIGTIME="(timestamp not enabled)" \
304             $ExtraConfigureFlags $BuildDir/llvm.src \
305             2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log
306     fi
307
308     cd $BuildDir
309 }
310
311 function build_llvmCore() {
312     Phase="$1"
313     Flavor="$2"
314     ObjDir="$3"
315     DestDir="$4"
316
317     cd $ObjDir
318     echo "# Compiling llvm $Release-$RC $Flavor"
319     echo "# ${MAKE} -j $NumJobs VERBOSE=1"
320     ${MAKE} -j $NumJobs VERBOSE=1 \
321         2>&1 | tee $LogDir/llvm.make-Phase$Phase-$Flavor.log
322
323     echo "# Installing llvm $Release-$RC $Flavor"
324     echo "# ${MAKE} install"
325     ${MAKE} install \
326         DESTDIR="${DestDir}" \
327         2>&1 | tee $LogDir/llvm.install-Phase$Phase-$Flavor.log
328     cd $BuildDir
329 }
330
331 function test_llvmCore() {
332     Phase="$1"
333     Flavor="$2"
334     ObjDir="$3"
335
336     cd $ObjDir
337     ${MAKE} -j $NumJobs -k check-all \
338         2>&1 | tee $LogDir/llvm.check-Phase$Phase-$Flavor.log
339
340     if [ "$use_autoconf" = "yes" ]; then
341         # In the cmake build, unit tests are run as part of check-all.
342         ${MAKE} -k unittests \
343             2>&1 | tee $LogDir/llvm.unittests-Phase$Phase-$Flavor.log
344     fi
345
346     cd $BuildDir
347 }
348
349 # Clean RPATH. Libtool adds the build directory to the search path, which is
350 # not necessary --- and even harmful --- for the binary packages we release.
351 function clean_RPATH() {
352   if [ `uname -s` = "Darwin" ]; then
353     return
354   fi
355   local InstallPath="$1"
356   for Candidate in `find $InstallPath/{bin,lib} -type f`; do
357     if file $Candidate | grep ELF | egrep 'executable|shared object' > /dev/null 2>&1 ; then
358       rpath=`objdump -x $Candidate | grep 'RPATH' | sed -e's/^ *RPATH *//'`
359       if [ -n "$rpath" ]; then
360         newrpath=`echo $rpath | sed -e's/.*\(\$ORIGIN[^:]*\).*/\1/'`
361         chrpath -r $newrpath $Candidate 2>&1 > /dev/null 2>&1
362       fi
363     fi
364   done
365 }
366
367 # Create a package of the release binaries.
368 function package_release() {
369     cwd=`pwd`
370     cd $BuildDir/Phase3/Release
371     mv llvmCore-$Release-$RC.install $Package
372     if [ "$use_gzip" = "yes" ]; then
373       tar cfz $BuildDir/$Package.tar.gz $Package
374     else
375       tar cfJ $BuildDir/$Package.tar.xz $Package
376     fi
377     mv $Package llvmCore-$Release-$RC.install
378     cd $cwd
379 }
380
381 # Exit if any command fails
382 # Note: pipefail is necessary for running build commands through
383 # a pipe (i.e. it changes the output of ``false | tee /dev/null ; echo $?``)
384 set -e
385 set -o pipefail
386
387 if [ "$do_checkout" = "yes" ]; then
388     export_sources
389 fi
390
391 (
392 Flavors="Release"
393 if [ "$do_debug" = "yes" ]; then
394     Flavors="Debug $Flavors"
395 fi
396 if [ "$do_asserts" = "yes" ]; then
397     Flavors="$Flavors Release+Asserts"
398 fi
399
400 for Flavor in $Flavors ; do
401     echo ""
402     echo ""
403     echo "********************************************************************************"
404     echo "  Release:     $Release-$RC"
405     echo "  Build:       $Flavor"
406     echo "  System Info: "
407     echo "    `uname -a`"
408     echo "********************************************************************************"
409     echo ""
410
411     c_compiler="$CC"
412     cxx_compiler="$CXX"
413
414     llvmCore_phase1_objdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.obj
415     llvmCore_phase1_destdir=$BuildDir/Phase1/$Flavor/llvmCore-$Release-$RC.install
416
417     llvmCore_phase2_objdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.obj
418     llvmCore_phase2_destdir=$BuildDir/Phase2/$Flavor/llvmCore-$Release-$RC.install
419
420     llvmCore_phase3_objdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.obj
421     llvmCore_phase3_destdir=$BuildDir/Phase3/$Flavor/llvmCore-$Release-$RC.install
422
423     rm -rf $llvmCore_phase1_objdir
424     rm -rf $llvmCore_phase1_destdir
425
426     rm -rf $llvmCore_phase2_objdir
427     rm -rf $llvmCore_phase2_destdir
428
429     rm -rf $llvmCore_phase3_objdir
430     rm -rf $llvmCore_phase3_destdir
431
432     mkdir -p $llvmCore_phase1_objdir
433     mkdir -p $llvmCore_phase1_destdir
434
435     mkdir -p $llvmCore_phase2_objdir
436     mkdir -p $llvmCore_phase2_destdir
437
438     mkdir -p $llvmCore_phase3_objdir
439     mkdir -p $llvmCore_phase3_destdir
440
441     ############################################################################
442     # Phase 1: Build llvmCore and clang
443     echo "# Phase 1: Building llvmCore"
444     configure_llvmCore 1 $Flavor $llvmCore_phase1_objdir
445     build_llvmCore 1 $Flavor \
446         $llvmCore_phase1_objdir $llvmCore_phase1_destdir
447     clean_RPATH $llvmCore_phase1_destdir/usr/local
448
449     ########################################################################
450     # Phase 2: Build llvmCore with newly built clang from phase 1.
451     c_compiler=$llvmCore_phase1_destdir/usr/local/bin/clang
452     cxx_compiler=$llvmCore_phase1_destdir/usr/local/bin/clang++
453     echo "# Phase 2: Building llvmCore"
454     configure_llvmCore 2 $Flavor $llvmCore_phase2_objdir
455     build_llvmCore 2 $Flavor \
456         $llvmCore_phase2_objdir $llvmCore_phase2_destdir
457     clean_RPATH $llvmCore_phase2_destdir/usr/local
458
459     ########################################################################
460     # Phase 3: Build llvmCore with newly built clang from phase 2.
461     c_compiler=$llvmCore_phase2_destdir/usr/local/bin/clang
462     cxx_compiler=$llvmCore_phase2_destdir/usr/local/bin/clang++
463     echo "# Phase 3: Building llvmCore"
464     configure_llvmCore 3 $Flavor $llvmCore_phase3_objdir
465     build_llvmCore 3 $Flavor \
466         $llvmCore_phase3_objdir $llvmCore_phase3_destdir
467     clean_RPATH $llvmCore_phase3_destdir/usr/local
468
469     ########################################################################
470     # Testing: Test phase 3
471     echo "# Testing - built with clang"
472     test_llvmCore 3 $Flavor $llvmCore_phase3_objdir
473
474     ########################################################################
475     # Compare .o files between Phase2 and Phase3 and report which ones
476     # differ.
477     if [ "$do_compare" = "yes" ]; then
478         echo
479         echo "# Comparing Phase 2 and Phase 3 files"
480         for p2 in `find $llvmCore_phase2_objdir -name '*.o'` ; do
481             p3=`echo $p2 | sed -e 's,Phase2,Phase3,'`
482             # Substitute 'Phase2' for 'Phase3' in the Phase 2 object file in
483             # case there are build paths in the debug info. On some systems,
484             # sed adds a newline to the output, so pass $p3 through sed too.
485             if ! cmp --ignore-initial=16 <(sed -e 's,Phase2,Phase3,g' $p2) \
486                     <(sed -e '' $p3) > /dev/null 2>&1 ; then
487                 echo "file `basename $p2` differs between phase 2 and phase 3"
488             fi
489         done
490     fi
491 done
492 ) 2>&1 | tee $LogDir/testing.$Release-$RC.log
493
494 package_release
495
496 set +e
497
498 # Woo hoo!
499 echo "### Testing Finished ###"
500 if [ "$use_gzip" = "yes" ]; then
501   echo "### Package: $Package.tar.gz"
502 else
503   echo "### Package: $Package.tar.xz"
504 fi
505 echo "### Logs: $LogDir"
506 exit 0