srctree: completely reimplement the task merging into do_populate_staging.
authorChris Larson <clarson@mvista.com>
Wed, 26 Aug 2009 21:02:48 +0000 (14:02 -0700)
committerChris Larson <clarson@mvista.com>
Wed, 26 Aug 2009 21:04:48 +0000 (14:04 -0700)
This fixes issues seen with the use of kernel.bbclass, so in existing source
tree kernel builds work happily now.

Signed-off-by: Chris Larson <clarson@mvista.com>
classes/srctree.bbclass

index e2a4303..67cb9ff 100644 (file)
@@ -27,8 +27,6 @@ SRC_URI = ""
 do_package ?= "    pass"
 do_package[func] = "1"
 do_package[python] = "1"
-
-# Ensure that do_package depends on populate_staging, rather than install
 addtask package after do_populate_staging
 
 # This stuff is needed to facilitate variants (normal, native, cross, sdk)
@@ -40,40 +38,94 @@ addtask package after do_populate_staging
 # lock file.  This ensures that none of the tasks which access ${S} can
 # interleave amongst the recipes that share that ${S}.
 
-def variant_hack(d):
+def merge_tasks(d):
+       """
+       merge_tasks performs two operations:
+       1) removes do_patch and its deps from the build entirely.
+       2) merges all of the operations that occur prior to do_populate_staging
+       into do_populate_staging.
+
+       This is necessary, because of recipe variants (normal, native, cross,
+       sdk).  If a bitbake run happens to want to build more than one of
+       these variants in a single run, it's possible for them to step on one
+       another's toes, due to the shared ${S}.  Interleaved
+       configure/compile/install amongst variants will break things badly.
+       """
        from itertools import chain
+       from bb import note
 
-       # Kill dependencies on the fromtasks
-       fromtasks = ["do_configure", "do_compile", "do_install"]
-       for key in d.keys():
-               task = d.getVarFlag(key, "task")
-               if task:
-                       deps = d.getVarFlag(key, "deps")
-                       for task_ in fromtasks:
-                               if task_ in deps:
-                                       deps.remove(task_)
-                       # if not key in fromtasks + ["do_populate_staging"]:
-                       #        deps.append("do_populate_staging")
-                       d.setVarFlag(key, "deps", deps)
-
-       # Pull the task deps from fromtasks over to the new task, minus deltasks
-       deltasks = ("do_patch", "do_unpack", "do_fetch")
-       deps = set(chain(*[(d.getVarFlag(old, "deps")) for old in fromtasks + ["do_populate_staging"]]))
-       d.setVarFlag("do_populate_staging", "deps", deps.difference(deltasks))
+       def __gather_taskdeps(task, seen):
+               for dep in d.getVarFlag(task, "deps"):
+                       if not dep in seen:
+                               __gather_taskdeps(dep, seen)
+               if not task in seen:
+                       seen.append(task)
+
+       def gather_taskdeps(task):
+               items = []
+               __gather_taskdeps(task, items)
+               return items
+
+       newtask = "do_populate_staging"
+       mergedtasks = gather_taskdeps(newtask)
+       mergedtasks.pop()
+       deltasks = gather_taskdeps("do_patch")
+
+       for task in (key for key in d.keys()
+                    if d.getVarFlag(key, "task") and
+                    not key in mergedtasks):
+               deps = d.getVarFlag(task, "deps")
+               for mergetask in mergedtasks:
+                       if mergetask in (d.getVarFlag(task, "recrdeptask"),
+                                        d.getVarFlag(task, "recdeptask"),
+                                        d.getVarFlag(task, "deptask")):
+                               continue
+
+                       if mergetask in deps:
+                               deps.remove(mergetask)
+                               #note("removing dep on %s from %s" % (mergetask, task))
+
+                               if not mergetask in deltasks and \
+                                  not newtask in deps:
+                                       #note("adding dep on %s to %s" % (newtask, task))
+                                       deps.append(newtask)
+               d.setVarFlag(task, "deps", deps)
+
+       for task in mergedtasks[:-1]:
+               deps = d.getVarFlag(task, "deps")
+               for deltask in deltasks:
+                       if deltask in deps:
+                               deps.remove(deltask)
+               d.setVarFlag(task, "deps", deps)
 
        # Pull cross recipe task deps over
-       d.setVarFlag("do_populate_staging", "depends", " ".join((d.getVarFlag(old, "depends") or "" for old in fromtasks)))
+       depends = (d.getVarFlag(task, "depends") or ""
+                  for task in mergedtasks[:-1]
+                  if not task in deltasks)
+       d.setVarFlag("do_populate_staging", "depends", " ".join(depends))
 
 python () {
-       variant_hack(d)
+    merge_tasks(d)
 }
 
+# Manually run do_install & all of its deps, then do_stage
 python do_populate_staging () {
+       from os.path import exists
        from bb.build import exec_task, exec_func
+       from bb import note
+
+       stamp = d.getVar("STAMP", True)
+
+       def rec_exec_task(task, seen):
+               for dep in d.getVarFlag(task, "deps"):
+                       if not dep in seen:
+                               rec_exec_task(dep, seen)
+               seen.add(task)
+               #if not exists("%s.%s" % (stamp, task)):
+               note("Executing task %s" % task)
+               exec_task(task, d)
 
-       exec_task("do_configure", d)
-       exec_task("do_compile", d)
-       exec_task("do_install", d)
+       rec_exec_task("do_install", set())
        exec_func("do_stage", d)
 }
 do_populate_staging[lockfiles] += "${S}/.lock"