~ruther/guix-local

54717bb5b3c06c9667efafb9410cc5122f36a25f — Efraim Flashner 1 year, 3 months ago fb8574b
guix: lint: Check for misplaced argument flags.

* guix/lint.scm (check-misplaced-flags): New procedure.
(%local-checkers): Register new lint-checker.
* doc/guix.texi (Invoking guix lint): Add entry for misplaced-flags.
* tests/lint.scm (misplaced-flags: make-flag is incorrect,
misplaced-flags: configure-flag is incorrect, misplaced-flags: cargo
feature flags, misplaced-flags: flags without g-exp is incorrect,
misplaced-flags: build-type set correctly): New tests.

Change-Id: Ia8abbe787e26bffc65ee5c763326c7e271c189a4
3 files changed, 128 insertions(+), 1 deletions(-)

M doc/guix.texi
M guix/lint.scm
M tests/lint.scm
M doc/guix.texi => doc/guix.texi +22 -1
@@ 33,7 33,7 @@ Copyright @copyright{} 2015, 2016, 2017, 2019, 2020, 2021, 2023, 2025 Leo Famula
Copyright @copyright{} 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Ricardo Wurmus@*
Copyright @copyright{} 2016 Ben Woodcroft@*
Copyright @copyright{} 2016, 2017, 2018, 2021 Chris Marusich@*
Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 Efraim Flashner@*
Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2025 Efraim Flashner@*
Copyright @copyright{} 2016 John Darrington@*
Copyright @copyright{} 2016, 2017 Nikita Gillmann@*
Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025 Janneke Nieuwenhuizen@*


@@ 15797,6 15797,27 @@ Parse the @code{source} URL to determine if a tarball from GitHub is
autogenerated or if it is a release tarball.  Unfortunately GitHub's
autogenerated tarballs are sometimes regenerated.

@item misplaced-flags
Parse the @code{make-flags} and @code{configure-flags} to check for any
flags which should be set with another flag as part of the build-system.
For example,

@lisp
(build-system cmake-build-system)
(arguments
 (list #:configure-flags #~(list "-DCMAKE_BUILD_TYPE=RELEASE"
                                 "-DTESTS=ON")))
@end lisp

should instead be written as:

@lisp
(build-system cmake-build-system)
(arguments
 (list #:build-type "RELEASE"
       #:configure-flags #~(list "-DTESTS=ON")))
@end lisp

@item derivation
Check that the derivation of the given packages can be successfully
computed for all the supported systems (@pxref{Derivations}).

M guix/lint.scm => guix/lint.scm +62 -0
@@ 117,6 117,7 @@
            check-vulnerabilities
            check-for-updates
            check-formatting
            check-misplaced-flags
            check-archival
            check-profile-collisions
            check-haskell-stackage


@@ 1635,6 1636,63 @@ vulnerability records for PACKAGE by calling PACKAGE-VULNERABILITIES."
               (list (string-join (map vulnerability-id unpatched)
                                  ", "))))))))))

