beeware / Python-Apple-support

A meta-package for building a version of Python that can be embedded into a macOS, iOS, tvOS or watchOS project.
MIT License
1.08k stars 155 forks source link

Using the manual installation (without briefcase), is there any way to install third party library like numpy ? #175

Closed johnfhima closed 1 year ago

johnfhima commented 1 year ago

Describe the bug

I have successfully completed your tutorial for the manual installation. I would like to use add python code to a swift project that already exist. Nevertheless I need numpy inside this code. Could you explain me what I should do to be able to install third part library (like numpy) ?

Thanks

Steps to reproduce

--

Expected behavior

--

Screenshots

No response

Environment

--

Logs

No response

Additional context

No response

freakboy3742 commented 1 year ago

Yes, you can install third party libraries; however, the process isn't simple. There's a reason Briefcase exists :-)

If it's a pure Python package, you can install the package into your source tree somewhere (pip install --target <some folder> <pkgname> will be useful here), ensure those resources are included in your app bundle, then configure your Python installation to include that path as part of your PYTHONPATH/sys.path.

If it's a binary package (like numpy), it's more complicated. You need to either obtain or build a compiled binary wheel that contains 2 .so files - one for the simulator ABI (potentially with 2 architectures - arm64 and x86_64), and one for the device ABI. You can get some precompiled binary wheels from the BeeWare iOS wheel repository - if you use pip install --prefer-binary --extra-index-url https://pypi.anaconda.org/beeware/simple --target <some folder> <pkgname>, you can install those wheels into your target packages folder. If the binary you want isn't in that repository, you need to build your own - at present, that isn't a simple proposition, but this folder contains the tools that were used to build the BeeWare packages.

Any .so files that are part of wheels then need to be signed with the app's signature.

It's very difficult to provide step-by-step instructions, as the specifics are entirely dependent on your own app. The best advice I can give you is to generate a test project using briefcase, passing in the -v option - that will show you all the commands that Briefcase is running under the hood; the generated Xcode project includes the build steps to sign the binary wheel libraries.

johnfhima commented 1 year ago

Thanks for your fast answer. Indeed it looks complicated and I am not sur I get everything. Is there any place I could find some details for the different step ? Let's assume I create a briefcase project. How can I use what have been generated inside an existing project to embed python with the libraries installed with briefcase ?

Thanks

freakboy3742 commented 1 year ago

We haven't really documented the steps - mostly because our focus is on using Briefcase to make the process as simple as possible for end users.

As for how to use what Briefcase generates - Briefcase generates an Xcode project; so compare, contrast and combine with your own project; and the process by which Briefcase generates what it does can be revealed by running any Briefcase command with -v to show the command line that was executed.

johnfhima commented 1 year ago

Thanks. But I am a bit lost using briefcase. The Xcode project it build me is not a classical one (swift UI or storyboard). I want my swift code to be able to run python function but I don't want to write an app without swift. Could you then explain me how could I create a project using briefcase and then use it as a regular swift project( ie storyboard) ?

freakboy3742 commented 1 year ago

This support package is enough to give you access to the Python embedded C API; the Briefcase projects shows you the Objective-C and Xcode settings that are needed to access that API. Those fundamentals won't change with a swift project; although the code invoking the C API will obviously change.

I believe PythonKit might be more helpful for Swift projects; but I haven't used it myself.

johnfhima commented 1 year ago

Finally by changing the version of the python installed to 3.9 I succeed to import numpy. Nevertheless I can't import scikit-image. Here is the error I have. Thanks for your help

Capture d’écran 2023-02-07 à 22 50 15
johnfhima commented 1 year ago

It also not work to install scikit-image using briefcase. Is there any other option to install this library ?

freakboy3742 commented 1 year ago

scikit-image hasn't been pre-compiled for iOS because of some complications - it's dependent on numpy, and while we're able to build numpy, using numpy as a build dependency is complicated because of how numpy is packaged.

The option for installing the library is "work out how to compile it for iOS". As I indicated previously, this folder includes the build setup for iOS packages, and there's a configuration there for scikit-image; however, that build configuration doesn't work on iOS at present. Fix that, and you'll have iOS wheels.

johnfhima commented 1 year ago

