[libvirt] [jenkins-ci PATCH v4 5/5] lcitool: support generating cross compiler dockerfiles

Daniel P. Berrangé berrange at redhat.com
Thu Feb 21 16:33:54 UTC 2019


Debian's filesystem layout has a nice advantage over Fedora which is
that it can install non-native RPMs in the main root filesystem. It is
thus possible to prepare an x86_64 filesystem containing -dev packages
for a foreign architecture, along with a GCC cross compiler.

QEMU has used this technique to facilitate developer build testing of
non-x86 architectures, since few people have access to physical
hardware for most of these architectures. For the same reason it would
be helpful to libvirt developers.

This patch extends the 'dockerfile' command to 'lcitool' so that it
accepts a '-x $ARCH' argument.

  $ lcitool dockerfile -x s390x libvirt-debian-9 libvirt

This is only valid when using a 'deb' based distro.
Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 guests/host_vars/libvirt-debian-9/main.yml   | 44 +++++++++++++
 guests/host_vars/libvirt-debian-sid/main.yml | 45 ++++++++++++++
 guests/lcitool                               | 65 +++++++++++++++++++-
 guests/vars/mappings.yml                     | 59 ++++++++++++++++++
 4 files changed, 211 insertions(+), 2 deletions(-)

diff --git a/guests/host_vars/libvirt-debian-9/main.yml b/guests/host_vars/libvirt-debian-9/main.yml
index ec7e6b4..3bf4ae1 100644
--- a/guests/host_vars/libvirt-debian-9/main.yml
+++ b/guests/host_vars/libvirt-debian-9/main.yml
@@ -21,3 +21,47 @@ os_name: 'Debian'
 os_version: '9'
 
 ansible_python_interpreter: /usr/bin/python3
+
+arches:
+  aarch64:
+    package_arch: arm64
+    abi: aarch64-linux-gnu
+    cross_gcc: gcc-aarch64-linux-gnu
+  armv6l:
+    package_arch: armel
+    abi: arm-linux-gnueabi
+    cross_gcc: gcc-arm-linux-gnueabi
+  armv7l:
+    package_arch: armhf
+    abi: arm-linux-gnueabihf
+    cross_gcc: gcc-arm-linux-gnueabihf
+  i686:
+    package_arch: i386
+    abi: i386-linux-gnu
+  mips:
+    package_arch: mips
+    abi: mips-linux-gnu
+    cross_gcc: gcc-mips-linux-gnu
+  mipsel:
+    package_arch: mipsel
+    abi: mipsel-linux-gnu
+    cross_gcc: gcc-mipsel-linux-gnu
+  mips64:
+    package_arch: mips64
+    abi: mips64-linux-gnu
+    cross_gcc: gcc-mips64-linux-gnu
+  mips64el:
+    package_arch: mips64el
+    abi: mips64el-linux-gnu
+    cross_gcc: gcc-mips64el-linux-gnu
+  ppc64el:
+    package_arch: ppc64el
+    abi: ppc64el-linux-gnu
+    cross_gcc: gcc-ppc64el-linux-gnu
+  s390x:
+    package_arch: s390x
+    abi: s390x-linux-gnu
+    cross_gcc: gcc-s390x-linux-gnu
+  x86_64:
+    package_arch: amd64
+    abi: x86_64-linux-gnu
diff --git a/guests/host_vars/libvirt-debian-sid/main.yml b/guests/host_vars/libvirt-debian-sid/main.yml
index 1c7a29b..b14a564 100644
--- a/guests/host_vars/libvirt-debian-sid/main.yml
+++ b/guests/host_vars/libvirt-debian-sid/main.yml
@@ -21,3 +21,48 @@ os_name: 'Debian'
 os_version: 'Sid'
 
 ansible_python_interpreter: /usr/bin/python3
