Skip to content

Conversation

mhsmith
Copy link

@mhsmith mhsmith commented Sep 5, 2025

The main motivation for this PR is CMake policy CMP0190, which will prohibit calling FindPython with both the Interpreter and Development components at the same time when cross-compiling. To encourage packages to be compatible with cross-compilation, I've removed Interpreter from all the documentation, examples and tests, except for the places which actually needed it.

CMake is still able to find the Android Python libraries by itself without an interpreter, but it takes a very long time (20 seconds). Going by the --debug-find option, this may be because it's searching a huge number of nonexistent paths, including every possible combination of Python version and abiflags squared (both for the directory name and the library name).

So I've changed builder.py to tell CMake the Python library location on Android, as it already does on Windows.

This performance problem doesn't affect the other Unix platforms, because they have the python3.x-config script available.

See also:

@mhsmith mhsmith changed the title Add Android support fix: add Android support Sep 5, 2025
README.md Outdated
project(${SKBUILD_PROJECT_NAME} LANGUAGES C)
find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)
find_package(Python COMPONENTS Development.Module REQUIRED)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skipping interpreter can be good and bad. Iirc cross compilation with cross-env behaves differently with and without it, but I don't remember which one is more preferred.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think CMake 4.1 kind of forces the no Interpreter case. From what I understand, you can set a emulated Python for it, though.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, since we don't correctly find and pass the Python library, adding the Interpreter components helps on Windows. If we could reliably find the Python library, then we don't need the Interpreter component. For some reason CMake is better than us at finding Python. I'd like a more principled approach than #1093's seeming "try everything" method, but we likely need something to get rid of the Interpreter component.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally think the user should provide the hints themselves when cross-compiling in the toolchain file, and we just document that. There are too many edge-cases we would have to account for, which otherwise could be better handled by SYSROOT and such

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm referring to when not cross compiling - we currently should compute this unless the user specifies something different, but instead we usually don't find it and rely on CMake to find the Python library using the interpreter. Yes, when cross-compiling, it has to be specified.

- An Android
[toolchain file](https://cmake.org/cmake/help/latest/variable/CMAKE_TOOLCHAIN_FILE.html)
which adds the location of the Python headers and libraries to
`CMAKE_FIND_ROOT_PATH`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Until #1050 is resolved, better add a note about how to pass CMAKE_TOOLCHAIN_FILE. Also should add an explicit note about what happens if you are finding Interpreter component or not.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added more details of the toolchain file, and reverted all the Interpreter changes as explained in my comment below.

if python_library:
cache_config[f"{prefix}_LIBRARY"] = python_library
if python_sabi_library:
cache_config[f"{prefix}_SABI_LIBRARY"] = python_sabi_library
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part needs some discussion. I think this would point these to an unwanted location. Could really use a more concrete example of how to cross-compile to see how these are expanded. #1050 is also relevant for these.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what we already have, though, just with android added alongside windows?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I don't believe it is needed or that it has the intended effect when cross-compiling. E.g. are we passing the library of the host or target environment there? A more concrete example of how a cross-compiled android project would help a lot, as well as how each environment does it

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't pass it, then it is required to include Interpreter, since CMake has to find it, it does so by queuing the Python interpreter (which is set to sys.interpreter, so literally the same python we are in now). If a user provides a toolchain file for cross compiling, these get overridden.

Though, to your point, since android will never be the host, not sure adding it here is needed?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we don't pass it, then it is required to include Interpreter, since CMake has to find it, it does so by queuing the Python interpreter (which is set to sys.interpreter, so literally the same python we are in now).

That is specific to windows though right? Because on linux it would use the bash file (forgot the name of it) that contains the configure values used when compiling (dunno why they don't provide something similar to windows though).

Though, to your point, since android will never be the host, not sure adding it here is needed?

Yes that would be preferred imo with relevant documentation

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not needed on other platforms, only Windows and Android care. So I'm not really sure, as it's not used.

@mhsmith
Copy link
Author

mhsmith commented Sep 13, 2025

From what I understand, you can set a emulated Python for it, though.

I saw that in the CMake documentation, but I initially rejected it because starting up a whole Android emulator just to run a short Python script would be too slow.

However, then I realized that cibuildwheel's simulated Android Python environment effectively is an emulator as far as FindPython is concerned. So all we need to do is add a dummy CMAKE_CROSSCOMPILING_EMULATOR to the toolchain file (pypa/cibuildwheel#2591), and then we can build for Android with the Interpreter component included.

This is a much better solution, because it's compatible with the many existing packages which already have Interpreter in their CMakeLists.

@henryiii
Copy link
Collaborator

(I'll work on helping with this when I get back from India, sorry for the delay!)

@jcfr jcfr added this to the v0.12.0 milestone Sep 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants