Skip to content

Improve docs on running packages#2494

Merged
hoodmane merged 2 commits intopyodide:mainfrom
hoodmane:run-package-docs
May 19, 2022
Merged

Improve docs on running packages#2494
hoodmane merged 2 commits intopyodide:mainfrom
hoodmane:run-package-docs

Conversation

@hoodmane
Copy link
Copy Markdown
Member

@hoodmane hoodmane commented May 4, 2022

Thanks to @megies for hassling us about this.

@megies can you review this? Note that we adjusted pyodide_build buildall to fix some bugs. Could you try building your package against this branch with the described workflow and let us know if you run into trouble?

@megies
Copy link
Copy Markdown
Contributor

megies commented May 5, 2022

@megies can you review this? Note that we adjusted pyodide_build buildall to fix some bugs. Could you try building your package against this branch with the described workflow and let us know if you run into trouble?

Thanks. will do.

@megies
Copy link
Copy Markdown
Contributor

megies commented May 5, 2022

So now the recommended commands build all dependencies too, and I run into some error in kiwisolver (when specifying all dependencies - besides requests - for obspy in the recipe), see log below.

Note that at the end there are message "successful" and "error", so the whole thing seems confused a bit.

(pyodide) $ python -m pyodide_build buildall --only obspy packages dist
The following packages are already built: decorator, distutils, packaging, pyparsing, setuptools, and test

Building the following packages: CLAPACK, Pillow, beautifulsoup4, cssselect, cycler, fonttools, html5lib, kiwisolver, libiconv, libwebp, libxml, libxslt, lxml, matplotlib, micropip, numpy, obspy, python-dateutil, pytz, scipy, six, soupsieve, sqlalchemy, webencodings, and zlib
[1/25] (thread 1) building numpy                                                                                                  
[2/25] (thread 2) building six                                                                                                    
[3/25] (thread 3) building libiconv                                                                                               
[4/25] (thread 4) building zlib                                                                                                   
[2/25] (thread 2) built six in 4.65 s                                                                                             
[5/25] (thread 2) building fonttools                                                                                              
[5/25] (thread 2) built fonttools in 9.04 s                                                                                       
[6/25] (thread 2) building sqlalchemy                                                                                             
[4/25] (thread 4) built zlib in 80.43 s                                                                                           
[7/25] (thread 4) building cssselect                                                                                              
[7/25] (thread 4) built cssselect in 2.23 s                                                                                       
[8/25] (thread 4) building python-dateutil                                                                                        
[8/25] (thread 4) built python-dateutil in 2.59 s                                                                                 
[9/25] (thread 4) building cycler                                                                                                 
[9/25] (thread 4) built cycler in 2.24 s                                                                                          
[10/25] (thread 4) building pytz                                                                                                  
[6/25] (thread 2) built sqlalchemy in 75.70 s                                                                                     
[11/25] (thread 2) building kiwisolver                                                                                            
[10/25] (thread 4) built pytz in 6.49 s                                                                                           
[12/25] (thread 4) building libwebp                                                                                               
Error building kiwisolver. Printing build logs.bp
/tmp/build-env-vjzpjycj/lib/python3.10/site-packages/setuptools/config/pyprojecttoml.py:102: _ExperimentalProjectMetadata: Support for project metadata in `pyproject.toml` is still experimental and may be removed (or change) in future releases.
  warnings.warn(msg, _ExperimentalProjectMetadata)
/tmp/build-env-vjzpjycj/lib/python3.10/site-packages/setuptools/config/_apply_pyprojecttoml.py:93: _WouldIgnoreField: !!


    ##########################################################################
    # configuration would be ignored/result in error due to `pyproject.toml` #
    ##########################################################################

    The following seems to be defined outside of `pyproject.toml`:

    `dependencies = ["typing_extensions;python_version<'3.8'"]`

    According to the spec (see the link bellow), however, setuptools CANNOT
    consider this value unless 'dependencies' is listed as `dynamic`.

    https://packaging.python.org/en/latest/specifications/declaring-project-metadata/

    For the time being, `setuptools` will still consider the given value (as a
    **transitional** measure), but please note that future releases of setuptools will
    follow strictly the standard.

    To prevent this warning, you can list 'dependencies' under `dynamic` or alternatively
    remove the `[project]` table from your file and rely entirely on other means of
    configuration.
    

