summaryrefslogtreecommitdiffstats
path: root/meta/lib/oe/package_manager
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oe/package_manager')
-rw-r--r--meta/lib/oe/package_manager/__init__.py109
-rw-r--r--meta/lib/oe/package_manager/common_deb_ipk.py97
-rw-r--r--meta/lib/oe/package_manager/deb/__init__.py122
-rw-r--r--meta/lib/oe/package_manager/deb/manifest.py2
-rw-r--r--meta/lib/oe/package_manager/deb/rootfs.py2
-rw-r--r--meta/lib/oe/package_manager/deb/sdk.py11
-rw-r--r--meta/lib/oe/package_manager/ipk/__init__.py113
-rw-r--r--meta/lib/oe/package_manager/ipk/manifest.py3
-rw-r--r--meta/lib/oe/package_manager/ipk/rootfs.py41
-rw-r--r--meta/lib/oe/package_manager/ipk/sdk.py11
-rw-r--r--meta/lib/oe/package_manager/rpm/__init__.py53
-rw-r--r--meta/lib/oe/package_manager/rpm/manifest.py2
-rw-r--r--meta/lib/oe/package_manager/rpm/rootfs.py4
-rw-r--r--meta/lib/oe/package_manager/rpm/sdk.py10
14 files changed, 282 insertions, 298 deletions
diff --git a/meta/lib/oe/package_manager/__init__.py b/meta/lib/oe/package_manager/__init__.py
index 8e7128b195..2100a97c12 100644
--- a/meta/lib/oe/package_manager/__init__.py
+++ b/meta/lib/oe/package_manager/__init__.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -90,7 +92,7 @@ def opkg_query(cmd_output):
90 92
91def failed_postinsts_abort(pkgs, log_path): 93def failed_postinsts_abort(pkgs, log_path):
92 bb.fatal("""Postinstall scriptlets of %s have failed. If the intention is to defer them to first boot, 94 bb.fatal("""Postinstall scriptlets of %s have failed. If the intention is to defer them to first boot,
93then please place them into pkg_postinst_ontarget_${PN} (). 95then please place them into pkg_postinst_ontarget:${PN} ().
94Deferring to first boot via 'exit 1' is no longer supported. 96Deferring to first boot via 'exit 1' is no longer supported.
95Details of the failure are in %s.""" %(pkgs, log_path)) 97Details of the failure are in %s.""" %(pkgs, log_path))
96 98
@@ -120,7 +122,8 @@ def generate_locale_archive(d, rootfs, target_arch, localedir):
120 "riscv32": ["--uint32-align=4", "--little-endian"], 122 "riscv32": ["--uint32-align=4", "--little-endian"],
121 "i586": ["--uint32-align=4", "--little-endian"], 123 "i586": ["--uint32-align=4", "--little-endian"],
122 "i686": ["--uint32-align=4", "--little-endian"], 124 "i686": ["--uint32-align=4", "--little-endian"],
123 "x86_64": ["--uint32-align=4", "--little-endian"] 125 "x86_64": ["--uint32-align=4", "--little-endian"],
126 "loongarch64": ["--uint32-align=4", "--little-endian"]
124 } 127 }
125 if target_arch in locale_arch_options: 128 if target_arch in locale_arch_options:
126 arch_options = locale_arch_options[target_arch] 129 arch_options = locale_arch_options[target_arch]
@@ -189,7 +192,7 @@ class PackageManager(object, metaclass=ABCMeta):
189 bb.utils.remove(self.intercepts_dir, True) 192 bb.utils.remove(self.intercepts_dir, True)
190 bb.utils.mkdirhier(self.intercepts_dir) 193 bb.utils.mkdirhier(self.intercepts_dir)
191 for intercept in postinst_intercepts: 194 for intercept in postinst_intercepts:
192 bb.utils.copyfile(intercept, os.path.join(self.intercepts_dir, os.path.basename(intercept))) 195 shutil.copy(intercept, os.path.join(self.intercepts_dir, os.path.basename(intercept)))
193 196
194 @abstractmethod 197 @abstractmethod
195 def _handle_intercept_failure(self, failed_script): 198 def _handle_intercept_failure(self, failed_script):
@@ -266,7 +269,7 @@ class PackageManager(object, metaclass=ABCMeta):
266 pass 269 pass
267 270
268 @abstractmethod 271 @abstractmethod
269 def install(self, pkgs, attempt_only=False): 272 def install(self, pkgs, attempt_only=False, hard_depends_only=False):
270 """ 273 """
271 Install a list of packages. 'pkgs' is a list object. If 'attempt_only' is 274 Install a list of packages. 'pkgs' is a list object. If 'attempt_only' is
272 True, installation failures are ignored. 275 True, installation failures are ignored.
@@ -321,7 +324,7 @@ class PackageManager(object, metaclass=ABCMeta):
321 # TODO don't have sdk here but have a property on the superclass 324 # TODO don't have sdk here but have a property on the superclass
322 # (and respect in install_complementary) 325 # (and respect in install_complementary)
323 if sdk: 326 if sdk:
324 pkgdatadir = self.d.expand("${TMPDIR}/pkgdata/${SDK_SYS}") 327 pkgdatadir = self.d.getVar("PKGDATA_DIR_SDK")
325 else: 328 else:
326 pkgdatadir = self.d.getVar("PKGDATA_DIR") 329 pkgdatadir = self.d.getVar("PKGDATA_DIR")
327 330
@@ -344,10 +347,8 @@ class PackageManager(object, metaclass=ABCMeta):
344 def install_complementary(self, globs=None): 347 def install_complementary(self, globs=None):
345 """ 348 """
346 Install complementary packages based upon the list of currently installed 349 Install complementary packages based upon the list of currently installed
347 packages e.g. locales, *-dev, *-dbg, etc. This will only attempt to install 350 packages e.g. locales, *-dev, *-dbg, etc. Note: every backend needs to
348 these packages, if they don't exist then no error will occur. Note: every 351 call this function explicitly after the normal package installation.
349 backend needs to call this function explicitly after the normal package
350 installation
351 """ 352 """
352 if globs is None: 353 if globs is None:
353 globs = self.d.getVar('IMAGE_INSTALL_COMPLEMENTARY') 354 globs = self.d.getVar('IMAGE_INSTALL_COMPLEMENTARY')
@@ -364,45 +365,43 @@ class PackageManager(object, metaclass=ABCMeta):
364 for complementary_linguas in (self.d.getVar('IMAGE_LINGUAS_COMPLEMENTARY') or "").split(): 365 for complementary_linguas in (self.d.getVar('IMAGE_LINGUAS_COMPLEMENTARY') or "").split():
365 globs += (" " + complementary_linguas) % lang 366 globs += (" " + complementary_linguas) % lang
366 367
367 if globs is None: 368 if globs:
368 return 369 # we need to write the list of installed packages to a file because the
369 370 # oe-pkgdata-util reads it from a file
370 # we need to write the list of installed packages to a file because the 371 with tempfile.NamedTemporaryFile(mode="w+", prefix="installed-pkgs") as installed_pkgs:
371 # oe-pkgdata-util reads it from a file 372 pkgs = self.list_installed()
372 with tempfile.NamedTemporaryFile(mode="w+", prefix="installed-pkgs") as installed_pkgs: 373
373 pkgs = self.list_installed() 374 provided_pkgs = set()
374 375 for pkg in pkgs.values():
375 provided_pkgs = set() 376 provided_pkgs |= set(pkg.get('provs', []))
376 for pkg in pkgs.values(): 377
377 provided_pkgs |= set(pkg.get('provs', [])) 378 output = oe.utils.format_pkg_list(pkgs, "arch")
378 379 installed_pkgs.write(output)
379 output = oe.utils.format_pkg_list(pkgs, "arch") 380 installed_pkgs.flush()
380 installed_pkgs.write(output) 381
381 installed_pkgs.flush() 382 cmd = ["oe-pkgdata-util",
382 383 "-p", self.d.getVar('PKGDATA_DIR'), "glob", installed_pkgs.name,
383 cmd = ["oe-pkgdata-util", 384 globs]
384 "-p", self.d.getVar('PKGDATA_DIR'), "glob", installed_pkgs.name, 385 exclude = self.d.getVar('PACKAGE_EXCLUDE_COMPLEMENTARY')
385 globs] 386 if exclude:
386 exclude = self.d.getVar('PACKAGE_EXCLUDE_COMPLEMENTARY') 387 cmd.extend(['--exclude=' + '|'.join(exclude.split())])
387 if exclude: 388 try:
388 cmd.extend(['--exclude=' + '|'.join(exclude.split())]) 389 bb.note('Running %s' % cmd)
389 try: 390 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
390 bb.note('Running %s' % cmd) 391 stdout, stderr = proc.communicate()
391 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 392 if stderr: bb.note(stderr.decode("utf-8"))
392 stdout, stderr = proc.communicate() 393 complementary_pkgs = stdout.decode("utf-8")
393 if stderr: bb.note(stderr.decode("utf-8")) 394 complementary_pkgs = set(complementary_pkgs.split())
394 complementary_pkgs = stdout.decode("utf-8") 395 skip_pkgs = sorted(complementary_pkgs & provided_pkgs)
395 complementary_pkgs = set(complementary_pkgs.split()) 396 install_pkgs = sorted(complementary_pkgs - provided_pkgs)
396 skip_pkgs = sorted(complementary_pkgs & provided_pkgs) 397 bb.note("Installing complementary packages ... %s (skipped already provided packages %s)" % (
397 install_pkgs = sorted(complementary_pkgs - provided_pkgs) 398 ' '.join(install_pkgs),
398 bb.note("Installing complementary packages ... %s (skipped already provided packages %s)" % ( 399 ' '.join(skip_pkgs)))
399 ' '.join(install_pkgs), 400 self.install(install_pkgs, hard_depends_only=True)
400 ' '.join(skip_pkgs))) 401 except subprocess.CalledProcessError as e:
401 self.install(install_pkgs, attempt_only=True) 402 bb.fatal("Could not compute complementary packages list. Command "
402 except subprocess.CalledProcessError as e: 403 "'%s' returned %d:\n%s" %
403 bb.fatal("Could not compute complementary packages list. Command " 404 (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
404 "'%s' returned %d:\n%s" %
405 (' '.join(cmd), e.returncode, e.output.decode("utf-8")))
406 405
407 if self.d.getVar('IMAGE_LOCALES_ARCHIVE') == '1': 406 if self.d.getVar('IMAGE_LOCALES_ARCHIVE') == '1':
408 target_arch = self.d.getVar('TARGET_ARCH') 407 target_arch = self.d.getVar('TARGET_ARCH')
@@ -448,7 +447,7 @@ class PackageManager(object, metaclass=ABCMeta):
448 return res 447 return res
449 return _append(uris, base_paths) 448 return _append(uris, base_paths)
450 449
451def create_packages_dir(d, subrepo_dir, deploydir, taskname, filterbydependencies): 450def create_packages_dir(d, subrepo_dir, deploydir, taskname, filterbydependencies, include_self=False):
452 """ 451 """
453 Go through our do_package_write_X dependencies and hardlink the packages we depend 452 Go through our do_package_write_X dependencies and hardlink the packages we depend
454 upon into the repo directory. This prevents us seeing other packages that may 453 upon into the repo directory. This prevents us seeing other packages that may
@@ -469,7 +468,10 @@ def create_packages_dir(d, subrepo_dir, deploydir, taskname, filterbydependencie
469 # Detect bitbake -b usage 468 # Detect bitbake -b usage
470 nodeps = d.getVar("BB_LIMITEDDEPS") or False 469 nodeps = d.getVar("BB_LIMITEDDEPS") or False
471 if nodeps or not filterbydependencies: 470 if nodeps or not filterbydependencies:
472 oe.path.symlink(deploydir, subrepo_dir, True) 471 for arch in d.getVar("ALL_MULTILIB_PACKAGE_ARCHS").split() + d.getVar("ALL_MULTILIB_PACKAGE_ARCHS").replace("-", "_").split():
472 target = os.path.join(deploydir + "/" + arch)
473 if os.path.exists(target):
474 oe.path.symlink(target, subrepo_dir + "/" + arch, True)
473 return 475 return
474 476
475 start = None 477 start = None
@@ -482,14 +484,17 @@ def create_packages_dir(d, subrepo_dir, deploydir, taskname, filterbydependencie
482 bb.fatal("Couldn't find ourself in BB_TASKDEPDATA?") 484 bb.fatal("Couldn't find ourself in BB_TASKDEPDATA?")
483 pkgdeps = set() 485 pkgdeps = set()
484 start = [start] 486 start = [start]
485 seen = set(start) 487 if include_self:
488 seen = set()
489 else:
490 seen = set(start)
486 # Support direct dependencies (do_rootfs -> do_package_write_X) 491 # Support direct dependencies (do_rootfs -> do_package_write_X)
487 # or indirect dependencies within PN (do_populate_sdk_ext -> do_rootfs -> do_package_write_X) 492 # or indirect dependencies within PN (do_populate_sdk_ext -> do_rootfs -> do_package_write_X)
488 while start: 493 while start:
489 next = [] 494 next = []
490 for dep2 in start: 495 for dep2 in start:
491 for dep in taskdepdata[dep2][3]: 496 for dep in taskdepdata[dep2][3]:
492 if taskdepdata[dep][0] != pn: 497 if include_self or taskdepdata[dep][0] != pn:
493 if "do_" + taskname in dep: 498 if "do_" + taskname in dep:
494 pkgdeps.add(dep) 499 pkgdeps.add(dep)
495 elif dep not in seen: 500 elif dep not in seen:
diff --git a/meta/lib/oe/package_manager/common_deb_ipk.py b/meta/lib/oe/package_manager/common_deb_ipk.py
new file mode 100644
index 0000000000..6a1e28ee6f
--- /dev/null
+++ b/meta/lib/oe/package_manager/common_deb_ipk.py
@@ -0,0 +1,97 @@
1#
2# Copyright OpenEmbedded Contributors
3#
4# SPDX-License-Identifier: GPL-2.0-only
5#
6
7import glob
8import os
9import subprocess
10import tempfile
11
12import bb
13
14from oe.package_manager import opkg_query, PackageManager
15
16class OpkgDpkgPM(PackageManager):
17 def __init__(self, d, target_rootfs):
18 """
19 This is an abstract class. Do not instantiate this directly.
20 """
21 super(OpkgDpkgPM, self).__init__(d, target_rootfs)
22
23 def package_info(self, pkg):
24 """
25 Returns a dictionary with the package info.
26 """
27 raise NotImplementedError
28
29 def _common_package_info(self, cmd):
30 """
31 "Returns a dictionary with the package info.
32
33 This method extracts the common parts for Opkg and Dpkg
34 """
35
36 proc = subprocess.run(cmd, capture_output=True, encoding="utf-8", shell=True)
37 if proc.returncode:
38 bb.fatal("Unable to list available packages. Command '%s' "
39 "returned %d:\n%s" % (cmd, proc.returncode, proc.stderr))
40 elif proc.stderr:
41 bb.note("Command '%s' returned stderr: %s" % (cmd, proc.stderr))
42
43 return opkg_query(proc.stdout)
44
45 def extract(self, pkg):
46 """
47 Returns the path to a tmpdir where resides the contents of a package.
48
49 Deleting the tmpdir is responsability of the caller.
50 """
51 pkg_info = self.package_info(pkg)
52 if not pkg_info:
53 bb.fatal("Unable to get information for package '%s' while "
54 "trying to extract the package." % pkg)
55
56 ar_cmd = bb.utils.which(os.getenv("PATH"), "ar")
57 tar_cmd = bb.utils.which(os.getenv("PATH"), "tar")
58 pkg_path = pkg_info[pkg]["filepath"]
59
60 if not os.path.isfile(pkg_path):
61 bb.fatal("Unable to extract package for '%s'."
62 "File %s doesn't exists" % (pkg, pkg_path))
63
64 tmp_dir = tempfile.mkdtemp()
65 current_dir = os.getcwd()
66 os.chdir(tmp_dir)
67
68 try:
69 cmd = [ar_cmd, 'x', pkg_path]
70 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
71 data_tar = glob.glob("data.tar.*")
72 if len(data_tar) != 1:
73 bb.fatal("Unable to extract %s package. Failed to identify "
74 "data tarball (found tarballs '%s').",
75 pkg_path, data_tar)
76 data_tar = data_tar[0]
77 cmd = [tar_cmd, 'xf', data_tar]
78 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
79 except subprocess.CalledProcessError as e:
80 bb.utils.remove(tmp_dir, recurse=True)
81 bb.fatal("Unable to extract %s package. Command '%s' "
82 "returned %d:\n%s" % (pkg_path, ' '.join(cmd), e.returncode, e.output.decode("utf-8")))
83 except OSError as e:
84 bb.utils.remove(tmp_dir, recurse=True)
85 bb.fatal("Unable to extract %s package. Command '%s' "
86 "returned %d:\n%s at %s" % (pkg_path, ' '.join(cmd), e.errno, e.strerror, e.filename))
87
88 bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
89 bb.utils.remove(os.path.join(tmp_dir, "debian-binary"))
90 bb.utils.remove(os.path.join(tmp_dir, "control.tar.gz"))
91 bb.utils.remove(os.path.join(tmp_dir, data_tar))
92 os.chdir(current_dir)
93
94 return tmp_dir
95
96 def _handle_intercept_failure(self, registered_pkgs):
97 self.mark_packages("unpacked", registered_pkgs.split())
diff --git a/meta/lib/oe/package_manager/deb/__init__.py b/meta/lib/oe/package_manager/deb/__init__.py
index 2ee68fefb1..e09e81e490 100644
--- a/meta/lib/oe/package_manager/deb/__init__.py
+++ b/meta/lib/oe/package_manager/deb/__init__.py
@@ -1,10 +1,13 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
5import re 7import re
6import subprocess 8import subprocess
7from oe.package_manager import * 9from oe.package_manager import *
10from oe.package_manager.common_deb_ipk import OpkgDpkgPM
8 11
9class DpkgIndexer(Indexer): 12class DpkgIndexer(Indexer):
10 def _create_configs(self): 13 def _create_configs(self):
@@ -53,6 +56,7 @@ class DpkgIndexer(Indexer):
53 56
54 index_cmds = [] 57 index_cmds = []
55 deb_dirs_found = False 58 deb_dirs_found = False
59 index_sign_files = set()
56 for arch in arch_list: 60 for arch in arch_list:
57 arch_dir = os.path.join(self.deploy_dir, arch) 61 arch_dir = os.path.join(self.deploy_dir, arch)
58 if not os.path.isdir(arch_dir): 62 if not os.path.isdir(arch_dir):
@@ -62,7 +66,10 @@ class DpkgIndexer(Indexer):
62 66
63 cmd += "%s -fcn Packages > Packages.gz;" % gzip 67 cmd += "%s -fcn Packages > Packages.gz;" % gzip
64 68
65 with open(os.path.join(arch_dir, "Release"), "w+") as release: 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:
66 release.write("Label: %s\n" % arch) 73 release.write("Label: %s\n" % arch)
67 74
68 cmd += "PSEUDO_UNLOAD=1 %s release . >> Release" % apt_ftparchive 75 cmd += "PSEUDO_UNLOAD=1 %s release . >> Release" % apt_ftparchive
@@ -77,7 +84,16 @@ class DpkgIndexer(Indexer):
77 84
78 oe.utils.multiprocess_launch(create_index, index_cmds, self.d) 85 oe.utils.multiprocess_launch(create_index, index_cmds, self.d)
79 if self.d.getVar('PACKAGE_FEED_SIGN') == '1': 86 if self.d.getVar('PACKAGE_FEED_SIGN') == '1':
80 raise NotImplementedError('Package feed signing not implementd for dpkg') 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)
81 97
82class PMPkgsList(PkgsList): 98class PMPkgsList(PkgsList):
83 99
@@ -96,72 +112,6 @@ class PMPkgsList(PkgsList):
96 112
97 return opkg_query(cmd_output) 113 return opkg_query(cmd_output)
98 114
99class OpkgDpkgPM(PackageManager):
100 def __init__(self, d, target_rootfs):
101 """
102 This is an abstract class. Do not instantiate this directly.
103 """
104 super(OpkgDpkgPM, self).__init__(d, target_rootfs)
105
106 def package_info(self, pkg, cmd):
107 """
108 Returns a dictionary with the package info.
109
110 This method extracts the common parts for Opkg and Dpkg
111 """
112
113 try:
114 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
115 except subprocess.CalledProcessError as e:
116 bb.fatal("Unable to list available packages. Command '%s' "
117 "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
118 return opkg_query(output)
119
120 def extract(self, pkg, pkg_info):
121 """
122 Returns the path to a tmpdir where resides the contents of a package.
123
124 Deleting the tmpdir is responsability of the caller.
125
126 This method extracts the common parts for Opkg and Dpkg
127 """
128
129 ar_cmd = bb.utils.which(os.getenv("PATH"), "ar")
130 tar_cmd = bb.utils.which(os.getenv("PATH"), "tar")
131 pkg_path = pkg_info[pkg]["filepath"]
132
133 if not os.path.isfile(pkg_path):
134 bb.fatal("Unable to extract package for '%s'."
135 "File %s doesn't exists" % (pkg, pkg_path))
136
137 tmp_dir = tempfile.mkdtemp()
138 current_dir = os.getcwd()
139 os.chdir(tmp_dir)
140 data_tar = 'data.tar.xz'
141
142 try:
143 cmd = [ar_cmd, 'x', pkg_path]
144 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
145 cmd = [tar_cmd, 'xf', data_tar]
146 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
147 except subprocess.CalledProcessError as e:
148 bb.utils.remove(tmp_dir, recurse=True)
149 bb.fatal("Unable to extract %s package. Command '%s' "
150 "returned %d:\n%s" % (pkg_path, ' '.join(cmd), e.returncode, e.output.decode("utf-8")))
151 except OSError as e:
152 bb.utils.remove(tmp_dir, recurse=True)
153 bb.fatal("Unable to extract %s package. Command '%s' "
154 "returned %d:\n%s at %s" % (pkg_path, ' '.join(cmd), e.errno, e.strerror, e.filename))
155
156 bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
157 bb.utils.remove(os.path.join(tmp_dir, "debian-binary"))
158 bb.utils.remove(os.path.join(tmp_dir, "control.tar.gz"))
159 os.chdir(current_dir)
160
161 return tmp_dir
162
163 def _handle_intercept_failure(self, registered_pkgs):
164 self.mark_packages("unpacked", registered_pkgs.split())
165 115
166class DpkgPM(OpkgDpkgPM): 116class DpkgPM(OpkgDpkgPM):
167 def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None, deb_repo_workdir="oe-rootfs-repo", filterbydependencies=True): 117 def __init__(self, d, target_rootfs, archs, base_archs, apt_conf_dir=None, deb_repo_workdir="oe-rootfs-repo", filterbydependencies=True):
@@ -214,7 +164,7 @@ class DpkgPM(OpkgDpkgPM):
214 164
215 tmp_sf.write(status) 165 tmp_sf.write(status)
216 166
217 os.rename(status_file + ".tmp", status_file) 167 bb.utils.rename(status_file + ".tmp", status_file)
218 168
219 def run_pre_post_installs(self, package_name=None): 169 def run_pre_post_installs(self, package_name=None):
220 """ 170 """
@@ -276,14 +226,18 @@ class DpkgPM(OpkgDpkgPM):
276 226
277 self.deploy_dir_unlock() 227 self.deploy_dir_unlock()
278 228
279 def install(self, pkgs, attempt_only=False): 229 def install(self, pkgs, attempt_only=False, hard_depends_only=False):
280 if attempt_only and len(pkgs) == 0: 230 if attempt_only and len(pkgs) == 0:
281 return 231 return
282 232
283 os.environ['APT_CONFIG'] = self.apt_conf_file 233 os.environ['APT_CONFIG'] = self.apt_conf_file
284 234
285 cmd = "%s %s install --allow-downgrades --allow-remove-essential --allow-change-held-packages --allow-unauthenticated --no-remove %s" % \ 235 extra_args = ""
286 (self.apt_get_cmd, self.apt_args, ' '.join(pkgs)) 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))
287 241
288 try: 242 try:
289 bb.note("Installing the following packages: %s" % ' '.join(pkgs)) 243 bb.note("Installing the following packages: %s" % ' '.join(pkgs))
@@ -299,13 +253,13 @@ class DpkgPM(OpkgDpkgPM):
299 for dir in dirs: 253 for dir in dirs:
300 new_dir = re.sub(r"\.dpkg-new", "", dir) 254 new_dir = re.sub(r"\.dpkg-new", "", dir)
301 if dir != new_dir: 255 if dir != new_dir:
302 os.rename(os.path.join(root, dir), 256 bb.utils.rename(os.path.join(root, dir),
303 os.path.join(root, new_dir)) 257 os.path.join(root, new_dir))
304 258
305 for file in files: 259 for file in files:
306 new_file = re.sub(r"\.dpkg-new", "", file) 260 new_file = re.sub(r"\.dpkg-new", "", file)
307 if file != new_file: 261 if file != new_file:
308 os.rename(os.path.join(root, file), 262 bb.utils.rename(os.path.join(root, file),
309 os.path.join(root, new_file)) 263 os.path.join(root, new_file))
310 264
311 265
@@ -422,7 +376,7 @@ class DpkgPM(OpkgDpkgPM):
422 multilib_variants = self.d.getVar("MULTILIB_VARIANTS"); 376 multilib_variants = self.d.getVar("MULTILIB_VARIANTS");
423 for variant in multilib_variants.split(): 377 for variant in multilib_variants.split():
424 localdata = bb.data.createCopy(self.d) 378 localdata = bb.data.createCopy(self.d)
425 variant_tune = localdata.getVar("DEFAULTTUNE_virtclass-multilib-" + variant, False) 379 variant_tune = localdata.getVar("DEFAULTTUNE:virtclass-multilib-" + variant, False)
426 orig_arch = localdata.getVar("DPKG_ARCH") 380 orig_arch = localdata.getVar("DPKG_ARCH")
427 localdata.setVar("DEFAULTTUNE", variant_tune) 381 localdata.setVar("DEFAULTTUNE", variant_tune)
428 variant_arch = localdata.getVar("DPKG_ARCH") 382 variant_arch = localdata.getVar("DPKG_ARCH")
@@ -477,7 +431,7 @@ class DpkgPM(OpkgDpkgPM):
477 Returns a dictionary with the package info. 431 Returns a dictionary with the package info.
478 """ 432 """
479 cmd = "%s show %s" % (self.apt_cache_cmd, pkg) 433 cmd = "%s show %s" % (self.apt_cache_cmd, pkg)
480 pkg_info = super(DpkgPM, self).package_info(pkg, cmd) 434 pkg_info = self._common_package_info(cmd)
481 435
482 pkg_arch = pkg_info[pkg]["pkgarch"] 436 pkg_arch = pkg_info[pkg]["pkgarch"]
483 pkg_filename = pkg_info[pkg]["filename"] 437 pkg_filename = pkg_info[pkg]["filename"]
@@ -485,19 +439,3 @@ class DpkgPM(OpkgDpkgPM):
485 os.path.join(self.deploy_dir, pkg_arch, pkg_filename) 439 os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
486 440
487 return pkg_info 441 return pkg_info
488
489 def extract(self, pkg):
490 """
491 Returns the path to a tmpdir where resides the contents of a package.
492
493 Deleting the tmpdir is responsability of the caller.
494 """
495 pkg_info = self.package_info(pkg)
496 if not pkg_info:
497 bb.fatal("Unable to get information for package '%s' while "
498 "trying to extract the package." % pkg)
499
500 tmp_dir = super(DpkgPM, self).extract(pkg, pkg_info)
501 bb.utils.remove(os.path.join(tmp_dir, "data.tar.xz"))
502
503 return tmp_dir
diff --git a/meta/lib/oe/package_manager/deb/manifest.py b/meta/lib/oe/package_manager/deb/manifest.py
index d8eab24a06..72983bae98 100644
--- a/meta/lib/oe/package_manager/deb/manifest.py
+++ b/meta/lib/oe/package_manager/deb/manifest.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
diff --git a/meta/lib/oe/package_manager/deb/rootfs.py b/meta/lib/oe/package_manager/deb/rootfs.py
index 8fbaca11d6..1e25b64ed9 100644
--- a/meta/lib/oe/package_manager/deb/rootfs.py
+++ b/meta/lib/oe/package_manager/deb/rootfs.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
diff --git a/meta/lib/oe/package_manager/deb/sdk.py b/meta/lib/oe/package_manager/deb/sdk.py
index 9859d8f32d..6f3005053e 100644
--- a/meta/lib/oe/package_manager/deb/sdk.py
+++ b/meta/lib/oe/package_manager/deb/sdk.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -65,7 +67,14 @@ class PkgSdk(Sdk):
65 67
66 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY')) 68 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY'))
67 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
68 self.target_pm.run_intercepts(populate_sdk='target') 76 self.target_pm.run_intercepts(populate_sdk='target')
77 os.environ.update(env_bkp)
69 78
70 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND")) 79 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND"))
71 80
@@ -78,6 +87,8 @@ class PkgSdk(Sdk):
78 self._populate_sysroot(self.host_pm, self.host_manifest) 87 self._populate_sysroot(self.host_pm, self.host_manifest)
79 self.install_locales(self.host_pm) 88 self.install_locales(self.host_pm)
80 89
90 self.host_pm.run_pre_post_installs()
91
81 self.host_pm.run_intercepts(populate_sdk='host') 92 self.host_pm.run_intercepts(populate_sdk='host')
82 93
83 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND")) 94 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_HOST_COMMAND"))
diff --git a/meta/lib/oe/package_manager/ipk/__init__.py b/meta/lib/oe/package_manager/ipk/__init__.py
index da488c1c7f..3d998e52ff 100644
--- a/meta/lib/oe/package_manager/ipk/__init__.py
+++ b/meta/lib/oe/package_manager/ipk/__init__.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -6,6 +8,7 @@ import re
6import shutil 8import shutil
7import subprocess 9import subprocess
8from oe.package_manager import * 10from oe.package_manager import *
11from oe.package_manager.common_deb_ipk import OpkgDpkgPM
9 12
10class OpkgIndexer(Indexer): 13class OpkgIndexer(Indexer):
11 def write_index(self): 14 def write_index(self):
@@ -14,6 +17,7 @@ class OpkgIndexer(Indexer):
14 ] 17 ]
15 18
16 opkg_index_cmd = bb.utils.which(os.getenv('PATH'), "opkg-make-index") 19 opkg_index_cmd = bb.utils.which(os.getenv('PATH'), "opkg-make-index")
20 opkg_index_cmd_extra_params = self.d.getVar('OPKG_MAKE_INDEX_EXTRA_PARAMS') or ""
17 if self.d.getVar('PACKAGE_FEED_SIGN') == '1': 21 if self.d.getVar('PACKAGE_FEED_SIGN') == '1':
18 signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND')) 22 signer = get_signer(self.d, self.d.getVar('PACKAGE_FEED_GPG_BACKEND'))
19 else: 23 else:
@@ -39,8 +43,8 @@ class OpkgIndexer(Indexer):
39 if not os.path.exists(pkgs_file): 43 if not os.path.exists(pkgs_file):
40 open(pkgs_file, "w").close() 44 open(pkgs_file, "w").close()
41 45
42 index_cmds.add('%s --checksum md5 --checksum sha256 -r %s -p %s -m %s' % 46 index_cmds.add('%s --checksum md5 --checksum sha256 -r %s -p %s -m %s %s' %
43 (opkg_index_cmd, pkgs_file, pkgs_file, pkgs_dir)) 47 (opkg_index_cmd, pkgs_file, pkgs_file, pkgs_dir, opkg_index_cmd_extra_params))
44 48
45 index_sign_files.add(pkgs_file) 49 index_sign_files.add(pkgs_file)
46 50
@@ -87,74 +91,6 @@ class PMPkgsList(PkgsList):
87 return opkg_query(cmd_output) 91 return opkg_query(cmd_output)
88 92
89 93
90
91class OpkgDpkgPM(PackageManager):
92 def __init__(self, d, target_rootfs):
93 """
94 This is an abstract class. Do not instantiate this directly.
95 """
96 super(OpkgDpkgPM, self).__init__(d, target_rootfs)
97
98 def package_info(self, pkg, cmd):
99 """
100 Returns a dictionary with the package info.
101
102 This method extracts the common parts for Opkg and Dpkg
103 """
104
105 try:
106 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True).decode("utf-8")
107 except subprocess.CalledProcessError as e:
108 bb.fatal("Unable to list available packages. Command '%s' "
109 "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8")))
110 return opkg_query(output)
111
112 def extract(self, pkg, pkg_info):
113 """
114 Returns the path to a tmpdir where resides the contents of a package.
115
116 Deleting the tmpdir is responsability of the caller.
117
118 This method extracts the common parts for Opkg and Dpkg
119 """
120
121 ar_cmd = bb.utils.which(os.getenv("PATH"), "ar")
122 tar_cmd = bb.utils.which(os.getenv("PATH"), "tar")
123 pkg_path = pkg_info[pkg]["filepath"]
124
125 if not os.path.isfile(pkg_path):
126 bb.fatal("Unable to extract package for '%s'."
127 "File %s doesn't exists" % (pkg, pkg_path))
128
129 tmp_dir = tempfile.mkdtemp()
130 current_dir = os.getcwd()
131 os.chdir(tmp_dir)
132 data_tar = 'data.tar.xz'
133
134 try:
135 cmd = [ar_cmd, 'x', pkg_path]
136 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
137 cmd = [tar_cmd, 'xf', data_tar]
138 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
139 except subprocess.CalledProcessError as e:
140 bb.utils.remove(tmp_dir, recurse=True)
141 bb.fatal("Unable to extract %s package. Command '%s' "
142 "returned %d:\n%s" % (pkg_path, ' '.join(cmd), e.returncode, e.output.decode("utf-8")))
143 except OSError as e:
144 bb.utils.remove(tmp_dir, recurse=True)
145 bb.fatal("Unable to extract %s package. Command '%s' "
146 "returned %d:\n%s at %s" % (pkg_path, ' '.join(cmd), e.errno, e.strerror, e.filename))
147
148 bb.note("Extracted %s to %s" % (pkg_path, tmp_dir))
149 bb.utils.remove(os.path.join(tmp_dir, "debian-binary"))
150 bb.utils.remove(os.path.join(tmp_dir, "control.tar.gz"))
151 os.chdir(current_dir)
152
153 return tmp_dir
154
155 def _handle_intercept_failure(self, registered_pkgs):
156 self.mark_packages("unpacked", registered_pkgs.split())
157
158class OpkgPM(OpkgDpkgPM): 94class OpkgPM(OpkgDpkgPM):
159 def __init__(self, d, target_rootfs, config_file, archs, task_name='target', ipk_repo_workdir="oe-rootfs-repo", filterbydependencies=True, prepare_index=True): 95 def __init__(self, d, target_rootfs, config_file, archs, task_name='target', ipk_repo_workdir="oe-rootfs-repo", filterbydependencies=True, prepare_index=True):
160 super(OpkgPM, self).__init__(d, target_rootfs) 96 super(OpkgPM, self).__init__(d, target_rootfs)
@@ -213,7 +149,7 @@ class OpkgPM(OpkgDpkgPM):
213 149
214 tmp_sf.write(status) 150 tmp_sf.write(status)
215 151
216 os.rename(status_file + ".tmp", status_file) 152 bb.utils.rename(status_file + ".tmp", status_file)
217 153
218 def _create_custom_config(self): 154 def _create_custom_config(self):
219 bb.note("Building from feeds activated!") 155 bb.note("Building from feeds activated!")
@@ -243,7 +179,7 @@ class OpkgPM(OpkgDpkgPM):
243 """ 179 """
244 if (self.d.getVar('FEED_DEPLOYDIR_BASE_URI') or "") != "": 180 if (self.d.getVar('FEED_DEPLOYDIR_BASE_URI') or "") != "":
245 for arch in self.pkg_archs.split(): 181 for arch in self.pkg_archs.split():
246 cfg_file_name = os.path.join(self.target_rootfs, 182 cfg_file_name = oe.path.join(self.target_rootfs,
247 self.d.getVar("sysconfdir"), 183 self.d.getVar("sysconfdir"),
248 "opkg", 184 "opkg",
249 "local-%s-feed.conf" % arch) 185 "local-%s-feed.conf" % arch)
@@ -337,7 +273,7 @@ class OpkgPM(OpkgDpkgPM):
337 273
338 self.deploy_dir_unlock() 274 self.deploy_dir_unlock()
339 275
340 def install(self, pkgs, attempt_only=False): 276 def install(self, pkgs, attempt_only=False, hard_depends_only=False):
341 if not pkgs: 277 if not pkgs:
342 return 278 return
343 279
@@ -346,6 +282,8 @@ class OpkgPM(OpkgDpkgPM):
346 cmd += " --add-exclude %s" % exclude 282 cmd += " --add-exclude %s" % exclude
347 for bad_recommendation in (self.d.getVar("BAD_RECOMMENDATIONS") or "").split(): 283 for bad_recommendation in (self.d.getVar("BAD_RECOMMENDATIONS") or "").split():
348 cmd += " --add-ignore-recommends %s" % bad_recommendation 284 cmd += " --add-ignore-recommends %s" % bad_recommendation
285 if hard_depends_only:
286 cmd += " --no-install-recommends"
349 cmd += " install " 287 cmd += " install "
350 cmd += " ".join(pkgs) 288 cmd += " ".join(pkgs)
351 289
@@ -443,15 +381,16 @@ class OpkgPM(OpkgDpkgPM):
443 cmd = "%s %s --noaction install %s " % (self.opkg_cmd, 381 cmd = "%s %s --noaction install %s " % (self.opkg_cmd,
444 opkg_args, 382 opkg_args,
445 ' '.join(pkgs)) 383 ' '.join(pkgs))
446 try: 384 proc = subprocess.run(cmd, capture_output=True, encoding="utf-8", shell=True)
447 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) 385 if proc.returncode:
448 except subprocess.CalledProcessError as e:
449 bb.fatal("Unable to dummy install packages. Command '%s' " 386 bb.fatal("Unable to dummy install packages. Command '%s' "
450 "returned %d:\n%s" % (cmd, e.returncode, e.output.decode("utf-8"))) 387 "returned %d:\n%s" % (cmd, proc.returncode, proc.stderr))
388 elif proc.stderr:
389 bb.note("Command '%s' returned stderr: %s" % (cmd, proc.stderr))
451 390
452 bb.utils.remove(temp_rootfs, True) 391 bb.utils.remove(temp_rootfs, True)
453 392
454 return output 393 return proc.stdout
455 394
456 def backup_packaging_data(self): 395 def backup_packaging_data(self):
457 # Save the opkglib for increment ipk image generation 396 # Save the opkglib for increment ipk image generation
@@ -477,7 +416,7 @@ class OpkgPM(OpkgDpkgPM):
477 Returns a dictionary with the package info. 416 Returns a dictionary with the package info.
478 """ 417 """
479 cmd = "%s %s info %s" % (self.opkg_cmd, self.opkg_args, pkg) 418 cmd = "%s %s info %s" % (self.opkg_cmd, self.opkg_args, pkg)
480 pkg_info = super(OpkgPM, self).package_info(pkg, cmd) 419 pkg_info = self._common_package_info(cmd)
481 420
482 pkg_arch = pkg_info[pkg]["arch"] 421 pkg_arch = pkg_info[pkg]["arch"]
483 pkg_filename = pkg_info[pkg]["filename"] 422 pkg_filename = pkg_info[pkg]["filename"]
@@ -485,19 +424,3 @@ class OpkgPM(OpkgDpkgPM):
485 os.path.join(self.deploy_dir, pkg_arch, pkg_filename) 424 os.path.join(self.deploy_dir, pkg_arch, pkg_filename)
486 425
487 return pkg_info 426 return pkg_info
488
489 def extract(self, pkg):
490 """
491 Returns the path to a tmpdir where resides the contents of a package.
492
493 Deleting the tmpdir is responsability of the caller.
494 """
495 pkg_info = self.package_info(pkg)
496 if not pkg_info:
497 bb.fatal("Unable to get information for package '%s' while "
498 "trying to extract the package." % pkg)
499
500 tmp_dir = super(OpkgPM, self).extract(pkg, pkg_info)
501 bb.utils.remove(os.path.join(tmp_dir, "data.tar.xz"))
502
503 return tmp_dir
diff --git a/meta/lib/oe/package_manager/ipk/manifest.py b/meta/lib/oe/package_manager/ipk/manifest.py
index ee4b57bcb0..3549d7428d 100644
--- a/meta/lib/oe/package_manager/ipk/manifest.py
+++ b/meta/lib/oe/package_manager/ipk/manifest.py
@@ -1,8 +1,11 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
5from oe.manifest import Manifest 7from oe.manifest import Manifest
8import re
6 9
7class PkgManifest(Manifest): 10class PkgManifest(Manifest):
8 """ 11 """
diff --git a/meta/lib/oe/package_manager/ipk/rootfs.py b/meta/lib/oe/package_manager/ipk/rootfs.py
index 26dbee6f6a..ba93eb62ea 100644
--- a/meta/lib/oe/package_manager/ipk/rootfs.py
+++ b/meta/lib/oe/package_manager/ipk/rootfs.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -145,51 +147,14 @@ class PkgRootfs(DpkgOpkgRootfs):
145 self.pm.recover_packaging_data() 147 self.pm.recover_packaging_data()
146 148
147 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True) 149 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
148
149 def _prelink_file(self, root_dir, filename):
150 bb.note('prelink %s in %s' % (filename, root_dir))
151 prelink_cfg = oe.path.join(root_dir,
152 self.d.expand('${sysconfdir}/prelink.conf'))
153 if not os.path.exists(prelink_cfg):
154 shutil.copy(self.d.expand('${STAGING_DIR_NATIVE}${sysconfdir_native}/prelink.conf'),
155 prelink_cfg)
156
157 cmd_prelink = self.d.expand('${STAGING_DIR_NATIVE}${sbindir_native}/prelink')
158 self._exec_shell_cmd([cmd_prelink,
159 '--root',
160 root_dir,
161 '-amR',
162 '-N',
163 '-c',
164 self.d.expand('${sysconfdir}/prelink.conf')])
165
166 ''' 150 '''
167 Compare two files with the same key twice to see if they are equal. 151 Compare two files with the same key twice to see if they are equal.
168 If they are not equal, it means they are duplicated and come from 152 If they are not equal, it means they are duplicated and come from
169 different packages. 153 different packages.
170 1st: Comapre them directly;
171 2nd: While incremental image creation is enabled, one of the
172 files could be probaly prelinked in the previous image
173 creation and the file has been changed, so we need to
174 prelink the other one and compare them.
175 ''' 154 '''
176 def _file_equal(self, key, f1, f2): 155 def _file_equal(self, key, f1, f2):
177
178 # Both of them are not prelinked
179 if filecmp.cmp(f1, f2): 156 if filecmp.cmp(f1, f2):
180 return True 157 return True
181
182 if bb.data.inherits_class('image-prelink', self.d):
183 if self.image_rootfs not in f1:
184 self._prelink_file(f1.replace(key, ''), f1)
185
186 if self.image_rootfs not in f2:
187 self._prelink_file(f2.replace(key, ''), f2)
188
189 # Both of them are prelinked
190 if filecmp.cmp(f1, f2):
191 return True
192
193 # Not equal 158 # Not equal
194 return False 159 return False
195 160
@@ -200,7 +165,7 @@ class PkgRootfs(DpkgOpkgRootfs):
200 """ 165 """
201 def _multilib_sanity_test(self, dirs): 166 def _multilib_sanity_test(self, dirs):
202 167
203 allow_replace = self.d.getVar("MULTILIBRE_ALLOW_REP") 168 allow_replace = "|".join((self.d.getVar("MULTILIBRE_ALLOW_REP") or "").split())
204 if allow_replace is None: 169 if allow_replace is None:
205 allow_replace = "" 170 allow_replace = ""
206 171
diff --git a/meta/lib/oe/package_manager/ipk/sdk.py b/meta/lib/oe/package_manager/ipk/sdk.py
index e2ca415c8e..3acd55f548 100644
--- a/meta/lib/oe/package_manager/ipk/sdk.py
+++ b/meta/lib/oe/package_manager/ipk/sdk.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -61,12 +63,19 @@ class PkgSdk(Sdk):
61 63
62 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY')) 64 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY'))
63 65
66 env_bkp = os.environ.copy()
67 os.environ['PATH'] = self.d.expand("${COREBASE}/scripts/nativesdk-intercept") + \
68 os.pathsep + os.environ["PATH"]
69
64 self.target_pm.run_intercepts(populate_sdk='target') 70 self.target_pm.run_intercepts(populate_sdk='target')
71 os.environ.update(env_bkp)
65 72
66 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND")) 73 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND"))
67 74
68 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d): 75 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
69 self.target_pm.remove_packaging_data() 76 self.target_pm.remove_packaging_data()
77 else:
78 self.target_pm.remove_lists()
70 79
71 bb.note("Installing NATIVESDK packages") 80 bb.note("Installing NATIVESDK packages")
72 self._populate_sysroot(self.host_pm, self.host_manifest) 81 self._populate_sysroot(self.host_pm, self.host_manifest)
@@ -78,6 +87,8 @@ class PkgSdk(Sdk):
78 87
79 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d): 88 if not bb.utils.contains("SDKIMAGE_FEATURES", "package-management", True, False, self.d):
80 self.host_pm.remove_packaging_data() 89 self.host_pm.remove_packaging_data()
90 else:
91 self.host_pm.remove_lists()
81 92
82 target_sysconfdir = os.path.join(self.sdk_target_sysroot, self.sysconfdir) 93 target_sysconfdir = os.path.join(self.sdk_target_sysroot, self.sysconfdir)
83 host_sysconfdir = os.path.join(self.sdk_host_sysroot, self.sysconfdir) 94 host_sysconfdir = os.path.join(self.sdk_host_sysroot, self.sysconfdir)
diff --git a/meta/lib/oe/package_manager/rpm/__init__.py b/meta/lib/oe/package_manager/rpm/__init__.py
index 6df0092281..323ec5008f 100644
--- a/meta/lib/oe/package_manager/rpm/__init__.py
+++ b/meta/lib/oe/package_manager/rpm/__init__.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -96,11 +98,15 @@ class RpmPM(PackageManager):
96 archs = ["sdk_provides_dummy_target"] + archs 98 archs = ["sdk_provides_dummy_target"] + archs
97 confdir = "%s/%s" %(self.target_rootfs, "etc/dnf/vars/") 99 confdir = "%s/%s" %(self.target_rootfs, "etc/dnf/vars/")
98 bb.utils.mkdirhier(confdir) 100 bb.utils.mkdirhier(confdir)
99 open(confdir + "arch", 'w').write(":".join(archs)) 101 with open(confdir + "arch", 'w') as f:
102 f.write(":".join(archs))
103
100 distro_codename = self.d.getVar('DISTRO_CODENAME') 104 distro_codename = self.d.getVar('DISTRO_CODENAME')
101 open(confdir + "releasever", 'w').write(distro_codename if distro_codename is not None else '') 105 with open(confdir + "releasever", 'w') as f:
106 f.write(distro_codename if distro_codename is not None else '')
102 107
103 open(oe.path.join(self.target_rootfs, "etc/dnf/dnf.conf"), 'w').write("") 108 with open(oe.path.join(self.target_rootfs, "etc/dnf/dnf.conf"), 'w') as f:
109 f.write("")
104 110
105 111
106 def _configure_rpm(self): 112 def _configure_rpm(self):
@@ -110,14 +116,17 @@ class RpmPM(PackageManager):
110 platformconfdir = "%s/%s" %(self.target_rootfs, "etc/rpm/") 116 platformconfdir = "%s/%s" %(self.target_rootfs, "etc/rpm/")
111 rpmrcconfdir = "%s/%s" %(self.target_rootfs, "etc/") 117 rpmrcconfdir = "%s/%s" %(self.target_rootfs, "etc/")
112 bb.utils.mkdirhier(platformconfdir) 118 bb.utils.mkdirhier(platformconfdir)
113 open(platformconfdir + "platform", 'w').write("%s-pc-linux" % self.primary_arch) 119 with open(platformconfdir + "platform", 'w') as f:
120 f.write("%s-pc-linux" % self.primary_arch)
114 with open(rpmrcconfdir + "rpmrc", 'w') as f: 121 with open(rpmrcconfdir + "rpmrc", 'w') as f:
115 f.write("arch_compat: %s: %s\n" % (self.primary_arch, self.archs if len(self.archs) > 0 else self.primary_arch)) 122 f.write("arch_compat: %s: %s\n" % (self.primary_arch, self.archs if len(self.archs) > 0 else self.primary_arch))
116 f.write("buildarch_compat: %s: noarch\n" % self.primary_arch) 123 f.write("buildarch_compat: %s: noarch\n" % self.primary_arch)
117 124
118 open(platformconfdir + "macros", 'w').write("%_transaction_color 7\n") 125 with open(platformconfdir + "macros", 'w') as f:
126 f.write("%_transaction_color 7\n")
119 if self.d.getVar('RPM_PREFER_ELF_ARCH'): 127 if self.d.getVar('RPM_PREFER_ELF_ARCH'):
120 open(platformconfdir + "macros", 'a').write("%%_prefer_color %s" % (self.d.getVar('RPM_PREFER_ELF_ARCH'))) 128 with open(platformconfdir + "macros", 'a') as f:
129 f.write("%%_prefer_color %s" % (self.d.getVar('RPM_PREFER_ELF_ARCH')))
121 130
122 if self.d.getVar('RPM_SIGN_PACKAGES') == '1': 131 if self.d.getVar('RPM_SIGN_PACKAGES') == '1':
123 signer = get_signer(self.d, self.d.getVar('RPM_GPG_BACKEND')) 132 signer = get_signer(self.d, self.d.getVar('RPM_GPG_BACKEND'))
@@ -164,13 +173,13 @@ class RpmPM(PackageManager):
164 repo_uri = uri + "/" + arch 173 repo_uri = uri + "/" + arch
165 repo_id = "oe-remote-repo" + "-".join(urlparse(repo_uri).path.split("/")) 174 repo_id = "oe-remote-repo" + "-".join(urlparse(repo_uri).path.split("/"))
166 repo_name = "OE Remote Repo:" + " ".join(urlparse(repo_uri).path.split("/")) 175 repo_name = "OE Remote Repo:" + " ".join(urlparse(repo_uri).path.split("/"))
167 open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'a').write( 176 with open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'a') as f:
168 "[%s]\nname=%s\nbaseurl=%s\n%s\n" % (repo_id, repo_name, repo_uri, gpg_opts)) 177 f.write("[%s]\nname=%s\nbaseurl=%s\n%s\n" % (repo_id, repo_name, repo_uri, gpg_opts))
169 else: 178 else:
170 repo_name = "OE Remote Repo:" + " ".join(urlparse(uri).path.split("/")) 179 repo_name = "OE Remote Repo:" + " ".join(urlparse(uri).path.split("/"))
171 repo_uri = uri 180 repo_uri = uri
172 open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'w').write( 181 with open(oe.path.join(self.target_rootfs, "etc", "yum.repos.d", repo_base + ".repo"), 'w') as f:
173 "[%s]\nname=%s\nbaseurl=%s\n%s" % (repo_base, repo_name, repo_uri, gpg_opts)) 182 f.write("[%s]\nname=%s\nbaseurl=%s\n%s" % (repo_base, repo_name, repo_uri, gpg_opts))
174 183
175 def _prepare_pkg_transaction(self): 184 def _prepare_pkg_transaction(self):
176 os.environ['D'] = self.target_rootfs 185 os.environ['D'] = self.target_rootfs
@@ -181,7 +190,7 @@ class RpmPM(PackageManager):
181 os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE') 190 os.environ['NATIVE_ROOT'] = self.d.getVar('STAGING_DIR_NATIVE')
182 191
183 192
184 def install(self, pkgs, attempt_only = False): 193 def install(self, pkgs, attempt_only=False, hard_depends_only=False):
185 if len(pkgs) == 0: 194 if len(pkgs) == 0:
186 return 195 return
187 self._prepare_pkg_transaction() 196 self._prepare_pkg_transaction()
@@ -192,13 +201,16 @@ class RpmPM(PackageManager):
192 201
193 output = self._invoke_dnf((["--skip-broken"] if attempt_only else []) + 202 output = self._invoke_dnf((["--skip-broken"] if attempt_only else []) +
194 (["-x", ",".join(exclude_pkgs)] if len(exclude_pkgs) > 0 else []) + 203 (["-x", ",".join(exclude_pkgs)] if len(exclude_pkgs) > 0 else []) +
195 (["--setopt=install_weak_deps=False"] if self.d.getVar('NO_RECOMMENDATIONS') == "1" else []) + 204 (["--setopt=install_weak_deps=False"] if (hard_depends_only or self.d.getVar('NO_RECOMMENDATIONS') == "1") else []) +
196 (["--nogpgcheck"] if self.d.getVar('RPM_SIGN_PACKAGES') != '1' else ["--setopt=gpgcheck=True"]) + 205 (["--nogpgcheck"] if self.d.getVar('RPM_SIGN_PACKAGES') != '1' else ["--setopt=gpgcheck=True"]) +
197 ["install"] + 206 ["install"] +
198 pkgs) 207 pkgs)
199 208
200 failed_scriptlets_pkgnames = collections.OrderedDict() 209 failed_scriptlets_pkgnames = collections.OrderedDict()
201 for line in output.splitlines(): 210 for line in output.splitlines():
211 if line.startswith("Error: Systemctl"):
212 bb.error(line)
213
202 if line.startswith("Error in POSTIN scriptlet in rpm package"): 214 if line.startswith("Error in POSTIN scriptlet in rpm package"):
203 failed_scriptlets_pkgnames[line.split()[-1]] = True 215 failed_scriptlets_pkgnames[line.split()[-1]] = True
204 216
@@ -326,7 +338,8 @@ class RpmPM(PackageManager):
326 return e.output.decode("utf-8") 338 return e.output.decode("utf-8")
327 339
328 def dump_install_solution(self, pkgs): 340 def dump_install_solution(self, pkgs):
329 open(self.solution_manifest, 'w').write(" ".join(pkgs)) 341 with open(self.solution_manifest, 'w') as f:
342 f.write(" ".join(pkgs))
330 return pkgs 343 return pkgs
331 344
332 def load_old_install_solution(self): 345 def load_old_install_solution(self):
@@ -360,7 +373,8 @@ class RpmPM(PackageManager):
360 bb.utils.mkdirhier(target_path) 373 bb.utils.mkdirhier(target_path)
361 num = self._script_num_prefix(target_path) 374 num = self._script_num_prefix(target_path)
362 saved_script_name = oe.path.join(target_path, "%d-%s" % (num, pkg)) 375 saved_script_name = oe.path.join(target_path, "%d-%s" % (num, pkg))
363 open(saved_script_name, 'w').write(output) 376 with open(saved_script_name, 'w') as f:
377 f.write(output)
364 os.chmod(saved_script_name, 0o755) 378 os.chmod(saved_script_name, 0o755)
365 379
366 def _handle_intercept_failure(self, registered_pkgs): 380 def _handle_intercept_failure(self, registered_pkgs):
@@ -372,14 +386,15 @@ class RpmPM(PackageManager):
372 self.save_rpmpostinst(pkg) 386 self.save_rpmpostinst(pkg)
373 387
374 def extract(self, pkg): 388 def extract(self, pkg):
375 output = self._invoke_dnf(["repoquery", "--queryformat", "%{location}", pkg]) 389 output = self._invoke_dnf(["repoquery", "--location", pkg])
376 pkg_name = output.splitlines()[-1] 390 pkg_name = output.splitlines()[-1]
377 if not pkg_name.endswith(".rpm"): 391 if not pkg_name.endswith(".rpm"):
378 bb.fatal("dnf could not find package %s in repository: %s" %(pkg, output)) 392 bb.fatal("dnf could not find package %s in repository: %s" %(pkg, output))
379 pkg_path = oe.path.join(self.rpm_repo_dir, pkg_name) 393 # Strip file: prefix
394 pkg_path = pkg_name[5:]
380 395
381 cpio_cmd = bb.utils.which(os.getenv("PATH"), "cpio") 396 tar_cmd = bb.utils.which(os.getenv("PATH"), "tar")
382 rpm2cpio_cmd = bb.utils.which(os.getenv("PATH"), "rpm2cpio") 397 rpm2archive_cmd = bb.utils.which(os.getenv("PATH"), "rpm2archive")
383 398
384 if not os.path.isfile(pkg_path): 399 if not os.path.isfile(pkg_path):
385 bb.fatal("Unable to extract package for '%s'." 400 bb.fatal("Unable to extract package for '%s'."
@@ -390,7 +405,7 @@ class RpmPM(PackageManager):
390 os.chdir(tmp_dir) 405 os.chdir(tmp_dir)
391 406
392 try: 407 try:
393 cmd = "%s %s | %s -idmv" % (rpm2cpio_cmd, pkg_path, cpio_cmd) 408 cmd = "%s -n %s | %s xv" % (rpm2archive_cmd, pkg_path, tar_cmd)
394 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) 409 output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
395 except subprocess.CalledProcessError as e: 410 except subprocess.CalledProcessError as e:
396 bb.utils.remove(tmp_dir, recurse=True) 411 bb.utils.remove(tmp_dir, recurse=True)
diff --git a/meta/lib/oe/package_manager/rpm/manifest.py b/meta/lib/oe/package_manager/rpm/manifest.py
index e6604b301f..6ee7c329f0 100644
--- a/meta/lib/oe/package_manager/rpm/manifest.py
+++ b/meta/lib/oe/package_manager/rpm/manifest.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
diff --git a/meta/lib/oe/package_manager/rpm/rootfs.py b/meta/lib/oe/package_manager/rpm/rootfs.py
index 00d07cd9cc..3ba5396320 100644
--- a/meta/lib/oe/package_manager/rpm/rootfs.py
+++ b/meta/lib/oe/package_manager/rpm/rootfs.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -108,7 +110,7 @@ class PkgRootfs(Rootfs):
108 if self.progress_reporter: 110 if self.progress_reporter:
109 self.progress_reporter.next_stage() 111 self.progress_reporter.next_stage()
110 112
111 self._setup_dbg_rootfs(['/etc', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf']) 113 self._setup_dbg_rootfs(['/etc/rpm', '/etc/rpmrc', '/etc/dnf', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
112 114
113 execute_pre_post_process(self.d, rpm_post_process_cmds) 115 execute_pre_post_process(self.d, rpm_post_process_cmds)
114 116
diff --git a/meta/lib/oe/package_manager/rpm/sdk.py b/meta/lib/oe/package_manager/rpm/sdk.py
index c5f232431f..ea79fe050b 100644
--- a/meta/lib/oe/package_manager/rpm/sdk.py
+++ b/meta/lib/oe/package_manager/rpm/sdk.py
@@ -1,4 +1,6 @@
1# 1#
2# Copyright OpenEmbedded Contributors
3#
2# SPDX-License-Identifier: GPL-2.0-only 4# SPDX-License-Identifier: GPL-2.0-only
3# 5#
4 6
@@ -65,7 +67,12 @@ class PkgSdk(Sdk):
65 67
66 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY')) 68 self.target_pm.install_complementary(self.d.getVar('SDKIMAGE_INSTALL_COMPLEMENTARY'))
67 69
70 env_bkp = os.environ.copy()
71 os.environ['PATH'] = self.d.expand("${COREBASE}/scripts/nativesdk-intercept") + \
72 os.pathsep + os.environ["PATH"]
73
68 self.target_pm.run_intercepts(populate_sdk='target') 74 self.target_pm.run_intercepts(populate_sdk='target')
75 os.environ.update(env_bkp)
69 76
70 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND")) 77 execute_pre_post_process(self.d, self.d.getVar("POPULATE_SDK_POST_TARGET_COMMAND"))
71 78
@@ -110,5 +117,6 @@ class PkgSdk(Sdk):
110 for f in glob.glob(os.path.join(self.sdk_output, "etc", "rpm*")): 117 for f in glob.glob(os.path.join(self.sdk_output, "etc", "rpm*")):
111 self.movefile(f, native_sysconf_dir) 118 self.movefile(f, native_sysconf_dir)
112 for f in glob.glob(os.path.join(self.sdk_output, "etc", "dnf", "*")): 119 for f in glob.glob(os.path.join(self.sdk_output, "etc", "dnf", "*")):
113 self.movefile(f, native_sysconf_dir) 120 self.mkdirhier(native_sysconf_dir + "/dnf")
121 self.movefile(f, native_sysconf_dir + "/dnf")
114 self.remove(os.path.join(self.sdk_output, "etc"), True) 122 self.remove(os.path.join(self.sdk_output, "etc"), True)