wiki:CrossCompiler/Examples

Trivial example using debhelper: h1date

We will package h1date, which is the application giving the GUI for setting the time and date.

Generating the tarball

cd trunk/src/applications/h1date
./autogen.sh
make dist # will create the tarball
cp h1date-0.1.tar.gz /tmp/h1date_0.1.orig.tar.gz && cd /tmp
tar -xvzf h1date_0.1.orig.tar.gz
cd h1date-0.1

# Create the debian directory and edit the files
/path/to/trunk/packages/mkdebpackaging.sh # if the script hangs ; press enter.

vim debian/* # or nano or emacs or ...

debian/changelog

First, debian/changelog contains:

h1date (0.1-1) unstable; urgency=low

  * Initial release (Closes: #nnnn)

 -- Foo Bar <foo@bar.com>  Tue, 19 Jan 2010 10:46:54 +0100

The spacing and the indentation are very important. The package won't build if not respected. You can however put as many line as you need between the first and the last ones.

Edit the changelog, save and edit the next one (^O^X on Nano, :wn on vim).

debian/version

debian/version may be ignored.

debian/control

debian/control contains the following:

Source: h1date
Section: unknown
Priority: extra
Maintainer: Foo Bar <foo@bar.org>
Build-Depends: debhelper
Homepage: <insert the upstream URL, if relevant>

Package: h1date
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: <insert up to 60 chars description>
 <insert long description, indented with spaces>

Edit the homepage and descriptions but take care of the indentation on the long description ; also edit the section (see  http://www.debian.org/doc/maint-guide/ch-dreq.en.html#s-control). Save and edit the next one.

debian/rules

debian/rules is the most important file ; let's see what is inside ("#n" marks are for reference).

#!/usr/bin/make -f
#1
DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
CROSS_CFLAGS=-I/usr/$(DEB_HOST_GNU_TYPE)/include -I/usr/$(DEB_HOST_GNU_TYPE)/usr/include
LDFLAGS=-L/usr/$(DEB_HOST_GNU_TYPE)/lib -L/usr/$(DEB_HOST_GNU_TYPE)/usr/lib
MAKE_LDFLAGS=-inst-prefix-dir /usr/$(DEB_HOST_GNU_TYPE) -Wl,-rpath-link /usr/$(DEB_HOST_GNU_TYPE)/lib -Wl,-rpath-link /usr/$(DEB_HOST_GNU_TYPE)/usr/lib
DH_STRIP=
#DH_SHLIBDEPS=dh_shlibdeps -l/usr/$(DEB_HOST_GNU_TYPE)/lib:/usr/$(DEB_HOST_GNU_TYPE)/usr/lib -- -Ldebian/shlibs.cross
else 
CROSS= --build $(DEB_BUILD_GNU_TYPE) 
DH_STRIP=dh_strip 
DH_SHLIBDEPS=dh_shlibdeps
endif 
#2
configure: 
                dh_testdir
                #3
                ./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS) $(CROSS_CFLAGS)" LDFLAGS="-Wl,-z,defs $(LDFLAGS)"
build: configure 
                dh_testdir
                $(MAKE) LDFLAGS="$(LDFLAGS) $(MAKE_LDFLAGS)" #4
                touch $@

clean: 
                dh_testdir
                dh_testroot
                [ ! -f Makefile ] || $(MAKE) distclean 
                dh_clean 

install: build
                dh_testdir
                dh_testroot
                dh_clean -k 
                dh_installdirs

                $(MAKE) DESTDIR=$(CURDIR)/debian/h1date install #5

binary: build install
                dh_testdir
                dh_testroot
                dh_installchangelogs 
                dh_installdocs
                dh_installexamples
                dh_installman
                dh_link
                $(DH_STRIP) #6
                dh_compress
                dh_fixperms
                dh_installdeb
                $(DH_SHLIBDEPS) #7
                dh_gencontrol
                dh_md5sums
                dh_builddeb

.PHONY: build clean binary install configure

From #1 to #2 lies the block responsible for the cross-compilation support. It defines the flags for compilation and link editing, passed to ./configure or make. In case of cross-compilation, the compiler must look for the libraries in the /usr/$triplet/lib and /usr/$triplet/usr/lib (Where $triplet stands for arm-linux-gnueabi in case you are compiling for armel) instead of /lib and /usr/lib.
The configure right after #3 uses these flags. (In cas of a regular compilation, they are empty except for $(CROSS)) ; the make at #4 and #5 too.
Take a look at #5: it contains the name of the package, so be careful if you do a copy/paste. dh_strip an dh_shlibdeps at #6 and #7 are disabled in case of cross-compilation. This was done because we couldn't strip non-native binaries back in the time mkdebpackaging.sh was written but this isn't true anymore (thanks to binutils-multiarch).

You may not have to modify this file at all but if you do, remember it's a regular Makefile.

Edit if needed, save and exit (that was the last file).

Building the package

If you wish to compile for your native architecture:

dpkg-buildpackage -us -uc # -us -uc avoids signing the package.

h1date using cdbs

Since h1date is a very simple package, we can use cdbs (which stands for Common Debian Build System) for the debian/rules file. CDBS gives a set of rules and automations.

We wrote a cdbs rule file using a cdbs wrapper. You can find it at /usr/share/h1packtools/cross.mk.

Do exactly like the previous example but, add the -t cdbs option to mkdebpackaging.sh.

Now, the debian/rules file will contain:

#!/usr/bin/make -f

include /usr/share/h1packtools/cross.mk

and it needs no editing.

You can add specific flags of targets after. For instance, here is vala's debian/rules:

#!/usr/bin/make -f

include /usr/share/h1packtools/cross.mk
include /usr/share/cdbs/1/class/gnome.mk

DEB_CONFIGURE_EXTRA_FLAGS += --enable-vapigen
VALAFLAGS = --target-glib=2.16

DEB_DH_MAKESHLIBS_ARGS_libvala0 += -V
DEB_SHLIBDEPS_INCLUDE := $(CURDIR)/debian/libvala0/usr/lib
DEB_DH_INSTALL_SOURCEDIR = $(CURDIR)/debian/tmp
DEB_DH_INSTALL_ARGS += -i
DEB_MAKE_CHECK_TARGET = check || true

To know what flags you can modify, take a look in cross.mk and the files it includes.