From 93a465f3778aae0149a86c4fc8de94435d8dbca6 Mon Sep 17 00:00:00 2001 From: Maxime Devos Date: Sun, 5 Sep 2021 14:02:30 +0200 Subject: [PATCH 08/10] compile-all,compile: Keep track of dependencies of compiled modules. This patch defines a 'notice-dependency' procedure. Macros can use this procedure to inform build-aux/compile-all.scm that a module needs to be recompiled when some file is updated. * guix/build/compile.scm (current-dependency-info, current-output-file): New parameters. (notice-dependency): New procedure. (compile-files)[build]: Set 'output-file'. Delete the old compiled file if necessary. Remove old dependency information. * build-aux/compile-all.scm: Populate current-dependency-info from a file. Populate the file dependency-info.scm from the hash table. (builddir): New variable. (file-needs-compilation?): Check if the .go file is older than the dependencies. * .gitignore: Ignore dependency-info.scm. --- .gitignore | 1 + build-aux/compile-all.scm | 39 +++++++++++++++++++++++++++++---- guix/build/compile.scm | 45 ++++++++++++++++++++++++++++++++------- 3 files changed, 73 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 88fe24586d..f24ea5fc3b 100644 --- a/.gitignore +++ b/.gitignore @@ -154,3 +154,4 @@ tmp /gnu/packages/bootstrap /gnu/packages/aux-files/guile-guile-launcher.o /guile +/dependency-info.scm diff --git a/build-aux/compile-all.scm b/build-aux/compile-all.scm index 9ffbce43ad..902527b083 100644 --- a/build-aux/compile-all.scm +++ b/build-aux/compile-all.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2016 Taylan Ulrich Bayırlı/Kammer ;;; Copyright © 2016, 2017, 2019, 2020, 2021 Ludovic Courtès +;;; Copyright © 2021 Maxime Devos ;;; ;;; This file is part of GNU Guix. ;;; @@ -20,12 +21,15 @@ (use-modules (ice-9 format) (ice-9 match) (ice-9 threads) + (ice-9 hash-table) (srfi srfi-1) + (srfi srfi-26) (guix build compile) (guix build utils)) (define host (getenv "host")) (define srcdir (getenv "srcdir")) +(define builddir (getcwd)) (define (relative-file file) (if (string-prefix? (string-append srcdir "/") file) @@ -41,10 +45,35 @@ (without-extension (string-drop-right relative 4))) (string-append without-extension ".go"))) +;; Read dependency information from previous "make" runs. +(current-dependency-info (make-hash-table)) +(if (file-exists? "dependency-info.scm") + (current-dependency-info + (alist->hash-table + (call-with-input-file "dependency-info.scm" read #:encoding "UTF-8"))) + (current-dependency-info (make-hash-table))) + +(define (dump-dependency-info) + "Dump the current dependency information for the next \"make\" run." + (call-with-output-file "dependency-info.scm.new" + (lambda (port) + (display ";; This is auto-generated by build-aux/compile-all.scm, +;; do not modify manually! +" port) + (write (hash-map->list cons (current-dependency-info)) port)) + #:encoding "UTF-8") + (rename-file "dependency-info.scm.new" "dependency-info.scm")) + (define (file-needs-compilation? file) - (let ((go (scm->go file))) + (let* ((go (scm->go file)) + (extra-dependencies + (hash-ref (current-dependency-info) (in-vicinity builddir go) + '()))) (or (not (file-exists? go)) - (file-mtimego file)) - (force-output)))))) + (force-output))))) + (dump-dependency-info)) (lambda _ + (dump-dependency-info) (primitive-exit 1)) (lambda args ;; Try to report the error in an intelligible way. diff --git a/guix/build/compile.scm b/guix/build/compile.scm index b86ec3b743..c259b27abf 100644 --- a/guix/build/compile.scm +++ b/guix/build/compile.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2013, 2014, 2016, 2017, 2018, 2019, 2020 Ludovic Courtès ;;; Copyright © 2015 Taylan Ulrich Bayırlı/Kammer +;;; Copyright © 2021 Maxime Devos ;;; ;;; This file is part of GNU Guix. ;;; @@ -29,14 +30,27 @@ #:use-module (guix build utils) #:use-module (language tree-il optimize) #:use-module (language cps optimize) - #:export (compile-files)) + #:export (compile-files notice-dependency current-dependency-info)) ;;; Commentary: ;;; -;;; Support code to compile Guile code as efficiently as possible (with 2.2). +;;; Support code to compile Guile code as efficiently as possible (with 2.2) +;;; and keep track of the dependencies of compiled files. ;;; ;;; Code: +(define current-dependency-info (make-parameter #f)) +(define current-output-file (make-parameter #f)) + +(define (notice-dependency dependency) + "Add the file DEPENDENCY to the list of dependencies of the compiled file +that is being computed, if any." + (define dependency-table (current-dependency-info)) + (define output (current-output-file)) + (when (and dependency-table output) + (hash-set! dependency-table output + (cons dependency (hash-ref dependency-table output '()))))) + (define optimizations-for-level (or (and=> (false-if-exception (resolve-interface '(system base optimize))) @@ -207,12 +221,27 @@ files are for HOST, a GNU triplet such as \"x86_64-linux-gnu\"." ;; Exit as soon as something goes wrong. (exit-on-exception file - (let ((relative (relative-file source-directory file))) - (compile-file file - #:output-file (string-append build-directory "/" - (scm->go relative)) - #:opts (append warning-options - (optimization-options relative)))))) + (let* ((relative (relative-file source-directory file)) + (output-file (string-append build-directory "/" + (scm->go relative)))) + (parameterize ((current-output-file output-file)) + (when (current-dependency-info) + ;; If dependency information is being tracked, remove + ;; the old compiled file first. Otherwise, if recompiling + ;; the file due to an updated dependency causes an exception, + ;; the new dependency information won't include the compiled + ;; file and therefore the old compiled file would be considered + ;; up-to-date on the following "make" run. + (when (file-exists? output-file) + (delete-file output-file)) + ;; Remove the old dependency information, otherwise + ;; the dependency information table will keep growing + ;; after each "make" run. + (hash-remove! (current-dependency-info) output-file)) + (compile-file file + #:output-file output-file + #:opts (append warning-options + (optimization-options relative))))))) (with-augmented-search-path %load-path source-directory (with-augmented-search-path %load-compiled-path build-directory -- 2.33.0