summaryrefslogtreecommitdiffstats
path: root/meta/classes-recipe/license_image.bbclass
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2023-09-19 11:46:42 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2023-09-20 23:51:11 +0100
commit7ebbd68f0fb237f511cd2629ef9f6fc4d8488736 (patch)
treeb7ee47c58e13569c5466e49c22cbdb1fbd88ff45 /meta/classes-recipe/license_image.bbclass
parent84e17003c6098007f896ef301449a4748f9720fe (diff)
downloadpoky-7ebbd68f0fb237f511cd2629ef9f6fc4d8488736.tar.gz
license/license_image: Fix license file layout to avoid overlapping files
Currently DEPLOY_DIR/licenses is added to SSTATE_ALLOW_OVERLAP_FILES. This leads to bugs since when one MACHINE_ARCH recipes is cleaned, it removes the files for another which then results in later build failures as license files disappear. The solution is to include SSTAGE_PKGARCH in the path names to the license files. That does mean a search has to be used to find the correct license files for a given PN but that can be done via SSTATE_ARCHS. The implication for other tools is the layout has changed so tools will need to adapt to the new paths. The benefit is no more strange build failures such as from patterns like: MACHINE=qemux86-64 bitbake core-image-minimal MACHINE=genericx86-64 bitbake core-image-minimal MACHINE=qemux86-64 bitbake linux-yocto -c clean MACHINE=genericx86-64 bitbake core-image-minimal -C rootfs [YOCTO #14123] For anyone finding this commit, I'd question how much people should be relying on this code for tooling and suggest the SPDX manifests should be the preferred data format going forward anyway. (From OE-Core rev: 1a4ab9fc26659507e678e87312b514e8ea515673) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes-recipe/license_image.bbclass')
-rw-r--r--meta/classes-recipe/license_image.bbclass46
1 files changed, 34 insertions, 12 deletions
diff --git a/meta/classes-recipe/license_image.bbclass b/meta/classes-recipe/license_image.bbclass
index fc859c7c65..19b3dc55ba 100644
--- a/meta/classes-recipe/license_image.bbclass
+++ b/meta/classes-recipe/license_image.bbclass
@@ -18,7 +18,7 @@ python() {
18 18
19python write_package_manifest() { 19python write_package_manifest() {
20 # Get list of installed packages 20 # Get list of installed packages
21 license_image_dir = d.expand('${LICENSE_DIRECTORY}/${IMAGE_NAME}') 21 license_image_dir = d.expand('${LICENSE_DIRECTORY}/${SSTATE_PKGARCH}/${IMAGE_NAME}')
22 bb.utils.mkdirhier(license_image_dir) 22 bb.utils.mkdirhier(license_image_dir)
23 from oe.rootfs import image_list_installed_packages 23 from oe.rootfs import image_list_installed_packages
24 from oe.utils import format_pkg_list 24 from oe.utils import format_pkg_list
@@ -49,7 +49,7 @@ python license_create_manifest() {
49 pkg_dic[pkg_name]["LICENSE"] = pkg_dic[pkg_name][pkg_lic_name] 49 pkg_dic[pkg_name]["LICENSE"] = pkg_dic[pkg_name][pkg_lic_name]
50 50
51 rootfs_license_manifest = os.path.join(d.getVar('LICENSE_DIRECTORY'), 51 rootfs_license_manifest = os.path.join(d.getVar('LICENSE_DIRECTORY'),
52 d.getVar('IMAGE_NAME'), 'license.manifest') 52 d.getVar('SSTATE_PKGARCH'), d.getVar('IMAGE_NAME'), 'license.manifest')
53 write_license_files(d, rootfs_license_manifest, pkg_dic, rootfs=True) 53 write_license_files(d, rootfs_license_manifest, pkg_dic, rootfs=True)
54} 54}
55 55
@@ -59,6 +59,8 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs=True):
59 59
60 bad_licenses = (d.getVar("INCOMPATIBLE_LICENSE") or "").split() 60 bad_licenses = (d.getVar("INCOMPATIBLE_LICENSE") or "").split()
61 bad_licenses = expand_wildcard_licenses(d, bad_licenses) 61 bad_licenses = expand_wildcard_licenses(d, bad_licenses)
62 pkgarchs = d.getVar("SSTATE_ARCHS").split()
63 pkgarchs.reverse()
62 64
63 exceptions = (d.getVar("INCOMPATIBLE_LICENSE_EXCEPTIONS") or "").split() 65 exceptions = (d.getVar("INCOMPATIBLE_LICENSE_EXCEPTIONS") or "").split()
64 with open(license_manifest, "w") as license_file: 66 with open(license_manifest, "w") as license_file:
@@ -98,9 +100,13 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs=True):
98 license_file.write("FILES: %s\n\n" % pkg_dic[pkg]["FILES"]) 100 license_file.write("FILES: %s\n\n" % pkg_dic[pkg]["FILES"])
99 101
100 for lic in pkg_dic[pkg]["LICENSES"]: 102 for lic in pkg_dic[pkg]["LICENSES"]:
101 lic_file = os.path.join(d.getVar('LICENSE_DIRECTORY'), 103 for pkgarch in pkgarchs:
102 pkg_dic[pkg]["PN"], "generic_%s" % 104 lic_file = os.path.join(d.getVar('LICENSE_DIRECTORY'),
103 re.sub(r'\+', '', lic)) 105 pkgarch,
106 pkg_dic[pkg]["PN"], "generic_%s" %
107 re.sub(r'\+', '', lic))
108 if os.path.exists(lic_file):
109 break
104 # add explicity avoid of CLOSED license because isn't generic 110 # add explicity avoid of CLOSED license because isn't generic
105 if lic == "CLOSED": 111 if lic == "CLOSED":
106 continue 112 continue
@@ -130,8 +136,13 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs=True):
130 for pkg in sorted(pkg_dic): 136 for pkg in sorted(pkg_dic):
131 pkg_rootfs_license_dir = os.path.join(rootfs_license_dir, pkg) 137 pkg_rootfs_license_dir = os.path.join(rootfs_license_dir, pkg)
132 bb.utils.mkdirhier(pkg_rootfs_license_dir) 138 bb.utils.mkdirhier(pkg_rootfs_license_dir)
133 pkg_license_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'), 139 for pkgarch in pkgarchs:
134 pkg_dic[pkg]["PN"]) 140 pkg_license_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
141 pkgarch, pkg_dic[pkg]["PN"])
142 if os.path.exists(pkg_license_dir):
143 break
144 if not os.path.exists(pkg_license_dir ):
145 bb.fatal("Couldn't find license information for dependency %s" % pkg)
135 146
136 pkg_manifest_licenses = [canonical_license(d, lic) \ 147 pkg_manifest_licenses = [canonical_license(d, lic) \
137 for lic in pkg_dic[pkg]["LICENSES"]] 148 for lic in pkg_dic[pkg]["LICENSES"]]
@@ -183,7 +194,7 @@ def write_license_files(d, license_manifest, pkg_dic, rootfs=True):
183 os.lchown(p, 0, 0) 194 os.lchown(p, 0, 0)
184 os.chmod(p, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) 195 os.chmod(p, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
185 196
186 197write_license_files[vardepsexclude] = "SSTATE_ARCHS"
187 198
188def license_deployed_manifest(d): 199def license_deployed_manifest(d):
189 """ 200 """
@@ -195,6 +206,8 @@ def license_deployed_manifest(d):
195 dep_dic = {} 206 dep_dic = {}
196 man_dic = {} 207 man_dic = {}
197 lic_dir = d.getVar("LICENSE_DIRECTORY") 208 lic_dir = d.getVar("LICENSE_DIRECTORY")
209 pkgarchs = d.getVar("SSTATE_ARCHS").split()
210 pkgarchs.reverse()
198 211
199 dep_dic = get_deployed_dependencies(d) 212 dep_dic = get_deployed_dependencies(d)
200 for dep in dep_dic.keys(): 213 for dep in dep_dic.keys():
@@ -204,12 +217,19 @@ def license_deployed_manifest(d):
204 man_dic[dep]["PN"] = dep 217 man_dic[dep]["PN"] = dep
205 man_dic[dep]["FILES"] = \ 218 man_dic[dep]["FILES"] = \
206 " ".join(get_deployed_files(dep_dic[dep])) 219 " ".join(get_deployed_files(dep_dic[dep]))
207 with open(os.path.join(lic_dir, dep, "recipeinfo"), "r") as f: 220
221 for pkgarch in pkgarchs:
222 licfile = os.path.join(lic_dir, pkgarch, dep, "recipeinfo")
223 if os.path.exists(licfile):
224 break
225 if not os.path.exists(licfile):
226 bb.fatal("Couldn't find license information for dependency %s" % dep)
227 with open(licfile, "r") as f:
208 for line in f.readlines(): 228 for line in f.readlines():
209 key,val = line.split(": ", 1) 229 key,val = line.split(": ", 1)
210 man_dic[dep][key] = val[:-1] 230 man_dic[dep][key] = val[:-1]
211 231
212 lic_manifest_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'), 232 lic_manifest_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'), d.getVar('SSTATE_PKGARCH'),
213 d.getVar('IMAGE_NAME')) 233 d.getVar('IMAGE_NAME'))
214 bb.utils.mkdirhier(lic_manifest_dir) 234 bb.utils.mkdirhier(lic_manifest_dir)
215 image_license_manifest = os.path.join(lic_manifest_dir, 'image_license.manifest') 235 image_license_manifest = os.path.join(lic_manifest_dir, 'image_license.manifest')
@@ -217,7 +237,7 @@ def license_deployed_manifest(d):
217 237
218 link_name = d.getVar('IMAGE_LINK_NAME') 238 link_name = d.getVar('IMAGE_LINK_NAME')
219 if link_name: 239 if link_name:
220 lic_manifest_symlink_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'), 240 lic_manifest_symlink_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'), d.getVar('SSTATE_PKGARCH'),
221 link_name) 241 link_name)
222 # remove old symlink 242 # remove old symlink
223 if os.path.islink(lic_manifest_symlink_dir): 243 if os.path.islink(lic_manifest_symlink_dir):
@@ -227,6 +247,8 @@ def license_deployed_manifest(d):
227 if lic_manifest_dir != lic_manifest_symlink_dir: 247 if lic_manifest_dir != lic_manifest_symlink_dir:
228 os.symlink(lic_manifest_dir, lic_manifest_symlink_dir) 248 os.symlink(lic_manifest_dir, lic_manifest_symlink_dir)
229 249
250license_deployed_manifest[vardepsexclude] = "SSTATE_ARCHS"
251
230def get_deployed_dependencies(d): 252def get_deployed_dependencies(d):
231 """ 253 """
232 Get all the deployed dependencies of an image 254 Get all the deployed dependencies of an image
@@ -255,7 +277,7 @@ def get_deployed_dependencies(d):
255 break 277 break
256 278
257 return deploy 279 return deploy
258get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA" 280get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA SSTATE_ARCHS"
259 281
260def get_deployed_files(man_file): 282def get_deployed_files(man_file):
261 """ 283 """