Message ID | 20200218094207.6196-3-dannym@scratchpost.org |
---|---|
State | Accepted |
Headers | show |
Series | system: Add kernel-module-packages to operating-system and use it. | expand |
Context | Check | Description |
---|---|---|
cbaines/comparison | success | View comparision |
cbaines/git branch | success | View Git branch |
cbaines/applying patch | success | View Laminar job |
Hello Danny, Thanks for this patch! A few remarks below. > + ; TODO: system, target. > + #:system #f > + #:target #f))) We need to figure out what #:system and #:target to pass, otherwise it will break system compilation with --system and --target. This is somehow linked to this thread[1]. > +(define (linux-module-database manifest) This is a rather long and over 80 columns procedure. Maybe you should consider split it into several functions. > + (display "FAILED\n" (current-error-port)) This could be more specific and would need to be translated. Mathieu [1]: https://lists.gnu.org/archive/html/guix-patches/2019-12/msg00416.html
Danny Milosavljevic <dannym@scratchpost.org> skribis: > * gnu/system.scm (<operating-system>): Add kernel-module-packages. > (operating-system-directory-base-entries): Use it. > * guix/profiles.scm (linux-module-database): New procedure. Export it. [...] > + (kernel-module-packages operating-system-kernel-module-packages > + (default '())) ; list of packages Technically we don’t require them to be <package> objects, right? Any lowerable object, like <computed-file>, would work? Thus, I’d be tempted to remove “packages” from the field name. ‘kernel-modules’ is not a good idea because one may assume it’s a list of .ko file names. Perhaps ‘kernel-loadable-modules’? Could you also add an entry in guix.texi? > + (mlet* %store-monad ((kernel -> (operating-system-kernel os)) > + (kernel-module-packages -> > + (operating-system-kernel-module-packages os)) Please use short names for local variables; ‘modules’ is enough here. > + (kernel* s/kernel*/kernel/ since there’s no ambiguity. > + (if (null? kernel-module-packages) > + kernel > + (profile-derivation > + (packages->manifest > + (cons kernel kernel-module-packages)) > + #:hooks (list linux-module-database) > + #:locales? #f > + #:allow-collisions? #f > + #:relative-symlinks? #t > + ; TODO: system, target. > + #:system #f > + #:target #f))) You can omit the ‘null?’ case. Also, rather leave out #:system and #:target so that they take their default value. > +(define (linux-module-database manifest) > + (mlet %store-monad > + ((kmod (manifest-lookup-package manifest "kmod"))) Please add a docstring and make the ‘mlet’ a single line. > + (define build > + (with-imported-modules '((guix build utils) > + (guix build union)) > + #~(begin > + (use-modules (srfi srfi-1) > + (srfi srfi-26) > + (guix build utils) > + (guix build union) > + (ice-9 ftw) > + (ice-9 match)) > + (let* ((inputs '#$(manifest-inputs manifest)) > + (input-files (lambda (path) > + (filter file-exists? > + (map (cut string-append <> path) inputs)))) s/path/file/ + use of ‘filter-map’ > + (module-directories (input-files "/lib/modules")) > + (System.maps (input-files "/System.map")) > + (Module.symverss (input-files "/Module.symvers")) ^ Typo. Also perhaps just ‘maps-file’ and ‘symvers-file’. > + (directory-entries (lambda (directory-name) > + (filter (lambda (basename) > + (not (string-prefix? "." > + basename))) > + (scandir directory-name)))) > + ;; Note: Should result in one entry. > + (versions (append-map directory-entries module-directories))) > + ;; TODO: if len(module-directories) == 1: return module-directories[0] > + (mkdir-p (string-append #$output "/lib/modules")) > + ;; Iterate over each kernel version directory (usually one). > + (for-each (lambda (version) > + (let ((destination-directory (string-append #$output "/lib/modules/" version))) > + (when (not (file-exists? destination-directory)) ; unique > + (union-build destination-directory > + ;; All directories with the same version as us. > + (filter-map (lambda (directory-name) > + (if (member version > + (directory-entries directory-name)) > + (string-append directory-name "/" version) > + #f)) > + module-directories) > + #:create-all-directories? #t) > + ;; Delete generated files (they will be recreated shortly). > + (for-each (lambda (basename) > + (when (string-prefix? "modules." basename) > + (false-if-file-not-found > + (delete-file > + (string-append > + destination-directory "/" > + basename))))) > + (directory-entries destination-directory)) > + (unless (zero? (system* (string-append #$kmod "/bin/depmod") > + "-e" ; Report symbols that aren't supplied > + "-w" ; Warn on duplicates > + "-b" #$output ; destination-directory > + "-F" (match System.maps > + ((x) x)) > + "-E" (match Module.symverss > + ((x) x)) > + version)) > + (display "FAILED\n" (current-error-port)) > + (exit #f))))) Like Mathieu wrote, I think this should be shortened and/or decomposed in several functions, with all the effects (‘for-each’, ‘when’, ‘unless’) happening at the very end. I wonder what’s missing form (gnu build linux-modules) to do the “depmod” bit entirely in Scheme. It would be nice for several reasons, one of which is that we wouldn’t need the ‘manifest-lookup-package’ hack, which in turn would allow us to keep this procedure out of (guix profiles). Thoughts? Ludo’.
Hi Ludo, On Sun, 23 Feb 2020 17:36:40 +0100 Ludovic Courtès <ludo@gnu.org> wrote: > Could you also add an entry in guix.texi? OK! > > + (module-directories (input-files "/lib/modules")) > > + (System.maps (input-files "/System.map")) > > + (Module.symverss (input-files "/Module.symvers")) > ^ > Typo. Not really. The file is called "Module.symvers" and those are multiple "Module.symvers"s. It's my naming convention for lists. If we don't want that then I can change it here. > I wonder what’s missing form (gnu build linux-modules) to do the > “depmod” bit entirely in Scheme. Probably not a lot, but there are quite a few binary cache files (.bin) generated by depmod and not by us--not sure whether we want to replicate that complexity given the problems we had even with the initrd stuff. I'm not sure whether those bin files are mandatory or optional to have. > It would be nice for several reasons, > one of which is that we wouldn’t need the ‘manifest-lookup-package’ > hack, which in turn would allow us to keep this procedure out of (guix > profiles). Yeah.
diff --git a/gnu/system.scm b/gnu/system.scm index 01baa248a2..b1cd278044 100644 --- a/gnu/system.scm +++ b/gnu/system.scm @@ -5,6 +5,7 @@ ;;; Copyright © 2016 Chris Marusich <cmmarusich@gmail.com> ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com> ;;; Copyright © 2019 Meiyo Peng <meiyo.peng@gmail.com> +;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -164,6 +165,8 @@ (kernel operating-system-kernel ; package (default linux-libre)) + (kernel-module-packages operating-system-kernel-module-packages + (default '())) ; list of packages (kernel-arguments operating-system-user-kernel-arguments (default '("quiet"))) ; list of gexps/strings (bootloader operating-system-bootloader) ; <bootloader-configuration> @@ -468,10 +471,25 @@ OS." "Return the basic entries of the 'system' directory of OS for use as the value of the SYSTEM-SERVICE-TYPE service." (let ((locale (operating-system-locale-directory os))) - (mlet %store-monad ((kernel -> (operating-system-kernel os)) - (initrd -> (operating-system-initrd-file os)) - (params (operating-system-boot-parameters-file os))) - (return `(("kernel" ,kernel) + (mlet* %store-monad ((kernel -> (operating-system-kernel os)) + (kernel-module-packages -> + (operating-system-kernel-module-packages os)) + (kernel* + (if (null? kernel-module-packages) + kernel + (profile-derivation + (packages->manifest + (cons kernel kernel-module-packages)) + #:hooks (list linux-module-database) + #:locales? #f + #:allow-collisions? #f + #:relative-symlinks? #t + ; TODO: system, target. + #:system #f + #:target #f))) + (initrd -> (operating-system-initrd-file os)) + (params (operating-system-boot-parameters-file os))) + (return `(("kernel" ,kernel*) ("parameters" ,params) ("initrd" ,initrd) ("locale" ,locale)))))) ;used by libc diff --git a/guix/profiles.scm b/guix/profiles.scm index 0d38b2513f..3e25cd7639 100644 --- a/guix/profiles.scm +++ b/guix/profiles.scm @@ -10,6 +10,7 @@ ;;; Copyright © 2017 Maxim Cournoyer <maxim.cournoyer@gmail.com> ;;; Copyright © 2019 Kyle Meyer <kyle@kyleam.com> ;;; Copyright © 2019 Mathieu Othacehe <m.othacehe@gmail.com> +;;; Copyright © 2020 Danny Milosavljevic <dannym@scratchpost.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -139,7 +140,9 @@ %current-profile ensure-profile-directory canonicalize-profile - user-friendly-profile)) + user-friendly-profile + + linux-module-database)) ;;; Commentary: ;;; @@ -1137,6 +1140,77 @@ for both major versions of GTK+." (hook . gtk-im-modules))) (return #f))))) +(define (linux-module-database manifest) + (mlet %store-monad + ((kmod (manifest-lookup-package manifest "kmod"))) + (define build + (with-imported-modules '((guix build utils) + (guix build union)) + #~(begin + (use-modules (srfi srfi-1) + (srfi srfi-26) + (guix build utils) + (guix build union) + (ice-9 ftw) + (ice-9 match)) + (let* ((inputs '#$(manifest-inputs manifest)) + (input-files (lambda (path) + (filter file-exists? + (map (cut string-append <> path) inputs)))) + (module-directories (input-files "/lib/modules")) + (System.maps (input-files "/System.map")) + (Module.symverss (input-files "/Module.symvers")) + (directory-entries (lambda (directory-name) + (filter (lambda (basename) + (not (string-prefix? "." + basename))) + (scandir directory-name)))) + ;; Note: Should result in one entry. + (versions (append-map directory-entries module-directories))) + ;; TODO: if len(module-directories) == 1: return module-directories[0] + (mkdir-p (string-append #$output "/lib/modules")) + ;; Iterate over each kernel version directory (usually one). + (for-each (lambda (version) + (let ((destination-directory (string-append #$output "/lib/modules/" version))) + (when (not (file-exists? destination-directory)) ; unique + (union-build destination-directory + ;; All directories with the same version as us. + (filter-map (lambda (directory-name) + (if (member version + (directory-entries directory-name)) + (string-append directory-name "/" version) + #f)) + module-directories) + #:create-all-directories? #t) + ;; Delete generated files (they will be recreated shortly). + (for-each (lambda (basename) + (when (string-prefix? "modules." basename) + (false-if-file-not-found + (delete-file + (string-append + destination-directory "/" + basename))))) + (directory-entries destination-directory)) + (unless (zero? (system* (string-append #$kmod "/bin/depmod") + "-e" ; Report symbols that aren't supplied + "-w" ; Warn on duplicates + "-b" #$output ; destination-directory + "-F" (match System.maps + ((x) x)) + "-E" (match Module.symverss + ((x) x)) + version)) + (display "FAILED\n" (current-error-port)) + (exit #f))))) + versions) + (exit #t))))) + (gexp->derivation "linux-module-database" build + #:local-build? #t + #:substitutable? #f + #:properties + `((type . profile-hook) + (hook . linux-module-database))))) + (define (xdg-desktop-database manifest) "Return a derivation that builds the @file{mimeinfo.cache} database from desktop files. It's used to query what applications can handle a given