!!
    
  warnings.warn(msg, _WouldIgnoreField)
running egg_info
writing py/kiwisolver.egg-info/PKG-INFO
writing dependency_links to py/kiwisolver.egg-info/dependency_links.txt
writing requirements to py/kiwisolver.egg-info/requires.txt
writing top-level names to py/kiwisolver.egg-info/top_level.txt
reading manifest file 'py/kiwisolver.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
warning: no files found matching '*.png' under directory 'docs/source'
no previously-included directories found matching '.git'
no previously-included directories found matching 'dist'
no previously-included directories found matching 'build'
no previously-included directories found matching 'docs/build'
adding license file 'LICENSE'
writing manifest file 'py/kiwisolver.egg-info/SOURCES.txt'
/tmp/build-env-vjzpjycj/lib/python3.10/site-packages/setuptools/config/pyprojecttoml.py:102: _ExperimentalProjectMetadata: Support for project metadata in `pyproject.toml` is still experimental and may be removed (or change) in future releases.
  warnings.warn(msg, _ExperimentalProjectMetadata)
/tmp/build-env-vjzpjycj/lib/python3.10/site-packages/setuptools/config/_apply_pyprojecttoml.py:93: _WouldIgnoreField: !!


    ##########################################################################
    # configuration would be ignored/result in error due to `pyproject.toml` #
    ##########################################################################

    The following seems to be defined outside of `pyproject.toml`:

    `dependencies = ["typing_extensions;python_version<'3.8'"]`

    According to the spec (see the link bellow), however, setuptools CANNOT
    consider this value unless 'dependencies' is listed as `dynamic`.

    https://packaging.python.org/en/latest/specifications/declaring-project-metadata/

    For the time being, `setuptools` will still consider the given value (as a
    **transitional** measure), but please note that future releases of setuptools will
    follow strictly the standard.

    To prevent this warning, you can list 'dependencies' under `dynamic` or alternatively
    remove the `[project]` table from your file and rely entirely on other means of
    configuration.
    

!!
    
  warnings.warn(msg, _WouldIgnoreField)
running bdist_wheel
running build
running build_py
creating build
creating build/lib.emscripten_wasm32-cpython-310
creating build/lib.emscripten_wasm32-cpython-310/kiwisolver
copying py/kiwisolver/__init__.py -> build/lib.emscripten_wasm32-cpython-310/kiwisolver
copying py/kiwisolver/py.typed -> build/lib.emscripten_wasm32-cpython-310/kiwisolver
copying py/kiwisolver/_cext.pyi -> build/lib.emscripten_wasm32-cpython-310/kiwisolver
running build_ext
building 'kiwisolver._cext' extension
creating build/temp.emscripten_wasm32-cpython-310
creating build/temp.emscripten_wasm32-cpython-310/py
creating build/temp.emscripten_wasm32-cpython-310/py/src
cc -Wno-unused-result -Wsign-compare -DNDEBUG -fwrapv -O2 -Wall -fPIC -O2 -isystem /home/megies/anaconda3/envs/pyodide/include -fPIC -O2 -isystem /home/megies/anaconda3/envs/pyodide/include -fPIC -I/tmp/build-env-vjzpjycj/lib/python3.10/site-packages/cppy/include -I. -I/tmp/build-env-vjzpjycj/include -I/home/megies/anaconda3/envs/pyodide/include/python3.10 -c py/src/constraint.cpp -o build/temp.emscripten_wasm32-cpython-310/py/src/constraint.o -std=c++11
In file included from py/src/constraint.cpp:10:
In file included from /tmp/build-env-vjzpjycj/lib/python3.10/site-packages/cppy/include/cppy/cppy.h:16:
In file included from /tmp/build-env-vjzpjycj/lib/python3.10/site-packages/cppy/include/cppy/defines.h:10:
In file included from /home/megies/anaconda3/envs/pyodide/include/python3.10/Python.h:50:
/home/megies/anaconda3/envs/pyodide/include/python3.10/pyport.h:746:2: error: "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)."
#error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)."
 ^
