How do I install dependencies when cross compiling

2019-04-18 21:56发布

问题:

I've successfully created a ghc cross compiler, that allows me to compile haskell code for armv6h (raspberry pi in my case) from my x64 linux machine. I've successfully run a hello world program on the raspberry.

No I want to build my real app, which has a lot of dependencies on other haskell modules. When I compile for x64 I simply do

cabal install dependenciy1 depenency2 ...

I know I could make my own programm a cabal-project an automate this step. But that's not the point here.

When I try to use the cross-compiler

arm-unknown-linux-gnueabi-ghc --make myapp.hs

It tells me about modules it could not find. Of course, they are not installed!

I read https://ghc.haskell.org/trac/ghc/wiki/Building/CrossCompiling and according to that I tried

cabal --with-ghc=arm-unknown-linux-gnueabi-ghc --with-ghc-pkg=arm-unknown-linux-gnueabi-ghc-pkg --with-ld=arm-unknown-linux-gnueabi-ld install random

random is the depenency I'm trying to install here. I get the following error:

Resolving dependencies...
Configuring random-1.0.1.3...
Failed to install random-1.0.1.3
Last 10 lines of the build log ( /home/daniel/.cabal/logs/random-1.0.1.3.log ):
/home/daniel/.cabal/setup-exe-cache/setup-Cabal-1.18.1.3-arm-linux-ghc-7.8.3.20140804: /home/daniel/.cabal/setup-exe-cache/setup-Cabal-1.18.1.3-arm-linux-ghc-7.8.3.20140804:      cannot execute binary file
cabal: Error: some packages failed to install:
random-1.0.1.3 failed during the configure step. The exception was:
ExitFailure 126

When I do

file /home/daniel/.cabal/setup-exe-cache/setup-Cabal-1.18.1.3-arm-linux-ghc-7.8.3.20140804

I get

/home/daniel/.cabal/setup-exe-cache/setup-Cabal-1.18.1.3-arm-linux-ghc-7.8.3.20140804: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 3.10.2, not stripped

No wonder it can't execute it. It's compiled for arm.

Am I missing something here? My goal is to pull in all dependencies, then create a statically linked app that I can deploy on my raspberry.

回答1:

To understand this error, you need to know how cabal install works internally. In essence, it will perform the following steps:

  1. Download and unpack the source code
  2. Compile Setup.hs (this file is used for customization of the build system, for example, you can implement some hooks to run additional haskell code in the configure phase).
  3. Run setup configure <configure flags> && setup build && setup install

The problem is now that cabal install uses the GHC given by --with-ghc also for step 2, but the executable produced by that step must run on the host system!

A workaround is to do the steps manually, which means you have full control. First, get the source:

$ cabal get random
Downloading random-1.0.1.3...
Unpacking to random-1.0.1.3/
$ cd random-1.0.1.3

Then, compile Setup.hs, using the host ghc:

$ ghc ./Setup.hs -o setup

And finally, configure, build and install. As suggested by @Yuras in a comment, we also add the -x option for running hsc2hs:

$ ./setup configure ----with-ghc=arm-unknown-linux-gnueabi-ghc --with-ghc-pkg=arm-unknown-linux-gnueabi-ghc-pkg --with-ld=arm-unknown-linux-gnueabi-ld --hsc2hs-options=-x
$ ./setup build && ./setup install

There is already a cabal issue about this: https://github.com/haskell/cabal/issues/2085