aboutsummaryrefslogtreecommitdiffstats
path: root/classes/srctree.bbclass
blob: dbf8ad2c3fd4a6d3a7850484ab276ba4c7e0d6eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# Copyright (C) 2009 Chris Larson <clarson@kergoth.com>
# Released under the MIT license (see COPYING.MIT for the terms)
#
# srctree.bbclass enables operation inside of an existing source tree for a
# project, rather than using the fetch/unpack/patch idiom.
#
# By default, it expects that you're keeping the recipe(s) inside the
# aforementioned source tree, but you could override S to point at an external
# directory and place the recipes in a normal collection/overlay, if you so
# chose.
#
# It also provides some convenience python functions for assembling your
# do_clean, if you want to leverage things like 'git clean' to simplify the
# operation.


# Grab convenience methods & sane default for do_clean
inherit clean

# Build here
S = "${FILE_DIRNAME}"
SRC_URI = ""


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

	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
	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 () {
    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("%s: executing task %s" % (d.getVar("PF", True), task))
		exec_task(task, d)

	rec_exec_task("do_install", set())
	exec_func("do_stage", d)
}
do_populate_staging[lockfiles] += "${S}/.lock"