blob: b5399b6d9609c2004bdb679c2735583b4ad60d5a [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
Brad Bishopf3f93bb2019-10-16 14:33:32 -040046 whitelist = []
47 for lic in bad_licenses:
48 whitelist.extend((d.getVar("WHITELIST_" + lic) or "").split())
49
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080050 with open(license_manifest, "w") as license_file:
51 for pkg in sorted(pkg_dic):
Brad Bishopf3f93bb2019-10-16 14:33:32 -040052 if bad_licenses and pkg not in whitelist:
Brad Bishop1a4b7ee2018-12-16 17:11:34 -080053 try:
Brad Bishopf3f93bb2019-10-16 14:33:32 -040054 if incompatible_pkg_license(d, bad_licenses, pkg_dic[pkg]["LICENSE"]):
55 bb.fatal("Package %s has an incompatible license %s and cannot be installed into the image." %(pkg, pkg_dic[pkg]["LICENSE"]))
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:
127 rootfs_license = os.path.join(rootfs_license_dir, lic)
128 pkg_license = os.path.join(pkg_license_dir, lic)
129 pkg_rootfs_license = os.path.join(pkg_rootfs_license_dir, lic)
130
Brad Bishop977dc1a2019-02-06 16:01:43 -0500131 if re.match(r"^generic_.*$", lic):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800132 generic_lic = canonical_license(d,
Brad Bishop977dc1a2019-02-06 16:01:43 -0500133 re.search(r"^generic_(.*)$", lic).group(1))
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800134
135 # Do not copy generic license into package if isn't
136 # declared into LICENSES of the package.
Brad Bishop977dc1a2019-02-06 16:01:43 -0500137 if not re.sub(r'\+$', '', generic_lic) in \
138 [re.sub(r'\+', '', lic) for lic in \
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800139 pkg_manifest_licenses]:
140 continue
141
142 if oe.license.license_ok(generic_lic,
143 bad_licenses) == False:
144 continue
145
146 if not os.path.exists(rootfs_license):
Brad Bishopc342db32019-05-15 21:57:59 -0400147 oe.path.copyhardlink(pkg_license, rootfs_license)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800148
149 if not os.path.exists(pkg_rootfs_license):
150 os.symlink(os.path.join('..', lic), pkg_rootfs_license)
151 else:
152 if (oe.license.license_ok(canonical_license(d,
153 lic), bad_licenses) == False or
154 os.path.exists(pkg_rootfs_license)):
155 continue
156
Brad Bishopc342db32019-05-15 21:57:59 -0400157 oe.path.copyhardlink(pkg_license, pkg_rootfs_license)
Brad Bishop19323692019-04-05 15:28:33 -0400158 # Fixup file ownership and permissions
159 for walkroot, dirs, files in os.walk(rootfs_license_dir):
160 for f in files:
161 p = os.path.join(walkroot, f)
162 os.lchown(p, 0, 0)
163 if not os.path.islink(p):
164 os.chmod(p, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
165 for dir in dirs:
166 p = os.path.join(walkroot, dir)
167 os.lchown(p, 0, 0)
168 os.chmod(p, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
169
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800170
171
172def license_deployed_manifest(d):
173 """
174 Write the license manifest for the deployed recipes.
175 The deployed recipes usually includes the bootloader
176 and extra files to boot the target.
177 """
178
179 dep_dic = {}
180 man_dic = {}
181 lic_dir = d.getVar("LICENSE_DIRECTORY")
182
183 dep_dic = get_deployed_dependencies(d)
184 for dep in dep_dic.keys():
185 man_dic[dep] = {}
186 # It is necessary to mark this will be used for image manifest
187 man_dic[dep]["IMAGE_MANIFEST"] = True
188 man_dic[dep]["PN"] = dep
189 man_dic[dep]["FILES"] = \
190 " ".join(get_deployed_files(dep_dic[dep]))
191 with open(os.path.join(lic_dir, dep, "recipeinfo"), "r") as f:
192 for line in f.readlines():
193 key,val = line.split(": ", 1)
194 man_dic[dep][key] = val[:-1]
195
196 lic_manifest_dir = os.path.join(d.getVar('LICENSE_DIRECTORY'),
197 d.getVar('IMAGE_NAME'))
198 bb.utils.mkdirhier(lic_manifest_dir)
199 image_license_manifest = os.path.join(lic_manifest_dir, 'image_license.manifest')
Brad Bishop19323692019-04-05 15:28:33 -0400200 write_license_files(d, image_license_manifest, man_dic, rootfs=False)
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800201
202def get_deployed_dependencies(d):
203 """
204 Get all the deployed dependencies of an image
205 """
206
207 deploy = {}
208 # Get all the dependencies for the current task (rootfs).
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800209 taskdata = d.getVar("BB_TASKDEPDATA", False)
210 depends = list(set([dep[0] for dep
211 in list(taskdata.values())
212 if not dep[0].endswith("-native")]))
213
214 # To verify what was deployed it checks the rootfs dependencies against
215 # the SSTATE_MANIFESTS for "deploy" task.
216 # The manifest file name contains the arch. Because we are not running
217 # in the recipe context it is necessary to check every arch used.
218 sstate_manifest_dir = d.getVar("SSTATE_MANIFESTS")
219 archs = list(set(d.getVar("SSTATE_ARCHS").split()))
220 for dep in depends:
221 for arch in archs:
222 sstate_manifest_file = os.path.join(sstate_manifest_dir,
223 "manifest-%s-%s.deploy" % (arch, dep))
224 if os.path.exists(sstate_manifest_file):
225 deploy[dep] = sstate_manifest_file
226 break
227
228 return deploy
229get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA"
230
231def get_deployed_files(man_file):
232 """
233 Get the files deployed from the sstate manifest
234 """
235
236 dep_files = []
237 excluded_files = []
238 with open(man_file, "r") as manifest:
239 all_files = manifest.read()
240 for f in all_files.splitlines():
241 if ((not (os.path.islink(f) or os.path.isdir(f))) and
242 not os.path.basename(f) in excluded_files):
243 dep_files.append(os.path.basename(f))
244 return dep_files
245
246ROOTFS_POSTPROCESS_COMMAND_prepend = "write_package_manifest; license_create_manifest; "
247do_rootfs[recrdeptask] += "do_populate_lic"
248
249python do_populate_lic_deploy() {
250 license_deployed_manifest(d)
251}
252
253addtask populate_lic_deploy before do_build after do_image_complete
254do_populate_lic_deploy[recrdeptask] += "do_populate_lic do_deploy"
255