[2/3] add multiarch support

Message ID 20230206122050.337270-3-adriaan.schmidt@siemens.com
State Superseded, archived
Headers show
Series multiarch support | expand

Commit Message

Schmidt, Adriaan Feb. 6, 2023, 12:20 p.m. UTC
This adds support for building packages for native and compat architectures
to dpdk-base.bbclass.
Thus, all package recipes automatically have a *-native and *-compat target,
which can be used in DEPENDS/RDEPENDS definitions.
Additionally *-compat targets can be used in IMAGE_INSTALL, where they
are automatically converted to install package:${COMPAT_DISTRO_ARCH}.

Note that the switch ISAR_ENABLE_COMPAT_ARCH still exist and controls
addition of the compat architecture during bootstrapping.

Signed-off-by: Adriaan Schmidt <adriaan.schmidt@siemens.com>
---
 .../recipes-app/samefile/samefile_2.14.bb     |  2 +-
 meta/classes/compat.bbclass                   | 49 +++++++++++++++++++
 meta/classes/debianize.bbclass                |  2 +-
 meta/classes/dpkg-base.bbclass                |  1 +
 meta/classes/image.bbclass                    |  4 +-
 meta/classes/multiarch.bbclass                | 44 +++++++++++++++++
 meta/classes/native.bbclass                   | 10 ++++
 meta/conf/bitbake.conf                        |  1 +
 8 files changed, 110 insertions(+), 3 deletions(-)
 create mode 100644 meta/classes/compat.bbclass
 create mode 100644 meta/classes/multiarch.bbclass
 create mode 100644 meta/classes/native.bbclass

Comments

Cedric Hombourger Feb. 28, 2023, 7:58 a.m. UTC | #1
On Monday, February 6, 2023 at 1:21:27 PM UTC+1 Adriaan Schmidt wrote:

This adds support for building packages for native and compat architectures 
to dpdk-base.bbclass. 
Thus, all package recipes automatically have a *-native and *-compat 
target, 
which can be used in DEPENDS/RDEPENDS definitions. 
Additionally *-compat targets can be used in IMAGE_INSTALL, where they 
are automatically converted to install package:${COMPAT_DISTRO_ARCH}. 

Note that the switch ISAR_ENABLE_COMPAT_ARCH still exist and controls 
addition of the compat architecture during bootstrapping. 

Signed-off-by: Adriaan Schmidt <adriaan...@siemens.com> 
--- 
.../recipes-app/samefile/samefile_2.14.bb | 2 +- 
meta/classes/compat.bbclass | 49 +++++++++++++++++++ 
meta/classes/debianize.bbclass | 2 +- 
meta/classes/dpkg-base.bbclass | 1 + 
meta/classes/image.bbclass | 4 +- 
meta/classes/multiarch.bbclass | 44 +++++++++++++++++ 
meta/classes/native.bbclass | 10 ++++ 
meta/conf/bitbake.conf | 1 + 
8 files changed, 110 insertions(+), 3 deletions(-) 
create mode 100644 meta/classes/compat.bbclass 
create mode 100644 meta/classes/multiarch.bbclass 
create mode 100644 meta/classes/native.bbclass 

