From: Michael Tremer Date: Sun, 10 Jan 2021 14:44:48 +0000 (+0000) Subject: arch: Drop Python class and replace with C implementation X-Git-Tag: 0.9.28~1285^2~914 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a5600261c8ea98df21013d9d5d7a5ac78d11b4c8;p=pakfire.git arch: Drop Python class and replace with C implementation 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 --- diff --git a/Makefile.am b/Makefile.am index 589760257..c13603409 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/src/_pakfire/_pakfiremodule.c b/src/_pakfire/_pakfiremodule.c index 519b7dac1..b0fed6e95 100644 --- a/src/_pakfire/_pakfiremodule.c +++ b/src/_pakfire/_pakfiremodule.c @@ -26,7 +26,10 @@ #include #include + +#include #include +#include #include "archive.h" #include "capabilities.h" @@ -45,6 +48,26 @@ #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 } }; diff --git a/src/_pakfire/pakfire.c b/src/_pakfire/pakfire.c index 349d8995f..627280c96 100644 --- a/src/_pakfire/pakfire.c +++ b/src/_pakfire/pakfire.c @@ -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 index 000000000..5cf301730 --- /dev/null +++ b/src/libpakfire/arch.c @@ -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 . # +# # +#############################################################################*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 index 000000000..6df436b68 --- /dev/null +++ b/src/libpakfire/include/pakfire/arch.h @@ -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 . # +# # +#############################################################################*/ + +#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 */ diff --git a/src/libpakfire/libpakfire.sym b/src/libpakfire/libpakfire.sym index 51cab4ac3..6b7d81c30 100644 --- a/src/libpakfire/libpakfire.sym +++ b/src/libpakfire/libpakfire.sym @@ -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; diff --git a/src/libpakfire/pakfire.c b/src/libpakfire/pakfire.c index 40985aa79..65193116f 100644 --- a/src/libpakfire/pakfire.c +++ b/src/libpakfire/pakfire.c @@ -34,6 +34,7 @@ #include #include +#include #include #include #include @@ -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 diff --git a/src/pakfire/arch.py b/src/pakfire/arch.py index 8de0b603c..8b1378917 100644 --- a/src/pakfire/arch.py +++ b/src/pakfire/arch.py @@ -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 . # -# # -############################################################################### -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 diff --git a/src/pakfire/base.py b/src/pakfire/base.py index d21a3adbf..15a88ee57 100644 --- a/src/pakfire/base.py +++ b/src/pakfire/base.py @@ -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() diff --git a/src/pakfire/builder.py b/src/pakfire/builder.py index 9ad87a193..165722203 100644 --- a/src/pakfire/builder.py +++ b/src/pakfire/builder.py @@ -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 diff --git a/src/pakfire/cli.py b/src/pakfire/cli.py index 0dc572a52..44a1b5a1c 100644 --- a/src/pakfire/cli.py +++ b/src/pakfire/cli.py @@ -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 diff --git a/src/pakfire/daemon.py b/src/pakfire/daemon.py index cbc205c56..0d31584aa 100644 --- a/src/pakfire/daemon.py +++ b/src/pakfire/daemon.py @@ -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) diff --git a/src/pakfire/system.py b/src/pakfire/system.py index f64cd82f1..5b9b79610 100644 --- a/src/pakfire/system.py +++ b/src/pakfire/system.py @@ -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)