106

Q: Is it possible to change the the context in which npm runs scripts?

What I want to is the following:

"scripts": {
   "test": "gulp mocha",
   "pre-install": "./deps/2.7/cpython/configure --prefix=$(pwd)/build --exec-prefix=$(pwd)/build && make -C deps/2.7/cpython && make -C deps/2.7/cpython install",
   "install": "node-gyp rebuild"
},

Obviously cd deps/2.7/cpython/ && ./configure would work on UNIX-like systems but not on windows.

Why: The root of the problem is, that the configure command of the python repo outputs files into the directory where it is called. The files however are build relevant for make and make install which look for the files in the directory of the repo.

In this case I can't change the Makefile since the build process of Python is understandably complex.

Alternative: The alternative is probably to write some install.js and use node's OS independent API and some child_process.exec(), which I am probably gonna do. However, not leaving npm would be really nice.

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
eljefedelrodeodeljefe
  • 6,304
  • 7
  • 29
  • 61
  • 1
    I believe there is nothing wrong about writing an extra script and run that one from npm. – webduvet May 17 '15 at 16:18
  • 2
    `cd deps/2.7/cpython/ && ./configure` should work on Windows - what problem do you encounter? – Richard Williams May 26 '15 at 10:40
  • Several. You can't use `./configure --prefix=$(pwd)/somepath`. It's not pretty. I haven't found it yet, but `npm` is probably using `var spawn = require('child_process').spawn`, which would allow you to set options like `{cwd: pwd + 'somepath'}`, but isn't exposing it. It's philosophy as well: Package manage have loads of functionality that they have in common with build tools. If they go this road, they need to have certain features like this as well. – eljefedelrodeodeljefe May 26 '15 at 16:07
  • 2
    I've solved it with a fairly large `install.js `, which does roughly that and it gets called from `package.json` like above. The API of `child_process` isn't that easy to handle, though, since it throughs laods of hard to debug erros. Took me some time, but I am happy now – eljefedelrodeodeljefe May 26 '15 at 16:10
  • Authored a PR [here](https://github.com/npm/npm/issues/10957) – eljefedelrodeodeljefe Jan 10 '16 at 19:01
  • Could you add your answer as per the resolution here: https://github.com/npm/npm/pull/10958 ? This will help anyone else with the same issue. – gnerkus Jan 23 '16 at 05:33

3 Answers3

124

npm allows only to do cd dir && command -args, which will also run on Windows.

A change to use node's spawn functionality has been made in PR https://github.com/npm/npm/pull/10958, but was rejected, due to the above solution.

eljefedelrodeodeljefe
  • 6,304
  • 7
  • 29
  • 61
  • 2
    Not sure if I've done something, but have recently had this break in Windows. –  Aug 26 '18 at 05:44
7

As noted above:

npm is probably using

var spawn = require('child_process').spawn

which would allow you to set options like:

    {cwd: pwd + 'somepath'}

but isn't exposing it.

I've solved it with a fairly large install.js, which does roughly that and it gets called from package.json like above. The API of child_process isn't that easy to handle, though, since it throws loads of hard to debug errors. Took me some time, but I am happy now.

Community
  • 1
  • 1
Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
0

try

 const { execSync } = require('child_process');

 execSync(`cd ${your_working_directory} && npm install`) 
pref
  • 1,651
  • 14
  • 24