blob: 09098f18d378111b7af10be09ca0ccf2aee70e43 [file] [log] [blame]
# Copyright 1999-2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id$
EAPI=7
PYTHON_COMPAT=( python3_{6..9} )
inherit cros-constants cmake flag-o-matic git-r3 multilib-minimal \
python-single-r1 pax-utils toolchain-funcs
LLVM_HASH="2916b99182752b1aece8cc4479d8d6a20b5e02da" # r484197
LLVM_NEXT_HASH="98f5a340975bc00197c57e39eb4ca26e2da0e8a2" # r496208
DESCRIPTION="Low Level Virtual Machine"
HOMEPAGE="http://llvm.org/"
SRC_URI="
!llvm-tot? (
!llvm-next? ( llvm_pgo_use? ( gs://chromeos-localmirror/distfiles/llvm-profdata-${LLVM_HASH}.tar.xz ) )
llvm-next? ( llvm-next_pgo_use? ( gs://chromeos-localmirror/distfiles/llvm-profdata-${LLVM_NEXT_HASH}.tar.xz ) )
)
"
EGIT_REPO_URI="${CROS_GIT_HOST_URL}/external/github.com/llvm/llvm-project
${CROS_GIT_HOST_URL}/external/github.com/llvm/llvm-project"
EGIT_BRANCH=main
LICENSE="UoI-NCSA"
SLOT="8"
KEYWORDS="-* amd64"
# FIXME: llvm-tot is somewhat misleading: at the moment, it's essentially
# llvm-next with a few extra checks enabled
IUSE="debug +default-compiler-rt +default-libcxx doc +libedit +libffi +llvm-crt
llvm-next llvm_pgo_generate +llvm_pgo_use llvm-next_pgo_use llvm-tot
multitarget ncurses ocaml test +thinlto xml video_cards_radeon continue-on-patch-failure"
COMMON_DEPEND="
sys-libs/zlib:0=[${MULTILIB_USEDEP}]
libedit? ( dev-libs/libedit:0=[${MULTILIB_USEDEP}] )
libffi? ( >=dev-libs/libffi-3.0.13-r1:0=[${MULTILIB_USEDEP}] )
ncurses? ( >=sys-libs/ncurses-5.9-r3:0=[${MULTILIB_USEDEP}] )
ocaml? (
>=dev-lang/ocaml-4.00.0:0=
dev-ml/findlib
dev-ml/ocaml-ctypes )"
# configparser-3.2 breaks the build (3.3 or none at all are fine)
DEPEND="${COMMON_DEPEND}
sys-devel/binutils
ocaml? ( test? ( dev-ml/ounit ) )"
RDEPEND="${COMMON_DEPEND}
abi_x86_32? ( !<=app-emulation/emul-linux-x86-baselibs-20130224-r2
!app-emulation/emul-linux-x86-baselibs[-abi_x86_32(-)] )
!<=sys-devel/llvm-8.0_pre
!sys-devel/lld
!sys-devel/clang"
BDEPEND="
dev-lang/perl
libffi? ( virtual/pkgconfig )
sys-devel/gnuconfig
$(python_gen_cond_dep '
dev-python/sphinx[${PYTHON_USEDEP}]
doc? ( dev-python/recommonmark[${PYTHON_USEDEP}] )
')
"
# pypy gives me around 1700 unresolved tests due to open file limit
# being exceeded. probably GC does not close them fast enough.
REQUIRED_USE="
llvm_pgo_generate? ( !llvm_pgo_use )"
check_lld_works() {
echo 'int main() {return 0;}' > "${T}"/lld.cxx || die
echo "Trying to link program with lld"
$(tc-getCXX) -fuse-ld=lld -std=c++11 -o /dev/null "${T}"/lld.cxx
}
check_pgo_works() {
echo 'int main() {return 0;}' > "${T}"/pgo.cxx || die
echo "Trying to link program with pgo"
$(tc-getCXX) -std=c++11 -o /dev/null "${T}"/pgo.cxx -fprofile-instr-use="${WORKDIR}"/llvm.profdata
}
apply_pgo_profile() {
! use llvm-tot && ( \
( use llvm-next && use llvm-next_pgo_use ) ||
( ! use llvm-next && use llvm_pgo_use ) )
}
src_unpack() {
export CMAKE_USE_DIR="${S}/llvm"
if use llvm-next || use llvm-tot; then
EGIT_COMMIT="${LLVM_NEXT_HASH}"
else
EGIT_COMMIT="${LLVM_HASH}"
fi
git-r3_src_unpack
if apply_pgo_profile; then
cd "${WORKDIR}" || die
local profile_hash
if use llvm-next; then
profile_hash="${LLVM_NEXT_HASH}"
else
profile_hash="${LLVM_HASH}"
fi
unpack "llvm-profdata-${profile_hash}.tar.xz"
fi
}
get_most_recent_revision() {
local subdir="${S}/llvm"
# Tries to get the revision ID of the most recent commit
"${FILESDIR}"/patch_manager/git_llvm_rev.py --llvm_dir "${subdir}" --sha "$(git -C "${subdir}" rev-parse HEAD)" | cut -d 'r' -f 2
}
src_prepare() {
# Make ocaml warnings non-fatal, bug #537308
sed -e "/RUN/s/-warn-error A//" -i llvm/test/Bindings/OCaml/*ml || die
python_setup
local failure_mode
failure_mode="$(usex continue-on-patch-failure continue fail)"
"${FILESDIR}"/patch_manager/patch_manager.py \
--svn_version "$(get_most_recent_revision)" \
--patch_metadata_file "${FILESDIR}"/PATCHES.json \
--failure_mode "${failure_mode}" \
--src_path "${S}" || die
cmake_src_prepare
# Native libdir is used to hold LLVMgold.so
# shellcheck disable=SC2034
NATIVE_LIBDIR=$(get_libdir)
}
enable_asserts() {
# keep asserts enabled for llvm-tot
if use llvm-tot; then
echo yes
else
usex debug
fi
}
multilib_src_configure() {
export CMAKE_BUILD_TYPE="RelWithDebInfo"
append-flags -Wno-poison-system-directories
local targets
if use multitarget; then
# for LLVM breakages specific to BPF (only)
# contact cros-enterprise-security@google.com
# for everything else contact OWNERs
targets='host;X86;ARM;AArch64;NVPTX;BPF'
else
targets='host;CppBackend'
use video_cards_radeon && targets+=';AMDGPU'
fi
local ffi_cflags ffi_ldflags
if use libffi; then
ffi_cflags=$($(tc-getPKG_CONFIG) --cflags-only-I libffi)
ffi_ldflags=$($(tc-getPKG_CONFIG) --libs-only-L libffi)
fi
local libdir=$(get_libdir)
local mycmakeargs=(
"${mycmakeargs[@]}"
"-DLLVM_ENABLE_PROJECTS=llvm;clang;lld;lldb;compiler-rt;clang-tools-extra"
"-DLLVM_LIBDIR_SUFFIX=${libdir#lib}"
"-DLLVM_BUILD_LLVM_DYLIB=ON"
# Link LLVM statically
"-DLLVM_LINK_LLVM_DYLIB=OFF"
"-DBUILD_SHARED_LIBS=OFF"
"-DLLVM_ENABLE_TIMESTAMPS=OFF"
"-DLLVM_TARGETS_TO_BUILD=${targets}"
"-DLLVM_BUILD_TESTS=$(usex test)"
"-DLLVM_ENABLE_FFI=$(usex libffi)"
"-DLLVM_ENABLE_TERMINFO=$(usex ncurses)"
"-DLLVM_ENABLE_ASSERTIONS=$(enable_asserts)"
"-DLLVM_ENABLE_EH=ON"
"-DLLVM_ENABLE_RTTI=ON"
"-DWITH_POLLY=OFF" # TODO
"-DLLVM_HOST_TRIPLE=${CHOST}"
"-DFFI_INCLUDE_DIR=${ffi_cflags#-I}"
"-DFFI_LIBRARY_DIR=${ffi_ldflags#-L}"
"-DLLVM_BINUTILS_INCDIR=${SYSROOT}/usr/include"
"-DHAVE_HISTEDIT_H=$(usex libedit)"
"-DENABLE_LINKER_BUILD_ID=ON"
"-DCLANG_VENDOR=Chromium OS ${PVR}"
# override default stdlib and rtlib
"-DCLANG_DEFAULT_CXX_STDLIB=$(usex default-libcxx libc++ "")"
"-DCLANG_DEFAULT_RTLIB=$(usex default-compiler-rt compiler-rt "")"
# crbug/855759
"-DCOMPILER_RT_BUILD_CRT=$(usex llvm-crt)"
"-DCMAKE_POSITION_INDEPENDENT_CODE=ON"
"-DCLANG_DEFAULT_UNWINDLIB=libgcc"
"-DCLANG_DEFAULT_PIE_ON_LINUX=ON"
# workaround for crbug/1198796
"-DCLANG_TOOLING_BUILD_AST_INTROSPECTION=OFF"
# By default do not enable PGO for compiler-rt
"-DCOMPILER_RT_ENABLE_PGO=OFF"
# compiler-rt needs libc++ sources to be specified to build
# an internal copy for libfuzzer, can be removed if libc++
# is built inside llvm ebuild.
"-DCOMPILER_RT_LIBCXXABI_PATH=${S}/libcxxabi"
"-DCOMPILER_RT_LIBCXX_PATH=${S}/libcxx"
"-DCOMPILER_RT_BUILTINS_HIDE_SYMBOLS=OFF"
# b/200831212: Disable per runtime install dirs.
"-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF"
# b/202073091: Disable Lua.
"-DLLDB_ENABLE_LUA=OFF"
# b/204220308: Disable ORC since we are not using it.
"-DCOMPILER_RT_BUILD_ORC=OFF"
# b/241569725: Explicitly set Python version so that it
# chooses the version we're currently supporting
"-DPython3_EXECUTABLE=${PYTHON}"
)
if check_lld_works; then
mycmakeargs+=(
# We use lld to link llvm, because:
# 1) Gold has issue with no index for archive,
# 2) Gold doesn't support instrumented compiler-rt well.
"-DLLVM_USE_LINKER=lld"
)
# The standalone toolchain may be run at places not supporting
# smallPIE, disabling it for lld.
# Pass -fuse-ld=lld to make cmake happy.
append-ldflags "-fuse-ld=lld -Wl,--pack-dyn-relocs=none"
# Disable warning about profile not matching.
append-flags "-Wno-backend-plugin"
if use thinlto; then
mycmakeargs+=(
"-DLLVM_ENABLE_LTO=thin"
# b/228090090: LLVM defaults to 2 parallel link
# jobs with ThinLTO enabled. Bumping this to 4
# speeds `emerge llvm` up on dev machines by
# 1.25x, and saves >10mins per LLVM build on the
# SDK builder.
"-DLLVM_PARALLEL_LINK_JOBS=4"
)
# b/227370760: Instr limits above 30 don't seem to help
# our performance (and might hurt in some cases). They
# also make builds take meaningfully longer, and add
# tens of MB to our SDK size. We tune this back in other
# large ThinLTO users (e.g., Chrome), so do it here,
# too.
append-ldflags "-Wl,-mllvm,-import-instr-limit=30"
fi
if apply_pgo_profile; then
if check_pgo_works; then
mycmakeargs+=(
"-DLLVM_PROFDATA_FILE=${WORKDIR}/llvm.profdata"
)
else
# PGO profile did not work which is only acceptable
# for the cases where llvm hash != profile hash.
# Error out in other cases.
$(tc-getCC) --version | grep -q "\b${EGIT_COMMIT}" && die \
"Could not build with PGO profile at sha ${EGIT_COMMIT}".
echo "Could not build with pgo profile, skipping pgo."
fi
fi
if use llvm_pgo_generate; then
mycmakeargs+=(
"-DLLVM_BUILD_INSTRUMENTED=IR"
)
fi
fi
if ! multilib_is_native_abi || ! use ocaml; then
mycmakeargs+=(
"-DOCAMLFIND=NO"
)
fi
# Note: go bindings have no CMake rules at the moment
# but let's kill the check in case they are introduced
# if ! multilib_is_native_abi || ! use go; then
mycmakeargs+=(
"-DGO_EXECUTABLE=GO_EXECUTABLE-NOTFOUND"
)
# fi
if [[ -z "${CCACHE_DISABLE:-}" ]]; then
# If ccache is enabled, use it as a compiler launcher. Chances
# are that folks are iterating on LLVM, and ccache speeds that
# up substantially.
mycmakeargs+=(
"-DCMAKE_C_COMPILER_LAUNCHER=ccache"
"-DCMAKE_CXX_COMPILER_LAUNCHER=ccache"
)
fi
if multilib_is_native_abi; then
mycmakeargs+=(
"-DLLVM_BUILD_DOCS=$(usex doc)"
"-DLLVM_ENABLE_SPHINX=$(usex doc)"
"-DLLVM_ENABLE_DOXYGEN=OFF"
"-DLLVM_INSTALL_HTML=${EPREFIX}/usr/share/doc/${PF}/html"
"-DSPHINX_WARNINGS_AS_ERRORS=OFF"
"-DLLVM_INSTALL_UTILS=ON"
)
fi
if ! use debug; then
append-cppflags -DNDEBUG
fi
cmake_src_configure
}
multilib_src_compile() {
# ...If folks are iterating on LLVM with `emerge`, every successful
# `emerge` invocation will replace their old compiler. Since doing so
# updates mtimes, we should be focusing on the _content_ of the
# compiler, rather than the mtime.
#
# Note that this is in `src_compile`, since it won't apply if we do it
# in `src_configure`.
export CCACHE_COMPILERCHECK=content
cmake_src_compile
pax-mark m "${BUILD_DIR}"/bin/llvm-rtdyld
pax-mark m "${BUILD_DIR}"/bin/lli
pax-mark m "${BUILD_DIR}"/bin/lli-child-target
if use test; then
pax-mark m "${BUILD_DIR}"/unittests/ExecutionEngine/Orc/OrcJITTests
pax-mark m "${BUILD_DIR}"/unittests/ExecutionEngine/MCJIT/MCJITTests
pax-mark m "${BUILD_DIR}"/unittests/Support/SupportTests
fi
}
multilib_src_test() {
# respect TMPDIR!
local -x LIT_PRESERVES_TMP=1
cmake_src_test
}
src_install() {
local MULTILIB_CHOST_TOOLS=(
/usr/bin/llvm-config
)
local MULTILIB_WRAPPED_HEADERS=(
/usr/include/llvm/Config/config.h
/usr/include/llvm/Config/llvm-config.h
)
multilib-minimal_src_install
}
# This computes the toolchain SHA that gets baked into our compiler_wrapper
# binaries. This SHA is potentially nice for uniquely identifying a toolchain,
# but the most critical purpose that it serves is making the SHA for our
# compiler_wrapper change with the toolchain that it was installed with. If any
# of these binaries get modified and we fail to update compiler_wrapper, tools
# like ccache, ninja, etc might not expect the updates without extra work (thus,
# cached object files might not be considered stale across compiler updates).
#
# Rather than playing whack-a-mole with ways to inform each build system that
# our compiler has changed (despite its hash remaining identical), we simply
# modify its hash when any of the binaries it calls may change.
compute_toolchain_sha() {
local toolchain_sha_binaries=(
"bin/clang"
"bin/clang-tidy"
"bin/ld.lld"
)
# Compute the SHA sums for each of these in parallel, then hash the
# result. This hash represents all of the (non-header, non-library)
# dependencies that Clang has.
#
# This is expected to be called in a subshell, so don't try to restore
# pipefail.
set -o pipefail
echo "${toolchain_sha_binaries[*]}" |
xargs -L1 -P8 sha256sum |
sort -k2 |
sha256sum - |
awk '{print $1}'
}
multilib_src_install() {
cmake_src_install
local use_llvm_next=false
if use llvm-next || use llvm-tot
then
use_llvm_next=true
fi
local wrapper_script=clang_host_wrapper
local toolchain_sha
echo "Current directory is $(pwd)"
toolchain_sha="$(compute_toolchain_sha)" || die
einfo "Computed toolchain SHA = ${toolchain_sha}"
local common_wrapper_flags=(
"--version_suffix=_toolchain_sha_${toolchain_sha}"
)
GO111MODULE=off "${FILESDIR}/compiler_wrapper/build.py" --config=cros.host --use_ccache=false \
--use_llvm_next="${use_llvm_next}" \
--output_file="${D}/usr/bin/${wrapper_script}" \
"${common_wrapper_flags[@]}" || die
newbin "${D}/usr/bin/clang-tidy" "clang-tidy"
dobin "${FILESDIR}/bisect_driver.py"
dobin "${FILESDIR}/clang_cc_wrapper"
exeinto "/usr/bin"
dosym "${wrapper_script}" "/usr/bin/${CHOST}-clang"
dosym "${wrapper_script}" "/usr/bin/${CHOST}-clang++"
newexe "${FILESDIR}/ldwrapper_lld.host" "${CHOST}-ld.lld"
# llvm-strip is a symlink to llvm-objcopy and distinguished by a argv[0] check.
# When creating standalone toolchain, argv[0] information is lost and causes
# llvm-strip invocations to be treated as llvm-objcopy breaking builds
# (crbug.com/1151787). Handle this by making llvm-strip a full binary.
if [[ -L "${D}/usr/bin/llvm-strip" ]]; then
rm "${D}/usr/bin/llvm-strip" || die
newbin "${D}/usr/bin/llvm-objcopy" "llvm-strip"
fi
# Build and install cross-compiler wrappers for supported ABIs.
# ccache wrapper is used in chroot and non-ccache wrapper is used
# in standalone SDK.
local ccache_suffixes=(noccache ccache)
local ccache_option_values=(false true)
for ccache_index in {0,1}; do
local ccache_suffix="${ccache_suffixes[${ccache_index}]}"
local ccache_option="${ccache_option_values[${ccache_index}]}"
# Build hardened wrapper written in golang.
GO111MODULE=off "${FILESDIR}/compiler_wrapper/build.py" --config="cros.hardened" \
--use_ccache="${ccache_option}" \
--use_llvm_next="${use_llvm_next}" \
--output_file="${D}/usr/bin/sysroot_wrapper.hardened.${ccache_suffix}" \
"${common_wrapper_flags[@]}" || die
# Build non-hardened wrapper written in golang.
GO111MODULE=off "${FILESDIR}/compiler_wrapper/build.py" --config="cros.nonhardened" \
--use_ccache="${ccache_option}" \
--use_llvm_next="${use_llvm_next}" \
--output_file="${D}/usr/bin/sysroot_wrapper.${ccache_suffix}" \
"${common_wrapper_flags[@]}" || die
done
local cros_hardened_targets=(
"aarch64-cros-linux-gnu"
"armv7a-cros-linux-gnueabihf"
"i686-cros-linux-gnu"
"x86_64-cros-linux-gnu"
)
local cros_nonhardened_targets=(
"arm-none-eabi"
"armv7m-cros-eabi"
)
local target
for target in "${cros_hardened_targets[@]}"; do
dosym "sysroot_wrapper.hardened.ccache" "/usr/bin/${target}-clang"
dosym "sysroot_wrapper.hardened.ccache" "/usr/bin/${target}-clang++"
done
for target in "${cros_nonhardened_targets[@]}"; do
dosym "sysroot_wrapper.ccache" "/usr/bin/${target}-clang"
dosym "sysroot_wrapper.ccache" "/usr/bin/${target}-clang++"
done
# Install a symlink bpf-clang which point to clang.
# Running through symlink will make clang default to bpf target.
dosym "clang" "/usr/bin/bpf-clang"
# Remove this file, if it exists, to avoid installation file collision,
# as this file is also generated/installed by the dev-python/six package.
find "${D}"/usr -name 'six.py' -delete
}
multilib_src_install_all() {
insinto /usr/share/vim/vimfiles
doins -r llvm/utils/vim/*/.
# some users may find it useful
dodoc llvm/utils/vim/vimrc
dobin "${S}/compiler-rt/lib/asan/scripts/asan_symbolize.py"
}
pkg_postinst() {
if has_version ">=dev-util/ccache-3.1.9-r2" ; then
#add ccache links as clang might get installed after ccache
"${EROOT}"/usr/bin/ccache-config --install-links
fi
}
pkg_postrm() {
if has_version ">=dev-util/ccache-3.1.9-r2" && [[ -z ${REPLACED_BY_VERSION} ]]; then
# --remove-links would remove all links, --install-links updates them
"${EROOT}"/usr/bin/ccache-config --install-links
fi
}