+
+arches:
+  aarch64:
+    package_arch: arm64
+    abi: aarch64-linux-gnu
+    cross_gcc: gcc-aarch64-linux-gnu
+  armv6l:
+    package_arch: armel
+    abi: arm-linux-gnueabi
+    cross_gcc: gcc-arm-linux-gnueabi
+  armv7l:
+    package_arch: armhf
+    abi: arm-linux-gnueabihf
+    cross_gcc: gcc-arm-linux-gnueabihf
+  i686:
+    package_arch: i386
+    abi: i686-linux-gnu
+    cross_gcc: gcc-i686-linux-gnu
+  mips:
+    package_arch: mips
+    abi: mips-linux-gnu
+    cross_gcc: gcc-mips-linux-gnu
+  mipsel:
+    package_arch: mipsel
+    abi: mipsel-linux-gnu
+    cross_gcc: gcc-mipsel-linux-gnu
+  mips64:
+    package_arch: mips64
+    abi: mips64-linux-gnu
+    cross_gcc: gcc-mips64-linux-gnu
+  mips64el:
+    package_arch: mips64el
+    abi: mips64el-linux-gnu
+    cross_gcc: gcc-mips64el-linux-gnu
+  ppc64el:
+    package_arch: ppc64el
+    abi: ppc64el-linux-gnu
+    cross_gcc: gcc-ppc64el-linux-gnu
+  s390x:
+    package_arch: s390x
+    abi: s390x-linux-gnu
+    cross_gcc: gcc-s390x-linux-gnu
+  x86_64:
+    package_arch: amd64
+    abi: x86_64-linux-gnu
diff --git a/guests/lcitool b/guests/lcitool
index ae7e4ee..b431b93 100755
--- a/guests/lcitool
+++ b/guests/lcitool
@@ -376,6 +376,10 @@ class Application:
 
         add_hosts_arg(dockerfileparser)
         add_projects_arg(dockerfileparser)
+        dockerfileparser.add_argument(
+            "-x", "--cross-arch",
+            help="cross compiler architecture",
+        )
 
     def _execute_playbook(self, playbook, hosts, projects, git_revision):
         base = Util.get_base()
@@ -546,10 +550,23 @@ class Application:
         os_name = facts["os_name"]
         os_version = facts["os_version"]
         os_full = os_name + os_version
+        cross_facts = None
 
         if package_format not in ["deb", "rpm"]:
             raise Error("Host {} doesn't support Dockerfiles".format(host))
 
+        if args.cross_arch is not None:
+            if "arches" not in facts:
+                raise Error("Non x86_64 arches not supported for this host")
+            if args.cross_arch not in facts["arches"]:
+                raise Error("Arch {} not supported for this host".format(
+                    args.cross_arch))
+            if "cross_gcc" not in facts["arches"][args.cross_arch]:
+                raise Error("Arch {} cross compiler not supported for this host".format
+                            (args.cross_arch))
+
+            cross_build_facts = facts["arches"][args.cross_arch]
+
         projects = self._projects.expand_pattern(args.projects)
         for project in projects:
             if project not in facts["projects"]:
@@ -561,25 +578,50 @@ class Application:
                 )
 
         pkgs = {}
+        cross_pkgs = {}
         base_keys = ["default", package_format, os_name, os_full]
-        keys = base_keys + [k + "-" + self._native_arch for k in base_keys]
+        cross_keys = []
+        if args.cross_arch:
+            keys = base_keys + [k + "-" + args.cross_arch for k in base_keys]
+            cross_keys = [k + "-cross-arch" for k in base_keys]
+        else:
+            keys = base_keys + [k + "-" + self._native_arch for k in base_keys]
+
         # We need to add the base project manually here: the standard
         # machinery hides it because it's an implementation detail
         for project in projects + ["base"]:
             for package in self._projects.get_packages(project):
+                policy = "native"
+                for key in cross_keys:
+                    if key in mappings[package]:
+                        policy = mappings[package][key]
+                if policy not in ["native", "foreign", "skip"]:
+                    raise Error("Unexpected policy {} for {}",
+                                policy, package)
+
                 for key in keys:
                     if key in mappings[package]:
                         pkgs[package] = mappings[package][key]
 
                 if package not in pkgs:
                     continue
