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

Consider supporting emscripten/webassembly as a build target #84461

Open
SimonBiggs mannequin opened this issue Apr 14, 2020 · 65 comments
Open

Consider supporting emscripten/webassembly as a build target #84461

SimonBiggs mannequin opened this issue Apr 14, 2020 · 65 comments
Labels
3.11 build type-feature

Comments

@SimonBiggs
Copy link
Mannequin

@SimonBiggs SimonBiggs mannequin commented Apr 14, 2020

BPO 40280
Nosy @warsaw, @brettcannon, @terryjreedy, @tiran, @mcepl, @pmp-p, @rdb, @ethanhs, @corona10, @miss-islington, @tirkarthi, @erlend-aasland
PRs
  • #29771
  • #29784
  • #29789
  • #29794
  • #29795
  • #29834
  • #29842
  • #29872
  • #29873
  • #29884
  • #29887
  • #29892
  • #29893
  • #29984
  • #30494
  • #30495
  • #30538
  • #30552
  • #30559
  • #30597
  • #30601
  • #30615
  • #30620
  • #30622
  • #30722
  • #30858
  • #30930
  • #31050
  • #31757
  • #31770
  • #31791
  • #31829
  • #31865
  • #31898
  • #31909
  • #31947
  • #31986
  • #32095
  • #32224
  • #32233
  • #32238
  • #32243
  • #32253
  • #32266
  • #32284
  • #32352
  • #32360
  • #32412
  • Dependencies
  • bpo-23325: Turn SIG_DFL and SIG_IGN into functions
  • bpo-33393: update config.guess and config.sub
  • bpo-41498: Undefinied _Py_Sigset_Converter function when HAVE_SIGSET_T not set
  • bpo-45881: Cross compiling on Linux is untested, undocumented, and broken
  • bpo-45886: Fix Program/freeze_module for cross compiling Python
  • bpo-45898: ctypes cfield.c defines duplicate ffi_type* symbols
  • bpo-46383: _zoneinfo module_free has invalid function signature
  • bpo-46390: Multiple test failures on Alpine 3.15 / musl-1.2.2-r7
  • bpo-46408: signal module wrongly relies on small int singletons
  • bpo-47162: Add call trampoline to work around bad fpcasts on Emscripten
  • bpo-47176: Interrupt handling for wasm32-emscripten builds without pthreads
  • bpo-47196: Function pointer cast in test_imp
  • bpo-47197: ctypes mishandles void return type
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2020-04-14.07:11:35.905>
    labels = ['type-feature', 'build', '3.11']
    title = 'Consider supporting emscripten/webassembly as a build target'
    updated_at = <Date 2022-04-08.10:17:32.793>
    user = 'https://bugs.python.org/SimonBiggs'

    bugs.python.org fields:

    activity = <Date 2022-04-08.10:17:32.793>
    actor = 'christian.heimes'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Build']
    creation = <Date 2020-04-14.07:11:35.905>
    creator = 'Simon Biggs'
    dependencies = ['23325', '33393', '41498', '45881', '45886', '45898', '46383', '46390', '46408', '47162', '47176', '47196', '47197']
    files = []
    hgrepos = []
    issue_num = 40280
    keywords = ['patch']
    message_count = 65.0
    messages = ['366369', '366374', '366375', '366379', '369598', '394081', '406985', '406986', '407011', '407012', '407013', '407014', '407015', '407018', '407020', '407021', '407030', '407046', '407048', '407049', '407052', '407080', '407264', '407284', '407484', '407498', '407519', '407524', '407541', '408855', '410138', '410400', '410423', '410554', '410577', '410647', '410727', '410743', '411039', '411514', '411560', '411847', '412595', '414748', '414769', '414780', '414845', '414940', '415136', '415259', '415297', '415398', '415757', '415976', '416494', '416509', '416541', '416542', '416579', '416681', '416763', '416865', '416916', '416933', '416934']
    nosy_count = 14.0
    nosy_names = ['barry', 'brett.cannon', 'terry.reedy', 'christian.heimes', 'mcepl', 'pmpp', 'rdb', 'ethan smith', 'corona10', 'miss-islington', 'Roman Yurchak', 'xtreak', 'erlendaasland', 'Simon Biggs']
    pr_nums = ['29771', '29784', '29789', '29794', '29795', '29834', '29842', '29872', '29873', '29884', '29887', '29892', '29893', '29984', '30494', '30495', '30538', '30552', '30559', '30597', '30601', '30615', '30620', '30622', '30722', '30858', '30930', '31050', '31757', '31770', '31791', '31829', '31865', '31898', '31909', '31947', '31986', '32095', '32224', '32233', '32238', '32243', '32253', '32266', '32284', '32352', '32360', '32412']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue40280'
    versions = ['Python 3.11']

    @SimonBiggs
    Copy link
    Mannequin Author

    @SimonBiggs SimonBiggs mannequin commented Apr 14, 2020

    Since asm.js came on the scene, and now Web Assembly people have created CPython patches to support building CPython with emscripten. See:

    To ease the compiling of CPython with emscripten it would be helpful if patches that achieved these ends for the compiling to Web Assembly with emscripten were built into the upstream source repository itself.

    If web assembly were to became a supported compilation target of the upstream CPython repository this would significantly reduce the friction of allowing CPython, and the latest CPython, to become a language readily usable within the browser.

    Cheers,
    Simon

    @SimonBiggs SimonBiggs mannequin added 3.9 build type-feature labels Apr 14, 2020
    @serhiy-storchaka
    Copy link
    Member

    @serhiy-storchaka serhiy-storchaka commented Apr 14, 2020

    Do you want to provide a pull request?

    @pmp-p
    Copy link
    Mannequin

    @pmp-p pmp-p mannequin commented Apr 14, 2020

    you can add

    (wasm not asm.js, clang-10+ required)

    demo https://pmp-p.github.io/python-next/test.html

    CPython can already run in the browser with very little patching, but major issues are :

    • asyncify'ing the whole wasm VM to have pre-emption over cPython's one to prevent blocking I/O slows down things *a lot* (10x)
      => (very?) bad user experience.

    • the size of vm + stdlib ~ 30 MiB and wasm compilation time.
      => bad user experience on first load or slow connexion.

    • the lack of threading in wasm MinimumViableProduct specification (but this is the browser standard for now), that leads to rewrite bits of stdlib ( like eg asyncio module )
      => adding more maintenance burden on stdlib (!)

    i tested them all and my personnal opinion is : I can see no use case that would favour "stock" cPython wasm versus a blazing fast MicroPytho (or pycopy) wasm flavour or supercharged full stack pyodide.

    @SimonBiggs
    Copy link
    Mannequin Author

    @SimonBiggs SimonBiggs mannequin commented Apr 14, 2020

    Hi pmp-p and Serhiy,

    I'd be more than happy to attempt a pull request, but I imagine a change
    such as this needs to be discussed first, trying not to "rush to make a
    patch" (https://www.youtube.com/watch?v=voXVTjwnn-U&feature=youtu.be&t=2546).
    Also, I doubt I will do a good job of it... but I am more than happy to try.

    A note regarding "supercharged full stack pyodide", potentially without
    efforts such as upstreaming into CPython and emscripten the relevant
    patches, that supercharged full stack may just unfortunately stagnate. See
    pyodide/pyodide#635 (comment)

    With respect to blocking when running Python as WASM, I have found running
    the WebAssembly CPython within a webworker and signalling data back and
    forth causes there to be no UI issues. It ends up being quite a neat set
    up. Main down side right now however is the set up is currently going
    stale, hence me believing reaching out like this is in the best interests
    of Python going forward.

    Cheers,
    Simon

    On Tue, 14 Apr 2020 at 18:58, pmp-p <report@bugs.python.org> wrote:

    pmp-p <pmpp.pub@gmail.com> added the comment:

    you can add
    *
    https://github.com/pmp-p/pydk/tree/master/sources.em/Python-3.8.0b4.patchset
    -- Python 3.8.x

    (wasm not asm.js, clang-10+ required)

    demo https://pmp-p.github.io/python-next/test.html

    CPython can already run in the browser with very little patching, but
    major issues are :

    • asyncify'ing the whole wasm VM to have pre-emption over cPython's one
      to prevent blocking I/O slows down things *a lot* (10x)
      => (very?) bad user experience.

    • the size of vm + stdlib ~ 30 MiB and wasm compilation time.
      => bad user experience on first load or slow connexion.

    • the lack of threading in wasm MinimumViableProduct specification (but
      this is the browser standard for now), that leads to rewrite bits of stdlib
      ( like eg asyncio module )
      => adding more maintenance burden on stdlib (!)

    i tested them all and my personnal opinion is : I can see no use case that
    would favour "stock" cPython wasm versus a blazing fast MicroPytho (or
    pycopy) wasm flavour or supercharged full stack pyodide.

    ----------
    nosy: +pmpp


    Python tracker <report@bugs.python.org>
    <https://bugs.python.org/issue40280\>


    @Beuc
    Copy link
    Mannequin

    @Beuc Beuc mannequin commented May 22, 2020

    I've been maintaining a Python Emscripten build for the Ren'Py (game engine) web port:
    https://github.com/python-emscripten/python
    https://renpy.beuc.net/

    I recently tackled Python3 with a minimal/embeddable approach and checking the other ports already pointed in the discussion:
    https://github.com/python-emscripten/python/tree/trunk/3.8/
    (2 patches, and a short pyconfig.h fix-up)

    There is also a Cython module to use the Emscripten C API.

    Here's a demo at:
    https://www.beuc.net/python-emscripten/demo/3/
    (hello-world size: 3MB, with a few common modules: 4MB)

    I can provide a pull request with a first few core changes.
    Should this be done on github?

    cross-compilation handling appears to follow an incorrect logic, in particular by querying 'dpkg' or parsing compiler output to detect include paths -- it is the (cross-)compiler's responsibility to provide the system paths, and detecting them manually causes conflicts. I had to patch setup.py. Let me know if I missed something.

    Usually cross-compiling is triggered by non-matching build-type/host-type. Here cross-compilation logic is apparently triggered when exporting _PYTHON_HOST_PLATFORM=xxx manually (it's in the Makefile but not exported, and breaks normal build when exported). Is this the way it's meant to be used?

    @ethanhs
    Copy link
    Mannequin

    @ethanhs ethanhs mannequin commented May 20, 2021

    I think the first thing we should do is figure out whether we want to support Emscripten or WASI (or both).

    Emscripten uses Javascript polyfills for some syscalls, while WASI makes direct calls the VM it is running in. They both can use WebAssembly for executing the code. This means Emscripten has wider API support, but WASI is lighter weight in many ways.

    I think starting with patches to support Emscripten would be best, as it is easier to target, then add support for WASI later.

    I think supporting WASI has a lot of value, because it can be run deterministically, which would be great for data science (Imagine a jupyter notebook that runs the same everywhere!)

    One issue with WASI, and may be an issue with Emscripten, is threads. In 3.8 (or 3.9?) threadless builds were removed. However, WebAssembly's threading API is not really meant to emulate pthread, and SharedArrayBuffer, the primitive it is built on, is disabled in several browsers due to Spectre concerns.

    Would patches to re-add a threadless build mode be accepted?

    @tiran
    Copy link
    Member

    @tiran tiran commented Nov 25, 2021

    I have added wasm32/wasm64 architectures with emscripten/wasi operating system as cross-build targets. The values are based on Rust targets:

    $ rustc --print target-list | grep wasm
    wasm32-unknown-emscripten
    wasm32-unknown-unknown
    wasm32-wasi
    wasm64-unknown-unknown

    wasm (WebAssembly) is "native instruction set" for the JavaScript VM while wasi or emscripten provide operating system facilities like memory management and I/O.

    @tiran tiran added 3.11 and removed 3.9 labels Nov 25, 2021
    @tiran
    Copy link
    Member

    @tiran tiran commented Nov 25, 2021

    Our config.sub is recent enough and has support for wasm32, wasm64, wasi, and emscripten:

    $ grep was[mi] config.sub 
                            | wasm32 | wasm64 \
                 | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \

    @brettcannon
    Copy link
    Member

    @brettcannon brettcannon commented Nov 25, 2021

    LLVM considers was32-wasi an alias for wasm32-unknown-wasi. Verified on the WebAssembly Discover server at https://discord.com/channels/453584038356058112/596492540388179976/898618010221310062.

    @brettcannon
    Copy link
    Member

    @brettcannon brettcannon commented Nov 25, 2021

    My last message had a couple of typos; should have been wasm32-wasi and "Discord", not "Discovery".

    @brettcannon
    Copy link
    Member

    @brettcannon brettcannon commented Nov 25, 2021

    Do we need to care about our config.guess being updated as well? This is a totally ignorant question based on https://github.com/WebAssembly/wasi-sdk#notes-for-autoconf mentioning config.guess.

    @brettcannon
    Copy link
    Member

    @brettcannon brettcannon commented Nov 25, 2021

    To help keep links up-to-date, Pyodide now lives at:

    https://github.com/pyodide/pyodide/tree/main/cpython

    @tiran
    Copy link
    Member

    @tiran tiran commented Nov 25, 2021

    Our config.sub agrees with LLVM:

    $ ./config.sub wasm32-wasi
    wasm32-unknown-wasi

    The config.sub and config.guess scripts in main are recent enough for wasm. Just to be sure I created #29781 and plan to backport the changeset to 3.10 and 3.9. It's generally safe to update the files to latest version.

    @tiran
    Copy link
    Member

    @tiran tiran commented Nov 25, 2021

    New changeset 1052a39 by Christian Heimes in branch 'main':
    bpo-40280: Add wasm cross build targets (GH-29771)
    1052a39

    @tiran
    Copy link
    Member

    @tiran tiran commented Nov 25, 2021

    I have uploaded my config.site override to https://gist.github.com/tiran/5ccffa28723d3e4739db848451bd9efa . It contains overrides based on pyodide and overrides for new features.

    I'm also getting this error with emscripten 2.0.13. _sys_shutdown is the syscall for shutdown(2) used by the socket module.

    error: undefined symbol: __sys_shutdown (referenced by top-level compiled C/C++ code)
    warning: Link with -s LLD_REPORT_UNDEFINED to get more information on undefined symbols
    warning: To disable errors for undefined symbols use -s ERROR_ON_UNDEFINED_SYMBOLS=0
    warning: ___sys_shutdown may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
    Error: Aborting compilation due to previous errors

    @tiran
    Copy link
    Member

    @tiran tiran commented Nov 25, 2021

    @tiran
    Copy link
    Member

    @tiran tiran commented Nov 26, 2021

    New changeset ee1e2c6 by Christian Heimes in branch 'main':
    bpo-40280: Use Setup.stdlib static for wasm builds (GH-29784)
    ee1e2c6

    @RomanYurchak
    Copy link
    Mannequin

    @RomanYurchak RomanYurchak mannequin commented Nov 26, 2021

    Thanks a lot for working on this!

    _sys_shutdown is the syscall for shutdown(2) used by the socket module.

    Yes, the issue with Emscripten is that a number of system calls are either not implemented or implemented but not tested. See a list we are using in https://github.com/pyodide/pyodide/blob/main/cpython/pyconfig.undefs.h (though things might have improved since it was created).

    FYI, with Emscripten, the list of CPython unit tests that are currently skipped (as of Python 3.9.5) is in https://github.com/pyodide/pyodide/blob/main/src/tests/python_tests.txt some of those are due to browser VM limitations (e.g. virtual filestem by Emscripten that's not fully POSIX compliant, no processes, no sockets, async only via the browser event loop etc), others because we are not yet using threading since not all browsers support it, and some failures probably need more investigation.

    Also opened pyodide/pyodide#2000 . Let us know if there is anything we can do help with this effort.

    @tiran
    Copy link
    Member

    @tiran tiran commented Nov 26, 2021

    New changeset d224e76 by Christian Heimes in branch 'main':
    bpo-40280: clean and ignore .wasm files (GH-29794)
    d224e76

    @tiran
    Copy link
    Member

    @tiran tiran commented Nov 26, 2021

    Thanks Roman, I replied on the pyodide issue tracker.

    @tiran
    Copy link
    Member

    @tiran tiran commented Jan 20, 2022

    New changeset c02e860 by Christian Heimes in branch 'main':
    bpo-40280: Misc fixes for wasm32-emscripten (GH-30722)
    c02e860

    @tiran
    Copy link
    Member

    @tiran tiran commented Jan 24, 2022

    New changeset d5fd438 by Christian Heimes in branch 'main':
    bpo-40280: Get help() working and more (GH-30858)
    d5fd438

    @tiran
    Copy link
    Member

    @tiran tiran commented Jan 25, 2022

    New changeset 8464fbc by Christian Heimes in branch 'main':
    bpo-40280: Skip subprocess-based tests on wasm32-emscripten (GH-30615)
    8464fbc

    @miss-islington
    Copy link
    Contributor

    @miss-islington miss-islington commented Jan 27, 2022

    New changeset 606e496 by Christian Heimes in branch 'main':
    bpo-40280: Use presence of msvcrt module to detect Windows (GH-30930)
    606e496

    @tiran
    Copy link
    Member

    @tiran tiran commented Feb 5, 2022

    New changeset 96b344c by Christian Heimes in branch 'main':
    bpo-40280: Address more test failures on Emscripten (GH-31050)
    96b344c

    @tiran
    Copy link
    Member

    @tiran tiran commented Mar 8, 2022

    New changeset 5081e78 by Christian Heimes in branch 'main':
    bpo-40280: Block more non-working syscalls in Emscripten (GH-31757)
    5081e78

    @tiran
    Copy link
    Member

    @tiran tiran commented Mar 8, 2022

    I have fixed a signal-related issue in #75949 / bpo-23325

    @tiran
    Copy link
    Member

    @tiran tiran commented Mar 8, 2022

    New changeset 95ba723 by Christian Heimes in branch 'main':
    bpo-40280: Skip dysfunctional pipe tests on Emscripten (GH-31770)
    95ba723

    @tiran
    Copy link
    Member

    @tiran tiran commented Mar 10, 2022

    New changeset de554d6 by Christian Heimes in branch 'main':
    bpo-40280: Skip more tests/features that don't apply to Emscripten (GH-31791)
    de554d6

    @tiran
    Copy link
    Member

    @tiran tiran commented Mar 11, 2022

    New changeset ecfff63 by Christian Heimes in branch 'main':
    bpo-40280: Disable AF_UNIX, AF_PACKET, SO_REUSE* on Emscripten (bpo-31829)
    ecfff63

    @tiran
    Copy link
    Member

    @tiran tiran commented Mar 14, 2022

    New changeset f00ced8 by Christian Heimes in branch 'main':
    bpo-40280: select: Use NULL for empty fdset (GH-31865)
    f00ced8

    @tiran
    Copy link
    Member

    @tiran tiran commented Mar 15, 2022

    New changeset b43b9b4 by Christian Heimes in branch 'main':
    bpo-40280: Skip wakeup_fd pipe tests on Emscripten (GH-31909)
    b43b9b4

    @tiran
    Copy link
    Member

    @tiran tiran commented Mar 15, 2022

    New changeset a4674f0 by Christian Heimes in branch 'main':
    bpo-40280: Detect presence of time.tzset and thread_time clock (GH-31898)
    a4674f0

    @tiran
    Copy link
    Member

    @tiran tiran commented Mar 17, 2022

    New changeset ef1327e by Christian Heimes in branch 'main':
    bpo-40280: Skip more tests on Emscripten (GH-31947)
    ef1327e

    @miss-islington
    Copy link
    Contributor

    @miss-islington miss-islington commented Mar 22, 2022

    New changeset deeaac4 by Christian Heimes in branch 'main':
    bpo-40280: Skip socket, fork, subprocess tests on Emscripten (GH-31986)
    deeaac4

    @miss-islington
    Copy link
    Contributor

    @miss-islington miss-islington commented Mar 24, 2022

    New changeset 8a0a9e5 by Christian Heimes in branch 'main':
    bpo-40280: Add wasm32-emscripten and wasm32-wasi SOABI (GH-32095)
    8a0a9e5

    @tiran
    Copy link
    Member

    @tiran tiran commented Apr 1, 2022

    New changeset 17245c8 by Christian Heimes in branch 'main':
    bpo-40280: Add debug Emscripten flavors (GH-32233)
    17245c8

    @tiran
    Copy link
    Member

    @tiran tiran commented Apr 1, 2022

    New changeset 082d349 by Christian Heimes in branch 'main':
    bpo-40280: Emscripten fork_exec now fails early (GH-32224)
    082d349

    @miss-islington
    Copy link
    Contributor

    @miss-islington miss-islington commented Apr 2, 2022

    New changeset 59be9cd by Christian Heimes in branch 'main':
    bpo-40280: Detect if WASM platform supports threading (GH-32243)
    59be9cd

    @tiran
    Copy link
    Member

    @tiran tiran commented Apr 2, 2022

    New changeset 4ed8a9a by Christian Heimes in branch 'main':
    bpo-40280: Enable most file-at() and nanosleep APIs again (GH-32238)
    4ed8a9a

    @tiran
    Copy link
    Member

    @tiran tiran commented Apr 2, 2022

    pmp-p wrote on #76434:
    when using --enable-wasm-dynamic-linking i think --enable-shared should set -fPIC and -s SIDE_MODULE=1 for libpython.so

    I have not tried --enable-shared with Emscripten yet. So far I have assumed that the result is a fat Python binary that can load additional shared libraries.

    @tiran
    Copy link
    Member

    @tiran tiran commented Apr 4, 2022

    New changeset c9844cb by Christian Heimes in branch 'main':
    bpo-40280: Add --enable-wasm-dynamic-linking (GH-32253)
    c9844cb

    @tiran
    Copy link
    Member

    @tiran tiran commented Apr 5, 2022

    New changeset 96e0983 by Christian Heimes in branch 'main':
    bpo-40280: Add limited Emscripten REPL (GH-32284)
    96e0983

    @tiran
    Copy link
    Member

    @tiran tiran commented Apr 6, 2022

    New changeset 765f6de by Christian Heimes in branch 'main':
    bpo-40280: WASM defaults to no dynamic linking (GH-32360)
    765f6de

    @tiran
    Copy link
    Member

    @tiran tiran commented Apr 7, 2022

    New changeset 2b16a08 by Christian Heimes in branch 'main':
    bpo-40280: Detect missing threading on WASM platforms (GH-32352)
    2b16a08

    @terryjreedy
    Copy link
    Member

    @terryjreedy terryjreedy commented Apr 7, 2022

    Christian: IDLE and test_idle require threading. I once tested for threading in test_idle (not sure about IDLE itself) but removed the test when threading was made supposedly non-optional. Test_idle still tests for tkinter and idlelib. For PR 32352. did you miss IDLE's requirement or is tkinter and hence IDLE and its test not included on WASM/emscripten? Will it never be?

    @tiran
    Copy link
    Member

    @tiran tiran commented Apr 7, 2022

    In #76533 I changed only tests that I was able to execute under wasm32-emscripten. As far as I know TK does not build for WASM. Somebody would have to port TCL/TK to WebGL or SDL2 to make it work in the browser.

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    tiran added a commit to tiran/cpython that referenced this issue Apr 14, 2022
    - drop unnecessary ``=1`` suffix from Emscripten flags
    - drop unnecessary ``-sWASM`` flag for side modules
    - rename ``build_platform`` to ``build_wasm``. I introduced the target
      for WASM builds a couple of months ago.
    - fix ``--enable-test-modules`` for browser builds
    tiran added a commit that referenced this issue Apr 14, 2022
    - drop unnecessary ``=1`` suffix from Emscripten flags
    - drop unnecessary ``-sWASM`` flag for side modules
    - rename ``build_platform`` to ``build_wasm``. I introduced the target
      for WASM builds a couple of months ago.
    - fix ``--enable-test-modules`` for browser builds
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.11 build type-feature
    Projects
    None yet
    Development

    No branches or pull requests

    5 participants