2016-12-15 05:31:15 -05:00
#!/usr/bin/env bash
MASON_NAME = llvm
MASON_LIB_FILE = bin/clang
. ${ MASON_DIR } /mason.sh
export MAJOR_MINOR = $( echo ${ MASON_VERSION } | cut -d '.' -f1-2)
if [ [ $( uname -s) = = 'Darwin' ] ] ; then
export BUILD_AND_LINK_LIBCXX = false
2017-01-09 03:56:44 -05:00
# avoids this kind of problem with include-what-you-use
# because iwyu hardcodes at https://github.com/include-what-you-use/include-what-you-use/blob/da5c9b17fec571e6b2bbca29145463d7eaa3582e/iwyu_driver.cc#L219
2016-12-15 05:31:15 -05:00
: '
/Library/Developer/CommandLineTools/usr/include/c++/v1/cstdlib:167:44: error: declaration conflicts with target of using declaration already in scope
inline _LIBCPP_INLINE_VISIBILITY long abs( long __x) _NOEXCEPT { return labs( __x) ; }
^
/Users/dane/.mason/mason_packages/osx-x86_64/llvm/3.9.0/bin/../include/c++/v1/stdlib.h:115:44: note: target of using declaration
inline _LIBCPP_INLINE_VISIBILITY long abs( long __x) _NOEXCEPT { return labs( __x) ; }
'
else
export BUILD_AND_LINK_LIBCXX = ${ BUILD_AND_LINK_LIBCXX :- true }
fi
# we use this custom function rather than "mason_download" since we need to easily grab multiple packages
function get_llvm_project( ) {
local URL = ${ 1 }
local TO_DIR = ${ 2 }
if [ [ ${ TO_DIR :- false } = = false ] ] ; then
mason_error "TO_DIR unset"
exit 1
fi
local EXPECTED_HASH = ${ 3 :- false }
local file_basename = $( basename ${ URL } )
local local_file_or_checkout = $( pwd ) /${ file_basename }
if [ [ ${ URL } = ~ '.git' ] ] ; then
if [ ! -d ${ local_file_or_checkout } ] ; then
mason_step " cloning ${ URL } to ${ local_file_or_checkout } "
git clone --depth 1 ${ URL } ${ local_file_or_checkout }
else
mason_substep " already cloned ${ URL } , pulling to update "
( cd ${ local_file_or_checkout } && git pull)
fi
mason_step " moving ${ local_file_or_checkout } into place at ${ TO_DIR } "
cp -r ${ local_file_or_checkout } ${ TO_DIR }
else
if [ ! -f ${ local_file_or_checkout } ] ; then
mason_step " Downloading ${ URL } to ${ local_file_or_checkout } "
curl --retry 3 -f -L -O " ${ URL } "
else
mason_substep " already downloaded $1 to ${ local_file_or_checkout } "
fi
export OBJECT_HASH = $( git hash-object ${ local_file_or_checkout } )
if [ [ ${ EXPECTED_HASH :- false } = = false ] ] ; then
mason_error " Warning: no expected hash provided by script.sh, actual was ${ OBJECT_HASH } "
else
if [ [ $3 != ${ OBJECT_HASH } ] ] ; then
mason_error " Error: hash mismatch ${ EXPECTED_HASH } (expected) != ${ OBJECT_HASH } (actual) "
exit 1
else
mason_success " Success: hash matched: ${ EXPECTED_HASH } (expected) == ${ OBJECT_HASH } (actual) "
fi
fi
mason_step " uncompressing ${ local_file_or_checkout } "
mkdir -p ./checkout
rm -rf ./checkout/*
tar xf ${ local_file_or_checkout } --strip-components= 1 --directory= ./checkout
mkdir -p ${ TO_DIR }
mv checkout/* ${ TO_DIR } /
fi
}
# Note: override this function to set custom hash
function setup_release( ) {
get_llvm_project " http://llvm.org/releases/ ${ MASON_VERSION } /llvm- ${ MASON_VERSION } .src.tar.xz " ${ MASON_BUILD_PATH } /
get_llvm_project " http://llvm.org/releases/ ${ MASON_VERSION } /cfe- ${ MASON_VERSION } .src.tar.xz " ${ MASON_BUILD_PATH } /tools/clang
get_llvm_project " http://llvm.org/releases/ ${ MASON_VERSION } /compiler-rt- ${ MASON_VERSION } .src.tar.xz " ${ MASON_BUILD_PATH } /projects/compiler-rt
if [ [ ${ BUILD_AND_LINK_LIBCXX } = = true ] ] ; then
get_llvm_project " http://llvm.org/releases/ ${ MASON_VERSION } /libcxx- ${ MASON_VERSION } .src.tar.xz " ${ MASON_BUILD_PATH } /projects/libcxx
get_llvm_project " http://llvm.org/releases/ ${ MASON_VERSION } /libcxxabi- ${ MASON_VERSION } .src.tar.xz " ${ MASON_BUILD_PATH } /projects/libcxxabi
get_llvm_project " http://llvm.org/releases/ ${ MASON_VERSION } /libunwind- ${ MASON_VERSION } .src.tar.xz " ${ MASON_BUILD_PATH } /projects/libunwind
fi
get_llvm_project " http://llvm.org/releases/ ${ MASON_VERSION } /lld- ${ MASON_VERSION } .src.tar.xz " ${ MASON_BUILD_PATH } /tools/lld
get_llvm_project " http://llvm.org/releases/ ${ MASON_VERSION } /clang-tools-extra- ${ MASON_VERSION } .src.tar.xz " ${ MASON_BUILD_PATH } /tools/clang/tools/extra
get_llvm_project " http://llvm.org/releases/ ${ MASON_VERSION } /lldb- ${ MASON_VERSION } .src.tar.xz " ${ MASON_BUILD_PATH } /tools/lldb
get_llvm_project " https://github.com/include-what-you-use/include-what-you-use/archive/clang_ ${ MAJOR_MINOR } .tar.gz " ${ MASON_BUILD_PATH } /tools/clang/tools/include-what-you-use
}
function mason_load_source {
mkdir -p " ${ MASON_ROOT } /.cache "
cd " ${ MASON_ROOT } /.cache "
export MASON_BUILD_PATH = ${ MASON_ROOT } /.build/llvm-${ MASON_VERSION }
mkdir -p " ${ MASON_ROOT } /.build "
if [ [ -d ${ MASON_BUILD_PATH } / ] ] ; then
rm -rf ${ MASON_BUILD_PATH } /
fi
# NOTE: this setup_release can be overridden per package to assert on different hash
setup_release
}
function mason_prepare_compile {
CCACHE_VERSION = 3.3.1
CMAKE_VERSION = 3.6.2
NINJA_VERSION = 1.7.1
${ MASON_DIR } /mason install ccache ${ CCACHE_VERSION }
MASON_CCACHE = $( ${ MASON_DIR } /mason prefix ccache ${ CCACHE_VERSION } )
${ MASON_DIR } /mason install cmake ${ CMAKE_VERSION }
MASON_CMAKE = $( ${ MASON_DIR } /mason prefix cmake ${ CMAKE_VERSION } )
${ MASON_DIR } /mason install ninja ${ NINJA_VERSION }
MASON_NINJA = $( ${ MASON_DIR } /mason prefix ninja ${ NINJA_VERSION } )
if [ [ $( uname -s) = = 'Linux' ] ] ; then
BINUTILS_VERSION = 2.27
${ MASON_DIR } /mason install binutils ${ BINUTILS_VERSION }
LLVM_BINUTILS_INCDIR = $( ${ MASON_DIR } /mason prefix binutils ${ BINUTILS_VERSION } ) /include
fi
}
function mason_compile {
export CXX = " ${ CXX :- clang ++ } "
export CC = " ${ CC :- clang } "
# knock out lldb doc building, to remove doxygen dependency
perl -i -p -e "s/add_subdirectory\(docs\)//g;" tools/lldb/CMakeLists.txt
2017-01-09 03:56:44 -05:00
# remove /usr/local/include from default paths (targeting linux)
# because we want users to have to explictly link things in /usr/local to avoid conflicts
# between mason and homebrew or source installs
perl -i -p -e "s/AddPath\(\"\/usr\/local\/include\"\, System\, false\)\;//g;" tools/clang/lib/Frontend/InitHeaderSearch.cpp
2016-12-15 05:31:15 -05:00
if [ [ ${ MAJOR_MINOR } = = "3.8" ] ] ; then
# workaround https://llvm.org/bugs/show_bug.cgi?id=25565
perl -i -p -e "s/set\(codegen_deps intrinsics_gen\)/set\(codegen_deps intrinsics_gen attributes_inc\)/g;" lib/CodeGen/CMakeLists.txt
# note: LIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON is only needed with llvm < 3.9.0 to avoid libcxx(abi) build breaking when only a static libc++ exists
CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON "
fi
if [ [ -d tools/clang/tools/include-what-you-use ] ] ; then
echo 'add_subdirectory(include-what-you-use)' >> tools/clang/tools/CMakeLists.txt
fi
mkdir -p ./build
cd ./build
CMAKE_EXTRA_ARGS = ""
if [ [ $( uname -s) = = 'Darwin' ] ] ; then
2017-01-09 03:56:44 -05:00
: '
Note: C_INCLUDE_DIRS and DEFAULT_SYSROOT are critical options to understand to ensure C and C++ headers are predictably found.
The way things work in clang++ on OS X ( inside http://clang.llvm.org/doxygen/InitHeaderSearch_8cpp.html) is:
- The ` :` separated ` C_INCLUDE_DIRS` are added to the include paths
- If ` C_INCLUDE_DIRS` is present ` InitHeaderSearch::AddDefaultCIncludePaths` returns early
- Without that early return ` /usr/include` would be added by default on OS X
- If ` -isysroot` is passed then absolute ` C_INCLUDE_DIRS` are appended to the sysroot
- So if sysroot = /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/ and
C_INCLUDE_DIRS = /usr/include the actual path searched would be:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
- Relative ` C_INCLUDE_DIRS` seem pointless because they are not appended to the sysroot and so will not be portable
- clang++ finds C++ headers relative to itself at https://github.com/llvm-mirror/clang/blob/master/lib/Frontend/InitHeaderSearch.cpp#L469-L470
- So, given on OS X we want to use the XCode/Apple provided libc++ and c++ headers we symlink the relative location to /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++
- The alternative would be to symlink to the command line tools location ( /Library/Developer/CommandLineTools/usr/include/c++/v1/)
Another viable sysroot would be the command line tools at /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
Generally each SDK/Platform version has its own C headers inside SDK_PATH/usr/include while all platforms share the C++ headers which
are at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/
NOTE: show search paths with: ` clang -x c -v -E /dev/null` || ` cpp -v` && ` clang -Xlinker -v`
'
CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DC_INCLUDE_DIRS=/usr/include "
# setting the default sysroot to an explicit SDK avoids clang++ adding `/usr/local/include` to the paths by default at https://github.com/llvm-mirror/clang/blob/91d69c3c9c62946245a0fe6526d5ec226dfe7408/lib/Frontend/InitHeaderSearch.cpp#L226
# because that value will be appended to the sysroot, not exist, and then get thrown out. If the sysroot were / then it would be added
CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DDEFAULT_SYSROOT=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk "
2016-12-15 05:31:15 -05:00
CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DCLANG_DEFAULT_CXX_STDLIB=libc++ "
CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DCMAKE_OSX_DEPLOYMENT_TARGET=10.11 "
CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DLLVM_CREATE_XCODE_TOOLCHAIN=ON -DLLVM_EXTERNALIZE_DEBUGINFO=ON "
fi
if [ [ $( uname -s) = = 'Linux' ] ] ; then
CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DLLVM_BINUTILS_INCDIR= ${ LLVM_BINUTILS_INCDIR } "
if [ [ ${ MAJOR_MINOR } = = "3.8" ] ] && [ [ ${ BUILD_AND_LINK_LIBCXX } = = true ] ] ; then
# note: LIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON is only needed with llvm < 3.9.0 to avoid libcxx(abi) build breaking when only a static libc++ exists
CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON "
fi
fi
# we strip this since we don't care about older os x for this package
if [ [ $( uname -s) = = 'Darwin' ] ] ; then
export CXXFLAGS = " ${ CXXFLAGS //-mmacosx-version-min=10.8 } "
export LDFLAGS = " ${ LDFLAGS //-mmacosx-version-min=10.8 } "
fi
# llvm may request c++14 instead so let's not force c++11
export CXXFLAGS = " ${ CXXFLAGS //-std=c++11 } "
if [ [ ${ BUILD_AND_LINK_LIBCXX } = = true ] ] ; then
# we link to libc++ even on linux to avoid runtime dependency on libstdc++:
# https://github.com/mapbox/mason/issues/252
export CXXFLAGS = " -stdlib=libc++ ${ CXXFLAGS } "
export LDFLAGS = " -stdlib=libc++ ${ LDFLAGS } "
if [ [ $( uname -s) = = 'Linux' ] ] ; then
export LDFLAGS = " ${ LDFLAGS } -Wl,--start-group -L $( pwd ) /lib -lc++ -lc++abi -pthread -lc -lgcc_s "
fi
fi
2017-01-09 03:56:44 -05:00
# on linux the default is to link programs compiled by clang++ to libstdc++ and below we make that explicit.
if [ [ $( uname -s) = = 'Linux' ] ] ; then
export CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DCLANG_DEFAULT_CXX_STDLIB=libstdc++ "
fi
2016-12-15 05:31:15 -05:00
# TODO: test this
#-DLLVM_ENABLE_LTO=ON \
2017-01-09 03:56:44 -05:00
# TODO: try rtlib=compiler-rt on linux
# https://blogs.gentoo.org/gsoc2016-native-clang/2016/05/31/build-gnu-free-executables-with-clang/
2016-12-15 05:31:15 -05:00
if [ [ ${ BUILD_AND_LINK_LIBCXX } = = true ] ] ; then
CMAKE_EXTRA_ARGS = " ${ CMAKE_EXTRA_ARGS } -DLIBCXX_ENABLE_ASSERTIONS=OFF -DLIBCXX_ENABLE_SHARED=OFF -DLIBCXXABI_ENABLE_SHARED=OFF -DLIBCXXABI_USE_LLVM_UNWINDER=ON -DLIBUNWIND_ENABLE_SHARED=OFF "
fi
${ MASON_CMAKE } /bin/cmake ../ -G Ninja -DCMAKE_INSTALL_PREFIX= ${ MASON_PREFIX } \
-DCMAKE_BUILD_TYPE= Release \
2017-01-09 03:56:44 -05:00
-DLLVM_INCLUDE_DOCS= OFF \
-DLLVM_TARGETS_TO_BUILD= "X86" \
2016-12-15 05:31:15 -05:00
-DCMAKE_CXX_COMPILER_LAUNCHER= " ${ MASON_CCACHE } /bin/ccache " \
-DCMAKE_CXX_COMPILER= " $CXX " \
-DCMAKE_C_COMPILER= " $CC " \
-DLLVM_ENABLE_ASSERTIONS= OFF \
-DCLANG_VENDOR= "mapbox/mason" \
-DCLANG_REPOSITORY_STRING= "https://github.com/mapbox/mason" \
-DCLANG_VENDOR_UTI= "org.mapbox.llvm" \
-DCMAKE_EXE_LINKER_FLAGS= " ${ LDFLAGS } " \
-DCMAKE_CXX_FLAGS= " ${ CXXFLAGS } " \
-DLLDB_DISABLE_PYTHON= 1 -DLLDB_DISABLE_CURSES= 1 -DLLDB_DISABLE_LIBEDIT= 1 -DLLVM_ENABLE_TERMINFO= 0 \
-DCMAKE_MAKE_PROGRAM= ${ MASON_NINJA } /bin/ninja \
${ CMAKE_EXTRA_ARGS }
if [ [ ${ BUILD_AND_LINK_LIBCXX } = = true ] ] ; then
${ MASON_NINJA } /bin/ninja unwind -j${ MASON_CONCURRENCY }
# make libc++ and libc++abi first
${ MASON_NINJA } /bin/ninja cxx -j${ MASON_CONCURRENCY }
${ MASON_NINJA } /bin/ninja lldb -j${ MASON_CONCURRENCY }
fi
# then make everything else
${ MASON_NINJA } /bin/ninja -j${ MASON_CONCURRENCY }
2017-01-09 03:56:44 -05:00
2016-12-15 05:31:15 -05:00
# install it all
${ MASON_NINJA } /bin/ninja install
2017-01-09 03:56:44 -05:00
if [ [ $( uname -s) = = 'Darwin' ] ] ; then
# https://reviews.llvm.org/D13605
${ MASON_NINJA } /bin/ninja install-xcode-toolchain -j${ MASON_CONCURRENCY }
fi
2016-12-15 05:31:15 -05:00
# install the asan_symbolizer.py tool
cp -a ../projects/compiler-rt/lib/asan/scripts/asan_symbolize.py ${ MASON_PREFIX } /bin/
2017-01-09 03:56:44 -05:00
# set up symlinks to match what llvm.org binaries provide
2016-12-15 05:31:15 -05:00
cd ${ MASON_PREFIX } /bin/
ln -s "clang++" " clang++- ${ MAJOR_MINOR } "
ln -s "asan_symbolize.py" "asan_symbolize"
2017-01-09 03:56:44 -05:00
# symlink so that we use the system libc++ headers on osx
if [ [ $( uname -s) = = 'Darwin' ] ] ; then
mkdir -p ${ MASON_PREFIX } /include
cd ${ MASON_PREFIX } /include
# note: passing -nostdinc++ will result in this local path being ignored
ln -s /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++ c++
2016-12-15 05:31:15 -05:00
fi
}
2017-01-09 03:56:44 -05:00
2016-12-15 05:31:15 -05:00
function mason_cflags {
:
}
function mason_ldflags {
:
}
function mason_static_libs {
:
}