GNU bug report logs - #49946
[PATCH 00/31] Tree-sitter, node-gyp addon support and emacs-tree-sitter

Previous Next

Package: guix-patches;

Reported by: Pierre Langlois <pierre.langlois <at> gmx.com>

Date: Sun, 8 Aug 2021 23:27:01 UTC

Severity: normal

Tags: patch

Full log


Message #224 received at 49946 <at> debbugs.gnu.org (full text, mbox):

From: Philip McGrath <philip <at> philipmcgrath.com>
To: Pierre Langlois <pierre.langlois <at> gmx.com>
Cc: 49946 <at> debbugs.gnu.org, Maxime Devos <maximedevos <at> telenet.be>
Subject: Re: [bug#49946] [PATCH 08/31] gnu: node: Patch /usr/bin/env in
 node-gyp.
Date: Sun, 26 Sep 2021 18:02:47 -0400
Hi Pierre,

On 9/25/21 6:24 AM, Pierre Langlois wrote:
> Philip McGrath <philip <at> philipmcgrath.com> writes:
>> Since the shebang line for node-gyp is specifically "#!/usr/bin/env node", I
>> wonder if it should use the node built by this package, rather than a dynamic
>> node.
> 
> Yeah we could do that, although I generally prefer to follow whatever
> the script already does, there could be a good reason for them to use
> `env' no
I think it might be better to use `patch-shebang` from `(guix build 
utils)` rather than `substitute*` these by hand, and it seems that 
`patch-shebang` removed the indirection through `env`. My guess is most 
of these cases are to accommodate the fact that `node` and `python` are 
often installed to places other than `/usr/bin`.

>> I'd guess node-gyp may not be the only one with shebangs that ought to

>> be patched.

>

> Yeah there could be others, although normally the patching phase from

> the gnu build system should have taken care of most of them, hopefully

> all, I'm not sure why it didn't work for /usr/bin/env though.

>

> I would suggest we patch things as we encounter them, did you find

> anymore issues when working on your package?


Looking at `gnu-build-system`, it seems that the `'patch-shebangs` phase 
only operates on files installed in the "/bin" and "/sbin" 
subdirectories of the package's outputs. That restriction doesn't make 
sense to me in general: for instance, what about "/libexec"? For Node 
specifically, this misses a lot of stuff under "/lib/node_modules" and 
"/lib/node_modules/npm/node_modules". I think I more general fix could 
subsume the `'patch-npm-shebang` and `'patch-node-shebang` phases in 
building Node, too.

> For instance, while working on a newer version of one of the packages in

> this series, I saw we may need to patch GYP's python reference as well,

> like so:

>

> (substitute* "deps/npm/node_modules/node-gyp/gyp/gyp_main.py"

>    (("#!/usr/bin/env python")

>     (string-append "#!" (assoc-ref inputs "python") "/bin/python3")))

>

> Only for node 14+. The reason seems to be that gyp still refers to

> "python", but python2 is no longer a dependency for newer nodes. And it

> seems GYP is perfectly happy with python3, and the shebang is fixed

> upstream so a never node will be fine:

> https://github.com/nodejs/node-gyp/pull/2355/files


I think in some places (but perhaps not enough places) Guix uses 
`python-wrapper` to work around this ...

>

> Maybe updating node would be better than this fix though.

I'm not totally clear on whether the upstream fix is in 14.17.6 LTS, 
but, if so, that seems great!

> 
>> More generally, I see that there are 355 directories installed under
>> "lib/node_modules/npm/node_modules" (which corresponds to the "deps"
>> path above). Most of them don't seem to be available as Guix packages that could
>> be depended upon by other Guix node packages.
> 
> Yeah that's tricky, ideally we should remove all the node_modules deps
> and package them separately, I wonder if anybody tried to do that
> already. I would suspect it to be quite a lot of work, sometimes
> unbundling stops being worth and when it's hard to maintain dependencies
> manually.
> 
> Hopefully we can get there one day though! I don't want to deter anybody
> from trying :-), I might give it a go on a raindy day.

