diff --git a/doc/guix.texi b/doc/guix.texi index ce67ea9c82..a3b17578a8 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -148,6 +148,7 @@ Copyright @copyright{} 2025 Edouard Klein@* Copyright @copyright{} 2025 Rodion Goritskov@* Copyright @copyright{} 2025 dan@* Copyright @copyright{} 2025 Noé Lopez@* +Copyright @copyright{} 2026 David Elsing@* Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or @@ -12982,6 +12983,15 @@ The example above returns an object that corresponds to the i686 build of Coreutils, regardless of the current value of @code{%current-system}. @end defmac +@defmac delayed object exp +This macro delays the evaluation of @var{exp} until the returned object +is lowered to a derivation or store item. + +Its intended use case is to prevent the use of a non-delayed top-level +variable of another module, e.g. when using a gexp in the @code{source} +field of a @var{package}. +@end defmac + @anchor{gexp-input} @deffn {Procedure} gexp-input @var{obj} [@var{output}] [#:native? #f] Return a @dfn{gexp input} record for the given @var{output} of file-like diff --git a/guix/gexp.scm b/guix/gexp.scm index 030092843a..5305678b34 100644 --- a/guix/gexp.scm +++ b/guix/gexp.scm @@ -6,6 +6,7 @@ ;;; Copyright © 2020 Maxim Cournoyer ;;; Copyright © 2021, 2022 Maxime Devos ;;; Copyright © 2025 Tomas Volf <~@wolfsden.cz> +;;; Copyright © 2026 David Elsing ;;; ;;; This file is part of GNU Guix. ;;; @@ -96,6 +97,10 @@ with-parameters parameterized? + delayed-object + delayed-object? + delayed-object-promise + load-path-expression gexp-modules @@ -778,6 +783,21 @@ x86_64-linux when COREUTILS is lowered." (obj ;store item obj))))))))) +;; Object which evaluates its promise when it is lowered. +(define-record-type + (%delayed-object promise) + delayed-object? + (promise delayed-object-promise)) + +(define-syntax-rule (delayed-object body ...) + "Delays the evaluation of BODY to lowering time of the return object." + (%delayed-object (delay (begin body ...)))) + +(define-gexp-compiler (delayed-object-compiler (object ) + system target) + (with-monad %store-monad + (return (force (delayed-object-promise object))))) + ;;; ;;; Inputs & outputs. diff --git a/tests/gexp.scm b/tests/gexp.scm index 3622324a15..bba8c141f6 100644 --- a/tests/gexp.scm +++ b/tests/gexp.scm @@ -1,6 +1,7 @@ ;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2014-2025 Ludovic Courtès ;;; Copyright © 2021-2022 Maxime Devos +;;; Copyright © 2026 David Elsing ;;; ;;; This file is part of GNU Guix. ;;; @@ -518,6 +519,20 @@ (return (and (eq? drv0 result0) (eq? drv1 result1))))) +(test-assertm "delayed-object" + (let ((evaluated #f)) + (mlet* %store-monad ((drv (package->derivation coreutils)) + (obj -> (delayed-object + (begin + (set! evaluated #t) + coreutils))) + (first-evaluated -> evaluated) + (result (lower-object obj))) + (return (and (string=? (derivation-file-name drv) + (derivation-file-name result)) + (not first-evaluated) + evaluated))))) + (test-assert "with-parameters + file-append" (let* ((system (match (%current-system) ("aarch64-linux" "x86_64-linux")