diff options
-rw-r--r-- | meta/classes/copyleft_compliance.bbclass | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/meta/classes/copyleft_compliance.bbclass b/meta/classes/copyleft_compliance.bbclass new file mode 100644 index 0000000000..5d9ab11926 --- /dev/null +++ b/meta/classes/copyleft_compliance.bbclass | |||
@@ -0,0 +1,94 @@ | |||
1 | # Deploy sources for recipes for compliance with copyleft-style licenses | ||
2 | # Defaults to using symlinks, as it's a quick operation, and one can easily | ||
3 | # follow the links when making use of the files (e.g. tar with the -h arg). | ||
4 | # | ||
5 | # By default, includes all GPL and LGPL, and excludes CLOSED and Proprietary. | ||
6 | # | ||
7 | # vi:sts=4:sw=4:et | ||
8 | |||
9 | COPYLEFT_SOURCES_DIR ?= '${DEPLOY_DIR}/copyleft_sources' | ||
10 | |||
11 | COPYLEFT_LICENSE_INCLUDE ?= 'GPL* LGPL*' | ||
12 | COPYLEFT_LICENSE_INCLUDE[type] = 'list' | ||
13 | COPYLEFT_LICENSE_INCLUDE[doc] = 'Space separated list of globs which include licenses' | ||
14 | |||
15 | COPYLEFT_LICENSE_EXCLUDE ?= 'CLOSED Proprietary' | ||
16 | COPYLEFT_LICENSE_EXCLUDE[type] = 'list' | ||
17 | COPYLEFT_LICENSE_INCLUDE[doc] = 'Space separated list of globs which exclude licenses' | ||
18 | |||
19 | |||
20 | def copyleft_should_include(d): | ||
21 | """Determine if this recipe's sources should be deployed for compliance""" | ||
22 | import ast | ||
23 | import oe.license | ||
24 | from fnmatch import fnmatchcase as fnmatch | ||
25 | |||
26 | if oe.utils.inherits(d, 'native', 'nativesdk', 'cross', 'crossdk'): | ||
27 | # not a target recipe | ||
28 | return | ||
29 | |||
30 | include = oe.data.typed_value('COPYLEFT_LICENSE_INCLUDE', d) | ||
31 | exclude = oe.data.typed_value('COPYLEFT_LICENSE_EXCLUDE', d) | ||
32 | |||
33 | def include_license(license): | ||
34 | if any(fnmatch(license, pattern) for pattern in exclude): | ||
35 | return False | ||
36 | if any(fnmatch(license, pattern) for pattern in include): | ||
37 | return True | ||
38 | return False | ||
39 | |||
40 | def choose_licenses(a, b): | ||
41 | """Select the left option in an OR if all its licenses are to be included""" | ||
42 | if all(include_license(lic) for lic in a): | ||
43 | return a | ||
44 | else: | ||
45 | return b | ||
46 | |||
47 | try: | ||
48 | licenses = oe.license.flattened_licenses(d.getVar('LICENSE', True), choose_licenses) | ||
49 | except oe.license.InvalidLicense as exc: | ||
50 | bb.fatal('%s: %s' % (d.getVar('PF', True), exc)) | ||
51 | |||
52 | return all(include_license(lic) for lic in licenses) | ||
53 | |||
54 | python do_prepare_copyleft_sources () { | ||
55 | """Populate a tree of the recipe sources and emit patch series files""" | ||
56 | import os.path | ||
57 | import shutil | ||
58 | |||
59 | if not copyleft_should_include(d): | ||
60 | return | ||
61 | |||
62 | sources_dir = d.getVar('COPYLEFT_SOURCES_DIR', 1) | ||
63 | src_uri = d.getVar('SRC_URI', 1).split() | ||
64 | fetch = bb.fetch2.Fetch(src_uri, d) | ||
65 | ud = fetch.ud | ||
66 | |||
67 | locals = (fetch.localpath(url) for url in fetch.urls) | ||
68 | localpaths = [local for local in locals if not local.endswith('.bb')] | ||
69 | if not localpaths: | ||
70 | return | ||
71 | |||
72 | pf = d.getVar('PF', True) | ||
73 | dest = os.path.join(sources_dir, pf) | ||
74 | shutil.rmtree(dest, ignore_errors=True) | ||
75 | bb.mkdirhier(dest) | ||
76 | |||
77 | for path in localpaths: | ||
78 | os.symlink(path, os.path.join(dest, os.path.basename(path))) | ||
79 | |||
80 | patches = src_patches(d) | ||
81 | for patch in patches: | ||
82 | _, _, local, _, _, parm = bb.decodeurl(patch) | ||
83 | patchdir = parm.get('patchdir') | ||
84 | if patchdir: | ||
85 | series = os.path.join(dest, 'series.subdir.%s' % patchdir.replace('/', '_')) | ||
86 | else: | ||
87 | series = os.path.join(dest, 'series') | ||
88 | |||
89 | with open(series, 'a') as s: | ||
90 | s.write('%s -p%s\n' % (os.path.basename(local), parm['striplevel'])) | ||
91 | } | ||
92 | |||
93 | addtask prepare_copyleft_sources after do_fetch before do_build | ||
94 | do_build[recrdeptask] += 'do_prepare_copyleft_sources' | ||