diff options
Diffstat (limited to 'bitbake/lib/bb/build.py')
| -rw-r--r-- | bitbake/lib/bb/build.py | 193 | 
1 files changed, 100 insertions, 93 deletions
| diff --git a/bitbake/lib/bb/build.py b/bitbake/lib/bb/build.py index 942bdc1a39..bf6b612f32 100644 --- a/bitbake/lib/bb/build.py +++ b/bitbake/lib/bb/build.py | |||
| @@ -1,29 +1,29 @@ | |||
| 1 | #!/usr/bin/env python | ||
| 2 | # ex:ts=4:sw=4:sts=4:et | 1 | # ex:ts=4:sw=4:sts=4:et | 
| 3 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- | 2 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- | 
| 4 | """ | 3 | # | 
| 5 | BitBake 'Build' implementation | 4 | # BitBake 'Build' implementation | 
| 6 | 5 | # | |
| 7 | Core code for function execution and task handling in the | 6 | # Core code for function execution and task handling in the | 
| 8 | BitBake build tools. | 7 | # BitBake build tools. | 
| 9 | 8 | # | |
| 10 | Copyright (C) 2003, 2004 Chris Larson | 9 | # Copyright (C) 2003, 2004 Chris Larson | 
| 11 | 10 | # | |
| 12 | Based on Gentoo's portage.py. | 11 | # Based on Gentoo's portage.py. | 
| 13 | 12 | # | |
| 14 | This program is free software; you can redistribute it and/or modify it under | 13 | # This program is free software; you can redistribute it and/or modify | 
| 15 | the terms of the GNU General Public License as published by the Free Software | 14 | # it under the terms of the GNU General Public License version 2 as | 
| 16 | Foundation; either version 2 of the License, or (at your option) any later | 15 | # published by the Free Software Foundation. | 
| 17 | version. | 16 | # | 
| 18 | 17 | # This program is distributed in the hope that it will be useful, | |
| 19 | This program is distributed in the hope that it will be useful, but WITHOUT | 18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 20 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
| 21 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. | 20 | # GNU General Public License for more details. | 
| 22 | 21 | # | |
| 23 | You should have received a copy of the GNU General Public License along with | 22 | # You should have received a copy of the GNU General Public License along | 
| 24 | 23 | # with this program; if not, write to the Free Software Foundation, Inc., | |
| 25 | Based on functions from the base bb module, Copyright 2003 Holger Schurig | 24 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 
| 26 | """ | 25 | # | 
| 26 | #Based on functions from the base bb module, Copyright 2003 Holger Schurig | ||
| 27 | 27 | ||
| 28 | from bb import data, fetch, event, mkdirhier, utils | 28 | from bb import data, fetch, event, mkdirhier, utils | 
| 29 | import bb, os | 29 | import bb, os | 
| @@ -219,14 +219,18 @@ def exec_func_shell(func, d): | |||
| 219 | bb.msg.error(bb.msg.domain.Build, "function %s failed" % func) | 219 | bb.msg.error(bb.msg.domain.Build, "function %s failed" % func) | 
| 220 | if data.getVar("BBINCLUDELOGS", d): | 220 | if data.getVar("BBINCLUDELOGS", d): | 
| 221 | bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile) | 221 | bb.msg.error(bb.msg.domain.Build, "log data follows (%s)" % logfile) | 
| 222 | f = open(logfile, "r") | 222 | number_of_lines = data.getVar("BBINCLUDELOGS_LINES", d) | 
| 223 | while True: | 223 | if number_of_lines: | 
| 224 | l = f.readline() | 224 | os.system('tail -n%s %s' % (number_of_lines, logfile)) | 
| 225 | if l == '': | 225 | else: | 
| 226 | break | 226 | f = open(logfile, "r") | 
| 227 | l = l.rstrip() | 227 | while True: | 
| 228 | print '| %s' % l | 228 | l = f.readline() | 
| 229 | f.close() | 229 | if l == '': | 
| 230 | break | ||
| 231 | l = l.rstrip() | ||
| 232 | print '| %s' % l | ||
| 233 | f.close() | ||
| 230 | else: | 234 | else: | 
| 231 | bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile) | 235 | bb.msg.error(bb.msg.domain.Build, "see log in %s" % logfile) | 
| 232 | raise FuncFailed( logfile ) | 236 | raise FuncFailed( logfile ) | 
| @@ -252,9 +256,8 @@ def exec_task(task, d): | |||
| 252 | raise EventException("Missing node in task graph", InvalidTask(task, d)) | 256 | raise EventException("Missing node in task graph", InvalidTask(task, d)) | 
| 253 | 257 | ||
| 254 | # check whether this task needs executing.. | 258 | # check whether this task needs executing.. | 
| 255 | if not data.getVarFlag(task, 'force', d): | 259 | if stamp_is_current(task, d): | 
| 256 | if stamp_is_current(task, d): | 260 | return 1 | 
| 257 | return 1 | ||
| 258 | 261 | ||
| 259 | # follow digraph path up, then execute our way back down | 262 | # follow digraph path up, then execute our way back down | 
| 260 | def execute(graph, item): | 263 | def execute(graph, item): | 
| @@ -291,59 +294,43 @@ def exec_task(task, d): | |||
| 291 | 294 | ||
| 292 | # make stamp, or cause event and raise exception | 295 | # make stamp, or cause event and raise exception | 
| 293 | if not data.getVarFlag(task, 'nostamp', d): | 296 | if not data.getVarFlag(task, 'nostamp', d): | 
| 294 | mkstamp(task, d) | 297 | make_stamp(task, d) | 
| 295 | 298 | ||
| 296 | def stamp_is_current_cache(dataCache, file_name, task, checkdeps = 1): | 299 | def extract_stamp_data(d, fn): | 
| 297 | """ | 300 | """ | 
| 298 | Check status of a given task's stamp. | 301 | Extracts stamp data from d which is either a data dictonary (fn unset) | 
| 299 | Returns 0 if it is not current and needs updating. | 302 | or a dataCache entry (fn set). | 
| 300 | Same as stamp_is_current but works against the dataCache instead of d | ||
| 301 | """ | 303 | """ | 
| 302 | task_graph = dataCache.task_queues[file_name] | 304 | if fn: | 
| 303 | 305 | return (d.task_queues[fn], d.stamp[fn], d.task_deps[fn]) | |
| 304 | if not dataCache.stamp[file_name]: | 306 | task_graph = data.getVar('_task_graph', d) | 
| 305 | return 0 | 307 | if not task_graph: | 
| 306 | 308 | task_graph = bb.digraph() | |
| 307 | stampfile = "%s.%s" % (dataCache.stamp[file_name], task) | 309 | data.setVar('_task_graph', task_graph, d) | 
| 308 | if not os.access(stampfile, os.F_OK): | 310 | return (task_graph, data.getVar('STAMP', d, 1), None) | 
| 309 | return 0 | ||
| 310 | |||
| 311 | if checkdeps == 0: | ||
| 312 | return 1 | ||
| 313 | |||
| 314 | import stat | ||
| 315 | tasktime = os.stat(stampfile)[stat.ST_MTIME] | ||
| 316 | |||
| 317 | _deps = [] | ||
| 318 | def checkStamp(graph, task): | ||
| 319 | # check for existance | ||
| 320 | if 'nostamp' in dataCache.task_deps[file_name] and task in dataCache.task_deps[file_name]['nostamp']: | ||
| 321 | return 1 | ||
| 322 | |||
| 323 | if not stamp_is_current_cache(dataCache, file_name, task, 0): | ||
| 324 | return 0 | ||
| 325 | |||
| 326 | depfile = "%s.%s" % (dataCache.stamp[file_name], task) | ||
| 327 | deptime = os.stat(depfile)[stat.ST_MTIME] | ||
| 328 | if deptime > tasktime: | ||
| 329 | return 0 | ||
| 330 | return 1 | ||
| 331 | 311 | ||
| 332 | return task_graph.walkdown(task, checkStamp) | 312 | def extract_stamp(d, fn): | 
| 313 | """ | ||
| 314 | Extracts stamp format which is either a data dictonary (fn unset) | ||
| 315 | or a dataCache entry (fn set). | ||
| 316 | """ | ||
| 317 | if fn: | ||
| 318 | return d.stamp[fn] | ||
| 319 | return data.getVar('STAMP', d, 1) | ||
| 333 | 320 | ||
| 334 | def stamp_is_current(task, d, checkdeps = 1): | 321 | def stamp_is_current(task, d, file_name = None, checkdeps = 1): | 
| 335 | """ | 322 | """ | 
| 336 | Check status of a given task's stamp. | 323 | Check status of a given task's stamp. | 
| 337 | Returns 0 if it is not current and needs updating. | 324 | Returns 0 if it is not current and needs updating. | 
| 325 | (d can be a data dict or dataCache) | ||
| 338 | """ | 326 | """ | 
| 339 | task_graph = data.getVar('_task_graph', d) | 327 | |
| 340 | if not task_graph: | 328 | (task_graph, stampfn, taskdep) = extract_stamp_data(d, file_name) | 
| 341 | task_graph = bb.digraph() | 329 | |
| 342 | data.setVar('_task_graph', task_graph, d) | 330 | if not stampfn: | 
| 343 | stamp = data.getVar('STAMP', d) | ||
| 344 | if not stamp: | ||
| 345 | return 0 | 331 | return 0 | 
| 346 | stampfile = "%s.%s" % (data.expand(stamp, d), task) | 332 | |
| 333 | stampfile = "%s.%s" % (stampfn, task) | ||
| 347 | if not os.access(stampfile, os.F_OK): | 334 | if not os.access(stampfile, os.F_OK): | 
| 348 | return 0 | 335 | return 0 | 
| 349 | 336 | ||
| @@ -356,13 +343,17 @@ def stamp_is_current(task, d, checkdeps = 1): | |||
| 356 | _deps = [] | 343 | _deps = [] | 
| 357 | def checkStamp(graph, task): | 344 | def checkStamp(graph, task): | 
| 358 | # check for existance | 345 | # check for existance | 
| 359 | if data.getVarFlag(task, 'nostamp', d): | 346 | if file_name: | 
| 360 | return 1 | 347 | if 'nostamp' in taskdep and task in taskdep['nostamp']: | 
| 348 | return 1 | ||
| 349 | else: | ||
| 350 | if data.getVarFlag(task, 'nostamp', d): | ||
| 351 | return 1 | ||
| 361 | 352 | ||
| 362 | if not stamp_is_current(task, d, 0): | 353 | if not stamp_is_current(task, d, file_name, 0 ): | 
| 363 | return 0 | 354 | return 0 | 
| 364 | 355 | ||
| 365 | depfile = "%s.%s" % (data.expand(stamp, d), task) | 356 | depfile = "%s.%s" % (stampfn, task) | 
| 366 | deptime = os.stat(depfile)[stat.ST_MTIME] | 357 | deptime = os.stat(depfile)[stat.ST_MTIME] | 
| 367 | if deptime > tasktime: | 358 | if deptime > tasktime: | 
| 368 | return 0 | 359 | return 0 | 
| @@ -370,24 +361,40 @@ def stamp_is_current(task, d, checkdeps = 1): | |||
| 370 | 361 | ||
| 371 | return task_graph.walkdown(task, checkStamp) | 362 | return task_graph.walkdown(task, checkStamp) | 
| 372 | 363 | ||
| 373 | 364 | def stamp_internal(task, d, file_name): | |
| 374 | def md5_is_current(task): | 365 | """ | 
| 375 | """Check if a md5 file for a given task is current""" | 366 | Internal stamp helper function | 
| 376 | 367 | Removes any stamp for the given task | |
| 377 | 368 | Makes sure the stamp directory exists | |
| 378 | def mkstamp(task, d): | 369 | Returns the stamp path+filename | 
| 379 | """Creates/updates a stamp for a given task""" | 370 | """ | 
| 380 | stamp = data.getVar('STAMP', d) | 371 | stamp = extract_stamp(d, file_name) | 
| 381 | if not stamp: | 372 | if not stamp: | 
| 382 | return | 373 | return | 
| 383 | stamp = "%s.%s" % (data.expand(stamp, d), task) | 374 | stamp = "%s.%s" % (stamp, task) | 
| 384 | mkdirhier(os.path.dirname(stamp)) | 375 | mkdirhier(os.path.dirname(stamp)) | 
| 385 | # Remove the file and recreate to force timestamp | 376 | # Remove the file and recreate to force timestamp | 
| 386 | # change on broken NFS filesystems | 377 | # change on broken NFS filesystems | 
| 387 | if os.access(stamp, os.F_OK): | 378 | if os.access(stamp, os.F_OK): | 
| 388 | os.remove(stamp) | 379 | os.remove(stamp) | 
| 389 | f = open(stamp, "w") | 380 | return stamp | 
| 390 | f.close() | 381 | |
| 382 | def make_stamp(task, d, file_name = None): | ||
| 383 | """ | ||
| 384 | Creates/updates a stamp for a given task | ||
| 385 | (d can be a data dict or dataCache) | ||
| 386 | """ | ||
| 387 | stamp = stamp_internal(task, d, file_name) | ||
| 388 | if stamp: | ||
| 389 | f = open(stamp, "w") | ||
| 390 | f.close() | ||
| 391 | |||
| 392 | def del_stamp(task, d, file_name = None): | ||
| 393 | """ | ||
| 394 | Removes a stamp for a given task | ||
| 395 | (d can be a data dict or dataCache) | ||
| 396 | """ | ||
| 397 | stamp_internal(task, d, file_name) | ||
| 391 | 398 | ||
| 392 | def add_task(task, deps, d): | 399 | def add_task(task, deps, d): | 
| 393 | task_graph = data.getVar('_task_graph', d) | 400 | task_graph = data.getVar('_task_graph', d) | 