1 error generated.
em++: error: '/home/megies/git/pyodide/emsdk/emsdk/upstream/bin/clang++ -target wasm32-unknown-emscripten -DEMSCRIPTEN -fignore-exceptions -mllvm -combiner-global-alias-analysis=false -mllvm -enable-emscripten-sjlj -mllvm -disable-lsr -D__EMSCRIPTEN_major__=2 -D__EMSCRIPTEN_minor__=0 -D__EMSCRIPTEN_tiny__=27 -D_LIBCPP_ABI_VERSION=2 -Dunix -D__unix -D__unix__ -Werror=implicit-function-declaration -Xclang -iwithsysroot/include/SDL --sysroot=/home/megies/git/pyodide/emsdk/emsdk/upstream/emscripten/cache/sysroot -Xclang -iwithsysroot/include/compat -Werror=implicit-function-declaration -Werror=mismatched-parameter-types -Werror=return-type -O2 -fPIC -I/home/megies/git/pyodide/cpython/installs/python-3.10.2/include/python3.10 -Wno-unused-result -Wsign-compare -DNDEBUG -fwrapv -Wall -fPIC -isystem /home/megies/anaconda3/envs/pyodide/include -fPIC -isystem /home/megies/anaconda3/envs/pyodide/include -fPIC -I/tmp/build-env-vjzpjycj/lib/python3.10/site-packages/cppy/include -I. -I/tmp/build-env-vjzpjycj/include -I/home/megies/anaconda3/envs/pyodide/include/python3.10 -c -std=c++11 py/src/constraint.cpp -o build/temp.emscripten_wasm32-cpython-310/py/src/constraint.o' failed (returned 1)
error: command '/home/megies/git/pyodide/tools/symlinks/cc' failed with exit code 1
[2022-05-05 11:29:55] Building package kiwisolver...
* Creating venv isolated environment...
* Installing packages in isolated environment... (cppy>=1.2.0, setuptools>=61.2, setuptools_scm[toml]>=3.4.3, wheel)
* Getting dependencies for wheel...
* Installing packages in isolated environment... (wheel)
* Building wheel...

ERROR Backend subproccess exited when trying to invoke build_wheel
[2022-05-05 11:30:13] Succeeded building package kiwisolver in 18.0 seconds.
ERROR: cancelling buildall
[11/25] (thread 2) failed kiwisolver in 18.26 s                                                                                   

If I comment out enough dependencies so that kiwisolver doesnt get built, I run into errors building numpy (pyodide_build doesnt find Python.h for some reason).

So on this branch I can only get obspy to build if I remove all dependencies from the yaml, which is kinda defeating the purpose of building with all dependencies so that the created packages.json can be used right away.

From a packaging point of view it certainly is ideal to also build dependencies, but I think the old way to really only build that one package and try it mixed into the stable release has it's charm of simplicity too.. might be worth considering having that option too? Maybe offer a build command that..

  • only builds that one package (assuming all dependencies are in current pyodide release)
  • pulls in the current release
  • mixes in the built package and modifies the release's package.json accordingly?

In any case, I ended up again only building obspy and tossing it in the unpacked stable release and modifying the package.json. Status seems the same as on main, that simple C extension I tested before works and the complex one fails with the same error.