Since these are developed and released with Node, and apparently we can 
build them as part of the Node build process, I was thinking we could 
just make packages that point to these versions we're already building. 
It might be good to hear from someone who develops with node/npm, though 
... I just use it to install software that I can't find packaged elsewhere.

> 
>> On 8/8/21 6:29 PM, Pierre Langlois wrote:
>>
>>>     ... `node-gyp' needs
>>
>>>     node headers to compile against, packaged as a tarball, which it tries
>>
>>>     to download.  Instead, we can run a `node-gyp --tarball <> configure'
>>
>>>     step to manually provide the tarball, which we can package separately
>>
>>>     for any given node version.
>>
>> There is also a --nodedir option, which I found could work with something like:
>>
>>      (string-append "--nodedir=" (assoc-ref inputs "node"))
>>
>> That seems like it might be better, though I don't know all the considerations
>> for cross-compilation and such.
> 
> Oh that's a good idea, I didn't really like having to download the
> headers separately from the main package, especially given we run
> snippet on the source to remove bundled dependencies.
> 
> Trying this out this approach does work, but I needed to:
> 
>    - Create a union directory with both node and libuv. The node package
>      only has headers for V8/node, but we also need libuv, so doing
>      something like this works:
> 
>      (union-build node-sources
>                  (list (assoc-ref inputs "node")
>                        (assoc-ref inputs "libuv"))
>                  #:create-all-directories? #t
>                  #:log-port (%make-void-port "w"))

I found it worked to just add libuv as an input of packages built with 
node-gyp. I hadn't tried to change `node-build-system`, but I think that 
would be the place to do it.

> 
>    - For some reason, --nodedir didn't really "configure" gyp to use that
>      node directory, I think it's meant to be passed everytime you run
>      any gyp command. Instead I found that you can use and environment
>      variable:
> 
>      (setenv "npm_config_nodedir" node-sources)

That seems right. I believe there's a similar "npm_config_python" for 
the Python executable to use.

Alternatively, I think it's possible to configure these in 
$PREFIX/etc/npmrc: <https://docs.npmjs.com/cli/v7/configuring-npm/npmrc>

> 
> And that works for the packages in this series!  That'll be much better
> than before, I'll do it this way.
> 
> Thanks again for taking a look, I'll see if I can send updated patches
> sometimes this weekend.

Glad it was useful!

For patching the shebangs, here's a variant of node-lts that worked for 
me, though I think it would be even better to combine it with the 
existing phases:

```
(define-public patched-node
  (let ((node node-lts))
    (package
      (inherit node)
      (arguments
       (substitute-keyword-arguments (package-arguments node)
         ((#:phases standard-phases)
          `(modify-phases ,standard-phases
             (add-after 'patch-npm-shebang 'patch-more-shebangs
               (lambda* (#:key inputs outputs #:allow-other-keys)
                 (define (append-map f lst)
                   (apply append (map f lst)))
                 ;; from patch-shebangs
                 (define bin-directories
                   ;;(match-lambda
                   ;;  ((_ . dir)
                   (lambda (pr)
                     (let ((dir (cdr pr)))
                       (list (string-append dir "/bin")
                             (string-append dir "/sbin")))))
                 (define output-bindirs
                   (append-map bin-directories outputs))
                 (define input-bindirs
                   ;; Shebangs should refer to binaries of the target 
system---i.e., from
                   ;; "inputs", not from "native-inputs".
                   (append-map bin-directories inputs))
                 (define path
                   (append output-bindirs input-bindirs))
                 (with-directory-excursion
                     (string-append (assoc-ref outputs "out")
                                    "/lib/node_modules/npm/node_modules")
                   (for-each
                    ;;(cut patch-shebang <> path)
                    (lambda (file)
                      (patch-shebang file path))
                    ;; from patch-generated-file-shebangs
                    (find-files "."
                                (lambda (file stat)
                                  (and (eq? 'regular (stat:type stat))
                                       (not (zero? (logand (stat:mode 
stat) #o100)))))
                                #:stat lstat))))))))))))
```

-Philip




This bug report was last modified 2 years and 119 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.