持续在不同的项目中碰到 npm install、pnpm install 或者 yarn add 时的报错,虽然在某个项目中解决了,但在另外的项目中又会碰到,干脆记录下来。
错误
类似这样:
plain
Exit code: 1
Command: node-gyp rebuild
Arguments:
Directory: /Users/jeff-tian/repos/weapp/node_modules/metrohash
Output:
gyp info it worked if it ends with ok
gyp info using node-gyp@8.4.1
gyp info using node@18.17.0 | darwin | arm64
gyp info find Python using Python version 3.12.6 found at /opt/homebrew/opt/python@3.12/bin/python3.12
gyp info spawn /opt/homebrew/opt/python@3.12/bin/python3.12
gyp info spawn args [
gyp info spawn args /Users/jeff-tian/repos/weapp/node_modules/node-gyp/gyp/gyp_main.py,
gyp info spawn args binding.gyp,
gyp info spawn args -f,
gyp info spawn args make,
gyp info spawn args -I,
gyp info spawn args /Users/jeff-tian/repos/weapp/node_modules/metrohash/build/config.gypi,
gyp info spawn args -I,
gyp info spawn args /Users/jeff-tian/repos/weapp/node_modules/node-gyp/addon.gypi,
gyp info spawn args -I,
gyp info spawn args /Users/jeff-tian/Library/Caches/node-gyp/18.17.0/include/node/common.gypi,
gyp info spawn args -Dlibrary=shared_library,
gyp info spawn args -Dvisibility=default,
gyp info spawn args -Dnode_root_dir=/Users/jeff-tian/Library/Caches/node-gyp/18.17.0,
gyp info spawn args -Dnode_gyp_dir=/Users/jeff-tian/repos/weapp/node_modules/node-gyp,
gyp info spawn args -Dnode_lib_file=/Users/jeff-tian/Library/Caches/node-gyp/18.17.0/<(target_arch)/node.lib,
gyp info spawn args -Dmodule_root_dir=/Users/jeff-tian/repos/weapp/node_modules/metrohash,
gyp info spawn args -Dnode_engine=v8,
gyp info spawn args --depth=.,
gyp info spawn args --no-parallel,
gyp info spawn args --generator-output,
gyp info spawn args build,
gyp info spawn args -Goutput_dir=.
gyp info spawn args ]
Traceback (most recent call last):
File /Users/jeff-tian/repos/weapp/node_modules/node-gyp/gyp/gyp_main.py, line 42, in
import gyp # noqa: E402
^^^^^^^^^^
File /Users/jeff-tian/repos/weapp/node_modules/node-gyp/gyp/pylib/gyp/init.py, line 9, in
import gyp.input
File /Users/jeff-tian/repos/weapp/node_modules/node-gyp/gyp/pylib/gyp/input.py, line 19, in
from distutils.version import StrictVersion
ModuleNotFoundError: No module named distutils
gyp ERR! configure error
gyp ERR! stack Error: gyp failed with exit code: 1
gyp ERR! stack at ChildProcess.onCpExit (/Users/jeff-tian/repos/weapp/node_modules/node-gyp/lib/configure.js:259:16)
gyp ERR! stack at ChildProcess.emit (node:events:514:28)
gyp ERR! stack at ChildProcess._handle.onexit (node:internal/child_process:291:12)
gyp ERR! System Darwin 23.3.0
gyp ERR! command /Users/jeff-tian/.nvm/versions/node/v18.17.0/bin/node /Users/jeff-tian/repos/weapp/node_modules/metrohash/node_modules/.bin/node-gyp rebuild
gyp ERR! cwd /Users/jeff-tian/repos/weapp/node_modules/metrohash
或者:
plain
.../node_modules/node-sass postinstall$ node scripts/build.js
│ Binary found at /Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/node-sa…
│ Testing binary
│ Binary has a problem: Error: dlopen(/Users/jeff-tian/brickverse/cool-project/node_m…
│ at Module._extensions..node (node:internal/modules/cjs/loader:1340:18)
│ at Module.load (node:internal/modules/cjs/loader:1119:32)
│ at Module._load (node:internal/modules/cjs/loader:960:12)
│ at Module.require (node:internal/modules/cjs/loader:1143:19)
│ at require (node:internal/modules/cjs/helpers:110:18)
│ at module.exports (/Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/…
│ at Object. (/Users/jeff-tian/brickverse/cool-project/node_modules/.p…
│ at Module._compile (node:internal/modules/cjs/loader:1256:14)
│ at Module._extensions..js (node:internal/modules/cjs/loader:1310:10)
│ at Module.load (node:internal/modules/cjs/loader:1119:32) {
│ code: ERR_DLOPEN_FAILED
│ }
│ Building the binary locally
│ Building: /Users/jeff-tian/.nvm/versions/node/v18.17.0/bin/node /Users/jeff-tian/brickverse/cce-…
│ gyp info it worked if it ends with ok
│ gyp verb cli [
│ gyp verb cli /Users/jeff-tian/.nvm/versions/node/v18.17.0/bin/node,
│ gyp verb cli /Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/node-gy…
│ gyp verb cli rebuild,
│ gyp verb cli --verbose,
│ gyp verb cli --libsass_ext=,
│ gyp verb cli --libsass_cflags=,
│ gyp verb cli --libsass_ldflags=,
│ gyp verb cli --libsass_library=
│ gyp verb cli ]
│ gyp info using node-gyp@8.4.1
│ gyp info using node@18.17.0 | darwin | arm64
│ gyp verb command rebuild []
│ gyp verb command clean []
│ gyp verb clean removing build directory
│ gyp verb command configure []
│ gyp verb find Python Python is not set from command line or npm configuration
│ gyp verb find Python Python is not set from environment variable PYTHON
│ gyp verb find Python checking if python3 can be used
│ gyp verb find Python - executing python3 to get executable path
│ gyp verb find Python - executable path is /opt/homebrew/opt/python@3.12/bin/python3.12
│ gyp verb find Python - executing /opt/homebrew/opt/python@3.12/bin/python3.12 to get v…
│ gyp verb find Python - version is 3.12.6
│ gyp info find Python using Python version 3.12.6 found at /opt/homebrew/opt/python@3.12…
│ gyp verb get node dir no --target version specified, falling back to host node version: …
│ gyp verb command install [ 18.17.0 ]
│ gyp verb install input version string 18.17.0
│ gyp verb install installing version: 18.17.0
│ gyp verb install --ensure was passed, so wont reinstall if already installed
│ gyp verb install version is already installed, need to check installVersion
│ gyp verb got installVersion 9
│ gyp verb needs installVersion 9
│ gyp verb install version is good
│ gyp verb get node dir target node version installed: 18.17.0
│ gyp verb build dir attempting to create build dir: /Users/jeff-tian/brickverse/cce-short-link…
│ gyp verb build dir build dir needed to be created? Yes
│ gyp verb build/config.gypi creating config file
│ gyp verb build/config.gypi writing out config file: /Users/jeff-tian/brickverse/cce-short-link-…
│ gyp verb config.gypi checking for gypi file: /Users/jeff-tian/brickverse/cce-short-link-dashboa…
│ gyp verb common.gypi checking for gypi file: /Users/jeff-tian/brickverse/cce-short-link-dashboa…
│ gyp verb gyp gyp format was not specified; forcing make
│ gyp info spawn /opt/homebrew/opt/python@3.12/bin/python3.12
│ gyp info spawn args [
│ gyp info spawn args /Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/…
│ gyp info spawn args binding.gyp,
│ gyp info spawn args -f,
│ gyp info spawn args make,
│ gyp info spawn args -I,
│ gyp info spawn args /Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/…
│ gyp info spawn args -I,
│ gyp info spawn args /Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/…
│ gyp info spawn args -I,
│ gyp info spawn args /Users/jeff-tian/Library/Caches/node-gyp/18.17.0/include/node/comm…
│ gyp info spawn args -Dlibrary=shared_library,
│ gyp info spawn args -Dvisibility=default,
│ gyp info spawn args -Dnode_root_dir=/Users/jeff-tian/Library/Caches/node-gyp/18.17.0,
│ gyp info spawn args -Dnode_gyp_dir=/Users/jeff-tian/brickverse/cool-project/node…
│ gyp info spawn args -Dnode_lib_file=/Users/jeff-tian/Library/Caches/node-gyp/18.17.0/<…
│ gyp info spawn args -Dmodule_root_dir=/Users/jeff-tian/brickverse/cool-project/n…
│ gyp info spawn args -Dnode_engine=v8,
│ gyp info spawn args --depth=.,
│ gyp info spawn args --no-parallel,
│ gyp info spawn args --generator-output,
│ gyp info spawn args build,
│ gyp info spawn args -Goutput_dir=.
│ gyp info spawn args ]
│ Traceback (most recent call last):
│ File /Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/node-gyp@https+…
│ import gyp # noqa: E402
│ ^^^^^^^^^^
│ File /Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/node-gyp@https+…
│ import gyp.input
│ File /Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/node-gyp@https+…
│ from distutils.version import StrictVersion
│ ModuleNotFoundError: No module named distutils
│ gyp ERR! configure error
│ gyp ERR! stack Error: gyp failed with exit code: 1
│ gyp ERR! stack at ChildProcess.onCpExit (/Users/jeff-tian/brickverse/cce-short-link-dashboa…
│ gyp ERR! stack at ChildProcess.emit (node:events:514:28)
│ gyp ERR! stack at ChildProcess._handle.onexit (node:internal/child_process:291:12)
│ gyp ERR! System Darwin 23.3.0
│ gyp ERR! command /Users/jeff-tian/.nvm/versions/node/v18.17.0/bin/node /Users/jeff-tian…
│ gyp ERR! cwd /Users/jeff-tian/brickverse/cool-project/node_modules/.pnpm/node-sass@…
│ gyp ERR! node -v v18.17.0
│ gyp ERR! node-gyp -v v8.4.1
│ gyp ERR! not ok
│ Build failed with error code: 1
看上去都是和 gyp 有关,并且都提到一个 distutils。我注意到很多项目中都会直接或者间接地引用 node-sass,一旦对它有直接或者间接的依赖,就很容易出现这个问题。
这个 distutils 似乎是一个 python 包,可以通过 python3 -c import distuils进行测试,如果这个命令报错,那就会出现上述错误。
解决办法
一般可以通过 python 的虚拟环境解决。
创建并激活虚拟环境
这可以隔离 python 包,以避免和系统级别的包产生冲突。
plain
python3 -m venv venv
source venv/bin/activate
安装 setuptools 和 wheel
这些包在构建和安装其他包时常常都是需要的。
plain
python3 -m pip install --upgrade pip
python3 -m pip install setuptools wheel
验证 distutils 安装成功了
确保 distutils 在虚拟环境中是可用的。
plain
python3 -c import distutils
重新安装依赖
这时重新执行 npm install 、 pnpm install 或者 yarn add 就可以成功了。