Building a multi-lib GCC on Solaris

From all the open source softwares in existence I do not think that any single one gathers as much “How to build X on Y” articles than GCC. When considering some of the intricacies of Solaris it's not surprising to see that Solaris gets his fair share of those articles. I however came to the conclusion that one more was needed, for a few reasons that I would like to explain before moving on. First, nearly all of the blogs and articles I read on the subject were very good, but they are not aimed at beginners. Such articles generally assume that the reader knows what he's doing and is knowledgeable about building softwares on Solaris. They also generally leave details out since the users should know them, which would be expected of any seasoned developer working with Solaris. However, if you are not from that group of individuals, or are just coming from another OS it might be useful to have a more in depth guide.

In this weblog entry I will present a somewhat step-by-step guide for building a multi-lib(32 and 64 bit) GCC for Solaris. I will also include in the guide how to correctly build and install GMP and MPFR if you really want to go all the way. Those instructions should work on Solaris 10 and OpenSolaris for the amd64 platform. Instructions specific to a Sparc build are included toward the end of the guide.

Requirements :

Maybe surprising, but very little is needed for building a working GCC on Solaris. In this guide I use the softwares distributed with Solaris 10 which includes gcc 3.4.3 and the minimal set of gnu utilities required to build GMP, MPFR and GCC. Users on OpenSolaris may use the same instructions without modification since the softwares are still available at legacy locations. Of course it's possible to use other third-party softwares, especially for the bootstrap compiler which can be any more recent and working release of GCC. Note that GCC no longer build with Sun Studio and as such another GCC should be used as the bootstrap compiler.

WARNING : It is super-important that LD_LIBRARY_PATH isn't set during all the phase of building GCC, at least not on the shell(s) used for building. Failing to satisfy this condition may result in unpredictable behaviour and a final GCC not able to find it's required dependencies or trying to dynamically link to the wrong libraries. It may also affect the validity of the tests used to verify the build of GMP and MPFR.

First the sources :

To build anything we need sources, the precious resource used to manufacture working binaries. Only three pack of source code are needed :

  • GMP : The GNU Multiple Precision Arithmetic Library.
  • MPFR : Multi-precision floating-point computation with correct rounding.
  • GCC : Gnu Compiler Collection.

For this guide I used versions 4.3.2, 2.4.2 and 4.4.2 of GMP, MPFR and GCC respectively. Earlier or later version of those softwares may have slightly different requirements for building. So I ended with three tarballs :

  • gmp-4.3.2.tar.gz
  • mpfr-2.4.2.tar.gz
  • gcc-4.4.2.tar.gz

Now we must extract those somewhere convenient. I used a subdirectory in my home dir named src. So in my case the source file ended up in the following paths :

  • GMP : /export/home/jo/src/gmp-4.3.2
  • MPFR : /export/home/jo/src/mpfr-2.4.2
  • GCC : /export/home/jo/src/gcc-4.4.2

Building GMP :

The next step now is to build GMP since it is required by MPFR and GCC. I recommend for all of the build of this guide to use a location other than the source directory to compile the software. This technique of building “out of source” is called a VPATH or parallel build, not to be confused with a concurrent (multi-processing) build. For GMP I chose, again, a subdirectory of my home dir gccbuild with three directories in it for all three softwares to be built.

I generally like to use a build script instead of typing everything in a shell. This is much more convenient and permits the user to control more closely the condition and environment of the build. So I can now dump the following script in my gccbuild/gmp directory.

#!/bin/bash

export LD_OPTIONS='-R/export/home/jo/local/lib'
export PATH=/usr/sfw/bin:/usr/ccs/bin:/usr/xpg4/bin:/usr/bin

/export/home/jo/src/gmp-4.3.2/configure --prefix=/export/home/jo/local --build=i386-pc-solaris2.10 ABI=32 \
--enable-shared --disable-static

if [ "$?" -eq "0" ]
then
  gmake -j 2
  if [ "$?" -eq "0" ]
  then
    gmake install
    gmake check
  fi
fi

Some elements of this script needs explaining as they are very important. First the PATH environment variable :

export PATH=/usr/sfw/bin:/usr/ccs/bin:/usr/xpg4/bin:/usr/bin

Here we want the gcc compiler shipped with Solaris and it is located in /usr/sfw/bin and that is placed first in the PATH. This same directory also contains a suitable gmake and associated utilities. Next is /usr/ccs/bin which contains the Sun linker ld. /usr/xpg4/bin and /usr/bin provides everything else needed.

Next the mighty configure line :

/export/home/jo/src/gmp-4.3.2/configure --prefix=/export/home/jo/local --build=i386-pc-solaris2.10 ABI=32 \
--enable-shared --disable-static

The first part of the statement is the full path to the configure script which should be changed to reflect the location of the GMP source. Next comes the --prefix statement specifying the install directory for the end result. In this case I decided to install into my home directory, it's important to be consistent with the install directory since this guide assumes that everything end-up at the same place.

We follow with the build triplet :

--build=i386-pc-solaris2.10

This tells the configure script three things about the type of build that we want. A build triplet is in the form of cpu-platform-os and in this case we chose the i386 cpu architecture, the famous PC platform and Solaris 2.10 as the OS. OpenSolaris would be Solaris 2.11. In the case of GMP the statement ABI=32 is used to set the whole build as being 32 bit, this is a feature specific to GMP in case of architecture with multiple ABI (Application Binary Interface). The --enabled-shared and --disable-static options are there to instruct the build system that we only desire the shared libraries. The rest of the script is just the different targets to build. The first gmake command will build the library while “gmake install” will install it and finally “gmake check” is used to run the testsuite to verify the compiled libraries.

