Merge branch 'org.openembedded.dev' of ssh+git://git@git.openembedded.net/openembedde...
[openembedded.git] / classes / srctree.bbclass
1 # Copyright (C) 2009 Chris Larson <clarson@kergoth.com>
2 # Released under the MIT license (see COPYING.MIT for the terms)
3 #
4 # srctree.bbclass enables operation inside of an existing source tree for a
5 # project, rather than using the fetch/unpack/patch idiom.
6 #
7 # By default, it expects that you're keeping the recipe(s) inside the
8 # aforementioned source tree, but you could override S to point at an external
9 # directory and place the recipes in a normal collection/overlay, if you so
10 # chose.
11 #
12 # It also provides some convenience python functions for assembling your
13 # do_clean, if you want to leverage things like 'git clean' to simplify the
14 # operation.
15
16
17 # Grab convenience methods & sane default for do_clean
18 inherit clean
19
20 # Build here
21 S = "${FILE_DIRNAME}"
22 SRC_URI = ""
23
24
25 def merge_tasks(d):
26         """
27         merge_tasks performs two operations:
28         1) removes do_patch and its deps from the build entirely.
29         2) merges all of the operations that occur prior to do_populate_staging
30         into do_populate_staging.
31
32         This is necessary, because of recipe variants (normal, native, cross,
33         sdk).  If a bitbake run happens to want to build more than one of
34         these variants in a single run, it's possible for them to step on one
35         another's toes, due to the shared ${S}.  Interleaved
36         configure/compile/install amongst variants will break things badly.
37         """
38         from itertools import chain
39         from bb import note
40
41         def __gather_taskdeps(task, seen):
42                 for dep in d.getVarFlag(task, "deps"):
43                         if not dep in seen:
44                                 __gather_taskdeps(dep, seen)
45                 if not task in seen:
46                         seen.append(task)
47
48         def gather_taskdeps(task):
49                 items = []
50                 __gather_taskdeps(task, items)
51                 return items
52
53         newtask = "do_populate_staging"
54         mergedtasks = gather_taskdeps(newtask)
55         mergedtasks.pop()
56         deltasks = gather_taskdeps("do_patch")
57
58         for task in (key for key in d.keys()
59                      if d.getVarFlag(key, "task") and
60                      not key in mergedtasks):
61                 deps = d.getVarFlag(task, "deps")
62                 for mergetask in mergedtasks:
63                         if mergetask in (d.getVarFlag(task, "recrdeptask"),
64                                          d.getVarFlag(task, "recdeptask"),
65                                          d.getVarFlag(task, "deptask")):
66                                 continue
67
68                         if mergetask in deps:
69                                 deps.remove(mergetask)
70                                 #note("removing dep on %s from %s" % (mergetask, task))
71
72                                 if not mergetask in deltasks and \
73                                    not newtask in deps:
74                                         #note("adding dep on %s to %s" % (newtask, task))
75                                         deps.append(newtask)
76                 d.setVarFlag(task, "deps", deps)
77
78         for task in mergedtasks[:-1]:
79                 deps = d.getVarFlag(task, "deps")
80                 for deltask in deltasks:
81                         if deltask in deps:
82                                 deps.remove(deltask)
83                 d.setVarFlag(task, "deps", deps)
84
85         # Pull cross recipe task deps over
86         depends = (d.getVarFlag(task, "depends") or ""
87                    for task in mergedtasks[:-1]
88                    if not task in deltasks)
89         d.setVarFlag("do_populate_staging", "depends", " ".join(depends))
90
91 python () {
92     merge_tasks(d)
93 }
94
95 # Manually run do_install & all of its deps, then do_stage
96 python do_populate_staging () {
97         from os.path import exists
98         from bb.build import exec_task, exec_func
99         from bb import note
100
101         stamp = d.getVar("STAMP", True)
102
103         def rec_exec_task(task, seen):
104                 for dep in d.getVarFlag(task, "deps"):
105                         if not dep in seen:
106                                 rec_exec_task(dep, seen)
107                 seen.add(task)
108                 #if not exists("%s.%s" % (stamp, task)):
109                 note("%s: executing task %s" % (d.getVar("PF", True), task))
110                 exec_task(task, d)
111
112         rec_exec_task("do_install", set())
113         exec_func("do_stage", d)
114 }
115 do_populate_staging[lockfiles] += "${S}/.lock"