cibuildwheel icon indicating copy to clipboard operation
cibuildwheel copied to clipboard

How to detect macos architecture inside setup.py

Open reynoldsnlp opened this issue 2 years ago • 11 comments

Description

I would like to change paths for include and libs in setup.py (or change symlinks during before-build), depending on whether cibuildwheel is building for x86_64 or arm64 on MacOS. Is there an environment variable or something similar that I can depend on?

I've tried using platform.version() and platform.uname(), but they always show x86_64.

Build log

No response

CI config

No response

reynoldsnlp avatar Jun 26 '23 23:06 reynoldsnlp

Looks like it can be accessed by inspecting sys.executable. Is there a better way to do this?

reynoldsnlp avatar Jun 27 '23 01:06 reynoldsnlp

platform.machine() is the standard way that cibuildwheel does it.

joerick avatar Jun 27 '23 06:06 joerick

Oh, you want this to support cross-builds. Simplest thing would be to check the _PYTHON_HOST_PLATFORM env var, and fall back to platform.machine() if it's not set. See cibuildwheel/macos.py for values.

There might be a cleaner method using the sysconfig built in module.


edit: just looked it up, I'd suggest sysconfig.get_platform() - that will do the fallbacks for you. e.g.

import sysconfig
sysconfig_platform = sysconfig.get_platform()
is_arm64 = sysconfig_platform.endswith('arm64')
is_universal2 = sysconfig_platform.endswith('universal2')
is_x86_64 = sysconfig_platform.endswith('x86_64')

joerick avatar Jun 27 '23 06:06 joerick

Keep in mind, that tells you about the Python interpreter you are compiling with if _PYTHON_HOST_PLATFORM isn't set. Specifically, is_universal2 could be true on either x86 or ARM if you have a universal build of Python. That's fine, just remember to handle that correctly in your setup.py. :)

henryiii avatar Jun 27 '23 14:06 henryiii

Yep. Though I think that detail echos what most build backends would do, too?

joerick avatar Jun 27 '23 14:06 joerick

Here, the interest is in changing paths based on the target, so you'd need special handing for the universal case - there I think you'd have to assume you are not cross-compiling, since I assume you can't support making universal wheels when doing something like this. But you need to be able to compile and run on a universal interpreter - the official Pythons are universal, for example, so I'd assume you'd fall back to the native arch.

henryiii avatar Jun 27 '23 14:06 henryiii

sysconfig.get_platform() works well for me. Thanks!

Is it something that's worth adding to the docs? If so, I would be happy to submit a PR. Otherwise, feel free to close the issue.

reynoldsnlp avatar Jun 29 '23 01:06 reynoldsnlp

We could add a note to the FAQ around this area - https://cibuildwheel.readthedocs.io/en/stable/faq/#how-to-cross-compile "Detecting the target architecture when cibuildwheel is cross-compiling" - noting the _PYTHON_HOST_PLATFORM mechanism and the sysconfig.get_platform() method. If you have time that would be much appreciated @reynoldsnlp !

joerick avatar Sep 19 '23 14:09 joerick

I'm also curious about this in non-Mac cases.

Say I'm cross-compiling for aarch64 on Linux (with an x86_64 host). In this case, I want to leave out a bunch of ext_modules that compile AVX2 libraries, since there's obviously 0% chance they would be appropriate for the target, even if there's a 99% chance the host has AVX2.

Is a call to sysconfig.get_platform going to return the target architecture, or the host builder's architecture?

James-E-A avatar Feb 07 '24 18:02 James-E-A

We don’t support cross compiling on Linux, only windows and macOS. Linux has other issues (like being forced to use the “system” compiler which is too old to support the new architecture), so it’s generally not useful to pursue traditionally. The Zig compiler sounds like a much more likely path to try.

I think _PYTHON_HOST_PLATFORM works on any system, though.

henryiii avatar Feb 08 '24 15:02 henryiii

+1 to all Henry said.

Just a little note on terminology-

Is a call to sysconfig.get_platform going to return the target architecture, or the host architecture?

It'll return the 'target' i.e. the platform the wheel you're building is gonna run on. Confusingly, in compiler terminology, that's also referred to as the 'host' platform (the machine that does the compiling is called the 'build' system). I suspect that's why the environment variable is called _PYTHON_HOST_PLATFORM.

joerick avatar Feb 08 '24 20:02 joerick