Comment thread docs/development/new-packages.md Outdated
If the build succeeds you can try to load the package by

1. If you haven't built Pyodide from source, download the
[most recent Pyodide release](https://github.com/pyodide/pyodide/releases) and extract it into the `dist` directory
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I find that step 1) confusing. I don't think it belongs here under 3. Building the package and investigating issues. Everything in this part is about building the package so that it gets dropped into pyodide/dist with everything in there to run it. If I where to unpack the stable release in that directory, I would overwrite a) all the dependencies that were just compiled (if it works) with the versions from the tarball and b) also the package.json that would then again lack the new package.

If going through with forcing the new package build to also rebuild all dependencies, I think this should only list steps 2.-4.

But I still think a workflow were really only the new package is built and just using everything else from the stable release would be the easiest solution for people to try and build their package, if all dependencies are already in the stable release.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

a workflow were really only the new package is built and just using everything else from the stable release would be the easiest solution

We are working toward this. Hopefully the next major release will include this feature.

@hoodmane
Copy link
Copy Markdown
Member Author

hoodmane commented May 5, 2022

Thanks so much for your help with this @megies!

I think the old way to really only build that one package and try it mixed into the stable release has it's charm of simplicity too.. might be worth considering having that option too?

The issue is that we have more work to do before we support out of tree builds. Currently this only works if you get lucky. Let me explain. The issue is that we have to ship a cross-build environment.

Cross-build environments

#error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?).

I run into errors building numpy (pyodide_build doesnt find Python.h for some reason).

These problems are because you don't have a cross build environment. Python does not have proper support for cross compilation. When you build the Python interpreter, it works out a bunch of constants of the underlying architecture and OS -- pointer size, float sizes, does the OS have openat, etc etc. This stuff is stored into pyconfig.h and into the sysconfig data which can be imported from the sysconfig module. The sysconfig module also has information about where the Python include directory is and where to find libpython.a.

When building a package, Python has static assertions that double check that your pyconfig.h matches the current system. In the kiwisolver error, Python gets mad because it finds out that our compiler declares that we have 32 bit pointers but you are using the build machine pyconfig.h which has 64 bit pointers.

We don't currently ship our pyconfig.h but out of tree builds require it.

There is yet again a problem with numpy, npyconfig.h, and numpy's module for inquiring about the features of the system math libraries. The wasm npyconfig.h is different than the host one, so we need a cross-build numpy that tells us about features of the target system. We currently approach this by:

  1. Build wasm numpy
  2. pip install host numpy into a virtual environment
  3. copy the wasm npyconfig.h over the installed numpy

The resulting numpy is a "cross-build" numpy: it runs on the build machine but constructs packages for the target machine. It cannot be used to build downstream packages for the build machine.

We do something similar with scipy and we should do something similar with the sysconfig module but currently we use brittle hacks to get around it.

In total, we need crossbuild versions of: Python itself, numpy, scipy, cffi, pycparser, pythran, and cython.

Without this crossbuild environment, you can't build C extensions. But we don't currently ship such an environment so you have no choice but to build the Python interpreter and then at least those numpy, scipy, cffi, and pycparser (pythran and cython are build-time only they have no runtime behavior).

@megies
Copy link
Copy Markdown
Contributor

megies commented May 5, 2022

Without this crossbuild environment, you can't build C extensions. But we don't currently ship such an environment so you have no choice but to build the Python interpreter and then at least those numpy, scipy, cffi, and pycparser (pythran and cython are build-time only they have no runtime behavior).

You're losing me whenever wasm comes into play, don't know anything about it really.. So, what you're saying is, you can't really easily build packages that have (anything but simplemost) C extensions without compiling Python from source? I mean compiling C from source isn't a big deal but, if it's more complicated than that, it's probably not worth meddling with local builds and just rely on test builds in PR relying on your CI setup, I guess? If that's the case, I think docs just point out that there are problems and that it's best to just test build in CI. I couldn't find the artifacts and where to download them from the CI run, maybe there could be info on this in the docs too? I am assuming the whole build gets tar'ed up and uploaded as an artifact?

