]> git.ipfire.org Git - pakfire.git/commitdiff
arch: Drop Python class and replace with C implementation
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 10 Jan 2021 14:44:48 +0000 (14:44 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 10 Jan 2021 14:44:48 +0000 (14:44 +0000)
It is easier to handle architectures just as a string and call functions
that figure out any details when we need them.

Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
13 files changed:
Makefile.am
src/_pakfire/_pakfiremodule.c
src/_pakfire/pakfire.c
src/libpakfire/arch.c [new file with mode: 0644]
src/libpakfire/include/pakfire/arch.h [new file with mode: 0644]
src/libpakfire/libpakfire.sym
src/libpakfire/pakfire.c
src/pakfire/arch.py
src/pakfire/base.py
src/pakfire/builder.py
src/pakfire/cli.py
src/pakfire/daemon.py
src/pakfire/system.py

index 589760257163f096c8d8a488c67d15a6b96d34fa..c1360340987c8c1e3412c2b2c615bda48dfa1191 100644 (file)
@@ -119,7 +119,6 @@ install-exec-local:
 pakfire_PYTHON = \
        src/pakfire/__init__.py \
        src/pakfire/__version__.py \
-       src/pakfire/arch.py \
        src/pakfire/base.py \
        src/pakfire/builder.py \
        src/pakfire/cgroup.py \
@@ -272,6 +271,7 @@ lib_LTLIBRARIES += \
        libpakfire.la
 
 libpakfire_la_SOURCES = \
+       src/libpakfire/arch.c \
        src/libpakfire/archive.c \
        src/libpakfire/errno.c \
        src/libpakfire/execute.c \
@@ -296,6 +296,7 @@ libpakfire_la_SOURCES = \
        src/libpakfire/util.c
 
 pkginclude_HEADERS += \
+       src/libpakfire/include/pakfire/arch.h \
        src/libpakfire/include/pakfire/archive.h \
        src/libpakfire/include/pakfire/constants.h \
        src/libpakfire/include/pakfire/errno.h \
index 519b7dac12b377157d7536a924337090c311201f..b0fed6e953bb4ea48f1dbc2e494400b3e5bffb87 100644 (file)
 #include <sys/personality.h>
 
 #include <solv/solver.h>
+
+#include <pakfire/arch.h>
 #include <pakfire/package.h>
+#include <pakfire/util.h>
 
 #include "archive.h"
 #include "capabilities.h"
 #include "transaction.h"
 #include "util.h"
 
+static PyObject* _pakfire_native_arch() {
+       const char* arch = pakfire_arch_native();
+       if (!arch)
+               Py_RETURN_NONE;
+
+       return PyUnicode_FromString(arch);
+}
+
+static PyObject* _pakfire_arch_supported_by_host(PyObject* self, PyObject* args) {
+       const char* name = NULL;
+
+       if (!PyArg_ParseTuple(args, "s", &name))
+               return NULL;
+
+       if (pakfire_arch_supported_by_host(name))
+               Py_RETURN_TRUE;
+
+       Py_RETURN_FALSE;
+}
+
 static PyMethodDef pakfireModuleMethods[] = {
        {"performance_index", (PyCFunction)performance_index, METH_VARARGS, NULL},
        {"version_compare", (PyCFunction)version_compare, METH_VARARGS, NULL},
@@ -52,6 +75,8 @@ static PyMethodDef pakfireModuleMethods[] = {
        {"personality", (PyCFunction)_personality, METH_VARARGS, NULL},
        {"sync", (PyCFunction)_sync, METH_NOARGS, NULL},
        {"unshare", (PyCFunction)_unshare, METH_VARARGS, NULL},
+       {"native_arch", (PyCFunction)_pakfire_native_arch, METH_NOARGS, NULL },
+       {"arch_supported_by_host", (PyCFunction)_pakfire_arch_supported_by_host, METH_VARARGS, NULL },
        { NULL, NULL, 0, NULL }
 };
 
index 349d8995fed6c09fb90b4ada764ba8a3505cf05e..627280c96e2e5770fa94c4567dc3bb258c825e34 100644 (file)
@@ -45,7 +45,7 @@ static int Pakfire_init(PakfireObject* self, PyObject* args, PyObject* kwds) {
        const char* path = NULL;
     const char* arch = NULL;
 
-       if (!PyArg_ParseTuple(args, "s|s", &path, &arch))
+       if (!PyArg_ParseTuple(args, "s|z", &path, &arch))
                return -1;
 
        // Create a new Pakfire instance
diff --git a/src/libpakfire/arch.c b/src/libpakfire/arch.c
new file mode 100644 (file)
index 0000000..5cf3017
--- /dev/null
@@ -0,0 +1,158 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2021 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/utsname.h>
+
+#include <pakfire/arch.h>
+#include <pakfire/constants.h>
+#include <pakfire/private.h>
+#include <pakfire/util.h>
+
+struct pakfire_arch {
+       const char* name;
+       const char* platform;
+       const char* compatible[5];
+};
+
+static const struct pakfire_arch PAKFIRE_ARCHES[] = {
+       // x86
+       {
+               .name = "x86_64",
+               .platform = "x86",
+               .compatible = { "i686", NULL },
+       },
+       {
+               .name = "i686",
+               .platform = "x86",
+       },
+
+       // ARM
+       {
+               .name = "aarch64",
+               .platform = "arm",
+       },
+       {
+               .name = "armv7hl",
+               .platform = "arm",
+               .compatible = { "armv7l", "armv6l", "armv5tejl", "armv5tel", NULL },
+       },
+       {
+               .name = "armv7l",
+               .platform = "arm",
+               .compatible = { "armv6l", "armv5tejl", "armv5tel", NULL },
+       },
+       {
+               .name = "armv6l",
+               .platform = "arm",
+               .compatible = { "armv5tejl", "armv5tel", NULL },
+       },
+       {
+               .name = "armv5tejl",
+               .platform = "arm",
+               .compatible = { "armv5tel", NULL },
+       },
+       {
+               .name = "armv5tel",
+               .platform = "arm",
+       },
+       NULL,
+};
+
+static const struct pakfire_arch* pakfire_arch_find(const char* name) {
+       for (const struct pakfire_arch* arch = PAKFIRE_ARCHES; arch; arch++) {
+               if (strcmp(arch->name, name) == 0)
+                       return arch;
+       }
+
+       return NULL;
+}
+
+PAKFIRE_EXPORT int pakfire_arch_supported(const char* name) {
+       const struct pakfire_arch* arch = pakfire_arch_find(name);
+
+       if (arch)
+               return 1;
+
+       return 0;
+}
+
+PAKFIRE_EXPORT const char* pakfire_arch_platform(const char* name) {
+       const struct pakfire_arch* arch = pakfire_arch_find(name);
+
+       if (arch && arch->platform)
+               return arch->platform;
+
+       return NULL;
+}
+
+PAKFIRE_EXPORT char* pakfire_arch_machine(const char* arch, const char* vendor) {
+       if (!vendor)
+               vendor = "unknown";
+
+       // Format string
+       char buffer[STRING_SIZE];
+       snprintf(buffer, STRING_SIZE - 1, "%s-%s-linux-gnu", arch, vendor);
+
+       // Make everything lowercase
+       for (unsigned int i = 0; i < strlen(buffer); i++)
+               buffer[i] = tolower(buffer[i]);
+
+       return pakfire_strdup(buffer);
+}
+
+static const char* __pakfire_arch_native = NULL;
+
+PAKFIRE_EXPORT const char* pakfire_arch_native() {
+       struct utsname buf;
+
+       if (!__pakfire_arch_native) {
+               if (uname(&buf) < 0)
+                       return NULL;
+
+               __pakfire_arch_native = pakfire_strdup(buf.machine);
+       }
+
+       return __pakfire_arch_native;
+}
+
+PAKFIRE_EXPORT int pakfire_arch_is_compatible(const char* name, const char* compatible_arch) {
+       const struct pakfire_arch* arch = pakfire_arch_find(name);
+
+       if (!arch)
+               return 0;
+
+       for (unsigned int i = 0; arch->compatible[i]; i++) {
+               if (strcmp(arch->compatible[i], compatible_arch) == 0)
+                       return 1;
+       }
+
+       return 0;
+}
+
+PAKFIRE_EXPORT int pakfire_arch_supported_by_host(const char* name) {
+       const char* native_arch = pakfire_arch_native();
+
+       // Check if those two architectures are compatible
+       return pakfire_arch_is_compatible(native_arch, name);
+}
diff --git a/src/libpakfire/include/pakfire/arch.h b/src/libpakfire/include/pakfire/arch.h
new file mode 100644 (file)
index 0000000..6df436b
--- /dev/null
@@ -0,0 +1,31 @@
+/*#############################################################################
+#                                                                             #
+# Pakfire - The IPFire package management system                              #
+# Copyright (C) 2021 Pakfire development team                                 #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef PAKFIRE_ARCH_H
+#define PAKFIRE_ARCH_H
+
+int pakfire_arch_supported(const char* name);
+const char* pakfire_arch_platform(const char* name);
+char* pakfire_arch_machine(const char* arch, const char* vendor);
+const char* pakfire_arch_native();
+int pakfire_arch_is_compatible(const char* name, const char* compatible_arch);
+int pakfire_arch_supported_by_host(const char* name);
+
+#endif /* PAKFIRE_ARCH_H */
index 51cab4ac3cc911a25719dbc4a9c380abad2f26db..6b7d81c30fea993598dec5499f21cc370d4a677d 100644 (file)
@@ -43,6 +43,14 @@ global:
        pakfire_version_compare;
        pakfire_whatprovides;
 
+       # arch
+       pakfire_arch_is_compatible;
+       pakfire_arch_machine;
+       pakfire_arch_native;
+       pakfire_arch_platform;
+       pakfire_arch_supported;
+       pakfire_arch_supported_by_host;
+
        # archive
        pakfire_archive_count_signatures;
        pakfire_archive_create;
index 40985aa791c8f300505a2f9f29237c8169f68dc7..65193116fc99f0d9a78b87bffc0a1c997c139c14 100644 (file)
@@ -34,6 +34,7 @@
 #include <solv/poolarch.h>
 #include <solv/queue.h>
 
+#include <pakfire/arch.h>
 #include <pakfire/constants.h>
 #include <pakfire/logging.h>
 #include <pakfire/package.h>
@@ -86,13 +87,21 @@ static int log_priority(const char* priority) {
 }
 
 PAKFIRE_EXPORT Pakfire pakfire_create(const char* path, const char* arch) {
+       // Default to the native architecture
+       if (!arch)
+               arch = pakfire_arch_native();
+
+       // Check if the architecture is supported
+       if (!pakfire_arch_supported(arch))
+               return NULL;
+
        Pakfire pakfire = pakfire_calloc(1, sizeof(*pakfire));
        if (pakfire) {
                pakfire->nrefs = 1;
 
                pakfire->path = pakfire_strdup(path);
-               if (!arch)
-                       arch = system_machine();
+
+               // Set architecture
                pakfire->arch = pakfire_strdup(arch);
 
                // Setup logging
index 8de0b603c0e8a1f99ee155489e2ab20cb8d8eb33..8b137891791fe96927ad78e64b0aad7bded08bdc 100644 (file)
@@ -1,130 +1 @@
-#!/usr/bin/python3
-###############################################################################
-#                                                                             #
-# Pakfire - The IPFire package management system                              #
-# Copyright (C) 2016 Pakfire development team                                 #
-#                                                                             #
-# This program is free software: you can redistribute it and/or modify        #
-# it under the terms of the GNU General Public License as published by        #
-# the Free Software Foundation, either version 3 of the License, or           #
-# (at your option) any later version.                                         #
-#                                                                             #
-# This program is distributed in the hope that it will be useful,             #
-# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
-# GNU General Public License for more details.                                #
-#                                                                             #
-# You should have received a copy of the GNU General Public License           #
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
-#                                                                             #
-###############################################################################
 
-import logging
-
-log = logging.getLogger("pakfire.arch")
-log.propagate = 1
-
-class Arch(object):
-       def __init__(self, name):
-               assert name
-
-               self.name = name
-
-       def __str__(self):
-               return self.name
-
-       def __repr__(self):
-               return "<%s %s>" % (self.__class__.__name__, self.name)
-
-       def __eq__(self, other):
-               return self.name == other.name
-
-       @property
-       def platform(self):
-               """
-                       Returns the "class" this architecture belongs to.
-               """
-               if self.name.startswith("arm") or self.name == "aarch64":
-                       return "arm"
-
-               if self.name in ("i686", "x86_64"):
-                       return "x86"
-
-               return "unknown"
-
-       def get_machine(self, vendor=None):
-               if vendor is None:
-                       vendor = "unknown"
-
-               # Make vendor lowercase
-               vendor = vendor.lower()
-               assert vendor
-
-               s = "%s-%s-linux-gnu" % (self.name, vendor)
-
-               if self.name.startswith("arm"):
-                       s += "eabi"
-
-               return s
-
-       def get_buildtarget(self, vendor=None):
-               machine = self.get_machine(vendor)
-
-               # Cut off last segment of machine.
-               return machine.replace("-gnu", "")
-
-       @property
-       def compatible_arches(self):
-               """
-                       Returns a list of all architectures that are
-                       compatible (i.e. can be emulated)
-               """
-               x = {
-                       # Host arch : Can build these arches.
-                       # x86
-                       "x86_64"    : ["x86_64", "i686",],
-                       "i686"      : ["i686",],
-
-                       # ARM
-                       "armv5tel"  : ["armv5tel",],
-                       "armv5tejl" : ["armv5tel",],
-                       "armv6l"    : ["armv5tel",],
-                       "armv7l"    : ["armv7hl", "armv5tel",],
-                       "armv7hl"   : ["armv7hl", "armv5tel",],
-
-                       "aarch64"   : ["aarch64",],
-               }
-
-               try:
-                       return (Arch(a) for a in x[self.name])
-               except KeyError:
-                       return []
-
-       def is_compatible_with(self, arch):
-               """
-                       Returns True if the given architecture is compatible
-                       with this architecture.
-               """
-               return arch in self.compatible_arches
-
-       @property
-       def personality(self):
-               """
-                       Return the personality of the target system.
-
-                       If host and target system are of the same architecture, we return
-                       None to skip the setting of the personality in the build chroot.
-               """
-               arch2personality = {
-                       "x86_64" : "linux64",
-                       "i686"   : "linux32",
-                       "i586"   : "linux32",
-                       "i486"   : "linux32",
-               }
-
-               try:
-                       personality = arch2personality[self.name]
-               except KeyError:
-                       personality = None
-
-               return personality
index d21a3adbf2ad0ff9c628a55b3037efd8c41d6152..15a88ee575a85bc1c4389052ccb0fc8d08008df1 100644 (file)
@@ -43,7 +43,7 @@ class Pakfire(_pakfire.Pakfire):
        mode = None
 
        def __init__(self, path="/", config=None, arch=None, distro=None, cache_path=None, offline=False):
-               _pakfire.Pakfire.__init__(self, path, "%s" % (arch or system.native_arch))
+               _pakfire.Pakfire.__init__(self, path, arch)
 
                # Initialise logging system
                self.log = self._setup_logger()
index 9ad87a1937540baba8c1c9a49650fb8440ff497a..1657222037957f891da9e2016ce08ae18f94fe8e 100644 (file)
@@ -31,7 +31,6 @@ import time
 import uuid
 
 from . import _pakfire
-from . import arch
 from . import base
 from . import cgroup
 from . import config
@@ -100,10 +99,10 @@ class Builder(object):
                self._lock = None
 
                # Architecture to build for
-               self.arch = arch or system.arch
+               self.arch = arch or _pakfire.native_arch()
 
                # Check if this host can build the requested architecture.
-               if not system.host_supports_arch(self.arch):
+               if not _pakfire.arch_supported_by_host(self.arch):
                        raise BuildError(_("Cannot build for %s on this host") % self.arch)
 
                # Initialize a cgroup (if supported)
@@ -453,10 +452,6 @@ class BuilderContext(object):
 
                self.setup()
 
-       @property
-       def arch(self):
-               return self.pakfire.arch
-
        @property
        def environ(self):
                env = MINIMAL_ENVIRONMENT.copy()
@@ -487,11 +482,10 @@ class BuilderContext(object):
 
                # Fake UTS_MACHINE, when we cannot use the personality syscall and
                # if the host architecture is not equal to the target architecture.
-               if not self.arch.personality and \
-                               not system.native_arch == self.arch.name:
+               if not _pakfire.native_arch() == self.pakfire.arch:
                        env.update({
                                "LD_PRELOAD"  : "/usr/lib/libpakfire_preload.so",
-                               "UTS_MACHINE" : self.arch.name,
+                               "UTS_MACHINE" : self.pakfire.arch,
                        })
 
                return env
index 0dc572a52fd2e660b333c3086efd5c9b667be2ce..44a1b5a1cfbe47bfe4658967b287e7e06fc01a72 100644 (file)
@@ -29,7 +29,6 @@ import sys
 import tempfile
 import time
 
-from . import arch
 from . import base
 from . import builder
 from . import client
@@ -493,11 +492,7 @@ class CliBuilder(Cli):
                return parser.parse_args()
 
        def builder(self, ns):
-               a = arch.Arch(ns.arch or system.native_arch)
-
-               b = builder.Builder(arch=a)
-
-               return b
+               return builder.Builder(arch=ns.arch)
 
        def handle_build(self, ns):
                package, = ns.package
index cbc205c562b1324c4a347fed279244ed0ea6cdf5..0d31584aa05708eae746884d3f4d87c9b73977ca 100644 (file)
@@ -15,6 +15,7 @@ import pakfire.util
 
 from .system import system
 
+from . import _pakfire
 from . import base
 from . import config
 from . import http
@@ -329,7 +330,7 @@ class PakfireDaemonKeepalive(multiprocessing.Process):
                        # CPU info
                        "cpu_model"       : system.cpu_model,
                        "cpu_count"       : system.cpu_count,
-                       "cpu_arch"        : system.native_arch,
+                       "cpu_arch"        : _pakfire.native_arch(),
                        "cpu_bogomips"    : system.cpu_bogomips,
 
                        # Memory + swap
@@ -339,9 +340,6 @@ class PakfireDaemonKeepalive(multiprocessing.Process):
                        # Pakfire + OS
                        "pakfire_version" : PAKFIRE_VERSION,
                        "os_name"         : system.distro.pretty_name,
-
-                       # Supported arches
-                       "supported_arches" : ",".join(system.supported_arches),
                }
                self.hub._request("/builders/info", method="POST", data=data)
 
index f64cd82f1d7de06e9ea66dfb0e628d8508c8665d..5b9b79610be2326ceb54ba61a482f236d6a18966 100644 (file)
@@ -24,7 +24,6 @@ import os
 import socket
 import tempfile
 
-from . import arch
 from . import distro
 from . import shell
 
@@ -38,9 +37,6 @@ class System(object):
                the system this software is running on.
        """
        def __init__(self):
-               # Load the system's native architecture
-               self.arch = arch.Arch(self.native_arch)
-
                # Load the system's distribution
                self.distro = distro.Distribution()
 
@@ -54,27 +50,6 @@ class System(object):
 
                return hn
 
-       @property
-       def native_arch(self):
-               """
-                       Return the native architecture of the host we
-                       are running on.
-               """
-               return os.uname()[4]
-
-       @property
-       def supported_arches(self):
-               """
-                       Check what architectures can be built on this host.
-               """
-               return self.arch.compatible_arches
-
-       def host_supports_arch(self, arch):
-               """
-                       Check if this host can build for the target architecture "arch".
-               """
-               return self.arch.is_compatible_with(arch)
-
        @property
        def cpu_count(self):
                """
@@ -418,7 +393,6 @@ class Mountpoint(object):
 if __name__ == "__main__":
        print("Hostname", system.hostname)
        print("Arch", system.arch)
-       print("Supported arches", system.supported_arches)
 
        print("CPU Model", system.cpu_model)
        print("CPU count", system.cpu_count)