diff --git a/meta-isar/recipes-app/samefile/samefile_2.14.bb 
b/meta-isar/recipes-app/samefile/samefile_2.14.bb 
index 5e36a2ac..c53c9445 100644 
--- a/meta-isar/recipes-app/samefile/samefile_2.14.bb 
+++ b/meta-isar/recipes-app/samefile/samefile_2.14.bb 
@@ -21,7 +21,7 @@ do_prepare_build() { 
# deb_debianize. Pre-exisiting files will not be recreated, changelog 
# will be prepended unless its latest entry is for CHANGELOG_V. 
cat << EOF > ${WORKDIR}/changelog 
-${PN} (0.1) unstable; urgency=low 
+${BPN} (0.1) unstable; urgency=low 

* a long long time ago there was an early version 

diff --git a/meta/classes/compat.bbclass b/meta/classes/compat.bbclass 
new file mode 100644 
index 00000000..7142ec3a 
--- /dev/null 
+++ b/meta/classes/compat.bbclass 
@@ -0,0 +1,49 @@ 
+# This software is a part of ISAR. 
+# Copyright (C) 2023 Siemens AG 
+# 
+# SPDX-License-Identifier: MIT 
+ 
+# this class is "dual-use": it can be inherited (e.g., by bootstrap and 
image 
+# classes) to access variables and functions, and it's also addedd via 
BBCLASSEXTEND 
+# when inheriting multiconfig.bbclass. 
+ 
+################################################################################ 

+# generic functions 
+################################################################################ 

+ 
+# calcucate COMPAT_DISTRO_ARCH


typo: calculate (but since it's not really a computation per se, I would 
just say determine)
 


+# we can't use simple overrides, because in case we're building a package 
+# with a PACKAGE_ARCH != DISTRO_ARCH, overrides would find the wrong 
value. 
+python() { 
+ distro_arch = d.getVar('DISTRO_ARCH') 
+ compat_distro_arch = d.getVar('COMPAT_DISTRO_ARCH:' + distro_arch) 
+ if compat_distro_arch is None and 'class-compat' in 
d.getVar('OVERRIDES').split(':'): 
+ bb.fatal(f"{distro_arch} does not have a compat arch") 
+ d.setVar('COMPAT_DISTRO_ARCH', compat_distro_arch) 
+} 
+ 
+# function to convert bitbake targets to installable debian packages, 
+# e.g., "hello-compat" to "hello:i386". 
+def isar_compat_packages(var, d): 
+ bb_targets = (d.getVar(var, True) or '').split() 
+ packages = [] 
+ compat_distro_arch = d.getVar('COMPAT_DISTRO_ARCH', True) 
+ for t in bb_targets: 
+ if t.endswith('-compat'): 
+ packages.append(t[:-len('-compat')] + ':' + compat_distro_arch) 
+ else: 
+ packages.append(t) 
+ return ' '.join(packages) 
+ 
+ 
+################################################################################ 

+# package recipe modifications when actually building *-compat: 
+################################################################################ 

+ 
+# check that we can actually build compat (ISAR_ENABLE_COMPAT_ARCH is set) 
+python do_fetch:prepend:class-compat() { 
+ if not d.getVar('ISAR_ENABLE_COMPAT_ARCH', True) == '1': 
+ bb.fatal("compat package requested, but ISAR_ENABLE_COMPAT_ARCH is not 
set.") 
+} 
+ 
+PACKAGE_ARCH:class-compat = "${COMPAT_DISTRO_ARCH}" 
diff --git a/meta/classes/debianize.bbclass 
b/meta/classes/debianize.bbclass 
index a6694a00..1b98c02d 100644 
--- a/meta/classes/debianize.bbclass 
+++ b/meta/classes/debianize.bbclass 
@@ -31,7 +31,7 @@ deb_add_changelog() { 

date=$(LANG=C date -R -d @${timestamp}) 
cat <<EOF > ${S}/debian/changelog 
-${PN} (${changelog_v}) UNRELEASED; urgency=low 
+${BPN} (${changelog_v}) UNRELEASED; urgency=low 

* generated by Isar 

diff --git a/meta/classes/dpkg-base.bbclass 
b/meta/classes/dpkg-base.bbclass 
index ad28f7b3..55cc6655 100644 
--- a/meta/classes/dpkg-base.bbclass 
+++ b/meta/classes/dpkg-base.bbclass 
@@ -5,6 +5,7 @@ 
# SPDX-License-Identifier: MIT 

inherit sbuild 
+inherit multiarch 
inherit debianize 
inherit terminal 
inherit repository 
diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass 
index 539ec51d..8d0dda30 100644 
--- a/meta/classes/image.bbclass 
+++ b/meta/classes/image.bbclass 
@@ -79,9 +79,11 @@ image_do_mounts() { 
buildchroot_do_mounts 
} 

+inherit compat 
+ 
ROOTFSDIR = "${IMAGE_ROOTFS}" 
ROOTFS_FEATURES += "clean-package-cache clean-pycache generate-manifest 
export-dpkg-status clean-log-files clean-debconf-cache" 
-ROOTFS_PACKAGES += "${IMAGE_PREINSTALL} ${IMAGE_INSTALL}" 
+ROOTFS_PACKAGES += "${IMAGE_PREINSTALL} 
${@isar_compat_packages('IMAGE_INSTALL', d)}" 
ROOTFS_MANIFEST_DEPLOY_DIR ?= "${DEPLOY_DIR_IMAGE}" 
ROOTFS_DPKGSTATUS_DEPLOY_DIR ?= "${DEPLOY_DIR_IMAGE}" 
ROOTFS_PACKAGE_SUFFIX ?= "${PN}-${DISTRO}-${MACHINE}" 
diff --git a/meta/classes/multiarch.bbclass 
b/meta/classes/multiarch.bbclass 
new file mode 100644 
index 00000000..5b280699 
--- /dev/null 
+++ b/meta/classes/multiarch.bbclass 
@@ -0,0 +1,44 @@ 
+# This software is a part of ISAR. 
+# Copyright (C) 2021-2022 Siemens AG 
+# 
+# SPDX-License-Identifier: MIT 
+ 
+BBCLASSEXTEND += "native compat" 
+BPN = "${PN}" 
+ 
+python multiarch_virtclass_handler() { 
+ def fixup_pn_in_vars(d): 
+ vars = 'SRC_URI FILESPATH'.split() 
+ for var in vars: 
+ v = d.getVar(var, False) 
+ if v is not None: 
+ d.setVar(var, v.replace('${PN}', '${BPN}')) 
+ 
+ def fixup_depends(suffix, d): 
+ vars = 'PROVIDES RPROVIDES DEPENDS RDEPENDS'.split() 
+ for var in vars: 
+ multiarch_var = [] 
+ val = d.getVar(var, True) 
+ if val is None: 
+ continue 
+ for v in val.split(): 
+ if v.endswith('-compat') or v.endswith('-native'): 
+ multiarch_var.append(v) 
+ else: 
+ multiarch_var.append(v + suffix) 
+ d.setVar(var, ' '.join(multiarch_var)) 
+ 
+ pn = e.data.getVar('PN') 
+ if pn.endswith('-compat'): 
+ e.data.setVar('BPN', pn[:-len('-compat')]) 
+ e.data.appendVar('OVERRIDES', ':class-compat') 
+ fixup_pn_in_vars(e.data) 
+ fixup_depends('-compat', e.data) 
+ elif pn.endswith('-native'): 
+ e.data.setVar('BPN', pn[:-len('-native')]) 
+ e.data.appendVar('OVERRIDES', ':class-native') 
+ fixup_pn_in_vars(e.data) 
+ fixup_depends('-native', e.data) 
+} 
+addhandler multiarch_virtclass_handler 
+multiarch_virtclass_handler[eventmask] = "bb.event.RecipePreFinalise" 
diff --git a/meta/classes/native.bbclass b/meta/classes/native.bbclass 
new file mode 100644 
index 00000000..ef20e8bc 
--- /dev/null 
+++ b/meta/classes/native.bbclass 
@@ -0,0 +1,10 @@ 
+# This software is a part of ISAR. 
+# Copyright (C) 2023 Siemens AG 
+# 
+# SPDX-License-Identifier: MIT 
+ 
+################################################################################ 

+# package recipe modifications when actually building *-native: 
+################################################################################ 

+ 
+PACKAGE_ARCH:class-native = "${HOST_ARCH}" 
diff --git a/meta/conf/bitbake.conf b/meta/conf/bitbake.conf 
index f1a9438e..f38bb447 100644 
--- a/meta/conf/bitbake.conf 
+++ b/meta/conf/bitbake.conf 
@@ -81,6 +81,7 @@ QEMU_ARCH:riscv64 = "riscv64" 

# Codename of the repository created by the caching class 
DEBDISTRONAME ?= "isar" 
+NATIVELSBSTRING ?= "isarnative" 

# Strings used in sstate signature files 
TARGET_VENDOR = ""
Schmidt, Adriaan Feb. 28, 2023, 8:24 a.m. UTC | #2
Hi Cedric,
Sorry for top-posting, but I didn't manage to inline-format nicely with your HTML mail and Outlook...
Please note that you're reviewing v1 of this series, and I'm currently at v3 (from Feb 24). So that typo is no longer there, but I'm happy to change "calculate" -> "determine" in that comment.
(And also the getVar(xx, True) thing will be changed for the next iteration).
Thanks,
Adriaan


From: isar-users@googlegroups.com <isar-users@googlegroups.com> On Behalf Of Cedric Hombourger
Sent: Dienstag, 28. Februar 2023 08:58
To: isar-users <isar-users@googlegroups.com>
Subject: Re: [PATCH 2/3] add multiarch support


On Monday, February 6, 2023 at 1:21:27 PM UTC+1 Adriaan Schmidt wrote:
This adds support for building packages for native and compat architectures 
to dpdk-base.bbclass. 
Thus, all package recipes automatically have a *-native and *-compat target, 
which can be used in DEPENDS/RDEPENDS definitions. 
Additionally *-compat targets can be used in IMAGE_INSTALL, where they 
are automatically converted to install package:${COMPAT_DISTRO_ARCH}. 

Note that the switch ISAR_ENABLE_COMPAT_ARCH still exist and controls 
addition of the compat architecture during bootstrapping. 

Signed-off-by: Adriaan Schmidt <adriaan...@siemens.com> 
--- 
.../recipes-app/samefile/http://samefile_2.14.bb | 2 +- 
meta/classes/compat.bbclass | 49 +++++++++++++++++++ 
meta/classes/debianize.bbclass | 2 +- 
meta/classes/dpkg-base.bbclass | 1 + 
meta/classes/image.bbclass | 4 +- 
meta/classes/multiarch.bbclass | 44 +++++++++++++++++ 
meta/classes/native.bbclass | 10 ++++ 
meta/conf/bitbake.conf | 1 + 
8 files changed, 110 insertions(+), 3 deletions(-) 
create mode 100644 meta/classes/compat.bbclass 
create mode 100644 meta/classes/multiarch.bbclass 
create mode 100644 meta/classes/native.bbclass 

diff --git a/meta-isar/recipes-app/samefile/http://samefile_2.14.bb b/meta-isar/recipes-app/samefile/http://samefile_2.14.bb 
index 5e36a2ac..c53c9445 100644 
--- a/meta-isar/recipes-app/samefile/http://samefile_2.14.bb 
+++ b/meta-isar/recipes-app/samefile/http://samefile_2.14.bb 
@@ -21,7 +21,7 @@ do_prepare_build() { 
# deb_debianize. Pre-exisiting files will not be recreated, changelog 
# will be prepended unless its latest entry is for CHANGELOG_V. 
cat << EOF > ${WORKDIR}/changelog 
-${PN} (0.1) unstable; urgency=low 
+${BPN} (0.1) unstable; urgency=low 

* a long long time ago there was an early version 

diff --git a/meta/classes/compat.bbclass b/meta/classes/compat.bbclass 
new file mode 100644 
index 00000000..7142ec3a 
--- /dev/null 
+++ b/meta/classes/compat.bbclass 
@@ -0,0 +1,49 @@ 
+# This software is a part of ISAR. 
+# Copyright (C) 2023 Siemens AG 
+# 
+# SPDX-License-Identifier: MIT 
+ 
+# this class is "dual-use": it can be inherited (e.g., by bootstrap and image 
+# classes) to access variables and functions, and it's also addedd via BBCLASSEXTEND 
+# when inheriting multiconfig.bbclass. 
+ 
+################################################################################ 
+# generic functions 
+################################################################################ 
+ 
+# calcucate COMPAT_DISTRO_ARCH

typo: calculate (but since it's not really a computation per se, I would just say determine)
 

+# we can't use simple overrides, because in case we're building a package 
+# with a PACKAGE_ARCH != DISTRO_ARCH, overrides would find the wrong value. 
+python() { 
+ distro_arch = d.getVar('DISTRO_ARCH') 
+ compat_distro_arch = d.getVar('COMPAT_DISTRO_ARCH:' + distro_arch) 
+ if compat_distro_arch is None and 'class-compat' in d.getVar('OVERRIDES').split(':'): 
+ bb.fatal(f"{distro_arch} does not have a compat arch") 
+ d.setVar('COMPAT_DISTRO_ARCH', compat_distro_arch) 
+} 
+ 
+# function to convert bitbake targets to installable debian packages, 
+# e.g., "hello-compat" to "hello:i386". 
+def isar_compat_packages(var, d): 
+ bb_targets = (d.getVar(var, True) or '').split() 
+ packages = [] 
+ compat_distro_arch = d.getVar('COMPAT_DISTRO_ARCH', True) 
+ for t in bb_targets: 
+ if t.endswith('-compat'): 
+ packages.append(t[:-len('-compat')] + ':' + compat_distro_arch) 
+ else: 
+ packages.append(t) 
+ return ' '.join(packages) 
+ 
+ 
+################################################################################ 
+# package recipe modifications when actually building *-compat: 
+################################################################################ 
+ 
+# check that we can actually build compat (ISAR_ENABLE_COMPAT_ARCH is set) 
+python do_fetch:prepend:class-compat() { 
+ if not d.getVar('ISAR_ENABLE_COMPAT_ARCH', True) == '1': 
+ bb.fatal("compat package requested, but ISAR_ENABLE_COMPAT_ARCH is not set.") 
+} 
+ 
+PACKAGE_ARCH:class-compat = "${COMPAT_DISTRO_ARCH}" 
diff --git a/meta/classes/debianize.bbclass b/meta/classes/debianize.bbclass 
index a6694a00..1b98c02d 100644 
--- a/meta/classes/debianize.bbclass 
+++ b/meta/classes/debianize.bbclass 
@@ -31,7 +31,7 @@ deb_add_changelog() { 

date=$(LANG=C date -R -d @${timestamp}) 
cat <<EOF > ${S}/debian/changelog 
-${PN} (${changelog_v}) UNRELEASED; urgency=low 
+${BPN} (${changelog_v}) UNRELEASED; urgency=low 

* generated by Isar 

diff --git a/meta/classes/dpkg-base.bbclass b/meta/classes/dpkg-base.bbclass 
index ad28f7b3..55cc6655 100644 
--- a/meta/classes/dpkg-base.bbclass 
+++ b/meta/classes/dpkg-base.bbclass 
@@ -5,6 +5,7 @@ 
# SPDX-License-Identifier: MIT 

inherit sbuild 
+inherit multiarch 
inherit debianize 
inherit terminal 
inherit repository 
diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass 
index 539ec51d..8d0dda30 100644 
--- a/meta/classes/image.bbclass 
+++ b/meta/classes/image.bbclass 
@@ -79,9 +79,11 @@ image_do_mounts() { 
buildchroot_do_mounts 
} 

+inherit compat 
+ 
ROOTFSDIR = "${IMAGE_ROOTFS}" 
ROOTFS_FEATURES += "clean-package-cache clean-pycache generate-manifest export-dpkg-status clean-log-files clean-debconf-cache" 
-ROOTFS_PACKAGES += "${IMAGE_PREINSTALL} ${IMAGE_INSTALL}" 
+ROOTFS_PACKAGES += "${IMAGE_PREINSTALL} ${@isar_compat_packages('IMAGE_INSTALL', d)}" 
ROOTFS_MANIFEST_DEPLOY_DIR ?= "${DEPLOY_DIR_IMAGE}" 
ROOTFS_DPKGSTATUS_DEPLOY_DIR ?= "${DEPLOY_DIR_IMAGE}" 
ROOTFS_PACKAGE_SUFFIX ?= "${PN}-${DISTRO}-${MACHINE}" 
diff --git a/meta/classes/multiarch.bbclass b/meta/classes/multiarch.bbclass 
new file mode 100644 
index 00000000..5b280699 
--- /dev/null 
+++ b/meta/classes/multiarch.bbclass 
@@ -0,0 +1,44 @@ 
+# This software is a part of ISAR. 
+# Copyright (C) 2021-2022 Siemens AG 
+# 
+# SPDX-License-Identifier: MIT 
+ 
+BBCLASSEXTEND += "native compat" 
+BPN = "${PN}" 
+ 
+python multiarch_virtclass_handler() { 
+ def fixup_pn_in_vars(d): 
+ vars = 'SRC_URI FILESPATH'.split() 
+ for var in vars: 
+ v = d.getVar(var, False) 
+ if v is not None: 
+ d.setVar(var, v.replace('${PN}', '${BPN}')) 
+ 
+ def fixup_depends(suffix, d): 
+ vars = 'PROVIDES RPROVIDES DEPENDS RDEPENDS'.split() 
+ for var in vars: 
+ multiarch_var = [] 
+ val = d.getVar(var, True) 
+ if val is None: 
+ continue 
+ for v in val.split(): 
+ if v.endswith('-compat') or v.endswith('-native'): 
+ multiarch_var.append(v) 
+ else: 
+ multiarch_var.append(v + suffix) 
+ d.setVar(var, ' '.join(multiarch_var)) 
+ 
+ pn = e.data.getVar('PN') 
+ if pn.endswith('-compat'): 
+ e.data.setVar('BPN', pn[:-len('-compat')]) 
+ e.data.appendVar('OVERRIDES', ':class-compat') 
+ fixup_pn_in_vars(e.data) 
+ fixup_depends('-compat', e.data) 
+ elif pn.endswith('-native'): 
+ e.data.setVar('BPN', pn[:-len('-native')]) 
+ e.data.appendVar('OVERRIDES', ':class-native') 
+ fixup_pn_in_vars(e.data) 
+ fixup_depends('-native', e.data) 
+} 
+addhandler multiarch_virtclass_handler 
+multiarch_virtclass_handler[eventmask] = "bb.event.RecipePreFinalise" 
diff --git a/meta/classes/native.bbclass b/meta/classes/native.bbclass 
new file mode 100644 
index 00000000..ef20e8bc 
--- /dev/null 
+++ b/meta/classes/native.bbclass 
@@ -0,0 +1,10 @@ 
+# This software is a part of ISAR. 
+# Copyright (C) 2023 Siemens AG 
+# 
+# SPDX-License-Identifier: MIT 
+ 
+################################################################################ 
+# package recipe modifications when actually building *-native: 
+################################################################################ 
+ 
+PACKAGE_ARCH:class-native = "${HOST_ARCH}" 
diff --git a/meta/conf/bitbake.conf b/meta/conf/bitbake.conf 
index f1a9438e..f38bb447 100644 
--- a/meta/conf/bitbake.conf 
+++ b/meta/conf/bitbake.conf 
@@ -81,6 +81,7 @@ QEMU_ARCH:riscv64 = "riscv64" 

# Codename of the repository created by the caching class 
DEBDISTRONAME ?= "isar" 
+NATIVELSBSTRING ?= "isarnative" 

# Strings used in sstate signature files 
TARGET_VENDOR = ""

Patch

diff --git a/meta-isar/recipes-app/samefile/samefile_2.14.bb b/meta-isar/recipes-app/samefile/samefile_2.14.bb
index 5e36a2ac..c53c9445 100644
--- a/meta-isar/recipes-app/samefile/samefile_2.14.bb
+++ b/meta-isar/recipes-app/samefile/samefile_2.14.bb
@@ -21,7 +21,7 @@  do_prepare_build() {
     # deb_debianize. Pre-exisiting files will not be recreated, changelog
     # will be prepended unless its latest entry is for CHANGELOG_V.
     cat << EOF > ${WORKDIR}/changelog
-${PN} (0.1) unstable; urgency=low
+${BPN} (0.1) unstable; urgency=low
 
   * a long long time ago there was an early version
 
diff --git a/meta/classes/compat.bbclass b/meta/classes/compat.bbclass
new file mode 100644
index 00000000..7142ec3a
--- /dev/null
+++ b/meta/classes/compat.bbclass
@@ -0,0 +1,49 @@ 
+# This software is a part of ISAR.
+# Copyright (C) 2023 Siemens AG
+#
+# SPDX-License-Identifier: MIT
+
+# this class is "dual-use": it can be inherited (e.g., by bootstrap and image
+# classes) to access variables and functions, and it's also addedd via BBCLASSEXTEND
+# when inheriting multiconfig.bbclass.
+
+################################################################################
+# generic functions
+################################################################################
+
+# calcucate COMPAT_DISTRO_ARCH
+# we can't use simple overrides, because in case we're building a package
+# with a PACKAGE_ARCH != DISTRO_ARCH, overrides would find the wrong value.
+python() {
+    distro_arch = d.getVar('DISTRO_ARCH')
+    compat_distro_arch = d.getVar('COMPAT_DISTRO_ARCH:' + distro_arch)
+    if compat_distro_arch is None and 'class-compat' in d.getVar('OVERRIDES').split(':'):
+        bb.fatal(f"{distro_arch} does not have a compat arch")
+    d.setVar('COMPAT_DISTRO_ARCH', compat_distro_arch)
+}
+
+# function to convert bitbake targets to installable debian packages,
+# e.g., "hello-compat" to "hello:i386".
+def isar_compat_packages(var, d):
+    bb_targets = (d.getVar(var, True) or '').split()
+    packages = []
+    compat_distro_arch = d.getVar('COMPAT_DISTRO_ARCH', True)
+    for t in bb_targets:
+        if t.endswith('-compat'):
+            packages.append(t[:-len('-compat')] + ':' + compat_distro_arch)
+        else:
+            packages.append(t)
+    return ' '.join(packages)
+
+
+################################################################################
+# package recipe modifications when actually building *-compat:
+################################################################################
+
+# check that we can actually build compat (ISAR_ENABLE_COMPAT_ARCH is set)
+python do_fetch:prepend:class-compat() {
+    if not d.getVar('ISAR_ENABLE_COMPAT_ARCH', True) == '1':
+        bb.fatal("compat package requested, but ISAR_ENABLE_COMPAT_ARCH is not set.")
+}
+
+PACKAGE_ARCH:class-compat = "${COMPAT_DISTRO_ARCH}"
diff --git a/meta/classes/debianize.bbclass b/meta/classes/debianize.bbclass
index a6694a00..1b98c02d 100644
--- a/meta/classes/debianize.bbclass
+++ b/meta/classes/debianize.bbclass
@@ -31,7 +31,7 @@  deb_add_changelog() {
 
 	date=$(LANG=C date -R -d @${timestamp})
 	cat <<EOF > ${S}/debian/changelog
-${PN} (${changelog_v}) UNRELEASED; urgency=low
+${BPN} (${changelog_v}) UNRELEASED; urgency=low
 
   * generated by Isar
 
diff --git a/meta/classes/dpkg-base.bbclass b/meta/classes/dpkg-base.bbclass
index ad28f7b3..55cc6655 100644
--- a/meta/classes/dpkg-base.bbclass
+++ b/meta/classes/dpkg-base.bbclass
@@ -5,6 +5,7 @@ 
 # SPDX-License-Identifier: MIT
 
 inherit sbuild
+inherit multiarch
 inherit debianize
 inherit terminal
 inherit repository
diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass
index 539ec51d..8d0dda30 100644
--- a/meta/classes/image.bbclass
+++ b/meta/classes/image.bbclass
@@ -79,9 +79,11 @@  image_do_mounts() {
     buildchroot_do_mounts
 }
 
+inherit compat
+
 ROOTFSDIR = "${IMAGE_ROOTFS}"
 ROOTFS_FEATURES += "clean-package-cache clean-pycache generate-manifest export-dpkg-status clean-log-files clean-debconf-cache"
-ROOTFS_PACKAGES += "${IMAGE_PREINSTALL} ${IMAGE_INSTALL}"
+ROOTFS_PACKAGES += "${IMAGE_PREINSTALL} ${@isar_compat_packages('IMAGE_INSTALL', d)}"
 ROOTFS_MANIFEST_DEPLOY_DIR ?= "${DEPLOY_DIR_IMAGE}"
 ROOTFS_DPKGSTATUS_DEPLOY_DIR ?= "${DEPLOY_DIR_IMAGE}"
 ROOTFS_PACKAGE_SUFFIX ?= "${PN}-${DISTRO}-${MACHINE}"
diff --git a/meta/classes/multiarch.bbclass b/meta/classes/multiarch.bbclass
new file mode 100644
index 00000000..5b280699
--- /dev/null
+++ b/meta/classes/multiarch.bbclass
@@ -0,0 +1,44 @@ 
+# This software is a part of ISAR.
+# Copyright (C) 2021-2022 Siemens AG
+#
+# SPDX-License-Identifier: MIT
+
+BBCLASSEXTEND += "native compat"
+BPN = "${PN}"
+
+python multiarch_virtclass_handler() {
+    def fixup_pn_in_vars(d):
+        vars = 'SRC_URI FILESPATH'.split()
+        for var in vars:
+            v = d.getVar(var, False)
+            if v is not None:
+                d.setVar(var, v.replace('${PN}', '${BPN}'))
+
+    def fixup_depends(suffix, d):
+        vars = 'PROVIDES RPROVIDES DEPENDS RDEPENDS'.split()
+        for var in vars:
+            multiarch_var = []
+            val = d.getVar(var, True)
+            if val is None:
+                continue
+            for v in val.split():
+                if v.endswith('-compat') or v.endswith('-native'):
+                    multiarch_var.append(v)
+                else:
+                    multiarch_var.append(v + suffix)
+            d.setVar(var, ' '.join(multiarch_var))
+
+    pn = e.data.getVar('PN')
+    if pn.endswith('-compat'):
+        e.data.setVar('BPN', pn[:-len('-compat')])
+        e.data.appendVar('OVERRIDES', ':class-compat')
+        fixup_pn_in_vars(e.data)
+        fixup_depends('-compat', e.data)
+    elif pn.endswith('-native'):
+        e.data.setVar('BPN', pn[:-len('-native')])
+        e.data.appendVar('OVERRIDES', ':class-native')
+        fixup_pn_in_vars(e.data)
+        fixup_depends('-native', e.data)
+}
+addhandler multiarch_virtclass_handler
+multiarch_virtclass_handler[eventmask] = "bb.event.RecipePreFinalise"
diff --git a/meta/classes/native.bbclass b/meta/classes/native.bbclass
new file mode 100644
index 00000000..ef20e8bc
--- /dev/null
+++ b/meta/classes/native.bbclass
@@ -0,0 +1,10 @@ 
+# This software is a part of ISAR.
+# Copyright (C) 2023 Siemens AG
+#
+# SPDX-License-Identifier: MIT
+
+################################################################################
+# package recipe modifications when actually building *-native:
+################################################################################
+
+PACKAGE_ARCH:class-native = "${HOST_ARCH}"
diff --git a/meta/conf/bitbake.conf b/meta/conf/bitbake.conf
index f1a9438e..f38bb447 100644
--- a/meta/conf/bitbake.conf
+++ b/meta/conf/bitbake.conf
@@ -81,6 +81,7 @@  QEMU_ARCH:riscv64 = "riscv64"
 
 # Codename of the repository created by the caching class
 DEBDISTRONAME ?= "isar"
+NATIVELSBSTRING ?= "isarnative"
 
 # Strings used in sstate signature files
 TARGET_VENDOR = ""