Size: 4558
Comment:
|
Size: 10480
Comment: merged in Dependencies from https://wiki.debian.org/umlaeute/Packaging4CrossCompiling
|
Deletions are marked like this. | Additions are marked like this. |
Line 3: | Line 3: |
This page describes good (and bad) practice in packaging (and upstream code) with respect to cross-building Debian-based packages. Little of this is yet mnandated by policy, but some is and more will be in the future. There are often lots of ways of 'fixing' a cross-build problem, but unless you are expert it he area it will not be clear what the implications of using one method over another are. This page endeavours to document standard guidelines so that packagers can use it as a reference, and Debian and derivatives can develop policy in this area. |
This page describes good (and bad) practice in packaging (and upstream code) with respect to cross-building Debian-based packages. Little of this is yet mandated by policy, but some is and more will be in the future. There are often lots of ways of 'fixing' a cross-build problem, but unless you are an expert in the area it will not be clear what the implications of using one method over another are. This page endeavours to document standard guidelines so that packagers can use it as a reference, and Debian and derivatives can develop policy in this area. <<TableOfContents>> |
Line 9: | Line 11: |
* HOST is the machine we are building for * BUILD is the machine we are building on This somewhat confusing terminology is GNU's fault. |
* '''HOST''' is the machine we are building ''for'' * '''BUILD''' is the machine we are building ''on'' * (TARGET is only relevant for compilers and is the architecture that a compiler outputs code for. Unless packaging ```binutils```, ```gcc``` or ```hurd```, the target architecture is irrelevant.) This somewhat confusing terminology is GNU's fault. |
Line 16: | Line 19: |
dpkg-architecture is responsible for translating between triplets, Debian architecture names and multiarch paths. This provides a consistent interface and namespace. | ```dpkg-architecture``` is responsible for translating between triplets, Debian architecture names and multiarch paths. This provides a consistent interface and namespace. |
Line 19: | Line 22: |
{{{ | |
Line 24: | Line 28: |
}}} | |
Line 27: | Line 32: |
Classic cross-compiling assumes never running any host architecture binaries, and this remains good policy, but we often have QEMU or similar emulation available these days so it makes sense to control this separately where we can. In practice this means running tests, which should be controlled with DEB_BUILD_OPTS=nocheck rather than 'are we cross-compiling or not'. Cross-build tools will set this by default, but it can be enabled when approapriate. When cross-building the build must select the correct tools who's output varies with architecture. This is usually done with an explicit GNU triplet prefix (arm-linux-gnueabi- ia64-linux-gnu-). This applies to the following tools: gcc, g++, binutils (ld, as, strip, ar, readelf etc), pkg-config |
Classic cross-compiling assumes never running any host architecture binaries, and this remains good policy, but we often have QEMU or similar emulation available these days so it makes sense to control this separately where we can. In practice this means running tests, which should be controlled with DEB_BUILD_OPTS=nocheck rather than 'are we cross-compiling or not'. Cross-build tools will set 'nocheck' by default, but it can be enabled when appropriate. When cross-building the build must select the correct tools who's output varies with architecture. This is usually done with an explicit GNU triplet prefix (```arm-linux-gnueabi-``` ```ia64-linux-gnu-```). This applies to the following tools: ```gcc```, ```g++```, ```binutils``` (```ld```, ```as```, ```strip```, ```ar```, ```readelf``` etc), ```pkg-config``` == Salsa CI == The [[https://salsa.debian.org/salsa-ci-team/pipeline|default Salsa-CI pipeline]] now includes a `test-crossbuild-arm64` job, that will attempt to cross-compile your package on the default '''amd64''' build architecture for the '''arm64''' host architecture. So use this default pipeline to get automatic feedback whether your package is cross-compilable (or not). NOTE: Currently the `test-crossbuild-arm64` job has the {{{allow_failure: true}}} property set, so even if the cross-build job fails, the entire pipeline will still be reported as '''success'''. You can either manually check the status of each job of the pipeline, or override the property to `false` in your pipeline definition. |
Line 33: | Line 47: |
Various things need to be set in the environment for cross-builds to work correctly. These are the things that are set by various tools: | Various things need to be set in the environment for cross-builds to work correctly. Below is a list of what is set by various tools, however the interface to package building is still defined as the debian rules targets and your rules file should not rely on any outside environment setting. The recommended way to set the architecture variables provided by dpkg-architecture is to include this snippet provided by dpkg-dev: {{{ include /usr/share/dpkg/architecture.mk }}} This is available from dpkg-dev 1.16.1 onwards, and will not overwrite any previously-supplied values. === Environment set by build tools === |
Line 63: | Line 88: |
sbuild duses dpkg-buildpackage so sets the same things as that, and: {{{ CONFIG_SITE/etc/dpkg-cross/cross-config.$DEB_HOST_ARCH (for autoconf cache settings provided by dpkg-cross) |
sbuild uses dpkg-buildpackage so sets the same things as that, and: {{{ CONFIG_SITE=/etc/dpkg-cross/cross-config.$DEB_HOST_ARCH (for autoconf cache settings provided by dpkg-cross) |
Line 70: | Line 95: |
'''pbuilder''' pbuilder automatically adds ```nocheck``` to ```DEB_BUILD_OPTIONS``` and ```DEB_BUILD_PROFILES``` unless passing ```--no-auto-cross```. |
|
Line 72: | Line 101: |
xdeb duses dpkg-buildpackage so sets the same things as that, and: | xdeb uses dpkg-buildpackage so sets the same things as that, and: |
Line 82: | Line 111: |
Make sets some things itself too. Some of them not very helpfully, like the implicit $(CC)=cc |
Make sets some things itself too. Some of them are not very helpfully, like the implicit ```$(CC)=cc``` == Dependencies == Many Build-Dependencies must use the architecture of the HOST architecture (e.g. C-libraries you want to link against). Other Build-Dependnecies must be ''executed'' on the BUILD machine. These are obviously compilers, but also interpreters, documentation generators,... To help the cross-building environment, you can (and probably should, if things go wrong) annotate Build-Dependencies, so that the correct architecture is picked. === Declare "Indep" Build-Dependencies === Typically, cross-compilation is mostly interesting to produce `arch:any` packages, as the host architecture can use `arch:all` packages produced on any (non-crossbuilding) build machine. To allow the resolver to not worry about any `Build-Depends` that it won't need anyhow, make sure to declare all build-dependencies that are only needed for building `arch:all` packages using the `Build-Depends-Indep` stanza. Eg: {{{#!highlight debcontrol Build-Depends-Indep: doxygen, }}} === Use ':any' specifier for dependencies === For some packages a given dependency must have the HOST architecture, and sometimes the BUILD architecture. If you require your Build-Dependecy to be ''executable'' on the HOST machine, annotate this by adding the `:any` architecture specifier; {{{#!highlight debcontrol Depends: python3:any, }}} === Hints for specific packages === ==== Perl extensions ==== Whenever building a Perl extension module (often called "xs" module), ```perl-xs-dev``` should be added to ```Build-Depends```. ==== Python extensions ==== When building a Python extension, ```pythonSOMETHING-dev``` is often added to ```Build-Depends```. For working with cross compilation, that should be replaced with ```libpythonSOMETHING-dev, pythonSOMETHING-dev:any```. == Building == |
Line 87: | Line 159: |
Simply hardcoding 'gcc' will not allow cross-building, and is arguably wrong for other reasons. Normally you want to set gcc for native builds and $(DEB_HOST_GNU_TYPE)-gcc for cross-builds. Sadly we can't just set $(DEB_HOST_GNU_TYPE)-gcc always because that doesn't work natively So normally people do this: {{{ ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE)) CC=gcc else CC=$(DEB_HOST_GNU_TYPE)-gcc |
Simply hardcoding 'gcc' will not allow cross-building, and is arguably wrong for other reasons (like using llvm/clang instead) The easiest way to re-initialize common tool variables inside ```debian/rules``` is relying on ```dpkg```: {{{ include /usr/share/dpkg/buildtools.mk }}} Formerly, you could set ```CC``` manually: {{{ CC=$(DEB_HOST_GNU_TYPE)-gcc }}} When dealing with ```makefile``` build systems, using ```dh_auto_build``` will automatically pass cross tools as command variables. Unfortunately make always sets $(CC) (to 'cc') so you can't just test if it is already set, and set it if not. This state can be detected with $(origin CC) see http://theory.uwinnipeg.ca/localfiles/infofiles/make/make_80.html In the end, this can be done this way for instance: {{{ DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) ifeq ($(origin CC),default) CC := $(DEB_HOST_GNU_TYPE)-gcc |
Line 98: | Line 184: |
}}} But it should also be possible to override the compiler for the build from the environment so that for example LLVM test builds or strangly-named external toolchains can be used. Unfortunately make always sets $(CC) (to 'cc') so you can't just test if it is already set, and set it if not. {{{CC ?= $(CC)}}} This state can be detected with $(origin CC) see http://theory.uwinnipeg.ca/localfiles/infofiles/make/make_80.html I wonder if we should be doing something clever with ifeq "$(origin CC)" "default" ?... |
override_dh_auto_build: $(MAKE) CC=$(CC) build }}} Note: nowadays debhelper takes care of this, so these lines are usually not needed anymore. This is a good way to set CC in a bash script: {{{: "${CC:=gcc}" }}} which means if $CC is not aleady set, set it to 'gcc', otherwise use the existing value. The ':' is the 'null command' and stops the value being executed. == Running pre-build tests (configure tests) == === Autoconf configure tests === ```autoconf``` will not do tests that need a program to be run when in 'cross-compiling' mode. To get the results that would be missing we can use the config.cache mechanism to supply pre-seeded answers. These can be architecture-specific answers, or generic 'Debian' answers. In rare cases you may need to change them for your own use-case. These autoconf cache files are managed by the dpkg-cross package, which contains a set of files in {{{/etc/dpkg-cross/}}} to pre-seed the answers. cross-config.<arch> contains the architecture-specific stuff (anything depending on size of variables, lengths of pointers, or peculiarities of this arch's glibc implementation). cross-config.cache contains the architecture-independent stuff. All you need to do in your package to enable this mechanism and use the default settings is to set the environment variable {{{CONFIG_SITE=/etc/dpkg-cross/cross-config.$DEB_HOST_ARCH}}} e.g. {{{/etc/dpkg-cross/cross-config.armel}}} If you need a special package-specific variable then you should set PACKAGE=<packagename> to match up with a stanza in one of the config files. This is to avoid clashes if two different packages need a variable set in a different way. == Running runtime tests (testsuite) == |
Line 110: | Line 215: |
{{{ set DEB_BUILD_OPTIONS=nocheck }}} However there are packages where the tests do make sense, and they can be done using ```qemu``` so the responsibility of packagers is just to honour this variable. Where build profiles are enabled (DebianBootstrap) having a profile for 'check' is useful to annotate build-dependencies which are only needed for checks/tests. = Questions = * will the nocheck stuff ever be part of the build system, I think it should be, (maybe setting an additional variable if it does so), this way it would be smarter, for example if we use cross-build to orchestrate multilib, or building with qemu--and still run tests.--scientes |
Guidelines for cross-build friendly packages
This page describes good (and bad) practice in packaging (and upstream code) with respect to cross-building Debian-based packages. Little of this is yet mandated by policy, but some is and more will be in the future.
There are often lots of ways of 'fixing' a cross-build problem, but unless you are an expert in the area it will not be clear what the implications of using one method over another are. This page endeavours to document standard guidelines so that packagers can use it as a reference, and Debian and derivatives can develop policy in this area.
Contents
Terminology
HOST is the machine we are building for
BUILD is the machine we are building on
(TARGET is only relevant for compilers and is the architecture that a compiler outputs code for. Unless packaging binutils, gcc or hurd, the target architecture is irrelevant.)
This somewhat confusing terminology is GNU's fault.
Principles
dpkg-architecture is responsible for translating between triplets, Debian architecture names and multiarch paths. This provides a consistent interface and namespace.
cross-building is defined as BUILD != HOST. more explicitly in debian.rules:
ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE)) native build else crossbuild endif
We cannot run tests to determine aspects of the host machine which will be different on the build machine.
Classic cross-compiling assumes never running any host architecture binaries, and this remains good policy, but we often have QEMU or similar emulation available these days so it makes sense to control this separately where we can. In practice this means running tests, which should be controlled with DEB_BUILD_OPTS=nocheck rather than 'are we cross-compiling or not'. Cross-build tools will set 'nocheck' by default, but it can be enabled when appropriate.
When cross-building the build must select the correct tools who's output varies with architecture. This is usually done with an explicit GNU triplet prefix (arm-linux-gnueabi- ia64-linux-gnu-). This applies to the following tools: gcc, g++, binutils (ld, as, strip, ar, readelf etc), pkg-config
Salsa CI
The default Salsa-CI pipeline now includes a test-crossbuild-arm64 job, that will attempt to cross-compile your package on the default amd64 build architecture for the arm64 host architecture.
So use this default pipeline to get automatic feedback whether your package is cross-compilable (or not).
NOTE: Currently the test-crossbuild-arm64 job has the allow_failure: true property set, so even if the cross-build job fails, the entire pipeline will still be reported as success. You can either manually check the status of each job of the pipeline, or override the property to false in your pipeline definition.
Build environment
Various things need to be set in the environment for cross-builds to work correctly.
Below is a list of what is set by various tools, however the interface to package building is still defined as the debian rules targets and your rules file should not rely on any outside environment setting.
The recommended way to set the architecture variables provided by dpkg-architecture is to include this snippet provided by dpkg-dev:
include /usr/share/dpkg/architecture.mk
This is available from dpkg-dev 1.16.1 onwards, and will not overwrite any previously-supplied values.
Environment set by build tools
dpkg-buildpackage
all the dpkg-architecture variables:
DEB_BUILD_ARCH DEB_BUILD_ARCH_OS DEB_BUILD_ARCH_CPU DEB_BUILD_ARCH_BITS DEB_BUILD_ARCH_ENDIAN DEB_BUILD_GNU_CPU DEB_BUILD_GNU_SYSTEM DEB_BUILD_GNU_TYPE DEB_BUILD_MULTIARCH DEB_HOST_ARCH DEB_HOST_ARCH_OS DEB_HOST_ARCH_CPU DEB_HOST_ARCH_BITS DEB_HOST_ARCH_ENDIAN DEB_HOST_GNU_CPU DEB_HOST_GNU_SYSTEM DEB_HOST_GNU_TYPE DEB_HOST_MULTIARCH
(it also sets some FAKEROOT stuff that we don't care about here, and sanitises a load of stuff out of your normal environment)
sbuild
sbuild uses dpkg-buildpackage so sets the same things as that, and:
CONFIG_SITE=/etc/dpkg-cross/cross-config.$DEB_HOST_ARCH (for autoconf cache settings provided by dpkg-cross) DEB_BUILD_OPTS+=nocheck
anything else configured to be set in build environment
pbuilder
pbuilder automatically adds nocheck to DEB_BUILD_OPTIONS and DEB_BUILD_PROFILES unless passing --no-auto-cross.
xdeb
xdeb uses dpkg-buildpackage so sets the same things as that, and:
CONFIG_SITE=/etc/dpkg-cross/cross-config.$DEB_HOST_ARCH (for autoconf cache settings provided by dpkg-cross) DEB_BUILD_OPTS+=nocheck GTEST_INCLUDEDIR=/usr/$DEB_HOST_GNU_TYPE/include GTEST_LIBDIR=/usr/$DEB_HOST_GNU_TYPE/lib
make
Make sets some things itself too. Some of them are not very helpfully, like the implicit $(CC)=cc
Dependencies
Many Build-Dependencies must use the architecture of the HOST architecture (e.g. C-libraries you want to link against).
Other Build-Dependnecies must be executed on the BUILD machine. These are obviously compilers, but also interpreters, documentation generators,...
To help the cross-building environment, you can (and probably should, if things go wrong) annotate Build-Dependencies, so that the correct architecture is picked.
Declare "Indep" Build-Dependencies
Typically, cross-compilation is mostly interesting to produce arch:any packages, as the host architecture can use arch:all packages produced on any (non-crossbuilding) build machine.
To allow the resolver to not worry about any Build-Depends that it won't need anyhow, make sure to declare all build-dependencies that are only needed for building arch:all packages using the Build-Depends-Indep stanza.
Eg:
Use ':any' specifier for dependencies
For some packages a given dependency must have the HOST architecture, and sometimes the BUILD architecture.
If you require your Build-Dependecy to be executable on the HOST machine, annotate this by adding the :any architecture specifier;
Hints for specific packages
Perl extensions
Whenever building a Perl extension module (often called "xs" module), perl-xs-dev should be added to Build-Depends.
Python extensions
When building a Python extension, pythonSOMETHING-dev is often added to Build-Depends. For working with cross compilation, that should be replaced with libpythonSOMETHING-dev, pythonSOMETHING-dev:any.
Building
Setting correct compiler
Simply hardcoding 'gcc' will not allow cross-building, and is arguably wrong for other reasons (like using llvm/clang instead)
The easiest way to re-initialize common tool variables inside debian/rules is relying on dpkg:
include /usr/share/dpkg/buildtools.mk
Formerly, you could set CC manually:
CC=$(DEB_HOST_GNU_TYPE)-gcc
When dealing with makefile build systems, using dh_auto_build will automatically pass cross tools as command variables.
Unfortunately make always sets $(CC) (to 'cc') so you can't just test if it is already set, and set it if not.
This state can be detected with $(origin CC) see http://theory.uwinnipeg.ca/localfiles/infofiles/make/make_80.html
In the end, this can be done this way for instance:
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) ifeq ($(origin CC),default) CC := $(DEB_HOST_GNU_TYPE)-gcc endif override_dh_auto_build: $(MAKE) CC=$(CC) build
Note: nowadays debhelper takes care of this, so these lines are usually not needed anymore.
This is a good way to set CC in a bash script: : "${CC:=gcc}" which means if $CC is not aleady set, set it to 'gcc', otherwise use the existing value. The ':' is the 'null command' and stops the value being executed.
Running pre-build tests (configure tests)
Autoconf configure tests
autoconf will not do tests that need a program to be run when in 'cross-compiling' mode. To get the results that would be missing we can use the config.cache mechanism to supply pre-seeded answers. These can be architecture-specific answers, or generic 'Debian' answers. In rare cases you may need to change them for your own use-case.
These autoconf cache files are managed by the dpkg-cross package, which contains a set of files in /etc/dpkg-cross/ to pre-seed the answers. cross-config.<arch> contains the architecture-specific stuff (anything depending on size of variables, lengths of pointers, or peculiarities of this arch's glibc implementation). cross-config.cache contains the architecture-independent stuff.
All you need to do in your package to enable this mechanism and use the default settings is to set the environment variable CONFIG_SITE=/etc/dpkg-cross/cross-config.$DEB_HOST_ARCH e.g. /etc/dpkg-cross/cross-config.armel
If you need a special package-specific variable then you should set PACKAGE=<packagename> to match up with a stanza in one of the config files. This is to avoid clashes if two different packages need a variable set in a different way.
Running runtime tests (testsuite)
Running/skipping tests
Normally you don't want to run tests when cross-building.
set DEB_BUILD_OPTIONS=nocheck
However there are packages where the tests do make sense, and they can be done using qemu so the responsibility of packagers is just to honour this variable.
Where build profiles are enabled (DebianBootstrap) having a profile for 'check' is useful to annotate build-dependencies which are only needed for checks/tests.
Questions
* will the nocheck stuff ever be part of the build system, I think it should be, (maybe setting an additional variable if it does so), this way it would be smarter, for example if we use cross-build to orchestrate multilib, or building with qemu--and still run tests.--scientes