-                if pkgs[package] is None:
+                if policy == "foreign" and pkgs[package] is not None:
+                    cross_pkgs[package] = pkgs[package]
+                if pkgs[package] is None or policy in ["skip", "foreign"]:
                     del pkgs[package]
 
         print("FROM {}".format(facts["docker_base"]))
 
         varmap = {}
         varmap["pkgs"] = " \\\n            ".join(sorted(set(pkgs.values())))
+        if args.cross_arch:
+            if package_format != "deb":
+                raise Error("Cannot install foreign {} packages".format(package_format))
+            varmap["cross_arch"] = cross_build_facts["package_arch"]
+            pkg_names = [p + ":" + cross_build_facts["package_arch"] for p in cross_pkgs.values()]
+            pkg_names.append(cross_build_facts["cross_gcc"])
+            varmap["cross_pkgs"] = " \\\n            ".join(sorted(set(pkg_names)))
+            varmap["cross_target"] = cross_build_facts["abi"]
         if package_format == "deb":
             sys.stdout.write(textwrap.dedent("""
                 RUN export DEBIAN_FRONTEND=noninteractive && \\
@@ -590,6 +632,25 @@ class Application:
                     apt-get autoremove -y && \\
                     apt-get autoclean -y
             """).format(**varmap))
+            if args.cross_arch:
+                # Intentionally a separate RUN command from the above
+                # so that the common packages of all cross-built images
+                # share a docker image layer.
+                sys.stdout.write(textwrap.dedent("""
+                    RUN export DEBIAN_FRONTEND=noninteractive && \\
+                        dpkg --add-architecture {cross_arch} && \\
+                        apt-get update && \\
+                        apt-get dist-upgrade -y && \\
+                        apt-get install --no-install-recommends -y \\
+                                {cross_pkgs} && \\
+                        apt-get autoremove -y && \\
+                        apt-get autoclean -y
+
+                    ENV TARGET "{cross_target}"
+                    ENV CONFIGURE_OPTS "--host={cross_target} \\
+                                        --target={cross_target}"
+                    ENV PKG_CONFIG_LIBDIR "/usr/lib/{cross_target}/pkgconfig"
+                """).format(**varmap))
         elif package_format == "rpm":
             if os_name == "Fedora" and os_version == "Rawhide":
                 sys.stdout.write(textwrap.dedent("""
diff --git a/guests/vars/mappings.yml b/guests/vars/mappings.yml
index 4ca8fae..a70a6a5 100644
--- a/guests/vars/mappings.yml
+++ b/guests/vars/mappings.yml
@@ -57,11 +57,15 @@
 #    deb-x86_64: libxen-dev
 #    Fedora-x86_64: xen-devel
 #
+# In parallel with this 'cross-arch: native|foreign|skip' entries can
+# used to indicate the policy when setting up a cross-architecture
+# build environment. If omitted 'native' is assumed
 
 mappings:
 
   apparmor:
     deb: libapparmor-dev
+    deb-cross-arch: foreign
 
   augeas:
     default: augeas
@@ -80,6 +84,7 @@ mappings:
 
   avahi:
     deb: libavahi-client-dev
+    deb-cross-arch: foreign
     pkg: avahi
     rpm: avahi-devel
 
@@ -106,6 +111,7 @@ mappings:
 
   cyrus-sasl:
     deb: libsasl2-dev
+    deb-cross-arch: foreign
     pkg: cyrus-sasl
     rpm: cyrus-sasl-devel
 
@@ -116,6 +122,7 @@ mappings:
 
   device-mapper:
     deb: libdevmapper-dev
+    deb-cross-arch: foreign
     rpm: device-mapper-devel
 
   dnsmasq:
@@ -124,6 +131,7 @@ mappings:
 
   dtrace:
     deb: systemtap-sdt-dev
+    deb-cross-arch: skip
     rpm: systemtap-sdt-devel
 
   dwarves:
@@ -144,6 +152,7 @@ mappings:
 
   fuse:
     deb: libfuse-dev
+    deb-cross-arch: foreign
     pkg: fusefs-libs
     rpm: fuse-devel
 
@@ -159,19 +168,23 @@ mappings:
 
   glib2:
     deb: libglib2.0-dev
+    deb-cross-arch: foreign
     pkg: glib
     rpm: glib2-devel
 
   glibc:
     deb: libc6-dev
+    deb-cross-arch: foreign
     rpm: glibc-devel
 
   glibc-static:
     deb: libc6-dev
+    deb-cross-arch: foreign
     rpm: glibc-static
 
   glusterfs:
     deb: libglusterfs-dev
+    deb-cross-arch: foreign
     rpm: glusterfs-api-devel
     Debian8: glusterfs-common
     Debian9: glusterfs-common
@@ -183,6 +196,7 @@ mappings:
 
   gnutls:
     deb: libgnutls28-dev
+    deb-cross-arch: foreign
     pkg: gnutls
     rpm: gnutls-devel
 
@@ -192,11 +206,13 @@ mappings:
 
   gobject-introspection:
     deb: libgirepository1.0-dev
+    deb-cross-arch: foreign
     pkg: gobject-introspection
     rpm: gobject-introspection-devel
 
   gtk3:
     deb: libgtk-3-dev
+    deb-cross-arch: foreign
     pkg: gtk3
     rpm: gtk3-devel
 
@@ -211,6 +227,7 @@ mappings:
 
   gtk-vnc2:
     deb: libgtk-vnc-2.0-dev
+    deb-cross-arch: foreign
     pkg: gtk-vnc
     rpm: gtk-vnc2-devel
 
@@ -243,32 +260,39 @@ mappings:
 
   json-glib:
     deb: libjson-glib-dev
+    deb-cross-arch: foreign
     pkg: json-glib
     rpm: json-glib-devel
 
   libacl:
     deb: libacl1-dev
+    deb-cross-arch: foreign
     rpm: libacl-devel
 
   libarchive:
     deb: libarchive-dev
+    deb-cross-arch: foreign
     pkg: libarchive
     rpm: libarchive-devel
 
   libattr:
     deb: libattr1-dev
+    deb-cross-arch: foreign
     rpm: libattr-devel
 
   libaudit:
     deb: libaudit-dev
+    deb-cross-arch: foreign
     rpm: audit-libs-devel
 
   libblkid:
     deb: libblkid-dev
+    deb-cross-arch: foreign
     rpm: libblkid-devel
 
   libcap-ng:
     deb: libcap-ng-dev
+    deb-cross-arch: foreign
     rpm: libcap-ng-devel
 
   libcmpiutil:
@@ -276,67 +300,81 @@ mappings:
 
   libconfig:
     deb: libconfig-dev
+    deb-cross-arch: foreign
     pkg: libconfig
     rpm: libconfig-devel
 
   libcurl:
     deb: libcurl4-gnutls-dev
+    deb-cross-arch: foreign
     pkg: curl
     rpm: libcurl-devel
 
   libdbus:
     deb: libdbus-1-dev
+    deb-cross-arch: foreign
     pkg: dbus
     rpm: dbus-devel
 
   libgovirt:
     rpm: libgovirt-devel
     Debian: libgovirt-dev
+    Debian-cross-arch: foreign
     Debian8:
 
   libiscsi:
     deb: libiscsi-dev
+    deb-cross-arch: foreign
     rpm: libiscsi-devel
 
   libnl3:
     deb: libnl-3-dev
+    deb-cross-arch: foreign
     rpm: libnl3-devel
 
   libnlroute3:
     deb: libnl-route-3-dev
+    deb-cross-arch: foreign
     rpm: libnl3-devel
 
   libnuma:
     deb: libnuma-dev
+    deb-cross-arch: foreign
     deb-armv6l:
     deb-armv7l:
     rpm: numactl-devel
 
   libparted:
     deb: libparted-dev
+    deb-cross-arch: foreign
     rpm: parted-devel
 
   libpcap:
     deb: libpcap0.8-dev
+    deb-cross-arch: foreign
     pkg: libpcap
     rpm: libpcap-devel
 
   libpciaccess:
     deb: libpciaccess-dev
+    deb-cross-arch: foreign
     pkg: libpciaccess
     rpm: libpciaccess-devel
 
   librbd:
     deb: librbd-dev
+    deb-cross-arch: foreign
     Fedora: librbd-devel
     CentOS7: librbd1-devel
 
   libselinux:
     deb: libselinux1-dev
+    deb-cross-arch: foreign
     rpm: libselinux-devel
 
   libsoup:
     deb: libsoup2.4-dev
+    deb-cross-arch: foreign
     pkg: libsoup
     rpm: libsoup-devel
 
@@ -344,15 +382,18 @@ mappings:
     pkg: libssh
     rpm: libssh-devel
     Debian: libssh-gcrypt-dev
+    Debian-cross-arch: foreign
     Ubuntu: libssh-dev
 
   libssh2:
     deb: libssh2-1-dev
+    deb-cross-arch: foreign
     pkg: libssh2
     rpm: libssh2-devel
 
   libtirpc:
     deb: libtirpc-dev
+    deb-cross-arch: foreign
     rpm: libtirpc-devel
 
   libtool:
@@ -364,20 +405,24 @@ mappings:
 
   libudev:
     deb: libudev-dev
+    deb-cross-arch: foreign
     rpm: libudev-devel
 
   libuuid:
     deb: uuid-dev
+    deb-cross-arch: foreign
     pkg: e2fsprogs-libuuid
     rpm: libuuid-devel
 
   libxml2:
     deb: libxml2-dev
+    deb-cross-arch: foreign
     pkg: libxml2
     rpm: libxml2-devel
 
   libxslt:
     deb: libxslt1-dev
+    deb-cross-arch: foreign
     pkg: libxslt
     rpm: libxslt-devel
 
@@ -550,6 +595,7 @@ mappings:
 
   netcf:
     deb: libnetcf-dev
+    deb-cross-arch: skip
     rpm: netcf-devel
 
   numad:
@@ -710,6 +756,7 @@ mappings:
 
   python2-devel:
     deb: python-dev
+    deb-cross-arch: foreign
     pkg: python2
     rpm: python2-devel
 
@@ -734,6 +781,7 @@ mappings:
 
   python3-devel:
     deb: python3-dev
+    deb-cross-arch: foreign
     pkg: python3
     Fedora: python3-devel
 
@@ -779,6 +827,7 @@ mappings:
 
   readline:
     deb: libreadline-dev
+    deb-cross-arch: foreign
     pkg: readline
     rpm: readline-devel
 
@@ -793,6 +842,7 @@ mappings:
 
   sanlock:
     deb: libsanlock-dev
+    deb-cross-arch: foreign
     rpm: sanlock-devel
 
   screen:
@@ -814,6 +864,7 @@ mappings:
 
   spice-gtk3:
     deb: libspice-client-gtk-3.0-dev
+    deb-cross-arch: foreign
     pkg: spice-gtk
     rpm: spice-gtk3-devel
 
@@ -845,10 +896,12 @@ mappings:
 
   wireshark:
     deb: wireshark-dev
+    deb-cross-arch: skip
     Fedora: wireshark-devel
     Debian8:
 
   xen:
+    deb-cross-arch: foreign
     deb-x86_64: libxen-dev
     deb-armv7l: libxen-dev
     deb-aarch64: libxen-dev
@@ -856,6 +909,7 @@ mappings:
 
   xfsprogs:
     deb: xfslibs-dev
+    deb-cross-arch: foreign
     rpm: xfsprogs-devel
 
   xmllint:
@@ -868,14 +922,17 @@ mappings:
 
   xz:
     deb: liblzma-dev
+    deb-cross-arch: foreign
     rpm: xz-devel
 
   xz-static:
     deb: liblzma-dev
+    deb-cross-arch: foreign
     Fedora: xz-static
 
   yajl:
     deb: libyajl-dev
+    deb-cross-arch: foreign
     pkg: yajl
     rpm: yajl-devel
 
@@ -886,8 +943,10 @@ mappings:
 
   zlib:
     deb: zlib1g-dev
+    deb-cross-arch: foreign
     rpm: zlib-devel
 
   zlib-static:
     deb: zlib1g-dev
+    deb-cross-arch: foreign
     rpm: zlib-static
-- 
2.20.1




More information about the libvir-list mailing list