I got it. I am currently trying to have a look at the chaquopy/server/pypi repo. Do you have any more insight about why the scikit-image build configuration provided by the repos does not work for iOS in order to have the direction on where to look ?

Jonathan Fhima Le 8 févr. 2023 à 1:44 AM +0200, Russell Keith-Magee @.***>, a écrit :

scikit-image hasn't been pre-compiled for iOS because of some complications - it's dependent on numpy, and while we're able to build numpy, using numpy as a build dependency is complicated because of how numpy is packaged. The option for installing the library is "work out how to compile it for iOS". As I indicated previously, this folder includes the build setup for iOS packages, and there's a configuration there for scikit-image; however, that build configuration doesn't work on iOS at present. Fix that, and you'll have iOS wheels. — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>

freakboy3742 commented 1 year ago

The problem is the process of building the wheel itself. Python/pip doesn't have a strong concept of "Cross platform" builds; it's assumed that the Python you're using to run "pip" is the platform where you're using the code. That's a problem for iOS, because you're not running pip on iOS; and when it comes to building a package, you're building on macOS, but want a wheel for iOS.

In the case of scikit-image, it requires numpy to be in the build environment; and while we can build numpy itself, we haven't yet been able to "trick" the build process that the version we want installed is the iOS version, rather than the macOS version that it will find by default.

It might be possible to make use of tools like crossenv to work around this; As I understand it, that's a more comprehensive approach to cross-platform environments, but I haven't actually tried with iOS (or Android, for that matter) to see if it will address the issues we're seeing.

There's also the issue of PEP517-compliant builds; at present, the build tools in that repository are pinned at a version of pip that didn't require or use PEP517 build isolation. That's something that is preventing us from publishing a more recent version of numpy, because newer versions of numpy use Meson to build binary components (rather than setuptools).

mhsmith commented 1 year ago

For scikit-image, the larger obstacle is that it requires SciPy, which requires a Fortran compiler, and last time we checked there was no fully working Fortran compiler for iOS.

freakboy3742 commented 1 year ago

Where is the SciPy dependency specified? The meta.yaml only declares a dependency on Cython and Numpy

mhsmith commented 1 year ago

Unlike a real conda recipe, our meta.yaml files only include the requirements to build a package, not to run it. Here are scikit-image's runtime requirements.

johnfhima commented 1 year ago

In case we assume that I am not interested in the entire scikit image library but in one specific function (the _fast_skeletonize one from this address https://github.com/scikit-image/scikit-image/blob/00177e14097237ef20ed3141ed454bc81b308f82/skimage/morphology/_skeletonize_cy.pyx) which rely only on numpy and cnumpy. Is there a way to include it in my project?

Otherwise thanks a lot for you help I succeed to run a pure python version of this function (but the time required by each run is definitely way more longer than the original version)

johnfhima commented 1 year ago

Also when I tried to upload the Hellowold briefcase on TestFlight I have the following error. Do you know how I could solved it ?

Capture d’écran 2023-02-08 à 20 30 06
freakboy3742 commented 1 year ago

Ah - that's... annoying. It appears the structure generated by Briefcase is being rejected by the App Store.

My immediate guess is that the code that is currently being included in the python-stdlib and app_packages folders will need to be moved to the Frameworks folder; possibly inside a directory structure that gives the appearance of an iOS Framework.

mhsmith commented 1 year ago

In case we assume that I am not interested in the entire scikit image library but in one specific function (the _fast_skeletonize one from this address https://github.com/scikit-image/scikit-image/blob/00177e14097237ef20ed3141ed454bc81b308f82/skimage/morphology/_skeletonize_cy.pyx) which rely only on numpy and cnumpy. Is there a way to include it in my project?

You could build your own package which contains only that one Cython module. Use the build tool that @freakboy3742 linked above, and base your recipe on this example.

I agree that it looks like the module only depends on NumPy, but it also has a cimport statement, which means it'll require NumPy at build time. We already have one iOS package with a build-time NumPy requirement (pandas), so it's possible all you'd need to do is add a NumPy host requirement in your package's meta.yaml file, but I'm not certain.

UnrealCherry commented 1 year ago

I met it too. How do I fix it

mhsmith commented 1 year ago

@UnrealCherry: If you mean your app has been rejected by the App Store, see #176. Otherwise, please create a new issue.