|Version 13 (modified by benl, 3 years ago)|
- Building on Solaris
Building on Solaris
These instructions have only been checked for GHC 6.8.3 on Solaris 10 on SPARC. It should mostly apply to later versions of GHC, Solaris 8 and later and perhaps Solaris on x86.
A common theme in these instructions is the issue that required tools and libraries are not part of the standard system set and the need for us to set various flags to tell the build system where to find them. For the sake of being concrete, the instructions below use the example of packages from the blastwave.org collection which get installed under the /opt/csw prefix. You can substitute your own path (or paths) as appropriate to your system.
Using a bootstrapping GHC
You can either get the binary from the ghc download page or use some other pre-existing ghc binary.
The binary from the ghc download page depends on gmp, readline and ncurses, none of which are on the default runtime linker search path. It is necessary therefore to set the LD_LIBRARY_PATH, either in the ghc driver shell script or in the environment while doing the build. The latter is simpler:
Note: part of the aim of these instructions is to build a ghc that will not require the use of LD_LIBRARY_PATH. That is, it should not be required to run ghc itself, or any of the programs built by ghc. This is appropriate for installing on a single machine or a set of identically configured machine, or for a binary package collection. However this is not appropriate if you are trying to build a generic, relocatable, redistributable binary package. In that case you do not want to hard code the location of libraries or programs and the user of the package will have to set their $PATH and LD_LIBRARY_PATH appropriately. The differences are noted below.
In the example below we will assume that the bootstrapping ghc is installed in /opt/ghc-bin and that our final ghc will be installed to /opt/ghc.
Using the right GCC
Avoid the system GCC versions
On Solaris 10, the /usr/bin/gcc is a version that uses Sun's code generator backend. This is completely unusable for ghc because ghc has to post-process the assembly output of gcc. It expects the format and layout that the normal gcc uses.
The /usr/sfw/bin/gcc version (at least on Solaris 10) is 3.4.x which is reported to have problems, see below.
It is recommended therefore to install another gcc package, either from some Solaris binary package or to build a vanilla gcc from source.
Selecting a good GCC version
GHC only works with particular GCC versions.
For compiling GHC 6.10.1, GCC versions 4.0.4 and 4.1.2 are known to work. Others in the 4.0.x and 4.1.x series may work, but haven't been tested.
GCC version 4.3.x produces assembly files that GHC's "evil mangler" does not yet deal with.
GCC version 4.2.x works but takes hours and hours to build the large .hc files that GHC generates. It is reported (#1293, #2906) that particular modules can take upwards of 5 hours and the overall build takes a couple days. This is due to complexity issues with respect to GCC moving to a unit-at-a-time compilation scheme instead of function-at-a-time.
GCC version 4.0.2 does not support thread local state (TLS), at least on SPARC.
GCC version 3.4.x is reported (#951) to mis-compile the runtime system leading to a runtime error schedule: re-entered unsafely. But such a gcc version is sufficient for most user programs in case you just installed a ghc binary distribution.
Using GCC from a non-standard location
Since the recommendation is not to use the system /usr/bin/gcc then it is necessary to configure GHC to use a different GCC. Not only do we have to ensure that this alternate GCC is used while building GHC, but we must ensure that this alternate GCC is used by default by the built GHC once we install it and try to use it. Otherwise it will default to whatever gcc is on the $PATH which would typically be /usr/bin/gcc again.
Due to a bug in the build system (#2966) it is not enough to specify --with-gcc= when running ./configure. It is necessary to adjust the $PATH so that the correct gcc is found *and* to use --with-gcc= to the full path to that same version of gcc. Having it first in the $PATH is required for the build to go through and the --with-gcc= flag is necessary to have the resulting ghc use that gcc once installed.
export PATH=/opt/gcc-vanilla/bin:$PATH ./configure --with-gcc=/opt/gcc-vanilla/4.1.2/bin/gcc
Of course, if you are building a relocatable binary package then it makes sense to omit the --with-gcc= flag (with an exotic path) and leave it to the user to ensure the proper gcc is found via the $PATH`.
Fixing the unix package
At the time of writing the unix package gets built wrong (see #2969) which results in getSymbolicLinkStatus not working which in turn breaks darcs. The fix is given in the ticket.
TODO: attach a patch for ghc-6.8.3, send in a patch for ghc-6.10.x and HEAD.
Using GMP from a non-standard location
The gmp library is not a standard system library on Solaris. It can usually be installed from a third party binary package collection or built from source. Either way it will usually not be on the standard cpp include path or the standard static linker path, or the standard dynamic linker path.
We can handle the first two aspects with these ./configure flags --with-gmp-includes and --with-gmp-libraries.
./configure --with-gmp-includes=/opt/csw/include --with-gmp-libraries=/opt/csw/lib
However to actually run programs compiled by ghc (such as stage1) that use gmp from this location we need to link them in such a way that they will find the gmp lib at runtime. The best way is to use the -R linker flag to 'bake in' the right path.
This can be specified in the mk/build.mk file by using:
TODO: check this works, it was only tested with a bootstrapping ghc that always used the above flag, baked into the driver shell script. In that case only GhcStage2HcOpts=-optl-R/opt/csw/lib was needed.
Additionally, the --with-gmp-* flags ensure that when using the resulting ghc, that it will be able to link programs to gmp. That is ghc --make Hello.hs will actually compile because it will pass -L/opt/csw/lib when linking it. However as before, while it links this does not ensure that the resulting program will run. We also need to tell the dynamic linker to look in the gmp lib dir. To get ghc to pass -R as well as -L we need to alter the registration information for the rts package.
Note that this currently needs to be done after installation. See #2933 about integrating it into the build process.
ghc-pkg describe rts > rts.pkg vim rts.pkg ghc-pkg update rts.pkg
In the editing step you need to add the -R/path/to/gmp/lib to the ld-options field.
Again, if you are building a relocatable binary package then you will want to avoid -L or -R linker flags being baked in and instead require that the end user set an appropriate $LD_LIBRARY_PATH.
Using readline from a non-standard location
As with gmp, we need to tell ./configure about the location of readline. Be careful here because it may look like you are building with readline support when in fact you are not.
Using the --with-gmp-includes= --with-gmp-libraries= flags are enough to get the top level ./configure script to believe that using readline will work, if you happen to have gmp and readline installed under the same prefix. However it is not enough for the Haskell readline package's configure script. Unfortunately that one gets run half way through the build process (after building stage1) and if it fails it does so silently and the readline feature is simply not used. This means you end up with a useless ghci. See #2970.
So it is necessary to pass these flags to ./configure:
./configure --with-readline-includes=/opt/csw/include --with-readline-libraries=/opt/csw/lib
If you want to double-check that ghci really did get built with readline support before you install it then run:
And check that it really does link to readline.
With the right toolchain this can work. It's been tested on Solaris 10 with ghc-6.8.3, gcc-4.1.2 and the system (not GNU) binutils (ie as, ld etc from /usr/ccs/bin).
If you run into problems however turn it off by adding this to your mk/build.mk:
Note that to use split objects at the moment you need your gcc to default to the SPARC V9 ABI or to tell ghc to tell gcc to use the V9 ABI it when assembling (-opta-mcpu=v9) otherwise you'll hit bug #2872.
Putting it all together
This example uses ghc-6.8.3 on Solaris 10, using gmp and other tools installed in /opt/csw. The gcc is 4.1.2 installed in /opt/ghc-vanilla/4.1.2/bin. The bootstrapping ghc is the binary from the ghc download page installed in /opt/ghc-bin.
The mk/build.mk file is
The ./configure options
./configure --prefix=/opt/ghc \ --with-ghc=/opt/ghc-bin/bin/ghc \ --with-gcc=/opt/gcc-vanilla/4.1.2/bin/gcc \ --with-gmp-includes=/opt/csw/include \ --with-gmp-libraries=/opt/csw/lib --with-readline-includes=/opt/csw/include \ --with-readline-libraries=/opt/csw/lib
Remember of course that you must use GNU make, not the system make. The Solaris 10 /usr/sfw/bin/gmake should do. Any other GNU make that you install from a third party repository should also be ok.
If you are lucky enough to have a box with lots of CPU cores then use them! Sadly the maximum number that it can actually use effectively is around 4. Hopefully the new build system in ghc-6.11 and later will be able to use more.
It is worth checking at this point that ghc will run without LD_LIBRARY_PATH set:
unset LD_LIBRARY_PATH ldd compiler/stage2/ghc-6.8.3
This should report all libs as being found. (If you expect to use readline then check it is also linked to readline.)
Now to install:
sudo gmake install
Remember that you will now need to modify the rts package for the newly installed ghc so that the programs it builds will be able to find the gmp lib at runtime. See the section above on using gmp from a non-standard location for more details.
export PATH=/opt/ghc/bin:$PATH ghc-pkg describe rts > rts.pkg vim rts.pkg # add -R/opt/csw/lib to the ld-options field. ghc-pkg update rts.pkg
Now check that compiling and running a hello world program works:
$ unset LD_LIBRARY_PATH $ which ghc /opt/ghc/bin/ghc $ echo 'main = print "hello"' > Hello.hs $ ghc --make Hello.hs $ ./Hello "hello"
- link to expected testsuite results.