Subject: [bug#49946] [PATCH 09/31] guix: node-build-system: Support compiling addons with node-gyp.

From: Pierre Langlois <[email-masked]>
Date: Mon, 9 Aug 2021 00:33:32 +0100

* gnu/packages/node.scm (node-headers): New function.
* guix/build-system/node.scm (python): New function.
(node-headers): New function.
(lower): Add node-headers and python to build inputs.
* guix/build/node-build-system.scm (configure-gyp): New function.
(%standard-phases): Add 'configure-gyp after 'configure.
---
 gnu/packages/node.scm            | 19 ++++++++++++++++++-
 guix/build-system/node.scm       | 16 ++++++++++++++++
 guix/build/node-build-system.scm | 15 +++++++++++++++
 3 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/gnu/packages/node.scm b/gnu/packages/node.scm
index 522d4943d0..d0f7c5cdb7 100644
--- a/gnu/packages/node.scm
+++ b/gnu/packages/node.scm
@@ -48,7 +48,24 @@
   #:use-module (gnu packages pkg-config)
   #:use-module (gnu packages python)
   #:use-module (gnu packages tls)
-  #:use-module (gnu packages web))
+  #:use-module (gnu packages web)
+  #:use-module (ice-9 match)
+  #:export (node-headers))
+
+(define (node-headers node)
+  "Return an <origin> object for a tarball with headers for the given node
+package version."
+  (let* ((version (package-version node))
+         (hash (match version
+                 ("10.24.0"
+                  "0h37zjwcpxjdqcxqjfj5zp1n5zjxaa0g8lsy83955afg5cca8p0n")
+                 ("14.16.0"
+                  "1vpdgq7kcw1a0w90lpvbvxbrc0n3pwjrs3sm42pjj7560clvji2b"))))
+    (origin
+      (method url-fetch)
+      (uri (string-append "https://nodejs.org/dist/v" version
+                          "/node-v" version "-headers.tar.gz"))
+      (sha256 (base32 hash)))))

 (define-public node
   (package
diff --git a/guix/build-system/node.scm b/guix/build-system/node.scm
index 98f63f87ef..7828582a9a 100644
--- a/guix/build-system/node.scm
+++ b/guix/build-system/node.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2016 Jelle Licht <[email-masked]>
 ;;; Copyright © 2019 Timothy Sample <[email-masked]>
+;;; Copyright © 2021 Pierre Langlois <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -41,6 +42,19 @@
   (let ((node (resolve-interface '(gnu packages node))))
     (module-ref node 'node-lts)))

+(define (python)
+  "Return the python package."
+  ;; Lazily resolve the binding to avoid a circular dependency.
+  (let ((module (resolve-interface '(gnu packages python))))
+    (module-ref module 'python-wrapper)))
+
+(define (node-headers node)
+  "Return a tarball with headers for the given node, needed for packages that
+need to build native bindings using node-gyp."
+  ;; Lazily resolve the binding to avoid a circular dependency.
+  (let ((module (resolve-interface '(gnu packages node))))
+    ((module-ref module 'node-headers) node)))
+
 (define* (lower name
                 #:key source inputs native-inputs outputs system target
                 (node (default-node))
@@ -62,6 +76,8 @@
                         ;; Keep the standard inputs of 'gnu-build-system'.
                         ,@(standard-packages)))
          (build-inputs `(("node" ,node)
+                         ("node-headers" ,(node-headers node))
+                         ("python" ,(python))
                          ,@native-inputs))
          (outputs outputs)
          (build node-build)
diff --git a/guix/build/node-build-system.scm b/guix/build/node-build-system.scm
index 70a367618e..2993c49b2b 100644
--- a/guix/build/node-build-system.scm
+++ b/guix/build/node-build-system.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2015 David Thompson <[email-masked]>
 ;;; Copyright © 2016, 2020 Jelle Licht <[email-masked]>
 ;;; Copyright © 2019, 2021 Timothy Sample <[email-masked]>
+;;; Copyright © 2021 Pierre Langlois <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -101,6 +102,19 @@
     (invoke npm "--offline" "--ignore-scripts" "install")
     #t))

+(define* (configure-gyp #:key inputs #:allow-other-keys)
+  "Run 'node-gyp configure' if we see a 'binding.gyp' file.
+
+By default, 'node-gyp' will try to download node headers from the internet, we
+prevent this with the '--tarball' flag."
+  (let ((node-gyp (string-append (assoc-ref inputs "node")
+                                 "/lib/node_modules/npm/node_modules/node-gyp"
+                                 "/bin/node-gyp.js")))
+    (if (file-exists? "binding.gyp")
+        (invoke node-gyp "--tarball" (assoc-ref inputs "node-headers")
+                "configure"))
+    #t))
+
 (define* (build #:key inputs #:allow-other-keys)
   (let ((package-meta (call-with-input-file "package.json" read-json)))
     (if (and=> (assoc-ref package-meta "scripts")
@@ -147,6 +161,7 @@
     (add-after 'unpack 'set-home set-home)
     (add-before 'configure 'patch-dependencies patch-dependencies)
     (replace 'configure configure)
+    (add-after 'configure 'configure-gyp configure-gyp)
     (replace 'build build)
     (replace 'check check)
     (add-before 'install 'repack repack)
--
2.32.0