Differences between revisions 2 and 94 (spanning 92 versions)
Revision 2 as of 2013-08-12 16:50:49
Size: 4460
Editor: josch
Comment: added Profile field description
Revision 94 as of 2015-07-27 14:23:27
Size: 18566
Editor: ?HelmutGrohne
Comment: dh-exec support. Big thanks to Gergely Nagy!
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
<<TableOfContents()>>

== Document status ==

Preliminary support of this spec was implemented in.

|| '''program''' || '''version''' || '''bug''' || '''vcs commit''' ||
|| dpkg || 1.17.14 || DebianBug:760158 || [[http://anonscm.debian.org/cgit/dpkg/dpkg.git/commit/?id=98956c26a2d8039b8ec66231910fc9418329c09b|git:8329c09b]] ||
|| sbuild || 0.65.0-1 || DebianBug:731798 || ||
|| apt || 1.0.9.3 || DebianBug:763721 || [[http://anonscm.debian.org/cgit/apt/apt.git/commit/?id=ac81c0f9b79351258d3a29212f7fda312e5afeb5|git:2e5afeb5]] ||
|| python-apt (dep on libapt) || 0.9.3.6 || DebianBug:744243 || [[http://anonscm.debian.org/cgit/apt/python-apt.git/commit/?id=c793c367d32d5a5adc220268ac4a0144419ac4d0|git:419ac4d0]], [[http://anonscm.debian.org/cgit/apt/python-apt.git/commit/?id=5b20a0c8bd6260b01f42ea402a7c4118921a75d9|git:921a75d9]] ||
|| debhelper || 9.20141010 || DebianBug:763766 || ||
|| cdbs || || DebianBug:772788 || ||
|| pbuilder || 0.215+nmu4 || DebianBug:740577 || [[https://anonscm.debian.org/cgit/pbuilder/pbuilder.git/commit/?id=19152b3f7db286f75de1b551010eb472260e0749|git:19152b3f]] ||
|| lintian || 2.5.29 || DebianBug:763773 || ||
|| dose3 || 3.3~beta1-1 || || ||
|| wanna-build || || || ||
|| dak || || DebianBug:744246 || ||
|| devscripts (mk-build-deps) || || || ||
|| python-debian || 0.1.23 || || [[https://anonscm.debian.org/cgit/pkg-python-debian/python-debian.git/commit/?id=3fa8a7b93707e9f6d8b1ee575b2b7a9a718fa762|git:718fa762]], [[https://anonscm.debian.org/cgit/pkg-python-debian/python-debian.git/commit/?id=7ea75aeeee9b16772cf482d3909b6caa118fa762|git:118fa762]] ||
|| libconfig-model-dpkg-perl || 2.057 || DebianBug:763772 || ||
|| augeas || || || ||
|| haskell-debian || || || ||
|| dh-exec || 0.15 || DebianBug:793736 || ||
|| autopkgtest || || DebianBug:787093 || [[http://anonscm.debian.org/cgit/autopkgtest/autopkgtest.git/commit/?id=fd343efd5f502592cb85c6b26d1263f8cbbbc950|git:fd343efd]], [[http://anonscm.debian.org/cgit/autopkgtest/autopkgtest.git/commit/?id=fd343efd5f502592cb85c6b26d1263f8cbbbc950|git:fd343efd5]] ||

{{{#!wiki comment/dashed

For historical purposes, here is the list of versions, bugs and commits that
implemented the original proposal with only one <> block, namespaces and
a complicated resolution mechanic:

|| '''package''' || '''version''' || '''bug''' || '''vcs commit''' ||
|| dpkg || 1.17.2 || DebianBug:661538 || [[http://anonscm.debian.org/cgit/dpkg/dpkg.git/commit/?id=7662e0937bb064a0754d12605d80a96a17e2aadf|git:7662e093]] [[http://anonscm.debian.org/cgit/dpkg/dpkg.git/commit/?id=c87941de954281a8aa66d032c85657f64bfe4dce|git:c87941de]]||
|| apt || 0.9.16.1 || DebianBug:661537 || [[http://anonscm.debian.org/cgit/apt/apt.git/commit/?id=565ded7b65240b25ad8551789ac388c8ce72b1f4|git:565ded7b]] [[http://anonscm.debian.org/cgit/apt/apt.git/commit/?id=ce7f128c020e1347f91c6074238fc5da58c5df71|git:ce7f128c]] ||
|| python-apt || 0.9.3.6 || DebianBug:744243 || [[http://anonscm.debian.org/gitweb/?p=apt/python-apt.git;a=commit;h=c793c367d32d5a5adc220268ac4a0144419ac4d0|git:c793c367]]||
|| debhelper || 9.20140227 || || [[http://anonscm.debian.org/cgit/debhelper/debhelper.git/commit/?id=f16d0915b10ff9ef0b0826ae896aaccd6f3ad84f|git:f16d0915b]] ||
|| lintian || 2.5.22 || DebianBug:740607 || [[http://anonscm.debian.org/cgit/lintian/lintian.git/commit/?id=1f8821b8b62205aa36eadbd799faad443cfa8b85|git:1f8821b8]] ||
|| dose3 || 3.1 (partial) || || [[https://gforge.inria.fr/plugins/scmgit/cgi-bin/gitweb.cgi?p=dose/dose.git;a=commitdiff;h=e8c0a518c56560e0bef5d81f0ff36450d7c6743b|git:e8c0a518]] [[https://gforge.inria.fr/plugins/scmgit/cgi-bin/gitweb.cgi?p=dose/dose.git;a=commitdiff;h=6268adba6929275e17771b185fafb259410503db|git:6268adba]] ||
|| libconfig-model-dpkg-perl || 2.051 || || [[http://anonscm.debian.org/cgit/pkg-perl/packages/libconfig-model-dpkg-perl.git/commit/?id=373cb3d014288ea73efccb96ff7f9c37f738538c|git:373cb3d0]] ||
}}}
Line 3: Line 45:
For some compilation scenarios it is required to build-depend on a different set of binary packages than specified in the Build-Depends line. The two most important scenarios are:

 * Bootstrapping (for breaking build dependency cycles) and
For some compilation scenarios it is required to build-depend on a different
set of binary packages than specified in the Build-Depends line. The two most
important scenarios are:

 * [[https://wiki.debian.org/DebianBootstrap|Bootstrapping]] (for breaking build dependency cycles) and
Line 8: Line 52:
We propose an extension of the Build-Depends field syntax. This extension allows to mark build dependencies as being needed or not needed when a specific profile is activated. We also propose the introduction of a new field called "Profile" which aids in marking binary packages as being built or not built while a certain profile is activated or having been built with a certain set of profiles activated.

Build profiles can be activated by setting the environment variable FIXME or by using the FIXME option with dpkg-buildpackage. More than one profile can be activated at a time.

Binary packages which were built with one or more profiles activated will have these profiles appended to their version number.

== Build-Depends syntax extension ==

We propose a syntax which in practice looks as follows:

{{{
Build-Depends: foo (>= 1.0) [i386 arm] [!profile.stage1], bar
}}}

Our proposal extends the architecture restriction syntax in square brackets from a single disjunctive list of architectures to a conjunctive list of logical disjunctions (a conjunctive normal form expression). Each clause of the conjunction is enclosed in square brackets. Every literal inside square brackets is a logical disjunction. The above example would therefore make the source package build depend on foo if the host architecture is either i386 or amd64 and if the profile named "stage1" is not active.

Every literal in a disjunction follows the following regular expression:

{{{
([a-z][a-z0-9-]*)\.([a-z][a-z0-9-]*)
}}}

The first group is called a namespace and we propose the namespace "profile" to support build profiles. The second group is called a label and for the "profile" namespace we propose as initial labels "stage1", "stage2" and "cross".

The other already existing namespace would be "arch" for architectures. For backwards compatibility it is allowed to specify architecture labels without the "arch" namespace in front. The following is therefore equivalent:

{{{
Build-Depends: foo [i386 arm64]
Build-Depends: foo [arch.i385 arch.arm64]
}}}

These literals can be negated by using an exclamation mark as a prefix. We propose that literals inside a disjunction can individually be negated or not. To provide backwards compatibility, a disjunction which only contains architecture lables without their "arch" namespace must either be all negated or all positive. The following statements would therefore be legal:

{{{
Build-Depends: foo [profile.stage1 !profile.cross]
}}}
        
But the following would be illegal as it was before:

{{{
Build-Depends: foo [i386 !amd64]
}}}
        
We propose that literals of different namespaces can be mixed within a disjunction. Therefore, the following would be legal:

{{{
Build-Depends foo [arch.i386 !profile.cross]
}}}

== The Profile field ==

The meaning of the Profile field is similar (but orthogonal) to the Architecture field and also (just like the Architecture field) its meaning differs depending on where it is used.

=== debian/control binary package stanza ===

Here, the content of the Profile field specifies the list of profiles for which that binary package does or does not build. This list can either be all positive or all negative. Entries are negated by using an exclamation mark as a prefix.

{{{
Profile: !cross !stage1
}}}

=== *.changes and Packages file ===

Here, the content of the Profile field specifies the list of profiles for which that binary or source package was built for. It is also possible to identify binary packages which were built with one or more profiles activated through their version number.

=== Sources file ===

Just as the Architecture field in a Sources file, the Profile field in a Sources file is automatically generated and specifies a list of profiles which that source package supports. It is therefore the union of the profile names given in the Build-Depends field and the profile names given in the Profile field in the binary package stanzas in the debian/control file.
This specification describes an extension of the Build-Depends field syntax.
The extensions allow the marking of build dependencies as being needed or not
needed when one or more build profiles are activated. It also defines a new
field called "Build-Profiles" which, depending on the context marks binary
packages as being built or not built with a certain set of build profiles
activated or marks binary packages as having been built with a certain set of
build profiles activated.

Build profiles can be activated by setting the environment variable
`DEB_BUILD_PROFILES` or by using the -P option with dpkg-buildpackage (or -o
Apt::Build-Profiles for apt, or --profiles in sbuild). More than one build
profile can be activated at a time. Multiple profiles are specified by
separating them with commas in commandline arguments and by separating them
with spaces in the `DEB_BUILD_PROFILES` environment variable. Some common
profile names are `"stage1"`, `"stage2"`, `"nocheck"`, `"nodoc"`,
`"nobiarch"` and `"cross"`.

== Build-Depends syntax extension (restriction formulas) ==

An example demonstrating the restriction formula syntax for build profiles:

{{{
Build-Depends: foo (>= 1.0) [i386 arm] <!stage1> <!cross>, bar
}}}

This specification introduces a new pair of brackets (using `<` as the opening
and `>` as the closing bracket) to be used after the architecture qualification
list. The `<` and `>` brackets enclose a whitespace separated list of terms
called a restriction list. But in contrast to architecture qualification there
can be multiple `<` and `>` enclosed restriction lists. The list of restriction
lists is called a restriction formula and individual restriction lists are
separated by whitespace.

Every term in a restriction list refers to the name of a build profile (see
above for a list). Terms can be negated by using an exclamation mark as a
prefix just as architectures in the architecture qualification list. In
contrast to the architecture qualification list, positive and negative terms
are allowed to be mixed.

The terms arranged as a restriction formula form 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 term
evaluates to "true" if the profile with the same name was set for the build. It
defaults to false if the profile was not set. In the example above, the
package would depend on `foo` for `i386` or `arm` and if neither the profile
`stage1` nor the profile `cross` are active.

Second example:

{{{
Build-Depends: foo <stage1 cross>
}}}

In this case, the source package would build depend on `foo` only if both, the
profile `stage1` and `cross` are active.

Third example:

{{{
Build-Depends: foo <stage1 cross> <stage1>
}}}

In this case, the source package would build depend on `foo` if either both,
`stage1` and `cross` are active or if the profile `stage1` is active. This
means that the dependency is not applied if the profile `cross` alone is
active.

In other words, if a build dependency is annotated with a restriction formula,
then that build dependency is included if and only if the condition expressed
by the conjunctive normal form expression evaluates to true.

== The Build-Profiles field ==

In debian/control binary package stanzas, the content of the Build-Profiles
field specifies the condition for which that binary package does or does not
build. To express that condition, the same restriction formula syntax from the
`Build-Depends` field is used.

{{{
Build-Profiles: <!cross> <!stage1>
}}}

If a binary package stanza in a debian/control file does not contain a
Build-Profiles field, then it implicitly means that it builds with all build
profiles (including none at all).

In other words, if a binary package stanza in debian/control is annotated with
a non-empty `Build-Profiles` field, then that binary package is generated if
and only if the condition expressed by the conjunctive normal form expression
evaluates to true.

== The Built-For-Profiles field ==

In *.changes and Packages files, the content of the Built-For-Profiles field
specifies the white space separated list of build profiles with which that
binary or source package was built.

== The DEB_BUILD_PROFILES environment variable ==

The DEB_BUILD_PROFILES environment variable contains a space separated
unordered list of activated profiles. The content of this variable must be
honored by all tools involved in package compilation. Here an example for
debian/rules (enabling sql for any build except stage1 profile - notice the
negated test):

{{{
ifneq ($(filter stage1,$(DEB_BUILD_PROFILES)),)
    DH_OPTIONS += -Nlibdb5.1-sql # not needed with debhelper (>= 9.20140227)
    CONFIGURE_SWITCHES += --disable-sql
else
    CONFIGURE_SWITCHES += --enable-sql
endif
}}}

== Profile built binary packages ==

A binary package must contain the exact same content for all profiles with
which it builds including no activated profile at all (if it builds in that
case). Otherwise a package depending on that binary package might not find the
functionality or data it expects it to provide. This means that if necessary
binary packages have to be split or that a source package has to be built in
two stages. This requirement can not technically be checked before
ReproducibleBuilds happen.

This requirement does not apply if the "stage1" or "nodoc" profile is active.
In this case, only the parts of the package that expose a functional interface
(scripts, programs, libraries, headers) must not be different. Non-functional
interfaces like documentation can be different or missing in the produced
binary packages.

=== Example ===

Imagine `src:foo` depends on `bar` which is needed to build a plugin that is
shipped together with other plugins in the package `foo-plugins`. When `bar` is
made optional as a build dependency of `src:foo` in a `stage1` build, then the
resulting `stage1` binary package `foo-plugins` would differ from the
`foo-plugins` package that is created during a full build. Thus the creation of
the `foo-plugins` binary package must be disabled by using the `Build-Profiles`
field in the `foo-plugins` binary package stanza and by adding the necessary
bits to `debian/rules` for packages without debhelper or when build depending
on debhelper (>> 9.20140227) is not desired.

If `foo-plugins` has reverse dependencies which are part of a cycle with `src:foo` itself, then not building `foo-plugins` would not solve the bootstrap problem. In that case it is necessary to either:

 * split the `foo-plugins` package into `foo-plugins-nobar` and `foo-plugins-bar` and adjust *all* reverse dependencies of `foo-plugins` to correctly depend on `foo-plugins-nobar` and `foo-plugins-bar`
 * or create a package `foo-plugins-nobar` during a `stage1` build and modify only the reverse dependencies that are in a cycle with `src:foo` to build depend on `foo-plugins-nobar` in their own `stage1` build. When `src:foo` is built fully, it will not produce `foo-plugins-nobar` anymore but the full `foo-plugins` package instead.

=== Rationale ===

The final goal is to allow a fully automated bootstrap where a buildd is able
to bootstrap the whole archive for a specific architecture without any manual
intervention.
This is only possible if reverse dependencies of any binary package continue to
be able to rely on its content being the one they expect no matter how the
binary package was created.
If this cannot be guaranteed, then a
dependency solver will choose an installation set which does not satisfy the
actual dependencies of a package and the bootstrap will fail. Just as it is
necessary for multiarch, this often means the addition of more binary packages.
In the case of bootstrapping, those binary packages might even only be useful
during the bootstrap process itself. For example, the dependency cycle between
src:gamin and src:glib2.0 can be solved by letting src:glib2.0 build an
additional package libglib2.0-stage1-dev which does not include gamin on which
src:gamin can then build depend upon during a stage1 build. While the temporary
package libglib2.0-stage1-dev is very short lived, there can be situations
where the stage1 package needs to be around for a long time. One example are
the binary packages built by glibc stage2. While these can be built very early,
the full glibc can only be built once audit and systemtap are available which
come much later. Without those temporary, differently named, stage1 packages,
another package might accidentally use a not fully built binary package to
satisfy its dependencies. This is especially likely to happen for long lived
stage1 binary packages. The only alternative to introducing temporary stage1
binary packages, would be to change the dependency system to include the
information for which build profiles a binary package is built. But this is
unlikely to happen due to the intrusiveness of such a change.

== Registered profile names ==

The profile names used is a distribution specific policy. Ideally Debian derivatives should use the same profile names registered in Debian so that there's consistency, but otherwise most of the tools do not care about the names or its semantics, only the packages making use of them.

The current prospective list of registered profile names in Debian is:

|| '''Name''' || '''C''' || '''S''' || '''Description''' ||
|| `stage1` || F<<FootNote(Ideally N)>> || Y || Used when bootstrapping an architecture, stage 1. Must reduce Build-Depends. ||
|| `stage2` || F<<FootNote(Ideally N)>> || Y || Used when bootstrapping an architecture, stage 2. Should not be necessary for packages other than `glibc` or `gcc`. ||
|| `nocheck` || N || N || No test suite should be run, and build dependencies used only for that purpose should be ignored. Builds that set this profile must also add `nocheck` to `DEB_BUILD_OPTIONS` ||
|| `nodoc` || F || Y || No documentation should be included or built into packages. ||
|| `nobiarch` || N || Y || No multilib packages should be built. ||
|| `cross` || N || N || Can be used to add extra dependencies for cross-compilation. Usually used when a package would build depend on it self. If the set of binary packages built changes, then it should be combined with a profile like `stage1`. ||

 C:: Whether the content of individual binary packages may change when activating this profile. Values: N (not at all), F (no functional changes, e.g. changes to `/usr/share/doc/`, `/usr/share/locale/` or `/usr/share/man/`), Y (package contents may change)
 S:: Whether the set of binary packages built may change when activating this profile. I.e.: whether this profile name can occur by itself in the Build-Profile field in binary stanzas in debian/control. Values: N (no), Y (yes)

Possible future additions include:

|| '''Name''' || '''Description''' ||
|| `nonls` or `nointl` or `noi18n` || No i18n support should be built into the package. ||

== Other uses for the restriction syntax ==

=== Mark build dependencies that need to be translated when cross building ===

See CrossTranslatableBuildDeps#A3._Use_restriction_syntax_with_new_namespace

=== Replace Build-Depends-Indep and Build-Depends-Arch ===

Instead of moving build dependencies needed to build arch:all or arch:any
packages into `Build-Depends-Indep` and `Build-Depends-Arch`, respectively,
mark them directly in the `Build-Depends` field using `<debbuildopt.archindep>`
and `<debbuildopt.archdep>`, respectively.

=== Map DEB_BUILD_OPTIONS to namespaces ===

Some `DEB_BUILD_OPTIONS` like `nocheck` or `noopt` could be mapped to
`<debbuildopt.nocheck>` or `<debbuildopt.noopt>`. This would allow not needing
to install certain dependencies if certain `DEB_BUILD_OPTIONS` are active.

=== Backports ===

A backports profile could adjust build dependencies depending on the Debian
release for which the backport is done. A backports profile name would thus
have to contain the targetted release. With support from debhelper, even the
binary versions could automatically adapted to contain the bpo postfix once a
build is done with a backport profile active. This would allow to do backports
without forking the packaging.

== Discussion ==

=== Interaction with ReproducibleBuilds ===

As it stands, build profiles and reproducible builds are inherently incompatible, because at least the Built-For-Profiles field will be added to the generated binary packages. A possible solution to this could be to stop adding those fields, and instead record the active set of build profiles in the *.buildinfo file. This has the inconvenience that the information is not tied to the actual binary package and as such might get lost, and that it's not as easily accessible from the archive Packages indices.

This might also get in the way of possibly setting the build profiles automatically by dpkg-buildpackage on certain DEB_BUILD_OPTION values or other criteria, like when cross-building.

Document status

Preliminary support of this spec was implemented in.

program

version

bug

vcs commit

dpkg

1.17.14

760158

git:8329c09b

sbuild

0.65.0-1

731798

apt

1.0.9.3

763721

git:2e5afeb5

python-apt (dep on libapt)

0.9.3.6

744243

git:419ac4d0, git:921a75d9

debhelper

9.20141010

763766

cdbs

772788

pbuilder

0.215+nmu4

740577

git:19152b3f

lintian

2.5.29

763773

dose3

3.3~beta1-1

wanna-build

dak

744246

devscripts (mk-build-deps)

python-debian

0.1.23

git:718fa762, git:118fa762

libconfig-model-dpkg-perl

2.057

763772

augeas

haskell-debian

dh-exec

0.15

793736

autopkgtest

787093

git:fd343efd, git:fd343efd5

Problem description

For some compilation scenarios it is required to build-depend on a different set of binary packages than specified in the Build-Depends line. The two most important scenarios are:

  • Bootstrapping (for breaking build dependency cycles) and

  • Cross building (for source packages having different build dependencies during cross building than during native building)

This specification describes an extension of the Build-Depends field syntax. The extensions allow the marking of build dependencies as being needed or not needed when one or more build profiles are activated. It also defines a new field called "Build-Profiles" which, depending on the context marks binary packages as being built or not built with a certain set of build profiles activated or marks binary packages as having been built with a certain set of build profiles activated.

Build profiles can be activated by setting the environment variable DEB_BUILD_PROFILES or by using the -P option with dpkg-buildpackage (or -o Apt::Build-Profiles for apt, or --profiles in sbuild). More than one build profile can be activated at a time. Multiple profiles are specified by separating them with commas in commandline arguments and by separating them with spaces in the DEB_BUILD_PROFILES environment variable. Some common profile names are "stage1", "stage2", "nocheck", "nodoc", "nobiarch" and "cross".

Build-Depends syntax extension (restriction formulas)

An example demonstrating the restriction formula syntax for build profiles:

Build-Depends: foo (>= 1.0) [i386 arm] <!stage1> <!cross>, bar

This specification introduces a new pair of brackets (using < as the opening and > as the closing bracket) to be used after the architecture qualification list. The < and > brackets enclose a whitespace separated list of terms called a restriction list. But in contrast to architecture qualification there can be multiple < and > enclosed restriction lists. The list of restriction lists is called a restriction formula and individual restriction lists are separated by whitespace.

Every term in a restriction list refers to the name of a build profile (see above for a list). Terms can be negated by using an exclamation mark as a prefix just as architectures in the architecture qualification list. In contrast to the architecture qualification list, positive and negative terms are allowed to be mixed.

The terms arranged as a restriction formula form 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 term evaluates to "true" if the profile with the same name was set for the build. It defaults to false if the profile was not set. In the example above, the package would depend on foo for i386 or arm and if neither the profile stage1 nor the profile cross are active.

Second example:

Build-Depends: foo <stage1 cross>

In this case, the source package would build depend on foo only if both, the profile stage1 and cross are active.

Third example:

Build-Depends: foo <stage1 cross> <stage1>

In this case, the source package would build depend on foo if either both, stage1 and cross are active or if the profile stage1 is active. This means that the dependency is not applied if the profile cross alone is active.

In other words, if a build dependency is annotated with a restriction formula, then that build dependency is included if and only if the condition expressed by the conjunctive normal form expression evaluates to true.

The Build-Profiles field

In debian/control binary package stanzas, the content of the Build-Profiles field specifies the condition for which that binary package does or does not build. To express that condition, the same restriction formula syntax from the Build-Depends field is used.

Build-Profiles: <!cross> <!stage1>

If a binary package stanza in a debian/control file does not contain a Build-Profiles field, then it implicitly means that it builds with all build profiles (including none at all).

In other words, if a binary package stanza in debian/control is annotated with a non-empty Build-Profiles field, then that binary package is generated if and only if the condition expressed by the conjunctive normal form expression evaluates to true.

The Built-For-Profiles field

In *.changes and Packages files, the content of the Built-For-Profiles field specifies the white space separated list of build profiles with which that binary or source package was built.

The DEB_BUILD_PROFILES environment variable

The DEB_BUILD_PROFILES environment variable contains a space separated unordered list of activated profiles. The content of this variable must be honored by all tools involved in package compilation. Here an example for debian/rules (enabling sql for any build except stage1 profile - notice the negated test):

ifneq ($(filter stage1,$(DEB_BUILD_PROFILES)),)
    DH_OPTIONS += -Nlibdb5.1-sql # not needed with debhelper (>= 9.20140227)
    CONFIGURE_SWITCHES += --disable-sql
else
    CONFIGURE_SWITCHES += --enable-sql
endif

Profile built binary packages

A binary package must contain the exact same content for all profiles with which it builds including no activated profile at all (if it builds in that case). Otherwise a package depending on that binary package might not find the functionality or data it expects it to provide. This means that if necessary binary packages have to be split or that a source package has to be built in two stages. This requirement can not technically be checked before ReproducibleBuilds happen.

This requirement does not apply if the "stage1" or "nodoc" profile is active. In this case, only the parts of the package that expose a functional interface (scripts, programs, libraries, headers) must not be different. Non-functional interfaces like documentation can be different or missing in the produced binary packages.

Example

Imagine src:foo depends on bar which is needed to build a plugin that is shipped together with other plugins in the package foo-plugins. When bar is made optional as a build dependency of src:foo in a stage1 build, then the resulting stage1 binary package foo-plugins would differ from the foo-plugins package that is created during a full build. Thus the creation of the foo-plugins binary package must be disabled by using the Build-Profiles field in the foo-plugins binary package stanza and by adding the necessary bits to debian/rules for packages without debhelper or when build depending on debhelper (>> 9.20140227) is not desired.

If foo-plugins has reverse dependencies which are part of a cycle with src:foo itself, then not building foo-plugins would not solve the bootstrap problem. In that case it is necessary to either:

  • split the foo-plugins package into foo-plugins-nobar and foo-plugins-bar and adjust *all* reverse dependencies of foo-plugins to correctly depend on foo-plugins-nobar and foo-plugins-bar

  • or create a package foo-plugins-nobar during a stage1 build and modify only the reverse dependencies that are in a cycle with src:foo to build depend on foo-plugins-nobar in their own stage1 build. When src:foo is built fully, it will not produce foo-plugins-nobar anymore but the full foo-plugins package instead.

Rationale

The final goal is to allow a fully automated bootstrap where a buildd is able to bootstrap the whole archive for a specific architecture without any manual intervention. This is only possible if reverse dependencies of any binary package continue to be able to rely on its content being the one they expect no matter how the binary package was created. If this cannot be guaranteed, then a dependency solver will choose an installation set which does not satisfy the actual dependencies of a package and the bootstrap will fail. Just as it is necessary for multiarch, this often means the addition of more binary packages. In the case of bootstrapping, those binary packages might even only be useful during the bootstrap process itself. For example, the dependency cycle between src:gamin and src:glib2.0 can be solved by letting src:glib2.0 build an additional package libglib2.0-stage1-dev which does not include gamin on which src:gamin can then build depend upon during a stage1 build. While the temporary package libglib2.0-stage1-dev is very short lived, there can be situations where the stage1 package needs to be around for a long time. One example are the binary packages built by glibc stage2. While these can be built very early, the full glibc can only be built once audit and systemtap are available which come much later. Without those temporary, differently named, stage1 packages, another package might accidentally use a not fully built binary package to satisfy its dependencies. This is especially likely to happen for long lived stage1 binary packages. The only alternative to introducing temporary stage1 binary packages, would be to change the dependency system to include the information for which build profiles a binary package is built. But this is unlikely to happen due to the intrusiveness of such a change.

Registered profile names

The profile names used is a distribution specific policy. Ideally Debian derivatives should use the same profile names registered in Debian so that there's consistency, but otherwise most of the tools do not care about the names or its semantics, only the packages making use of them.

The current prospective list of registered profile names in Debian is:

Name

C

S

Description

stage1

F1

Y

Used when bootstrapping an architecture, stage 1. Must reduce Build-Depends.

stage2

F1

Y

Used when bootstrapping an architecture, stage 2. Should not be necessary for packages other than glibc or gcc.

nocheck

N

N

No test suite should be run, and build dependencies used only for that purpose should be ignored. Builds that set this profile must also add nocheck to DEB_BUILD_OPTIONS

nodoc

F

Y

No documentation should be included or built into packages.

nobiarch

N

Y

No multilib packages should be built.

cross

N

N

Can be used to add extra dependencies for cross-compilation. Usually used when a package would build depend on it self. If the set of binary packages built changes, then it should be combined with a profile like stage1.

C

Whether the content of individual binary packages may change when activating this profile. Values: N (not at all), F (no functional changes, e.g. changes to /usr/share/doc/, /usr/share/locale/ or /usr/share/man/), Y (package contents may change)

S
Whether the set of binary packages built may change when activating this profile. I.e.: whether this profile name can occur by itself in the Build-Profile field in binary stanzas in debian/control. Values: N (no), Y (yes)

Possible future additions include:

Name

Description

nonls or nointl or noi18n

No i18n support should be built into the package.

Other uses for the restriction syntax

Mark build dependencies that need to be translated when cross building

See CrossTranslatableBuildDeps#A3._Use_restriction_syntax_with_new_namespace

Replace Build-Depends-Indep and Build-Depends-Arch

Instead of moving build dependencies needed to build arch:all or arch:any packages into Build-Depends-Indep and Build-Depends-Arch, respectively, mark them directly in the Build-Depends field using <debbuildopt.archindep> and <debbuildopt.archdep>, respectively.

Map DEB_BUILD_OPTIONS to namespaces

Some DEB_BUILD_OPTIONS like nocheck or noopt could be mapped to <debbuildopt.nocheck> or <debbuildopt.noopt>. This would allow not needing to install certain dependencies if certain DEB_BUILD_OPTIONS are active.

Backports

A backports profile could adjust build dependencies depending on the Debian release for which the backport is done. A backports profile name would thus have to contain the targetted release. With support from debhelper, even the binary versions could automatically adapted to contain the bpo postfix once a build is done with a backport profile active. This would allow to do backports without forking the packaging.

Discussion

Interaction with ReproducibleBuilds

As it stands, build profiles and reproducible builds are inherently incompatible, because at least the Built-For-Profiles field will be added to the generated binary packages. A possible solution to this could be to stop adding those fields, and instead record the active set of build profiles in the *.buildinfo file. This has the inconvenience that the information is not tied to the actual binary package and as such might get lost, and that it's not as easily accessible from the archive Packages indices.

This might also get in the way of possibly setting the build profiles automatically by dpkg-buildpackage on certain DEB_BUILD_OPTION values or other criteria, like when cross-building.

  1. Ideally N (1 2)