diff options
Diffstat (limited to 'meta/classes')
-rw-r--r-- | meta/classes/license.bbclass | 152 |
1 files changed, 114 insertions, 38 deletions
diff --git a/meta/classes/license.bbclass b/meta/classes/license.bbclass index 4fd1f85130..a4d34e7c02 100644 --- a/meta/classes/license.bbclass +++ b/meta/classes/license.bbclass | |||
@@ -14,6 +14,42 @@ LICSSTATEDIR = "${WORKDIR}/license-destdir/" | |||
14 | addtask populate_lic after do_patch before do_package | 14 | addtask populate_lic after do_patch before do_package |
15 | do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}" | 15 | do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}" |
16 | do_populate_lic[cleandirs] = "${LICSSTATEDIR}" | 16 | do_populate_lic[cleandirs] = "${LICSSTATEDIR}" |
17 | |||
18 | # Standards are great! Everyone has their own. In an effort to standardize licensing | ||
19 | # names, common-licenses will use the SPDX standard license names. In order to not | ||
20 | # break the non-standardized license names that we find in LICENSE, we'll set | ||
21 | # up a bunch of VarFlags to accomodate non-SPDX license names. | ||
22 | # | ||
23 | # We should really discuss standardizing this field, but that's a longer term goal. | ||
24 | # For now, we can do this and it should grab the most common LICENSE naming variations. | ||
25 | # | ||
26 | #GPL variations | ||
27 | SPDXLICENSEMAP[GPL] = "GPL-1" | ||
28 | SPDXLICENSEMAP[GPLv2] = "GPL-2" | ||
29 | SPDXLICENSEMAP[GPLv3] = "GPL-3" | ||
30 | |||
31 | #LGPL variations | ||
32 | SPDXLICENSEMAP[LGPL] = "LGPL-2" | ||
33 | SPDXLICENSEMAP[LGPLv2] = "LGPL-2" | ||
34 | SPDXLICENSEMAP[LGPL2.1] = "LGPL-2.1" | ||
35 | SPDXLICENSEMAP[LGPLv2.1] = "LGPL-2.1" | ||
36 | SPDXLICENSEMAP[LGPLv3] = "LGPL-3" | ||
37 | |||
38 | #MPL variations | ||
39 | SPDXLICENSEMAP[MPL] = "MPL-1" | ||
40 | SPDXLICENSEMAP[MPLv1] = "MPL-1" | ||
41 | SPDXLICENSEMAP[MPLv1.1] = "MPL-1" | ||
42 | |||
43 | #MIT variations | ||
44 | SPDXLICENSEMAP[MIT-X] = "MIT" | ||
45 | |||
46 | #Openssl variations | ||
47 | SPDXLICENSEMAP[openssl] = "Openssl" | ||
48 | |||
49 | #Other variations | ||
50 | SPDXLICENSEMAP[AFL2.1] = "AFL-2" | ||
51 | SPDXLICENSEMAP[EPLv1.0] = "EPL-1" | ||
52 | |||
17 | python do_populate_lic() { | 53 | python do_populate_lic() { |
18 | """ | 54 | """ |
19 | Populate LICENSE_DIRECTORY with licenses. | 55 | Populate LICENSE_DIRECTORY with licenses. |
@@ -21,6 +57,68 @@ python do_populate_lic() { | |||
21 | import os | 57 | import os |
22 | import bb | 58 | import bb |
23 | import shutil | 59 | import shutil |
60 | import ast | ||
61 | |||
62 | class LicenseVisitor(ast.NodeVisitor): | ||
63 | def generic_visit(self, node): | ||
64 | ast.NodeVisitor.generic_visit(self, node) | ||
65 | |||
66 | def visit_Str(self, node): | ||
67 | # | ||
68 | # Until I figure out what to do with | ||
69 | # the two modifiers I support (or greater = + | ||
70 | # and "with exceptions" being * | ||
71 | # we'll just strip out the modifier and put | ||
72 | # the base license. | ||
73 | find_license(node.s.replace("+", "").replace("*", "")) | ||
74 | ast.NodeVisitor.generic_visit(self, node) | ||
75 | |||
76 | def visit_BinOp(self, node): | ||
77 | op = node.op | ||
78 | if isinstance(op, ast.BitOr): | ||
79 | x = LicenseVisitor() | ||
80 | x.visit(node) | ||
81 | else: | ||
82 | ast.NodeVisitor.generic_visit(self, node) | ||
83 | |||
84 | def copy_license(source, destination, file_name): | ||
85 | try: | ||
86 | bb.copyfile(os.path.join(source, file_name), os.path.join(destination, file_name)) | ||
87 | except: | ||
88 | bb.warn("%s: No generic license file exists for: %s at %s" % (pn, file_name, source)) | ||
89 | pass | ||
90 | |||
91 | def link_license(source, destination, file_name): | ||
92 | try: | ||
93 | os.symlink(os.path.join(source, file_name), os.path.join(destination, "generic_" + file_name)) | ||
94 | except: | ||
95 | bb.warn("%s: Could not symlink: %s at %s to %s at %s" % (pn, file_name, source, file_name, destination)) | ||
96 | pass | ||
97 | |||
98 | def find_license(license_type): | ||
99 | |||
100 | try: | ||
101 | bb.mkdirhier(gen_lic_dest) | ||
102 | except: | ||
103 | pass | ||
104 | |||
105 | # If the generic does not exist we need to check to see if there is an SPDX mapping to it | ||
106 | if not os.path.isfile(os.path.join(generic_directory, license_type)): | ||
107 | if bb.data.getVarFlag('SPDXLICENSEMAP', license_type, d) != None: | ||
108 | # Great, there is an SPDXLICENSEMAP. We can copy! | ||
109 | bb.warn("We need to use a SPDXLICENSEMAP for %s" % (license_type)) | ||
110 | spdx_generic = bb.data.getVarFlag('SPDXLICENSEMAP', license_type, d) | ||
111 | copy_license(generic_directory, gen_lic_dest, spdx_generic) | ||
112 | link_license(gen_lic_dest, destdir, spdx_generic) | ||
113 | else: | ||
114 | # And here is where we warn people that their licenses are lousy | ||
115 | bb.warn("%s: No generic license file exists for: %s at %s" % (pn, license_type, generic_directory)) | ||
116 | bb.warn("%s: There is also no SPDXLICENSEMAP for this license type: %s at %s" % (pn, license_type, generic_directory)) | ||
117 | pass | ||
118 | elif os.path.isfile(os.path.join(generic_directory, license_type)): | ||
119 | copy_license(generic_directory, gen_lic_dest, license_type) | ||
120 | link_license(gen_lic_dest, destdir, license_type) | ||
121 | |||
24 | 122 | ||
25 | # All the license types for the package | 123 | # All the license types for the package |
26 | license_types = bb.data.getVar('LICENSE', d, True) | 124 | license_types = bb.data.getVar('LICENSE', d, True) |
@@ -33,6 +131,12 @@ python do_populate_lic() { | |||
33 | srcdir = bb.data.getVar('S', d, True) | 131 | srcdir = bb.data.getVar('S', d, True) |
34 | # Directory we store the generic licenses as set in the distro configuration | 132 | # Directory we store the generic licenses as set in the distro configuration |
35 | generic_directory = bb.data.getVar('COMMON_LICENSE_DIR', d, True) | 133 | generic_directory = bb.data.getVar('COMMON_LICENSE_DIR', d, True) |
134 | bb.warn(generic_directory) | ||
135 | try: | ||
136 | bb.mkdirhier(destdir) | ||
137 | except: | ||
138 | pass | ||
139 | |||
36 | if not generic_directory: | 140 | if not generic_directory: |
37 | raise bb.build.FuncFailed("COMMON_LICENSE_DIR is unset. Please set this in your distro config") | 141 | raise bb.build.FuncFailed("COMMON_LICENSE_DIR is unset. Please set this in your distro config") |
38 | 142 | ||
@@ -51,45 +155,18 @@ python do_populate_lic() { | |||
51 | if ret is False or ret == 0: | 155 | if ret is False or ret == 0: |
52 | bb.warn("%s could not be copied for some reason. It may not exist. WARN for now." % srclicfile) | 156 | bb.warn("%s could not be copied for some reason. It may not exist. WARN for now." % srclicfile) |
53 | 157 | ||
54 | # This takes some explaining.... we now are going to go an try to symlink | 158 | gen_lic_dest = os.path.join(bb.data.getVar('LICENSE_DIRECTORY', d, True), "common-licenses") |
55 | # to a generic file. But, with the way LICENSE works, a package can have multiple | ||
56 | # licenses. Some of them are, for example, GPLv2+, which means it can use that version | ||
57 | # of GPLv2 specified in it's license, or a later version of GPLv2. For the purposes of | ||
58 | # what we're doing here, we really don't track license revisions (although we may want to) | ||
59 | # So, we strip out the + and link to a generic GPLv2 | ||
60 | # | ||
61 | # That said, there are some entries into LICENSE that either have no generic (bzip, zlib, ICS) | ||
62 | # or the LICENSE is messy (Apache 2.0 .... when they mean Apache-2.0). This should be corrected | ||
63 | # but it's outside of scope for this. | ||
64 | # | ||
65 | # Also, you get some clever license fields with logic in the field. | ||
66 | # I'm sure someone has written a logic parser for these fields, but if so, I don't know where it is. | ||
67 | # So what I do is just link to every license mentioned in the license field. | ||
68 | 159 | ||
69 | for license_type in ((license_types.replace('+', '').replace('|', '&') | 160 | clean_licenses = "" |
70 | .replace('(', '').replace(')', '').replace(';', '') | 161 | for x in license_types.replace("(", " ( ").replace(")", " ) ").split(): |
71 | .replace(',', '').replace(" ", "").split("&"))): | 162 | if ((x != "(") and (x != ")") and (x != "&") and (x != "|")): |
72 | if os.path.isfile(os.path.join(generic_directory, license_type)): | 163 | clean_licenses += "'" + x + "'" |
73 | gen_lic_dest = os.path.join(bb.data.getVar('LICENSE_DIRECTORY', d, True), "common-licenses") | ||
74 | try: | ||
75 | bb.mkdirhier(gen_lic_dest) | ||
76 | except: | ||
77 | pass | ||
78 | |||
79 | try: | ||
80 | bb.copyfile(os.path.join(generic_directory, license_type), os.path.join(gen_lic_dest, license_type)) | ||
81 | except: | ||
82 | bb.warn("%s: No generic license file exists for: %s at %s" % (pn, license_type, generic_directory)) | ||
83 | pass | ||
84 | try: | ||
85 | os.symlink(os.path.join(gen_lic_dest, license_type), os.path.join(destdir, "generic_" + license_type)) | ||
86 | except: | ||
87 | bb.warn("%s: No generic license file exists for: %s at %s" % (pn, license_type, generic_directory)) | ||
88 | pass | ||
89 | else: | 164 | else: |
90 | bb.warn("%s: Something went wrong with copying: %s to %s" % (pn, license_type, generic_directory)) | 165 | clean_licenses += " " + x + " " |
91 | bb.warn("This could be either because we do not have a generic for this license or the LICENSE field is incorrect") | 166 | |
92 | pass | 167 | node = ast.parse(clean_licenses) |
168 | v = LicenseVisitor() | ||
169 | v.visit(node) | ||
93 | } | 170 | } |
94 | 171 | ||
95 | SSTATETASKS += "do_populate_lic" | 172 | SSTATETASKS += "do_populate_lic" |
@@ -102,4 +179,3 @@ python do_populate_lic_setscene () { | |||
102 | } | 179 | } |
103 | addtask do_populate_lic_setscene | 180 | addtask do_populate_lic_setscene |
104 | 181 | ||
105 | |||