Hi Sean,

thank you for your review. Please excuse the delay of our response. I 
happened to run into Nattie again and she helped me a lot in improving 
the text in combination with your remarks.  Also Colin reviewed it and 
Stefano Rivera helped on a few paragraphs.

On Sun, Jun 01, 2025 at 11:12:31AM +0100, Sean Whitton wrote:
> > +``Build-Profiles``
> > +~~~~~~~~~~~~~~~~~~
> > +
> > +Specifies the condition for which that binary package does or does not
> > +build.
> 
> ... when it doesn't have any FTBFS bugs? :)
> 
> How about
> 
>     Build profiles are <succinct description>.  This field expresses
>     just when the binary package builds, with respect to active and
>     inactive build profiles.  This condition is expressed using the
>     `restriction formula syntax <s-restrictions>` ...

We found the paragraph hard to read, agreed with your criticism and 
significantly rephrased it.

> > + If a binary package stanza in a source package template control file
> > + is annotated with a ``Build-Profiles`` field, then that binary
> > + package is generated if and only if the condition expressed by the
> > + disjunctive normal form expression evaluates to true.
> 
> I know what disjunctive normal form means but I don't think Policy
> defines it and I'm not sure it is necessary to mention it here.
> Why not just say
> 
>     If a binary package stanza in a source package template control file
>     has a ``Build-Profiles`` field, then that binary package is
>     generated if and only if the condition expressed by the field's
>     value holds.

We do explain disjuntive normal form later. Indeed there is little value 
in mentioning it here.

