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