delocate icon indicating copy to clipboard operation
delocate copied to clipboard

This function does not support separate values per-architecture: 'i386'

Open alexsavulescu opened this issue 2 years ago • 8 comments

Describe the bug running delocate-wheel for an arm64-only wheel with universal2 python installation:

otool: /opt/X11/lib/libSM.6.dylib
Traceback (most recent call last):
  File "/Users/savulesc/Workspace/nrn/nrn_build_venv38_-2850068/bin/delocate-wheel", line 8, in <module>
    sys.exit(main())
  File "/Users/savulesc/Workspace/nrn/nrn_build_venv38_-2850068/lib/python3.8/site-packages/delocate/cmd/delocate_wheel.py", line 128, in main
    copied = delocate_wheel(
  File "/Users/savulesc/Workspace/nrn/nrn_build_venv38_-2850068/lib/python3.8/site-packages/delocate/delocating.py", line 643, in delocate_wheel
    copied_libs = delocate_path(
  File "/Users/savulesc/Workspace/nrn/nrn_build_venv38_-2850068/lib/python3.8/site-packages/delocate/delocating.py", line 465, in delocate_path
    lib_dict = tree_libs_from_directory(
  File "/Users/savulesc/Workspace/nrn/nrn_build_venv38_-2850068/lib/python3.8/site-packages/delocate/libsana.py", line 384, in tree_libs_from_directory
    return _tree_libs_from_libraries(
  File "/Users/savulesc/Workspace/nrn/nrn_build_venv38_-2850068/lib/python3.8/site-packages/delocate/libsana.py", line 309, in _tree_libs_from_libraries
    for depending_path, install_name in get_dependencies(
  File "/Users/savulesc/Workspace/nrn/nrn_build_venv38_-2850068/lib/python3.8/site-packages/delocate/libsana.py", line 105, in get_dependencies
    for install_name in get_install_names(lib_fname):
  File "/Users/savulesc/Workspace/nrn/nrn_build_venv38_-2850068/lib/python3.8/site-packages/delocate/tools.py", line 474, in get_install_names
    names_data = _check_ignore_archs(_parse_otool_install_names(otool.stdout))
  File "/Users/savulesc/Workspace/nrn/nrn_build_venv38_-2850068/lib/python3.8/site-packages/delocate/tools.py", line 324, in _check_ignore_archs
    raise NotImplementedError(
NotImplementedError: This function does not support separate values per-architecture: {'i386': [('/opt/X11/lib/libSM.6.dylib', '7.0.0', '7.1.0'), ('/opt/X11/lib/libICE.6.dylib', '10.0.0', '10.0.0'), ('/usr/lib/libSystem.B.dylib', '1.0.0', '1252.50.4')], 'x86_64': [('/opt/X11/lib/libSM.6.dylib', '7.0.0', '7.1.0'), ('/opt/X11/lib/libICE.6.dylib', '10.0.0', '10.0.0'), ('/usr/lib/libSystem.B.dylib', '1.0.0', '1311.120.1')], 'arm64': [('/opt/X11/lib/libSM.6.dylib', '7.0.0', '7.1.0'), ('/opt/X11/lib/libICE.6.dylib', '10.0.0', '10.0.0'), ('/usr/lib/libSystem.B.dylib', '1.0.0', '1311.120.1')]}

To Reproduce

delocate-wheel -w wheelhouse -v dist/*.whl. # from `build_wheels.bash` -> see `Wheels used` section

Expected behavior delocate-wheel works

Wheels used Attaching here.

Manual: Install universal2 Python 3.8.10 from Python.org ; XQuartz from xquartz.org (this installs to /opt/X11 where the issue is manifesting from) To create the wheel:

git clone [email protected]:neuronsimulator/nrn.git
cd nrn
bash packaging/python/build_static_readline_osx.bash
bash packaging/python/build_wheels.bash osx 3.8

Platform (please complete the following information):

  • OS version: macOS 12.3.1
  • Delocate version: 0.10.2

Additional context If I pop the 'i386' from the dict passed to _check_ignore_archs it works. wheel.zip

alexsavulescu avatar Jul 01 '22 13:07 alexsavulescu

I had to put them side-by-side to understand:

{  'i386': [('/opt/X11/lib/libSM.6.dylib', '7.0.0', '7.1.0'), ('/opt/X11/lib/libICE.6.dylib', '10.0.0', '10.0.0'), ('/usr/lib/libSystem.B.dylib', '1.0.0', '1252.50.4')],
 'x86_64': [('/opt/X11/lib/libSM.6.dylib', '7.0.0', '7.1.0'), ('/opt/X11/lib/libICE.6.dylib', '10.0.0', '10.0.0'), ('/usr/lib/libSystem.B.dylib', '1.0.0', '1311.120.1')],
  'arm64': [('/opt/X11/lib/libSM.6.dylib', '7.0.0', '7.1.0'), ('/opt/X11/lib/libICE.6.dylib', '10.0.0', '10.0.0'), ('/usr/lib/libSystem.B.dylib', '1.0.0', '1311.120.1')]}

I personally wasn't expecting a lib with all three architectures, although I probably should have, and it's clear that ignoring i386 would be appropriate to have this link a universal2 binary.

I'm not sure what would be best here. Based on your workaround, maybe allowing the --require-archs flag to ignore architectures outside of what's specified could work, or use the architectures of the initial in-wheel libraries to determine which ones should be ignored.

I don't have the tools to make a proper test for this, and my setup doesn't make it easy to make contributions either. At most I could approve a PR. In your case you could upload your workaround to a personal branch and tell Pip to install delocate from that.

HexDecimal avatar Jul 01 '22 14:07 HexDecimal

Thanks @HexDecimal , I will try to find some time next week to do a PR.

alexsavulescu avatar Jul 01 '22 14:07 alexsavulescu

There's no simple workaround.

All functions calling _check_ignore_archs will need to become aware of which architectures they're working with by getting that info from their caller. This info will need to passed along the entire chain of functions. With this info, get_install_names can filter dependencies by architecture and ignore the per-architecture versioning.

The CI tests for Decloate were running on older software, but adding macos-14 to the workflow matrix will test the newer tools. Currently tests on macos-14 do not pass.

HexDecimal avatar Jul 22 '24 20:07 HexDecimal

Thanks. I deleted my post, since I realized the problem might not be entirely in delocate. When I build wheels on my local machine they get built for arm64 and delocate processes them successfully. When I build them on Github Actions they instead get built for universal2, and that triggers the error in delocate. I think I need to figure out how to tell it not to build universal wheels?

peastman avatar Jul 22 '24 20:07 peastman

Thanks. I deleted my post, since I realized the problem might not be entirely in delocate.

No, you were correct. This is an issue with Delocate. Specifically that Delocate hasn't yet been updated to correctly handle how the newer macOS tools treat libraries with multiple architectures.

In the future, do not hastily delete your posts. It's better for a repo maintainer to hide your post if it turns out to be irrelevant.

If you're using GitHub Actions then you could workaround the issue by using an older runner. macos-13 or earlier. It's better to use an earlier macOS runner to make wheels since this will often affect compatibility.

HexDecimal avatar Jul 22 '24 21:07 HexDecimal

I don't actually want a multi-architecture wheel. It already uses libraries that are single architecture, so really I just want an arm64 wheel. Then I'll do a separate build on macos-13 to get an x86_64 wheel.

So now I'm digging through the source code for wheel, and found that it's hardcoded to get the architecture from sysconfig.get_platform(). On my computer it returns 'macosx-11.0-arm64', and on the runner it returns 'macosx-10.9-universal2', even though both of them are actually macOS 14.

peastman avatar Jul 22 '24 21:07 peastman

sysconfig.get_platform() will return the architecture that the running Python installation was built for. Normally universal2 is what people want, but you can ask cibuildwheel for alternative architectures.

The platform version number should be as low as possible because wheels are forward compatible.

HexDecimal avatar Jul 22 '24 21:07 HexDecimal

I'm not using cibuildwheel. I was using the python installed with actions/setup-python. I just switched to micromamba and that gets the architecture right. Hopefully it won't cause any compatibility problems (since cibuildwheel uses the python.org versions).

peastman avatar Jul 22 '24 22:07 peastman