aboutsummaryrefslogtreecommitdiff
path: root/build-aux/cuirass/evaluate.scm
blob: 7ae5c266d136be4b015fdc7b7413a31511d7b217 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2016-2018, 2020, 2022 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2017 Jan Nieuwenhuizen <janneke@gnu.org>
;;; Copyright © 2021 Mathieu Othacehe <othacehe@gnu.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix 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.
;;;
;;; GNU Guix 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 GNU Guix.  If not, see <http://www.gnu.org/licenses/>.

;;; This program replicates the behavior of Cuirass's 'evaluate' process.
;;; It displays the evaluated jobs on the standard output.

(use-modules (guix channels)
             (guix derivations)
             (guix git-download)
             (guix inferior)
             (guix packages)
             (guix store)
             (guix ui)
             ((guix ui) #:select (build-notifier))
             (ice-9 match)
             (ice-9 threads))

(define %top-srcdir
  (and=> (assq-ref (current-source-location) 'filename)
         (lambda (file)
           (canonicalize-path
            (string-append (dirname file) "/../..")))))

(match (command-line)
  ((command directory)
   (let ((real-build-things build-things))
     (with-store store
       ;; Make sure we don't resort to substitutes.
       (set-build-options store
                          #:use-substitutes? #f
                          #:substitute-urls '())

       ;; The evaluation of Guix itself requires building a "trampoline"
       ;; program, and possibly everything it depends on.  Thus, allow builds
       ;; but print a notification.
       (with-build-handler (build-notifier #:use-substitutes? #f)

         ;; Add %TOP-SRCDIR to the store with a proper Git predicate so we
         ;; work from a clean checkout.
         (let ((source (add-to-store store "guix-source" #t
                                     "sha256" %top-srcdir
                                     #:select? (git-predicate %top-srcdir))))
           (define instances
             (list (checkout->channel-instance source)))

           (define channels
             (map channel-instance-channel instances))

           (define derivation
             ;; Compute the derivation of Guix for COMMIT.
             (run-with-store store
               (channel-instances->derivation instances)))

           ;; TODO: Remove 'show-what-to-build' call when Cuirass' 'evaluate'
           ;; scripts uses 'with-build-handler'.
           (show-what-to-build store (list derivation))
           (build-derivations store (list derivation))


           ;; Evaluate jobs on a per-system basis for two reasons.  It speeds
           ;; up the evaluation speed as the evaluations can be performed
           ;; concurrently.  It also decreases the amount of memory needed per
           ;; evaluation process.
           ;;
           ;; Fork inferior processes upfront before we have created any
           ;; threads.
           (let ((inferiors (map (lambda _
                                   (open-inferior (derivation->output-path derivation)))
                                 %cuirass-supported-systems)))
             (n-par-for-each
              (min (length %cuirass-supported-systems)
                   (current-processor-count))
              (lambda (system inferior)
                (with-store store
                  (let ((channels (map channel-instance->sexp instances)))
                    (inferior-eval '(use-modules (gnu ci)) inferior)
                    (let ((jobs
                           (inferior-eval-with-store
                            inferior store
                            `(lambda (store)
                               (cuirass-jobs store
                                             '((subset . all)
                                               (systems . ,(list system))
                                               (channels . ,channels))))))
                          (file
                           (string-append directory "/jobs-" system ".scm")))
                      (close-inferior inferior)
                      (call-with-output-file file
                        (lambda (port)
                          (write jobs port)))))))
              %cuirass-supported-systems
              inferiors)))))))
  (x
   (format (current-error-port) "Wrong command: ~a~%." x)
   (exit 1)))
unner)) ;;; ;;; SRFI 64 test specifiers. ;;; (define (test-match-name* regexp) "Return a test specifier that matches a test name against REGEXP." (lambda (runner) (string-match regexp (test-runner-test-name runner)))) (define (test-match-name*/negated regexp) "Return a negated test specifier version of test-match-name*." (lambda (runner) (not (string-match regexp (test-runner-test-name runner))))) ;;; XXX: test-match-all is a syntax, which isn't convenient to use with a list ;;; of test specifiers computed at run time. Copy this SRFI 64 internal ;;; definition here, which is the procedural equivalent of 'test-match-all'. (define (%test-match-all . pred-list) (lambda (runner) (let ((result #t)) (let loop ((l pred-list)) (if (null? l) result (begin (if (not ((car l) runner)) (set! result #f)) (loop (cdr l)))))))) ;;; ;;; Entry point. ;;; (define (main . args) (let* ((opts (getopt-long (command-line) %options)) (option (cut option-ref opts <> <>))) (cond ((option 'help #f) (show-help)) ((option 'version #f) (format #t "test-driver.scm ~A~%" script-version)) (else (let* ((log (and=> (option 'log-file #f) (cut open-file <> "w0"))) (trs (and=> (option 'trs-file #f) (cut open-file <> "wl"))) (out (duplicate-port (current-output-port) "wl")) (test-name (option 'test-name #f)) (select (option 'select #f)) (exclude (option 'exclude #f)) (test-specifiers (filter-map identity (list (and=> select test-match-name*) (and=> exclude test-match-name*/negated)))) (test-specifier (apply %test-match-all test-specifiers)) (color-tests (if (assoc 'color-tests opts) (option->boolean opts 'color-tests) #t))) (when log (redirect-port log (current-output-port)) (redirect-port log (current-warning-port)) (redirect-port log (current-error-port))) (test-with-runner (test-runner-gnu test-name #:color? color-tests #:brief? (option->boolean opts 'brief) #:errors-only? (option->boolean opts 'errors-only) #:show-duration? (option->boolean opts 'show-duration) #:out-port out #:trs-port trs) (test-apply test-specifier (lambda _ (load-from-path test-name)))) (and=> log close-port) (and=> trs close-port) (close-port out)))) (exit 0))) ;;; Local Variables: ;;; mode: scheme ;;; eval: (add-hook 'write-file-functions 'time-stamp) ;;; time-stamp-start: "(define script-version \"" ;;; time-stamp-format: "%:y-%02m-%02d.%02H" ;;; time-stamp-time-zone: "UTC" ;;; time-stamp-end: "\") ;UTC" ;;; End: ;;;; test-driver.scm ends here.