Finally, just before actually compiling GMP one last thing deserves discussion. The LD_OPTIONS options environment variable that is unique to Sun ld.

export LD_OPTIONS='-R/export/home/jo/local/lib'

When LD_OPTIONS is set ld will automatically use the content as if it was entered at the ld invocation command line. This can be used to simplify the building of software under Solaris since it will bypass the configure script and libtool altogether ensuring that the options are used as-is without modifications or unintended side-effects. In our case we use it to add a runtime path or RPATH to the shared libraries of GMP. Every -R option adds an entry to the binaries that will instruct the dynamic linker where to search for the needed dependencies. In this case we add the library directory of the install location, it is not absolutely necessary for GMP but it will be for MPFR and GCC.

Finally we can now launch the build of GMP by running the script. If all goes well it should finish without error. The testsuite should return a 100% success, be very suspicious of any failure as they should not happen.

Building MPFR :

Building MPFR is very similar to GMP except that we must add the location of GMP at the configure phase and that the ABI option is no longer needed. The script looks somewhat like this :

#!/bin/bash

export LD_OPTIONS='-R/export/home/jo/local/lib'
export PATH=/usr/sfw/bin:/usr/ccs/bin:/usr/xpg4/bin:/usr/bin

/export/home/jo/src/mpfr-2.4.2/configure --prefix=/export/home/jo/local --build=i386-pc-solaris2.10 \
--enable-shared --disable-static --with-gmp=/export/home/jo/local

if [ "$?" -eq "0" ]
then
  gmake -j 2
  if [ "$?" -eq "0" ]
  then
    gmake install
    gmake check
  fi
fi

Running it should build, install and check MPFR. Again, like GMP, no failure should be reported by the testsuite.

Building GCC :

Now that we have GMP and MPFR taken care of we can start building GCC. It is more complicated than GMP and MPFR but not by much. So let's go directly to the build script :

#!/bin/bash

export LD_OPTIONS='-R/export/home/jo/local/lib/$ISALIST -R/export/home/jo/local/lib'
export PATH=/usr/sfw/bin:/usr/ccs/bin:/usr/xpg4/bin:/usr/bin

/export/home/jo/src/gcc-4.4.2/configure  --prefix=/export/home/jo/local \
--build=i386-pc-solaris2.10 --enable-languages=c,c++,fortran \
--with-gmp=/export/home/jo/local --with-mpfr=/export/home/jo/local \
--disable-nls --enable-checking=release --enable-werror=no --enable-multilib \
--with-system-zlib --enable-bootstrap \
--with-gnu-as --with-as=/opt/csw/bin/gas --without-gnu-ld --with-ld=/usr/ccs/bin/ld

if [ "$?" -eq "0" ]
then
  gmake -j 2
  if [ "$?" -eq "0" ]
  then
    gmake install
  fi
fi

Most of the configure options are self-explanatory except for a few. First, as recommended by the GCC manual is to use the GNU assembler but Sun ld, especially on x86. This is quintessential to a correct build as Sun as will not work and GNU ld exhibits a few incompatibilities.

--with-gnu-as --with-as=/opt/csw/bin/gas --without-gnu-ld --with-ld=/usr/ccs/bin/ld

The other options are just the recommended settings for a Solaris build. In this case the C, C++ and Fortran compilers are enabled, you could also add ObjectiveC and Treelang if they are wanted. The LD_OPTIONS value is also different for GCC :

export LD_OPTIONS='-R/export/home/jo/local/lib/$ISALIST -R/export/home/jo/local/lib'

Here the $ISALIST keyword is added to the lib directory. This will enable both the 32 and 64 bit libraries to be able to find their respective dependencies.

Now we can launch the build of GCC by running the script, if all goes well you should have a working multilib GCC installed when the script finish.

Building on Sparc :

Not much has to be changed when building on Sparc. The build triplet for GMP and MPFR should be changed to sparcv8-sun-solaris2.10 and the one for GCC to sparc-sun-solaris2.10 .

Hints and tips :

  • The -j n option to gmake can be used to specify the number of concurrent compilation to be used for building. Using it will greatly speed up the build process, it should be adjusted according to the number of available cpus.
  • Up to date pre-built GCC are available from the IPS for OpenSolaris and from Blastwave for Solaris 8+ if you do not want to build your own.
  • Be careful of also configuring the correct RPATH for everything you will build with the new compilers since the libraries are located where you chose to install GCC.

Comments

General comments

The page is very useful, as the ability to build code, without relying on setting LD_LIBRARY_PATH is nice. I do however have a few comments.

* I thought the general consensus was that for SPARC, it was better to use the Sun assembler and Sun linker.
* This page needs updating for gcc 4.5, as that needs the mpc library. I've personally found mpc builds ok, but it always fails to compile the test code, so I can never run a single mpc test.
* It would be useful if you included information on how to test gcc once its been built. I think that's a non-trivial process in itself.

Dave

RE : General comments

The usage of gnu as is more important on x86 than sparc but I found that gnu as give a better result. This was also the findings with the Blastwave distribution of GCC.

As for the new MPC as well as CooG and others this is an excellent idea and I will try to update the blog entry. Same goes with testing gcc.

Thanks for the feedback,

MPFR should be patched before build MPFR and so GCC

The MPFR developers recommend that you patch MPFR with any patch file - see the INSTALL file

(I think you need to use the GNU patch command, gpatch)

2. It is strongly advised to apply the latest patches (if this has
not been done yet), e.g.
wget http://www.mpfr.org/mpfr-3.0.0/patches
patch -N -Z -p1 < patches
or
curl http://www.mpfr.org/mpfr-3.0.0/patches | patch -N -Z -p1

Post new comment

The content of this field is kept private and will not be shown publicly.