問題
Windows 環境で poetry install を実行すると、C++ バックエンド (_tangency_cpp_impl.dll) のビルドが 2 回呼び出され、2 回目に LNK1104 エラーで失敗する。
エラーメッセージ
\
LINK : fatal error LNK1104: ファイル '_tangency_cpp_impl.dll' を開くことができません。
subprocess.CalledProcessError: Command '[...\link.exe', ..., '/OUT:..._tangency_cpp_impl.dll']' returned non-zero exit status 1104.
distutils.errors.DistutilsExecError: command '...link.exe' failed with exit code 1104
\\
再現手順
- Windows 上で poetry install を実行する(特に .venv を削除後のクリーンな状態)。
- 1 回目のビルドは成功し DLL が生成される。
- Poetry が build backend を再度呼び出す際(wheel の install フェーズ)に同じ DLL へ上書き書き込みしようとするが、1 回目のビルドスクリプト内で ctypes.CDLL() によりロードされた DLL がプロセスに保持されており、ファイルが排他ロックされている。
- リンカが DLL を開けずエラー終了する。
原因の詳細
scripts/build_tangency_cpp.py の build() 関数内で既存 DLL のバージョンを確認するために ctypes.CDLL(str(path)) を呼び出している。Windows では LoadLibrary でロードしたファイルはプロセスが終了するまで排他ロックされるため、同一プロセス内での上書きができない。
Poetry の build backend は「build wheel」と「install wheel」の 2 フェーズで build hook を呼び出すため、同一 Python プロセス内でビルドスクリプトが 2 回実行される。
対応案
_existing_library_version() / _existing_library_linalg_kind() 内で ctypes.CDLL() によるロードを行う前に、プロセスを分離してバージョン文字列を取得する(例: subprocess.check_output で別プロセスを起動)。あるいは DLL を一時ディレクトリへコピーしてからロードすることでロックを回避できる。
暫定ワークアラウンド
pip install -e . --no-build-isolation を使用することでビルドが 1 回に抑えられ問題を回避できる。
問題
Windows 環境で poetry install を実行すると、C++ バックエンド (_tangency_cpp_impl.dll) のビルドが 2 回呼び出され、2 回目に LNK1104 エラーで失敗する。
エラーメッセージ
\
LINK : fatal error LNK1104: ファイル '_tangency_cpp_impl.dll' を開くことができません。
subprocess.CalledProcessError: Command '[...\link.exe', ..., '/OUT:..._tangency_cpp_impl.dll']' returned non-zero exit status 1104.
distutils.errors.DistutilsExecError: command '...link.exe' failed with exit code 1104
\\
再現手順
原因の詳細
scripts/build_tangency_cpp.py の build() 関数内で既存 DLL のバージョンを確認するために ctypes.CDLL(str(path)) を呼び出している。Windows では LoadLibrary でロードしたファイルはプロセスが終了するまで排他ロックされるため、同一プロセス内での上書きができない。
Poetry の build backend は「build wheel」と「install wheel」の 2 フェーズで build hook を呼び出すため、同一 Python プロセス内でビルドスクリプトが 2 回実行される。
対応案
_existing_library_version() / _existing_library_linalg_kind() 内で ctypes.CDLL() によるロードを行う前に、プロセスを分離してバージョン文字列を取得する(例: subprocess.check_output で別プロセスを起動)。あるいは DLL を一時ディレクトリへコピーしてからロードすることでロックを回避できる。
暫定ワークアラウンド
pip install -e . --no-build-isolation を使用することでビルドが 1 回に抑えられ問題を回避できる。