diff options
Diffstat (limited to 'scripts/build/p-llvm.inc')
-rw-r--r-- | scripts/build/p-llvm.inc | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/scripts/build/p-llvm.inc b/scripts/build/p-llvm.inc new file mode 100644 index 00000000..4e0740a2 --- /dev/null +++ b/scripts/build/p-llvm.inc @@ -0,0 +1,366 @@ +validate_build_config_llvm() { + # Check variables that are needed for building + [[ -n "${LLVM_SRC_BASE}" ]] || { echo "LLVM_SRC_BASE not set"; exit 1; } + [[ -n "${LLVM_VERSION_SHORT}" ]] || { echo "LLVM_VERSION_SHORT not set"; exit 1; } +} + +setup_build_variables_llvm() { + LLVM_SUFFIX="" + + local BuildMode="" + local enable_optimized=$(to_bool "${ENABLE_OPTIMIZED}") + local enable_debug=$(to_bool "${ENABLE_DEBUG}") + local disable_assertions=$(to_bool "${DISABLE_ASSERTIONS}") + local requires_rtti=$(to_bool "${REQUIRES_RTTI}") + + if [[ "${enable_optimized}" == "1" ]]; then + LLVM_SUFFIX+="_O" + BuildMode="Release" + else + LLVM_SUFFIX+="_NO" + fi + + if [[ ("${enable_debug}" == "1") || ("${enable_optimized}" != "1") ]]; then + LLVM_SUFFIX+="_D" + [ -z "$BuildMode" ] && BuildMode="Debug" || BuildMode="$BuildMode+Debug" + else + LLVM_SUFFIX+="_ND" + fi + + if [[ "${disable_assertions}" == "1" || -z "${disable_assertions}" ]]; then + LLVM_SUFFIX+="_NA" + else + LLVM_SUFFIX+="_A" + [ -z "$BuildMode" ] && BuildMode="Asserts" || BuildMode="$BuildMode+Asserts" + fi + + if [[ "${requires_rtti}" == "1" ]]; then + LLVM_SUFFIX+="_RTTI" + fi + + if [[ "${SANITIZER_SUFFIX}x" != "x" ]]; then + LLVM_SUFFIX+="${SANITIZER_SUFFIX}" + fi + + LLVM_SRC_BASE="${BASE}/llvm-${LLVM_VERSION_SHORT}" + LLVM_BUILD="${LLVM_SRC_BASE}-build${LLVM_SUFFIX}" + LLVM_INSTALL="${LLVM_SRC_BASE}-install${LLVM_SUFFIX}" + LLVM_BIN="${LLVM_INSTALL}/bin" + if [[ ${LLVM_VERSION_SHORT} -le 37 ]]; then + LLVM_BUILDMODE="$BuildMode" + LLVM_BUILD_BIN="${LLVM_BUILD}/${LLVM_BUILDMODE}/bin" + else + LLVM_BUILD_BIN="${LLVM_BUILD}/bin" + fi + + LLVM_CONFIG="${LLVM_BIN}/llvm-config" + BITCODE_CC="${LLVM_BIN}/clang" + BITCODE_CXX="${LLVM_BIN}/clang++" + + + for sanitizer in "${SANITIZERS[@]}"; do + [[ -z "${sanitizer}" ]] && continue + # Undefined Behaviour Sanitizer + if [ "${sanitizer}" == "memory" ]; then + SANITIZER_LLVM_UNINSTRUMENTED="${LLVM_BUILD}_uninstrumented" + SANITIZER_LLVM_LIBCXX="${LLVM_BUILD}_libcxx" + + SANITIZER_C_COMPILER="${SANITIZER_LLVM_UNINSTRUMENTED}/bin/clang" + SANITIZER_CXX_COMPILER="${SANITIZER_LLVM_UNINSTRUMENTED}/bin/clang++" + SANITIZER_CMAKE_C_COMPILER=("-DCMAKE_C_COMPILER=${SANITIZER_C_COMPILER}") + SANITIZER_CMAKE_CXX_COMPILER=("-DCMAKE_CXX_COMPILER=${SANITIZER_CXX_COMPILER}") + + MSAN_LINK_FLAGS=("-lc++abi" "-Wl,--rpath=${SANITIZER_LLVM_LIBCXX}/lib" "-L${SANITIZER_LLVM_LIBCXX}/lib") + MSAN_FLAGS=("${MSAN_LINK_FLAGS[@]}" -nostdinc++ + -isystem "${SANITIZER_LLVM_LIBCXX}/include" + -isystem "${SANITIZER_LLVM_LIBCXX}/include/c++/v1" + "-fsanitize=memory" + "-fsanitize-memory-track-origins" + -w -fno-omit-frame-pointer -g) + SANITIZER_CXX_FLAGS+=("${MSAN_FLAGS[@]}" "-stdlib=libc++") + SANITIZER_C_FLAGS+=("${MSAN_FLAGS[@]}") + SANITIZER_LD_FLAGS+=("${MSAN_LINK_FLAGS[@]}") + + # Use the uninstrumented compiler + BITCODE_CC="${SANITIZER_C_COMPILER}" + BITCODE_CXX="${SANITIZER_CXX_COMPILER}" + # But point to the instrumented llvm-config + LLVM_CONFIG="${LLVM_BIN}/llvm-config" + continue + fi + # Setup default sanitizer arguments + SANITIZER_C_COMPILER="${LLVM_BIN}/clang" + SANITIZER_CXX_COMPILER="${LLVM_BIN}/clang++" + done +} + +download_llvm() { + # Skip step if we already checked out code + [[ -f "${LLVM_SRC_BASE}/.src_checked_out" ]] && return 0 + + # Checkout LLVM code + svn co "http://llvm.org/svn/llvm-project/llvm/branches/release_${LLVM_VERSION_SHORT}" "${LLVM_SRC_BASE}" + cd "${LLVM_SRC_BASE}/tools" || (echo "Directory does not exist"; exit 1) + svn co "http://llvm.org/svn/llvm-project/cfe/branches/release_${LLVM_VERSION_SHORT}" clang + cd "${LLVM_SRC_BASE}/projects" || (echo "Directory does not exist"; exit 1) + svn co "http://llvm.org/svn/llvm-project/compiler-rt/branches/release_${LLVM_VERSION_SHORT}" compiler-rt + + if [[ ${LLVM_VERSION_SHORT} -gt 37 ]]; then + cd "${LLVM_SRC_BASE}/projects" || (echo "Directory does not exist"; exit 1) + svn co "http://llvm.org/svn/llvm-project/libcxx/branches/release_${LLVM_VERSION_SHORT}" libcxx + cd "${LLVM_SRC_BASE}/projects" || (echo "Directory does not exist"; exit 1) + svn co "http://llvm.org/svn/llvm-project/libcxxabi/branches/release_${LLVM_VERSION_SHORT}" libcxxabi + fi + + # Apply existing patches if needed + if [ -f "${DIR}/patches/llvm${LLVM_VERSION_SHORT}.patch" ]; then + cd "${LLVM_SRC_BASE}" || (echo "Directory does not exist"; exit 1) + patch -p0 -i "${DIR}/patches/llvm${LLVM_VERSION_SHORT}.patch" + fi + + touch "${LLVM_SRC_BASE}/.src_checked_out" +} + +build_llvm() { + local enable_optimized=$(to_bool "${ENABLE_OPTIMIZED}") + local enable_debug=$(to_bool "${ENABLE_DEBUG}") + local disable_assertions=$(to_bool "${DISABLE_ASSERTIONS}") + local requires_rtti=$(to_bool "${REQUIRES_RTTI}") + + # For memory sanitizer, we have a multi-stage build process + if [[ "${SANITIZER_BUILD}" == "memory" ]]; then + if [[ ${LLVM_VERSION_SHORT} -le 37 ]]; then + echo "Memory sanitizer builds for <= LLVM 3.7 are not supported" + exit 1 + fi + # Build uninstrumented compiler + mkdir -p "${SANITIZER_LLVM_UNINSTRUMENTED}" + cd "${SANITIZER_LLVM_UNINSTRUMENTED}" + cmake -GNinja -DCMAKE_BUILD_TYPE=Release "${LLVM_SRC_BASE}" + ninja + + # Build instrumented libc/libc++ + mkdir -p "${SANITIZER_LLVM_LIBCXX}" + cd "${SANITIZER_LLVM_LIBCXX}" + cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DLLVM_USE_SANITIZER=MemoryWithOrigins \ + "${SANITIZER_CMAKE_C_COMPILER}" \ + "${SANITIZER_CMAKE_CXX_COMPILER}" \ + "${LLVM_SRC_BASE}" + ninja cxx cxxabi + + # Build instrumented clang + mkdir -p "${LLVM_BUILD}" + cd "${LLVM_BUILD}" + C_F="${SANITIZER_C_FLAGS[*]}" + CXX_F="${SANITIZER_CXX_FLAGS[*]}" + LD_F="${SANITIZER_LD_FLAGS[*]}" + cmake -GNinja \ + "${SANITIZER_CMAKE_C_COMPILER[*]}" \ + "${SANITIZER_CMAKE_CXX_COMPILER[*]}" \ + -DCMAKE_C_FLAGS="$C_F" \ + -DCMAKE_CXX_FLAGS="${CXX_F}" \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + -DLLVM_ENABLE_ASSERTIONS=On \ + -DLLVM_USE_SANITIZER=MemoryWithOrigins \ + -DLLVM_ENABLE_LIBCXX=ON \ + -DCMAKE_EXE_LINKER_FLAGS="${LD_F}" \ + -DCMAKE_INSTALL_PREFIX="${LLVM_INSTALL}" \ + "${LLVM_SRC_BASE}" + # Build clang as a dependency and install all needed packages + ninja clang + return 0 + fi + + # Configure; build; and install + mkdir -p "${LLVM_BUILD}" + cd "${LLVM_BUILD}" + + # Skip building if already finished + [[ -e "${LLVM_BUILD}/.build_finished" ]] && return 0 + + + # Configure LLVM + if [[ ${LLVM_VERSION_SHORT} -le 37 ]]; then + local CONFIG=("--enable-jit" "--prefix=${LLVM_INSTALL}") + if [[ "${enable_optimized}" == "1" ]]; then + CONFIG+=(--enable-optimized) + else + CONFIG+=(--disable-optimized) + fi + + if [[ "${disable_assertions}" == "1" ]]; then + CONFIG+=(--disable-assertions) + else + CONFIG+=(--enable-assertions) + fi + + if [[ "${enable_debug}" == "1" ]]; then + CONFIG+=(--enable-debug-runtime --enable-debug-symbols) + else + CONFIG+=(--disable-debug-symbols) + fi + + local variables=() + if [[ -n "${CC:-}" ]]; then + variables+=("CC=${CC}") + fi + + if [[ -n "${CXX:-}" ]]; then + variables+=("CXX=${CXX}") + fi + + if [[ -n "${LDFLAGS:-}" ]]; then + variables+=("LDFLAGS=${LLVM_LDFLAGS}") + fi + + if [[ -n "${LLVM_CFLAGS:-}" ]]; then + variables+=("CFLAGS=${LLVM_CFLAGS}") + fi + + if [[ -n "${LLVM_CXXFLAGS:-}" ]]; then + variables+=("CXXFLAGS=${LLVM_CXXFLAGS}") + fi + + if [[ -n "${LLVM_LDFLAGS:-}" ]]; then + variables+=("LDFLAGS=${LLVM_LDFLAGS}") + fi + ${variables[@]+"${variables[@]}"} "${LLVM_SRC_BASE}/configure" "${CONFIG[@]}" + + else + CONFIG=( + "-DCMAKE_INSTALL_PREFIX=${LLVM_INSTALL}" + "-LLVM_BUILD_LLVM_DYLIB=TRUE" + ) + # cmake build + if [[ "${enable_optimized}" == "1" && "${enable_debug}" != "1" ]]; then + CONFIG+=("-DCMAKE_BUILD_TYPE=Release") + fi + if [[ "${enable_optimized}" == "1" && "${enable_debug}" == "1" ]]; then + CONFIG+=("-DCMAKE_BUILD_TYPE=RelWithDebInfo") + fi + if [[ "${enable_optimized}" != "1" && "${enable_debug}" == "1" ]]; then + CONFIG+=("-DCMAKE_BUILD_TYPE=Debug") + fi + + if [[ "${disable_assertions}" == "1" ]]; then + CONFIG+=("-DLLVM_ENABLE_ASSERTIONS=Off") + else + CONFIG+=("-DLLVM_ENABLE_ASSERTIONS=On") + fi + + if [[ -n "${LLVM_CFLAGS:-}" ]]; then + CONFIG+=("-DCMAKE_C_FLAGS=\"$LLVM_CFLAGS\"") + fi + + if [[ -n "${LLVM_CXXFLAGS:-}" ]]; then + CONFIG+=("-DCMAKE_CXX_FLAGS=\"$LLVM_CXXFLAGS\"") + fi + + if [[ "${requires_rtti}" -eq 1 ]]; then + CONFIG+=("-DLLVM_ENABLE_RTTI=TRUE") + fi + + # Remove unneeded targets + CONFIG+=( + -DLLVM_INCLUDE_EXAMPLES=OFF +# -DLLVM_INCLUDE_TESTS=OFF +# -DCLANG_INCLUDE_TESTS=OFF + -DLLVM_INCLUDE_BENCHMARKS=OFF + -DBUILD_SHARED_LIBS=ON + ) + + local variables=("") + + if [[ -n "${CC:-}" ]]; then + variables+=("CC=${CC}") + fi + + if [[ -n "${CXX:-}" ]]; then + variables+=("CXX=${CXX}") + fi + + if [[ -n "${LDFLAGS:-}" ]]; then + variables+=("LDFLAGS=${LLVM_LDFLAGS}") + fi + + if [[ -n "${variables[*]}" ]]; then + "${variables[*]}" cmake "${CONFIG[@]}" "${LLVM_SRC_BASE}" + else + cmake "${CONFIG[@]}" "${LLVM_SRC_BASE}" + fi + fi + + # Linking LLVM can require a lot of memory. + # First try multicore - if that doesn't work, try single core + (make "-j$(nproc)") || (make) || return 1 + touch "${LLVM_BUILD}/.build_finished" +} + +install_llvm() { + if [[ "${SANITIZER_BUILD}" != "memory" ]]; then + cd "${LLVM_BUILD}" + make "-j$(nproc)" install + cp "${LLVM_BUILD_BIN}/FileCheck" "${LLVM_INSTALL}/bin/" + cp "${LLVM_BUILD_BIN}/not" "${LLVM_INSTALL}/bin/" + + # Remove debug information from binaries + strip "${LLVM_INSTALL}/bin/"* || /bin/true + strip "${LLVM_INSTALL}/lib/libclang"* || /bin/true + strip "${LLVM_INSTALL}/lib/libLTO"* || /bin/true + else + # Handle memory sanitizer install + LLVM_PACKAGES=( \ + install-clang install-llvm-config install-llvm-objdump + install-llvm-link install-llvm-ar install-llvm-nm install-llvm-dis + install-clang-headers install-llvm-as + install-llvm-symbolizer install-LLVMSupport install-lli not FileCheck ) + + if [[ ${LLVM_VERSION_SHORT} -eq 38 ]]; then + LLVM_PACKAGES=("${LLVM_PACKAGES[@]}" installhdrs) + else + LLVM_PACKAGES=("${LLVM_PACKAGES[@]}" install-llvm-headers) + fi + + ninja "${LLVM_PACKAGES[@]}" + + for i in $(ninja -t targets |grep install-LLVM | cut -d : -f 1); do ninja "$i"; done + + cp "${LLVM_BUILD}/bin/FileCheck" "${LLVM_INSTALL}/bin/" + cp "${LLVM_BUILD}/bin/not" "${LLVM_INSTALL}/bin/" + fi + + touch "${LLVM_INSTALL}/.install_finished" +} + +# Check if the binary artifact is installed +is_installed_llvm() { + ( + setup_build_variables_llvm + # Check if the specific llvm-config exists + [[ -f "${LLVM_BUILD_BIN}/llvm-config" ]] + [[ -f "${LLVM_INSTALL}/.install_finished" ]] + ) || return 1 +} + +# Returns a unique id for this configuration +get_docker_config_id_llvm() { + ( + setup_build_variables_llvm + echo "${LLVM_VERSION_SHORT}${LLVM_SUFFIX}" + ) +} + +setup_artifact_variables_llvm() { + setup_build_variables_llvm +} + +get_build_artifacts_llvm() { + ( + setup_build_variables_llvm + echo "${LLVM_INSTALL}" + echo "${LLVM_SRC_BASE}" + [[ "${sanitizer}" == "memory" ]] && echo "${SANITIZER_LLVM_UNINSTRUMENTED}" + [[ "${sanitizer}" == "memory" ]] && echo "${SANITIZER_LLVM_LIBCXX}" + ) +} \ No newline at end of file |