porting to uClibc-based 686 Linux

Dubiousjim lists+haskell-glasgow at jimpryor.net
Mon Apr 1 19:11:20 CEST 2013


My preferred system is a 686 Linux distro based on uClibc. No ghc
binaries available yet there. I'd like to remedy that.

I have ghc 7.4.2 running on an 686 Linux distro based on glibc (and also
on two different versions of Mac OS X, but they seem more distant and so
less likely to be helpful). In fact, ghc 7.6.2 binaries are also
available for that system, but I'd like to keep in synch with the last
released Haskell platform (which is what I've got on the Macs). That's
supposed to be updated in May, so if it's only possible to port ghg >=
7.6.x to my target system, that won't be so terrible. I'm hoping though
to be able to port a ghc < 7.8.x, because I don't expect to see that
version in any soon-to-be-released Haskell platform. (I mention this
because
http://hackage.haskell.org/trac/ghc/wiki/CrossCompilation says:
"Support for cross-compilation works reasonably well in 7.8.1. Previous
versions had various issues which are usually work-aroundable.")

Ok, so I'm getting stuck trying to build a version of ghc that will run
on the target, uClibc-based system. I have a working cross-compiler. (In
fact, I have two, one built using crosstools-NG, the other built using
buildroot.) My target identifier is "i686-buildroot-linux-uclibc".

I've tried the method for cross-compiling ghc posted here:
http://hackage.haskell.org/trac/ghc/wiki/Building/CrossCompiling
I had to tweak the configure script to not complain about the
"buildroot" vendor id. Here is the content of my mk/build.mk file:

    BuildFlavour = unreg
    ...
    ifeq "$(BuildFlavour)" "unreg"
    
    GhcUnregisterised    = YES
    GhcWithNativeCodeGen = NO
    
    # SRC_HC_OPTS          = -O -H64m
    # GhcStage1HcOpts      = -O
    # GhcStage2HcOpts      = -O2
    # GhcLibHcOpts         = -O2
    SRC_HC_OPTS          = -O -H64m -fasm
    GhcStage1HcOpts      = -O -fasm
    GhcStage2HcOpts      = -O2 -fasm
    GhcHcOpts            = -Rghc-timing
    GhcLibHcOpts         = -O2 -fasm
    SplitObjs            = NO
    HADDOCK_DOCS         = NO
    BUILD_DOCBOOK_HTML   = NO
    BUILD_DOCBOOK_PS     = NO
    BUILD_DOCBOOK_PDF    = NO
    
    endif


Using the following commands:

    $ export PATH=${PATH}:/path/to/my/cross/compiler
    $ make clean
    $ ./configure --target=i686-buildroot-linux-uclibc
    $ make

will successfully build ghc. However, the inplace/lib/ghc-stage2 it
generates won't run on the target system. (Neither will the
utils/ghc-pkg/dist/build/ghc-pkg, this will be relevant later.) Checking
these with
ldd says "not a dynamic executable." Checking them with objdump -p gives
NEEDED lines like this:

    ...
    NEEDED               libc.so.6
    ...

which indicates that they're linking against the glibc on my host,
rather
than the uClibc of my cross-compiler toolchain.

Perhaps I'm doing something wrong, or perhaps the build system
distributed with ghc 7.4.2 just doesn't yet properly support
cross-compiling. It's strange though that the build completes without
any errors. grepping the Makefiles doesn't show any evidence that it's
using my cross-compiler. Do I need to make links using the target
identifier "i386-unknown-linux-..." to my actual tools
"i686-buildroot-linux-uclibc-..."?

The web instructions say:

    If you need to specify the tools explicitly, then you can say

        $ ./configure --target=<target> --with-gcc=<gcc> \
        --with-ld=<ld> --with-nm=<nm> --with-objdump=<objdump>

However, if I specify my cross-compiler tools in this way, the build
breaks already at the configure step, because the binaries generated
won't run on the host.


Alright, that isn't working. I also tried instead to use the older
instructions at
http://hackage.haskell.org/trac/ghc/wiki/Building/Porting

This requires some tweaking, then at a certain point in this process I
also get stuck.

What I had to tweak:

* The instructions say to copy an executable pwd to
  utils/ghc-pwd/ghc-pwd on the target, then run:

      $ perl boot
      $ ./configure --enable-hc-boot --build=<plat> \
      --host=<plat> --target=<plat>

  However, the configure process still tries to build ghc-pwd
  and of course fails, since there's no ghc on the target to build
  it with. I comment out the line in the configure script which
  tries to build ghc-pwd and make sure that GHC_PWD points to
  my replacement pwd (which can't be at the location
  the configure script tries to make GHC_PWD point to, since that
  keeps getting clobbered).

* Ok, so we get past the ghc-pwd issue and the configure continues.
  But then I get stuck with ghc-pkg:

      $ ./configure --enable-hc-boot --build=i386-unknown-linux \
      --host=i386-unknown-linux --target=i386-unknown-linux
      ...
      checking for ghc... no
      checking build system type... i386-unknown-linux-gnu
      checking host system type... i386-unknown-linux-gnu
      checking target system type... i386-unknown-linux-gnu
      GHC build  : i386-unknown-linux
      GHC host   : i386-unknown-linux
      GHC target : i386-unknown-linux
      configure: Building in-tree ghc-pwd
      checking for path to top of build tree... /home/jim/ghc-7.4.2
      checking for gcc... /usr/bin/gcc
      ...
      checking for i386-unknown-linux-gcc... /usr/bin/gcc
      checking whether the C compiler works... yes
      ...
      checking whether we are cross compiling... no
      ...
      checking version of gcc... 4.7.2
      ...
      checking for ghc-pkg matching ... configure: error: Cannot find
      matching ghc-pkg

  Well of course there's no ghc-pkg, because I'm trying to port ghc to
  this system!

  I checked the ghc-pkg I (tried to) build with the cross-compiler
  toolchain, earlier, but this (contrary to my intention) links against
  the libc on its host, and so won't run on the target either.

* Ok, so let's hack the configure script to skip building ghc-pkg too.
  Then configure completes successfully on the target. The next step
  is to:

      $ cd libraries/integer-gmp
      $ ./configure
      $ cd ..
      $ make bootstrapping-files

  However, this fails at the following point:

      ""  -fno-stack-protector -DNO_REGS -DUSE_MINIINTERPRETER
      -D__GLASGOW_HASKELL__=704 -Iincludes -DNO_REGS
      -DUSE_MINIINTERPRETER
      -Iincludes -Iincludes/dist-derivedconstants/header
      -Iincludes/dist-ghcconstants/header -Irts -DNOSMP -c
      includes/mkDerivedConstants.c -o
      includes/dist-derivedconstants/build/mkDerivedConstants.o
      /bin/sh: : Permission denied
      make[1]: ***
      [includes/dist-derivedconstants/build/mkDerivedConstants.o]
      Error 127
      make: *** [bootstrapping-files] Error 2

  I don't know if it's a variable that's supposed to point to $CC that's
  coming up "", or one that's supposed to point to ghc. I'm guessing the
  latter. I can't proceed with the porting instructions at this point
  because includes/dist-derivedconstants is empty (just an empty build
  dir), and includes/dist-ghcconstants doesn't exist yet.


Any advice on how to proceed further using either of the strategies I
described (cross-compiling, or bootstrapping using using unregisterised
intermediate C files), would be welcomed.

-- 
Dubiousjim
dubiousjim at gmail.com
-- 
dubiousjim at gmail.com




More information about the Glasgow-haskell-users mailing list