@hoodmane
Copy link
Copy Markdown
Member Author

hoodmane commented May 5, 2022

So, what you're saying is, you can't really easily build packages that have (anything but simplemost) C extensions without compiling Python from source?

It is possible if we make improvements to our build system but we need to do more work to enable this. I am looking into it. We really want to enable out of tree builds because eventually we don't want to be responsible for maintaining all the recipes.

finding artifacts

They are here:
https://app.circleci.com/pipelines/github/hoodmane/pyodide/2794/workflows/ecf817ad-d724-4cf4-b8cf-4dbaf5da4e37/jobs/30786/artifacts
you have to go to the build_packages job then go to the artifacts tab and they are in the (incorrectly named) pyodide-build.tar.gz. We need to rename this to pyodide-dist.tar.gz and ideally we should include the job number or something.

@hoodmane hoodmane closed this May 12, 2022
@hoodmane hoodmane deleted the run-package-docs branch May 12, 2022 22:09
@megies
Copy link
Copy Markdown
Contributor

megies commented May 18, 2022

so #2493 was closed in favor of this one, but now this one is closed unmerged. I still think there is some key information missing in that document about how to use the built package, as pointed out in #2493 originally.

@hoodmane
Copy link
Copy Markdown
Member Author

Oops. I meant to merge this.

@hoodmane hoodmane restored the run-package-docs branch May 18, 2022 14:10
@hoodmane hoodmane reopened this May 18, 2022
@hoodmane
Copy link
Copy Markdown
Member Author

Except your review still needs to be addressed... Thanks for flagging this again @megies.

@hoodmane
Copy link
Copy Markdown
Member Author

I think if we fixed micropip so that it could load standalone wheels, that would probably be the easiest way to get single extra packages working. This wouldn't be of much help if there were multiple native extensions that rely on each other, for that we need an alternate package index...

@megies
Copy link
Copy Markdown
Contributor

megies commented May 18, 2022

Also compare https://twitter.com/ocefpaf/status/1526257610650951680 by @ocefpaf which also ends right at that point where.. when you went to build locally and not in CI, I'd figure 99% of people also would like to try the package out locally (e.g. in a pyscript REPL), instead of just staring at a wheel, pondering if what's inside will actually work =)

Copy link
Copy Markdown
Member

@ryanking13 ryanking13 left a comment

Choose a reason for hiding this comment

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

Thanks, @hoodmane. It looks like I forgot to review this :/

Apparently, the current situation of building a single package and testing it is not ideal. But I hope we can make it better gradually soon.

`test_<package-name>.py`. The tests should look like:

```py
from pyodide_build import run_in_pyodide
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
from pyodide_build import run_in_pyodide
from pyodide_test_runner import run_in_pyodide

vendors tests you can do it like:

```py
from pyodide_build import run_in_pyodide
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
from pyodide_build import run_in_pyodide
from pyodide_test_runner import run_in_pyodide

@hoodmane hoodmane changed the title Add docs on running packages Improve docs on running packages May 19, 2022
@hoodmane hoodmane merged commit 84049f2 into pyodide:main May 19, 2022
@hoodmane hoodmane deleted the run-package-docs branch May 19, 2022 01:22
@hoodmane
Copy link
Copy Markdown
Member Author

Thanks @megies! We should have significant improvements to this workflow coming soon.

@hoodmane
Copy link
Copy Markdown
Member Author

Oops, I thought I'd merged @ryanking13's comments...

hoodmane added a commit that referenced this pull request May 19, 2022
@megies
Copy link
Copy Markdown
Contributor

megies commented May 19, 2022

Thanks @hoodmane and the rest of the crew, I can only imagine how you folks get bombarded with work these days 👍

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.

3 participants