blob: cdef3d36039a3a7e5fa56f32a8a77a3d98da1a94 [file] [log] [blame]
#! /usr/bin/env bash
#
# TODO:
# - Try adding lldb once again.
OS=`uname`
if [ "$OS" == "Linux" ]; then
triple=""
soext="so"
somask="so.%s"
addl_ldflags="-ldl"
addl_cmake=""
elif [ "$OS" == "FreeBSD" ]; then
triple=""
soext="so"
somask="so.%s"
addl_ldflags=""
addl_cmake=""
elif [ "$OS" == "Darwin" ]; then
triple="-apple-"
soext="dylib"
somask="%d.dylib"
addl_ldflags=""
addl_cmake="-DCMAKE_OSX_ARCHITECTURES=x86_64;i386"
else
echo "OS $OS not supported by this script."
exit 1
fi
if [ -n "$CC" ]; then
cc=$CC
elif which clang > /dev/null 2>&1; then
cc=clang
elif which gcc > /dev/null 2>&1; then
cc=gcc
else
echo could not find clang or gcc in '$PATH'
exit 1
fi
if [ -n "$CXX" ]; then
cxx=$CXX
elif which clang++ > /dev/null 2>&1; then
cxx=clang++
elif which g++ > /dev/null 2>&1; then
cxx=g++
else
echo could not find clang++ or g++ in '$PATH'
exit 1
fi
use_master=0
perform_clone=1 # If 0, skip the cloning (for testing only).
perform_stage1=1 # If 0, skip the 1st bootstrap stage (for testing only).
perform_stage2=1 # If 0, skip the 2nd stage compiling LLVM/clang against libc++ (for testing only).
perform_lldb_build=0 # If 1, attempt to build LLDB.
perform_lld_build=0 # If 1, attempt to build LLDB.
perform_extra_build=1 # If 1, attempt to build clang-extra tools.
perform_cleanup=0 # If 1, delete all source and build directories.
assertions=off # If "on", enable LLVM assertions.
parallelism=1 # The value X to pass to make -j X to build in parallel.
buildtype=RelWithDebInfo # LLVM/clang build type.
mode=install # Install from scratch.
targets=host # LLVM_TARGETS_TO_BUILD ("all" builds them all).
if eval ${cxx} --version | grep -q clang; then
perform_stage0=0
have_clang=1
else
perform_stage0=1
have_clang=0
fi
usage()
{
printf "Usage: %s [<options>] <install-prefix>\n" $(basename $0)
echo ""
echo "Available options:"
echo " -A enables assertions in LLVM libraries"
echo " -b build type (Release, Debug, RelWithDebInfo) [default: ${buildtype}]"
echo " -c skip cloning repositories, assume they are in place"
echo " -C clean up after build by deleting the LLVM/clang source/build directories"
echo " -h|-? display this help"
echo " -j <n> build with <n> threads in parallel [default: ${parallelism}]"
echo " -m use git/master instead of preconfigured versions"
echo " -s <stage> begin build from <stage> [0, 1, 2]"
echo " -u update an existing build in <prefix> instead of installing new"
echo ""
echo "Environment variables:"
echo " CC path to the C compiler for bootstrapping"
echo " CXX path to the C++ compiler for bootstrapping"
}
while getopts "Ab::j:lms:ucCh?" opt ; do
case "$opt" in
c)
perform_clone=0
;;
C)
perform_cleanup=1
;;
h|\?)
usage
exit 0
;;
j)
parallelism=$OPTARG
;;
m)
use_master=1
;;
s)
if [ "$OPTARG" == "0" ]; then
perform_stage0=1
perform_stage1=1
perform_stage2=1
elif [ "$OPTARG" == "1" ]; then
perform_stage0=0
perform_stage1=1
perform_stage2=1
elif [ "$OPTARG" == "2" ]; then
perform_stage0=0
perform_stage1=0
perform_stage2=1
else
echo 'stage parameter must be in [0,1,2].'
exit 1
fi
;;
u)
mode=update
;;
A)
assertions=on
;;
b)
buildtype=$OPTARG
;;
esac
done
shift $(expr $OPTIND - 1)
prefix=`echo $1 | sed 's#/$##'`
shift
if [ "${use_master}" != "1" ]; then
# git version to checkout.
version_llvm=release_35
version_clang=release_35
version_libcxx=release_35
version_compilerrt=release_35
version_libcxxabi=239a032 # No 3.5 branch. Hardcoding.
version_lldb=master # No 3.5 branch. Probably won't work.
version_lld=master # No 3.5 branch. Probably won't work.
version_extra=release_35
cherrypick="projects/libcxx 0c6d1a88 e515bbda f2e8c0454" # Fix linking against in-tree libc++abi.
cherrypick="$cherrypick;/ 168d0c143" # Correctly add libc++abi to project list.
cherrypick="$cherrypick;/ d9aaca0ec" # Fix libc++abi build on FreeBSD.
else
# git version to checkout.
version_llvm=master
version_clang=master
version_libcxx=master
version_compilerrt=master
version_libcxxabi=master
version_lldb=master
version_lld=master
version_extra=master
fi
if [ "$mode" == "" -o "$prefix" == "" ]; then
usage
exit 1
fi
if [ ! -d $prefix ]; then
if [ "$mode" == "install" ]; then
if ! mkdir -p $prefix; then
echo failed to create directory $prefix
exit 1
fi
else
echo $prefix does not exist
exit 1
fi
fi
#### Copy all output to log file.
log=install.$$.log
echo "Recording log in $log ..."
exec > >(tee $log) # Requires fdescfs mounted to /dev/fd on FreeBSD.
exec 2>&1
#### Set paths and environment.
unset CFLAGS
unset CXXFLAGS
unset CPPFLAGS
unset LDFLAGS
unset LD_LIBRARY_PATH
unset DYLD_LIBRARY_PATH
# Built libraries with RTTI.
export REQUIRES_RTTI=1
export PATH=$prefix/bin:$PATH
src="$prefix/src/llvm"
src_libcxxabi=${src}/projects/libcxxabi
src_libcxx=${src}/projects/libcxx
src_compilerrt=${src}/projects/compiler-rt
src_lldb=${src}/lldb
src_lld=${src}/lld
libcxx_include=$prefix/include/c++/v1
libcxx_lib=$prefix/lib
default_includes=${libcxx_include}:/usr/include
mkdir -p $libcxx_include
function st
{
eval echo \$\{$1_stage${stage}\}
}
function add_include_path
{
include=$1
search_patch=$2
path=`find "${search_patch}" | grep "${include}$" | awk '{print length, $0;}' | sort -n | head -1 | awk '{printf("%s", $2)}'`
if [ "$path" != "" ]; then
path=`echo -n ${path} | sed "s#${include}##g"`
if [ "${default_includes}" = "" ]; then
echo -n "${path}"
else
echo -n "${default_includes}:${path}"
fi
fi
}
function apply_patch
{
patch=$1
base=`basename $patch`
cwd=`pwd`
cd $src
if basename "$patch" | grep -q -- '--'; then
dir=`echo $base | awk -v src=$src -F '--' '{printf("%s/%s/%s", src, $1, $2);}'`
if [ ! -d "$dir" ]; then
return
fi
cd $dir
fi
cat $patch | git am -3
}
#### Clone reposistories.
export GIT_COMMITTER_EMAIL="`whoami`@localhost"
export GIT_COMMITTER_NAME="`whoami`"
d=`dirname $0`
patches=`cd $d; pwd`/patches
if [ "${perform_clone}" == "1" ]; then
# Get/update the repositories.
if [ "$mode" == "install" ]; then
test -d $src && echo "$src already exists, aborting" && exit 1
mkdir -p $src
echo Changing directory to `dirname $src` for installing ...
cd `dirname $src`
git clone http://llvm.org/git/llvm.git `basename $src`
( cd $src/tools && git clone http://llvm.org/git/clang.git )
( cd $src/projects && git clone http://llvm.org/git/libcxx )
( cd $src/projects && git clone http://llvm.org/git/compiler-rt )
( cd $src && git checkout -q ${version_llvm} )
( cd $src/tools/clang && git checkout -q ${version_clang} )
( cd ${src_libcxx} && git checkout -q ${version_libcxx} )
( cd ${src_compilerrt} && git checkout -q ${version_compilerrt} )
( cd $src/projects && git clone http://llvm.org/git/libcxxabi )
( cd ${src_libcxxabi} && git checkout -q ${version_libcxxabi} )
if [ "${perform_extra_build}" == "1" ]; then
( cd $src/tools && git clone http://llvm.org/git/clang-tools-extra.git extra )
( cd $src/tools/extra && git checkout -q ${version_extra} )
fi
if [ "${perform_lldb_build}" == "1" ]; then
( cd `dirname ${src_lldb}` && git clone http://llvm.org/git/lldb `basename ${src_lldb}`)
( cd ${src_lldb} && git checkout -q ${version_lldb} )
fi
if [ "${perform_lld_build}" == "1" ]; then
( cd `dirname ${src_lld}` && git clone http://llvm.org/git/lld `basename ${src_lld}`)
( cd ${src_lld} && git checkout -q ${version_lld} )
fi
else
echo Changing directory to `dirname $src` for updating ...
cd `dirname $src`
( cd ${src} && git pull --rebase )
( cd ${src}/tools/clang && git pull --rebase )
( cd ${src_libcxx} && git pull --rebase )
( cd ${src_compilerrt} && git pull --rebase )
( cd $src && git checkout -q ${version_llvm} )
( cd $src/tools/clang && git checkout -q ${version_clang} )
( cd ${src_libcxx} && git checkout -q ${version_libcxx} )
( cd ${src_compilerrt} && git checkout -q ${version_compilerrt} )
( cd ${src_libcxxabi} && git pull --rebase )
( cd ${src_libcxxabi} && git checkout -q ${version_libcxxabi} )
if [ "${perform_extra_build}" == "1" ]; then
( cd $src/tools/extra && git pull --rebase )
( cd $src/tools/extra && git checkout -q ${version_extra} )
fi
if [ "${perform_lldb_build}" == "1" ]; then
( cd ${src_lldb} && git pull --rebase )
( cd ${src_lldb} && git checkout -q ${version_lldb} )
fi
if [ "${perform_lld_build}" == "1" ]; then
( cd ${src_lld} && git pull --rebase )
( cd ${src_lld} && git checkout -q ${version_lld} )
fi
fi
# Cherry pick additional commits from master.
echo "${cherrypick}" | awk -v RS=\; '{print}' | while read line; do
if [ "$line" != "" ]; then
repo=`echo $line | cut -d ' ' -f 1`
commits=`echo $line | cut -d ' ' -f 2-`
echo "Cherry-picking $commits in $repo"
( cd ${src}/$repo \
&& git cherry-pick --strategy=recursive -X theirs $commits )
fi
done
# Apply any patches we might need.
for i in $patches/*; do
apply_patch $i
done
echo === Done applying patches
fi
if [ "$OS" == "Darwin" ]; then
CMAKE_stage1="-DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++"
elif [ "$OS" == "Linux" ] || [ "$OS" == "FreeBSD" ]; then
CMAKE_stage1="-DLIBCXX_LIBCXXABI_WHOLE_ARCHIVE=on -DLIBCXXABI_ENABLE_SHARED=off -DBUILD_SHARED_LIBS=on"
CMAKE_stage2=$CMAKE_stage1
CMAKE_stage3=$CMAKE_stage1
default_includes=`add_include_path features.h /usr/include`
default_includes=`add_include_path sys/cdefs.h /usr/include`
else
echo "OS $OS not supported"
exit 1
fi
CMAKE_common="-DBUILD_SHARED_LIBS=on -DLLVM_TARGETS_TO_BUILD=${targets}"
CMAKE_stage0="${CMAKE_common} ${CMAKE_stage0} -DLLVM_INCLUDE_TOOLS=bootstrap-only -DLLVM_EXTERNAL_LIBCXX_BUILD=off -DLLVM_EXTERNAL_LIBCXXABI_BUILD=off -DLLVM_EXTERNAL_COMPILER_RT_BUILD=off"
CMAKE_stage1="${CMAKE_common} ${CMAKE_stage1} -DLLVM_INCLUDE_TOOLS=bootstrap-only -DLLVM_ENABLE_ASSERTIONS=${assertions} -DLLVM_EXTERNAL_LIBCXXABI_BUILD=on"
CMAKE_stage2="${CMAKE_common} ${CMAKE_stage2} -DLLVM_ENABLE_ASSERTIONS=${assertions}"
#### Configure the stages.
# Stage 0 options. Get us a clang.
CC_stage0="$cc"
CXX_stage0="$cxx"
CXXFLAGS_stage0=""
CMAKE_stage0="${CMAKE_stage0}"
BUILD_TYPE_stage0=${buildtype}
# Stage 1 options. Compile against standard libraries.
if [ "${have_clang}" == "1" ]; then
CC_stage1="$cc"
CXX_stage1="$cxx"
else
CC_stage1=$prefix/bin/clang
CXX_stage1=$prefix/bin/clang++
fi
CXXFLAGS_stage1=""
BUILD_TYPE_stage1=${buildtype}
# Stage 2 options. Compile against our own libraries.
CC_stage2=$prefix/bin/clang
CXX_stage2=$prefix/bin/clang++
CFLAGS_stage2="-stdlib=libc++"
CXXFLAGS_stage2="-stdlib=libc++"
CMAKE_stage2="${CMAKE_stage2}"
BUILD_TYPE_stage2=${buildtype}
#### Compile the stages.
echo Changing directory to $src ...
cd $src
for stage in 0 1 2; do
if [ "`st perform`" == "0" ]; then
continue
fi
echo ===
echo === Building LLVM/clang, stage ${stage} ...
echo ===
( cd $src &&\
mkdir -p build-stage${stage} && \
cd build-stage${stage} && \
CC=`st CC` \
CXX=`st CXX` \
CFLAGS="`st CFLAGS`" \
CXXFLAGS="`st CXXFLAGS`" \
LDFLAGS="${addl_ldflags}" \
cmake -DCMAKE_BUILD_TYPE=`st BUILD_TYPE` \
-DLLVM_REQUIRES_RTTI=1 \
-DCMAKE_INSTALL_PREFIX=${prefix} \
-DC_INCLUDE_DIRS=${default_includes} \
${addl_cmake} \
`st CMAKE` \
.. && \
make -j $parallelism && \
make install \
)
if [ "$?" != "0" ] ; then
echo ===
echo === Faild building LLVM/clang at stage ${stage}
echo ===
exit 1
fi
done
if [ "${perform_cleanup}" == "1" ]; then
echo Deleting $src ...
rm -rf "${src}"
fi
echo "===="
echo "==== Complete log in $log"
echo "===="