Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does GHC take so long to link?

Tags:

>cabal update
>cabal install cabal-install
.......
[43 of 44] Compiling Distribution.Client.Install ( Distribution/Client/Install.hs, dist/build/cabal/cabal-tmp/Distribution/Client/Install.o )
[44 of 44] Compiling Main             ( Main.hs, dist/build/cabal/cabal-tmp/Main.o )
Linking dist/build/cabal/cabal ..

then i will wait for a VERY long time for it to finish linking.

Sincerely!

like image 272
z_axis Avatar asked Aug 05 '11 06:08

z_axis


People also ask

How long does GHC take to compile?

It can take a while. When I used to compile it on my iBook G4, it took as long as 7 hours. Even on a MacBook Pro with plenty of RAM and a fast processor, it can take 2-3 hours.

Why is GHC so big?

Short answer is that it's because all executables are statically linked, may have debug info in them and libraries are included in multiple copies. This has already been said by other commenters. I build with GHC 7.4.


2 Answers

Very likely it's the linker itself. The standard ld from binutils is known to be slow. If you want to speed things up (and live a bit on the edge), try installing the Gold linker. On Ubuntu (and I assume Debian), that would be:

sudo apt-get install binutils-gold

I've been using it on my home system for a while now, no issues yet.

like image 179
Michael Snoyman Avatar answered Oct 03 '22 23:10

Michael Snoyman


This should be a comment, but I cannot format code like this in comments:

I managed to use gold as the linker used by GHC, working around standard ghc-with-gold errors like /usr/bin/ld.gold: --hash-size=31: unknown option, by installing binutils-gold (as suggested in Michael Snoyman's answer) and then replacing the symlink /usr/bin/ld by the following script (made executable with chmod +x):

#!/usr/bin/env python2

import sys
import os
import subprocess


tofilter = [
    "--hash-size",
    "--reduce-memory-overheads",
]

filtered = [ a for a in sys.argv if not any(a.startswith(p) for p in tofilter) ]
filtered[0] = "/usr/bin/ld.gold"

subprocess.check_call(subprocess.list2cmdline(filtered))

Note that trying to set the linker with ghc -pgml /usr/bin/ld.gold or ghc -pgml /usr/bin/ld.whateverElse is not sufficient because the argument to -pgml needs to be a replacement for GCC, not LD. GHC calls GCC, which calls /usr/bin/ld; this is why the above script works.

like image 30
nh2 Avatar answered Oct 04 '22 00:10

nh2