@@ -509,28 +509,47 @@ including browsers and Node.js.
509509 CPython being designed for ``./configure `` / ``make ``.
510510
511511To build for Emscripten, you will need to cross-compile CPython. This requires a
512- C compiler just like building for :ref: `Unix <unix-compiling >` as well as:
512+ C compiler just like building for :ref: `Unix <unix-compiling >`. The Node Version
513+ Manager (``nvm ``) must also be on your path.
513514
514- * The Emscripten compiler
515- * Node.js
515+ Building for Emscripten requires doing a cross-build where you have a *build *
516+ Python to help produce an Emscripten build of CPython. This means you build
517+ CPython twice: once to have a version of Python for the build system to use and
518+ another that's the build you ultimately care about (that is, the build Python is
519+ not meant for use by you directly, only the build system).
516520
517- The simplest way to install the Emscripten compiler is :
521+ The simplest way to build Emscripten is to run :
518522
519523.. code-block :: sh
520524
521- # Install Emscripten
522- git clone https://github.com/emscripten-core/emsdk
523- ./emsdk/emsdk install 4.0.12
524- ./emsdk/emsdk activate 4.0.12
525- source ./emsdk/emsdk_env.sh
525+ python3 Platforms/emscripten build all --emsdk-cache=./cross-build/emsdk
526+
527+ This will:
528+
529+ 1. Build a copy of Python that can run on the host machine (the "build" python);
530+ 2. Download a copy of the Emscripten SDK matching the version required by the
531+ version of Python being compiled;
532+ 3. Ensure that a required version of Node is installed;
533+ 4. Download the code for all the binary dependencies of Python (such as
534+ ``libFFI `` and ``xz ``), and compile them for Emscripten; and
535+ 5. Build a copy of Python that can run on Emscripten (the "host" python).
536+
537+ If you omit the ``--emsdk-cache `` environment variable, the build script will
538+ assume that the current environment has the Emscripten tools available. You are
539+ responsible for downloading and activating those tools in your environment. The
540+ version of Emscripten and Node that is required to build Python is defined in
541+ the :cpy-file: `Platforms/emscripten/config.toml ` configuration file.
526542
527- Updating the Emscripten compiler version can cause breakages. For the best
528- compatibility, use the appropriate Emscripten version based on the version of
529- CPython you're building:
543+ There are three environment variables that can be used to control the operation of
544+ the ``Platforms/emscripten `` build script:
530545
531- * For building CPython 3.14, use ``emsdk `` version ``4.0.12 ``.
532- * For building the main branch of the CPython repository, you may wish to use
533- ``latest `` instead of a specific version.
546+ * ``EMSDK_CACHE `` controls the location of the emscripten SDK. You can use this instead
547+ environment variable instead of passing the ``--emsdk-cache `` flag.
548+ * ``CACHE_DIR `` defines the location where downloaded artefacts, such
549+ as precompiled ``libFFI `` and ``xz `` binaries, will be stored.
550+ * ``CROSS_BUILD_DIR `` defines the name of the ``cross-build `` directory
551+ that will be used for builds. This can be useful if you need to maintain
552+ builds of multiple versions of Python.
534553
535554It is possible (but not necessary) to enable ``ccache `` for Emscripten builds
536555by setting the ``EM_COMPILER_WRAPPER `` environment, but this step will only
@@ -541,68 +560,39 @@ sourced script removes the environment variable):
541560
542561 export EM_COMPILER_WRAPPER=ccache
543562
544- Building for Emscripten requires doing a cross-build where you have a *build *
545- Python to help produce an Emscripten build of CPython. This means you build
546- CPython twice: once to have a version of Python for the build system to use and
547- another that's the build you ultimately care about (that is, the build Python is
548- not meant for use by you directly, only the build system).
549-
550- The easiest way to get a debug build of CPython for Emscripten is to use the
551- ``Tools/wasm/emscripten build `` command, which should be run with a recent
552- version of Python (3.13 or newer) already installed on your machine:
563+ To get a debug build of CPython for Emscripten, use:
553564
554565.. code-block :: shell
555566
556- python3 Tools/wasm/ emscripten build --quiet -- --config-cache --with-pydebug
567+ python3 Platforms/ emscripten build all -- --with-pydebug
557568
558569 That single command will configure and build both the build Python and the
559570Emscripten build in ``cross-build/build `` and
560571``cross-build/wasm32-emscripten/build/python/ ``, respectively.
561572
562- You can also do each configuration and build step separately; the command above
563- is a convenience wrapper around the following commands:
564-
565- .. code-block :: shell
566-
567- python Tools/wasm/emscripten configure-build-python --quiet -- --config-cache --with-pydebug
568- python Tools/wasm/emscripten make-build-python --quiet
569- python Tools/wasm/emscripten make-libffi --quiet
570- python Tools/wasm/emscripten make-mpdec --quiet
571- python Tools/wasm/emscripten configure-host --quiet -- --config-cache
572- python Tools/wasm/emscripten make-host --quiet
573-
574- .. note ::
575-
576- The ``configure-host `` command infers the use of ``--with-pydebug `` from the
577- build Python.
578-
579- Running the separate commands after ``emscripten build `` is useful if you, for
580- example, only want to run the ``make-host `` step after making code changes.
573+ The ``Platforms/emscripten `` script has a number of other entry points that allow for
574+ fine-grained execution of each part of an iOS build; run ``python3
575+ Platforms/emscripten --help `` for more details.
581576
582- Once everything is complete, there will be a
583- ``cross-build/wasm32-emscripten/build/python/python.sh `` helper file which you
584- can use to run the ``python.mjs `` file:
577+ Once the build is complete, you can run Python code using:
585578
586579.. code-block :: shell
587580
588- cross-build/wasm32- emscripten/build/python/python.sh --version
581+ python3 Platforms/ emscripten run ./path/to/script.py
589582
590- You can also use ``Makefile `` targets and they will work as expected thanks to
591- the ``HOSTRUNNER `` environment variable having been set to a similar value as
592- used in ``python.sh ``:
583+ You can run the CPython test suite using:
593584
594585.. code-block :: shell
595586
596- make -C cross-build/wasm32- emscripten/build/python/ test
587+ python3 Platforms/ emscripten run -- test
597588
598589 Additional instructions for running the resulting builds (through Node.js and/or
599590through web browsers) are available in the CPython repository at
600- :cpy-file: `Tools/wasm /README.md `.
591+ :cpy-file: `Platforms/emscripten /README.md `.
601592
602593.. _Emscripten : https://emscripten.org/
603594.. _WebAssembly : https://webassembly.org
604595
605-
606596Android
607597-------
608598
@@ -626,128 +616,108 @@ macOS; then once for each of the three underlying platforms used by iOS:
626616* An ARM64 simulator running on a recent macOS machine; and
627617* An x86_64 simulator running on older macOS machine.
628618
629- The macOS build is required because building Python involves running some Python
630- code. On a normal desktop build of Python, you can compile a Python interpreter
631- and then use that interpreter to run Python code. However, the binaries produced
632- for iOS won't run on macOS, so you need to provide an external Python
633- interpreter. From the root of a CPython code checkout, run the following::
634-
635- $ ./configure --prefix=$(pwd)/cross-build/macOS
636- $ make -j4 all
637- $ make install
638-
639- This will build and install Python for macOS into the ``cross-build/macOS ``
640- directory.
641-
642- The CPython build system can compile a single platform at a time. It is possible
643- to *test * a single platform at a time; however, for distribution purposes, you
644- must compile all three, and merge the results. See the `iOS README
645- <https://github.com/python/cpython/blob/main/iOS/README.rst#merge-thin-frameworks-into-fat-frameworks> `__
646- for details on this merging process.
647-
648- The following instructions will build CPython for iOS with all extensions
649- enabled, provided you have installed the build dependencies XZ, BZip2, OpenSSL
650- and libFFI in subfolders of the ``cross-build `` folder. See :ref: `the iOS
651- section on installing build dependencies <build-dependencies>` for details on
652- how to obtain these dependencies. These dependencies are all strictly optional,
653- however, including libFFI is *highly * recommended, as it is required by the
654- :py:mod: `ctypes ` module which is used on iOS to support accessing native system APIs.
655-
656- .. tab :: ARM64 device
657-
658- .. code-block :: console
659-
660- $ export PATH="$(pwd)/iOS/Resources/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin"
661- $ ./configure \
662- LIBLZMA_CFLAGS="-I$(pwd)/cross-build/iphoneos.arm64/xz/include" \
663- LIBLZMA_LIBS="-L$(pwd)/cross-build/iphoneos.arm64/xz/lib -llzma" \
664- BZIP2_CFLAGS="-I$(pwd)/cross-build/iphoneos.arm64/bzip2/include" \
665- BZIP2_LIBS="-L$(pwd)/cross-build/iphoneos.arm64/bzip2/lib -lbz2" \
666- LIBFFI_CFLAGS="-I$(pwd)/cross-build/iphoneos.arm64/libffi/include" \
667- LIBFFI_LIBS="-L$(pwd)/cross-build/iphoneos.arm64/libffi/lib -lffi" \
668- --with-openssl="$(pwd)/cross-build/iphoneos.arm64/openssl" \
669- --host=arm64-apple-ios12.0 \
670- --build=arm64-apple-darwin \
671- --with-build-python=$(pwd)/cross-build/macOS/bin/python3.13 \
672- --enable-framework
673- $ make -j4 all
674- $ make install
675-
676- .. tab :: ARM64 simulator
677-
678- .. code-block :: console
679-
680- $ export PATH="$(pwd)/iOS/Resources/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin"
681- $ ./configure \
682- LIBLZMA_CFLAGS="-I$(pwd)/cross-build/iphonesimulator.arm64/xz/include" \
683- LIBLZMA_LIBS="-L$(pwd)/cross-build/iphonesimulator.arm64/xz/lib -llzma" \
684- BZIP2_CFLAGS="-I$(pwd)/cross-build/iphonesimulator.arm64/bzip2/include" \
685- BZIP2_LIBS="-L$(pwd)/cross-build/iphonesimulator.arm64/bzip2/lib -lbz2" \
686- LIBFFI_CFLAGS="-I$(pwd)/cross-build/iphonesimulator.arm64/libffi/include" \
687- LIBFFI_LIBS="-L$(pwd)/cross-build/iphonesimulator.arm64/libffi/lib -lffi" \
688- --with-openssl="$(pwd)/cross-build/iphonesimulator.arm64/openssl" \
689- --host=arm64-apple-ios12.0-simulator \
690- --build=arm64-apple-darwin \
691- --with-build-python=$(pwd)/cross-build/macOS/bin/python3.13 \
692- --enable-framework
693- $ make -j4 all
694- $ make install
695-
696- .. tab :: x86-64 simulator
697-
698- .. code-block :: console
699-
700- $ export PATH="$(pwd)/iOS/Resources/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin"
701- $ ./configure \
702- LIBLZMA_CFLAGS="-I$(pwd)/cross-build/iphonesimulator.x86_64/xz/include" \
703- LIBLZMA_LIBS="-L$(pwd)/cross-build/iphonesimulator.x86_64/xz/lib -llzma" \
704- BZIP2_CFLAGS="-I$(pwd)/cross-build/iphonesimulator.x86_64/bzip2/include" \
705- BZIP2_LIBS="-L$(pwd)/cross-build/iphonesimulator.x86_64/bzip2/lib -lbz2" \
706- LIBFFI_CFLAGS="-I$(pwd)/cross-build/iphonesimulator.x86_64/libffi/include" \
707- LIBFFI_LIBS="-L$(pwd)/cross-build/iphonesimulator.x86_64/libffi/lib -lffi" \
708- --with-openssl="$(pwd)/cross-build/iphonesimulator.x86_64/openssl" \
709- --host=x86_64-apple-ios12.0-simulator \
710- --build=arm64-apple-darwin \
711- --with-build-python=$(pwd)/cross-build/macOS/bin/python3.13 \
712- --enable-framework
713- $ make -j4 all
714- $ make install
715-
716- These instructions modify your ``PATH `` before the build. As iOS and macOS share
717- a hardware architecture (ARM64), it is easy for a macOS ARM64 binary to be
718- accidentally linked into your iOS build. This is especially common when Homebrew
719- is present on the build system. The most reliable way to avoid this problem is
720- to remove any potential source of other libraries from your ``PATH ``.
721-
722- However, the ``PATH `` is not completely bare --- it includes the
723- ``iOS/Resources/bin `` folder. This folder contains a collection of scripts that
724- wrap the invocation of the Xcode :program: `xcrun ` tool, removing user- and
725- version-specific paths from the values encoded in the :py:mod: `sysconfig `
726- module. Copies of these scripts are included in the final build products.
727-
728- Once this build completes, the ``iOS/Frameworks `` folder will contain a
729- ``Python.framework `` that can be used for testing.
730-
731- To run the test suite on iOS, complete a build for a *simulator * platform,
732- ensure the path modifications from the build are still in effect, and run::
733-
734- $ make testios
619+ You will need an existing Python 3 interpreter to build Python. From the root of
620+ a CPython code checkout, run the following:
621+
622+ .. tab :: Python 3.15+
623+
624+ .. code-block :: shell
625+
626+ $ python3 Platforms/Apple build iOS all
627+
628+ .. tab :: Python 3.14
629+
630+ .. code-block :: shell
631+
632+ $ python3 Apple build iOS all
633+
634+ .. tab :: Python 3.13
635+
636+ Python 3.13 requires explicitly invoking ``configure `` and ``make `` for each
637+ platform. For example, to build for the ARM64 simulator, run:
638+
639+ .. code-block :: shell
640+
641+ $ export PATH=" $( pwd) /iOS/Resources/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin"
642+ $ ./configure \
643+ LIBLZMA_CFLAGS=" -Ipath/to/xz/include" \
644+ LIBLZMA_LIBS=" -Lpath/to/xz/lib -llzma" \
645+ BZIP2_CFLAGS=" -Ipath/to/bzip2/include" \
646+ BZIP2_LIBS=" -Lpath/to/bzip2/lib -lbz2" \
647+ LIBFFI_CFLAGS=" -Ipath/to/libffi/include" \
648+ LIBFFI_LIBS=" -Lpath/to/libffi/lib -lffi" \
649+ --with-openssl=" path/to/openssl" \
650+ --host=arm64-apple-ios-simulator \
651+ --build=arm64-apple-darwin \
652+ --with-build-python=path/to/python3.13 \
653+ --enable-framework
654+ $ make -j4 all
655+ $ make install
656+
657+ The ``--host `` argument should be one of ``arm64-apple-ios-simulator ``,
658+ ``x64_64-apple-ios-simulator `` or ``arm64-apple-ios ``. Your ``PATH `` should
659+ be kept to a minimum to avoid inadvertently linking ARM64 macOS binaries into
660+ your iOS project. You must specify a path to pre-compiled binary dependencies.
661+
662+ Once you have built an Apple Framework for each architecture, you will need
663+ to manually construct an XCframework.
664+
665+ This will:
666+
667+ 1. Build a copy of Python that can run on macOS (the "build" python);
668+ 2. Download pre-compiled binaries for dependencies of CPython (such as
669+ ``libFFI `` and ``xz ``)
670+ 3. Build a copy of Python for each supported iOS architecture (x86_64 simulator,
671+ ARM64 simulator, and ARM64 device); and
672+ 4. Generate a release artefact for iOS
673+
674+ Once this build completes, the ``cross-build/iOS `` folder will contain a
675+ ``Python.xcframework ``, and the ``cross-build/dist `` folder will contain a
676+ release tarball.
677+
678+ To run the test suite on iOS, run:
679+
680+ .. tab :: Python 3.15+
681+
682+ .. code-block :: shell
683+
684+ $ python3 Platforms/Apple test iOS
685+
686+ .. tab :: Python 3.14
687+
688+ .. code-block :: shell
689+
690+ $ python3 Apple test iOS
691+
692+ .. tab :: Python 3.13
693+
694+ .. code-block :: shell
695+
696+ $ make testios
735697
736698 The full test suite takes approximately 12 minutes to run on a 2022 M1 MacBook
737699Pro, plus a couple of extra minutes to build the testbed application and boot
738- the simulator. There will be an initial burst of console output while the Xcode
739- test project is compiled; however, while the test suite is running, there is no
740- console output or progress. This is a side effect of how Xcode operates when
741- executed at the command line. You should see an iOS simulator appear during the
742- testing process; the simulator will booth to an iOS landing screen, the testbed
700+ the simulator. You should see an iOS simulator appear during the
701+ testing process; the simulator will boot to an iOS landing screen, the testbed
743702app will be installed, and then started. The screen of the simulator will be
744703black while the test suite is running. When the test suite completes, success or
745- failure will be reported at the command line. In the case of failure, you will
746- see the full log of CPython test suite output.
704+ failure will be reported at the command line.
705+
706+ Two environment variables can be used to configure the operation of the Apple
707+ build script:
708+
709+ * ``CACHE_DIR `` defines the location where downloaded artefacts, such
710+ as precompiled ``libFFI `` and ``xz `` binaries, will be stored.
711+ * ``CROSS_BUILD_DIR `` defines the name of the ``cross-build `` directory
712+ that will be used for builds. This can be useful if you need to maintain
713+ builds of multiple versions of Python.
714+
715+ The ``Platforms/Apple `` script has a number of other entry points that allow for
716+ fine-grained execution of each part of an iOS build; run ``python3
717+ Platforms/Apple --help `` for more details.
747718
748719You can also run the test suite in Xcode itself. This is required if you want to
749- run on a physical device; it is also the easiest approach if you need to run a
750- single test, or a subset of tests. See the `iOS README
720+ run on a physical device. See the `iOS README
751721<https://github.com/python/cpython/blob/main/iOS/README.rst#debugging-test-failures> `__
752722for details.
753723
0 commit comments