unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
From: Maxim Cournoyer <maxim.cournoyer@gmail.com>
To: Stefan <stefan-guix@vodafonemail.de>
Cc: "Vagrant Cascadian" <vagrant@debian.org>,
	"Danny Milosavljevic" <dannym@scratchpost.org>,
	"Ludovic Courtès" <ludo@gnu.org>,
	phodina <phodina@protonmail.com>,
	48314@debbugs.gnu.org
Subject: [bug#48314] [PATCH] Install guix system on Raspberry Pi
Date: Thu, 01 Dec 2022 11:22:41 -0500	[thread overview]
Message-ID: <87ilivhz5a.fsf_-_@gmail.com> (raw)
In-Reply-To: <204332DD-AA02-4A31-9B48-FB3FAB9BD8F3@vodafonemail.de> (Stefan's message of "Thu, 22 Sep 2022 18:18:59 +0200")

Hi,

Stefan <stefan-guix@vodafonemail.de> writes:

[...]

> new file mode 100644
> index 0000000000..0cfaffe056
> --- /dev/null
> +++ b/guix/build/kconfig.scm

[...]

> +(define-module (guix build kconfig)
> +  #:use-module  (ice-9 rdelim)
> +  #:use-module  (ice-9 regex)
> +  #:use-module  (srfi srfi-1)
> +  #:use-module  (srfi srfi-26)
> +  #:export (modify-defconfig
> +            verify-config))
> +
> +;; Commentary:
> +;;
> +;; Builder-side code to modify configurations for the Kconfig build system as
> +;; used by Linux and U-Boot.
> +;;
> +;; Code:
> +
> +(define (config-string->pair config-string)
> +  "Parse a configuration string like \"CONFIG_EXAMPLE=m\" into a key-value pair.
> +An error is thrown for invalid configurations.
> +
> +\"CONFIG_A=y\"            -> '(\"CONFIG_A\" . \"y\")
> +\"CONFIG_B=\\\"\\\"\"         -> '(\"CONFIG_B\" . \"\\\"\\\"\")
> +\"CONFIG_C=\"             -> '(\"CONFIG_C\" . \"\")
> +\"# CONFIG_E is not set\" -> '(\"CONFIG_E\" . #f)
> +\"CONFIG_D\"              -> '(\"CONFIG_D\" . #f)
> +\"# Any comment\"         -> '(#f . \"# Any comment\")
> +\"\"                      -> '(#f . \"\")
> +\"# CONFIG_E=y\"          -> (error \"Invalid configuration\")
> +\"CONFIG_E is not set\"   -> (error \"Invalid configuration\")
> +\"Anything else\"         -> (error \"Invalid configuration\")"
> +  (define config-regexp
> +    (make-regexp
> +     ;; (match:substring (string-match "=(.*)" "=") 1) returns "", but the
> +     ;; pattern "=(.+)?" makes it return #f instead.  From a "CONFIG_A=" we like
> +     ;; to get "", which later emits "CONFIG_A=" again.
> +     "^ *(#[\\t ]*)?(CONFIG_[a-zA-Z0-9_]+)([\\t ]*=[\\t ]*(.*)|([\\t ]+is[\\t ]+not[\\t ]+set))?$"))
> +
> +  (define config-comment-regexp
> +    (make-regexp "^([\\t ]*(#.*)?)$"))
> +
> +  (let ((match (regexp-exec config-regexp (string-trim-right config-string))))
> +    (if match
> +        (let* ((comment (match:substring match 1))
> +               (key (match:substring match 2))
> +               (unset (match:substring match 5))
> +               (value (and (not comment)
> +                           (not unset)
> +                           (match:substring match 4))))
> +          (if (eq? (not comment) (not unset))
> +              ;; The key is uncommented and set or commented and unset.
> +              (cons key value)
> +              ;; The key is set or unset ambigiously.
> +              (error (format #f "Invalid configuration, did you mean \"~a\"?"
> +                             (pair->config-string (cons key #f)))
> +                     config-string)))
> +        ;; This is not a valid or ambigious config-string, but mayby a comment.
> +        (if (regexp-exec config-comment-regexp config-string)
> +            ;; We keep valid comments.
> +            (cons #f config-string)
> +            (error "Invalid configuration" config-string)))))
> +
> +(define (pair->config-string pair)
> +  "Convert a PAIR back to a config-string."
> +  (let* ((key (first pair))
> +         (value (cdr pair)))
> +    (if (string? key)
> +        (if (string? value)
> +            (string-append key "=" value)
> +            (string-append "# " key " is not set"))
> +        value)))
> +
> +(define (defconfig->alist defconfig)
> +  "Convert the content of a DEFCONFIG (or .config) file into an alist."
> +  (with-input-from-file defconfig
> +    (lambda ()
> +      (let loop ((alist '())
> +                 (line (read-line)))
> +        (if (eof-object? line)
> +            ;; Building the alist is done, now check for duplicates.
> +            (let loop ((keys (map first (filter first alist)))
                                           ^
What is this filter used for here? EDIT: saw later, it's used to filter
out comments.

[...]

> +(define (verify-config config defconfig)
> +  "Verify that the CONFIG file contains all configurations from the DEFCONFIG
> +file and return #t in this case. Otherwise throw an error with the mismatching
> +keys and their values."
> +  (let* ((config-pairs (defconfig->alist config))
> +         (defconfig-pairs (defconfig->alist defconfig))
> +         (mismatching-pairs
> +          (remove (lambda (pair)
> +                    ;; Remove all configurations, whose values are #f and whose
> +                    ;; keys are not in config-pairs, as not in config-pairs
> +                    ;; means unset, …
> +                    (and (not (cdr pair))
> +                         (not (assoc-ref config-pairs (first pair)))))
> +                  ;; … from the defconfig-pairs different to config-pairs.

So, it finds mismatched configurations that exist in both CONFIG and
DEFCONFIG, but it doesn't error when there are configs that exist in
DEFCONFIG but missing from CONFIG, right?  Should it?

> +                  (lset-difference equal?
> +                                   ;; Remove comments by filtering with first.
> +                                   (filter first defconfig-pairs)
> +                                   config-pairs))))
> +    (if (null? mismatching-pairs)
> +        #t
> +        (error (format #f
> +                       "Mismatching configurations in ~a and ~a"
> +                       config
> +                       defconfig)
> +               (map (lambda (mismatching-pair)
> +                      (let* ((key (first mismatching-pair))
> +                             (defconfig-value (cdr mismatching-pair))
> +                             (config-value (assoc-ref config-pairs key)))
> +                        (cons key (list (list config-value defconfig-value)))))
> +                    mismatching-pairs)))))
>
>

I've made the following mostly cosmetic changes:

--8<---------------cut here---------------start------------->8---
2 files changed, 43 insertions(+), 45 deletions(-)
gnu/packages/bootloaders.scm | 18 +++++++++---------
guix/build/kconfig.scm       | 70 ++++++++++++++++++++++++++++++++++------------------------------------

modified   gnu/packages/bootloaders.scm
@@ -792,9 +792,9 @@ (define*-public (make-u-boot-package board triplet #:key defconfig configs)
                                                      "_" "-")))
       (native-inputs
        `(,@(if (not (same-arch?))
-             `(("cross-gcc" ,(cross-gcc triplet))
-               ("cross-binutils" ,(cross-binutils triplet)))
-             `())
+               `(("cross-gcc" ,(cross-gcc triplet))
+                 ("cross-binutils" ,(cross-binutils triplet)))
+               `())
          ,@(package-native-inputs u-boot)))
       (arguments
        `(#:modules ((ice-9 ftw)
@@ -808,8 +808,8 @@ (define*-public (make-u-boot-package board triplet #:key defconfig configs)
          #:make-flags
          (list "HOSTCC=gcc"
                ,@(if (not (same-arch?))
-                   `((string-append "CROSS_COMPILE=" ,triplet "-"))
-                   '()))
+                     `((string-append "CROSS_COMPILE=" ,triplet "-"))
+                     '()))
          #:phases
          (modify-phases %standard-phases
            (replace 'configure
@@ -828,7 +828,7 @@ (define*-public (make-u-boot-package board triplet #:key defconfig configs)
                        (apply invoke "make" `(,@make-flags ,config-name))
                        (verify-config ".config" config-file))
                      (begin
-                       (display "Invalid board name. Valid board names are:"
+                       (display "invalid board name; valid board names are:"
                                 (current-error-port))
                        (let ((suffix-len (string-length "_defconfig"))
                              (entries (scandir "configs")))
@@ -839,7 +839,7 @@ (define*-public (make-u-boot-package board triplet #:key defconfig configs)
                                                (string-drop-right file-name
                                                                   suffix-len))))
                                    (sort entries string-ci<)))
-                       (error "Invalid boardname ~s." ,board))))))
+                       (error "invalid boardname ~s" ,board))))))
            (add-after 'configure 'disable-tools-libcrypto
              ;; Disable libcrypto due to GPL and OpenSSL license
              ;; incompatibilities
@@ -881,8 +881,8 @@ (define-public u-boot-malta

 (define-public u-boot-am335x-boneblack
   (let ((base (make-u-boot-package "am335x_evm" "arm-linux-gnueabihf"
-               ;; Patch out other device trees to build image small enough to
-               ;; fit within typical partitioning schemes where the first
+               ;; Patch out other device trees to build an image small enough
+               ;; to fit within typical partitioning schemes where the first
                ;; partition begins at sector 2048.
                #:configs '("CONFIG_OF_LIST=\"am335x-evm am335x-boneblack\""))))
     (package
modified   guix/build/kconfig.scm
@@ -50,7 +50,8 @@ (define config-regexp
      ;; (match:substring (string-match "=(.*)" "=") 1) returns "", but the
      ;; pattern "=(.+)?" makes it return #f instead.  From a "CONFIG_A=" we like
      ;; to get "", which later emits "CONFIG_A=" again.
-     "^ *(#[\\t ]*)?(CONFIG_[a-zA-Z0-9_]+)([\\t ]*=[\\t ]*(.*)|([\\t ]+is[\\t ]+not[\\t ]+set))?$"))
+     (string-append "^ *(#[\\t ]*)?(CONFIG_[a-zA-Z0-9_]+)([\\t ]*="
+                    "[\\t ]*(.*)|([\\t ]+is[\\t ]+not[\\t ]+set))?$")))

   (define config-comment-regexp
     (make-regexp "^([\\t ]*(#.*)?)$"))
@@ -67,13 +68,13 @@ (define config-comment-regexp
               ;; The key is uncommented and set or commented and unset.
               (cons key value)
               ;; The key is set or unset ambigiously.
-              (error (format #f "Invalid configuration, did you mean \"~a\"?"
+              (error (format #f "invalid configuration, did you mean \"~a\"?"
                              (pair->config-string (cons key #f)))
                      config-string)))
-        ;; This is not a valid or ambigious config-string, but mayby a comment.
+        ;; This is not a valid or ambigious config-string, but maybe a
+        ;; comment.
         (if (regexp-exec config-comment-regexp config-string)
-            ;; We keep valid comments.
-            (cons #f config-string)
+            (cons #f config-string)     ;keep valid comments
             (error "Invalid configuration" config-string)))))

 (define (pair->config-string pair)
@@ -94,6 +95,7 @@ (define (defconfig->alist defconfig)
                  (line (read-line)))
         (if (eof-object? line)
             ;; Building the alist is done, now check for duplicates.
+            ;; Note: the filter invocation is used to remove comments.
             (let loop ((keys (map first (filter first alist)))
                        (duplicates '()))
               (if (null? keys)
@@ -102,11 +104,11 @@ (define (defconfig->alist defconfig)
                   (if (null? duplicates)
                       alist
                       (error
-                       (format #f "Duplicate configurations in ~a" defconfig)
+                       (format #f "duplicate configurations in ~a" defconfig)
                        duplicates))
                   ;; Continue the search for duplicates.
                   (loop (cdr keys)
-                        (if (member (first keys) (cdr keys) equal?)
+                        (if (member (first keys) (cdr keys))
                             (cons (first keys) duplicates)
                             duplicates))))
             ;; Build the alist.
@@ -127,13 +129,13 @@ (define (modify-defconfig defconfig configs)
   \"CONFIG_D=m\"
   \"CONFIG_E=\"
   \"# CONFIG_G is not set\"
-  ;; For convinience this abbrevation can be used for not set configurations.
+  ;; For convenience this abbrevation can be used for not set configurations.
   \"CONFIG_F\")

-Instead of a list, CONFGIS can be a string with one configuration per line."
-  (let* (;; Split the configs into a list of single configuations.
-         ;; To minimize mistakes, we support a string and a list of strings,
-         ;; each with newlines to separate configurations.
+Instead of a list, CONFIGS can be a string with one configuration per line."
+  (let* (;; Split the configs into a list of single configurations.  Both a
+         ;; string and or a list of strings is supported, each with newlines
+         ;; to separate configurations.
          (config-pairs (map config-string->pair
                             (append-map (cut string-split <>  #\newline)
                                         (if (string? configs)
@@ -141,45 +143,41 @@ (define (modify-defconfig defconfig configs)
                                             configs))))
          ;; Generate a blocklist from all valid keys in config-pairs.
          (blocklist (delete #f (map first config-pairs)))
-         ;; Generate an alist from the defconifg without the keys in blocklist.
+         ;; Generate an alist from the defconfig without the keys in blocklist.
          (filtered-defconfig-pairs (remove (lambda (pair)
                                              (member (first pair) blocklist))
                                            (defconfig->alist defconfig))))
     (with-output-to-file defconfig
       (lambda ()
-        (for-each
-           (lambda (pair)
-             (display (pair->config-string pair))
-             (newline))
-           (append filtered-defconfig-pairs config-pairs))))))
+        (for-each (lambda (pair)
+                    (display (pair->config-string pair))
+                    (newline))
+                  (append filtered-defconfig-pairs config-pairs))))))

 (define (verify-config config defconfig)
   "Verify that the CONFIG file contains all configurations from the DEFCONFIG
-file and return #t in this case. Otherwise throw an error with the mismatching
-keys and their values."
+file.  When the verification fails, raise an error with the mismatching keys
+and their values."
   (let* ((config-pairs (defconfig->alist config))
          (defconfig-pairs (defconfig->alist defconfig))
          (mismatching-pairs
           (remove (lambda (pair)
-                    ;; Remove all configurations, whose values are #f and whose
-                    ;; keys are not in config-pairs, as not in config-pairs
-                    ;; means unset, …
+                    ;; Remove all configurations, whose values are #f and
+                    ;; whose keys are not in config-pairs, as not in
+                    ;; config-pairs means unset, ...
                     (and (not (cdr pair))
                          (not (assoc-ref config-pairs (first pair)))))
-                  ;; … from the defconfig-pairs different to config-pairs.
+                  ;; ... from the defconfig-pairs different to config-pairs.
                   (lset-difference equal?
                                    ;; Remove comments by filtering with first.
                                    (filter first defconfig-pairs)
                                    config-pairs))))
-    (if (null? mismatching-pairs)
-        #t
-        (error (format #f
-                       "Mismatching configurations in ~a and ~a"
-                       config
-                       defconfig)
-               (map (lambda (mismatching-pair)
-                      (let* ((key (first mismatching-pair))
-                             (defconfig-value (cdr mismatching-pair))
-                             (config-value (assoc-ref config-pairs key)))
-                        (cons key (list (list config-value defconfig-value)))))
-                    mismatching-pairs)))))
+    (unless (null? mismatching-pairs)
+      (error (format #f "Mismatching configurations in ~a and ~a"
+                     config defconfig)
+             (map (lambda (mismatching-pair)
+                    (let* ((key (first mismatching-pair))
+                           (defconfig-value (cdr mismatching-pair))
+                           (config-value (assoc-ref config-pairs key)))
+                      (cons key (list (list config-value defconfig-value)))))
+                  mismatching-pairs)))))
--8<---------------cut here---------------end--------------->8---

And streamlined the commit messages as:

--8<---------------cut here---------------start------------->8---
build: kconfig: Add new module to modify defconfig files.

* guix/build/kconfig.scm: New file.
* Makefile.am: Register it.
* gnu/packages/bootloaders.scm (make-u-boot-package)
(make-u-boot-sunxi64-package): Add DEFCONFIGS and CONFIGS arguments.
(u-boot-am335x-boneblack, u-boot-pinebook)
(u-boot-novena,u-boot-rockpro64-rk3399): Simplify packages by using the new
keyword arguments.
--8<---------------cut here---------------end--------------->8---

Explanations don't go in the GNU ChangeLog, they go ideally in comments
in the code or *before* the GNU ChangeLog, if some rationale helps
understanding the change, so you can keep things dry there.

I'll push this change shortly.

-- 
Thanks,
Maxim




  parent reply	other threads:[~2022-12-01 16:23 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-09 15:32 [bug#48314] Patches to install guix system on Raspberry Pi Stefan
2021-05-16 12:46 ` Stefan
2021-06-19 18:11   ` Danny Milosavljevic
2021-06-19 18:13   ` Danny Milosavljevic
2021-06-19 19:10     ` Stefan
2021-06-19 19:04   ` Danny Milosavljevic
2021-06-19 19:18     ` Stefan
2021-06-19 19:10   ` Danny Milosavljevic
2021-06-19 20:21     ` Stefan
2021-07-28 18:58       ` Stefan
2021-10-31 22:07         ` Stefan
2021-11-13 18:05           ` Vagrant Cascadian
2021-11-13 18:51             ` Vagrant Cascadian
2022-07-17 16:47             ` Stefan via Guix-patches via
2021-11-13 18:23           ` Vagrant Cascadian
2022-07-17 16:47             ` Stefan via Guix-patches via
2021-11-13 20:21           ` Vagrant Cascadian
2022-07-17 16:47             ` Stefan via Guix-patches via
2022-07-17 17:21               ` Vagrant Cascadian
2022-07-17 18:04                 ` Stefan via Guix-patches via
2021-11-17 14:00 ` [bug#48314] Install " phodina via Guix-patches via
2022-04-14  7:38 ` [bug#48314] [PATCH v3] " phodina via Guix-patches via
2022-04-14  8:17   ` phodina via Guix-patches via
2022-04-14  8:32   ` Maxime Devos
2022-04-14  9:25     ` [bug#48314] [PATCH v4] " phodina via Guix-patches via
2022-04-14 11:00       ` Maxime Devos
2022-04-14 12:23         ` [bug#48314] [PATCH v5] " phodina via Guix-patches via
2022-04-14 13:03           ` phodina via Guix-patches via
2022-04-14 13:57             ` Maxime Devos
2022-04-14 14:00           ` Maxime Devos
2022-04-14 14:06   ` [bug#48314] [PATCH v3] " Maxime Devos
2022-04-14 15:53     ` phodina via Guix-patches via
2022-04-14 17:33       ` Maxime Devos
2022-04-15 17:17       ` Ludovic Courtès
2022-04-16  8:53         ` phodina via Guix-patches via
2022-04-18 21:00           ` Ludovic Courtès
2022-04-21 10:52             ` phodina via Guix-patches via
2022-04-21 19:32               ` Stefan
2022-04-14 15:56   ` Vagrant Cascadian
2022-04-28  2:57     ` Vagrant Cascadian
2022-04-28  6:05       ` Stefan
2022-04-28 15:25         ` Vagrant Cascadian
2022-07-02  6:40           ` phodina via Guix-patches via
2022-07-17 16:48             ` Stefan via Guix-patches via
2022-07-17 16:48             ` Stefan via Guix-patches via
2022-07-18 19:23               ` phodina via Guix-patches via
2022-07-19  6:55                 ` Stefan via Guix-patches via
2022-07-19  7:35                   ` phodina via Guix-patches via
2022-07-20  6:13                     ` Stefan via Guix-patches via
2022-07-20  7:16                       ` phodina via Guix-patches via
2022-07-20 19:42                         ` Stefan via Guix-patches via
2022-08-12 14:27                           ` phodina via Guix-patches via
2022-08-13 10:48                             ` Stefan via Guix-patches via
2022-08-14  9:59                               ` phodina via Guix-patches via
2022-08-14 11:35                                 ` Stefan via Guix-patches via
2022-09-01 23:55                                   ` Stefan via Guix-patches via
2022-09-02  5:49                                     ` phodina via Guix-patches via
2022-09-04 18:41                                       ` Stefan via Guix-patches via
2022-09-22 16:18                                         ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
2022-10-05 13:02                                           ` Ludovic Courtès
2022-10-08 16:22                                           ` Vagrant Cascadian
2022-10-09 13:41                                             ` Stefan via Guix-patches via
2022-10-30 12:39                                               ` phodina via Guix-patches via
2022-10-30 17:08                                                 ` Stefan via Guix-patches via
2022-10-30 17:31                                                   ` Stefan via Guix-patches via
2022-12-01 14:25                                           ` [bug#48314] [PATCH] " Maxim Cournoyer
2022-12-01 15:32                                           ` Maxim Cournoyer
2022-12-01 16:22                                           ` Maxim Cournoyer [this message]
2022-12-01 18:01                                           ` Maxim Cournoyer
2022-12-01 19:33                                           ` bug#48314: " Maxim Cournoyer
2022-12-03  5:53                                             ` [bug#48314] " Vagrant Cascadian
2022-12-04  6:28                                               ` Maxim Cournoyer
2022-10-30 17:32 ` [bug#48314] [PATCH v5] " Stefan via Guix-patches via
2022-10-30 17:33 ` Stefan via Guix-patches via

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://guix.gnu.org/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ilivhz5a.fsf_-_@gmail.com \
    --to=maxim.cournoyer@gmail.com \
    --cc=48314@debbugs.gnu.org \
    --cc=dannym@scratchpost.org \
    --cc=ludo@gnu.org \
    --cc=phodina@protonmail.com \
    --cc=stefan-guix@vodafonemail.de \
    --cc=vagrant@debian.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).