Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port upstream Shapely 2.0.1 #1

Merged
merged 3 commits into from
Aug 17, 2023
Merged

Conversation

andreittr
Copy link
Contributor

This change set ports the Shapely Python extension to unikraft at upstream version 2.0.1, along with necessary compatibility patches.

This work depends on Python 3.10 and NumPy:

and all their dependencies; plus a patch to register shapely modules:

In addition it requires libGEOS:

Libs used for build:

LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-libcxx
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-libcxxabi
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-libunwind
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-intel-intrinsics
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-compiler-rt
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-musl
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-libffi
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-lwip
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-bzip2
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-sqlite
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-openssl
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-libuuid
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-zlib
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-geos
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-python3
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-python-numpy
LIBS-y := $(LIBS-y):$(UK_LIBS)/lib-python-shapely

@razvand razvand self-assigned this Aug 5, 2023
@razvand razvand added the enhancement New feature or request label Aug 7, 2023
Copy link
Member

@StefanJum StefanJum left a comment

Choose a reason for hiding this comment

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

Looks good @andreittr, few comments.

README.md Outdated
Comment on lines 1 to 9
Shapely Python extension for Unikraft
=====================================

This is a port of the [Shapely](https://pypi.org/project/shapely/) Python
extension to Unikraft.

Please refer to the `README.md` as well as the documentation in the
`doc/` subdirectory of the main unikraft repository for further
information.
Copy link
Member

Choose a reason for hiding this comment

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

Change this to md format instead of rst.
Use one line per sentence and one sentence per line.

Config.uk Outdated
Comment on lines 1 to 6
config LIBPYTHON_SHAPELY
bool "Shapely - Python package for planar geometric objects"
default n
select LIBPYTHON_NUMPY
select LIBGEOS
Copy link
Member

Choose a reason for hiding this comment

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

I would add select X for all the necessary dependencies, it would be difficult to keep track of them otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe the one direct dependency that's missing is python3, as shapely directly makes use of python API headers; I'll add it to the list.
As for other, indirect dependencies, I strongly believe it's better to delegate to the depended-on libraries instead of aggregating duplicate information here.

touch $@

# Add shapely rootfs to main python
python-rootfs: $(PYTHON_ROOTFS)/.shapely_done
Copy link
Member

Choose a reason for hiding this comment

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

Who will configure PYTHON_ROOTFS? Will it be done by lib-python3?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, PYTHON_ROOTFS is set when the python-rootfs make target is being run and taken from whatever you specify on the cmdline under path=, with the logic being provided by lib-python3.
If lib-python3 is not present/selected this line becomes a no-op, as no recipe for python-rootfs exists, nor is it an implicit target of anything.

Copy link
Member

Choose a reason for hiding this comment

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

Got it, nice.

Signed-off-by: Andrei Tatar <andrei@unikraft.io>
Files under `generated/` are created by the upstream build process from
templates; we include these files verbatim for the unikraft build.
Any potential patches should be clearly marked to ease future updates.
Files under `importfix/` are correctly namespaced wrapper modules for
any binary modules that we compile and link into unikraft, and must be
copied over to the python rootfs.
Selecting this library will add its files to the python rootfs build.

Signed-off-by: Andrei Tatar <andrei@unikraft.io>
Copy link

@RaduNichita RaduNichita left a comment

Choose a reason for hiding this comment

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

Looks very good, @andreittr, thank you for that. I left two minor questions regarding python, they should be easy to deal with.

@@ -0,0 +1,9 @@
#!/usr/bin/env python

Choose a reason for hiding this comment

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

Here we should have python or python3?

Copy link
Contributor Author

@andreittr andreittr Aug 10, 2023

Choose a reason for hiding this comment

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

Depends; most distros today have python symlinked to python3 (as IMO one should, py2 is very deprecated), with scarce few outliers remaining.
On unikraft however it is irrelevant since the hashbang line is never taken into account (we don't have #! support, nor even exec()), and even if it were we have python -> python3 in the standard rootfs.

Choose a reason for hiding this comment

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

Gotcha, thanks for clarification!

@@ -0,0 +1,9 @@
#!/usr/bin/env python

from shapely__geometry_helpers import *

Choose a reason for hiding this comment

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

It is the * import actually useful, since we import from the same module a line below?

Copy link
Contributor Author

@andreittr andreittr Aug 10, 2023

Choose a reason for hiding this comment

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

Very much so, the * imports everything present in the module's __all__ attribute, while the following line explicitly imports things that aren't in __all__.
This is necessary so that the fully-namespaced pure python module (shapely._geometry_helpers) behaves exactly the same as the built-in compiled module it masquerades as, so no calling code can tell the difference.

Choose a reason for hiding this comment

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

Gotcha, thanks for clarification!

Copy link
Member

@StefanJum StefanJum left a comment

Choose a reason for hiding this comment

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

All good @andreittr, I'll add the tag after all numpy and libgeos dependencies are merged.

@RaduNichita RaduNichita self-requested a review August 10, 2023 22:02
Copy link

@RaduNichita RaduNichita left a comment

Choose a reason for hiding this comment

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

All good with me. Many thanks again @andreittr for the consistent effort!!

Reviewed-by: Radu Nichita radunichita99@gmail.com

Copy link
Member

@StefanJum StefanJum left a comment

Choose a reason for hiding this comment

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

@andreittr there seems to be a problem with the installation of the shapely module.
In the end it is not copied in the PYTHON_ROOTFS dir. It looks like the pip install . --prefix=$(PYTHON_ROOTFS) --no-compile command fails with

      x86_64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/usr/include/python3.11 -I/tmp/pip-build-env-dslda_80/overlay/local/lib/python3.11/dist-packages/numpy/core/include -c src/c_api.c -o build/temp.linux-x86_64-cpython-311/src/c_api.o
      In file included from src/c_api.h:22,
                       from src/c_api.c:15:
      src/geos.h:15:10: fatal error: geos_c.h: No such file or directory
         15 | #include <geos_c.h>

I've been looking into it with @mariasfiraiala and that is likely the cause.

@andreittr
Copy link
Contributor Author

andreittr commented Aug 11, 2023

@andreittr there seems to be a problem with the installation of the shapely module. In the end it is not copied in the PYTHON_ROOTFS dir. It looks like the pip install . --prefix=$(PYTHON_ROOTFS) --no-compile command fails with

      x86_64-linux-gnu-gcc -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/usr/include/python3.11 -I/tmp/pip-build-env-dslda_80/overlay/local/lib/python3.11/dist-packages/numpy/core/include -c src/c_api.c -o build/temp.linux-x86_64-cpython-311/src/c_api.o
      In file included from src/c_api.h:22,
                       from src/c_api.c:15:
      src/geos.h:15:10: fatal error: geos_c.h: No such file or directory
         15 | #include <geos_c.h>

I've been looking into it with @mariasfiraiala and that is likely the cause.

Aw crap, I see what's going wrong: pip is looking for shapely's build deps on the host system (which I incidentally had left over from the porting job so I didn't bump into it). Nice catch.
Lemme see if there's a way to force pip to not attempt to build the native bits (or patch it out of setup.py (oor have pip use unikraft's CINCLUDES)).

This patch to setup.py prevents pip from trying to compile the C/C++
shapely sources when building the Unikraft Python rootfs, since we never
make use of these compiled files.
This prevents build failures when the host system lacks dev files for
shapely dependencies.

Signed-off-by: Andrei Tatar <andrei@unikraft.io>
@andreittr
Copy link
Contributor Author

Should be fixed now; I've patched setup.py to not build these files. As a bonus now rootfs building is much faster for shapely 😄 ; semi-offtopic: would've been nice to have smth like this for numpy but it's not as trivial, some other time.

@RaduNichita
Copy link

I was able to get shapely working by creating a custom rootfs, @andreittr!

Should the shapely module be also put in the rootfs for the python3 app?

@RaduNichita RaduNichita self-requested a review August 11, 2023 23:10
@StefanJum
Copy link
Member

StefanJum commented Aug 13, 2023

@andreittr I tried this with the last patch, and it still does not seem to add the shapely module to the root filesystem.
Just to confirm, the build command should be make path=fs0/, where fs0 is the directory we extract the rootfs.tar.gz archive from the python3 app repository, right?

LE: nvm, I missed the make python-rootfs rule.

Few issues:

  1. We need the python-rootfs build rule to be very well documented. We should update the app-python3 README file to add it.

  2. Depending on the python version on the host system, the root filesystem might get messed up. You would need to do a make python-rootfs path=rootfs and then extract the tar archive from the app repository over the rootfs in order for everything to work fine. Maybe we can enforce the python 3.10 version to be used?

This is anyway dev stuff, from a user point of view, as @RaduNichita said, I think we should have everything in the rootfs.tar.gz archive, including the shapely module files.

@andreittr
Copy link
Contributor Author

I was able to get shapely working by creating a custom rootfs, @andreittr!

Nice! I assume you used the standard rootfs recipe after building a unikraft image with shapely (if not, do try that out, it's by far the easiest).

Should the shapely module be also put in the rootfs for the python3 app?

I doubt that's the right place to put it, since app-python3 is so clearly meant as a minimal "Python Hello World" and not a full installation of python + everything we ever support (+ the latter will get quite bloated once we start supporting more 3rd party extensions).

@andreittr I tried this with the last patch, and it still does not seem to add the shapely module to the root filesystem. Just to confirm, the build command should be make path=fs0/, where fs0 is the directory we extract the rootfs.tar.gz archive from the python3 app repository, right?

LE: nvm, I missed the make python-rootfs rule.

As you mention, there's the python-rootfs rule which builds a rootfs with exactly the libs you configured for the unikraft image (i.e. std lib + any other extensions selected). You do not need to extract rootfs.tar.gz anywhere in order to build a new rootfs --- the tarball is there only if you don't want to go through the trouble of making your own rootfs and are fine with using a minimal one.

Few issues:

1. We need the `python-rootfs` build rule to be **very** well documented. We should update the `app-python3` README file to add it.

It is fairly well documented in lib-python3 and IMO that is where the authoritative documentation should stay, as lib-python3 is what implements rootfs building, and is what users will use to make their own custom python images + rootfs'es for their workloads (with an intrepid user conceivably never even seeing the app-python3 repo).
We can add a pointer to these docs in app-python3's README but I really wouldn't duplicate detailed documentation around, that's just asking for it to become out of date.

2. Depending on the python version on the host system, the root filesystem might get messed up. You would need to do a `make python-rootfs path=rootfs` and then extract the tar archive from the app repository over the rootfs in order for everything to work fine. Maybe we can enforce the python 3.10 version to be used?

Indeed, and that's precisely why you get a warning if you try to build a rootfs with a python version that does not match Unikraft python; it also completely errors out if you try to build pyc files with the wrong python version too.
As said previously, you do not extract anything when building your own rootfs, everything gets built from scratch in a new empty dir with your host python (which should be same major+minor version as Unikraft python, thus is checked) and is populated with all selected python extensions.

This is anyway dev stuff, from a user point of view, as @RaduNichita said, I think we should have everything in the rootfs.tar.gz archive, including the shapely module files.

I think that is a bad call considering the purpose of app-python3 as a python Hello World rather than a "everything-plus-kitchen-sink" complete distribution. Since previously we hadn't really supported anything beyond a stripped-down python stdlib there hadn't been much difference between a minimal and "full" rootfs, but now there very much is. And with other extension modules being ported, especially large frameworks, I believe maintaining a complete rootfs containing absolutely everything is very impractical.
Similar to how app-helloworld-cpp does not include all possible C++ libs, so I think that app-python3 should stay a minimal, stdlib-only, hello world.

I am ok with creating "demo apps" (e.g., app-python3-numpy) for py extensions like numpy and shapely and whatnot; something akin to a playground where users can test out their scripts/snippets before customizing unikraft and building their own rootfs. This is also much more scalable and customizable to each particular use case compared to a "everything-included" hello world.

@StefanJum
Copy link
Member

I am ok with creating "demo apps" (e.g., app-python3-numpy) for py extensions like numpy and shapely and whatnot; something akin to a playground where users can test out their scripts/snippets before customizing unikraft and building their own rootfs. This is also much more scalable and customizable to each particular use case compared to a "everything-included" hello world.

Ok, fair. I think "demo apps" are a good idea. The main point is to have users able to use the stuff that we provide without too much work on their side, and I think having apps for python extensions will achieve that nicely. Not adding the extensions in the python app or having a separate shapely app I think will end up in just people having no idea that we support it.

We can add a pointer to these docs in app-python3's README

If we go for separate applications that's not needed, we can have the python3 application as it is.

And one more question, why is the numpy module added in the rootfs archive of the python3 application if we go for a minimal "helloworld" build? Is it needed by anything or can we just remove it?

@andreittr
Copy link
Contributor Author

And one more question, why is the numpy module added in the rootfs archive of the python3 application if we go for a minimal "helloworld" build? Is it needed by anything or can we just remove it?

Oh crap, I did not realize that was the case, it most definitely should not be there; this is a bug, thanks for catching it. Looking into fixing it right now.

@RaduNichita
Copy link

Indeed, and that's precisely why you get a warning if you try to build a rootfs with a python version that does not match Unikraft python; it also completely errors out if you try to build pyc files with the wrong python version too.
As said previously, you do not extract anything when building your own rootfs, everything gets built from scratch in a new empty dir with your host python (which should be same major+minor version as Unikraft python, thus is checked) and is populated with all selected python extensions.

Do you need something special for that? I tried running make python-rootfs with python3.11 as default python version on my OS and I ended up having two folders in my rootfs/lib, one for python3.10 and one for python3.11, the python3.11 containing only the site-package folder.

So, to make it work this PR, I had to move the site-packages from the rootfs.tar.gz archive.

@mariasfiraiala mariasfiraiala self-requested a review August 14, 2023 13:16
@StefanJum
Copy link
Member

Oh crap, I did not realize that was the case, it most definitely should not be there; this is a bug, thanks for catching it. Looking into fixing it right now.

Got it, then this is fine, we can merge it. Ee'll wait for the pr on app-python3 to remove numpy and for demo applications for numpy and shapely.

Copy link
Member

@StefanJum StefanJum left a comment

Choose a reason for hiding this comment

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

Reviewed-by: Stefan Jumarea stefanjumarea02@gmail.com

Copy link

@mariasfiraiala mariasfiraiala left a comment

Choose a reason for hiding this comment

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

Since this is finally working and doesn't need any more amends, shall we merge it?

Reviewed-by: Maria Sfiraiala maria.sfiraiala@gmail.com

Copy link

@RaduNichita RaduNichita left a comment

Choose a reason for hiding this comment

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

Ok, so let's merge as it is and focus on the demo appa

Reviewed-by: Radu Nichita radunichita99@gmail.com

@andreittr
Copy link
Contributor Author

Do you need something special for that? I tried running make python-rootfs with python3.11 as default python version on my OS and I ended up having two folders in my rootfs/lib, one for python3.10 and one for python3.11, the python3.11 containing only the site-package folder.

So, to make it work this PR, I had to move the site-packages from the rootfs.tar.gz archive.

Did you receive the warning that your host Python is a different version? If so, then it's normal to get both dirs under site-packages/, you can use a virtualenv with the right python version to prevent this.

@andreittr
Copy link
Contributor Author

@StefanJum @mariasfiraiala @RaduNichita Wait, let's not merge yet; the issue with numpy wrongly being in the rootfs has to do with these lib PRs.

@RaduNichita
Copy link

Do you need something special for that? I tried running make python-rootfs with python3.11 as default python version on my OS and I ended up having two folders in my rootfs/lib, one for python3.10 and one for python3.11, the python3.11 containing only the site-package folder.
So, to make it work this PR, I had to move the site-packages from the rootfs.tar.gz archive.

Did you receive the warning that your host Python is a different version? If so, then it's normal to get both dirs under site-packages/, you can use a virtualenv with the right python version to prevent this.

Yes, I agree, but let's document this as well.

@StefanJum
Copy link
Member

@StefanJum @mariasfiraiala @RaduNichita Wait, let's not merge yet; the issue with numpy wrongly being in the rootfs has to do with these lib PRs.

How so? The numpy is just there in the tar archive, doesn't it just need to be removed?

@andreittr
Copy link
Contributor Author

@StefanJum @mariasfiraiala @RaduNichita Wait, let's not merge yet; the issue with numpy wrongly being in the rootfs has to do with these lib PRs.

How so? The numpy is just there in the tar archive, doesn't it just need to be removed?

But the fact that it's there in the tar archive to begin with suggests there might be a bug in numpy's Makefile.uk (since I didn't select numpy in Kconfig when generating the rootfs) and I want to test to double-check, and I might've made the same mistake in shapely too.

@StefanJum
Copy link
Member

But the fact that it's there in the tar archive to begin with suggests there might be a bug in numpy's Makefile.uk (since I didn't select numpy in Kconfig when generating the rootfs) and I want to test to double-check, and I might've made the same mistake in shapely too.

I see, we'll wait then.

@andreittr
Copy link
Contributor Author

Ok, double-checked, rebuilt rootfs and it seems ok; I think I just messed up before. Rootfs fix in this PR:

Other than that, all clear for merge.

Copy link
Contributor

@razvand razvand left a comment

Choose a reason for hiding this comment

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

Approved-by: Razvan Deaconescu razvand@unikraft.io

@razvand razvand merged commit 2860337 into unikraft:staging Aug 17, 2023
razvand pushed a commit that referenced this pull request Aug 17, 2023
Signed-off-by: Andrei Tatar <andrei@unikraft.io>
Reviewed-by: Stefan Jumarea <stefanjumarea02@gmail.com>
Reviewed-by: Maria Sfiraiala <maria.sfiraiala@gmail.com>
Reviewed-by: Radu Nichita <radunichita99@gmail.com>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
GitHub-Closes: #1
razvand pushed a commit that referenced this pull request Aug 17, 2023
Files under `generated/` are created by the upstream build process from
templates; we include these files verbatim for the unikraft build.
Any potential patches should be clearly marked to ease future updates.
Files under `importfix/` are correctly namespaced wrapper modules for
any binary modules that we compile and link into unikraft, and must be
copied over to the python rootfs.
Selecting this library will add its files to the python rootfs build.

Signed-off-by: Andrei Tatar <andrei@unikraft.io>
Reviewed-by: Stefan Jumarea <stefanjumarea02@gmail.com>
Reviewed-by: Maria Sfiraiala <maria.sfiraiala@gmail.com>
Reviewed-by: Radu Nichita <radunichita99@gmail.com>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
GitHub-Closes: #1
razvand pushed a commit that referenced this pull request Aug 17, 2023
This patch to setup.py prevents pip from trying to compile the C/C++
shapely sources when building the Unikraft Python rootfs, since we never
make use of these compiled files.
This prevents build failures when the host system lacks dev files for
shapely dependencies.

Signed-off-by: Andrei Tatar <andrei@unikraft.io>
Reviewed-by: Stefan Jumarea <stefanjumarea02@gmail.com>
Reviewed-by: Maria Sfiraiala <maria.sfiraiala@gmail.com>
Reviewed-by: Radu Nichita <radunichita99@gmail.com>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
GitHub-Closes: #1
@andreittr andreittr deleted the ttr/up-2.0.1 branch August 17, 2023 12:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Done!
Development

Successfully merging this pull request may close these issues.

None yet

5 participants