blob: 3f102d0fbc355de36cc687714333a95be61ceec9 [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).
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800201 taskdata = d.getVar("BB_TASKDEPDATA", False)
202 depends = list(set([dep[0] for dep
203 in list(taskdata.values())
204 if not dep[0].endswith("-native")]))
205
206 # To verify what was deployed it checks the rootfs dependencies against
207 # the SSTATE_MANIFESTS for "deploy" task.
208 # The manifest file name contains the arch. Because we are not running
209 # in the recipe context it is necessary to check every arch used.
210 sstate_manifest_dir = d.getVar("SSTATE_MANIFESTS")
211 archs = list(set(d.getVar("SSTATE_ARCHS").split()))
212 for dep in depends:
213 for arch in archs:
214 sstate_manifest_file = os.path.join(sstate_manifest_dir,
215 "manifest-%s-%s.deploy" % (arch, dep))
216 if os.path.exists(sstate_manifest_file):
217 deploy[dep] = sstate_manifest_file
218 break
219
220 return deploy
221get_deployed_dependencies[vardepsexclude] = "BB_TASKDEPDATA"
222
223def get_deployed_files(man_file):
224 """
225 Get the files deployed from the sstate manifest
226 """
227
228 dep_files = []
229 excluded_files = []
230 with open(man_file, "r") as manifest:
231 all_files = manifest.read()
232 for f in all_files.splitlines():
233 if ((not (os.path.islink(f) or os.path.isdir(f))) and
234 not os.path.basename(f) in excluded_files):
235 dep_files.append(os.path.basename(f))
236 return dep_files
237
238ROOTFS_POSTPROCESS_COMMAND_prepend = "write_package_manifest; license_create_manifest; "
239do_rootfs[recrdeptask] += "do_populate_lic"
240
241python do_populate_lic_deploy() {
242 license_deployed_manifest(d)
243}
244
245addtask populate_lic_deploy before do_build after do_image_complete
246do_populate_lic_deploy[recrdeptask] += "do_populate_lic do_deploy"
247