Merge pull request #807 from jbarlow83/pr-auditwheel-diag
Improve diagnostics when auditwheel repair fails
This commit is contained in:
+20
-4
@@ -306,18 +306,27 @@ def build(options: BuildOptions) -> None:
|
|||||||
log.step_end_with_error(
|
log.step_end_with_error(
|
||||||
f"Command {error.cmd} failed with code {error.returncode}. {error.stdout}"
|
f"Command {error.cmd} failed with code {error.returncode}. {error.stdout}"
|
||||||
)
|
)
|
||||||
troubleshoot(options.package_dir, error)
|
troubleshoot(options, error)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
def troubleshoot(package_dir: Path, error: Exception) -> None:
|
def _matches_prepared_command(error_cmd: List[str], command_template: str) -> bool:
|
||||||
|
if len(error_cmd) < 3 or error_cmd[0:2] != ["sh", "-c"]:
|
||||||
|
return False
|
||||||
|
command_prefix = command_template.split("{", maxsplit=1)[0].strip()
|
||||||
|
return error_cmd[2].startswith(command_prefix)
|
||||||
|
|
||||||
|
|
||||||
|
def troubleshoot(options: BuildOptions, error: Exception) -> None:
|
||||||
|
|
||||||
if isinstance(error, subprocess.CalledProcessError) and (
|
if isinstance(error, subprocess.CalledProcessError) and (
|
||||||
error.cmd[0:4] == ["python", "-m", "pip", "wheel"]
|
error.cmd[0:4] == ["python", "-m", "pip", "wheel"]
|
||||||
or error.cmd[0:3] == ["python", "-m", "build"]
|
or error.cmd[0:3] == ["python", "-m", "build"]
|
||||||
|
or _matches_prepared_command(error.cmd, options.repair_command)
|
||||||
):
|
):
|
||||||
# the wheel build step failed
|
# the wheel build step failed
|
||||||
print("Checking for common errors...")
|
print("Checking for common errors...")
|
||||||
so_files = list(package_dir.glob("**/*.so"))
|
so_files = list(options.package_dir.glob("**/*.so"))
|
||||||
|
|
||||||
if so_files:
|
if so_files:
|
||||||
print(
|
print(
|
||||||
@@ -326,10 +335,17 @@ def troubleshoot(package_dir: Path, error: Exception) -> None:
|
|||||||
NOTE: Shared object (.so) files found in this project.
|
NOTE: Shared object (.so) files found in this project.
|
||||||
|
|
||||||
These files might be built against the wrong OS, causing problems with
|
These files might be built against the wrong OS, causing problems with
|
||||||
auditwheel.
|
auditwheel. If possible, run cibuildwheel in a clean checkout.
|
||||||
|
|
||||||
If you're using Cython and have previously done an in-place build,
|
If you're using Cython and have previously done an in-place build,
|
||||||
remove those build files (*.so and *.c) before starting cibuildwheel.
|
remove those build files (*.so and *.c) before starting cibuildwheel.
|
||||||
|
|
||||||
|
setuptools uses the build/ folder to store its build cache. It
|
||||||
|
may be necessary to remove those build files (*.so and *.o) before
|
||||||
|
starting cibuildwheel.
|
||||||
|
|
||||||
|
Files that belong to a virtual environment are probably not an issue
|
||||||
|
unless you used a custom command telling cibuildwheel to activate it.
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
file=sys.stderr,
|
file=sys.stderr,
|
||||||
|
|||||||
@@ -3,25 +3,23 @@ import subprocess
|
|||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from . import utils
|
from . import utils
|
||||||
from .test_projects import TestProject
|
from .test_projects import TestProject, new_c_project
|
||||||
|
|
||||||
so_file_project = TestProject()
|
SO_FILE_WARNING = "NOTE: Shared object (.so) files found in this project."
|
||||||
|
|
||||||
so_file_project.files["libnothing.so"] = ""
|
|
||||||
|
|
||||||
so_file_project.files[
|
|
||||||
"setup.py"
|
|
||||||
] = """
|
|
||||||
raise Exception('this build will fail')
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def test_failed_project_with_so_files(tmp_path, capfd, build_frontend_env):
|
@pytest.mark.parametrize("project_contains_so_files", [False, True])
|
||||||
|
def test_failed_build_with_so_files(tmp_path, capfd, build_frontend_env, project_contains_so_files):
|
||||||
|
project = TestProject()
|
||||||
|
project.files["setup.py"] = "raise Exception('this build will fail')\n"
|
||||||
|
if project_contains_so_files:
|
||||||
|
project.files["libnothing.so"] = ""
|
||||||
|
|
||||||
if utils.platform != "linux":
|
if utils.platform != "linux":
|
||||||
pytest.skip("this test is only relevant to the linux build")
|
pytest.skip("this test is only relevant to the linux build")
|
||||||
|
|
||||||
project_dir = tmp_path / "project"
|
project_dir = tmp_path / "project"
|
||||||
so_file_project.generate(project_dir)
|
project.generate(project_dir)
|
||||||
|
|
||||||
with pytest.raises(subprocess.CalledProcessError):
|
with pytest.raises(subprocess.CalledProcessError):
|
||||||
utils.cibuildwheel_run(project_dir, add_env=build_frontend_env)
|
utils.cibuildwheel_run(project_dir, add_env=build_frontend_env)
|
||||||
@@ -29,4 +27,34 @@ def test_failed_project_with_so_files(tmp_path, capfd, build_frontend_env):
|
|||||||
captured = capfd.readouterr()
|
captured = capfd.readouterr()
|
||||||
print("out", captured.out)
|
print("out", captured.out)
|
||||||
print("err", captured.err)
|
print("err", captured.err)
|
||||||
assert "NOTE: Shared object (.so) files found in this project." in captured.err
|
|
||||||
|
if project_contains_so_files:
|
||||||
|
assert SO_FILE_WARNING in captured.err
|
||||||
|
else:
|
||||||
|
assert SO_FILE_WARNING not in captured.err
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("project_contains_so_files", [False, True])
|
||||||
|
def test_failed_repair_with_so_files(tmp_path, capfd, project_contains_so_files):
|
||||||
|
if utils.platform != "linux":
|
||||||
|
pytest.skip("this test is only relevant to the linux build")
|
||||||
|
|
||||||
|
project = new_c_project()
|
||||||
|
|
||||||
|
if project_contains_so_files:
|
||||||
|
project.files["libnothing.so"] = ""
|
||||||
|
|
||||||
|
project_dir = tmp_path / "project"
|
||||||
|
project.generate(project_dir)
|
||||||
|
|
||||||
|
with pytest.raises(subprocess.CalledProcessError):
|
||||||
|
utils.cibuildwheel_run(project_dir, add_env={"CIBW_REPAIR_WHEEL_COMMAND": "false"})
|
||||||
|
|
||||||
|
captured = capfd.readouterr()
|
||||||
|
print("out", captured.out)
|
||||||
|
print("err", captured.err)
|
||||||
|
|
||||||
|
if project_contains_so_files:
|
||||||
|
assert SO_FILE_WARNING in captured.err
|
||||||
|
else:
|
||||||
|
assert SO_FILE_WARNING not in captured.err
|
||||||
|
|||||||
Reference in New Issue
Block a user