Bug#853285: ghc: Patch to add support for cross-compilation of GHC
John Paul Adrian Glaubitz
glaubitz at physik.fu-berlin.de
Tue Jan 31 08:20:46 UTC 2017
Source: ghc
Version: 8.0.1-17
Severity: normal
Tags: patch
User: helmutg at debian.org
Usertags: rebootstrap
Hi!
Since building GHC natively on slower machines like m68k or sh4 can be quite
painful, I have started working on making the GHC package cross-buildable.
Naturally, being able to cross-build the GHC package also makes it much easier
to bootstrap the compiler for new architecture once basic support has been
added like here [1].
Quick summary what my current patch does:
- use-stage1-binaries-for-install.patch:
This patches the main ghc.mk to use the stage1 binaries of ghc
and ghc-pkg to perform some installation jobs during 'make
install'. This change was suggested by upstream [2]
- build-unlit-and-hp2ps-twice.patch:
Build the unlit and hp2ps binaries twice. Without the patch,
the binaries created are for the build architecture, e.g.
stage1 and not for the host architecture (stage2). See [3].
This change was suggested by upstream, I extended it for
hp2ps. Unfortunately, it was never merged. See also this
upstream ticket [4].
- debian/control:
Replace "ghc (>= 7.8)" with "ghc:native (>= 7.8)" to tell debhelper
to use the GHC compiler of the build system. This is what the
gcc package does as well.
Move haskell-devscripts-minimal and python-sphinx to
Build-Depends-Indep. Please note, this is a hack. The
proper fix would be to make both python-sphinx and
haskell-devscripts-minimal (and probably haskell-devscripts, too)
both arch:any. See this bug report [5].
- debian/rules:
When DEB_BUILD_GNU_TYPE doesn't match DEB_HOST_GNU_TYPE, set:
confflags += --target $(DEB_HOST_GNU_TYPE) --enable-unregisterised
BUILD_HADDOCK_DOCS=NO
Setting "--target" allows enabling cross-compiling, adding
--enable-unregisterised is important for architectures not
having native code generation support. Disabling the documentation
is required by GHC itself. Trying to build the documentation
when cross-compiling causes an error message.
Throughout the rest of the debian/rules changes, I basically
just made the necessary changes to cope with the fact that
the documentation is not being built. This includes skipping
the installation of all documentation and manpages.
Additionally, I'm also guarding out the section which tries
to run the compiler for cross-builds, e.g. ("# Do some very
simple tests that the compiler actually works"). But Helmut
Grohne already pointed out that the proper way would be to
guard this by checking for "nocheck" in DEB_BUILD_OPTIONS
as both sbuild and pbuilder set "nocheck" by default when
cross-compiling. However, in some cases, like cross-compiling
from amd64 to i386, running the tests is still desired.
With the patch applied, I can successfully cross-build GHC provided
that I have pre-installed "haskell-devscripts-minimal" in the
chroot by simply running "sbuild --host=$HOST --no-arch-all -d sid"
provided that the package cross-build-essential-$HOST exists which
is unfortunately not the case for all architectures in Debian [6].
Adding additional architectures to cross-build-essential was
very easy though. I just edited debian/cross-targets, uncommented
the architectures I needed, ran ./debian/rules debian/control,
rebuilt the package and pre-installed it in the build chroot. So,
we should probably file a bug report against src:build-essential
to add more architectures as needed. I don't see why most of
the architectures are currently missing.
Anyway, without the haskell-devscripts-minimal package pre-installed
in the chroot, the cross-build will fail with:
dh_haskell_provides
make[1]: dh_haskell_provides: Command not found
debian/rules:268: recipe for target 'override_dh_installdeb' failed
make[1]: *** [override_dh_installdeb] Error 127
make[1]: Leaving directory '/<<PKGBUILDDIR>>'
debian/rules:46: recipe for target 'binary-arch' failed
make: *** [binary-arch] Error 2
dpkg-buildpackage: error: fakeroot debian/rules binary-arch gave error exit status 2
Additionally, the generated GHC package does not have the proper
symlinks set:
glaubitz at ikarus:/srv/chroots/sid-m68k-sbuild$ dpkg-deb -c ghc_8.0.1-17_m68k.deb |grep "/usr/bin"
drwxr-xr-x root/root 0 2016-12-17 03:44 ./usr/bin/
-rwxr-xr-x root/root 55 2016-12-17 03:44 ./usr/bin/ghci-8.0.1
-rwxr-xr-x root/root 226 2016-12-17 03:44 ./usr/bin/m68k-unknown-linux-gnu-ghc-8.0.1
-rwxr-xr-x root/root 258 2016-12-17 03:44 ./usr/bin/m68k-unknown-linux-gnu-ghc-pkg-8.0.1
-rwxr-xr-x root/root 188 2016-12-17 03:44 ./usr/bin/m68k-unknown-linux-gnu-hpc
-rwxr-xr-x root/root 967 2016-12-17 03:44 ./usr/bin/m68k-unknown-linux-gnu-hsc2hs
-rwxr-xr-x root/root 234 2016-12-17 03:44 ./usr/bin/m68k-unknown-linux-gnu-runghc-8.0.1
lrwxrwxrwx root/root 0 2016-12-17 03:44 ./usr/bin/ghci -> ghci-8.0.1
lrwxrwxrwx root/root 0 2016-12-17 03:44 ./usr/bin/m68k-unknown-linux-gnu-ghc -> m68k-unknown-linux-gnu-ghc-8.0.1
lrwxrwxrwx root/root 0 2016-12-17 03:44 ./usr/bin/m68k-unknown-linux-gnu-ghc-pkg -> m68k-unknown-linux-gnu-ghc-pkg-8.0.1
lrwxrwxrwx root/root 0 2016-12-17 03:44 ./usr/bin/runghc -> runghc-8.0.1
lrwxrwxrwx root/root 0 2016-12-17 03:44 ./usr/bin/runhaskell -> runghc
glaubitz at ikarus:/srv/chroots/sid-m68k-sbuild$
As you can see, /usr/bin/ghc is missing. For my tests, I added the symlinks
manually in my m68k chroot, but I still ran into the following problem
when trying to build haskell-text:
Configuring text-1.2.2.1...
Warning: cannot determine version of /usr/bin/ghc-pkg :
""
hlibrary.setup: The program 'ghc-pkg' is required but the version of
/usr/bin/ghc-pkg could not be determined.
/usr/share/cdbs/1/class/hlibrary.mk:142: recipe for target 'configure-ghc-stamp' failed
make: *** [configure-ghc-stamp] Error 1
dpkg-buildpackage: error: debian/rules build-arch gave error exit status 2
But I'm not sure if it's related because running 'ghc-pkg --version' works:
(sid-m68k-sbuild)root at ikarus:/# ghc-pkg --version
GHC package manager version 8.0.1
(sid-m68k-sbuild)root at ikarus:/#
So, I'd really appreciate any advise on what could be wrong here.
Either way, I think my patch is a good starting point to actually
make the GHC package cross-buildable.
> [1] https://git.haskell.org/ghc.git/commitdiff/f48015bcac59960f6d266506a5f378c9bcf8f005
> [2] https://github.com/rwbarton/ghc-android/blob/rwbarton-ghci/patches/ghc-install.patch
> [3] https://github.com/thomie/ghc/commit/eba93774c3ce2f151e7c72f6d068b753f24dbcfa
> [4] https://ghc.haskell.org/trac/ghc/ticket/12193
> [5] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=818115
> [6] https://packages.qa.debian.org/b/build-essential.html
--
.''`. John Paul Adrian Glaubitz
: :' : Debian Developer - glaubitz at debian.org
`. `' Freie Universitaet Berlin - glaubitz at physik.fu-berlin.de
`- GPG: 62FF 8A75 84E0 2956 9546 0006 7426 3B37 F5B5 F913
-------------- next part --------------
diff -Nru ghc-8.0.1/debian/control ghc-8.0.1/debian/control
--- ghc-8.0.1/debian/control 2016-10-28 07:42:05.000000000 +0200
+++ ghc-8.0.1/debian/control 2017-01-27 15:26:59.000000000 +0100
@@ -6,23 +6,23 @@
Standards-Version: 3.9.8
Build-Depends:
debhelper (>= 9),
- haskell-devscripts-minimal,
devscripts,
dh-autoreconf,
autotools-dev,
grep-dctrl,
pkg-config,
- ghc (>= 7.8),
+ ghc:native (>= 7.8),
libgmp-dev,
llvm-3.7 [arm64 armel armhf],
libffi-dev,
binutils [arm64 armel armhf],
libncurses5-dev,
- python-sphinx,
dpkg-dev (>= 1.16.1.1)
Build-Depends-Indep:
hscolour,
- fop
+ fop,
+ python-sphinx,
+ haskell-devscripts-minimal
Build-Conflicts:
ccache,
ghc (= 8.0.0.20160111-3),
diff -Nru ghc-8.0.1/debian/patches/build-unlit-and-hp2ps-twice.patch ghc-8.0.1/debian/patches/build-unlit-and-hp2ps-twice.patch
--- ghc-8.0.1/debian/patches/build-unlit-and-hp2ps-twice.patch 1970-01-01 01:00:00.000000000 +0100
+++ ghc-8.0.1/debian/patches/build-unlit-and-hp2ps-twice.patch 2017-01-30 17:11:34.000000000 +0100
@@ -0,0 +1,80 @@
+Description: Build unlit and hp2ps twice
+Author: Thomas Miedema <thomasmiedema at gmail.com>
+ John Paul Adrian Glaubitz <glaubitz at physik.fu-berlin.de>
+
+Index: ghc-8.0.1/utils/ghc-pkg/ghc.mk
+===================================================================
+--- ghc-8.0.1.orig/utils/ghc-pkg/ghc.mk
++++ ghc-8.0.1/utils/ghc-pkg/ghc.mk
+@@ -27,7 +27,7 @@ utils/ghc-pkg_PACKAGE = ghc-pkg
+ # Note [Why build certain utils twice?]
+ #
+ # We build certain utils twice: once with stage0, and once with stage1.
+-# Examples are ghc-pkg and hsc2hs.
++# Examples are ghc-pkg, hsc2hs, hp2ps and unlit.
+ #
+ # These tools are needed during the bootstrapping process, so we have to use
+ # stage0 to build them at first (stage1 doesn't exist yet). (side note: they're
+@@ -38,6 +38,11 @@ utils/ghc-pkg_PACKAGE = ghc-pkg
+ # dynamically linked. But the stage0 copies are either statically linked, or
+ # linked against libraries on the build machine.
+ #
++# Another reason why we can't install the stage0 copies is that they are
++# built to run on the build(=host) platform, but when installing a
++# "cross-compiled stage2 compiler" we need copies that run on the target
++# platform.
++#
+ # Therefore we build fresh copies, using the stage1 compiler, and install them
+ # when you run 'make install'. They are not used for any other purpose.
+
+Index: ghc-8.0.1/utils/hp2ps/ghc.mk
+===================================================================
+--- ghc-8.0.1.orig/utils/hp2ps/ghc.mk
++++ ghc-8.0.1/utils/hp2ps/ghc.mk
+@@ -17,10 +17,23 @@ utils/hp2ps_dist_C_SRCS = AreaB
+ Utilities.c
+ utils/hp2ps_dist_EXTRA_LIBRARIES = m
+ utils/hp2ps_dist_PROGNAME = $(CrossCompilePrefix)hp2ps
+-utils/hp2ps_dist_INSTALL = YES
++utils/hp2ps_dist_INSTALL = NO
+ utils/hp2ps_dist_INSTALL_INPLACE = YES
+
+ utils/hp2ps_CC_OPTS += $(addprefix -I,$(GHC_INCLUDE_DIRS))
+
+ $(eval $(call build-prog,utils/hp2ps,dist,0))
+
++utils/hp2ps_dist-install_C_SRCS = AreaBelow.c Curves.c Error.c Main.c \
++ Reorder.c TopTwenty.c AuxFile.c Deviation.c \
++ HpFile.c Marks.c Scale.c TraceElement.c \
++ Axes.c Dimensions.c Key.c PsFile.c Shade.c \
++ Utilities.c
++utils/hp2ps_dist-install_EXTRA_LIBRARIES = m
++utils/hp2ps_dist-install_PROGNAME = hp2ps
++utils/hp2ps_dist-install_TOPDIR = YES
++utils/hp2ps_dist-install_INSTALL = YES
++utils/hp2ps_dist-install_INSTALL_INPLACE = NO
++
++# See Note [Why build certain utils twice?].
++$(eval $(call build-prog,utils/hp2ps,dist-install,1))
+Index: ghc-8.0.1/utils/unlit/ghc.mk
+===================================================================
+--- ghc-8.0.1.orig/utils/unlit/ghc.mk
++++ ghc-8.0.1/utils/unlit/ghc.mk
+@@ -13,8 +13,16 @@
+ utils/unlit_dist_C_SRCS = unlit.c
+ utils/unlit_dist_PROGNAME = unlit
+ utils/unlit_dist_TOPDIR = YES
+-utils/unlit_dist_INSTALL = YES
++utils/unlit_dist_INSTALL = NO
+ utils/unlit_dist_INSTALL_INPLACE = YES
+
+ $(eval $(call build-prog,utils/unlit,dist,0))
+
++utils/unlit_dist-install_C_SRCS = unlit.c
++utils/unlit_dist-install_PROGNAME = unlit
++utils/unlit_dist-install_TOPDIR = YES
++utils/unlit_dist-install_INSTALL = YES
++utils/unlit_dist-install_INSTALL_INPLACE = NO
++
++# See Note [Why build certain utils twice?].
++$(eval $(call build-prog,utils/unlit,dist-install,1))
diff -Nru ghc-8.0.1/debian/patches/series ghc-8.0.1/debian/patches/series
--- ghc-8.0.1/debian/patches/series 2016-12-17 03:43:34.000000000 +0100
+++ ghc-8.0.1/debian/patches/series 2017-01-30 16:16:17.000000000 +0100
@@ -15,3 +15,5 @@
osdecommitmemory-compat.patch
smp-arm-fix.patch
R_X86_64_REX_GOTPCRELX
+use-stage1-binaries-for-install.patch
+build-unlit-and-hp2ps-twice.patch
diff -Nru ghc-8.0.1/debian/patches/use-stage1-binaries-for-install.patch ghc-8.0.1/debian/patches/use-stage1-binaries-for-install.patch
--- ghc-8.0.1/debian/patches/use-stage1-binaries-for-install.patch 1970-01-01 01:00:00.000000000 +0100
+++ ghc-8.0.1/debian/patches/use-stage1-binaries-for-install.patch 2017-01-29 11:32:45.000000000 +0100
@@ -0,0 +1,26 @@
+Description: Use the stage1 binaries for install
+ In order to be able to perform a cross-build, we need to use
+ the stage1 binaries during installation. Both ghc and ghc-pkg
+ are run during the install target and therefore must be able
+ to run on the build machine.
+ .
+Author: John Paul Adrian Glaubitz <glaubitz at physik.fu-berlin.de>
+Last-Update: 2017-01-29
+
+--- ghc-8.0.1.orig/ghc.mk
++++ ghc-8.0.1/ghc.mk
+@@ -958,8 +958,12 @@ INSTALLED_PACKAGE_CONF=$(DESTDIR)$(topdi
+ # Install packages in the right order, so that ghc-pkg doesn't complain.
+ # Also, install ghc-pkg first.
+ ifeq "$(Windows_Host)" "NO"
+-INSTALLED_GHC_REAL=$(DESTDIR)$(ghclibexecdir)/bin/ghc
+-INSTALLED_GHC_PKG_REAL=$(DESTDIR)$(ghclibexecdir)/bin/ghc-pkg
++# Use the inplace/stage1 versions for installation,
++# since the installed versions are built for the target
++#INSTALLED_GHC_REAL=$(DESTDIR)$(ghclibexecdir)/bin/ghc
++#INSTALLED_GHC_PKG_REAL=$(DESTDIR)$(ghclibexecdir)/bin/ghc-pkg
++INSTALLED_GHC_REAL=$(CURDIR)/inplace/bin/ghc-stage1
++INSTALLED_GHC_PKG_REAL=$(CURDIR)/utils/ghc-pkg/dist/build/tmp/ghc-pkg
+ else
+ INSTALLED_GHC_REAL=$(DESTDIR)$(bindir)/ghc.exe
+ INSTALLED_GHC_PKG_REAL=$(DESTDIR)$(bindir)/ghc-pkg.exe
diff -Nru ghc-8.0.1/debian/rules ghc-8.0.1/debian/rules
--- ghc-8.0.1/debian/rules 2016-11-14 17:07:27.000000000 +0100
+++ ghc-8.0.1/debian/rules 2017-01-30 15:35:39.000000000 +0100
@@ -22,20 +22,20 @@
export DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
export DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
export DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
-# Commented out for now. The build scripts don't recognise i486 as an
-# architecture and cross compiling isn't supported anyway.
-#ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
-# confflags += --build $(DEB_HOST_GNU_TYPE)
-#else
-# confflags += --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
-#endif
+
+# We're cross-building if DEB_BUILD_GNU_TYPE != DEB_HOST_GNU_TYPE
+ifneq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
+ confflags += --target $(DEB_HOST_GNU_TYPE) --enable-unregisterised
+ BUILD_HADDOCK_DOCS=NO
+else
+ BUILD_HADDOCK_DOCS=YES
+endif
ProjectVersion=$(shell cat VERSION)
GHC=$(firstword $(shell bash -c "type -p ghc"))
EXTRA_CONFIGURE_FLAGS=--with-ghc="$(GHC)"
-BUILD_HADDOCK_DOCS=YES
DEB_HOOGLE_TXT_DIR = /usr/lib/ghc-doc/hoogle/
ifeq (x32,$(DEB_HOST_ARCH))
@@ -48,9 +48,13 @@
override_dh_auto_configure:
dh_autoreconf perl -- boot
echo "SRC_HC_OPTS += -lffi -optl-pthread" >> mk/build.mk
+ifeq (YES,$(BUILD_HADDOCK_DOCS))
echo "HADDOCK_DOCS := YES" >> mk/build.mk
echo "EXTRA_HADDOCK_OPTS += --mathjax=file:///usr/share/javascript/mathjax/MathJax.js" >> mk/build.mk
echo "XSLTPROC_OPTS += --nonet" >> mk/build.mk
+else
+ echo "HADDOCK_DOCS := NO" >> mk/build.mk
+endif
ifneq (,$(findstring $(DEB_HOST_ARCH), arm64 armel armhf))
echo "SRC_HC_OPTS += -optl-B/usr/bin/ld.gold" >> mk/build.mk
endif
@@ -98,6 +102,8 @@
echo 'dvidir := $$(docdir)' >> mk/build.mk
echo 'pdfdir := $$(docdir)' >> mk/build.mk
echo 'psdir := $$(docdir)' >> mk/build.mk
+ echo 'STRIP_CMD = $(DEB_HOST_GNU_TYPE)-strip' >> mk/build.mk
+ echo 'RANLIB_CMD = $(DEB_HOST_GNU_TYPE)-ranlib'>> mk/build.mk
# We want verbose builds
echo 'V=1' >> mk/build.mk
./configure $(confflags) --prefix=/usr \
@@ -108,6 +114,7 @@
override_dh_auto_build:
dh_auto_build
+ifeq ($(DEB_BUILD_GNU_TYPE), $(DEB_HOST_GNU_TYPE))
# Do some very simple tests that the compiler actually works
rm -rf debian/testghc
mkdir debian/testghc
@@ -122,7 +129,7 @@
@printf "====BEGIN GHC INFO OUTPUT====\n"
@inplace/bin/ghc-stage2 --info
@printf "====END GHC INFO OUTPUT====\n"
-
+endif
FILES = \( -type f -o -type l \)
PROF_FILE = \( -name "*.p_*" -o -name "lib*_p.a" \)
@@ -175,9 +182,8 @@
mkdir debian/tmp/usr/lib/ghc-doc/haddock/ghc/`basename $$f` ; \
mv $$f/*.haddock debian/tmp/usr/lib/ghc-doc/haddock/ghc/`basename $$f` ; done
cd debian/tmp/usr/share/doc/ghc-doc/html/libraries/; ln -s ghc-$(ProjectVersion) ghc
- install -Dm 644 debian/index.html debian/tmp/usr/share/doc/ghc-doc/index.html
-endif
+ install -Dm 644 debian/index.html debian/tmp/usr/share/doc/ghc-doc/index.html
# manpages
rm -f debian/*.1
echo ".so man1/ghc.1" > debian/ghc-$(ProjectVersion).1
@@ -193,14 +199,13 @@
echo debian/*.1 > debian/ghc.manpages
cp debian/haddock.man debian/haddock.1
echo debian/haddock.1 >> debian/ghc.manpages
-
+endif
# ####################
# Now all the files are sorted, create the package filelists
# ghc
find debian/tmp/usr/bin $(FILES) > debian/ghc.install
# find debian/tmp/usr/share/ghc* $(FILES) >> debian/ghc.install
- find debian/tmp/usr/share/man $(FILES) >> debian/ghc.install
find debian/tmp/usr/lib/ghc $(FILES) ! $(PROF_FILE) >> debian/ghc.install
find debian/tmp/var >> debian/ghc.install
echo debian/tmp/usr/share/lintian/overrides/ghc >> debian/ghc.install
@@ -209,14 +214,15 @@
echo debian/tmp/usr/share/lintian/overrides/ghc-prof >> debian/ghc-prof.install
# ghc-doc
ifeq (YES,$(BUILD_HADDOCK_DOCS))
+ find debian/tmp/usr/share/man $(FILES) >> debian/ghc.install
mkdir -p debian/tmp/$(DEB_HOOGLE_TXT_DIR)
cat debian/ghc-doc.links.in > debian/ghc-doc.links
find debian/tmp/usr/share/doc/ghc-doc/html/libraries/*/ -name "*.txt" \
-printf "%p $(DEB_HOOGLE_TXT_DIR)/%f\n" >> debian/ghc-doc.links
find debian/tmp/usr/share/doc/ghc-doc $(FILES) > debian/ghc-doc.install
find debian/tmp/usr/lib/ghc-doc $(FILES) >> debian/ghc-doc.install
-endif
sed -i s,^debian/tmp,, debian/*.install debian/*.links
+endif
rm -f debian/ghc.links
echo "/var/lib/ghc/package.conf.d /usr/lib/ghc/package.conf.d" >> debian/ghc.links
More information about the Pkg-haskell-maintainers
mailing list