diff options
Diffstat (limited to 'meta/classes')
-rw-r--r-- | meta/classes/license.bbclass | 219 |
1 files changed, 153 insertions, 66 deletions
diff --git a/meta/classes/license.bbclass b/meta/classes/license.bbclass index 8c6e2d2c9b..8c64e4cd8a 100644 --- a/meta/classes/license.bbclass +++ b/meta/classes/license.bbclass | |||
@@ -1,17 +1,12 @@ | |||
1 | # Populates LICENSE_DIRECTORY as set in distro config with the license files as set by | 1 | # Populates LICENSE_DIRECTORY as set in distro config with the license files as set by |
2 | # LIC_FILES_CHKSUM. | 2 | # LIC_FILES_CHKSUM. |
3 | # TODO: | 3 | # TODO: |
4 | # - We should also enable the ability to put the generated license directory onto the | 4 | # - There is a real issue revolving around license naming standards. |
5 | # rootfs | ||
6 | # - Gather up more generic licenses | ||
7 | # - There is a real issue revolving around license naming standards. See license names | ||
8 | # licenses.conf and compare them to the license names in the recipes. You'll see some | ||
9 | # differences and that should be corrected. | ||
10 | 5 | ||
11 | LICENSE_DIRECTORY ??= "${DEPLOY_DIR}/licenses" | 6 | LICENSE_DIRECTORY ??= "${DEPLOY_DIR}/licenses" |
12 | LICSSTATEDIR = "${WORKDIR}/license-destdir/" | 7 | LICSSTATEDIR = "${WORKDIR}/license-destdir/" |
13 | 8 | ||
14 | addtask populate_lic after do_patch before do_package | 9 | addtask populate_lic after do_patch before do_compile |
15 | do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}" | 10 | do_populate_lic[dirs] = "${LICSSTATEDIR}/${PN}" |
16 | do_populate_lic[cleandirs] = "${LICSSTATEDIR}" | 11 | do_populate_lic[cleandirs] = "${LICSSTATEDIR}" |
17 | 12 | ||
@@ -22,33 +17,122 @@ do_populate_lic[cleandirs] = "${LICSSTATEDIR}" | |||
22 | # | 17 | # |
23 | # We should really discuss standardizing this field, but that's a longer term goal. | 18 | # 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. | 19 | # For now, we can do this and it should grab the most common LICENSE naming variations. |
25 | 20 | # | |
26 | #GPL variations | 21 | # Changing GPL mapping to GPL-2 as it's not very likely to be GPL-1 |
27 | SPDXLICENSEMAP[GPL] = "GPL-1" | 22 | # We should NEVER have a GPL/LGPL without a version!!!! |
28 | SPDXLICENSEMAP[GPLv2] = "GPL-2" | 23 | # Any mapping to MPL/LGPL/GPL should be fixed |
29 | SPDXLICENSEMAP[GPLv3] = "GPL-3" | 24 | # see: https://wiki.yoctoproject.org/wiki/License_Audit |
25 | |||
26 | # GPL variations | ||
27 | SPDXLICENSEMAP[GPL-2] = "GPL-2.0" | ||
28 | SPDXLICENSEMAP[GPLv2] = "GPL-2.0" | ||
29 | SPDXLICENSEMAP[GPLv2.0] = "GPL-2.0" | ||
30 | SPDXLICENSEMAP[GPL-3] = "GPL-3.0" | ||
31 | SPDXLICENSEMAP[GPLv3] = "GPL-3.0" | ||
32 | SPDXLICENSEMAP[GPLv3.0] = "GPL-3.0" | ||
30 | 33 | ||
31 | #LGPL variations | 34 | #LGPL variations |
32 | SPDXLICENSEMAP[LGPL] = "LGPL-2" | 35 | SPDXLICENSEMAP[LGPLv2] = "LGPL-2.0" |
33 | SPDXLICENSEMAP[LGPLv2] = "LGPL-2" | ||
34 | SPDXLICENSEMAP[LGPL2.1] = "LGPL-2.1" | 36 | SPDXLICENSEMAP[LGPL2.1] = "LGPL-2.1" |
35 | SPDXLICENSEMAP[LGPLv2.1] = "LGPL-2.1" | 37 | SPDXLICENSEMAP[LGPLv2.1] = "LGPL-2.1" |
36 | SPDXLICENSEMAP[LGPLv3] = "LGPL-3" | 38 | SPDXLICENSEMAP[LGPLv3] = "LGPL-3.0" |
37 | 39 | ||
38 | #MPL variations | 40 | #MPL variations |
39 | SPDXLICENSEMAP[MPL] = "MPL-1" | 41 | SPDXLICENSEMAP[MPL-1] = "MPL-1.0" |
40 | SPDXLICENSEMAP[MPLv1] = "MPL-1" | 42 | SPDXLICENSEMAP[MPLv1] = "MPL-1.0" |
41 | SPDXLICENSEMAP[MPLv1.1] = "MPL-1" | 43 | SPDXLICENSEMAP[MPLv1.1] = "MPL-1.1" |
42 | 44 | ||
43 | #MIT variations | 45 | #MIT variations |
44 | SPDXLICENSEMAP[MIT-X] = "MIT" | 46 | SPDXLICENSEMAP[MIT-X] = "MIT" |
47 | SPDXLICENSEMAP[MIT-style] = "MIT" | ||
45 | 48 | ||
46 | #Openssl variations | 49 | #Openssl variations |
47 | SPDXLICENSEMAP[openssl] = "OpenSSL" | 50 | SPDXLICENSEMAP[openssl] = "OpenSSL" |
48 | 51 | ||
52 | #Python variations | ||
53 | SPDXLICENSEMAP[PSF] = "Python-2.0" | ||
54 | SPDXLICENSEMAP[PSFv2] = "Python-2.0" | ||
55 | SPDXLICENSEMAP[Python-2] = "Python-2.0" | ||
56 | |||
57 | #Apache variations | ||
58 | SPDXLICENSEMAP[Apachev2] = "Apache-2.0" | ||
59 | SPDXLICENSEMAP[Apache-2] = "Apache-2.0" | ||
60 | |||
61 | #Artistic variations | ||
62 | SPDXLICENSEMAP[Artisticv1] = "Artistic-1.0" | ||
63 | SPDXLICENSEMAP[Artistic-1] = "Artistic-1.0" | ||
64 | |||
65 | #Academic variations | ||
66 | SPDXLICENSEMAP[AFL-2] = "AFL-2.0" | ||
67 | SPDXLICENSEMAP[AFL-1] = "AFL-1.2" | ||
68 | SPDXLICENSEMAP[AFLv2] = "AFL-2.0" | ||
69 | SPDXLICENSEMAP[AFLv1] = "AFL-1.2" | ||
70 | |||
49 | #Other variations | 71 | #Other variations |
50 | SPDXLICENSEMAP[AFL2.1] = "AFL-2" | 72 | SPDXLICENSEMAP[EPLv1.0] = "EPL-1.0" |
51 | SPDXLICENSEMAP[EPLv1.0] = "EPL-1" | 73 | |
74 | license_create_manifest() { | ||
75 | mkdir -p ${LICENSE_DIRECTORY}/${IMAGE_NAME} | ||
76 | # Get list of installed packages | ||
77 | list_installed_packages | grep -v "locale" |sort > ${LICENSE_DIRECTORY}/${IMAGE_NAME}/package.manifest | ||
78 | INSTALLED_PKGS=`cat ${LICENSE_DIRECTORY}/${IMAGE_NAME}/package.manifest` | ||
79 | # list of installed packages is broken for deb | ||
80 | if [ ${IMAGE_PKGTYPE} != "deb" ]; then | ||
81 | |||
82 | for pkg in ${INSTALLED_PKGS}; do | ||
83 | # not the best way to do this but licenses are not arch dependant iirc | ||
84 | files=`find ${TMPDIR}/pkgdata/*/runtime -name ${pkg}| head -1` | ||
85 | for filename in $files; do | ||
86 | pkged_pn="$(sed -n 's/^PN: //p' ${filename})" | ||
87 | pkged_lic="$(sed -n '/^LICENSE: /{ s/^LICENSE: //; s/[+|&()*]/ /g; s/ */ /g; p }' ${filename})" | ||
88 | # check to see if the package name exists in the manifest. if so, bail. | ||
89 | if ! grep -q "PACKAGE NAME: ${pkg}" ${filename}; then | ||
90 | # exclude local recipes | ||
91 | if [ ! ${pkged_pn} == "*locale*" ]; then | ||
92 | echo "PACKAGE NAME:" ${pkg} >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest | ||
93 | echo "RECIPE NAME:" ${pkged_pn} >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest | ||
94 | echo "LICENSE: " >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest | ||
95 | for lic in ${pkged_lic}; do | ||
96 | if [ -e "${LICENSE_DIRECTORY}/${pkged_pn}/generic_${lic}" ]; then | ||
97 | echo ${lic}|sed s'/generic_//'g >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest | ||
98 | else | ||
99 | echo "WARNING: The license listed, " ${lic} " was not in the licenses collected for " ${pkged_pn}>> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest | ||
100 | fi | ||
101 | done | ||
102 | echo "" >> ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest | ||
103 | fi | ||
104 | fi | ||
105 | done | ||
106 | done | ||
107 | fi | ||
108 | |||
109 | # Two options here: | ||
110 | # - Just copy the manifest | ||
111 | # - Copy the manifest and the license directories | ||
112 | # This will make your image a bit larger, however | ||
113 | # if you are concerned about license compliance | ||
114 | # and delivery this should cover all your bases | ||
115 | |||
116 | if [ -n ${COPY_LIC_MANIFEST} ]; then | ||
117 | mkdir -p ${IMAGE_ROOTFS}/usr/share/common-licenses/ | ||
118 | cp ${LICENSE_DIRECTORY}/${IMAGE_NAME}/license.manifest ${IMAGE_ROOTFS}/usr/share/common-licenses/license.manifest | ||
119 | if [ -n ${COPY_LIC_DIRS} ]; then | ||
120 | for pkg in ${INSTALLED_PKGS}; do | ||
121 | mkdir -p ${IMAGE_ROOTFS}/usr/share/common-licenses/${pkg} | ||
122 | for lic in `ls ${LICENSE_DIRECTORY}/${pkged_pn}`; do | ||
123 | # Really don't need to copy the generics as they're | ||
124 | # represented in the manifest and in the actual pkg licenses | ||
125 | # Doing so would make your image quite a bit larger | ||
126 | if [ ! ${lic} == "generic_*" ]; then | ||
127 | cp ${LICENSE_DIRECTORY}/${pkged_pn}/${lic} ${IMAGE_ROOTFS}/usr/share/common-licenses/${pkg}/${lic} | ||
128 | fi | ||
129 | done | ||
130 | done | ||
131 | fi | ||
132 | fi | ||
133 | |||
134 | } | ||
135 | |||
52 | 136 | ||
53 | python do_populate_lic() { | 137 | python do_populate_lic() { |
54 | """ | 138 | """ |
@@ -59,6 +143,26 @@ python do_populate_lic() { | |||
59 | import shutil | 143 | import shutil |
60 | import oe.license | 144 | import oe.license |
61 | 145 | ||
146 | # All the license types for the package | ||
147 | license_types = d.getVar('LICENSE', True) | ||
148 | # All the license files for the package | ||
149 | lic_files = d.getVar('LIC_FILES_CHKSUM', True) | ||
150 | pn = d.getVar('PN', True) | ||
151 | # The base directory we wrangle licenses to | ||
152 | destdir = os.path.join(d.getVar('LICSSTATEDIR', True), pn) | ||
153 | # The license files are located in S/LIC_FILE_CHECKSUM. | ||
154 | srcdir = d.getVar('S', True) | ||
155 | # Directory we store the generic licenses as set in the distro configuration | ||
156 | generic_directory = d.getVar('COMMON_LICENSE_DIR', True) | ||
157 | license_source_dirs = [] | ||
158 | license_source_dirs.append(generic_directory) | ||
159 | try: | ||
160 | additional_lic_dirs = d.getVar('LICENSE_DIR', True).split() | ||
161 | for lic_dir in additional_lic_dirs: | ||
162 | license_source_dirs.append(lic_dir) | ||
163 | except: | ||
164 | pass | ||
165 | |||
62 | class FindVisitor(oe.license.LicenseVisitor): | 166 | class FindVisitor(oe.license.LicenseVisitor): |
63 | def visit_Str(self, node): | 167 | def visit_Str(self, node): |
64 | # | 168 | # |
@@ -70,54 +174,38 @@ python do_populate_lic() { | |||
70 | find_license(node.s.replace("+", "").replace("*", "")) | 174 | find_license(node.s.replace("+", "").replace("*", "")) |
71 | self.generic_visit(node) | 175 | self.generic_visit(node) |
72 | 176 | ||
73 | def copy_license(source, destination, file_name): | ||
74 | try: | ||
75 | bb.copyfile(os.path.join(source, file_name), os.path.join(destination, file_name)) | ||
76 | except: | ||
77 | bb.warn("%s: No generic license file exists for: %s at %s" % (pn, file_name, source)) | ||
78 | pass | ||
79 | |||
80 | def link_license(source, destination, file_name): | ||
81 | try: | ||
82 | os.symlink(os.path.join(source, file_name), os.path.join(destination, "generic_" + file_name)) | ||
83 | except: | ||
84 | bb.warn("%s: Could not symlink: %s at %s to %s at %s" % (pn, file_name, source, file_name, destination)) | ||
85 | pass | ||
86 | |||
87 | def find_license(license_type): | 177 | def find_license(license_type): |
88 | try: | 178 | try: |
89 | bb.mkdirhier(gen_lic_dest) | 179 | bb.mkdirhier(gen_lic_dest) |
90 | except: | 180 | except: |
91 | pass | 181 | pass |
92 | 182 | spdx_generic = None | |
183 | license_source = None | ||
93 | # If the generic does not exist we need to check to see if there is an SPDX mapping to it | 184 | # If the generic does not exist we need to check to see if there is an SPDX mapping to it |
94 | if not os.path.isfile(os.path.join(generic_directory, license_type)): | 185 | for lic_dir in license_source_dirs: |
95 | if d.getVarFlag('SPDXLICENSEMAP', license_type) != None: | 186 | if not os.path.isfile(os.path.join(lic_dir, license_type)): |
96 | # Great, there is an SPDXLICENSEMAP. We can copy! | 187 | if d.getVarFlag('SPDXLICENSEMAP', license_type) != None: |
97 | bb.note("We need to use a SPDXLICENSEMAP for %s" % (license_type)) | 188 | # Great, there is an SPDXLICENSEMAP. We can copy! |
98 | spdx_generic = d.getVarFlag('SPDXLICENSEMAP', license_type) | 189 | bb.debug(1, "We need to use a SPDXLICENSEMAP for %s" % (license_type)) |
99 | copy_license(generic_directory, gen_lic_dest, spdx_generic) | 190 | spdx_generic = d.getVarFlag('SPDXLICENSEMAP', license_type) |
100 | link_license(gen_lic_dest, destdir, spdx_generic) | 191 | license_source = lic_dir |
101 | else: | 192 | break |
102 | # And here is where we warn people that their licenses are lousy | 193 | elif os.path.isfile(os.path.join(lic_dir, license_type)): |
103 | bb.warn("%s: No generic license file exists for: %s at %s" % (pn, license_type, generic_directory)) | 194 | spdx_generic = license_type |
104 | bb.warn("%s: There is also no SPDXLICENSEMAP for this license type: %s at %s" % (pn, license_type, generic_directory)) | 195 | license_source = lic_dir |
105 | pass | 196 | break |
106 | elif os.path.isfile(os.path.join(generic_directory, license_type)): | 197 | |
107 | copy_license(generic_directory, gen_lic_dest, license_type) | 198 | if spdx_generic and license_source: |
108 | link_license(gen_lic_dest, destdir, license_type) | 199 | # we really should copy to generic_ + spdx_generic, however, that ends up messing the manifest |
109 | 200 | # audit up. This should be fixed in emit_pkgdata (or, we actually got and fix all the recipes) | |
110 | # All the license types for the package | 201 | ret = bb.copyfile(os.path.join(license_source, spdx_generic), os.path.join(os.path.join(d.getVar('LICSSTATEDIR', True), pn), "generic_" + license_type)) |
111 | license_types = d.getVar('LICENSE', True) | 202 | # If the copy didn't occur, something horrible went wrong and we fail out |
112 | # All the license files for the package | 203 | if not ret: |
113 | lic_files = d.getVar('LIC_FILES_CHKSUM', True) | 204 | bb.warn("%s for %s could not be copied for some reason. It may not exist. WARN for now." % (spdx_generic, pn)) |
114 | pn = d.getVar('PN', True) | 205 | else: |
115 | # The base directory we wrangle licenses to | 206 | # And here is where we warn people that their licenses are lousy |
116 | destdir = os.path.join(d.getVar('LICSSTATEDIR', True), pn) | 207 | bb.warn("%s: No generic license file exists for: %s in any provider" % (pn, license_type)) |
117 | # The license files are located in S/LIC_FILE_CHECKSUM. | 208 | pass |
118 | srcdir = d.getVar('S', True) | ||
119 | # Directory we store the generic licenses as set in the distro configuration | ||
120 | generic_directory = d.getVar('COMMON_LICENSE_DIR', True) | ||
121 | 209 | ||
122 | try: | 210 | try: |
123 | bb.mkdirhier(destdir) | 211 | bb.mkdirhier(destdir) |
@@ -139,11 +227,9 @@ python do_populate_lic() { | |||
139 | srclicfile = os.path.join(srcdir, path) | 227 | srclicfile = os.path.join(srcdir, path) |
140 | ret = bb.copyfile(srclicfile, os.path.join(destdir, os.path.basename(path))) | 228 | ret = bb.copyfile(srclicfile, os.path.join(destdir, os.path.basename(path))) |
141 | # If the copy didn't occur, something horrible went wrong and we fail out | 229 | # If the copy didn't occur, something horrible went wrong and we fail out |
142 | if ret is False or ret == 0: | 230 | if not ret: |
143 | bb.warn("%s could not be copied for some reason. It may not exist. WARN for now." % srclicfile) | 231 | bb.warn("%s could not be copied for some reason. It may not exist. WARN for now." % srclicfile) |
144 | 232 | ||
145 | gen_lic_dest = os.path.join(d.getVar('LICENSE_DIRECTORY', True), "common-licenses") | ||
146 | |||
147 | v = FindVisitor() | 233 | v = FindVisitor() |
148 | try: | 234 | try: |
149 | v.visit_string(license_types) | 235 | v.visit_string(license_types) |
@@ -156,8 +242,9 @@ do_populate_lic[sstate-name] = "populate-lic" | |||
156 | do_populate_lic[sstate-inputdirs] = "${LICSSTATEDIR}" | 242 | do_populate_lic[sstate-inputdirs] = "${LICSSTATEDIR}" |
157 | do_populate_lic[sstate-outputdirs] = "${LICENSE_DIRECTORY}/" | 243 | do_populate_lic[sstate-outputdirs] = "${LICENSE_DIRECTORY}/" |
158 | 244 | ||
245 | ROOTFS_POSTINSTALL_COMMAND += "license_create_manifest; " | ||
246 | |||
159 | python do_populate_lic_setscene () { | 247 | python do_populate_lic_setscene () { |
160 | sstate_setscene(d) | 248 | sstate_setscene(d) |
161 | } | 249 | } |
162 | addtask do_populate_lic_setscene | 250 | addtask do_populate_lic_setscene |
163 | |||