Add project LLVM (https://llvm.org) ...
and also lib/ossbuild-common.bash.
This commit is contained in:
parent
531ee60fcf
commit
e7e9990871
6
lib/ossbuild-common.bash
Normal file
6
lib/ossbuild-common.bash
Normal file
@ -0,0 +1,6 @@
|
||||
# Helper functions for project build scripts.
|
||||
|
||||
# Check is current system is running GNU/Linux based QNAP QTS OS.
|
||||
is-qnap-qts() {
|
||||
[ -r '/etc/os-release' ] && grep -q '^NAME="QTS"$' '/etc/os-release'
|
||||
}
|
||||
21
projects/llvm/README.org
Normal file
21
projects/llvm/README.org
Normal file
@ -0,0 +1,21 @@
|
||||
#+title: LLVM Compiler Infrastructure
|
||||
|
||||
See https://llvm.org.
|
||||
|
||||
Tools:
|
||||
- clang(++)
|
||||
- clang-extra-tools
|
||||
- clangd
|
||||
- clang-format
|
||||
- clang-tidy
|
||||
- ...
|
||||
- lld
|
||||
- lldb
|
||||
- ...
|
||||
|
||||
Runtimes
|
||||
- libc++
|
||||
- libc++abi
|
||||
- libunwind
|
||||
|
||||
To build the runtimes, the build script uses the [[https://libcxx.llvm.org/BuildingLibcxx.html#bootstrapping-build][Bootstrapping build]] method.
|
||||
284
projects/llvm/ossbuild-llvm.bash
Executable file
284
projects/llvm/ossbuild-llvm.bash
Executable file
@ -0,0 +1,284 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
LIB_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]}")")/../../lib"
|
||||
source "${LIB_DIR}/ossbuild-common.bash"
|
||||
|
||||
llvm-source-workon() {
|
||||
echo "[INF] ${FUNCNAME[0]} ..."
|
||||
local version="${1}"
|
||||
|
||||
local repository="https://github.com/llvm/llvm-project"
|
||||
local archive="llvm-project-${version}.src.tar.xz"
|
||||
pushd "${HOME}/work/oss" &> /dev/null
|
||||
[ -e "${archive}" ] || {
|
||||
wget "${repository}/releases/download/llvmorg-${version}/${archive}"
|
||||
}
|
||||
|
||||
local src_dir
|
||||
src_dir="${HOME}/work/oss/$(basename "${archive}" .tar.xz)"
|
||||
|
||||
[ -d "${src_dir}" ] || tar xvf "${archive}"
|
||||
popd &> /dev/null
|
||||
pushd "${src_dir}" &> /dev/null
|
||||
}
|
||||
|
||||
llvm-cmake-generate() {
|
||||
echo "[INF] ${FUNCNAME[0]} ..."
|
||||
local build_type="${1:-Release}"
|
||||
local projects="${2:-}"
|
||||
local prefix="${3:-}"
|
||||
|
||||
local source_dir='llvm'
|
||||
[ -d "${source_dir}" ] || {
|
||||
echo "[ERR] could not find source dir: '${source_dir}'"
|
||||
return 1
|
||||
}
|
||||
|
||||
local -a cmake_extra_args
|
||||
local build_dir="build-${build_type,,}"
|
||||
if [ -n "${projects}" ]; then
|
||||
build_dir="${build_dir}.${projects//;/.}"
|
||||
else
|
||||
# get runtime target from GCC
|
||||
local gcc_runtime_target
|
||||
gcc_runtime_target="$(gcc -xc /dev/null -v -E 2>&1 | grep '^Target:' | cut -d' ' -f2)"
|
||||
#projects='clang;clang-tools-extra;lld;lldb;compiler-rt;libunwind;libcxx;libcxxabi'
|
||||
projects='clang;clang-tools-extra;compiler-rt;lld;lldb'
|
||||
cmake_extra_args+=(
|
||||
-DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi;libunwind"
|
||||
|
||||
# must match triple of GCC used for first build step (here:
|
||||
# /opt/lib/gcc/x86_64-openwrt-linux-gnu/8.4.0)
|
||||
-DLLVM_RUNTIME_TARGETS="${gcc_runtime_target}"
|
||||
# required )in case of a non-standard triple) in order to allow the
|
||||
# final clang to find the GCC resource dir which contains files
|
||||
# required by the linker (like crti.o, libgcc, libc_nonshared.a in
|
||||
# e.g. /opt/lib/gcc/x86_64-openwrt-linux-gnu/8.4.0)
|
||||
#
|
||||
# Note: This also sets LLVM_DEFAULT_TARGET_TRIPLE.
|
||||
-DLLVM_HOST_TRIPLE="${gcc_runtime_target}"
|
||||
|
||||
# Avoid error during cmake toolchain generation:
|
||||
#
|
||||
# ERROR: Compiler doesn't support generation of unwind tables if
|
||||
# exception support is disabled. Building libunwind DSO with runtime
|
||||
# dependency on C++ ABI library is not supported.
|
||||
-DRUNTIMES_${gcc_runtime_target}_LIBUNWIND_ENABLE_SHARED="Off"
|
||||
)
|
||||
fi
|
||||
local log="${build_dir/build-/cmake-}.log"
|
||||
|
||||
if [ -z "${prefix}" ]; then
|
||||
if is-qnap-qts; then
|
||||
prefix="$(readlink /opt)/local"
|
||||
else
|
||||
prefix='/usr/local'
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -d "${build_dir}" ]; then
|
||||
if [ -v FORCE_REGENERATE ]; then
|
||||
if [ "${FORCE_REGENERATE}" != "no-rm" ]; then
|
||||
rm -rf "${build_dir}"
|
||||
fi
|
||||
else
|
||||
echo "[INF] keep existing build dir: '${build_dir}'"
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
local -a cmd=(
|
||||
cmake
|
||||
-S "${source_dir}"
|
||||
-B "${build_dir}"
|
||||
-G Ninja
|
||||
-DCMAKE_BUILD_TYPE="${build_type}"
|
||||
-DCMAKE_INSTALL_PREFIX="${prefix}"
|
||||
-DLLVM_ENABLE_PROJECTS="${projects}"
|
||||
#-DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,\$ORIGIN/../lib -L${prefix}/lib"
|
||||
-DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,${prefix}/lib -L${prefix}/lib -L/opt/lib"
|
||||
"${cmake_extra_args[@]}"
|
||||
)
|
||||
|
||||
if command -v ccache &> /dev/null; then
|
||||
cmd+=(
|
||||
-DLLVM_CCACHE_BUILD="ON"
|
||||
-DLLVM_CCACHE_PARAMS="CCACHE_CPP2=yes CCACHE_HASHDIR=yes CCACHE_BASEDIR='${PWD}/${build_dir}'"
|
||||
)
|
||||
fi
|
||||
|
||||
if is-qnap-qts; then
|
||||
# get gcc_install_prefix
|
||||
local gcc_install_prefix
|
||||
gcc_install_prefix="$(gcc -x c -E /dev/null -v 2>&1 | rg 'Configured with' | sed -e 's/.* --prefix=\([^ ]\+\).*/\1/')"
|
||||
|
||||
cmd+=(
|
||||
# enable clang to locate the GCC toolchain if it is in a
|
||||
# non-standard location (like ~/opt~ on QNAP Entware)
|
||||
-DGCC_INSTALL_PREFIX="${gcc_install_prefix}"
|
||||
|
||||
# CMAKE_EXE_LINKER_FLAGS and LLVM_PARALLEL_LINK_JOBS flags reduce linker
|
||||
# memory usage (without them, llvm build fails on qnas)
|
||||
-DCMAKE_EXE_LINKER_FLAGS="-Wl,--reduce-memory-overheads -Wl,--hash-size=1021"
|
||||
-DLLVM_PARALLEL_LINK_JOBS=1
|
||||
|
||||
# avoid cmake warning: 'runtime library [libz.so.1] in /lib may be
|
||||
# hidden by files in ...'
|
||||
-DZLIB_ROOT="${prefix}"
|
||||
)
|
||||
|
||||
# From https://lists.llvm.org/pipermail/cfe-users/2016-November/001076.html:
|
||||
#
|
||||
# ... gcc's configure file comes with handy flags like:
|
||||
# - --with-local-prefix= which allows to override the default system
|
||||
# header include /usr/local/include
|
||||
# - --with-native-system-header-dir= to override the default system
|
||||
# header include /include
|
||||
# - --enable-linker-build-id to enable build ids by default (in clang
|
||||
# the equivalent is -DENABLE_LINKER_BUILD_ID)
|
||||
# - --with-linker-hash-style=gnu to force the gnu hash style when
|
||||
# emitting the symbol table.
|
||||
#
|
||||
# However, LLVM/clang doesn't seem to provide an equivalent for
|
||||
# --with-local-prefix, --with-native-system-header-dir and
|
||||
# --with-linker-hash-style. So instead, some sources need to be
|
||||
# patched.
|
||||
echo
|
||||
local clang_toolchain_src
|
||||
clang_toolchain_src='clang/lib/Driver/ToolChains/Linux.cpp'
|
||||
[ -e "${clang_toolchain_src}.orig" ] || {
|
||||
echo "[INF] patching ${clang_toolchain_src} ..."
|
||||
sed -i.orig \
|
||||
-e 's,/usr/,/opt/,g' "${clang_toolchain_src}"
|
||||
}
|
||||
echo "[INF] using patch:"
|
||||
diff -u "${clang_toolchain_src}"{.orig,} || true
|
||||
echo "[INF] end of patch (${clang_toolchain_src})"
|
||||
|
||||
echo
|
||||
clang_toolchain_src='clang/lib/Driver/ToolChains/Gnu.cpp'
|
||||
[ -e "${clang_toolchain_src}.orig" ] || {
|
||||
echo "[INF] patching ${clang_toolchain_src} ..."
|
||||
sed -i.orig \
|
||||
-e 's,\(basePath = "/\)usr\(/lib/gcc/"\),\1opt\2,g' \
|
||||
"${clang_toolchain_src}"
|
||||
}
|
||||
echo "[INF] using patch:"
|
||||
diff -u "${clang_toolchain_src}"{.orig,} || true
|
||||
echo "[INF] end of patch (${clang_toolchain_src})"
|
||||
fi
|
||||
|
||||
echo "[INF] generating build system for: ${projects}" | tee "${log}"
|
||||
echo "${cmd[@]}" | tee -a "${log}"
|
||||
"${cmd[@]}" 2>&1 | tee -a "${log}"
|
||||
local -i retval=${?}
|
||||
|
||||
echo
|
||||
local logprfx="INF"
|
||||
if [ ${retval} -ne 0 ] || grep -q "Configuring incomplete" "${log}" ; then
|
||||
logprfx="ERR"
|
||||
echo "[${logprfx}] failed to generate build system for: ${projects}"
|
||||
[ ${retval} -ne 0 ] || retval=10
|
||||
else
|
||||
echo "[${logprfx}] successfully generated build system for: ${projects}"
|
||||
fi
|
||||
|
||||
echo "[${logprfx}] build dir: '${build_dir}'"
|
||||
echo "[${logprfx}] cmake log: '${log}'"
|
||||
|
||||
return ${retval}
|
||||
}
|
||||
|
||||
# shellcheck disable=SC2120
|
||||
llvm-cmake-build() {
|
||||
echo "[INF] ${FUNCNAME[0]} ..."
|
||||
local build_type="${1:-Release}"
|
||||
local build_args="${2:-}"
|
||||
local build_dir="${3:-build-${build_type,,}}"
|
||||
local cmd=(
|
||||
cmake --build "${build_dir}"
|
||||
--
|
||||
)
|
||||
|
||||
if [ -n "${build_args}" ]; then
|
||||
read -a extra_args <<< "${build_args}"
|
||||
cmd+=(
|
||||
"${extra_args[@]}"
|
||||
)
|
||||
elif is-qnap-qts; then
|
||||
cmd+=(
|
||||
# compiling on QTS sometimes fails (probably due to memory
|
||||
# limitations), so limit the parallel jobs to 2
|
||||
-j2
|
||||
# don't stop at failures
|
||||
-k0
|
||||
)
|
||||
fi
|
||||
|
||||
# enable verbose logging when V is non-empty
|
||||
[ -z "${V:-}" ] || cmd+=(-v)
|
||||
|
||||
echo "${cmd[@]}"
|
||||
"${cmd[@]}"
|
||||
}
|
||||
|
||||
llvm-cmake-install() {
|
||||
echo "[INF] ${FUNCNAME[0]} ..."
|
||||
local build_type="${1:-Release}"
|
||||
local build_dir="${2:-build-${build_type,,}}"
|
||||
local cmd=(
|
||||
sudo cmake --build "${build_dir}"
|
||||
--
|
||||
install
|
||||
)
|
||||
echo "${cmd[@]}"
|
||||
"${cmd[@]}"
|
||||
}
|
||||
|
||||
llvm-cmake-generate-fallback() {
|
||||
echo "[INF] ${FUNCNAME[0]} ..."
|
||||
local build_type="${1:-Release}"
|
||||
local build_dir="${2:-build-${build_type,,}}"
|
||||
|
||||
# Fallback 1: Build a smaller subset of LLVM projects
|
||||
local llvm_projects=(
|
||||
clang
|
||||
clang-tools-extra
|
||||
lld
|
||||
)
|
||||
local IFS=';'
|
||||
llvm-cmake-generate "${build_type}" "${llvm_projects[*]}"
|
||||
|
||||
# Fallback 2: Generate build systems for individual projects
|
||||
IFS=';' read -a LLVM_PROJECTS \
|
||||
<<< $(grep 'set(LLVM_ALL_PROJECTS ' llvm/CMakeLists.txt | cut -d\" -f2)
|
||||
local project
|
||||
for project in "${llvm_projects[@]}"; do
|
||||
llvm-cmake-generate "${build_type}" "${project}"
|
||||
done
|
||||
}
|
||||
|
||||
ossbuild-llvm() {
|
||||
local version="${1:-15.0.5}"
|
||||
local build_type="${2:-Release}" # or 'RelWithDebInfo', but beware of the huge binaries
|
||||
|
||||
llvm-source-workon "${version}"
|
||||
llvm-cmake-generate "${build_type}"
|
||||
|
||||
# Ideally, llcm-cmake-build should build the most LLVM projects. However, if
|
||||
# it doesn't, it might make sense to build projects individually (see
|
||||
# `llvm-cmake-generate-fallback` above).
|
||||
llvm-cmake-build "${build_type}"
|
||||
# Install the toolchain
|
||||
llvm-cmake-install "${build_type}"
|
||||
|
||||
return $?
|
||||
}
|
||||
|
||||
|
||||
# stop here when sourced
|
||||
return 0 2>/dev/null || true
|
||||
set -euo pipefail
|
||||
[ "${DEBUG:-0}" -le 0 ] || set -x
|
||||
|
||||
ossbuild-llvm "${@}"
|
||||
Loading…
x
Reference in New Issue
Block a user