Re: porting to uClibc-based 686 Linux

I've gotten somewhat further cross-compiling 7.6.2 sources, though still not all the way. I also tried following the instructions at http://hackage.haskell.org/trac/ghc/wiki/Building/Porting with these sources, but couldn't get them to work either. This continues to log my efforts to follow the instructions at http://hackage.haskell.org/trac/ghc/wiki/Building/CrossCompiling One thing I notice by comparing the 7.6.2 sources and the pre-release sources available at http://www.haskell.org/ghc/dist/current/dist/ghc-7.7-src.tar.bz2 is that the instructions at the wiki webpage just cited are tailored to the post-7.6.2 sources. Some of the configure settings should be different for 7.6.2. In particular, I had been using this: is that the instructions at the wiki webpage just cited are tailored to the post-7.6.2 sources. Some of the configure settings should be different for 7.6.2. In particular, I had been using this: ./configure --target=i686-buildroot-linux-uclibc --disable-largefile as the wiki pages seem to suggest. But now I see that I should also be setting --host for 7.6.2, and also supplying an --alien=<script> option. The latter is a script you need to write which will run on the host and take arguments of the form "run <cmd> <more arguments...>". It should then copy "<cmd>" to the target machine and execute "<cmd> <more arguments...>" there, passing through its stdout. Here is the alien script I'm using: #!/bin/sh -x TARGET=its.ip.address CMD=$2 shift 2 scp "$CMD" ${USER}@${TARGET}:alien.cache/ ssh ${USER}@${TARGET} alien.cache/"${CMD##*/}" "$@" That relies on the presence of a folder alien.cache in ${USER}'s home directory on the target machine. It also relies on your being able to ssh from host to target without requiring a password. This script seems to be invoked twice during my builds, for mkGHCConstants mkDerivedConstants There's a third time I think it should be invoked but isn't, and then I have to invoke it manually. (This is explained below.) So here are the steps I'm following now. Most everything described in my preceding email still seems to be necessary; I'm including those steps here as well.
To refresh, I'm trying to bootstrap from a working ghc (now I have 7.6.2 installed on the host) on a typical Linux 686 host system, glibc-based, to get a ghc that can be installed on a similar target system, differing in that it uses uclibc instead of glibc.
I have a working cross-compiler, and seem to have everything else I need to have installed on my host. I did have to make sure that my cross-compiler tree had gmp and libiconv and ncurses installed in it.
I also had to edit the file /usr/lib/ghc-7.6.2/include/ghcautoconf.h on my host system. This was #defining _FILE_OFFSET_BITS to 64, but the uclibc on my target system wasn't compiled with large file support, hence I thought the uclibc in my cross-compiler toolchain shouldn't be either. But then that #define in the host's ghcautoconf.h was conflicting. So I just commented it out for the time being.
Here's what I've done, on the host, from a clean detar of the ghc 7.6.2 sources.
I made this change at three locations in ghc's topmost configure script, to get it to recognize my cross-compiler tag "i686-buildroot-linux-uclibc":
case "$build_vendor" in - pc|gentoo) # like i686-pc-linux-gnu and i686-gentoo-freebsd8 + pc|gentoo|buildroot) # like i686-pc-linux-gnu and i686-gentoo-freebsd8 BuildVendor="unknown" ;;
(The other two locations are for $host_vendor and $target_vendor. Maybe it's only necessary to do this for $target_vendor.)
Next, here is my mk/build.mk file:
# Fast build with optimised libraries, no profiling (RECOMMENDED): BuildFlavour = quick ... # An unregisterised, optimised build of ghc, for porting: # BuildFlavour = unreg ...
The rest as in mk/build.mk.sample
Next, the configure scripts for libraries/{base,directory,integer-gmp,old-time,process,terminfo,time,unix} would stall, complaining that the C compiler didn't generate binaries they could execute. I fixed that by patching those configure scripts like this---I don't know if this is correct, it may be the source of my later troubles. On the other hand, I don't know how else to get past the configure scripts failing. Adding switches like --host and --host="" to my original configure, as an error message suggests, seems to have no effect.
@@ -2833,7 +2833,7 @@ test $ac_status = 0; }; }; then cross_compiling=no else - if test "$cross_compiling" = maybe; then + if true || test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
Next, I had to make this patch to libraries/haskeline/cbits/h_wcwidth.c, else I would get errors about types like size_t not being recognized. (I forget the exact error.)
@@ -59,6 +59,7 @@ * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */
+#include
#include struct interval {
Here is the actual error message this patch avoids: "inplace/bin/mkdirhier" libraries/haskeline/dist-install/build/cbits//. HC [stage 1] libraries/haskeline/dist-install/build/cbits/h_wcwidth.o libraries/haskeline/cbits/h_wcwidth.c:70:31: error: unknown type name 'wchar_t' libraries/haskeline/cbits/h_wcwidth.c:122:26: error: unknown type name 'wchar_t' libraries/haskeline/cbits/h_wcwidth.c:207:1: error: unknown type name 'wchar_t' libraries/haskeline/cbits/h_wcwidth.c:207:48: error: unknown type name 'size_t' libraries/haskeline/cbits/h_wcwidth.c:230:30: error: unknown type name 'wchar_t' libraries/haskeline/cbits/h_wcwidth.c:298:1: error: unknown type name 'wchar_t' libraries/haskeline/cbits/h_wcwidth.c:298:52: error: unknown type name 'size_t' Ok, so here are the steps I'm currently using to configure and build: export PATH=${PATH}:/path/to/my/cross-compiler make distclean ./configure --host=i686-buildroot-linux-uclibc \ --target=i686-buildroot-linux-uclibc --disable-largefile \ --with-alien=/path/to/alien make As I mentioned in my previous email, at a certain point the build tries to execute: libraries/integer-gmp/cbits/mkGmpDerivedConstants > \ libraries/integer-gmp/cbits/GmpDerivedConstants.h where the first is a binary it generated using the cross-compiler. This won't run on the host system. Now we can run it by issuing the following command on the host: /path/to/alien run libraries/integer-gmp/cbits/mkGmpDerivedConstants > \ libraries/integer-gmp/cbits/GmpDerivedConstants.h As I also mentioned in my previous email, the build will also fail unless I add the following lines to libraries/base/include/HsBaseConfig.h: #define HTYPE_DOUBLE Double #define HTYPE_FLOAT Float That's based on what I see in my host system. The HsBaseConfig.h file is only generated during the build, so you can't make this change ahead of time; you have to wait for the build to fail, make the change, and then reissue "make". Now, with the new configure options, this build continues past stage1 and proceeds to build stage2 as well. However, it gets stuck while trying to build these binaries: utils/ghctags/dist-install/build/Main.o libraries/haskell98/dist-install/build/Prelude.o libraries/haskell2010/dist-install/build/Prelude.o It gets stuck because it tries to execute the inplace/lib/ghc-stage2 it has built, but this will only run on the target machine. What a pain. I was able to hack around this in an ugly way. I'll explain what I did, but it depends on the fact that my host environment is a chroot inside my target. You don't want to do this at home. So inside my home directory on the TARGET environment, I did this. CROSSPATH is the absolute path to my cross-compiler i686-buildroot-linux-uclibc-gcc in my host environment (that is, where / is the base of the chroot, not the base of the target's filesystem). GHCSOURCE is the absolute path to my ghc-7.6.2 source tree in the same host environment. mkdir -p ${CROSSPATH%/*} ln -s `which gcc` ${CROSSPATH} ln -s /path/on/target/to/host/chroot/$GHCSOURCE/libraries Then inside the ghc-7.6.2 folder in the host environment, I moved inplace/lib/ghc-stage2 to inplace/lib/ghc-stage2.exe and installed the following script as inplace/lib/ghc-stage2: #!/bin/sh -x TARGET=its.ip.address CMD=$0 ssh ${USER}@${TARGET} "${CMD}.exe" "$@" I also had to make $GHCSOURCE on my target machine be a symlink to /path/on/target/to/host/chroot/$GHCSOURCE. This will get me a bit further in the make process. There are two commands that fail even this way, and that I have to run manually on the target machine, to build utils/ghctags/dist-install/build/Main.o. Ok, with all of that, the build completes. And the build ghc-stage2 (which I temporarily named inplace/lib/ghc-stage2.exe, but now let's restore it to its original name) does in fact execute on the target machine: $ inplace/lib/ghc-stage2 --version The Glorious Glasgow Haskell Compilation System, version 7.6.2 $ inplace/lib/ghc-stage2 --interactive ghc-stage2: missing -B<dir> option $ inplace/lib/ghc-stage2 -B./inplace/lib --interactive GHCi, version 7.6.2: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... ghc-stage2: mmap 442368 bytes at (nil): Operation not permitted ghc-stage2: Try specifying an address with +RTS -xm<addr> -RTS $ cat ~/hello.hs main = putStrLn "Hello World!\n" $ inplace/lib/ghc-stage2 -B./inplace/lib ~/hello.hs -o hello $ ./hello Can't modify application's text section; use the GCC option -fPIE for position-independent executables. That's as far as I've got for now. Hopefully someone will have bothered to read this far and have some suggestions for what I should be doing differently, or how to proceed from here, to get the compiled ghc-stage2 really working on the target machine, so that I can use it to compile ghc on the target machine directly. -- dubiousjim@gmail.com
participants (1)
-
Dubiousjim