summaryrefslogtreecommitdiffstats
path: root/meta/lib/oe/package_manager/deb
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2025-11-07 13:31:53 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2025-11-07 13:31:53 +0000
commit8c22ff0d8b70d9b12f0487ef696a7e915b9e3173 (patch)
treeefdc32587159d0050a69009bdf2330a531727d95 /meta/lib/oe/package_manager/deb
parentd412d2747595c1cc4a5e3ca975e3adc31b2f7891 (diff)
downloadpoky-8c22ff0d8b70d9b12f0487ef696a7e915b9e3173.tar.gz
The poky repository master branch is no longer being updated.
You can either: a) switch to individual clones of bitbake, openembedded-core, meta-yocto and yocto-docs b) use the new bitbake-setup You can find information about either approach in our documentation: https://docs.yoctoproject.org/ Note that "poky" the distro setting is still available in meta-yocto as before and we continue to use and maintain that. Long live Poky! Some further information on the background of this change can be found in: https://lists.openembedded.org/g/openembedded-architecture/message/2179 Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oe/package_manager/deb')
-rw-r--r--meta/lib/oe/package_manager/deb/__init__.py451
-rw-r--r--meta/lib/oe/package_manager/deb/manifest.py28
-rw-r--r--meta/lib/oe/package_manager/deb/rootfs.py212
-rw-r--r--meta/lib/oe/package_manager/deb/sdk.py107
4 files changed, 0 insertions, 798 deletions
diff --git a/meta/lib/oe/package_manager/deb/__init__.py b/meta/lib/oe/package_manager/deb/__init__.py
deleted file mode 100644
index eb48f3f982..0000000000
--- a/meta/lib/oe/package_manager/deb/__init__.py
+++ /dev/null
@@ -1,451 +0,0 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6
7import re
8import subprocess
9from oe.package_manager import *
10from oe.package_manager.common_deb_ipk import OpkgDpkgPM
11
12class DpkgIndexer(Indexer):
13 def _create_configs(self):
14 bb.utils.mkdirhier(self.apt_conf_dir)
15 bb.utils.mkdirhier(os.path.join(self.apt_conf_dir, "lists", "partial"))
16 bb.utils.mkdirhier(os.path.join(self.apt_conf_dir, "apt.conf.d"))
17 bb.utils.mkdirhier(os.path.join(self.apt_conf_dir, "preferences.d"))
18
19 with open(os.path.join(self.apt_conf_dir, "preferences"),
20 "w") as prefs_file:
21 pass
22 with open(os.path.join(self.apt_conf_dir, "sources.list"),
23 "w+") as sources_file:
24 pass
25
26 with open(self.apt_conf_file, "w") as apt_conf:
27 with open(os.path.join(self.d.expand("${STAGING_ETCDIR_NATIVE}"),
28 "apt", "apt.conf.sample")) as apt_conf_sample:
29 for line in apt_conf_sample.read().split("\n"):
30 line = re.sub(r"#ROOTFS#", "/dev/null", line)
31 line = re.sub(r"#APTCONF#", self.apt_conf_dir, line)
32 apt_conf.write(line + "\n")
33
34 def write_index(self):
35 self.apt_conf_dir = os.path.join(self.d.expand("${APTCONF_TARGET}"),
36 "apt-ftparchive")
37 self.apt_conf_file = os.path.join(self.apt_conf_dir, "apt.conf")
38 self._create_configs()
39
40 os.environ['APT_CONFIG'] = self.apt_conf_file
41
42 pkg_archs = self.d.getVar('PACKAGE_ARCHS')
43 if pkg_archs is not None:
44 arch_list = pkg_archs.split()
45 sdk_pkg_archs = self.d.getVar('SDK_PACKAGE_ARCHS')
46 if sdk_pkg_archs is not None:
47 for a in sdk_pkg_archs.split():
48 if a not in pkg_archs:
49 arch_list.append(a)
50
51 all_mlb_pkg_arch_list = (self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS') or "").split()
52 arch_list.extend(arch for arch in all_mlb_pkg_arch_list if arch not in arch_list)
53
54 apt_ftparchive = bb.utils.which(os.getenv('PATH'), "apt-ftparchive")
55 gzip = bb.utils.which(os.getenv('PATH'), "gzip")
56
57 index_cmds = []
58 deb_dirs_found = False
59 index_sign_files = set()
60 for arch in arch_list:
61 arch_dir = os.path.join(self.deploy_dir, arch)
62 if not os.path.isdir(arch_dir):
63 continue
64
65 cmd = "cd %s; PSEUDO_UNLOAD=1 %s packages . > Packages;" % (arch_dir, apt_ftparchive)
66
67 cmd += "%s -fcn Packages > Packages.gz;" % gzip
68
69 release_file = os.path.join(arch_dir, "Release")
70 index_sign_files.add(release_file)
71
72 with open(release_file, "w+") as release:
73 release.write("Label: %s\n" % arch)
74
75 cmd += "PSEUDO_UNLOAD=1 %s release . >> Release" % apt_ftparchive
76
77 index_cmds.append(cmd)
78
79 deb_dirs_found = True
80
81 if not deb_dirs_found:
82 bb.note("There are no packages in %s" % self.deploy_dir)
83 return
84
85 oe.utils.multiprocess_launch(create_index, index_cmds, self.d)
86 if self.d.getVar('PACKAGE_FEED_SIGN') == '1':
87 signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND'))
88 else:
89 signer = None
90 if signer:
91 for f in index_sign_files:
92 signer.detach_sign(f,
93 self.d.getVar('PACKAGE_FEED_GPG_NAME'),
94 self.d.getVar('PACKAGE_FEED_GPG_PASSPHRASE_FILE'),
95 output_suffix="gpg",
96 use_sha256=True)
97
98class PMPkgsList(PkgsList):
99
100 def list_pkgs(self):
101 cmd = [bb.utils.which(os.getenv('PATH'), "dpkg-query"),
102 "--admindir=%s/var/lib/dpkg" % self.rootfs_dir,
103 "-W"]
104
105 cmd.append("-f=Package: ${Package}\nArchitecture: ${PackageArch}\nVersion: ${Version}\nFile: ${Package}_${Version}_${Architecture}.deb\nDepends: ${Depends}\nRecommends: ${Recommends}\nProvides: ${Provides}\n\n")
106
107 try:
108 cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip().decode("utf-8")
109 except subprocess.CalledProcessError as e:
110 bb.fatal("Cannot get the installed packages list. Command '%s' "
111 "returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
112
113 return opkg_query(cmd_output)
114
115
116class DpkgPM(OpkgDpkgPM):
117 def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None, deb_repo_workdir="oe-rootfs-repo", filterbydependencies=True):
118 super(DpkgPM, self).__init__(d, target_rootfs)
119 self.deploy_dir = oe.path.join(self.d.getVar('WORKDIR'), deb_repo_workdir)
120
121 create_packages_dir(self.d, self.deploy_dir, d.getVar("DEPLOY_DIR_DEB"), "package_write_deb", filterbydependencies)
122
123 if apt_conf_dir is None:
124 self.apt_conf_dir = self.d.expand("${APTCONF_TARGET}/apt")
125 else:
126 self.apt_conf_dir = apt_conf_dir
127 self.apt_conf_file = os.path.join(self.apt_conf_dir, "apt.conf")
128 self.apt_get_cmd = bb.utils.which(os.getenv('PATH'), "apt-get")
129 self.apt_cache_cmd = bb.utils.which(os.getenv('PATH'), "apt-cache")
130
131 self.apt_args = d.getVar("APT_ARGS")
132
133 self.all_arch_list = archs.split()
134 all_mlb_pkg_arch_list = (self.d.getVar('ALL_MULTILIB_PACKAGE_ARCHS') or "").split()
135 self.all_arch_list.extend(arch for arch in all_mlb_pkg_arch_list if arch not in self.all_arch_list)
136
137 self._create_configs(archs, base_archs)
138
139 self.indexer = DpkgIndexer(self.d, self.deploy_dir)
140
141 def mark_packages(self, status_tag, packages=None):
142 """
143 This function will change a package's status in /var/lib/dpkg/status file.
144 If 'packages' is None then the new_status will be applied to all
145 packages
146 """
147 status_file = self.target_rootfs + "/var/lib/dpkg/status"
148
149 with open(status_file, "r") as sf:
150 with open(status_file + ".tmp", "w+") as tmp_sf:
151 if packages is None:
152 tmp_sf.write(re.sub(r"Package: (.*?)\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)",
153 r"Package: \1\n\2Status: \3%s" % status_tag,
154 sf.read()))
155 else:
156 if type(packages).__name__ != "list":
157 raise TypeError("'packages' should be a list object")
158
159 status = sf.read()
160 for pkg in packages:
161 status = re.sub(r"Package: %s\n((?:[^\n]+\n)*?)Status: (.*)(?:unpacked|installed)" % pkg,
162 r"Package: %s\n\1Status: \2%s" % (pkg, status_tag),
163 status)
164
165 tmp_sf.write(status)
166
167 bb.utils.rename(status_file + ".tmp", status_file)
168
169 def run_pre_post_installs(self, package_name=None):
170 """
171 Run the pre/post installs for package "package_name". If package_name is
172 None, then run all pre/post install scriptlets.
173 """
174 info_dir = self.target_rootfs + "/var/lib/dpkg/info"
175 ControlScript = collections.namedtuple("ControlScript", ["suffix", "name", "argument"])
176 control_scripts = [
177 ControlScript(".preinst", "Preinstall", "install"),
178 ControlScript(".postinst", "Postinstall", "configure")]
179 status_file = self.target_rootfs + "/var/lib/dpkg/status"
180 installed_pkgs = []
181
182 with open(status_file, "r") as status:
183 for line in status.read().split('\n'):
184 m = re.match(r"^Package: (.*)", line)
185 if m is not None:
186 installed_pkgs.append(m.group(1))
187
188 if package_name is not None and not package_name in installed_pkgs:
189 return
190
191 os.environ['D'] = self.target_rootfs
192 os.environ['OFFLINE_ROOT'] = self.target_rootfs
193 os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs
194 os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs
195 os.environ['INTERCEPT_DIR'] = self.intercepts_dir
196 os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE')
197
198 for pkg_name in installed_pkgs:
199 for control_script in control_scripts:
200 p_full = os.path.join(info_dir, pkg_name + control_script.suffix)
201 if os.path.exists(p_full):
202 try:
203 bb.note("Executing %s for package: %s ..." %
204 (control_script.name.lower(), pkg_name))
205 output = subprocess.check_output([p_full, control_script.argument],
206 stderr=subprocess.STDOUT).decode("utf-8")
207 bb.note(output)
208 except subprocess.CalledProcessError as e:
209 bb.warn("%s for package %s failed with %d:\n%s" %
210 (control_script.name, pkg_name, e.returncode,
211 e.output.decode("utf-8")))
212 failed_postinsts_abort([pkg_name], self.d.expand("${T}/log.do_${BB_CURRENTTASK}"))
213
214 def update(self):
215 os.environ['APT_CONFIG'] = self.apt_conf_file
216
217 self.deploy_dir_lock()
218
219 cmd = "%s update" % self.apt_get_cmd
220
221 try:
222 subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
223 except subprocess.CalledProcessError as e:
224 bb.fatal("Unable to update the package index files. Command '%s' "
225 "returned %d:\n%s" % (e.cmd, e.returncode, e.output.decode("utf-8")))
226
227 self.deploy_dir_unlock()
228
229 def install(self, pkgs, attempt_only=False, hard_depends_only=False):
230 if attempt_only and len(pkgs) == 0:
231 return
232
233 os.environ['APT_CONFIG'] = self.apt_conf_file
234
235 extra_args = ""
236 if hard_depends_only:
237 extra_args = "--no-install-recommends"
238
239 cmd = "%s %s install --allow-downgrades --allow-remove-essential --allow-change-held-packages --allow-unauthenticated --no-remove %s %s" % \
240 (self.apt_get_cmd, self.apt_args, extra_args, ' '.join(pkgs))
241
242 try:
243 bb.note("Installing the following packages: %s" % ' '.join(pkgs))
244 output = subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
245 bb.note(output.decode("utf-8"))
246 except subprocess.CalledProcessError as e:
247 e_output = e.output.decode("utf-8")
248 extra_info = ""
249 for e_line in e_output.split('\n'):
250 if 'has no installation candidate' in e_line or 'Unable to locate package' in e_line:
251 match = re.search(r"E: Package '([a-z0-9+\-\._]+)' has no installation candidate", e_line)
252 if match:
253 pkg = match.group(1)
254 else:
255 pkg = re.search(r"E: Unable to locate package ([a-z0-9+\-\._]+)", e_line).group(1)
256 extra_info += self.get_missing_pkg_reason(pkg)
257 (bb.fatal, bb.warn)[attempt_only]("Unable to install packages. "
258 "Command '%s' returned %d:\n%s%s" %
259 (cmd, e.returncode, e_output, extra_info))
260
261 # rename *.dpkg-new files/dirs
262 for root, dirs, files in os.walk(self.target_rootfs):
263 for dir in dirs:
264 new_dir = re.sub(r"\.dpkg-new", "", dir)
265 if dir != new_dir:
266 bb.utils.rename(os.path.join(root, dir),
267 os.path.join(root, new_dir))
268
269 for file in files:
270 new_file = re.sub(r"\.dpkg-new", "", file)
271 if file != new_file:
272 bb.utils.rename(os.path.join(root, file),
273 os.path.join(root, new_file))
274
275
276 def remove(self, pkgs, with_dependencies=True):
277 if not pkgs:
278 return
279
280 os.environ['D'] = self.target_rootfs
281 os.environ['OFFLINE_ROOT'] = self.target_rootfs
282 os.environ['IPKG_OFFLINE_ROOT'] = self.target_rootfs
283 os.environ['OPKG_OFFLINE_ROOT'] = self.target_rootfs
284 os.environ['INTERCEPT_DIR'] = self.intercepts_dir
285
286 if with_dependencies:
287 os.environ['APT_CONFIG'] = self.apt_conf_file
288 cmd = "%s purge %s" % (self.apt_get_cmd, ' '.join(pkgs))
289 else:
290 cmd = "%s --admindir=%s/var/lib/dpkg --instdir=%s" \
291 " -P --force-depends %s" % \
292 (bb.utils.which(os.getenv('PATH'), "dpkg"),
293 self.target_rootfs, self.target_rootfs, ' '.join(pkgs))
294
295 try:
296 subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
297 except subprocess.CalledProcessError as e:
298 bb.fatal("Unable to remove packages. Command '%s' "
299 "returned %d:\n%s" % (e.cmd, e.returncode, e.output.decode("utf-8")))
300
301 def write_index(self):
302 self.deploy_dir_lock()
303
304 result = self.indexer.write_index()
305
306 self.deploy_dir_unlock()
307
308 if result is not None:
309 bb.fatal(result)
310
311 def insert_feeds_uris(self, feed_uris, feed_base_paths, feed_archs):
312 if feed_uris == "":
313 return
314
315
316 sources_conf = os.path.join("%s/etc/apt/sources.list"
317 % self.target_rootfs)
318 if not os.path.exists(os.path.dirname(sources_conf)):
319 return
320
321 arch_list = []
322
323 if feed_archs is None:
324 for arch in self.all_arch_list:
325 if not os.path.exists(os.path.join(self.deploy_dir, arch)):
326 continue
327 arch_list.append(arch)
328 else:
329 arch_list = feed_archs.split()
330
331 feed_uris = self.construct_uris(feed_uris.split(), feed_base_paths.split())
332
333 with open(sources_conf, "w+") as sources_file:
334 for uri in feed_uris:
335 if arch_list:
336 for arch in arch_list:
337 bb.note('Adding dpkg channel at (%s)' % uri)
338 sources_file.write("deb [trusted=yes] %s/%s ./\n" %
339 (uri, arch))
340 else:
341 bb.note('Adding dpkg channel at (%s)' % uri)
342 sources_file.write("deb [trusted=yes] %s ./\n" % uri)
343
344 def _create_configs(self, archs, base_archs):
345 base_archs = re.sub(r"_", r"-", base_archs)
346
347 if os.path.exists(self.apt_conf_dir):
348 bb.utils.remove(self.apt_conf_dir, True)
349
350 bb.utils.mkdirhier(self.apt_conf_dir)
351 bb.utils.mkdirhier(self.apt_conf_dir + "/lists/partial/")
352 bb.utils.mkdirhier(self.apt_conf_dir + "/apt.conf.d/")
353 bb.utils.mkdirhier(self.apt_conf_dir + "/preferences.d/")
354
355 arch_list = []
356 for arch in self.all_arch_list:
357 if not os.path.exists(os.path.join(self.deploy_dir, arch)):
358 continue
359 arch_list.append(arch)
360
361 with open(os.path.join(self.apt_conf_dir, "preferences"), "w+") as prefs_file:
362 priority = 801
363 for arch in arch_list:
364 prefs_file.write(
365 "Package: *\n"
366 "Pin: release l=%s\n"
367 "Pin-Priority: %d\n\n" % (arch, priority))
368
369 priority += 5
370
371 pkg_exclude = self.d.getVar('PACKAGE_EXCLUDE') or ""
372 for pkg in pkg_exclude.split():
373 prefs_file.write(
374 "Package: %s\n"
375 "Pin: release *\n"
376 "Pin-Priority: -1\n\n" % pkg)
377
378 arch_list.reverse()
379
380 with open(os.path.join(self.apt_conf_dir, "sources.list"), "w+") as sources_file:
381 for arch in arch_list:
382 sources_file.write("deb [trusted=yes] file:%s/ ./\n" %
383 os.path.join(self.deploy_dir, arch))
384
385 base_arch_list = base_archs.split()
386 multilib_variants = self.d.getVar("MULTILIB_VARIANTS");
387 for variant in multilib_variants.split():
388 localdata = bb.data.createCopy(self.d)
389 variant_tune = localdata.getVar("DEFAULTTUNE:virtclass-multilib-" + variant, False)
390 orig_arch = localdata.getVar("DPKG_ARCH")
391 localdata.setVar("DEFAULTTUNE", variant_tune)
392 variant_arch = localdata.getVar("DPKG_ARCH")
393 if variant_arch not in base_arch_list:
394 base_arch_list.append(variant_arch)
395
396 with open(self.apt_conf_file, "w+") as apt_conf:
397 with open(self.d.expand("${STAGING_ETCDIR_NATIVE}/apt/apt.conf.sample")) as apt_conf_sample:
398 for line in apt_conf_sample.read().split("\n"):
399 match_arch = re.match(r" Architecture \".*\";$", line)
400 architectures = ""
401 if match_arch:
402 for base_arch in base_arch_list:
403 architectures += "\"%s\";" % base_arch
404 apt_conf.write(" Architectures {%s};\n" % architectures);
405 apt_conf.write(" Architecture \"%s\";\n" % base_archs)
406 else:
407 line = re.sub(r"#ROOTFS#", self.target_rootfs, line)
408 line = re.sub(r"#APTCONF#", self.apt_conf_dir, line)
409 apt_conf.write(line + "\n")
410
411 target_dpkg_dir = "%s/var/lib/dpkg" % self.target_rootfs
412 bb.utils.mkdirhier(os.path.join(target_dpkg_dir, "info"))
413
414 bb.utils.mkdirhier(os.path.join(target_dpkg_dir, "updates"))
415
416 if not os.path.exists(os.path.join(target_dpkg_dir, "status")):
417 open(os.path.join(target_dpkg_dir, "status"), "w+").close()
418 if not os.path.exists(os.path.join(target_dpkg_dir, "available")):
419 open(os.path.join(target_dpkg_dir, "available"), "w+").close()
420
421 def remove_packaging_data(self):
422 bb.utils.remove(self.target_rootfs + self.d.getVar('opkglibdir'), True)
423 bb.utils.remove(self.target_rootfs + "/var/lib/dpkg/", True)
424
425 def fix_broken_dependencies(self):
426 os.environ['APT_CONFIG'] = self.apt_conf_file
427
428 cmd = "%s %s --allow-unauthenticated -f install" % (self.apt_get_cmd, self.apt_args)
429
430 try:
431 subprocess.check_output(cmd.split(), stderr=subprocess.STDOUT)
432 except subprocess.CalledProcessError as e:
433 bb.fatal("Cannot fix broken dependencies. Command '%s' "
434 "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
435
436 def list_installed(self):
437 return PMPkgsList(self.d, self.target_rootfs).list_pkgs()
438
439 def package_info(self, pkg):
440 """
441 Returns a dictionary with the package info.
442 """
443 cmd = "%s show %s" % (self.apt_cache_cmd, pkg)
444 pkg_info = self._common_package_info(cmd)
445
446 pkg_arch = pkg_info[pkg]["pkgarch"]
447 pkg_filename = pkg_info[pkg]["filename"]
448 pkg_info[pkg]["filepath"] = \
449 os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
450
451 return pkg_info
diff --git a/meta/lib/oe/package_manager/deb/manifest.py b/meta/lib/oe/package_manager/deb/manifest.py
deleted file mode 100644
index 72983bae98..0000000000
--- a/meta/lib/oe/package_manager/deb/manifest.py
+++ /dev/null
@@ -1,28 +0,0 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6
7from oe.manifest import Manifest
8
9class PkgManifest(Manifest):
10 def create_initial(self):
11 with open(self.initial_manifest, "w+") as manifest:
12 manifest.write(self.initial_manifest_file_header)
13
14 for var in self.var_maps[self.manifest_type]:
15 pkg_list = self.d.getVar(var)
16
17 if pkg_list is None:
18 continue
19
20 for pkg in pkg_list.split():
21 manifest.write("%s,%s\n" %
22 (self.var_maps[self.manifest_type][var], pkg))
23
24 def create_final(self):
25 pass
26
27 def create_full(self, pm):
28 pass
diff --git a/meta/lib/oe/package_manager/deb/rootfs.py b/meta/lib/oe/package_manager/deb/rootfs.py
deleted file mode 100644
index 1e25b64ed9..0000000000
--- a/meta/lib/oe/package_manager/deb/rootfs.py
+++ /dev/null
@@ -1,212 +0,0 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6
7import re
8import shutil
9from oe.rootfs import Rootfs
10from oe.manifest import Manifest
11from oe.utils import execute_pre_post_process
12from oe.package_manager.deb.manifest import PkgManifest
13from oe.package_manager.deb import DpkgPM
14
15class DpkgOpkgRootfs(Rootfs):
16 def __init__(self, d, progress_reporter=None, logcatcher=None):
17 super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
18
19 def _get_pkgs_postinsts(self, status_file):
20 def _get_pkg_depends_list(pkg_depends):
21 pkg_depends_list = []
22 # filter version requirements like libc (>= 1.1)
23 for dep in pkg_depends.split(', '):
24 m_dep = re.match(r"^(.*) \(.*\)$", dep)
25 if m_dep:
26 dep = m_dep.group(1)
27 pkg_depends_list.append(dep)
28
29 return pkg_depends_list
30
31 pkgs = {}
32 pkg_name = ""
33 pkg_status_match = False
34 pkg_depends = ""
35
36 with open(status_file) as status:
37 data = status.read()
38 status.close()
39 for line in data.split('\n'):
40 m_pkg = re.match(r"^Package: (.*)", line)
41 m_status = re.match(r"^Status:.*unpacked", line)
42 m_depends = re.match(r"^Depends: (.*)", line)
43
44 #Only one of m_pkg, m_status or m_depends is not None at time
45 #If m_pkg is not None, we started a new package
46 if m_pkg is not None:
47 #Get Package name
48 pkg_name = m_pkg.group(1)
49 #Make sure we reset other variables
50 pkg_status_match = False
51 pkg_depends = ""
52 elif m_status is not None:
53 #New status matched
54 pkg_status_match = True
55 elif m_depends is not None:
56 #New depends macthed
57 pkg_depends = m_depends.group(1)
58 else:
59 pass
60
61 #Now check if we can process package depends and postinst
62 if "" != pkg_name and pkg_status_match:
63 pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
64 else:
65 #Not enough information
66 pass
67
68 # remove package dependencies not in postinsts
69 pkg_names = list(pkgs.keys())
70 for pkg_name in pkg_names:
71 deps = pkgs[pkg_name][:]
72
73 for d in deps:
74 if d not in pkg_names:
75 pkgs[pkg_name].remove(d)
76
77 return pkgs
78
79 def _get_delayed_postinsts_common(self, status_file):
80 def _dep_resolve(graph, node, resolved, seen):
81 seen.append(node)
82
83 for edge in graph[node]:
84 if edge not in resolved:
85 if edge in seen:
86 raise RuntimeError("Packages %s and %s have " \
87 "a circular dependency in postinsts scripts." \
88 % (node, edge))
89 _dep_resolve(graph, edge, resolved, seen)
90
91 resolved.append(node)
92
93 pkg_list = []
94
95 pkgs = None
96 if not self.d.getVar('PACKAGE_INSTALL').strip():
97 bb.note("Building empty image")
98 else:
99 pkgs = self._get_pkgs_postinsts(status_file)
100 if pkgs:
101 root = "__packagegroup_postinst__"
102 pkgs[root] = list(pkgs.keys())
103 _dep_resolve(pkgs, root, pkg_list, [])
104 pkg_list.remove(root)
105
106 if len(pkg_list) == 0:
107 return None
108
109 return pkg_list
110
111 def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
112 if bb.utils.contains("IMAGE_FEATURES", "package-management",
113 True, False, self.d):
114 return
115 num = 0
116 for p in self._get_delayed_postinsts():
117 bb.utils.mkdirhier(dst_postinst_dir)
118
119 if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
120 shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
121 os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
122
123 num += 1
124
125class PkgRootfs(DpkgOpkgRootfs):
126 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
127 super(PkgRootfs, self).__init__(d, progress_reporter, logcatcher)
128 self.log_check_regex = '^E:'
129 self.log_check_expected_regexes = \
130 [
131 "^E: Unmet dependencies."
132 ]
133
134 bb.utils.remove(self.image_rootfs, True)
135 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
136 self.manifest = PkgManifest(d, manifest_dir)
137 self.pm = DpkgPM(d, d.getVar('IMAGE_ROOTFS'),
138 d.getVar('PACKAGE_ARCHS'),
139 d.getVar('DPKG_ARCH'))
140
141
142 def _create(self):
143 pkgs_to_install = self.manifest.parse_initial_manifest()
144 deb_pre_process_cmds = self.d.getVar('DEB_PREPROCESS_COMMANDS')
145 deb_post_process_cmds = self.d.getVar('DEB_POSTPROCESS_COMMANDS')
146
147 alt_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/alternatives")
148 bb.utils.mkdirhier(alt_dir)
149
150 # update PM index files
151 self.pm.write_index()
152
153 execute_pre_post_process(self.d, deb_pre_process_cmds)
154
155 if self.progress_reporter:
156 self.progress_reporter.next_stage()
157 # Don't support incremental, so skip that
158 self.progress_reporter.next_stage()
159
160 self.pm.update()
161
162 if self.progress_reporter:
163 self.progress_reporter.next_stage()
164
165 for pkg_type in self.install_order:
166 if pkg_type in pkgs_to_install:
167 self.pm.install(pkgs_to_install[pkg_type],
168 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
169 self.pm.fix_broken_dependencies()
170
171 if self.progress_reporter:
172 # Don't support attemptonly, so skip that
173 self.progress_reporter.next_stage()
174 self.progress_reporter.next_stage()
175
176 self.pm.install_complementary()
177
178 if self.progress_reporter:
179 self.progress_reporter.next_stage()
180
181 self._setup_dbg_rootfs(['/var/lib/dpkg'])
182
183 self.pm.fix_broken_dependencies()
184
185 self.pm.mark_packages("installed")
186
187 self.pm.run_pre_post_installs()
188
189 execute_pre_post_process(self.d, deb_post_process_cmds)
190
191 if self.progress_reporter:
192 self.progress_reporter.next_stage()
193
194 @staticmethod
195 def _depends_list():
196 return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMANDS']
197
198 def _get_delayed_postinsts(self):
199 status_file = self.image_rootfs + "/var/lib/dpkg/status"
200 return self._get_delayed_postinsts_common(status_file)
201
202 def _save_postinsts(self):
203 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
204 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
205 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
206
207 def _log_check(self):
208 self._log_check_warn()
209 self._log_check_error()
210
211 def _cleanup(self):
212 pass
diff --git a/meta/lib/oe/package_manager/deb/sdk.py b/meta/lib/oe/package_manager/deb/sdk.py
deleted file mode 100644
index 6f3005053e..0000000000
--- a/meta/lib/oe/package_manager/deb/sdk.py
+++ /dev/null
@@ -1,107 +0,0 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6
7import glob
8import shutil
9from oe.utils import execute_pre_post_process
10from oe.sdk import Sdk
11from oe.manifest import Manifest
12from oe.package_manager.deb import DpkgPM
13from oe.package_manager.deb.manifest import PkgManifest
14
15class PkgSdk(Sdk):
16 def __init__(self, d, manifest_dir=None):
17 super(PkgSdk, self).__init__(d, manifest_dir)
18
19 self.target_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET"), "apt")
20 self.host_conf_dir = os.path.join(self.d.getVar("APTCONF_TARGET"), "apt-sdk")
21
22
23 self.target_manifest = PkgManifest(d, self.manifest_dir,
24 Manifest.MANIFEST_TYPE_SDK_TARGET)
25 self.host_manifest = PkgManifest(d, self.manifest_dir,
26 Manifest.MANIFEST_TYPE_SDK_HOST)
27
28 deb_repo_workdir = "oe-sdk-repo"
29 if "sdk_ext" in d.getVar("BB_RUNTASK"):
30 deb_repo_workdir = "oe-sdk-ext-repo"
31
32 self.target_pm = DpkgPM(d, self.sdk_target_sysroot,
33 self.d.getVar("PACKAGE_ARCHS"),
34 self.d.getVar("DPKG_ARCH"),
35 self.target_conf_dir,
36 deb_repo_workdir=deb_repo_workdir)
37
38 self.host_pm = DpkgPM(d, self.sdk_host_sysroot,
39 self.d.getVar("SDK_PACKAGE_ARCHS"),
40 self.d.getVar("DEB_SDK_ARCH"),
41 self.host_conf_dir,
42 deb_repo_workdir=deb_repo_workdir)
43
44 def _copy_apt_dir_to(self, dst_dir):
45 staging_etcdir_native = self.d.getVar("STAGING_ETCDIR_NATIVE")
46
47 self.remove(dst_dir, True)
48
49 shutil.copytree(os.path.join(staging_etcdir_native, "apt"), dst_dir)
50
51 def _populate_sysroot(self, pm, manifest):
52 pkgs_to_install = manifest.parse_initial_manifest()
53
54 pm.write_index()
55 pm.update()
56
57 for pkg_type in self.install_order:
58 if pkg_type in pkgs_to_install:
59 pm.install(pkgs_to_install[pkg_type],
60 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
61
62 def _populate(self):
63 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_PRE_TARGET_COMMAND"))
64
65 bb.note("Installing TARGET packages")
66 self._populate_sysroot(self.target_pm, self.target_manifest)
67
68 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY'))
69
70 self.target_pm.run_pre_post_installs()
71
72 env_bkp = os.environ.copy()
73 os.environ['PATH'] = self.d.expand("${COREBASE}/scripts/nativesdk-intercept") + \
74 os.pathsep + os.environ["PATH"]
75
76 self.target_pm.run_intercepts(populate_sdk='target')
77 os.environ.update(env_bkp)
78
79 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND"))
80
81 self._copy_apt_dir_to(os.path.join(self.sdk_target_sysroot, "etc", "apt"))
82
83 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
84 self.target_pm.remove_packaging_data()
85
86 bb.note("Installing NATIVESDK packages")
87 self._populate_sysroot(self.host_pm, self.host_manifest)
88 self.install_locales(self.host_pm)
89
90 self.host_pm.run_pre_post_installs()
91
92 self.host_pm.run_intercepts(populate_sdk='host')
93
94 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND"))
95
96 self._copy_apt_dir_to(os.path.join(self.sdk_output, self.sdk_native_path,
97 "etc", "apt"))
98
99 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
100 self.host_pm.remove_packaging_data()
101
102 native_dpkg_state_dir = os.path.join(self.sdk_output, self.sdk_native_path,
103 "var", "lib", "dpkg")
104 self.mkdirhier(native_dpkg_state_dir)
105 for f in glob.glob(os.path.join(self.sdk_output, "var", "lib", "dpkg", "*")):
106 self.movefile(f, native_dpkg_state_dir)
107 self.remove(os.path.join(self.sdk_output, "var"), True)