エラーの内容
npm install または npm rebuild を実行すると、ビルドが次のエラーで失敗します:
gyp info spawn args '-Wno-unused-variable',
gyp info spawn args '-arch', 'arm64'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
ネイティブ Node.js モジュール — sharp、bcrypt、sqlite3、canvas、node-sass のように C/C++ コードをコンパイルするもの — は、コンパイルとリンクの2段階でビルドされます。このエラーはリンクが失敗したことを意味します。オブジェクトファイルは存在していますが、clang が最終的なバイナリにまとめることができませんでした。
根本原因
macOS のアップグレードが引き金になることがほとんどです。複数の問題が同時に発生する場合があります:
- Xcode コマンドラインツールが未インストール、古い、または macOS アップデート後に静かに破損している
- macOS SDK のパスが変わり、clang がシステムライブラリを見つけられなくなった
- アーキテクチャの不一致 — Apple Silicon(M1/M2/M3)上で x86_64 向けにビルドしようとしている、またはその逆
- ネイティブモジュールがリンクするシステムライブラリやフレームワークが見つからない
- Node.js のバージョンと node-gyp のバージョンに互換性がない
- Python のバージョンが間違っている(node-gyp は Python 3.x が必要で、2.x は非対応)
修正1: Xcode コマンドラインツールを再インストールする
特に macOS アップグレード直後は、これだけで解決することがほとんどです。
# 既存の(壊れている可能性がある)インストールを削除
sudo rm -rf /Library/Developer/CommandLineTools
# 新規インストールを開始
sudo xcode-select --install
確認ダイアログが表示されます。完了したら:
# パスが正しく設定されているか確認
xcode-select -p
# 出力されるべき値: /Library/Developer/CommandLineTools
# clang が動作するか確認
clang --version
npm install を再試行してください。成功すれば完了です。
修正2: Xcode ライセンスの同意と SDK パスのリセット
フル Xcode(CLT だけでなく)にはライセンス同意が必要で、保留中の場合はビルドが静かにブロックされることがあります:
sudo xcodebuild -license accept
次に、xcode-select が指しているパスを確認します:
# フル Xcode がインストールされている場合
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer
# フル Xcode が不要な場合は CLT に戻す
sudo xcode-select -s /Library/Developer/CommandLineTools
修正3: SDK パスを手動で固定する
clang は自身の場所を把握していても、SDK を見失うことがあります。特に macOS の差分アップデートで SDK バージョンが MacOSX13.sdk から MacOSX14.sdk に変わった場合に起きやすいです。明示的に固定してください:
# 現在の SDK パスを確認
xcrun --show-sdk-path
# 例: /Library/Developer/CommandLineTools/SDKs/MacOSX14.sdk
# ビルド前にエクスポート
export SDKROOT=$(xcrun --show-sdk-path)
npm install
次回のターミナルセッションでも壊れないよう、永続的に設定します:
echo 'export SDKROOT=$(xcrun --show-sdk-path)' >> ~/.zshrc
source ~/.zshrc
修正4: Apple Silicon でのアーキテクチャ不一致
M1/M2/M3 Mac は arm64 で動作します。Node.js が Rosetta または x86_64 シェル経由でインストールされていると、リンカーが誤ったアーキテクチャをターゲットにして失敗します。
# Node.js のアーキテクチャを確認
node -e "console.log(process.arch)"
# Apple Silicon では 'arm64' が表示されるべき('x64' ではない)
# Rosetta 上で動作しているか確認
rosetta --version 2>/dev/null || echo "Not using Rosetta"
arm64 Mac で x64 と表示された場合は、Node.js をネイティブで再インストールしてください。Homebrew の場合:
# Homebrew 自体が arm64 かどうか確認
file $(which brew)
# 表示されるべき内容: Mach-O 64-bit executable arm64
brew uninstall node
brew install node
nvm の場合:
nvm install 20 --default
nvm use 20
node -e "console.log(process.arch)" # arm64
修正5: npm キャッシュのクリアとクリーンビルド
壊れたビルド成果物がキャッシュに残ることがあります。根本原因を修正した後でも、npm が同じ壊れたビルドをキャッシュから再生する可能性があります。
npm cache clean --force
rm -rf node_modules
npm install
全体を再インストールせず、特定のパッケージだけを対象にする場合:
npm rebuild sharp
# または
npm rebuild bcrypt
修正6: node-gyp を更新する
古いバージョンの node-gyp は、新しい Node.js リリースや更新された SDK パスを認識しないことがあります。たとえば Node.js 22 には node-gyp 10 以上が必要です。
npm install -g node-gyp@latest
# 更新されたバージョンで再ビルド
node-gyp rebuild
パッケージによっては古い node-gyp を内包していることがあります。次のようにして上書きできます:
npm_config_node_gyp=$(npm root -g)/node-gyp/bin/node-gyp.js npm install
修正7: 不足しているライブラリを見つける
詳細な出力を確認すると、リンカーが何を見つけられなかったかが正確にわかります。汎用的な終了コードよりもはるかに有用です:
npm install --verbose 2>&1 | grep -A5 'linker command failed'
またはエラー自体が提案する -v フラグを使って clang を実行してください。macOS のクリーンインストール後によくある原因:
- OpenSSL(macOS 12 以降に未搭載):
brew install opensslの後、export OPENSSL_ROOT_DIR=$(brew --prefix openssl) - libvips(sharp 用):
brew install vips - libpng / libjpeg:
brew install libpng libjpeg
インストール後、pkg-config を新しいライブラリに向けて再ビルドします:
export PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig:$PKG_CONFIG_PATH"
npm rebuild
動作確認
完了と判断する前に、簡単なチェックを行いましょう:
# 末尾20行を確認 — エラーはすぐに目に入る
npm install 2>&1 | tail -20
# モジュールを読み込んでみる
node -e "require('your-module-name'); console.log('OK')"
# bcrypt での具体的な例
node -e "const b = require('bcrypt'); console.log(b.getRounds(b.hashSync('test', 10)))"
例外が発生しなければ、リンクは成功しており、モジュールは正常に動作しています。
予防策
- macOS をアップグレードするたびに、事前に
sudo xcode-select --installを実行してください — 深夜2時にビルドが失敗してから対処するのでは遅いです - SDK パスの変更が将来のインストールを静かに壊さないよう、シェルプロファイルに
SDKROOTを設定しておきましょう - チーム全体で Node.js のアーキテクチャを統一してください — README に期待される
process.archを明記しましょう - ネイティブモジュールを自身でメンテナンスしている場合は、devDependencies で node-gyp を新しいバージョンに固定してください
- GitHub Actions では、Xcode CLI ツールを明示的にインストールするか、それらがプリインストールされた macOS ランナーイメージを使用してください

