1 |
Hey all, |
2 |
|
3 |
I've been using Bazel (https://bazel.build/) to build TensorFlow for a |
4 |
while now. Here is a bazel.eclass I'd like to commit to make it easier |
5 |
for packages that use it to build. It's basically bits that I've |
6 |
refactored out of the TensorFlow ebuild that would be useful to other |
7 |
packages as well. I have a bump to sci-libs/tensorflow-1.12.0 prepared |
8 |
that uses this eclass and have tested a full install. |
9 |
|
10 |
-- Jason |
11 |
|
12 |
# Copyright 1999-2018 Jason Zaman |
13 |
# Distributed under the terms of the GNU General Public License v2 |
14 |
|
15 |
# @ECLASS: bazel.eclass |
16 |
# @MAINTAINER: |
17 |
# Jason Zaman <perfinion@g.o> |
18 |
# @AUTHOR: |
19 |
# Jason Zaman <perfinion@g.o> |
20 |
# @BLURB: Utility functions for packages using Bazel Build |
21 |
# @DESCRIPTION: |
22 |
# A utility eclass providing functions to run the Bazel Build system. |
23 |
# |
24 |
# This eclass does not export any phase functions. |
25 |
|
26 |
case "${EAPI:-0}" in |
27 |
0|1|2|3|4|5|6) |
28 |
die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" |
29 |
;; |
30 |
7) |
31 |
;; |
32 |
*) |
33 |
die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" |
34 |
;; |
35 |
esac |
36 |
|
37 |
if [[ ! ${_BAZEL_ECLASS} ]]; then |
38 |
|
39 |
inherit multiprocessing toolchain-funcs |
40 |
|
41 |
BDEPEND=">=dev-util/bazel-0.19" |
42 |
|
43 |
# @FUNCTION: bazel_get_flags |
44 |
# @DESCRIPTION: |
45 |
# Obtain and print the bazel flags for target and host *FLAGS. |
46 |
# |
47 |
# To add more flags to this, append the flags to the |
48 |
# appropriate variable before calling this function |
49 |
bazel_get_flags() { |
50 |
local i fs=() |
51 |
for i in ${CFLAGS}; do |
52 |
fs+=( "--conlyopt=${i}" ) |
53 |
done |
54 |
for i in ${BUILD_CFLAGS}; do |
55 |
fs+=( "--host_conlyopt=${i}" ) |
56 |
done |
57 |
for i in ${CXXFLAGS}; do |
58 |
fs+=( "--cxxopt=${i}" ) |
59 |
done |
60 |
for i in ${BUILD_CXXFLAGS}; do |
61 |
fs+=( "--host_cxxopt=${i}" ) |
62 |
done |
63 |
for i in ${CPPFLAGS}; do |
64 |
fs+=( "--conlyopt=${i}" "--cxxopt=${i}" ) |
65 |
done |
66 |
for i in ${BUILD_CPPFLAGS}; do |
67 |
fs+=( "--host_conlyopt=${i}" "--host_cxxopt=${i}" ) |
68 |
done |
69 |
for i in ${LDFLAGS}; do |
70 |
fs+=( "--linkopt=${i}" ) |
71 |
done |
72 |
for i in ${BUILD_LDFLAGS}; do |
73 |
fs+=( "--host_linkopt=${i}" ) |
74 |
done |
75 |
echo "${fs[*]}" |
76 |
} |
77 |
|
78 |
# @FUNCTION: bazel_setup_bazelrc |
79 |
# @DESCRIPTION: |
80 |
# Creates the bazelrc with common options that will be passed |
81 |
# to bazel. This will be called by ebazel automatically so |
82 |
# does not need to be called from the ebuild. |
83 |
bazel_setup_bazelrc() { |
84 |
if [[ -f "${T}/bazelrc" ]]; then |
85 |
return |
86 |
fi |
87 |
|
88 |
# F: fopen_wr |
89 |
# P: /proc/self/setgroups |
90 |
# Even with standalone enabled, the Bazel sandbox binary is run for feature test: |
91 |
# https://github.com/bazelbuild/bazel/blob/7b091c1397a82258e26ab5336df6c8dae1d97384/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedSpawnRunner.java#L61 |
92 |
# https://github.com/bazelbuild/bazel/blob/76555482873ffcf1d32fb40106f89231b37f850a/src/main/tools/linux-sandbox-pid1.cc#L113 |
93 |
addpredict /proc |
94 |
|
95 |
mkdir -p "${T}/bazel-cache" || die |
96 |
mkdir -p "${T}/bazel-distdir" || die |
97 |
|
98 |
cat > "${T}/bazelrc" <<-EOF || die |
99 |
startup --batch |
100 |
|
101 |
# dont strip HOME, portage sets a temp per-package dir |
102 |
build --action_env HOME |
103 |
|
104 |
# make bazel respect MAKEOPTS |
105 |
build --jobs=$(makeopts_jobs) |
106 |
build --compilation_mode=opt --host_compilation_mode=opt |
107 |
|
108 |
# FLAGS |
109 |
build $(bazel_get_flags) |
110 |
|
111 |
# Use standalone strategy to deactivate the bazel sandbox, since it |
112 |
# conflicts with FEATURES=sandbox. |
113 |
build --spawn_strategy=standalone --genrule_strategy=standalone |
114 |
test --spawn_strategy=standalone --genrule_strategy=standalone |
115 |
|
116 |
build --strip=never |
117 |
build --verbose_failures --noshow_loading_progress |
118 |
test --verbose_test_summary --verbose_failures --noshow_loading_progress |
119 |
|
120 |
# make bazel only fetch distfiles from the cache |
121 |
fetch --repository_cache="${T}/bazel-cache/" --distdir="${T}/bazel-distdir/" |
122 |
build --repository_cache="${T}/bazel-cache/" --distdir="${T}/bazel-distdir/" |
123 |
|
124 |
build --define=PREFIX=${EPREFIX%/}/usr |
125 |
build --define=LIBDIR=\$(PREFIX)/$(get_libdir) |
126 |
|
127 |
EOF |
128 |
|
129 |
tc-is-cross-compiler || \ |
130 |
echo "build --nodistinct_host_configuration" >> "${T}/bazelrc" || die |
131 |
} |
132 |
|
133 |
# @FUNCTION: ebazel |
134 |
# @USAGE: [<args>...] |
135 |
# @DESCRIPTION: |
136 |
# Run bazel with the bazelrc and output_base. |
137 |
# |
138 |
# If $MULTIBUILD_VARIANT is set, this will make an output_base |
139 |
# specific to that variant. |
140 |
# bazel_setup_bazelrc will be called and the created bazelrc |
141 |
# will be passed to bazel. |
142 |
# |
143 |
# Will automatically die if bazel does not exit cleanly. |
144 |
ebazel() { |
145 |
bazel_setup_bazelrc |
146 |
|
147 |
# Use different build folders for each multibuild variant. |
148 |
local base_suffix="${MULTIBUILD_VARIANT+-}${MULTIBUILD_VARIANT}" |
149 |
local output_base="${WORKDIR}/bazel-base${base_suffix}" |
150 |
mkdir -p "${output_base}" || die |
151 |
|
152 |
einfo Running: bazel --output_base="${output_base}" "$@" |
153 |
bazel --bazelrc="${T}/bazelrc" --output_base="${output_base}" $@ || die "ebazel $@" |
154 |
} |
155 |
|
156 |
# @FUNCTION: bazel_load_distfiles |
157 |
# @USAGE: <distfiles>... |
158 |
# @DESCRIPTION: |
159 |
# Populate the bazel distdir to fetch from since it cannot use |
160 |
# the network. Bazel looks in distdir but will only look for the |
161 |
# original filename, not the possibly renamed one that portage |
162 |
# downloaded. If the line has -> we to rename it back. This also |
163 |
# handles use-conditionals that SRC_URI does. |
164 |
# |
165 |
# Example: |
166 |
# @CODE |
167 |
# bazel_external_uris="http://a/file-2.0.tgz |
168 |
# python? ( http://b/1.0.tgz -> foo-1.0.tgz )" |
169 |
# SRC_URI="http://c/${PV}.tgz |
170 |
# ${bazel_external_uris}" |
171 |
# |
172 |
# src_unpack() { |
173 |
# unpack ${PV}.tgz |
174 |
# bazel_load_distfiles "${bazel_external_uris}" |
175 |
# } |
176 |
# @CODE |
177 |
bazel_load_distfiles() { |
178 |
local src dst uri rename |
179 |
|
180 |
[[ "$@" ]] || die "Missing args" |
181 |
mkdir -p "${T}/bazel-distdir" || die |
182 |
|
183 |
while read uri rename dst; do |
184 |
src="${uri##*/}" |
185 |
[[ -z $src ]] && continue |
186 |
if [[ "$rename" != "->" ]]; then |
187 |
dst="${src}" |
188 |
fi |
189 |
|
190 |
[[ ${A} =~ ${dst} ]] || continue |
191 |
|
192 |
if [[ "$dst" == "$src" ]]; then |
193 |
einfo "Copying $dst to bazel distdir ..." |
194 |
else |
195 |
einfo "Copying $dst to bazel distdir $src ..." |
196 |
fi |
197 |
dst="$(readlink -f "${DISTDIR}/${dst}")" |
198 |
ln -s "${dst}" "${T}/bazel-distdir/${src}" || die |
199 |
done <<< "$(sed -re 's/!?[A-Za-z]+\?\s+\(\s*//g; s/\s+\)//g' <<< "$@")" |
200 |
} |
201 |
|
202 |
_BAZEL_ECLASS=1 |
203 |
fi |