(define (check-misplaced-flags package)
  "Check if there are flags set (for example, in #:configure-flags) which
can be set as part of the build system."
  (define (make-misplaced-flag-warning flag)
    (define (flag-pair flag)
      (cond ((string-prefix? "-DCMAKE_BUILD_TYPE" flag)
             '("CMAKE_BUILD_TYPE" "build-type"))
            ((string-prefix? "--buildtype" flag)
             '("buildtype" "build-type"))
            ((or (string-prefix? "-Drelease-" flag)
                 (string-prefix? "--release" flag))
             '("release" "release-type"))
            ((string-prefix? "--features" flag)
             '("features" "features"))))
    (list (make-warning package
                  (G_ "'~a' should be set with the '~a' flag")
                  (flag-pair flag)
                  #:field 'arguments)))
  (define (find-incorrect-flags flag)
    (match flag
      ((and (? (cut string? <>))
            (or (? (cut string-prefix? "-DCMAKE_BUILD_TYPE=" <>))
                (? (cut string-prefix? "--buildtype=" <>))
                (? (cut string-prefix? "-Drelease-" <>))
                (? (cut string-prefix? "--release=" <>))
                (? (cut string-prefix? "--features" <>))))
       (make-misplaced-flag-warning flag))
      ((x . y)
       (append (find-incorrect-flags x)
               (find-incorrect-flags y)))
      (_ '())))
  (apply (lambda* (#:key (make-flags '()) (configure-flags '())
                   (cargo-build-flags '())
                   (cargo-test-flags '())
                   #:allow-other-keys)
           (define make-flags/sexp
             (if (gexp? make-flags)
                 (gexp->approximate-sexp make-flags)
                 make-flags))
           (define configure-flags/sexp
             (if (gexp? configure-flags)
                 (gexp->approximate-sexp configure-flags)
                 configure-flags))
           (define cargo-build-flags/sexp
             (if (gexp? cargo-build-flags)
                 (gexp->approximate-sexp cargo-build-flags)
                 cargo-build-flags))
           (define cargo-test-flags/sexp
             (if (gexp? cargo-test-flags)
                 (gexp->approximate-sexp cargo-test-flags)
                 cargo-test-flags))
           (find-incorrect-flags (append make-flags/sexp
                                         configure-flags/sexp
                                         cargo-build-flags/sexp
                                         cargo-test-flags/sexp)))
         (package-arguments package)))

(define (check-for-updates package)
  "Check if there is an update available for PACKAGE."
  (match (lookup-updater package)


@@ 2080,6 2138,10 @@ or a list thereof")
     (description "Check for autogenerated tarballs")
     (check       check-source-unstable-tarball))
   (lint-checker
     (name        'misplaced-flags)
     (description "Check for misplaced flags")
     (check       check-misplaced-flags))
   (lint-checker
     (name            'derivation)
     (description     "Report failure to compile a package to a derivation")
     (check           check-derivation)

M tests/lint.scm => tests/lint.scm +44 -0
@@ 414,6 414,50 @@
                   (list #:target #false
                         #:make-flags #~(list "CC=gcc"))))))

(test-equal "misplaced-flags: make-flag is incorrect"
  "'CMAKE_BUILD_TYPE' should be set with the 'build-type' flag"
  (single-lint-warning-message
   (check-misplaced-flags
     (dummy-package "x"
                    (arguments
                     (list #:make-flags #~(list "-DCMAKE_BUILD_TYPE=RELEASE"
                                                "-DTESTS=ON")))))))

(test-equal "misplaced-flags: configure-flag is incorrect"
  "'buildtype' should be set with the 'build-type' flag"
  (single-lint-warning-message
   (check-misplaced-flags
     (dummy-package "x"
                    (arguments
                     (list #:configure-flags #~(list "--buildtype=release"
                                                     "--with-tests")))))))

(test-equal "misplaced-flags: cargo feature flags"
  "'features' should be set with the 'features' flag"
  (single-lint-warning-message
   (check-misplaced-flags
     (dummy-package "x"
                    (arguments
                     '(#:cargo-test-flags
                       '("--features" "force_system_lib")))))))

(test-equal "misplaced-flags: flags without g-exp is incorrect"
  "'CMAKE_BUILD_TYPE' should be set with the 'build-type' flag"
  (single-lint-warning-message
   (check-misplaced-flags
     (dummy-package "x"
                    (arguments
                     '(#:make-flags '("-DCMAKE_BUILD_TYPE=RELEASE"
                                      "-DTESTS=ON")))))))

(test-equal "misplaced-flags: build-type set correctly"
  '()
  (check-misplaced-flags
    (dummy-package "x"
                   (arguments
                    (list #:build-type "RELEASE"
                          #:make-flags #~(list "-DTESTS=ON"))))))

;; The emacs-build-system sets #:tests? #f by default.
(test-equal "tests-true: #:tests? #t acceptable for emacs packages"
  '()