Description
Expected Behavior
cmake
should work with an arbitrary runtime environment when calling the cmake
executable with an absolution path.
Current Behavior
When a venv
(A) is installed with the cmake
PyPI package, a venv/bin/cmake
executable will present in PATH
if the venv
(A) is activated. While install a PyPI package from source, a build venv
(B) will be created. In the build venv
(B), run cmake
installed in the venv
(A) with absolute path will raise an error that cannot find the cmake
module (installed in venv
(A)).
After adding some debug script to the cmake
executable:
#!${PROJECT}/venvA/bin/python3.13
# -*- coding: utf-8 -*-
import re
import sys
+ import site
+ from pprint import pformat
+
+ with open('debug.txt', 'w') as f:
+ print(f'site-packages: {pformat(site.getsitepackages())}', file=f)
+ print(f'sys.path: {pformat(sys.path)}', file=f)
+
from cmake import cmake
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(cmake())
I got:
site-packages: ['${PROJECT}/venvA/lib/python3.13/site-packages']
sys.path: ['${PROJECT}/venvA/bin',
'${TMP}/pip-build-env-xxx/site',
'/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python313.zip',
'/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13',
'/opt/homebrew/Cellar/python@3.13/3.13.2/Frameworks/Python.framework/Versions/3.13/lib/python3.13/lib-dynload',
'${TMP}/pip-build-env-xxx/overlay/lib/python3.13/site-packages',
'${TMP}/pip-build-env-xxx/normal/lib/python3.13/site-packages']
where the site-packages
of venv
(A) is not present in sys.path
.
Reproduce Script
# setup.py
import os
import shutil
from pathlib import Path
from setuptools import Extension, setup
from setuptools.command.build_ext import build_ext
HERE = Path(__file__).absolute().parent
class CMakeExtension(Extension):
def __init__(self, name, source_dir=".", target=None, **kwargs):
super().__init__(name, sources=[], **kwargs)
self.source_dir = Path(source_dir).absolute()
self.target = target if target is not None else name.rpartition(".")[-1]
@classmethod
def cmake_executable(cls):
cmake = os.getenv("CMAKE_EXECUTABLE", "")
if not cmake:
cmake = shutil.which("cmake")
return cmake
class cmake_build_ext(build_ext):
def build_extension(self, ext):
if not isinstance(ext, CMakeExtension):
super().build_extension(ext)
return
cmake = ext.cmake_executable()
if cmake is None:
raise RuntimeError("Cannot find CMake executable.")
self.spawn([cmake, "--version"])
setup(
name="cmake-venv-test",
version="0.0.1",
cmdclass={"build_ext": cmake_build_ext},
ext_modules=[CMakeExtension("cmake_venv_test._C", source_dir=HERE)],
)
$ python3 -m venv venv
$ source venv/bin/activate
$ pip3 install cmake
$ which cmake
${PROJECT}/venv/bin/cmake
$ pip3 install .
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Processing ${PROJECT}
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... done
Building wheels for collected packages: cmake-venv-test
Building wheel for cmake-venv-test (pyproject.toml) ... error
error: subprocess-exited-with-error
× Building wheel for cmake-venv-test (pyproject.toml) did not run successfully.
│ exit code: 1
╰─> [9 lines of output]
running bdist_wheel
running build
running build_ext
${PROJECT}/venv/bin/cmake --version
Traceback (most recent call last):
File "${PROJECT}/venv/bin/cmake", line 5, in <module>
from cmake import cmake
ModuleNotFoundError: No module named 'cmake'
error: command '${PROJECT}/venv/bin/cmake' failed with exit code 1
[end of output]
note: This error originates from a subprocess, and is likely not a problem with pip.
ERROR: Failed building wheel for cmake-venv-test
Failed to build cmake-venv-test
ERROR: Failed to build installable wheels for some pyproject.toml based projects (cmake-venv-test)
Additional Context
Related:
- [BUG]
optree
tries to installcmake
from PyPI unconditionally metaopt/optree#187 - feat(setup): support using system CMake metaopt/optree#188
The above issue and PR changed to use the cmake
executable in PATH
instead of adding the cmake
PyPI package to build-system.requires
in pyproject.toml
.
cc @mgorny