blob: ba0fda953c83aaf5192c4f45cf7c1abfec25160f [file] [log] [blame]
# Copyright 1999-2018 Jason Zaman
# Distributed under the terms of the GNU General Public License v2
# @ECLASS: bazel.eclass
# @MAINTAINER:
# Jason Zaman <perfinion@gentoo.org>
# @AUTHOR:
# Jason Zaman <perfinion@gentoo.org>
# @BLURB: Utility functions for packages using Bazel Build
# @DESCRIPTION:
# A utility eclass providing functions to run the Bazel Build system.
#
# This eclass does not export any phase functions.
# TODO(chromium:924701): re-disable EAPI 6 support.
case "${EAPI:-0}" in
0|1|2|3|4|5)
die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
;;
6|7)
;;
*)
die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
;;
esac
if [[ ! ${_BAZEL_ECLASS} ]]; then
inherit multiprocessing toolchain-funcs
BDEPEND=">=dev-util/bazel-0.20"
# @FUNCTION: bazel_get_flags
# @DESCRIPTION:
# Obtain and print the bazel flags for target and host *FLAGS.
#
# To add more flags to this, append the flags to the
# appropriate variable before calling this function
bazel_get_flags() {
local i fs=()
for i in ${CFLAGS}; do
fs+=( "--conlyopt=${i}" )
done
for i in ${BUILD_CFLAGS}; do
fs+=( "--host_conlyopt=${i}" )
done
for i in ${CXXFLAGS}; do
fs+=( "--cxxopt=${i}" )
done
for i in ${BUILD_CXXFLAGS}; do
fs+=( "--host_cxxopt=${i}" )
done
for i in ${CPPFLAGS}; do
fs+=( "--conlyopt=${i}" "--cxxopt=${i}" )
done
for i in ${BUILD_CPPFLAGS}; do
fs+=( "--host_conlyopt=${i}" "--host_cxxopt=${i}" )
done
for i in ${LDFLAGS}; do
fs+=( "--linkopt=${i}" )
done
for i in ${BUILD_LDFLAGS}; do
fs+=( "--host_linkopt=${i}" )
done
# Temporarily disable sanitizer blacklist until upstream issue
# https://github.com/bazelbuild/bazel/issues/10561 is fixed.
fs+=( "--copt=-fno-sanitize-blacklist" )
echo "${fs[*]}"
}
# @FUNCTION: bazel_setup_bazelrc
# @DESCRIPTION:
# Creates the bazelrc with common options that will be passed
# to bazel. This will be called by ebazel automatically so
# does not need to be called from the ebuild.
bazel_setup_bazelrc() {
if [[ -f "${T}/bazelrc" ]]; then
return
fi
# F: fopen_wr
# P: /proc/self/setgroups
# Even with standalone enabled, the Bazel sandbox binary is run for feature test:
# https://github.com/bazelbuild/bazel/blob/7b091c1397a82258e26ab5336df6c8dae1d97384/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedSpawnRunner.java#L61
# https://github.com/bazelbuild/bazel/blob/76555482873ffcf1d32fb40106f89231b37f850a/src/main/tools/linux-sandbox-pid1.cc#L113
addpredict /proc
mkdir -p "${T}/bazel-cache" || die
mkdir -p "${T}/bazel-distdir" || die
cat > "${T}/bazelrc" <<-EOF || die
startup --batch
# dont strip HOME, portage sets a temp per-package dir
build --action_env HOME
# make bazel respect MAKEOPTS
build --jobs=$(makeopts_jobs)
build --compilation_mode=opt --host_compilation_mode=opt
# FLAGS
build $(bazel_get_flags)
# Use standalone strategy to deactivate the bazel sandbox, since it
# conflicts with FEATURES=sandbox.
build --spawn_strategy=standalone --genrule_strategy=standalone
test --spawn_strategy=standalone --genrule_strategy=standalone
build --strip=never
build --verbose_failures --noshow_loading_progress
test --verbose_test_summary --verbose_failures --noshow_loading_progress
# make bazel only fetch distfiles from the cache
fetch --repository_cache="${T}/bazel-cache/" --distdir="${T}/bazel-distdir/"
build --repository_cache="${T}/bazel-cache/" --distdir="${T}/bazel-distdir/"
build --define=PREFIX=${EPREFIX%/}/usr
build --define=LIBDIR=\$(PREFIX)/$(get_libdir)
EOF
if tc-is-cross-compiler; then
echo "build --nodistinct_host_configuration" >> "${T}/bazelrc" || die
fi
}
# @FUNCTION: ebazel
# @USAGE: [<args>...]
# @DESCRIPTION:
# Run bazel with the bazelrc and output_base.
#
# output_base will be specific to $BUILD_DIR (if unset, $S).
# bazel_setup_bazelrc will be called and the created bazelrc
# will be passed to bazel.
#
# Will automatically die if bazel does not exit cleanly.
ebazel() {
bazel_setup_bazelrc
# Use different build folders for each multibuild variant.
local output_base="${BUILD_DIR:-${S}}"
output_base="${output_base%/}-bazel-base"
mkdir -p "${output_base}" || die
set -- bazel --bazelrc="${T}/bazelrc" --output_base="${output_base}" ${@}
echo "${*}" >&2
"${@}" || die "ebazel failed"
}
# @FUNCTION: bazel_load_distfiles
# @USAGE: <distfiles>...
# @DESCRIPTION:
# Populate the bazel distdir to fetch from since it cannot use
# the network. Bazel looks in distdir but will only look for the
# original filename, not the possibly renamed one that portage
# downloaded. If the line has -> we to rename it back. This also
# handles use-conditionals that SRC_URI does.
#
# Example:
# @CODE
# bazel_external_uris="http://a/file-2.0.tgz
# python? ( http://b/1.0.tgz -> foo-1.0.tgz )"
# SRC_URI="http://c/${PV}.tgz
# ${bazel_external_uris}"
#
# src_unpack() {
# unpack ${PV}.tgz
# bazel_load_distfiles "${bazel_external_uris}"
# }
# @CODE
bazel_load_distfiles() {
local file=""
local rename=0
[[ "${@}" ]] || die "Missing args"
mkdir -p "${T}/bazel-distdir" || die
for word in ${@}
do
if [[ "${word}" == "->" ]]; then
# next word is a dest filename
rename=1
elif [[ "${word}" == ")" ]]; then
# close conditional block
continue
elif [[ "${word}" == "(" ]]; then
# open conditional block
continue
elif [[ "${word}" == ?(\!)[A-Za-z0-9]*([A-Za-z0-9+_@-])\? ]]; then
# use-conditional block
# USE-flags can contain [A-Za-z0-9+_@-], and start with alphanum
# https://dev.gentoo.org/~ulm/pms/head/pms.html#x1-200003.1.4
# ?(\!) matches zero-or-one !'s
# *(...) zero-or-more characters
# ends with a ?
continue
elif [[ ${rename} -eq 1 ]]; then
# Make sure the distfile is used
if [[ "${A}" == *"${word}"* ]]; then
echo "Copying ${file} to bazel distdir as ${word}"
ln -s "${DISTDIR}/${word}" "${T}/bazel-distdir/${file}" || die
fi
rename=0
file=""
else
# another URL, current one may or may not be a rename
# if there was a previous one, its not renamed so copy it now
if [[ -n "${file}" && "${A}" == *"${file}"* ]]; then
echo "Copying ${file} to bazel distdir"
ln -s "${DISTDIR}/${file}" "${T}/bazel-distdir/${file}" || die
fi
# save the current URL, later we will find out if its a rename or not.
file="${word##*/}"
fi
done
# handle last file
if [[ -n "${file}" ]]; then
echo "Copying ${file} to bazel distdir"
ln -s "${DISTDIR}/${file}" "${T}/bazel-distdir/${file}" || die
fi
}
_BAZEL_ECLASS=1
fi