diff options
-rw-r--r-- | meta/classes/archiver.bbclass | 27 | ||||
-rw-r--r-- | meta/classes/copyleft_compliance.bbclass | 56 | ||||
-rw-r--r-- | meta/classes/copyleft_filter.bbclass | 62 |
3 files changed, 88 insertions, 57 deletions
diff --git a/meta/classes/archiver.bbclass b/meta/classes/archiver.bbclass index 7780c71ade..9aa9335b94 100644 --- a/meta/classes/archiver.bbclass +++ b/meta/classes/archiver.bbclass | |||
@@ -12,9 +12,23 @@ | |||
12 | # 5) The environment data, similar to 'bitbake -e recipe': | 12 | # 5) The environment data, similar to 'bitbake -e recipe': |
13 | # ARCHIVER_MODE[dumpdata] = "1" | 13 | # ARCHIVER_MODE[dumpdata] = "1" |
14 | # 6) The recipe (.bb and .inc): ARCHIVER_MODE[recipe] = "1" | 14 | # 6) The recipe (.bb and .inc): ARCHIVER_MODE[recipe] = "1" |
15 | # 7) Whether output the .src.rpm package: | ||
16 | # ARCHIVER_MODE[srpm] = "1" | ||
17 | # 8) Filter the license, the recipe whose license in | ||
18 | # COPYLEFT_LICENSE_INCLUDE will be included, and in | ||
19 | # COPYLEFT_LICENSE_EXCLUDE will be excluded. | ||
20 | # COPYLEFT_LICENSE_INCLUDE = 'GPL* LGPL*' | ||
21 | # COPYLEFT_LICENSE_EXCLUDE = 'CLOSED Proprietary' | ||
22 | # 9) The recipe type that will be archived: | ||
23 | # COPYLEFT_RECIPE_TYPES = 'target' | ||
15 | # | 24 | # |
16 | # All of the above can be packed into a .src.rpm package: (when PACKAGES != "") | 25 | |
17 | # ARCHIVER_MODE[srpm] = "1" | 26 | # Don't filter the license by default |
27 | COPYLEFT_LICENSE_INCLUDE ?= '' | ||
28 | COPYLEFT_LICENSE_EXCLUDE ?= '' | ||
29 | # Create archive for all the recipe types | ||
30 | COPYLEFT_RECIPE_TYPES ?= 'target native nativesdk cross crosssdk cross-canadian' | ||
31 | inherit copyleft_filter | ||
18 | 32 | ||
19 | ARCHIVER_MODE[srpm] ?= "0" | 33 | ARCHIVER_MODE[srpm] ?= "0" |
20 | ARCHIVER_MODE[src] ?= "patched" | 34 | ARCHIVER_MODE[src] ?= "patched" |
@@ -38,6 +52,15 @@ do_ar_original[dirs] = "${ARCHIVER_OUTDIR} ${ARCHIVER_WORKDIR}" | |||
38 | python () { | 52 | python () { |
39 | pn = d.getVar('PN', True) | 53 | pn = d.getVar('PN', True) |
40 | 54 | ||
55 | if d.getVar('COPYLEFT_LICENSE_INCLUDE', True) or \ | ||
56 | d.getVar('COPYLEFT_LICENSE_EXCLUDE', True): | ||
57 | included, reason = copyleft_should_include(d) | ||
58 | if not included: | ||
59 | bb.debug(1, 'archiver: %s is excluded: %s' % (pn, reason)) | ||
60 | return | ||
61 | else: | ||
62 | bb.debug(1, 'archiver: %s is included: %s' % (pn, reason)) | ||
63 | |||
41 | ar_src = d.getVarFlag('ARCHIVER_MODE', 'src', True) | 64 | ar_src = d.getVarFlag('ARCHIVER_MODE', 'src', True) |
42 | ar_dumpdata = d.getVarFlag('ARCHIVER_MODE', 'dumpdata', True) | 65 | ar_dumpdata = d.getVarFlag('ARCHIVER_MODE', 'dumpdata', True) |
43 | ar_recipe = d.getVarFlag('ARCHIVER_MODE', 'recipe', True) | 66 | ar_recipe = d.getVarFlag('ARCHIVER_MODE', 'recipe', True) |
diff --git a/meta/classes/copyleft_compliance.bbclass b/meta/classes/copyleft_compliance.bbclass index b47c2c95ad..907c1836b3 100644 --- a/meta/classes/copyleft_compliance.bbclass +++ b/meta/classes/copyleft_compliance.bbclass | |||
@@ -2,66 +2,12 @@ | |||
2 | # Defaults to using symlinks, as it's a quick operation, and one can easily | 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). | 3 | # follow the links when making use of the files (e.g. tar with the -h arg). |
4 | # | 4 | # |
5 | # By default, includes all GPL and LGPL, and excludes CLOSED and Proprietary. | ||
6 | # | ||
7 | # vi:sts=4:sw=4:et | 5 | # vi:sts=4:sw=4:et |
8 | 6 | ||
9 | COPYLEFT_LICENSE_INCLUDE ?= 'GPL* LGPL*' | 7 | inherit copyleft_filter |
10 | COPYLEFT_LICENSE_INCLUDE[type] = 'list' | ||
11 | COPYLEFT_LICENSE_INCLUDE[doc] = 'Space separated list of globs which include licenses' | ||
12 | |||
13 | COPYLEFT_LICENSE_EXCLUDE ?= 'CLOSED Proprietary' | ||
14 | COPYLEFT_LICENSE_EXCLUDE[type] = 'list' | ||
15 | COPYLEFT_LICENSE_EXCLUDE[doc] = 'Space separated list of globs which exclude licenses' | ||
16 | |||
17 | COPYLEFT_RECIPE_TYPE ?= '${@copyleft_recipe_type(d)}' | ||
18 | COPYLEFT_RECIPE_TYPE[doc] = 'The "type" of the current recipe (e.g. target, native, cross)' | ||
19 | |||
20 | COPYLEFT_RECIPE_TYPES ?= 'target' | ||
21 | COPYLEFT_RECIPE_TYPES[type] = 'list' | ||
22 | COPYLEFT_RECIPE_TYPES[doc] = 'Space separated list of recipe types to include' | ||
23 | |||
24 | COPYLEFT_AVAILABLE_RECIPE_TYPES = 'target native nativesdk cross crosssdk cross-canadian' | ||
25 | COPYLEFT_AVAILABLE_RECIPE_TYPES[type] = 'list' | ||
26 | COPYLEFT_AVAILABLE_RECIPE_TYPES[doc] = 'Space separated list of available recipe types' | ||
27 | 8 | ||
28 | COPYLEFT_SOURCES_DIR ?= '${DEPLOY_DIR}/copyleft_sources' | 9 | COPYLEFT_SOURCES_DIR ?= '${DEPLOY_DIR}/copyleft_sources' |
29 | 10 | ||
30 | def copyleft_recipe_type(d): | ||
31 | for recipe_type in oe.data.typed_value('COPYLEFT_AVAILABLE_RECIPE_TYPES', d): | ||
32 | if oe.utils.inherits(d, recipe_type): | ||
33 | return recipe_type | ||
34 | return 'target' | ||
35 | |||
36 | def copyleft_should_include(d): | ||
37 | """ | ||
38 | Determine if this recipe's sources should be deployed for compliance | ||
39 | """ | ||
40 | import ast | ||
41 | import oe.license | ||
42 | from fnmatch import fnmatchcase as fnmatch | ||
43 | |||
44 | recipe_type = d.getVar('COPYLEFT_RECIPE_TYPE', True) | ||
45 | if recipe_type not in oe.data.typed_value('COPYLEFT_RECIPE_TYPES', d): | ||
46 | return False, 'recipe type "%s" is excluded' % recipe_type | ||
47 | |||
48 | include = oe.data.typed_value('COPYLEFT_LICENSE_INCLUDE', d) | ||
49 | exclude = oe.data.typed_value('COPYLEFT_LICENSE_EXCLUDE', d) | ||
50 | |||
51 | try: | ||
52 | is_included, reason = oe.license.is_included(d.getVar('LICENSE', True), include, exclude) | ||
53 | except oe.license.LicenseError as exc: | ||
54 | bb.fatal('%s: %s' % (d.getVar('PF', True), exc)) | ||
55 | else: | ||
56 | if is_included: | ||
57 | if reason: | ||
58 | return True, 'recipe has included licenses: %s' % ', '.join(reason) | ||
59 | else: | ||
60 | return False, 'recipe does not include a copyleft license' | ||
61 | else: | ||
62 | return False, 'recipe has excluded licenses: %s' % ', '.join(reason) | ||
63 | |||
64 | |||
65 | python do_prepare_copyleft_sources () { | 11 | python do_prepare_copyleft_sources () { |
66 | """Populate a tree of the recipe sources and emit patch series files""" | 12 | """Populate a tree of the recipe sources and emit patch series files""" |
67 | import os.path | 13 | import os.path |
diff --git a/meta/classes/copyleft_filter.bbclass b/meta/classes/copyleft_filter.bbclass new file mode 100644 index 0000000000..2c1d8f1c90 --- /dev/null +++ b/meta/classes/copyleft_filter.bbclass | |||
@@ -0,0 +1,62 @@ | |||
1 | # Filter the license, the copyleft_should_include returns True for the | ||
2 | # COPYLEFT_LICENSE_INCLUDE recipe, and False for the | ||
3 | # COPYLEFT_LICENSE_EXCLUDE. | ||
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_LICENSE_INCLUDE ?= 'GPL* LGPL*' | ||
10 | COPYLEFT_LICENSE_INCLUDE[type] = 'list' | ||
11 | COPYLEFT_LICENSE_INCLUDE[doc] = 'Space separated list of globs which include licenses' | ||
12 | |||
13 | COPYLEFT_LICENSE_EXCLUDE ?= 'CLOSED Proprietary' | ||
14 | COPYLEFT_LICENSE_EXCLUDE[type] = 'list' | ||
15 | COPYLEFT_LICENSE_EXCLUDE[doc] = 'Space separated list of globs which exclude licenses' | ||
16 | |||
17 | COPYLEFT_RECIPE_TYPE ?= '${@copyleft_recipe_type(d)}' | ||
18 | COPYLEFT_RECIPE_TYPE[doc] = 'The "type" of the current recipe (e.g. target, native, cross)' | ||
19 | |||
20 | COPYLEFT_RECIPE_TYPES ?= 'target' | ||
21 | COPYLEFT_RECIPE_TYPES[type] = 'list' | ||
22 | COPYLEFT_RECIPE_TYPES[doc] = 'Space separated list of recipe types to include' | ||
23 | |||
24 | COPYLEFT_AVAILABLE_RECIPE_TYPES = 'target native nativesdk cross crosssdk cross-canadian' | ||
25 | COPYLEFT_AVAILABLE_RECIPE_TYPES[type] = 'list' | ||
26 | COPYLEFT_AVAILABLE_RECIPE_TYPES[doc] = 'Space separated list of available recipe types' | ||
27 | |||
28 | def copyleft_recipe_type(d): | ||
29 | for recipe_type in oe.data.typed_value('COPYLEFT_AVAILABLE_RECIPE_TYPES', d): | ||
30 | if oe.utils.inherits(d, recipe_type): | ||
31 | return recipe_type | ||
32 | return 'target' | ||
33 | |||
34 | def copyleft_should_include(d): | ||
35 | """ | ||
36 | Determine if this recipe's sources should be deployed for compliance | ||
37 | """ | ||
38 | import ast | ||
39 | import oe.license | ||
40 | from fnmatch import fnmatchcase as fnmatch | ||
41 | |||
42 | recipe_type = d.getVar('COPYLEFT_RECIPE_TYPE', True) | ||
43 | if recipe_type not in oe.data.typed_value('COPYLEFT_RECIPE_TYPES', d): | ||
44 | return False, 'recipe type "%s" is excluded' % recipe_type | ||
45 | |||
46 | include = oe.data.typed_value('COPYLEFT_LICENSE_INCLUDE', d) | ||
47 | exclude = oe.data.typed_value('COPYLEFT_LICENSE_EXCLUDE', d) | ||
48 | |||
49 | try: | ||
50 | is_included, reason = oe.license.is_included(d.getVar('LICENSE', True), include, exclude) | ||
51 | except oe.license.LicenseError as exc: | ||
52 | bb.fatal('%s: %s' % (d.getVar('PF', True), exc)) | ||
53 | else: | ||
54 | if is_included: | ||
55 | if reason: | ||
56 | return True, 'recipe has included licenses: %s' % ', '.join(reason) | ||
57 | else: | ||
58 | return False, 'recipe does not include a copyleft license' | ||
59 | else: | ||
60 | return False, 'recipe has excluded licenses: %s' % ', '.join(reason) | ||
61 | |||
62 | |||