Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local" #1645

Closed
rockchalkwushock opened this issue Oct 30, 2017 · 63 comments

Comments

@rockchalkwushock
Copy link

  • Operating system and version:

  • nvm debug output:

rockchalkwushock in mashaeltsova-photography on development [+?] $ nvm debug
nvm --version: v0.33.6
$TERM_PROGRAM: vscode
$SHELL: /bin/bash
$HOME: /Users/rockchalkwushock
$NVM_DIR: '$HOME/.nvm'
$PREFIX: ''
$NPM_CONFIG_PREFIX: ''
$NVM_NODEJS_ORG_MIRROR: ''
$NVM_IOJS_ORG_MIRROR: ''
shell version: 'GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)'
uname -a: 'Darwin 17.0.0 Darwin Kernel Version 17.0.0: Thu Aug 24 21:48:19 PDT 2017; root:xnu-4570.1.46~2/RELEASE_X86_64 x86_64'
OS version: Mac 10.13 17A405
curl: /usr/bin/curl, curl 7.54.0 (x86_64-apple-darwin17.0) libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0
wget: not found
git: /usr/local/bin/git, git version 2.14.3
grep: /usr/bin/grep, grep (BSD grep) 2.5.1-FreeBSD
awk: /usr/bin/awk, awk version 20070501
sed: illegal option -- -
usage: sed script [-Ealn] [-i extension] [file ...]
       sed [-Ealn] [-i extension] [-e script] ... [-f script_file] ... [file ...]
sed: /usr/bin/sed,
cut: illegal option -- -
usage: cut -b list [-n] [file ...]
       cut -c list [file ...]
       cut -f list [-s] [-d delim] [file ...]
cut: /usr/bin/cut,
basename: illegal option -- -
usage: basename string [suffix]
       basename [-a] [-s suffix] string [...]
basename: /usr/bin/basename,
rm: illegal option -- -
usage: rm [-f | -i] [-dPRrvW] file ...
       unlink file
rm: /bin/rm,
mkdir: illegal option -- -
usage: mkdir [-pv] [-m mode] directory ...
mkdir: /bin/mkdir,
xargs: illegal option -- -
usage: xargs [-0opt] [-E eofstr] [-I replstr [-R replacements]] [-J replstr]
             [-L number] [-n number [-x]] [-P maxprocs] [-s size]
             [utility [argument ...]]
xargs: /usr/bin/xargs,
nvm current: v8.8.1
which node: $NVM_DIR/versions/node/v8.8.1/bin/node
which iojs:
which npm: $NVM_DIR/versions/node/v8.8.1/bin/npm
npm config get prefix: $NVM_DIR/versions/node/v8.8.1
npm root -g: $NVM_DIR/versions/node/v8.8.1/lib/node_modules
  • nvm ls output:
rockchalkwushock in mashaeltsova-photography on development [+?] $ nvm ls
->       v8.8.1
default -> node (-> v8.8.1)
node -> stable (-> v8.8.1) (default)
stable -> 8.8 (-> v8.8.1) (default)
iojs -> N/A (default)
lts/* -> lts/boron (-> N/A)
lts/argon -> v4.8.5 (-> N/A)
lts/boron -> v6.11.5 (-> N/A)
rockchalkwushock in mashaeltsova-photography on development [+?] $
  • How did you install nvm? (e.g. install script in readme, homebrew):
    install_script
  • What steps did you perform?
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash

# inside .bash_profile
export NVM_DIR="$HOME/.nvm";
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh";  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion";  # This loads nvm bash_completion

source .bashrc
nvm install node
nvm use node
  • What happened?
    When trying to commit to git using husky & lint-staged I am getting the following output:
nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"
Run `unset PREFIX` to unset it.
Found '/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/.nvmrc' with version <8.8.1>
nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"
Run `unset PREFIX` to unset it.
Found '/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/.nvmrc' with version <8.8.1>
nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"
Run `unset PREFIX` to unset it.
.git/hooks/pre-commit: line 49: node: command not found
husky > npm run -s precommit (node )

env: node: No such file or directory

husky > pre-commit hook failed (add --no-verify to bypass)
/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/node_modules/commitizen/dist/cli/strategies/git-cz.js:102
        throw error;
        ^

Error: git exited with error code 1
    at ChildProcess.<anonymous> (/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/node_modules/commitizen/dist/git/commit.js:50:26)
    at emitTwo (events.js:125:13)
    at ChildProcess.emit (events.js:213:7)
    at Process.ChildProcess._handle.onexit (internal/child_process.js:200:12)
The script called "commit" which runs "git cz" failed with exit code 1 https://github.com/kentcdodds/nps/blob/v5.7.1/other/ERRORS_AND_WARNINGS.md#failed-with-exit-code
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
  • What did you expect to happen?

Commit and push up as I have been doing with no issues. Had zero problems on Saturday. No updates were ran in between then and now. I have since upgraded nvm from 0.33.4 to 0.33.6 and upgraded node 8.8.0 to 8.8.1. git has always been installed with homebrew and has caused me not issues before when working with nvm.

  • Is there anything in any of your profile files (.bashrc, .bash_profile, .zshrc, etc) that modifies the PATH?
PATH=/Users/rockchalkwushock/.nvm/versions/node/v8.8.1/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/rockchalkwushock/.config/yarn/global/bin

# in .exports
# Set Yarn Global Binary Path.
export PATH="$PATH:`yarn global bin`";
@rockchalkwushock
Copy link
Author

Update

I need to keep moving on this project so I am bypassing the use of git-cz and just running git commit The following was output:

rockchalkwushock in mashaeltsova-photography on rework [+] $ git commit -m "Begin Rework"
Found '/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/.nvmrc' with version <8.8.1>
Now using node v8.8.1 (npm v5.4.2)
Found '/Users/rockchalkwushock/Desktop/MEP/mashaeltsova-photography/.nvmrc' with version <8.8.1>
Now using node v8.8.1 (npm v5.4.2)
husky > npm run -s precommit (node v8.8.1)

Should nvm be running outputting that twice? At any rate I can commit and keep going on this project.

@ljharb
Copy link
Member

ljharb commented Oct 30, 2017

The issue is that something was setting the PREFIX environment variable; if git-cz is doing that, then that's where the issue needs to be filed.

As for the nvm output, if your precommit hook is sourcing nvm.sh twice (perhaps by invoking multiple login shells, instead of doing it all in one go), then the output is expected - if you share the code for your precommit hook, I can take a look at it.

Either way tho this isn't actionable for nvm itself, so I'm going to close the issue (but we can of course keep discussing)

@ljharb ljharb closed this as completed Oct 30, 2017
@bradennapier
Copy link

bradennapier commented Mar 12, 2018

Not really sure why this was closed as it is clearly still an issue.

100% default system here, I just bought a new iMac pro... XCode then this was my first installations. I have installed nvm many times on other systems and now I run into this...

Nothing in my files or setup that could possibly set PREFIX so its being done somewhere invisible to me

Last login: Sun Mar 11 21:20:45 on ttys008
nvm is not compatible with the "PREFIX" environment variable: currently set to "/usr/local"
Run `unset PREFIX` to unset it.
Bradens-iMac-Pro-2:~ bradennapier$ 

with my .bashrc

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

and my .bash_profile

source ~/.bashrc

I have reinstalled nvm, i have tried everything. I have never installed node on the system.

This appears to happen by doing a npm install -g ____ as a default issue

Perhaps Node 9.8.0 uses PREFIX?

I literally have no idea how that is set but i have about 100 env vars set by default in terminal seemingly by XCode

I would also point out that OSX's default Terminal.app does not work however iTerm does work.

@bradennapier
Copy link

Since this is being launched by react-native - it does appear it might be related to that in some way?

expo/expo#626

Not really sure it works sometimes but not others at this point

@temrysh
Copy link

temrysh commented May 9, 2018

@bradennapier Seems like Xcode launching Terminal from /usr/local, but your nvm has been installed and located in your user's folder.

@JBallin

This comment has been minimized.

@ljharb

This comment has been minimized.

@JBallin

This comment has been minimized.

@goodevilgenius
Copy link

I had this issue trying to use nvm in Termux, which is a prefixed Linux environment for Android.

I got around it by running:

PREFIX= nvm use --delete-prefix stable

This didn't unset the PREFIX environment variable, or even delete the prefix npm config (npm config get prefix still returns the old prefix), but it did let nvm run properly.

@ljharb
Copy link
Member

ljharb commented Jun 12, 2018

@goodevilgenius note that that will cause nvm to not actually work properly - which is the reason that the prefix is blocked in the first place. Why is the prefix needed?

@goodevilgenius
Copy link

goodevilgenius commented Jun 13, 2018

@ljharb The prefix is needed in Termux. It's a Linux environment made to work on top of an existing version of Android. It's not a chroot, and since it's made to work without root access, it must be installed within a directory to which it has write permissions, thus the need for the PREFIX. The entire system (apt, coreutils, the home directory, etc.) are installed into the app's data directory.

I can install node as usual through apt, and it works fine. But nvm fails because of the PREFIX.

@ljharb
Copy link
Member

ljharb commented Jun 13, 2018

@goodevilgenius PREFIX is used to change the location of npm root -g. When using nvm, that lives inside $NVM_DIR - which is inside that directory. Thus, you should not, in fact, need PREFIX for node when using nvm under any circumstances. (separately, don't install node via apt, and if you insist on doing so, use the nodesource repo)

@goodevilgenius
Copy link

@ljharb That's fine for nvm, but I'm saying that I have to have PREFIX set when using Termux, otherwise other apps won't work properly. It's just the way Termux was built.

So, by doing PREFIX= nvm use --delete-prefix stable, it basically unset PREFIX only for nvm. npm and npx then worked after that, although node did not.

But, I can't just add unset PREFIX in my .bashrc and use everything as usual. Everything else will break.

@ljharb
Copy link
Member

ljharb commented Jun 13, 2018

@goodevilgenius ohhh i gotcha, it's a collision in the environment variable name :-( that's very unfortunate. The problem is that PREFIX will also change how npm works - so that kind of sounds like Termux is simply incompatible with node/npm, tbh.

@goodevilgenius
Copy link

node/npm work fine in Termux when installed from apt, just not when installed from nvm.

@ljharb
Copy link
Member

ljharb commented Jun 13, 2018

@goodevilgenius npm root -g will be whatever's in $PREFIX; that's still impacting npm even if it ends up working. nvm is incompatible with having a prefix, so it seems like Termux is, at the moment, incompatible with nvm.

Please file a separate issue for tracking Termux specifically.

@JBallin

This comment has been minimized.

@AugustoAleGon
Copy link

Having the same issue. With no solution at all

@redreceipt
Copy link

I uninstalled Termux and the issue went away so there's definitely a conflict that needs to be worked out.

@luxueyan
Copy link

luxueyan commented Jan 7, 2019

@goodevilgenius I have the same problem, is there new resolution pls?

@goodevilgenius
Copy link

@luxueyan I never found a solution. I just installed node from apt, instead of using nvm.

@ljharb
Copy link
Member

ljharb commented Jan 7, 2019

@goodevilgenius I’d be happy to help if you filed a separate issue; node shouldn’t be installed from apt.

@goodevilgenius
Copy link

@ljharb What would be the point of creating a separate issue? This issue already states the problem. You said:

nvm is incompatible with having a prefix, so it seems like Termux is, at the moment, incompatible with nvm.

Termux isn't going to stop using a PREFIX, as it's necessary to their implementation on Android, and nvm isn't going to support an environment with PREFIX, or this issue wouldn't have been closed, so as far as I can tell, ne'er the twain shall meet.

@ljharb
Copy link
Member

ljharb commented Jan 7, 2019

Ah, fair enough.

@luxueyan
Copy link

luxueyan commented Jan 8, 2019

@goodevilgenius Now my resolution is installing a ubuntu using atilo:https://github.com/YadominJinta/atilo and then install nvm in ubuntu.

@mjumbewu
Copy link

Agree that this appears to be an actual issue.

Could a possible solution be to use a more specific environment variable name instead of PREFIX? Something like NVM_PREFIX, which would make collisions much less likely

@ljharb
Copy link
Member

ljharb commented Sep 21, 2020

@mjumbewu no, unfortunately it's node itself that uses "PREFIX", and the nature of a node version manager is that it needs to own the prefix location, so there's simply no working around it.

In other words, if both Termux and node aren't going to change, then Termux just isn't compatible with using a node version manager. I'm still not clear on why Termux couldn't change the name of their env var - is there an issue on their project I could read about it?

@sfratini
Copy link

sfratini commented Nov 6, 2020

FYI, I am having this issue with any regular MacOS terminal now. I am using react native as someone posted before and my PREFIX variable returns '/usr/local'. Not sure which tool is setting it now. @goodevilgenius workaround worked for me tho.

@emidesigns
Copy link

@ntelkedzhiev 's solution worked. Small grammar police thing to note, the command is brew uninstall yarn but I'm sure most of us figured that out :)

Thank you @ntelkedzhiev !

@Nevosis
Copy link

Nevosis commented Feb 16, 2022

No need to unset anything... This behavior happens when you have more than 1 installation of npm/yarn. I had 3 :D. Here are the steps I performed in order to solve it:

1. Delete all installations of npm and yarn.
brew uninstall npm 
brew unistall yarn

npm uninstall yarn

uninstall npm. See https://docs.npmjs.com/cli/v7/using-npm/removal.

2. Make sure you have a working nvm. `which npm` should return something like this `/Users/*******/.nvm/versions/node/v14.17.0/bin/npm` and not a path that starts with `/usr/local`.

3. ONLY AFTER THAT, install yarn globally with `npm install -g yarn`.

Thanks a lot. I had to reinstall nvm to have access to npm somehow.
This SO thread helped me : https://stackoverflow.com/a/68165193/4099279

@Viiprogrammer
Copy link

When I try to configure husky pre commit hook to commitlint, I get error:

image

I try to create .huskyrc with NVM load script:


export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

I get more errors:
image

My solution


When I try to add node to PATH in .huskyrc directly, it's works fine

export PATH=/home/righthaze/.nvm/versions/node/v16.16.0/bin:$PATH

where - v16.16.0 my node version

image

@p8ul
Copy link

p8ul commented Sep 6, 2022

I fixed this by editing <name-of-your-app>/node_modules/react-native/scripts/node-binary.sh

Paste this after line 6 (after the comment section)

# LICENSE file in the root directory of this source tree. -> this is line 5 of original file

source ~/.nvm/nvm.sh
[[ -s $HOME/.nvm/nvm.sh ]] && . $HOME/.nvm/nvm.sh  # This loads NVM
unset PREFIX
PREFIX= nvm use --delete-prefix stable
nvm use default

@piperiver
Copy link

@bradennapier Seems like Xcode launching Terminal from /usr/local, but your nvm has been installed and located in your user's folder.

this is my solution

  1. Move the .nvm folder (user root directory) to the directory /usr/local
  2. update the location on your .zshrc or .bash_profile file
  3. restart your terminal

@martin-braun
Copy link

martin-braun commented Jan 14, 2023

@ljharb

In other words, if both Termux and node aren't going to change, then Termux just isn't compatible with using a node version manager. I'm still not clear on why Termux couldn't change the name of their env var - is there an issue on their project I could read about it?

What a great suffering trying to get NVM and Termux work in harmony now, because of the "great" naming decisions that were made on Termux and Nodes end.

To answer your questions few years after:

PREFIX can't be renamed in termux at this point. Termux packages including termux-tools, scripts of termux users, wikis, termux plugins, etc rely on it. Changing it would break a lot (understatement), so it's not possible.

Originally posted by @agnostic-apollo in termux/termux-app#2096 (comment)

What I don't get, though: If this cannot be fixed in NVM and Node is at fault, how is it that Node runs when installed from the Termux package manager?

Is there really nothing we can do about it?

What if I create aliases for npm and node in which I preset the proper PREFIX? What should the PREFIX actually be to get node and npm to work? I tried to launch node --prefix $NVM_DIR/versions/node/v.../ for test purposes, but no matter what I launch it with, I always get: bash: /data/data/com.termux/files/home/.nvm/versions/node/v.../bin/node: cannot execute: required file not found. I was able to get this far by doing PREFIX= nvm install 'lts/*'

@ljharb
Copy link
Member

ljharb commented Jan 15, 2023

Since node isn't officially distributed on the Termux package manager, i'm assuming it's been patched somehow.

There's really nothing we can do about it, unless termux's PREFIX variable can work when pointed to the default location of npm root -g on whichever npm-managed node is active.

@martin-braun
Copy link

martin-braun commented Jan 15, 2023

unless termux's PREFIX variable can work when pointed to the default location of npm root -g on whichever npm-managed node is active.

will never gonna happen, it points to the usr directory within the Termux files. It will break everything if it will be changed.

This is really a huge F for both parties. I was trying to give node and npm a scoped variable somehow, but even overriding the prefix explicitly was not leading to any direction. I'm not deep enough into their code to understand it (yet) and their documentation lacks clear information about the PREFIX variable, only the argument is documented.

I wasn't sure about the "mistakes were made" statement from Ryan Dahl until I faced this limitation yesterday. Termux has blood on their hands as well, I mean, it could've been obvious that PREFIX could collide and that TERMUX_PREFIX would've been a smarter choice, but we are humans and human do errors.

Now running their nodejs-lts, so that the neovim-node-host can run at least, but it locks me away from testing some legacy stuff before porting it to LTS, which is quite a bummer.

@agnostic-apollo
Copy link

agnostic-apollo commented Jan 15, 2023

I have added support in termux-app to export $TERMUX__PREFIX as well and can move our packages repo to use it as well in future, but we have millions of users and they would still be using $PREFIX in their custom scripts. Third party, including multi platform ones also use $PREFIX, likely to check if running in termux if its set to /data/data/com.termux/files/user. So even if I wanted to, its unlikely that we can ever remove it, or at the very least for a long while. We can deprecate $PREFIX in next version and put out an advisory to users to use $TERMUX__PREFIX instead, pretty much all we can do at this point.

As for solving issues of termux and other platforms where $PREFIX may be set to something different, wouldn't it be much simpler to just patch the receivers node/npm/nvm instead of tonne of others repos/scripts? Can't something like $NPM_IGNORE_LEGACY_PREFIX be added to ignore using $PREFIX if its already set, and to use $NPM_PREFIX as well or something. The node prefix and node root -g can be patched appropriately. Or are other node packages and support tools using $PREFIX directly somehow without the commands? I don't use node myself, so my knowledge is lacking in that area.

If I am not mistaken, the patches should be pretty simple to set globalPrefix.

https://docs.npmjs.com/cli/v8/commands/npm-root

https://docs.npmjs.com/cli/v9/commands/npm-prefix

https://github.com/search?q=org%3Anpm+env.PREFIX&type=code

https://github.com/search?q=org%3Anodejs+%24PREFIX&type=code

https://github.com/search?q=org%3Anpm+%24PREFIX&type=code&p=2

https://github.com/nodejs/node/blob/67a9ed3f7f3c02cd908f98ac375bf1041a64ec70/Makefile#L189

https://github.com/nodejs/node/blob/67a9ed3f7f3c02cd908f98ac375bf1041a64ec70/lib/internal/modules/cjs/loader.js#L1380

@ljharb
Copy link
Member

ljharb commented Jan 15, 2023

There are far more installations of npm than termux, without any doubt, so the easiest would be patching termux.

@ksh5a

This comment was marked as spam.

@martin-braun
Copy link

martin-braun commented Jan 15, 2023

@agnostic-apollo first of all, thank you for stepping in explaining the matter in your own words. I think that deprecating PREFIX and introducing TERMUX__PREFIX is still the way to go, regardless of other actions taken or not, because I think it is better to have rather less collision potential in the far future than such a high risk potential of collisions forever. The result could be that unsetting PREFIX could become a Termux property that will come with a risk to break old things, but given enough time the risk shall becomes low as third parties update their scripts. Unfortunately, accessing PREFIX cannot print any warning on stderr, so it's really necessary to inform developers to update their scripts to use the new environment variable.

Patching npm would be great too, but you'd have to update unmaintained decade-old versions of it, since the latest npm is not compatible with older node versions in my experience. I have to agree with @ljharb's statement about the numbers, but I can absolutely understand that these are not pleasant conclusions for maintaining Termux.

@ljharb I think changing this in Termux is still harder though. If I understand you correctly, npm just reads this variable and nvm provides it. Termux cannot change it easily, because there are far more scripts in the wild that rely on this variable. On the flip-side npm could just read a different variable and fallback to $PREFIX, if it is not found. Then you could simply set the new variable and things would not break.

I opened a discussion at npm about it.

@agnostic-apollo
Copy link

agnostic-apollo commented Jan 15, 2023

To be clear, it’s npm, not node, that looks at PREFIX.

The node makefile is using it too.

https://github.com/nodejs/node/blob/67a9ed3f7f3c02cd908f98ac375bf1041a64ec70/Makefile#L189

There are far more installations of npm than termux, without any doubt, so the easiest would be patching termux.

Sure. But why would that matter? Users can use the new version if they want the fix and it will behave just as before without any breaking changes, and $PREFIX will be used as well, unless $NPM_IGNORE_LEGACY_PREFIX is set. Patching couple of functions in npm should surely be easier than patching countless user scripts and third party softwares and multiple termux packages. And like I said, even if termux internal packages are patched, it doesn't matter too much, its like a linux distribution, users using $PREFIX would still exist unless they move.

But I guess, if termux internal packages are patched, then it should allow users who want to unset $PREFIX to be able to do that as long as they don't use third party software that requires it. I also don't know if even patching 100% of termux internal packages would even be possible without any issues.

And adding a alternate variable (like $NPM_PREFIX) to solve compatibility or conflict issues from old software is standard practice.

thank you for stepping in explaining the matter in your own words.

You are very welcome.

, because I think it is better to have rather less collision potential in the far future than such a high risk potential of collisions forever.

Yeah, I agree. I didn't add the $PREFIX variable myself, it exists since termux was created in 2015, I only took over development around 2 years ago, but any new variables that I add now are all scoped to $TERMUX__ or $TERMUX_APP__, etc, to prevent this kinda situation. Softwares should always use scoped variables, easier to understand code too.

but you'd have to update unmaintained decade-old versions of it, since the latest npm is not compatible with older node versions in my experience.

Termux only provides latest and LTS node, so using latest npm and latest/LTS node should work just fine. Old versions get removed from our repos and mirrors due to space issues and shared lib linking issues against old dependencies. There are user hosted repos that provide old versions, but everyone knows that all fixes don't get backported and often updated versions must be used for fixes.

https://github.com/termux/termux-packages/tree/master/packages/nodejs

https://github.com/termux/termux-packages/tree/master/packages/nodejs-lts

For a patch, currently npm uses checks like following in different places

https://github.com/npm/libnpmconfig/blob/e9b201772fc461dd66b0b65a768e1f888273c302/index.js#L94

function getGlobalPrefix () {
  if (process.env.PREFIX) {
    return process.env.PREFIX
  } else if (process.platform === 'win32') {
    // c:\node\node.exe --> prefix=c:\node\
    return path.dirname(process.execPath)
  } else {
    // /usr/local/bin/node --> prefix=/usr/local
    let pref = path.dirname(path.dirname(process.execPath))
    // destdir only is respected on Unix
    if (process.env.DESTDIR) {
      pref = path.join(process.env.DESTDIR, pref)
    }
    return pref
  }
}

And it can use

function getGlobalPrefix () {
  if (process.env.NPM_PREFIX) {
    return process.env.NPM_PREFIX
  } else if (process.env.PREFIX && process.env.NPM_IGNORE_LEGACY_PREFIX != "1") {
    return process.env.PREFIX
  } else if (process.platform === 'win32') {
...

Then termux and other $PREFIX conflicted platforms can always export NPM_IGNORE_LEGACY_PREFIX=1 and optionally export $NPM_PREFIX if they need custom prefix.

@agnostic-apollo
Copy link

@thunder-coding Tagging you (termux nodejs packages maintainer) here since you would know better about potential issues than me and may be able to suggest a different design.

@martin-braun
Copy link

martin-braun commented Jan 15, 2023

Termux only provides latest and LTS node, so using latest npm and latest/LTS node should work just fine.

But the issue is not with node latest or LTS from the Termux repos, the issue is with nvm and Termux as nvm requires to set $PREFIX. You would need to patch a lot of node/npm versions to support most of the versions that nvm can install.

Softwares should always use scoped variables, easier to understand code too.

I couldn't agree more to this.

And it can use
...

You don't need a flag to ignore the legacy variable. As long as NPM_PREFIX is read first nvm could simply set this and PREFIX could be dedicated to Termux.

I've looked into the versions of node/npm and luckily, older LTS versions of node are shipped with newer versions of npm, which would boil down to 3 versions requiring to be patched to get as far as node v12 back:

  • node 19 = npm 9.2
  • node 18 & 16 = npm 8.19
  • node 14 & 12 = npm 6.14

I doubt npm 6.14 will be patched though, since node 14 is out of support, but it would be nice to see.

@agnostic-apollo
Copy link

You would need to patch a lot of node/npm versions to support most of the versions that nvm can install.

I see, I don't know the details of nvm, so I am probably missing things regarding the issue. But wouldn't providing the latest version of major npm/node releases that have been patched and using $NPM_PREFIX fix the issue for users who install the latest version and any future versions?

You don't need a flag to ignore the legacy variable

It would be needed if user wants to engage the current third condition and $PREFIX is already set, like in termux, there would be cases where npm is used without nvm setting prefix.

let pref = path.dirname(path.dirname(process.execPath))

@martin-braun
Copy link

I see, I don't know the details of nvm, so I am probably missing things regarding the issue. But wouldn't providing the latest version of major npm/node releases that have been patched and using $NPM_PREFIX fix the issue for users who install the latest version and any future versions?

nvm is a version manager for node and npm that allows to install any versions of node/npm at the same time by switching between environments. Every node version has a specific npm version that it ships with. Simply fixing the issue in the latest npm version will fix the issue in the future, but older projects that require older node versions still won't run in Termux.

It would be needed if user wants to engage the current third condition and $PREFIX is already set, like in termux, there would be cases where npm is used without nvm setting prefix.

Yes you are right, I missed that final else if statement.

@agnostic-apollo
Copy link

agnostic-apollo commented Jan 15, 2023

but older projects that require older node versions still won't run in Termux.

I understand that part, but since termux doesn't keep old versions of node, so there wouldn't exist users using it, unless they stick to old versions or are using custom repos to get them. A way should be looked into getting out of this mess for future versions, instead of doing nothing since old versions may never get fixed.

Moreover, if users want old versions fixed, they can always send pull requests so that nvm maintainers don't need to fix old versions themselves.

There is also the issue that node provided by termux is patched to work for termux and standard node wouldn't work.

@ljharb
Copy link
Member

ljharb commented Jan 15, 2023

@agnostic-apollo nvm provides all old versions of node, so nvm users on termux will forever have this problem (unless termux is able to change)

@agnostic-apollo
Copy link

Right, sorry. I guess then suggested fix would only be useful for npm, but not for nvm. Standard node provided by nvm wouldn't work for termux either if its not patched for termux or conditional patches get merged in upstream.

@ljharb
Copy link
Member

ljharb commented Jan 15, 2023

Exactly. If this had been fixed when it was first reported to termux (years ago, long before you took over) then it might be reasonable to tell termux users "just confine yourselves to node > n", but that n would be way too high to be useful advice for a long time if it were fixed today.

@martin-braun
Copy link

martin-braun commented Jan 16, 2023

I understand that part, but since termux doesn't keep old versions of node ...

nvm itself installs old versions of node/npm. It does not leverage pkg or apt, so Termux would absolutely keep old versions of node installed by nvm, as @ljharb said.

I guess then suggested fix would only be useful for npm, but not for nvm.

It would be useful if you patch a couple of major versions of npm and publish new minor versions of all (LTS) versions of node to ship with the new npm. This wouldn't fix the entire problem, but would enable at least the latest LTS versions to function in Termux with nvm, which would be a big win, already.

Even if we fix it today for future versions of node / npm only, it would be at least no problem in half or full a decade.

@Efreak
Copy link

Efreak commented Oct 9, 2023

Is there any chance nvm can maintain a set of patches for existing users to apply and build node/nvm themselves? Such patches should probably be kept by nvm (because nvm would be applying them, though perhaps they should be kept in a community patch repo), however it should be entirely possible to simply copy them from termux build scripts.

While it's not ideal to be building your own nodejs for each install, I already use nvm install -s on a server that's far inferior to most modern Android devices (1 vcpu, 512mb ram) and it should be entirely possible (for users, not necessarily nvm) to redistribute with an index in a repo and the binaries in GitHub releases. This would also be useful in other scenarios, like building nodejs with custom build settings, or even simply hosting nodejs releases inside a firewall without network access.

@ljharb
Copy link
Member

ljharb commented Oct 9, 2023

I don't think it makes any sense for nvm to maintain patches, unless it's something that can be done transparently for a wide swath of environments.

huntie added a commit to huntie/dotfiles that referenced this issue Apr 2, 2024
https://github.com/Schniz/fnm

Performance motivated — since my shell startup time was being greatly slowed by nvm.

Also resolves [this](nvm-sh/nvm#1645 (comment)) incompatibility warning in macOS Terminal, where I was still looking for a workaround.
huntie added a commit to huntie/dotfiles that referenced this issue Apr 2, 2024
https://github.com/Schniz/fnm

Performance motivated — since my shell startup time was being greatly slowed by nvm.

Also resolves [this](nvm-sh/nvm#1645 (comment)) incompatibility warning in macOS Terminal, where I was still looking for a workaround.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests