blob: 2cfda81c9925e8bbe8ed1710160c2560da53c88e [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 Bishop15ae2502019-06-18 21:44:24 -040043 bad_licenses = [canonical_license(d, l) for l in bad_licenses]
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080044 bad_licenses = expand_wildcard_licenses(d, bad_licenses)
45
46 with open(license_manifest, "w") as license_file:
47 for pkg in sorted(pkg_dic):
48 if bad_licenses:
49 try:
50 (pkg_dic[pkg]["LICENSE"], pkg_dic[pkg]["LICENSES"]) = \
51 oe.license.manifest_licenses(pkg_dic[pkg]["LICENSE"],
52 bad_licenses, canonical_license, d)
53 except oe.license.LicenseError as exc:
54 bb.fatal('%s: %s' % (d.getVar('P'), exc))
55 else:
Brad Bishop977dc1a2019-02-06 16:01:43 -050056 pkg_dic[pkg]["LICENSES"] = re.sub(r'[|&()*]', ' ', pkg_dic[pkg]["LICENSE"])
57 pkg_dic[pkg]["LICENSES"] = re.sub(r' *', ' ', pkg_dic[pkg]["LICENSES"])
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080058 pkg_dic[pkg]["LICENSES"] = pkg_dic[pkg]["LICENSES"].split()
59
60 if not "IMAGE_MANIFEST" in pkg_dic[pkg]:
61 # Rootfs manifest
62 license_file.write("PACKAGE NAME: %s\n" % pkg)
63 license_file.write("PACKAGE VERSION: %s\n" % pkg_dic[pkg]["PV"])
64 license_file.write("RECIPE NAME: %s\n" % pkg_dic[pkg]["PN"])
65 license_file.write("LICENSE: %s\n\n" % pkg_dic[pkg]["LICENSE"])
66
67 # If the package doesn't contain any file, that is, its size is 0, the license
68 # isn't relevant as far as the final image is concerned. So doing license check
69 # doesn't make much sense, skip it.
70 if pkg_dic[pkg]["PKGSIZE_%s" % pkg] == "0":
71 continue
72 else:
73 # Image manifest
74 license_file.write("RECIPE NAME: %s\n" % pkg_dic[pkg]["PN"])
75 license_file.write("VERSION: %s\n" % pkg_dic[pkg]["PV"])
76 license_file.write("LICENSE: %s\n" % pkg_dic[pkg]["LICENSE"])
77 license_file.write("FILES: %s\n\n" % pkg_dic[pkg]["FILES"])
78
79 for lic in pkg_dic[pkg]["LICENSES"]:
80 lic_file = os.path.join(d.getVar('LICENSE_DIRECTORY'),
81 pkg_dic[pkg]["PN"], "generic_%s" %
Brad Bishop977dc1a2019-02-06 16:01:43 -050082 re.sub(r'\+', '', lic))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080083 # add explicity avoid of CLOSED license because isn't generic
84 if lic == "CLOSED":
85 continue
86
87 if not os.path.exists(lic_file):
88 bb.warn("The license listed %s was not in the "\
89 "licenses collected for recipe %s"
90 % (lic, pkg_dic[pkg]["PN"]))
91
92 # Two options here:
93 # - Just copy the manifest
94 # - Copy the manifest and the license directories
95 # With both options set we see a .5 M increase in core-image-minimal
96 copy_lic_manifest = d.getVar('COPY_LIC_MANIFEST')
97 copy_lic_dirs = d.getVar('COPY_LIC_DIRS')
Brad Bishop19323692019-04-05 15:28:33 -040098 if rootfs and copy_lic_manifest == "1":
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080099 rootfs_license_dir = os.path.join(d.getVar('IMAGE_ROOTFS'),
100 'usr', 'share', 'common-licenses')
101 bb.utils.mkdirhier(rootfs_license_dir)
102 rootfs_license_manifest = os.path.join(rootfs_license_dir,
103 os.path.split(license_manifest)[1])
104 if not os.path.exists(rootfs_license_manifest):
Brad Bishopc342db32019-05-15 21:57:59 -0400105 oe.path.copyhardlink(license_manifest, rootfs_license_manifest)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800106
107 if copy_lic_dirs == "1":
108 for pkg in sorted(pkg_dic):
109 pkg_rootfs_license_dir = os.path.join(rootfs_license_dir, pkg)
110 bb.utils.mkdirhier(pkg_rootfs_license_dir)
111 pkg_license_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
112 pkg_dic[pkg]["PN"])
113
114 pkg_manifest_licenses = [canonical_license(d, lic) \
115 for lic in pkg_dic[pkg]["LICENSES"]]
116
117 licenses = os.listdir(pkg_license_dir)
118 for lic in licenses:
119 rootfs_license = os.path.join(rootfs_license_dir, lic)
120 pkg_license = os.path.join(pkg_license_dir, lic)
121 pkg_rootfs_license = os.path.join(pkg_rootfs_license_dir, lic)
122
Brad Bishop977dc1a2019-02-06 16:01:43 -0500123 if re.match(r"^generic_.*$", lic):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800124 generic_lic = canonical_license(d,
Brad Bishop977dc1a2019-02-06 16:01:43 -0500125 re.search(r"^generic_(.*)$", lic).group(1))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800126
127 # Do not copy generic license into package if isn't
128 # declared into LICENSES of the package.
Brad Bishop977dc1a2019-02-06 16:01:43 -0500129 if not re.sub(r'\+$', '', generic_lic) in \
130 [re.sub(r'\+', '', lic) for lic in \
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800131 pkg_manifest_licenses]:
132 continue
133
134 if oe.license.license_ok(generic_lic,
135 bad_licenses) == False:
136 continue
137
138 if not os.path.exists(rootfs_license):
Brad Bishopc342db32019-05-15 21:57:59 -0400139 oe.path.copyhardlink(pkg_license, rootfs_license)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800140
141 if not os.path.exists(pkg_rootfs_license):
142 os.symlink(os.path.join('..', lic), pkg_rootfs_license)
143 else:
144 if (oe.license.license_ok(canonical_license(d,
145 lic), bad_licenses) == False or
146 os.path.exists(pkg_rootfs_license)):
147 continue
148
Brad Bishopc342db32019-05-15 21:57:59 -0400149 oe.path.copyhardlink(pkg_license, pkg_rootfs_license)
Brad Bishop19323692019-04-05 15:28:33 -0400150 # Fixup file ownership and permissions
151 for walkroot, dirs, files in os.walk(rootfs_license_dir):
152 for f in files:
153 p = os.path.join(walkroot, f)
154 os.lchown(p, 0, 0)
155 if not os.path.islink(p):
156 os.chmod(p, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
157 for dir in dirs:
158 p = os.path.join(walkroot, dir)
159 os.lchown(p, 0, 0)
160 os.chmod(p, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
161
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800162
163
164def license_deployed_manifest(d):
165 """
166 Write the license manifest for the deployed recipes.
167 The deployed recipes usually includes the bootloader
168 and extra files to boot the target.
169 """
170
171 dep_dic = {}
172 man_dic = {}
173 lic_dir = d.getVar("LICENSE_DIRECTORY")
174
175 dep_dic = get_deployed_dependencies(d)
176 for dep in dep_dic.keys():
177 man_dic[dep] = {}
178 # It is necessary to mark this will be used for image manifest
179 man_dic[dep]["IMAGE_MANIFEST"] = True
180 man_dic[dep]["PN"] = dep
181 man_dic[dep]["FILES"] = \
182 " ".join(get_deployed_files(dep_dic[dep]))
183 with open(os.path.join(lic_dir, dep, "recipeinfo"), "r") as f:
184 for line in f.readlines():
185 key,val = line.split(": ", 1)
186 man_dic[dep][key] = val[:-1]
187
188 lic_manifest_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
189 d.getVar('IMAGE_NAME'))
190 bb.utils.mkdirhier(lic_manifest_dir)
191 image_license_manifest = os.path.join(lic_manifest_dir, 'image_license.manifest')
Brad Bishop19323692019-04-05 15:28:33 -0400192 write_license_files(d, image_license_manifest, man_dic, rootfs=False)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800193
194def get_deployed_dependencies(d):
195 """
196 Get all the deployed dependencies of an image
197 """
198
199 deploy = {}
200 # Get all the dependencies for the current task (rootfs).
201 # Also get EXTRA_IMAGEDEPENDS because the bootloader is
202 # usually in this var and not listed in rootfs.
203 # At last, get the dependencies from boot classes because
204 # it might contain the bootloader.
205 taskdata = d.getVar("BB_TASKDEPDATA", False)
206 depends = list(set([dep[0] for dep
207 in list(taskdata.values())
208 if not dep[0].endswith("-native")]))
209
210 # To verify what was deployed it checks the rootfs dependencies against
211 # the SSTATE_MANIFESTS for "deploy" task.
212 # The manifest file name contains the arch. Because we are not running
213 # in the recipe context it is necessary to check every arch used.
214 sstate_manifest_dir = d.getVar("SSTATE_MANIFESTS")
215 archs = list(set(d.getVar("SSTATE_ARCHS").split()))
216 for dep in depends:
217 for arch in archs:
218 sstate_manifest_file = os.path.join(sstate_manifest_dir,
219 "manifest-%s-%s.deploy" % (arch, dep))
220 if os.path.exists(sstate_manifest_file):
221 deploy[dep] = sstate_manifest_file
222 break
223
224 return deploy
225get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA"
226
227def get_deployed_files(man_file):
228 """
229 Get the files deployed from the sstate manifest
230 """
231
232 dep_files = []
233 excluded_files = []
234 with open(man_file, "r") as manifest:
235 all_files = manifest.read()
236 for f in all_files.splitlines():
237 if ((not (os.path.islink(f) or os.path.isdir(f))) and
238 not os.path.basename(f) in excluded_files):
239 dep_files.append(os.path.basename(f))
240 return dep_files
241
242ROOTFS_POSTPROCESS_COMMAND_prepend = "write_package_manifest; license_create_manifest; "
243do_rootfs[recrdeptask] += "do_populate_lic"
244
245python do_populate_lic_deploy() {
246 license_deployed_manifest(d)
247}
248
249addtask populate_lic_deploy before do_build after do_image_complete
250do_populate_lic_deploy[recrdeptask] += "do_populate_lic do_deploy"
251