guix_mirror_bot pushed a commit to branch next-master
in repository guix.
commit 6bb73a58d96e78ef14e3aaa28b4efd1d6fd02698
Author: Ludovic Courtès <[email protected]>
AuthorDate: Tue Jan 13 09:38:38 2026 +0100
transformations: Add ‘--amd-gpu’ transformation option.
* guix/transformations.scm (split-on-commas): New procedure, moved from…
(transform-package-toolchain): … here.
(package-amd-gpu-specialization, transform-package-amd-gpu-targets): New
procedures.
(%transformations, %options): Add ‘amd-gpu’.
* tests/transformations.scm ("options->transformations, amd-gpu")
("options->transformations, amd-gpu, not applicable")
("options->transformations, amd-gpu, missing clang-rocm input")
("options->transformations, amd-gpu, wrong GPU"): New tests.
* doc/guix.texi (Package Transformation Options): Document it.
Change-Id: I56bf0dffbf12bc08cf6318fe56952473b395c303
Signed-off-by: Ludovic Courtès <[email protected]>
Merges: #5583
---
doc/guix.texi | 33 ++++++++++++++-
guix/transformations.scm | 105 ++++++++++++++++++++++++++++++++++++++++++++--
tests/transformations.scm | 41 +++++++++++++++++-
3 files changed, 173 insertions(+), 6 deletions(-)
diff --git a/doc/guix.texi b/doc/guix.texi
index 8022655c81..7c800db83b 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -22,7 +22,7 @@
@set SUBSTITUTE-URLS https://@value{SUBSTITUTE-SERVER-1}
https://@value{SUBSTITUTE-SERVER-2}
@copying
-Copyright @copyright{} 2012--2025 Ludovic Courtès@*
+Copyright @copyright{} 2012--2026 Ludovic Courtès@*
Copyright @copyright{} 2013, 2014, 2016, 2024 Andreas Enge@*
Copyright @copyright{} 2013 Nikita Karetnikov@*
Copyright @copyright{} 2014, 2015, 2016 Alex Kost@*
@@ -13662,6 +13662,37 @@ coarse-grain counterpart of @dfn{function
multi-versioning} as
implemented by the GNU tool chain (@pxref{Function Multiversioning,,,
gcc, Using the GNU Compiler Collection (GCC)}).
+@cindex GPUs, AMD compilation targets
+@cindex AMD GPUs
+@cindex ROCm/HIP GPU targets
+@vindex amd-gpu-targets
+@anchor{amd-gpu-transformation-option}
+@item --amd-gpu=@var{targets}
+Build relevant packages for the AMD GPUs specified by @var{targets}.
+Only packages with an @code{amd-gpu-targets} property are affected.
+@var{targets} must be a comma-separated list of
+@uref{https://llvm.org/docs/AMDGPUUsage.html#amdgpu-processor-table, AMD
+GPU target identifiers}. For example, the command below builds the GPU
+code of @code{rocm-bandwidth-test} for AMD Instinct MI250
+(@code{gfx90a}) and for AMD Instinct MI300 (@code{gfx942}):
+
+@example
+guix build --amd-gpu=gfx90a,gfx942 rocm-bandwidth-test
+@end example
+
+To know the identifier(s) of the GPU(s) available on your machine, run:
+
+@example
+guix shell rocminfo -- rocm_agent_enumerator
+@end example
+
+Under the hood, these GPU identifiers are
+passed to Clang's @option{--offload-arch} option.
+
+When @option{--amd-gpu} is omitted, packages are built for a default set
+of GPUs, that we hope covers common needs. Building for more GPUs
+increases build time significantly and leads to bigger package binaries.
+
@item --with-source=@var{source}
@itemx --with-source=@var{package}=@var{source}
@itemx --with-source=@var{package}@@@var{version}=@var{source}
diff --git a/guix/transformations.scm b/guix/transformations.scm
index 198b55ed23..0cad18ba6e 100644
--- a/guix/transformations.scm
+++ b/guix/transformations.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2016-2024 Ludovic Courtès <[email protected]>
+;;; Copyright © 2016-2024, 2026 Ludovic Courtès <[email protected]>
;;; Copyright © 2021 Marius Bakke <[email protected]>
;;; Copyright © 2023 Sarthak Shah <[email protected]>
;;; Copyright © 2023-2025 Efraim Flashner <[email protected]>
@@ -422,15 +422,15 @@ TOOLCHAIN must be an input list."
(not (memq p set))))
#:deep? #t))))
+(define split-on-commas
+ (cute string-tokenize <> (char-set-complement (char-set #\,))))
+
(define (transform-package-toolchain replacement-specs)
"Return a procedure that, when passed a package, changes its toolchain or
that of its dependencies according to REPLACEMENT-SPECS. REPLACEMENT-SPECS is
a list of strings like \"fftw=gcc-toolchain@10\" meaning that the package to
the left of the equal sign must be built with the toolchain to the right of
the equal sign."
- (define split-on-commas
- (cute string-tokenize <> (char-set-complement (char-set #\,))))
-
(define (specification->input spec)
(let ((package (specification->package spec)))
(list (package-name package) package)))
@@ -704,6 +704,97 @@ for MICRO-ARCHITECTURE, a string suitable for GCC's
'-march'."
(rewrite obj)
obj))))))
+(define (package-for-amd-gpu-targets p targets)
+ "Return a variant of P compiled for TARGETS, a list of strings denoting AMD
+GPU targets."
+ (package/inherit p
+ (properties
+ `((amd-gpu-targets . ,targets)
+ ,@(alist-delete 'amd-gpu-targets (package-properties p))))))
+
+(define (assert-valid-amd-gpu-targets package targets)
+ "Raise an error if the AMD GPU identifiers listed in TARGETS are not known
+to the compiler of PACKAGE."
+ (define (compiler-amd-gpu-targets package)
+ (assoc-ref (package-properties package) 'compiler-amd-gpu-targets))
+
+ (match (any (match-lambda
+ ((label (? package? package))
+ (and (compiler-amd-gpu-targets package)
+ package))
+ (_ #f))
+ (package-direct-inputs package))
+ (#f
+ (raise (make-compound-condition
+ (formatted-message
+ (G_ "~a: no ROCm compiler was found among the inputs")
+ (package-full-name package))
+ (condition (&error-location
+ (location (package-location package)))))))
+ (compiler
+ (let ((supported (compiler-amd-gpu-targets compiler)))
+ ;; This is quadratic but on small lists.
+ (and=> (find (negate (cut member <> supported)) targets)
+ (lambda (unsupported)
+ (raise
+ (make-compound-condition
+ (formatted-message
+ (G_ "compiler ~a does not support AMD GPU target ~a")
+ (package-full-name compiler) unsupported)
+ (condition (&error-location
+ (location (package-location compiler))))
+ (condition
+ (&fix-hint
+ (hint (format #f (G_ "Compiler ~a supports the following
+AMD GPU targets:
+
+@quotation
+~a
+@end quotation")
+ (package-full-name compiler "@@")
+ (string-join supported ", ")))))))))))))
+
+(define package-amd-gpu-specialization
+ (mlambda (targets)
+ "Return a procedure that maps the given package to its counterpart built
+for the given ROCm TARGETS, a list of GPU architectures."
+ (define rewriting-property
+ (gensym " package-amd-gpu-specialization"))
+
+ (define (mark p)
+ ;; Mark P as already processed.
+ (package/inherit p
+ (properties `((,rewriting-property . #t)
+ ,@(package-properties p)))))
+
+ (package-mapping (lambda (p)
+ (cond ((assq rewriting-property (package-properties p))
+ p)
+ ((assq 'amd-gpu-targets (package-properties p))
+ (assert-valid-amd-gpu-targets p targets)
+ (info (N_ "compiling ~a for AMD GPU~{ ~a~}~%"
+ "compiling ~a for these AMD GPUs:~{
~a~}~%"
+ (length targets))
+ (package-full-name p) targets)
+ (mark (package-for-amd-gpu-targets p targets)))
+ (else
+ p)))
+ (lambda (p)
+ (assq rewriting-property (package-properties p)))
+ #:deep? #t)))
+
+(define (transform-package-amd-gpu-targets targets)
+ "Return a procedure that, when applied to a package, returns that package
+such that the package itself and all its dependencies are specialized for
+TARGET-LIST, a list of strings denoting AMD GPUs."
+ (match targets
+ ((targets _ ...)
+ (let* ((rewrite (package-amd-gpu-specialization targets)))
+ (lambda (obj)
+ (if (package? obj)
+ (rewrite obj)
+ obj))))))
+
(define (transform-package-with-debug-info specs)
"Return a procedure that, when passed a package, set its 'replacement' field
to the same package but with #:strip-binaries? #f in its 'arguments' field."
@@ -999,6 +1090,7 @@ are replaced by the specified upstream version."
(with-git-url . ,transform-package-source-git-url)
(with-c-toolchain . ,transform-package-toolchain)
(tune . ,transform-package-tuning)
+ (amd-gpu . ,transform-package-amd-gpu-targets)
(with-debug-info . ,transform-package-with-debug-info)
(without-tests . ,transform-package-tests)
(with-configure-flag . ,transform-package-configure-flag)
@@ -1085,6 +1177,11 @@ building for ~a instead of ~a, so tuning cannot be
guessed~%")
result)
(alist-delete 'tune result))
rest)))
+ (option '("amd-gpu") #t #f
+ (lambda (opt name arg result . rest)
+ (apply values
+ (alist-cons 'amd-gpu (split-on-commas arg) result)
+ rest)))
(option '("with-debug-info") #t #f
(parser 'with-debug-info))
(option '("without-tests") #t #f
diff --git a/tests/transformations.scm b/tests/transformations.scm
index 9f5aacc41b..1db54a0e19 100644
--- a/tests/transformations.scm
+++ b/tests/transformations.scm
@@ -1,5 +1,5 @@
;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2016-2017, 2019-2024 Ludovic Courtès <[email protected]>
+;;; Copyright © 2016-2017, 2019-2024, 2026 Ludovic Courtès <[email protected]>
;;; Copyright © 2021 Marius Bakke <[email protected]>
;;;
;;; This file is part of GNU Guix.
@@ -638,6 +638,45 @@
(package->bag (t p))
#f)))
+(test-equal "options->transformations, amd-gpu"
+ '("gfx90a" "gfx942")
+ (let ((p (dummy-package "amd-gpu-code"
+ (native-inputs
+ (list (@ (gnu packages llvm) clang-rocm)))
+ (properties '((amd-gpu-targets . ("whatever"))))))
+ (t (options->transformation '((amd-gpu . ("gfx90a" "gfx942"))))))
+ (assoc-ref (package-properties (t p)) 'amd-gpu-targets)))
+
+(test-equal "options->transformations, amd-gpu, not applicable"
+ #f
+ (let ((p (dummy-package "not-amd-gpu-code"))
+ (t (options->transformation '((amd-gpu . ("gfx90a" "gfx942"))))))
+ (assoc-ref (package-properties (t p)) 'amd-gpu-targets)))
+
+(test-assert "options->transformations, amd-gpu, missing clang-rocm input"
+ (let ((p (dummy-package "amd-gpu-code"
+ (properties '((amd-gpu-targets . ("whatever"))))))
+ (t (options->transformation '((amd-gpu . ("generic"))))))
+ ;; Since 'clang-rocm' is not among the inputs, an error should be raised.
+ (guard (c ((formatted-message? c)
+ (string-contains (formatted-message-string c)
+ "no ROCm compiler")))
+ (t p)
+ #f)))
+
+(test-assert "options->transformations, amd-gpu, wrong GPU"
+ (let ((p (dummy-package "amd-gpu-code"
+ (native-inputs
+ (list (@ (gnu packages llvm) clang-rocm)))
+ (properties '((amd-gpu-targets . ("whatever"))))))
+ (t (options->transformation '((amd-gpu . ("does-not-exist"))))))
+ ;; Since this AMD GPU target is not known to 'clang-rocm', an error should
+ ;; be raised.
+ (guard (c ((formatted-message? c)
+ (member "does-not-exist" (formatted-message-arguments c))))
+ (t p)
+ #f)))
+
(test-equal "options->transformation + package->manifest-entry"
'((transformations . ((without-tests . "foo"))))
(let* ((p (dummy-package "foo"))