blob: c96b032ebd4abaf494b41683889fd4eb9b4318e3 [file] [log] [blame]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08001python write_package_manifest() {
2 # Get list of installed packages
3 license_image_dir = d.expand('${LICENSE_DIRECTORY}/${IMAGE_NAME}')
4 bb.utils.mkdirhier(license_image_dir)
5 from oe.rootfs import image_list_installed_packages
6 from oe.utils import format_pkg_list
7
8 pkgs = image_list_installed_packages(d)
9 output = format_pkg_list(pkgs)
10 open(os.path.join(license_image_dir, 'package.manifest'),
11 'w+').write(output)
12}
13
14python license_create_manifest() {
15 import oe.packagedata
16 from oe.rootfs import image_list_installed_packages
17
18 build_images_from_feeds = d.getVar('BUILD_IMAGES_FROM_FEEDS')
19 if build_images_from_feeds == "1":
20 return 0
21
22 pkg_dic = {}
23 for pkg in sorted(image_list_installed_packages(d)):
24 pkg_info = os.path.join(d.getVar('PKGDATA_DIR'),
25 'runtime-reverse', pkg)
26 pkg_name = os.path.basename(os.readlink(pkg_info))
27
28 pkg_dic[pkg_name] = oe.packagedata.read_pkgdatafile(pkg_info)
29 if not "LICENSE" in pkg_dic[pkg_name].keys():
30 pkg_lic_name = "LICENSE_" + pkg_name
31 pkg_dic[pkg_name]["LICENSE"] = pkg_dic[pkg_name][pkg_lic_name]
32
33 rootfs_license_manifest = os.path.join(d.getVar('LICENSE_DIRECTORY'),
34 d.getVar('IMAGE_NAME'), 'license.manifest')
Brad Bishop19323692019-04-05 15:28:33 -040035 write_license_files(d, rootfs_license_manifest, pkg_dic, rootfs=True)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080036}
37
Brad Bishop19323692019-04-05 15:28:33 -040038def write_license_files(d, license_manifest, pkg_dic, rootfs=True):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080039 import re
Brad Bishop19323692019-04-05 15:28:33 -040040 import stat
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080041
42 bad_licenses = (d.getVar("INCOMPATIBLE_LICENSE") or "").split()
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080043 bad_licenses = expand_wildcard_licenses(d, bad_licenses)
44
Brad Bishopf3f93bb2019-10-16 14:33:32 -040045 whitelist = []
46 for lic in bad_licenses:
47 whitelist.extend((d.getVar("WHITELIST_" + lic) or "").split())
48
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080049 with open(license_manifest, "w") as license_file:
50 for pkg in sorted(pkg_dic):
Brad Bishopf3f93bb2019-10-16 14:33:32 -040051 if bad_licenses and pkg not in whitelist:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080052 try:
Andrew Geissler82c905d2020-04-13 13:39:40 -050053 licenses = incompatible_pkg_license(d, bad_licenses, pkg_dic[pkg]["LICENSE"])
54 if licenses:
55 bb.fatal("Package %s cannot be installed into the image because it has incompatible license(s): %s" %(pkg, ' '.join(licenses)))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080056 (pkg_dic[pkg]["LICENSE"], pkg_dic[pkg]["LICENSES"]) = \
57 oe.license.manifest_licenses(pkg_dic[pkg]["LICENSE"],
58 bad_licenses, canonical_license, d)
59 except oe.license.LicenseError as exc:
60 bb.fatal('%s: %s' % (d.getVar('P'), exc))
61 else:
Brad Bishop977dc1a2019-02-06 16:01:43 -050062 pkg_dic[pkg]["LICENSES"] = re.sub(r'[|&()*]', ' ', pkg_dic[pkg]["LICENSE"])
63 pkg_dic[pkg]["LICENSES"] = re.sub(r' *', ' ', pkg_dic[pkg]["LICENSES"])
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080064 pkg_dic[pkg]["LICENSES"] = pkg_dic[pkg]["LICENSES"].split()
Brad Bishopf3f93bb2019-10-16 14:33:32 -040065 if pkg in whitelist:
66 bb.warn("Including %s with an incompatible license %s into the image, because it has been whitelisted." %(pkg, pkg_dic[pkg]["LICENSE"]))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080067
68 if not "IMAGE_MANIFEST" in pkg_dic[pkg]:
69 # Rootfs manifest
70 license_file.write("PACKAGE NAME: %s\n" % pkg)
71 license_file.write("PACKAGE VERSION: %s\n" % pkg_dic[pkg]["PV"])
72 license_file.write("RECIPE NAME: %s\n" % pkg_dic[pkg]["PN"])
73 license_file.write("LICENSE: %s\n\n" % pkg_dic[pkg]["LICENSE"])
74
75 # If the package doesn't contain any file, that is, its size is 0, the license
76 # isn't relevant as far as the final image is concerned. So doing license check
77 # doesn't make much sense, skip it.
78 if pkg_dic[pkg]["PKGSIZE_%s" % pkg] == "0":
79 continue
80 else:
81 # Image manifest
82 license_file.write("RECIPE NAME: %s\n" % pkg_dic[pkg]["PN"])
83 license_file.write("VERSION: %s\n" % pkg_dic[pkg]["PV"])
84 license_file.write("LICENSE: %s\n" % pkg_dic[pkg]["LICENSE"])
85 license_file.write("FILES: %s\n\n" % pkg_dic[pkg]["FILES"])
86
87 for lic in pkg_dic[pkg]["LICENSES"]:
88 lic_file = os.path.join(d.getVar('LICENSE_DIRECTORY'),
89 pkg_dic[pkg]["PN"], "generic_%s" %
Brad Bishop977dc1a2019-02-06 16:01:43 -050090 re.sub(r'\+', '', lic))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080091 # add explicity avoid of CLOSED license because isn't generic
92 if lic == "CLOSED":
93 continue
94
95 if not os.path.exists(lic_file):
96 bb.warn("The license listed %s was not in the "\
97 "licenses collected for recipe %s"
98 % (lic, pkg_dic[pkg]["PN"]))
99
100 # Two options here:
101 # - Just copy the manifest
102 # - Copy the manifest and the license directories
103 # With both options set we see a .5 M increase in core-image-minimal
104 copy_lic_manifest = d.getVar('COPY_LIC_MANIFEST')
105 copy_lic_dirs = d.getVar('COPY_LIC_DIRS')
Brad Bishop19323692019-04-05 15:28:33 -0400106 if rootfs and copy_lic_manifest == "1":
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800107 rootfs_license_dir = os.path.join(d.getVar('IMAGE_ROOTFS'),
108 'usr', 'share', 'common-licenses')
109 bb.utils.mkdirhier(rootfs_license_dir)
110 rootfs_license_manifest = os.path.join(rootfs_license_dir,
111 os.path.split(license_manifest)[1])
112 if not os.path.exists(rootfs_license_manifest):
Brad Bishopc342db32019-05-15 21:57:59 -0400113 oe.path.copyhardlink(license_manifest, rootfs_license_manifest)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800114
115 if copy_lic_dirs == "1":
116 for pkg in sorted(pkg_dic):
117 pkg_rootfs_license_dir = os.path.join(rootfs_license_dir, pkg)
118 bb.utils.mkdirhier(pkg_rootfs_license_dir)
119 pkg_license_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
120 pkg_dic[pkg]["PN"])
121
122 pkg_manifest_licenses = [canonical_license(d, lic) \
123 for lic in pkg_dic[pkg]["LICENSES"]]
124
125 licenses = os.listdir(pkg_license_dir)
126 for lic in licenses:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800127 pkg_license = os.path.join(pkg_license_dir, lic)
128 pkg_rootfs_license = os.path.join(pkg_rootfs_license_dir, lic)
129
Brad Bishop977dc1a2019-02-06 16:01:43 -0500130 if re.match(r"^generic_.*$", lic):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800131 generic_lic = canonical_license(d,
Brad Bishop977dc1a2019-02-06 16:01:43 -0500132 re.search(r"^generic_(.*)$", lic).group(1))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800133
134 # Do not copy generic license into package if isn't
135 # declared into LICENSES of the package.
Brad Bishop977dc1a2019-02-06 16:01:43 -0500136 if not re.sub(r'\+$', '', generic_lic) in \
137 [re.sub(r'\+', '', lic) for lic in \
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800138 pkg_manifest_licenses]:
139 continue
140
141 if oe.license.license_ok(generic_lic,
142 bad_licenses) == False:
143 continue
144
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600145 # Make sure we use only canonical name for the license file
146 rootfs_license = os.path.join(rootfs_license_dir, "generic_%s" % generic_lic)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800147 if not os.path.exists(rootfs_license):
Brad Bishopc342db32019-05-15 21:57:59 -0400148 oe.path.copyhardlink(pkg_license, rootfs_license)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800149
150 if not os.path.exists(pkg_rootfs_license):
151 os.symlink(os.path.join('..', lic), pkg_rootfs_license)
152 else:
153 if (oe.license.license_ok(canonical_license(d,
154 lic), bad_licenses) == False or
155 os.path.exists(pkg_rootfs_license)):
156 continue
157
Brad Bishopc342db32019-05-15 21:57:59 -0400158 oe.path.copyhardlink(pkg_license, pkg_rootfs_license)
Brad Bishop19323692019-04-05 15:28:33 -0400159 # Fixup file ownership and permissions
160 for walkroot, dirs, files in os.walk(rootfs_license_dir):
161 for f in files:
162 p = os.path.join(walkroot, f)
163 os.lchown(p, 0, 0)
164 if not os.path.islink(p):
165 os.chmod(p, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
166 for dir in dirs:
167 p = os.path.join(walkroot, dir)
168 os.lchown(p, 0, 0)
169 os.chmod(p, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
170
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800171
172
173def license_deployed_manifest(d):
174 """
175 Write the license manifest for the deployed recipes.
176 The deployed recipes usually includes the bootloader
177 and extra files to boot the target.
178 """
179
180 dep_dic = {}
181 man_dic = {}
182 lic_dir = d.getVar("LICENSE_DIRECTORY")
183
184 dep_dic = get_deployed_dependencies(d)
185 for dep in dep_dic.keys():
186 man_dic[dep] = {}
187 # It is necessary to mark this will be used for image manifest
188 man_dic[dep]["IMAGE_MANIFEST"] = True
189 man_dic[dep]["PN"] = dep
190 man_dic[dep]["FILES"] = \
191 " ".join(get_deployed_files(dep_dic[dep]))
192 with open(os.path.join(lic_dir, dep, "recipeinfo"), "r") as f:
193 for line in f.readlines():
194 key,val = line.split(": ", 1)
195 man_dic[dep][key] = val[:-1]
196
197 lic_manifest_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
198 d.getVar('IMAGE_NAME'))
199 bb.utils.mkdirhier(lic_manifest_dir)
200 image_license_manifest = os.path.join(lic_manifest_dir, 'image_license.manifest')
Brad Bishop19323692019-04-05 15:28:33 -0400201 write_license_files(d, image_license_manifest, man_dic, rootfs=False)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800202
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500203 link_name = d.getVar('IMAGE_LINK_NAME')
204 if link_name:
205 lic_manifest_symlink_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
206 link_name)
207 # remove old symlink
208 if os.path.islink(lic_manifest_symlink_dir):
209 os.unlink(lic_manifest_symlink_dir)
210
211 # create the image dir symlink
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600212 if lic_manifest_dir != lic_manifest_symlink_dir:
213 os.symlink(lic_manifest_dir, lic_manifest_symlink_dir)
Andrew Geisslerc9f78652020-09-18 14:11:35 -0500214
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800215def get_deployed_dependencies(d):
216 """
217 Get all the deployed dependencies of an image
218 """
219
220 deploy = {}
221 # Get all the dependencies for the current task (rootfs).
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800222 taskdata = d.getVar("BB_TASKDEPDATA", False)
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600223 pn = d.getVar("PN", True)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800224 depends = list(set([dep[0] for dep
225 in list(taskdata.values())
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600226 if not dep[0].endswith("-native") and not dep[0] == pn]))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800227
228 # To verify what was deployed it checks the rootfs dependencies against
229 # the SSTATE_MANIFESTS for "deploy" task.
230 # The manifest file name contains the arch. Because we are not running
231 # in the recipe context it is necessary to check every arch used.
232 sstate_manifest_dir = d.getVar("SSTATE_MANIFESTS")
233 archs = list(set(d.getVar("SSTATE_ARCHS").split()))
234 for dep in depends:
235 for arch in archs:
236 sstate_manifest_file = os.path.join(sstate_manifest_dir,
237 "manifest-%s-%s.deploy" % (arch, dep))
238 if os.path.exists(sstate_manifest_file):
239 deploy[dep] = sstate_manifest_file
240 break
241
242 return deploy
243get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA"
244
245def get_deployed_files(man_file):
246 """
247 Get the files deployed from the sstate manifest
248 """
249
250 dep_files = []
251 excluded_files = []
252 with open(man_file, "r") as manifest:
253 all_files = manifest.read()
254 for f in all_files.splitlines():
255 if ((not (os.path.islink(f) or os.path.isdir(f))) and
256 not os.path.basename(f) in excluded_files):
257 dep_files.append(os.path.basename(f))
258 return dep_files
259
260ROOTFS_POSTPROCESS_COMMAND_prepend = "write_package_manifest; license_create_manifest; "
261do_rootfs[recrdeptask] += "do_populate_lic"
262
263python do_populate_lic_deploy() {
264 license_deployed_manifest(d)
265}
266
267addtask populate_lic_deploy before do_build after do_image_complete
268do_populate_lic_deploy[recrdeptask] += "do_populate_lic do_deploy"
269