Nächste: , Vorige: , Nach oben: Systemkonfiguration   [Inhalt][Index]


3.2 Den Kernel anpassen

Im Kern ist Guix eine quellcodebasierte Distribution mit Substituten (siehe Substitute in Referenzhandbuch zu GNU Guix), daher ist das Erstellen von Paketen aus ihrem Quellcode heraus genauso vorgesehen wie die normale Installation und Aktualisierung von Paketen. Von diesem Standpunkt ist es sinnvoll, zu versuchen, den Zeitaufwand für das Kompilieren von Paketen zu senken, und kürzliche Neuerungen sowie Verbesserungen beim Erstellen und Verteilen von Substituten bleiben ein Diskussionsthema innerhalb von Guix.

Der Kernel braucht zwar keine übermäßigen Mengen an Arbeitsspeicher beim Erstellen, jedoch jede Menge Zeit auf einer durchschnittlichen Maschine. Die offizielle Konfiguration des Kernels umfasst, wie bei anderen GNU/Linux-Distributionen auch, besser zu viel als zu wenig. Das ist der eigentliche Grund, warum seine Erstellung so lange dauert, wenn man den Kernel aus dem Quellcode heraus erstellt.

Man kann den Linux-Kernel jedoch auch als ganz normales Paket beschreiben, das genau wie jedes andere Paket angepasst werden kann. Der Vorgang ist ein klein wenig anders, aber das liegt hauptsächlich an der Art, wie die Paketdefinition geschrieben ist.

Die linux-libre-Kernelpaketdefinition ist tatsächlich eine Prozedur, die ein Paket liefert.

