diff options
author | Tudor Florea <tudor.florea@enea.com> | 2015-10-09 22:59:03 +0200 |
---|---|---|
committer | Tudor Florea <tudor.florea@enea.com> | 2015-10-09 22:59:03 +0200 |
commit | 972dcfcdbfe75dcfeb777150c136576cf1a71e99 (patch) | |
tree | 97a61cd7e293d7ae9d56ef7ed0f81253365bb026 /meta/classes/icecc.bbclass | |
download | poky-972dcfcdbfe75dcfeb777150c136576cf1a71e99.tar.gz |
initial commit for Enea Linux 5.0 arm
Signed-off-by: Tudor Florea <tudor.florea@enea.com>
Diffstat (limited to 'meta/classes/icecc.bbclass')
-rw-r--r-- | meta/classes/icecc.bbclass | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/meta/classes/icecc.bbclass b/meta/classes/icecc.bbclass new file mode 100644 index 0000000000..2f9e3cf8ef --- /dev/null +++ b/meta/classes/icecc.bbclass | |||
@@ -0,0 +1,332 @@ | |||
1 | # IceCream distributed compiling support | ||
2 | # | ||
3 | # Stages directories with symlinks from gcc/g++ to icecc, for both | ||
4 | # native and cross compilers. Depending on each configure or compile, | ||
5 | # the directories are added at the head of the PATH list and ICECC_CXX | ||
6 | # and ICEC_CC are set. | ||
7 | # | ||
8 | # For the cross compiler, creates a tar.gz of our toolchain and sets | ||
9 | # ICECC_VERSION accordingly. | ||
10 | # | ||
11 | # The class now handles all 3 different compile 'stages' (i.e native ,cross-kernel and target) creating the | ||
12 | # necessary environment tar.gz file to be used by the remote machines. | ||
13 | # It also supports meta-toolchain generation | ||
14 | # | ||
15 | # If ICECC_PATH is not set in local.conf then the class will try to locate it using 'bb.utils.which' | ||
16 | # but nothing is sure ;) | ||
17 | # | ||
18 | # If ICECC_ENV_EXEC is set in local.conf, then it should point to the icecc-create-env script provided by the user | ||
19 | # or the default one provided by icecc-create-env.bb will be used | ||
20 | # (NOTE that this is a modified version of the script need it and *not the one that comes with icecc* | ||
21 | # | ||
22 | # User can specify if specific packages or packages belonging to class should not use icecc to distribute | ||
23 | # compile jobs to remote machines, but handled locally, by defining ICECC_USER_CLASS_BL and ICECC_USER_PACKAGE_BL | ||
24 | # with the appropriate values in local.conf. In addition the user can force to enable icecc for packages | ||
25 | # which set an empty PARALLEL_MAKE variable by defining ICECC_USER_PACKAGE_WL. | ||
26 | # | ||
27 | ######################################################################################### | ||
28 | #Error checking is kept to minimum so double check any parameters you pass to the class | ||
29 | ########################################################################################### | ||
30 | |||
31 | BB_HASHBASE_WHITELIST += "ICECC_PARALLEL_MAKE ICECC_DISABLED ICECC_USER_PACKAGE_BL ICECC_USER_CLASS_BL ICECC_USER_PACKAGE_WL ICECC_PATH ICECC_ENV_EXEC" | ||
32 | |||
33 | ICECC_ENV_EXEC ?= "${STAGING_BINDIR_NATIVE}/icecc-create-env" | ||
34 | |||
35 | def icecc_dep_prepend(d): | ||
36 | # INHIBIT_DEFAULT_DEPS doesn't apply to the patch command. Whether or not | ||
37 | # we need that built is the responsibility of the patch function / class, not | ||
38 | # the application. | ||
39 | if not d.getVar('INHIBIT_DEFAULT_DEPS'): | ||
40 | return "icecc-create-env-native" | ||
41 | return "" | ||
42 | |||
43 | DEPENDS_prepend += "${@icecc_dep_prepend(d)} " | ||
44 | |||
45 | def get_cross_kernel_cc(bb,d): | ||
46 | kernel_cc = d.getVar('KERNEL_CC') | ||
47 | |||
48 | # evaluate the expression by the shell if necessary | ||
49 | if '`' in kernel_cc or '$(' in kernel_cc: | ||
50 | kernel_cc = os.popen("echo %s" % kernel_cc).read()[:-1] | ||
51 | |||
52 | kernel_cc = d.expand(kernel_cc) | ||
53 | kernel_cc = kernel_cc.replace('ccache', '').strip() | ||
54 | kernel_cc = kernel_cc.split(' ')[0] | ||
55 | kernel_cc = kernel_cc.strip() | ||
56 | return kernel_cc | ||
57 | |||
58 | def get_icecc(d): | ||
59 | return d.getVar('ICECC_PATH') or bb.utils.which(os.getenv("PATH"), "icecc") | ||
60 | |||
61 | def create_path(compilers, bb, d): | ||
62 | """ | ||
63 | Create Symlinks for the icecc in the staging directory | ||
64 | """ | ||
65 | staging = os.path.join(d.expand('${STAGING_BINDIR}'), "ice") | ||
66 | if icc_is_kernel(bb, d): | ||
67 | staging += "-kernel" | ||
68 | |||
69 | #check if the icecc path is set by the user | ||
70 | icecc = get_icecc(d) | ||
71 | |||
72 | # Create the dir if necessary | ||
73 | try: | ||
74 | os.stat(staging) | ||
75 | except: | ||
76 | try: | ||
77 | os.makedirs(staging) | ||
78 | except: | ||
79 | pass | ||
80 | |||
81 | for compiler in compilers: | ||
82 | gcc_path = os.path.join(staging, compiler) | ||
83 | try: | ||
84 | os.stat(gcc_path) | ||
85 | except: | ||
86 | try: | ||
87 | os.symlink(icecc, gcc_path) | ||
88 | except: | ||
89 | pass | ||
90 | |||
91 | return staging | ||
92 | |||
93 | def use_icc(bb,d): | ||
94 | if d.getVar('ICECC_DISABLED') == "1": | ||
95 | # don't even try it, when explicitly disabled | ||
96 | return "no" | ||
97 | |||
98 | # allarch recipes don't use compiler | ||
99 | if icc_is_allarch(bb, d): | ||
100 | return "no" | ||
101 | |||
102 | pn = d.getVar('PN', True) | ||
103 | |||
104 | system_class_blacklist = [] | ||
105 | user_class_blacklist = (d.getVar('ICECC_USER_CLASS_BL') or "none").split() | ||
106 | package_class_blacklist = system_class_blacklist + user_class_blacklist | ||
107 | |||
108 | for black in package_class_blacklist: | ||
109 | if bb.data.inherits_class(black, d): | ||
110 | bb.debug(1, "%s: class %s found in blacklist, disable icecc" % (pn, black)) | ||
111 | return "no" | ||
112 | |||
113 | # "system" recipe blacklist contains a list of packages that can not distribute compile tasks | ||
114 | # for one reason or the other | ||
115 | # this is the old list (which doesn't seem to be valid anymore, because I was able to build | ||
116 | # all these with icecc enabled) | ||
117 | # system_package_blacklist = [ "uclibc", "glibc", "gcc", "bind", "u-boot", "dhcp-forwarder", "enchant", "connman", "orbit2" ] | ||
118 | # when adding new entry, please document why (how it failed) so that we can re-evaluate it later | ||
119 | # e.g. when there is new version | ||
120 | system_package_blacklist = [] | ||
121 | user_package_blacklist = (d.getVar('ICECC_USER_PACKAGE_BL') or "").split() | ||
122 | user_package_whitelist = (d.getVar('ICECC_USER_PACKAGE_WL') or "").split() | ||
123 | package_blacklist = system_package_blacklist + user_package_blacklist | ||
124 | |||
125 | if pn in package_blacklist: | ||
126 | bb.debug(1, "%s: found in blacklist, disable icecc" % pn) | ||
127 | return "no" | ||
128 | |||
129 | if pn in user_package_whitelist: | ||
130 | bb.debug(1, "%s: found in whitelist, enable icecc" % pn) | ||
131 | return "yes" | ||
132 | |||
133 | if d.getVar('PARALLEL_MAKE') == "": | ||
134 | bb.debug(1, "%s: has empty PARALLEL_MAKE, disable icecc" % pn) | ||
135 | return "no" | ||
136 | |||
137 | return "yes" | ||
138 | |||
139 | def icc_is_allarch(bb, d): | ||
140 | return d.getVar("PACKAGE_ARCH") == "all" | ||
141 | |||
142 | def icc_is_kernel(bb, d): | ||
143 | return \ | ||
144 | bb.data.inherits_class("kernel", d); | ||
145 | |||
146 | def icc_is_native(bb, d): | ||
147 | return \ | ||
148 | bb.data.inherits_class("cross", d) or \ | ||
149 | bb.data.inherits_class("native", d); | ||
150 | |||
151 | # Don't pollute allarch signatures with TARGET_FPU | ||
152 | icc_version[vardepsexclude] += "TARGET_FPU" | ||
153 | def icc_version(bb, d): | ||
154 | if use_icc(bb, d) == "no": | ||
155 | return "" | ||
156 | |||
157 | parallel = d.getVar('ICECC_PARALLEL_MAKE') or "" | ||
158 | if not d.getVar('PARALLEL_MAKE') == "" and parallel: | ||
159 | d.setVar("PARALLEL_MAKE", parallel) | ||
160 | |||
161 | if icc_is_native(bb, d): | ||
162 | archive_name = "local-host-env" | ||
163 | elif d.expand('${HOST_PREFIX}') == "": | ||
164 | bb.fatal(d.expand("${PN}"), " NULL prefix") | ||
165 | else: | ||
166 | prefix = d.expand('${HOST_PREFIX}' ) | ||
167 | distro = d.expand('${DISTRO}') | ||
168 | target_sys = d.expand('${TARGET_SYS}') | ||
169 | float = d.getVar('TARGET_FPU') or "hard" | ||
170 | archive_name = prefix + distro + "-" + target_sys + "-" + float | ||
171 | if icc_is_kernel(bb, d): | ||
172 | archive_name += "-kernel" | ||
173 | |||
174 | import socket | ||
175 | ice_dir = d.expand('${STAGING_DIR_NATIVE}${prefix_native}') | ||
176 | tar_file = os.path.join(ice_dir, 'ice', archive_name + "-@VERSION@-" + socket.gethostname() + '.tar.gz') | ||
177 | |||
178 | return tar_file | ||
179 | |||
180 | def icc_path(bb,d): | ||
181 | if use_icc(bb, d) == "no": | ||
182 | # don't create unnecessary directories when icecc is disabled | ||
183 | return | ||
184 | |||
185 | if icc_is_kernel(bb, d): | ||
186 | return create_path( [get_cross_kernel_cc(bb,d), ], bb, d) | ||
187 | |||
188 | else: | ||
189 | prefix = d.expand('${HOST_PREFIX}') | ||
190 | return create_path( [prefix+"gcc", prefix+"g++"], bb, d) | ||
191 | |||
192 | def icc_get_external_tool(bb, d, tool): | ||
193 | external_toolchain_bindir = d.expand('${EXTERNAL_TOOLCHAIN}${bindir_cross}') | ||
194 | target_prefix = d.expand('${TARGET_PREFIX}') | ||
195 | return os.path.join(external_toolchain_bindir, '%s%s' % (target_prefix, tool)) | ||
196 | |||
197 | # Don't pollute native signatures with target TUNE_PKGARCH through STAGING_BINDIR_TOOLCHAIN | ||
198 | icc_get_tool[vardepsexclude] += "STAGING_BINDIR_TOOLCHAIN" | ||
199 | def icc_get_tool(bb, d, tool): | ||
200 | if icc_is_native(bb, d): | ||
201 | return bb.utils.which(os.getenv("PATH"), tool) | ||
202 | elif icc_is_kernel(bb, d): | ||
203 | return bb.utils.which(os.getenv("PATH"), get_cross_kernel_cc(bb, d)) | ||
204 | else: | ||
205 | ice_dir = d.expand('${STAGING_BINDIR_TOOLCHAIN}') | ||
206 | target_sys = d.expand('${TARGET_SYS}') | ||
207 | tool_bin = os.path.join(ice_dir, "%s-%s" % (target_sys, tool)) | ||
208 | if os.path.isfile(tool_bin): | ||
209 | return tool_bin | ||
210 | else: | ||
211 | external_tool_bin = icc_get_external_tool(bb, d, tool) | ||
212 | if os.path.isfile(external_tool_bin): | ||
213 | return external_tool_bin | ||
214 | else: | ||
215 | return "" | ||
216 | |||
217 | def icc_get_and_check_tool(bb, d, tool): | ||
218 | # Check that g++ or gcc is not a symbolic link to icecc binary in | ||
219 | # PATH or icecc-create-env script will silently create an invalid | ||
220 | # compiler environment package. | ||
221 | t = icc_get_tool(bb, d, tool) | ||
222 | if t and os.popen("readlink -f %s" % t).read()[:-1] == get_icecc(d): | ||
223 | bb.error("%s is a symlink to %s in PATH and this prevents icecc from working" % (t, get_icecc(d))) | ||
224 | return "" | ||
225 | else: | ||
226 | return t | ||
227 | |||
228 | wait_for_file() { | ||
229 | local TIME_ELAPSED=0 | ||
230 | local FILE_TO_TEST=$1 | ||
231 | local TIMEOUT=$2 | ||
232 | until [ -f "$FILE_TO_TEST" ] | ||
233 | do | ||
234 | TIME_ELAPSED=`expr $TIME_ELAPSED + 1` | ||
235 | if [ $TIME_ELAPSED -gt $TIMEOUT ] | ||
236 | then | ||
237 | return 1 | ||
238 | fi | ||
239 | sleep 1 | ||
240 | done | ||
241 | } | ||
242 | |||
243 | def set_icecc_env(): | ||
244 | # dummy python version of set_icecc_env | ||
245 | return | ||
246 | |||
247 | set_icecc_env() { | ||
248 | if [ "${@use_icc(bb, d)}" = "no" ] | ||
249 | then | ||
250 | return | ||
251 | fi | ||
252 | ICECC_VERSION="${@icc_version(bb, d)}" | ||
253 | if [ "x${ICECC_VERSION}" = "x" ] | ||
254 | then | ||
255 | bbwarn "Cannot use icecc: could not get ICECC_VERSION" | ||
256 | return | ||
257 | fi | ||
258 | |||
259 | ICE_PATH="${@icc_path(bb, d)}" | ||
260 | if [ "x${ICE_PATH}" = "x" ] | ||
261 | then | ||
262 | bbwarn "Cannot use icecc: could not get ICE_PATH" | ||
263 | return | ||
264 | fi | ||
265 | |||
266 | ICECC_CC="${@icc_get_and_check_tool(bb, d, "gcc")}" | ||
267 | ICECC_CXX="${@icc_get_and_check_tool(bb, d, "g++")}" | ||
268 | # cannot use icc_get_and_check_tool here because it assumes as without target_sys prefix | ||
269 | ICECC_WHICH_AS="${@bb.utils.which(os.getenv('PATH'), 'as')}" | ||
270 | if [ ! -x "${ICECC_CC}" -o ! -x "${ICECC_CXX}" ] | ||
271 | then | ||
272 | bbwarn "Cannot use icecc: could not get ICECC_CC or ICECC_CXX" | ||
273 | return | ||
274 | fi | ||
275 | |||
276 | ICE_VERSION=`$ICECC_CC -dumpversion` | ||
277 | ICECC_VERSION=`echo ${ICECC_VERSION} | sed -e "s/@VERSION@/$ICE_VERSION/g"` | ||
278 | if [ ! -x "${ICECC_ENV_EXEC}" ] | ||
279 | then | ||
280 | bbwarn "Cannot use icecc: invalid ICECC_ENV_EXEC" | ||
281 | return | ||
282 | fi | ||
283 | |||
284 | ICECC_AS="`${ICECC_CC} -print-prog-name=as`" | ||
285 | # for target recipes should return something like: | ||
286 | # /OE/tmp-eglibc/sysroots/x86_64-linux/usr/libexec/arm920tt-oe-linux-gnueabi/gcc/arm-oe-linux-gnueabi/4.8.2/as | ||
287 | # and just "as" for native, if it returns "as" in current directory (for whatever reason) use "as" from PATH | ||
288 | if [ "`dirname "${ICECC_AS}"`" = "." ] | ||
289 | then | ||
290 | ICECC_AS="${ICECC_WHICH_AS}" | ||
291 | fi | ||
292 | |||
293 | if [ ! -f "${ICECC_VERSION}.done" ] | ||
294 | then | ||
295 | mkdir -p "`dirname "${ICECC_VERSION}"`" | ||
296 | |||
297 | # the ICECC_VERSION generation step must be locked by a mutex | ||
298 | # in order to prevent race conditions | ||
299 | if flock -n "${ICECC_VERSION}.lock" \ | ||
300 | ${ICECC_ENV_EXEC} "${ICECC_CC}" "${ICECC_CXX}" "${ICECC_AS}" "${ICECC_VERSION}" | ||
301 | then | ||
302 | touch "${ICECC_VERSION}.done" | ||
303 | elif [ ! wait_for_file "${ICECC_VERSION}.done" 30 ] | ||
304 | then | ||
305 | # locking failed so wait for ${ICECC_VERSION}.done to appear | ||
306 | bbwarn "Timeout waiting for ${ICECC_VERSION}.done" | ||
307 | return | ||
308 | fi | ||
309 | fi | ||
310 | |||
311 | export ICECC_VERSION ICECC_CC ICECC_CXX | ||
312 | export PATH="$ICE_PATH:$PATH" | ||
313 | export CCACHE_PATH="$PATH" | ||
314 | |||
315 | bbnote "Using icecc" | ||
316 | } | ||
317 | |||
318 | do_configure_prepend() { | ||
319 | set_icecc_env | ||
320 | } | ||
321 | |||
322 | do_compile_prepend() { | ||
323 | set_icecc_env | ||
324 | } | ||
325 | |||
326 | do_compile_kernelmodules_prepend() { | ||
327 | set_icecc_env | ||
328 | } | ||
329 | |||
330 | do_install_prepend() { | ||
331 | set_icecc_env | ||
332 | } | ||