From c8e9b2e423cb0702d240814b21224843541c9d2b Mon Sep 17 00:00:00 2001 From: Callahan Date: Sun, 10 Sep 2023 02:11:33 -0500 Subject: [PATCH] docs(architectures): add how-to, reference, and explanation (#4349) Signed-off-by: Callahan Kovacs --- docs/explanation/architectures.rst | 190 +++++++++++++++++++++++ docs/explanation/index.rst | 2 + docs/howto/architectures.rst | 239 +++++++++++++++++++++++++++++ docs/howto/index.rst | 2 + docs/reference/architectures.rst | 233 ++++++++++++++++++++++++++++ docs/reference/index.rst | 1 + 6 files changed, 667 insertions(+) create mode 100644 docs/explanation/architectures.rst create mode 100644 docs/howto/architectures.rst create mode 100644 docs/reference/architectures.rst diff --git a/docs/explanation/architectures.rst b/docs/explanation/architectures.rst new file mode 100644 index 0000000000..48622eb426 --- /dev/null +++ b/docs/explanation/architectures.rst @@ -0,0 +1,190 @@ +Architectures +============= + +Build-on, build-for, and run-on +------------------------------- + +``build-on``, ``build-for``, and ``run-on`` are used inside the root +``architectures`` keyword in a ``snapcraft.yaml``. + +* ``core22`` uses ``build-on`` and ``build-for`` +* ``core20`` uses ``build-on`` and ``run-on`` + +build-on +^^^^^^^^ + +The architecture of the machine that the snap is built on (i.e. the machine +where snapcraft runs). + +build-for +^^^^^^^^^ + +The architecture of the machine that the snap is built for (i.e. the machine +where the snap will be installed). + +run-on +^^^^^^ + +This is used for ``core20`` and has the same meaning as ``build-for``. It has +been replaced with the preferred term ``build-for`` in ``core22``. + +.. _build-plans: + +Build plans +----------- + +A build plan is a list of what snaps snapcraft will build. It can be defined +in the ``snapcraft.yaml`` and filtered with command-line arguments and +environment variables. + +core22 +^^^^^^ + +Snapcraft can create multiple snaps, each built for a different architecture. +Consider the following ``snapcraft.yaml`` snippet: + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + build-for: [amd64] + - build-on: [amd64, arm64] + build-for: [arm64] + +If snapcraft executes on an ``amd64`` machine, then it will create the +following build plan: + +.. code-block:: text + + Created build plan: + build-on: amd64 build-for: amd64 + build-on: amd64 build-for: arm64 + +Two snap files will be created: ``my-snap_1.0_amd64.snap`` and +``my-snap_1.0_arm64.snap``. + +If snapcraft executes on an ``arm64`` machine, then it will create the +following build plan: + +.. code-block:: text + + Created build plan: + build-on: arm64 build-for: arm64 + +One snap file will be created: ``my-snap_1.0_arm64.snap``. + +This build plan can be filtered with the environment variable +``SNAPCRAFT_BUILD_FOR=`` or the command-line argument +``--build-for=``. The command-line argument takes priority over the +environment variable. In the example above, using ``--build-for=arm64`` would +cause snapcraft to only build one snap for ``arm64``. + +Building with a provider +"""""""""""""""""""""""" + +When building a snap with LXD or Multipass, each build in the build plan occurs +in its own environment. + +Destructive mode +"""""""""""""""" + +In destructive mode, all builds in the build plan occur in the same location. +This can cause unintended consequences, such as parts not being re-built. For +more information, see `this issue `_. + +To workaround this, use ``--build-for`` or ``SNAPCRAFT_BUILD_FOR`` to build +one snap at a time and run ``snapcraft clean --destructive-mode`` when changing +the build-for architecture. + +core20 +^^^^^^ + +Build plans are not supported in ``core20`` so building a ``core20`` snap will +only produce one snap. + +Snapcraft does not automatically clean the build environment when the +``architecture`` keyword is changed. Therefore ``snapcraft clean`` should be +run when changing architectures. + +Remote build +^^^^^^^^^^^^ + +Launchpad supports building snaps on multiple architectures. + +If architectures are not defined in the ``snapcraft.yaml``, then Launchpad will +build the snap on all architectures +:ref:`supported by Launchpad`. + +If architectures are defined in the ``snapcraft.yaml``, then Launchpad will +build the snap on all ``build-on`` architectures. + +When a snap can be built on multiple architectures, Launchpad can choose which +``build-on`` platform to use. For example: + +.. code-block:: yaml + + architectures: + - build-on: [amd64, arm64] + build-for: [ppc64el] + +Launchpad may build the snap on an ``amd64`` or ``arm64`` platform. This choice +is controlled by Launchpad and cannot be influenced by the user. + +Architecture errors +------------------- + +.. _build-plan-error: + +Could not make build plan +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + Could not make build plan: build-on architectures in snapcraft.yaml does + not match host architecture (amd64). + +This ``core22`` error has two common causes. + +The first cause is that snapcraft is not able to create a build plan because +the there are no ``build-on`` architectures matching the host's architecture. +To resolve this, build the snap on an architecture listed in the +``snapcraft.yaml`` or add the host architecture as a ``build-on`` value. + +The second cause is due to not enclosing a list of multiple architectures +with brackets. For example: + +.. code-block:: yaml + + architectures: + - build-on: amd64, arm64 + build-for: [arm64] + +should be changed to: + +.. code-block:: yaml + + architectures: + - build-on: [amd64, arm64] + build-for: [arm64] + +The brackets are required for lists. This problem is described in +more detail `here `_. + +Unsupported architectures in remote build +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: text + + The following architectures are not supported by the remote builder: + amd64, arm64. + Please remove them from the architecture list and try again. + +This error has two common causes. First, the architecture may not be supported +by launchpad. See :ref:`here ` for a list of +architectures supported by Launchpad. + +The second cause is the same :ref:`as above` - not enclosing +a list of multiple architectures with brackets. + +.. _`issue 4340`: https://github.com/snapcore/snapcraft/issues/4340 +.. _`issue 4356`: https://github.com/snapcore/snapcraft/issues/4356 diff --git a/docs/explanation/index.rst b/docs/explanation/index.rst index b9ed902fb0..ba25dd5754 100644 --- a/docs/explanation/index.rst +++ b/docs/explanation/index.rst @@ -5,3 +5,5 @@ Explanation .. toctree:: :maxdepth: 1 + + architectures diff --git a/docs/howto/architectures.rst b/docs/howto/architectures.rst new file mode 100644 index 0000000000..503dd9e8b9 --- /dev/null +++ b/docs/howto/architectures.rst @@ -0,0 +1,239 @@ +Architectures +============= + +By default, Snapcraft builds a snap to run on the same architecture as the build +environment. This behaviour can be modified with the root keyword +``architectures`` in the snap’s ``snapcraft.yaml``. + +The ``architectures`` keyword is used to create a build plan. See +:ref:`build plans` for an explanation on how build plans are +created. + +How to create a snap for a specific architecture +------------------------------------------------ + +To create a snap that will be built on ``amd64`` and built for ``amd64``, use +one of the ``snapcraft.yaml`` snippets below. + +core22 +^^^^^^ + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + build-for: [amd64] + +Building on ``amd64`` will produce one snap built for ``amd64``. Snapcraft will +raise an error when building on another architecture. + +If ``build-for`` is omitted, then it will assume the value of ``build-on``. The +following snippet snippet will produce the same result: + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + +The shorthand format will also produce the same result: + +.. code-block:: yaml + + architectures: + - amd64 + +core20 +^^^^^^ + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + run-on: [amd64] + +Building on ``amd64`` will produce one snap built for ``amd64``. Snapcraft will +not raise an error when building on another architecture. Instead, it will +ignore the ``architectures`` keyword and build for the build-on architecture. + +If ``run-on`` is omitted, then it will assume the value of ``build-on``. The +following snippet snippet will produce the same result: + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + +The shorthand format will also produce the same result: + +.. code-block:: yaml + + architectures: + - amd64 + +How to create a set of snaps for multiple architectures +------------------------------------------------------- + +core22 +^^^^^^ + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + build-for: [amd64] + - build-on: [arm64] + build-for: [arm64] + +Building on ``amd64`` will produce one snap for ``amd64``. Building on ``arm64`` +will produce one snap for ``arm64``. Snapcraft will raise an error when building +on another architecture. + +If ``build-for`` is omitted, then it will assume the value of ``build-on``. The +following snippet snippet will produce the same result: + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + - build-on: [arm64] + +The shorthand format will also produce the same result: + +.. code-block:: yaml + + architectures: [amd64, arm64] + +core20 +^^^^^^ + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + run-on: [amd64] + - build-on: [arm64] + run-on: [arm64] + +Building on ``amd64`` will produce one snap built for ``amd64``. Building on +``arm64`` will produce one snap built for ``arm64``. Snapcraft will not raise +an error when building on another architecture. Instead, it will ignore the +``architectures`` keyword and build for the build-on architecture. + +If ``run-on`` is omitted, then it will assume the value of ``build-on``. The +following snippet snippet will produce the same result: + +.. code-block:: yaml + + architectures: + - build-on: amd64 + - build-on: arm64 + +The shorthand format will also produce the same result: + +.. code-block:: yaml + + architectures: [amd64, arm64] + +.. _how-to-arch-build-for-all: + +How to create an architecture independent snap +---------------------------------------------- + +``build-for: [all]`` is used for a snap that can run on all architectures, like +a snap that is a shell or python script. It cannot be combined with other +architectures. Click :ref:`here` for more information on +the ``all`` keyword. + +core22 +^^^^^^ + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + build-for: [all] + +core20 +^^^^^^ + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + run-on: [all] + +How to create a cross-compiling snap +------------------------------------ + +core22 +^^^^^^ + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + build-for: [arm64] + +Building on ``amd64`` will produce one snap built for ``arm64``. Snapcraft will +raise an error when building on another architecture. + +``core22`` can handle complex build plans. For example: + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + build-for: [amd64] + - build-on: [amd64, arm64] + build-for: [arm64] + +Building on ``amd64`` will produce two snaps, one built for ``amd64`` and one +built for ``arm64``. Building on ``arm64`` will produce one snap built for +``arm64``. Snapcraft will raise an error when building on another architecture. + +core20 +^^^^^^ + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + run-on: [arm64] + +Building on ``amd64`` will produce one snap built for ``arm64``. Snapcraft will +not raise an error when building on another architecture. Instead, it will +ignore the ``architectures`` keyword and build for the build-on architecture. + +Complex build plans like the previous ``core22`` example are not supported for +``core20``. + +How to stage packages from another architecture +----------------------------------------------- + +To use an ``i386`` package for an ``amd64`` snap, use the following +``snapcraft.yaml`` snippets for ``core22``: + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + build-for: [amd64] + + package-repositories: + - type: apt + formats: [deb] + architectures: [i386] + components: [main] + suites: [jammy] + key-id: F23C5A6CF475977595C89F51BA6932366A755776 + url: https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu + + parts: + mypart: + stage-packages: + - libpython3.11-minimal:i386 + +This is supported for related architectures. A snap built for ``amd64`` can +stage ``i386`` packages and a snap built for ``i386`` can stage ``amd64`` +packages. Similarly, a snap built for ``arm64`` can stage ``armhf`` packages +and a snap built for ``armhf`` can stage ``amd64`` packages. diff --git a/docs/howto/index.rst b/docs/howto/index.rst index 436a1880c1..1da05de317 100644 --- a/docs/howto/index.rst +++ b/docs/howto/index.rst @@ -5,3 +5,5 @@ How-to guides .. toctree:: :maxdepth: 1 + + architectures diff --git a/docs/reference/architectures.rst b/docs/reference/architectures.rst new file mode 100644 index 0000000000..fef00ad2aa --- /dev/null +++ b/docs/reference/architectures.rst @@ -0,0 +1,233 @@ +Architectures +============= + +snapcraft.yaml +-------------- + +The :doc:`architectures how-to` provides examples of how +to use the ``architectures`` keyword. + +core22 +^^^^^^ + +The root keyword ``architectures`` defines a list of ``build-on->build-for`` +pairs with the following syntax: + +.. code-block:: yaml + + architectures: + - build-on: [, ] + build-for: [] + - build-on: [] + build-for: [] + ... + +See :ref:`here` for a list of supported architectures. + +Data types +"""""""""" + +If the value is a single item, it can be written as a single element list or a +scalar. For example: + +.. code-block:: yaml + + architectures: + - build-on: amd64 + build-for: arm64 + +is equivalent to: + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + build-for: [arm64] + +.. note:: + + Using a list is the recommended syntax. Scalars are not recommended. + +``build-on`` +"""""""""""" + +The ``build-on`` field is required and can contain multiple architectures. + +.. _reference-build-for: + +``build-for`` +""""""""""""" + +The ``build-for`` field is optional and should be a single element list. If it +is not defined, the ``build-for`` will be set the ``build-on`` for each build +in the :ref:`build plan`. + +``build-for: [all]`` is a special keyword to denote an architecture-independent +snap. If the ``all`` keyword is used, no other ``build-on/build-for`` pairs can +be defined. See :ref:`this page` to learn how to +use the ``all`` keyword. + +``all`` cannot be used for ``build-on``. + +The same architecture cannot be defined in multiple ``build-for`` entries. + +Shorthand format +"""""""""""""""" + +As an alternative to the explicit format described above, a shorthand format +can be used for simple ``build-on/build-for`` pairs. The following shorthand: + +.. code-block:: yaml + + architectures: [amd64, arm64] + +is equivalent to: + +.. code-block:: yaml + + architectures: + - build-on: [amd64] + build-for: [amd64] + - build-on: [arm64] + build-for: [arm64] + +The explicit and shorthand format cannot be mixed. + +core20 +^^^^^^ + +The above syntax and rules for ``core22`` apply for ``core20`` except that +``run-on`` is used in place of ``build-for``. Additionally, ``core20`` supports +multiple architectures in the ``run-on`` field, which will create +multi-architecture snaps. + +Project variables +----------------- + +core22 +^^^^^^ + ++----------------------------------+-------------------------------------------+ +| Project variable | Description | ++==================================+===========================================+ +| ``CRAFT_ARCH_BUILD_FOR`` | The architecture of the platform the snap | +| | is built for. | ++----------------------------------+-------------------------------------------+ +| ``CRAFT_ARCH_BUILD_ON`` | The architecture of the platform the snap | +| | is built on. | ++----------------------------------+-------------------------------------------+ +| ``CRAFT_ARCH_TRIPLET_BUILD_FOR`` | The architecture triplet of the platform | +| | the snap is built for. | ++----------------------------------+-------------------------------------------+ +| ``CRAFT_ARCH_TRIPLET_BUILD_ON`` | The architecture triplet of the platform | +| | the snap is built on. | ++----------------------------------+-------------------------------------------+ +| ``CRAFT_ARCH_TRIPLET`` | deprecated: use | +| | ``CRAFT_ARCH_TRIPLET_BUILD_FOR`` instead | ++----------------------------------+-------------------------------------------+ +| ``CRAFT_TARGET_ARCH`` | deprecated: use ``CRAFT_ARCH_BUILD_FOR`` | +| | instead | ++----------------------------------+-------------------------------------------+ + +core20 +^^^^^^ + +``core20`` snaps use the terminology ``run-on`` in the ``architectures`` field +in ``snapcraft.yaml``. The project variables and documentation use the +preferred term ``build-for``. + ++--------------------------------------+---------------------------------------+ +| Project variable | Description | ++======================================+=======================================+ +| ``SNAPCRAFT_ARCH_BUILD_FOR`` | The architecture of the platform the | +| | snap is built for. | ++--------------------------------------+---------------------------------------+ +| ``SNAPCRAFT_ARCH_BUILD_ON`` | The architecture of the platform the | +| | snap is built on. | ++--------------------------------------+---------------------------------------+ +| ``SNAPCRAFT_ARCH_TRIPLET_BUILD_FOR`` | The architecture triplet of the | +| | platform the snap is built for. | ++--------------------------------------+---------------------------------------+ +| ``SNAPCRAFT_ARCH_TRIPLET_BUILD_ON`` | The architecture triplet of the | +| | platform the snap is built on. | ++--------------------------------------+---------------------------------------+ +| ``SNAPCRAFT_ARCH_TRIPLET`` | The architecture triplet specified by | +| | ``--target-arch``. If a target arch | +| | is not provided, then the | +| | architecture of the build-on platform | +| | is used. | ++--------------------------------------+---------------------------------------+ +| ``SNAPCRAFT_TARGET_ARCH`` | The architecture specified by | +| | ``--target-arch``. If a target arch | +| | is not provided, then the | +| | architecture of the build-on platform | +| | is used. | ++--------------------------------------+---------------------------------------+ + +``SNAPCRAFT_ARCH_BUILD_FOR`` and ``SNAPCRAFT_ARCH_TRIPLET_BUILD_FOR`` are not +available in any of the following scenarios: + +* when the build-for architecture is not in the list of supported architectures +* when building a multi-architecture snap + +.. _supported-architectures: + +Supported architectures +----------------------- + +Supported locally +^^^^^^^^^^^^^^^^^ + +The following architectures can be used when building a snap locally. + +* amd64 +* arm64 +* armhf +* i386 +* powerpc +* ppc64el +* riscv64 +* s390x + +.. _supported-architectures-launchpad: + +Supported by Launchpad +^^^^^^^^^^^^^^^^^^^^^^ + +The following architectures are supported by Launchpad for remote building. + +* amd64 +* arm64 +* armhf +* ppc64el +* s390x + +Environment variables and command line arguments +------------------------------------------------ + +core22 +^^^^^^ + +The command line argument ``--build-for=`` or environment variable +``SNAPCRAFT_BUILD_FOR=`` is used to build a single snap package for an +architecture. It selects a single ``build-on->build-for`` pair from the build +plan. It does not allow building a snap not defined by the build plan. + +The command line argument takes priority over the environment variable. + +See :ref:`build-plans` for more information on how build plans are created. + +core20 +^^^^^^ + +``--target-arch=`` is used for cross-compiling in ``core20``. It adds +repositories for the target arch, which are used for ``stage-packages``. The +target arch does not need to be listed in the ``snapcraft.yaml`` +``architectures`` keyword. + +The ``--target-arch`` argument can only be used in destructive mode and with +``--enable-experimental-target-arch`` or the environment variable +``SNAPCRAFT_ENABLE_EXPERIMENTAL_TARGET_ARCH``. + +The full usage is +``snapcraft --destructive-mode --enable-experimental-target-arch --target-arch=``. diff --git a/docs/reference/index.rst b/docs/reference/index.rst index 1fd62f9388..d3cfd3a7a3 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -6,6 +6,7 @@ Reference .. toctree:: :maxdepth: 1 + architectures commands Indices and tables