(define* (make-linux-libre* version gnu-revision source supported-systems
                            #:key
                            (extra-version #f)
                            ;; A function that takes an arch and a variant.
                            ;; See kernel-config for an example.
                            (configuration-file #f)
                            (defconfig "defconfig")
                            (extra-options %default-extra-linux-options))
  )

Das momentane linux-libre-Paket zielt ab auf die 5.15.x-Serie und ist wie folgt deklariert:

(define-public linux-libre-5.15
  (make-linux-libre* linux-libre-5.15-version
                     linux-libre-5.15-gnu-revision
                     linux-libre-5.15-source
                     '("x86_64-linux" "i686-linux" "armhf-linux" "aarch64-linux" "riscv64-linux")
                     #:configuration-file kernel-config))

Alle Schlüssel, denen kein Wert zugewiesen wird, erben ihren Vorgabewert von der Definition von make-linux-libre. Wenn Sie die beiden Schnipsel oben vergleichen, ist anzumerken, dass sich der Code-Kommentar in ersterem auf #:configuration-file bezieht. Deswegen ist es nicht so leicht, aus der Definition heraus eine eigene Kernel-Konfiguration anhand der Definition zu schreiben, aber keine Sorge, es gibt andere Möglichkeiten, um mit dem zu arbeiten, was uns gegeben wurde.

Es gibt zwei Möglichkeiten, einen Kernel mit eigener Kernel-Konfiguration zu erzeugen. Die erste ist, eine normale .config-Datei als native Eingabe zu unserem angepassten Kernel hinzuzufügen. Im Folgenden sehen Sie ein Schnipsel aus der angepassten 'configure-Phase der make-linux-libre-Paketdefinition:

(let ((build  (assoc-ref %standard-phases 'build))
      (config (assoc-ref (or native-inputs inputs) "kconfig")))

  ;; Use a custom kernel configuration file or a default
  ;; configuration file.
  (if config
      (begin
        (copy-file config ".config")
        (chmod ".config" #o666))
      (invoke "make" ,defconfig)))

Nun folgt ein Beispiel-Kernel-Paket. Das linux-libre-Paket ist nicht anders als andere Pakete und man kann von ihm erben und seine Felder ersetzen wie bei jedem anderen Paket.

(define-public linux-libre/E2140
  (package
    (inherit linux-libre)
    (native-inputs
     `(("kconfig" ,(local-file "E2140.config"))
      ,@(alist-delete "kconfig"
                      (package-native-inputs linux-libre))))))

Im selben Verzeichnis wie die Datei, die linux-libre-E2140 definiert, befindet sich noch eine Datei namens E2140.config, bei der es sich um eine richtige Kernel-Konfigurationsdatei handelt. Das Schlüsselwort defconfig von make-linux-libre wird hier leer gelassen, so dass die einzige Kernel-Konfiguration im Paket die im native-inputs-Feld ist.

Die zweite Möglichkeit, einen eigenen Kernel zu erzeugen, ist, einen neuen Wert an das extra-options-Schlüsselwort der make-linux-libre-Prozedur zu übergeben. Das extra-options-Schlüsselwort wird zusammen mit einer anderen, direkt darunter definierten Funktion benutzt:

(define %default-extra-linux-options
  `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html
   ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #true)
   ;; Modules required for initrd:
   ("CONFIG_NET_9P" . m)
   ("CONFIG_NET_9P_VIRTIO" . m)
   ("CONFIG_VIRTIO_BLK" . m)
   ("CONFIG_VIRTIO_NET" . m)
   ("CONFIG_VIRTIO_PCI" . m)
   ("CONFIG_VIRTIO_BALLOON" . m)
   ("CONFIG_VIRTIO_MMIO" . m)
   ("CONFIG_FUSE_FS" . m)
   ("CONFIG_CIFS" . m)
   ("CONFIG_9P_FS" . m)))

(define (config->string options)
  (string-join (map (match-lambda
                      ((option . 'm)
                       (string-append option "=m"))
                      ((option . #true)
                       (string-append option "=y"))
                      ((option . #false)
                       (string-append option "=n")))
                    options)
               "\n"))

Und im eigenen configure-Skript des „make-linux-libre“-Pakets:

;; Appending works even when the option wasn't in the
;; file.  The last one prevails if duplicated.
(let ((port (open-file ".config" "a"))
      (extra-configuration ,(config->string extra-options)))
  (display extra-configuration port)
  (close-port port))

(invoke "make" "oldconfig")

Indem wir also kein „configuration-file“ mitgeben, ist .config anfangs leer und danach schreiben wir dort die Sammlung der gewünschten Optionen („Flags“) hinein. Hier ist noch ein eigener Kernel:

(define %macbook41-full-config
  (append %macbook41-config-options
          %file-systems
          %efi-support
          %emulation
          (@@ (gnu packages linux) %default-extra-linux-options)))

(define-public linux-libre-macbook41
  ;; XXX: Auf die interne 'make-linux-libre*'-Prozedur zugreifen, welche privat
  ;; ist und nicht exportiert, desweiteren kann sie sich in Zukunft ändern.
  ((@@ (gnu packages linux) make-linux-libre*)
   (@@ (gnu packages linux) linux-libre-version)
   (@@ (gnu packages linux) linux-libre-gnu-revision)
   (@@ (gnu packages linux) linux-libre-source)
   '("x86_64-linux")
   #:extra-version "macbook41"
   #:extra-options %macbook41-config-options))

Im obigen Beispiel ist %file-systems eine Sammlung solcher „Flags“, mit denen Unterstützung für verschiedene Dateisysteme aktiviert wird, %efi-support aktiviert Unterstützung für EFI und %emulation ermöglicht es einer x86_64-linux-Maschine, auch im 32-Bit-Modus zu arbeiten. Die %default-extra-linux-options sind die oben zitierten, die wieder hinzugefügt werden mussten, weil sie durch das extra-options-Schlüsselwort ersetzt worden waren.

All das klingt machbar, aber woher weiß man überhaupt, welche Module für ein bestimmtes System nötig sind? Es gibt zwei hilfreiche Anlaufstellen, zum einen das Gentoo-Handbuch, zum anderen die Dokumentation des Kernels selbst. Aus der Kernel-Dokumentation erfahren wir, dass make localmodconfig der Befehl sein könnte, den wir wollen.

Um make localmodconfig auch tatsächlich ausführen zu können, müssen wir zunächst den Quellcode des Kernels holen und entpacken:

tar xf $(guix build linux-libre --source)

Sobald wir im Verzeichnis mit dem Quellcode sind, führen Sie touch .config aus, um mit einer ersten, leeren .config anzufangen. make localmodconfig funktioniert so, dass angeschaut wird, was bereits in Ihrer .config steht, und Ihnen mitgeteilt wird, was Ihnen noch fehlt. Wenn die Datei leer bleibt, fehlt eben alles. Der nächste Schritt ist, das hier auszuführen:

guix environment linux-libre -- make localmodconfig

und uns die Ausgabe davon anzuschauen. Beachten Sie, dass die .config-Datei noch immer leer ist. Die Ausgabe enthält im Allgemeinen zwei Arten von Warnungen. Am Anfang der ersten steht „WARNING“ und in unserem Fall können wir sie tatsächlich ignorieren. Bei der zweiten heißt es:

module pcspkr did not have configs CONFIG_INPUT_PCSPKR

Für jede solche Zeile kopieren Sie den CONFIG_XXXX_XXXX-Teil in die .config im selben Verzeichnis und hängen =m an, damit es am Ende so aussieht:

CONFIG_INPUT_PCSPKR=m
CONFIG_VIRTIO=m

Nachdem Sie alle Konfigurationsoptionen kopiert haben, führen Sie noch einmal make localmodconfig aus, um sicherzugehen, dass es keine Ausgaben mehr gibt, deren erstes Wort „module“ ist. Zusätzlich zu diesen maschinenspezifischen Modulen gibt es noch ein paar mehr, die Sie auch brauchen. CONFIG_MODULES brauchen Sie, damit Sie Module getrennt erstellen und laden können und nicht alles im Kernel eingebaut sein muss. Sie brauchen auch CONFIG_BLK_DEV_SD, um von Festplatten lesen zu können. Möglicherweise gibt es auch sonst noch Module, die Sie brauchen werden.

Die Absicht hinter dem hier Niedergeschriebenen ist nicht, eine Anleitung zum Konfigurieren eines eigenen Kernels zu sein. Wenn Sie also vorhaben, den Kernel an Ihre ganz eigenen Bedürfnisse anzupassen, werden Sie in anderen Anleitungen fündig.

Die zweite Möglichkeit, die Kernel-Konfiguration einzurichten, benutzt mehr von Guix’ Funktionalitäten und sie ermöglicht es Ihnen, Gemeinsamkeiten von Konfigurationen zwischen verschiedenen Kernels zu teilen. Zum Beispiel wird eine Reihe von EFI-Konfigurationsoptionen von allen Maschinen, die EFI benutzen, benötigt. Wahrscheinlich haben all diese Kernels eine Schnittmenge zu unterstützender Dateisysteme. Indem Sie Variable benutzen, können Sie leicht auf einen Schlag sehen, welche Funktionalitäten aktiviert sind, und gleichzeitig sicherstellen, dass Ihnen nicht Funktionalitäten des einen Kernels im anderen fehlen.

Was wir hierbei nicht erläutert haben, ist, wie Guix’ initrd und dessen Anpassung funktioniert. Wahrscheinlich werden Sie auf einer Maschine mit eigenem Kernel die initrd verändern müssen, weil sonst versucht wird, bestimmte Module in die initrd einzubinden, die Sie gar nicht erstellen haben lassen.


Nächste: , Vorige: , Nach oben: Systemkonfiguration   [Inhalt][Index]