> > +
> > --- a/policy/ch-relationships.rst
> > +++ b/policy/ch-relationships.rst
> > @@ -51,22 +51,76 @@ For example, a list of dependencies might appear as:
> >      Version: 1.3.17-1
> >      Depends: libc6 (>= 2.2.1), default-mta | mail-transport-agent
> >
> > -Relationships may be restricted to a certain set of architectures. This
> > -is indicated in brackets after each individual package name and the
> > -optional version specification. The brackets enclose a non-empty list of
> > -Debian architecture names in the format described in
> > -:ref:`s-arch-spec`, separated by whitespace. Exclamation
> > -marks may be prepended to each of the names. (It is not permitted for
> > -some names to be prepended with exclamation marks while others aren't.)
> > +.. _s-restrictions
> > +
> > +Restrictions
> > +~~~~~~~~~~~~
> > +
> > +Relationships may be restricted to a certain set of architectures or
> > +build profiles. This is indicated in brackets after each individual
> > +package name and the optional version specification. There are two types
> > +of restrictions.  Architecture restriction lists are enclosed in a pair
> > +of opening and closing rectangular brackets, specifics of which are
> > +`described below <s-architecture-restrictions>`.
> 
> "*the* specifics of which"

Yes, thanks

> > +Build profile
> > +restriction lists are enclosed by pairs of opening and closing angular
> > +brackets and are further `described below as well
> > +<s-profile-restrictions>`.
> 
> s/further described below as well/also described in detail below/
> 
> Also, I'd suggest a paragraph break after this sentence.

Yes, both, thanks.

> > +There can only be at most one architecture
> > +restriction list per package
> 
> Per binary package, right?

I found that ambiguous as well and went for "dependency alternative" 
instead. Hope that also makes sense to you and others.

> > but there can be more than one build
> > +profile restriction list.  One or more build profile restriction lists
> > +form a build profile restriction formula.  If both an architecture
> > +restriction list as well as a build profile restriction formula are to
> > +be applied to a dependency, then the architecture restriction list must
> > +come before the build profile restriction formula.
> 
> "... must come before the build profile restriction formula *in the field
> value*."

Yes, thanks.

> > The non-empty set of
> > +terms enclosed in either rectangular or angular brackets are separated
> > +by whitespace.
> 
> This doesn't make sense -- the singular non-empty set has a plural "are
> separated".  What do you mean?

It's the set that should have been plural and the sets that should be 
separated. Thank you.

> > +Architecture restriction lists and build profile restriction formulas
> > +are evaluated differently but they both evaluate to a boolean decision
> > +as to whether the dependency that the restriction was applied to is
> > +being kept or should be ignored.
> 
> "as to whether the dependency to which the restriction is applied should
> be kept or ignored."

Rewritten instead.

> > For a dependency to be ignored, it is
> > +enough for either the architecture restriction list or the build profile
> > +restriction formula to evaluate to false. If the dependency with a
> > +restriction is part of a set of alternatives, the alternative for which
> > +either restriction does not apply is ignored and the other alternatives
> > +remain for evaluation.
> 
> "remain for evaluation" seems vague.
> 
> I think you are trying to capture how a system consuming these files is
> allowed to consider only the first alternative?
> 
> Could you just say that each restriction applies separately to each
> alternative?

You are not the only one being confused. Rewritten. Thanks.

> > +A dependency with an architecture restriction list or build profile
> > +restriction formula in one of the build relationship fields
> > +(``Build-Depends``, ``Build-Depends-Indep``, ``Build-Depends-Arch``,
> > +``Build-Conflicts``, ``Build-Conflicts-Indep`` and
> > +``Build-Conflicts-Arch``) which does not not match will result in that
> > +build dependency to be ignored. If the dependency is used for binary
> > +relationship fields and the ``Built-Using`` field, the architecture and
> > +build profile restriction syntax is only supported in the source package
> > +template control file ``debian/control``. When the corresponding binary
> > +package control file is generated, the relationship will either be
> > +omitted or included with neither the architecture restriction nor the
> > +build profile restriction formula.
> 
> This is very dense, let me suggest something like
> 
>     The sense in which a dependency is ignored depends on the field in
>     which the restriction appears.  A restriction in one of the build
>     relationship fields (``Build-Depends``...) that does not match means
>     that the build-dependency is not required to be satisfied for the
>     package to be built.  For example, a restriction specifying that
>     building a package on a certain architecture requires an additional
>     dependency doesn't match on other architectures, meaning the package
>     can be built there without first installing that additional
>     dependency.
> 
>     A restriction appearing in a field describing relationships between
>     binary packages (such as ``Depends``) must appear in only the source
>     package template control file ``debian/control``.  The dependency is
>     ignored in the sense that it will not appear in the corresponding
>     binary package control file if the restriction does not match [right?].

Thank you. Accepted with minor changes.

> > +Build profile restriction formulas
> > +^^^^^^^^^^^^^^^^^^^^^^^^^^^
> > +
> > +In contrast to architecture restriction lists, of which at most one can
> > +be added to a dependency, build profile restriction formulas consist of
> > +multiple restriction lists.
> 
> It would be good to rewrite this using must/must
> not/required/prohibited -- the Policy normative magic words.

Significantly rephrased.

> > Each list is enclosed in angular brackets
> > +(less than sign and greater than sign). Each of the space separated
> > +terms of a restriction list is the optionally negated name of a build
> > +profile.
> 
> "Each of the space-separated terms of a restriction list is the
> possibly-negated name of a build profile."

Yes, thanks.

> > Negation happens by prefixing the name with an exclamation
> > +mark. In contrast to architecture restriction lists, positive and
> > +negative terms can be mixed.
> 
> "may be mixed" to use the Policy normative magic words.

Yes, thanks.

> > +One or more restriction lists form a restriction formula. A restriction
> > +formula can be evaluated as a disjunctive normal form expression.  This
> > +is, each term within a restriction list is AND-ed together while the
> > +restriction lists in a restriction formula are OR-ed together. This also
> > +means that the order of terms within restriction lists and the order of
> > +restriction lists within a restriction formula does not matter.  A
> > +profile name in a term evaluates to "true" if the profile with the same
> > +name was set for the build and to "false" otherwise.  Optional negation
> > +with an exclamation mark is applied before evaluating conjunctions and
> > +disjunctions.
> 
> I think that the sense of "set for the build" should be explained.
> Indeed, it would be good to just describe what build profiles are before
> getting into how they are evaluated.  What sort of things are they used
> for?  How do they help with bootstrapping?
> Probably you want to refer to "debian/rules and DEB_BUILD_PROFILES" and
> put the general introduction there.

The reference definitely makes sense and I readily added it. We further 
rephrased it to improve readability, but I disagree about going into 
bootstrapping here as build profiles are a wider concept applicable way 
beyond bootstrapping.

> > +``debian/rules`` and ``DEB_BUILD_PROFILES``
> > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > +
> > +The environment variable ``DEB_BUILD_PROFILES`` may be set to a space
> > +separated unordered list of build profiles that are active for this
> > +build. All build profiles not listed in that variable are considered
> > +disabled and therefore no build profiles are enabled by default.  The
> > +meaning of the following build profiles has been standardized:
> 
> Please rewrite this intro using the normative words.

I was struggling to see how this is not normative. Nevertheless, we 
found it difficult to read and rephrased it hoping that you may find it 
more normative now.

> Policy can standardise them, here.

I'm not sure what you want me to change here.

> > +``nocheck``
> > +    This profile extends the meaning of the ``nocheck`` tag in
> > +    ``DEB_BUILD_OPTIONS`` and may only be enabled in combination with
> > +    setting that tag. In addition to disabling build-time testing, it
> > +    allows skipping the installation of dependencies required for those
> > +    tests during the build. Note that neither the profile nor the tag
> > +    may functionally change the emitted binary packages nor the set of
> > +    binary packages. If tests happen to be installed into a binary
> > +    package, consider supporting the ``noinsttest`` build profile.
> > +
> > +``noinsttest``
> > +    Disable binary packages consisting entirely of automated tests,
> > +    manual tests, example/demo programs and test tools. Other packages
> > +    may not functionally change when this profile is enabled. Note that
> > +    dependencies used for building these tests often con only be dropped
> > +    when enabling both the ``noinsttest`` and the ``nocheck`` build
> > +    profile and therefore such dependencies tend to be conditional to
> > +    ``<!nocheck> <!noinsttest>``.
> 
> These should probably be rewritten using the normative words, too.

Rephrased, thanks.

As much as we may continue word smithing this text, I suggest that the 
perfect is the enemy of the good. By now, not having this text in policy 
seems worse to me than having a buggy description of build profiles.

Helmut
>From 17d3b9a27b5edb707d1ef1e170f6c3a6f5df76a6 Mon Sep 17 00:00:00 2001
From: Johannes Schauer Marin Rodrigues <[email protected]>
Date: Sat, 29 Mar 2025 23:04:56 +0100
Subject: [PATCH] document build profiles

Closes: #757760

Co-Authored-by: Helmut Grohne <[email protected]>
Co-Authored-by: Jochen Sprickerhof <[email protected]>
Co-Authored-by: Nattie Mayer-Hutchings <[email protected]>
Reviewed-by: Colin Watson <[email protected]>
---
 policy/ch-controlfields.rst |  19 ++++++
 policy/ch-relationships.rst | 131 +++++++++++++++++++++++++++++++-----
 policy/ch-source.rst        |  60 +++++++++++++++++
 3 files changed, 195 insertions(+), 15 deletions(-)

diff --git a/policy/ch-controlfields.rst b/policy/ch-controlfields.rst
index 9f06cc9..b492790 100644
--- a/policy/ch-controlfields.rst
+++ b/policy/ch-controlfields.rst
@@ -152,6 +152,8 @@ The fields in the binary package stanzas are:
 
 -  :ref:`Package-Type <s-f-Package-Type>`
 
+-  :ref:`Build-Profiles <s-f-Build-Profiles>`
+
 The syntax and semantics of the fields are described below.
 
 These fields are used by ``dpkg-gencontrol`` to generate control files
@@ -1251,6 +1253,23 @@ or set it to ``binary-targets`` if it has been requested to test
 whether the package it builds correctly implements the fall-back for
 legacy builders.
 
+``Build-Profiles``
+~~~~~~~~~~~~~~~~~~
+
+This field occurs in the binary package sections of a source template
+control file. It expresses whether the binary package is being
+produced, given a set of enabled build profiles.  The condition uses
+the same `restriction formula syntax <s-restrictions>` from the
+``Build-Depends`` field.
+
+If a binary package stanza in a source package template control file
+does not contain a ``Build-Profiles`` field, then it implicitly means
+that it builds unconditionally with respect to build profiles.  If a
+binary package stanza in a source package template control file is
+annotated with a ``Build-Profiles`` field, then that binary package is
+generated if and only if the condition expressed by field's value
+evaluates to true.
+
 Remarks
 ^^^^^^^
 
diff --git a/policy/ch-relationships.rst b/policy/ch-relationships.rst
index fb9dae8..dfce035 100644
--- a/policy/ch-relationships.rst
+++ b/policy/ch-relationships.rst
@@ -51,22 +51,73 @@ For example, a list of dependencies might appear as:
     Version: 1.3.17-1
     Depends: libc6 (>= 2.2.1), default-mta | mail-transport-agent
 
-Relationships may be restricted to a certain set of architectures. This
-is indicated in brackets after each individual package name and the
-optional version specification. The brackets enclose a non-empty list of
-Debian architecture names in the format described in
-:ref:`s-arch-spec`, separated by whitespace. Exclamation
-marks may be prepended to each of the names. (It is not permitted for
-some names to be prepended with exclamation marks while others aren't.)
+.. _s-restrictions
+
+Restrictions
+~~~~~~~~~~~~
+
+Relationships may be restricted to a certain set of architectures or
+build profiles. This is indicated in brackets after each individual
+package name and the optional version specification. There are two types
+of restrictions.  Architecture restriction lists are enclosed in a pair
+of opening and closing square brackets, the specifics of which are
+`described below <s-architecture-restrictions>`. Build profile
+restriction lists are enclosed by pairs of opening and closing angle
+brackets and are also `described in detail below
+<s-profile-restrictions>`.
+
+There can be at most one architecture restriction list per dependency
+alternative, but there can be more than one build profile restriction
+list. One or more build profile restriction lists form a build profile
+restriction formula. If both an architecture restriction list and a
+build profile restriction formula are to be applied to a dependency
+alternative, then the architecture restriction list must come before the
+build profile restriction formula in the field value. The non-empty sets
+of terms enclosed in either square or angle brackets must be separated
+by whitespace.
+
+Architecture restriction lists and build profile restriction formulas
+are evaluated differently. Both can be evaluated to booleans, given a
+host architecture and a set of enabled build profiles. Their results
+indicate whether the dependency alternative should be considered or
+ignored. For a dependency alternative to be considered, the architecture
+restriction list (if any) and the build profile restriction formula (if
+any) must evaluate to true. A dependency is considered satisfied if none
+of its alternatives apply.
+
+The sense in which a dependency is ignored depends on the field in which
+the restriction appears.  A restriction in one of the build relationship
+fields (``Build-Depends``...) that does not match means that the
+build-dependency is not required to be satisfied for the package to be
+built.  For example, a restriction might specify that building a package
+on a certain architecture requires an additional dependency; such a
+restriction does not match on other architectures, meaning the package
+can be built there without first installing that additional dependency.
+
+A restriction appearing in a field describing relationships between
+binary packages (such as ``Depends``) must only appear in the source
+package template control file ``debian/control``.  The dependency is
+ignored, in the sense that it will not appear in the corresponding
+binary package control file, if the restriction does not match.
+
+.. _s-architecture-restrictions
+
+Architecture restrictions
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Architecture restriction lists consist of Debian :ref:`architecture
+specification strings <s-arch-spec>`.  Exclamation marks may be
+prepended to each of the names. (It is not permitted for some names to
+be prepended with exclamation marks while others aren't.)
 
 For build relationship fields (``Build-Depends``,
 ``Build-Depends-Indep``, ``Build-Depends-Arch``, ``Build-Conflicts``,
 ``Build-Conflicts-Indep`` and ``Build-Conflicts-Arch``), if the current
 Debian host architecture is not in this list and there are no
 exclamation marks in the list, or it is in the list with a prepended
-exclamation mark, the package name and the associated version
-specification are ignored completely for the purposes of defining the
-relationships.
+exclamation mark, the restriction list evaluates to false.  This means
+that the package name and the associated version specification are
+ignored completely for the purposes of defining the relationships.
 
 For example:
 
@@ -134,11 +185,61 @@ is equivalent to ``foo`` on architectures using the Linux kernel and any
 cpu, ``bar`` on architectures using any kernel and an i386 cpu, and
 ``baz`` on any architecture using a kernel other than Linux.
 
-Note that the binary package relationship fields such as ``Depends``
-appear in one of the binary package stanzas of the template control file,
-whereas the build-time relationships such as ``Build-Depends`` appear in
-the source package stanza of the template control file (which is the first
-section).
+.. _s-profile-restrictions
+
+Build profile restriction formulas
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A build profile restriction formula is a sequence of build profile
+restriction lists. In contrast, there must not be more than one
+architecture restriction list per dependency alternative.  Each list
+is enclosed in angle brackets (less than sign and greater than
+sign). Each of the space-separated terms of a restriction list is the
+possibly-negated name of a build profile. Negation happens by
+prefixing the name with an exclamation mark. Unlike architecture
+restriction lists, positive and negative terms may be mixed.
+
+A restriction formula may be evaluated as a disjunctive normal form
+expression, given a set of :ref:`enabled build profiles
+<s-rules-build-profiles>`. In other words, each term within a
+restriction list is AND-ed together while the restriction lists in a
+restriction formula are OR-ed together. Therefore, the order of terms
+within restriction lists and the order of restriction lists within a
+restriction formula does not matter. A profile name in a term
+evaluates to "true" if the profile with its name is enabled for the
+build and to "false" otherwise. The result may be negated by
+prefixing the profile name with an exclamation mark.
+
+In the following example, the package would depend on ``foo`` when built
+for ``i386`` or 32-bit ARM architectures and if one of the ``nocheck``
+and ``cross`` profiles is not enabled by the builder:
+
+::
+
+    Build-Depends: foo (>= 1.0) [i386 any-arm] <!nocheck> <!cross>, bar
+
+In the following example, the source package would build-depend on
+``foo`` only if both the ``nocheck`` profile and the ``cross`` profile
+are enabled at the same time.
+
+::
+
+    Build-Depends: foo <nocheck cross>
+
+In the next example, the source package would build-depend on ``foo`` if
+``nopython`` is disabled and at least one of ``nocheck`` and
+``nopython`` is disabled.
+
+::
+
+    Build-Depends: foo <!nopython !nocheck> <!nopython !noinsttest>
+
+The last example can also be rewritten to this alternative form which is
+equal in meaning:
+
+::
+
+    Build-Depends: foo <!nopython !nocheck>, foo <!nopython !noinsttest>
 
 .. _s-binarydeps:
 
diff --git a/policy/ch-source.rst b/policy/ch-source.rst
index a2aa4cc..fed0468 100644
--- a/policy/ch-source.rst
+++ b/policy/ch-source.rst
@@ -621,6 +621,66 @@ order to make it work for your package.
             # Code to run the package test suite.
     endif
 
+.. _s-rules-build-profiles
+
+``debian/rules`` and ``DEB_BUILD_PROFILES``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If the ``DEB_BUILD_PROFILES`` environment variable is defined during the
+build of a source package, it specifies which build profiles are
+enabled. Its value is a space-separated, unordered list of enabled build
+profile names. By default, no build profiles are enabled. The meaning of
+the following build profiles has been standardized:
+
+``nocheck``
+    This profile extends the meaning of the ``nocheck`` tag in
+    ``DEB_BUILD_OPTIONS`` and must not be enabled unless combined with
+    that tag. In addition to disabling build-time testing, it allows
+    skipping the installation of dependencies required for those tests
+    during the build. Note that enabling the profile or the tag must not
+    functionally change the emitted binary packages and also must not
+    change the set of binary packages being produced. If tests happen to
+    be installed into a binary package, consider supporting the
+    ``noinsttest`` build profile.
+
+``noinsttest``
+    This profile disables the emission of binary packages consisting
+    entirely of automated tests, manual tests, example/demo programs,
+    and test tools. Other packages must not functionally change when
+    this profile is enabled. Note that in many cases, it is only
+    possible to drop such dependencies used for building when enabling
+    both the ``noinsttest`` and the ``nocheck`` build profile
+    concurrently.  Therefore such dependencies tend to be conditional to
+    ``<!nocheck> <!noinsttest>``.
+
+A larger list of commonly used build profiles can be found in the `Build
+Profile Spec
+<https://wiki.debian.org/BuildProfileSpec#Registered_profile_names>`_.
+
+The following makefile snippet is an example of how to enable python for
+all builds except when the package is built with the ``nopython`` build
+profile active.
+
+.. code-block:: Makefile
+
+    ifneq ($(filter nopython,$(DEB_BUILD_PROFILES)),)
+        # nopython build profile was activated -- disable python
+        CONFIGURE_SWITCHES += --disable-python
+    else
+        CONFIGURE_SWITCHES += --enable-python
+    endif
+
+Alternatively, one may defer the evaluation of restriction formulas in
+general (including architecture restrictions) to ``debhelper``.
+
+.. code-block:: Makefile
+
+    ifneq ($(filter foo,$(shell dh_listpackages)),)
+        # foo is being built
+        CONFIGURE_SWITCHES += --enable-foo
+    else
+        CONFIGURE_SWITCHES += --disable-foo
+    endif
 
 .. _s-debianrules-gainrootapi:
 
-- 
2.47.3

Reply via email to