diff options
author | Philip McGrath <philip@philipmcgrath.com> | 2022-01-08 03:41:52 -0500 |
---|---|---|
committer | Liliana Marie Prikler <liliana.prikler@gmail.com> | 2022-01-09 02:07:11 +0100 |
commit | df7d787ba45c4d7b5a4a49c7fdb163069ff2e47b (patch) | |
tree | d467e10bc6c748cd699f93f2b43c34d663d33b12 | |
parent | 2ef3fe9f35cf4c4709352600a1370b852b70b27c (diff) | |
download | guix-df7d787ba45c4d7b5a4a49c7fdb163069ff2e47b.tar guix-df7d787ba45c4d7b5a4a49c7fdb163069ff2e47b.tar.gz |
guix: node-build-system: Add avoid-node-gyp-rebuild phase.
Packages with native addons currently try to write to store paths
when used as dependecies. This patch adds a phase to replace that
behaviour with a no-op.
* guix/build/node-build-system.scm (avoid-node-gyp-rebuild): New
variable.
(%standard-phases): Add 'avoid-node-gyp-rebuild' after 'install'.
Signed-off-by: Liliana Marie Prikler <liliana.prikler@gmail.com>
-rw-r--r-- | guix/build/node-build-system.scm | 54 |
1 files changed, 53 insertions, 1 deletions
diff --git a/guix/build/node-build-system.scm b/guix/build/node-build-system.scm index 5286a902c7..a1556ce4b8 100644 --- a/guix/build/node-build-system.scm +++ b/guix/build/node-build-system.scm @@ -242,6 +242,57 @@ exist." "install" "../package.tgz") #t)) +(define* (avoid-node-gyp-rebuild #:key outputs #:allow-other-keys) + "Adjust the installed 'package.json' to remove an 'install' script that +would try to run 'node-gyp rebuild'." + ;; We want to take advantage of `npm install`'s automatic support for + ;; building native addons with node-gyp: in particular, it helps us avoid + ;; hard-coding the specifics of how npm's internal copy of node-gyp is + ;; currently packaged. However, the mechanism by which the automatic support + ;; is implemented causes problems for us. + ;; + ;; If a package contains a 'binding.gyp' file and does not define an + ;; 'install' or 'preinstall' script, 'npm install' runs a default install + ;; script consisting of 'node-gyp rebuild'. In our 'install' phase, this + ;; implicit 'install' script, if it is applicable, is explicitly added to + ;; the "package.json" file. However, if another Guix package were to use a + ;; Node.js package with such an 'install' script, the dependent package's + ;; build process would fail, because 'node-gyp rebuild' would try to write + ;; to the store. + ;; + ;; Here, if the installed "package.json" defines scripts.install as + ;; "node-gyp rebuild", we replace it with a no-op. Importantly, deleting the + ;; install script definition would not be enough, because the default + ;; install script would cause the same problem. + ;; + ;; For further details, see: + ;; - https://docs.npmjs.com/cli/v8/configuring-npm/package-json#default-values + ;; - https://docs.npmjs.com/cli/v8/using-npm/scripts#best-practices + (define installed-package.json + (search-input-file outputs (string-append "/lib/node_modules/" + (module-name ".") + "/package.json"))) + ;; We don't want to use an atomic replacement here, because we often don't + ;; even need to overwrite this file. Therefore, let's use some helpers + ;; that we'd otherwise not need. + (define pkg-meta + (call-with-input-file installed-package.json read-json)) + (define scripts + (jsobject-ref pkg-meta "scripts" '(@))) + (define (jsobject-set js key val) + (jsobject-update* js (list key (const val)))) + + (when (equal? "node-gyp rebuild" (jsobject-ref scripts "install" #f)) + (call-with-output-file installed-package.json + (lambda (out) + (write-json + (jsobject-set pkg-meta + "scripts" + (jsobject-set scripts + "install" + "echo Guix: avoiding node-gyp rebuild")) + out))))) + (define %standard-phases (modify-phases gnu:%standard-phases (add-after 'unpack 'set-home set-home) @@ -251,7 +302,8 @@ exist." (replace 'build build) (replace 'check check) (add-before 'install 'repack repack) - (replace 'install install))) + (replace 'install install) + (add-after 'install 'avoid-node-gyp-rebuild avoid-node-gyp-rebuild))) (define* (node-build #:key inputs (phases %standard-phases) #:allow-other-keys #:rest args) |