LAMP 2018Linux

Development Tools – Building a LAMP Server

This is the fourth article in a series on building the ultimate LAMP Server. Here we will cover setting up development tools for use in compiling software. While most distributions come with a set of development tools you can install from their repository, there are some that we may wish to compile manually, usually because the distribution contains very old versions.

Important: you can probably skip most of this article for Fedora, Debian, and Arch Linux, since those distributions tend to have more recent packages. But do the Essentials section first. The other sections can be done in any order (if desired, you may want to upgrade GCC right after installing the stuff in Essentials). The GCC section is what will take the most time, which is why I have placed it last. Read the notes carefully.

Estimated time (this post only): 5 minutes to 5 hours
* varies depending on whether you choose to compile everything listed from source and how many processor cores you have

Essentials

There are a few essential tools you may need that you should download from the repository first. You may already have some of these installed, but let’s check anyway (technically, you may not even need half of these depending on what you compile, but this should minimize any possible errors).

CentOSFedoraUbuntuDebianopenSUSEArch Linux
sudo yum install make automake autoconf gcc wget dkms bzip2 \
tar kernel-devel-$(uname -r) nano gpg git gcc-c++ gdb cmake \
perl libstdc++ libstdc++-static tcl expect dejagnu gcc-gnat \
binutils texinfo doxygen zlib zlib-devel glibc-devel autogen \
gettext gperf guile flex tex svn diffutils patch \
libuuid-devel gnulib-devel glibc-headers tar
sudo dnf install make automake autoconf gcc wget dkms bzip2 \
tar kernel-devel-$(uname -r) nano gpg git gcc-c++ gdb cmake \
perl libstdc++ libstdc++-static tcl expect dejagnu gcc-gnat \
binutils texinfo doxygen zlib zlib-devel glibc-devel autogen \
gettext gperf guile flex tex svn diffutils patch \
libuuid-devel gnulib-devel glibc-headers tar
sudo apt-get update && sudo apt-get install make automake \
autoconf gcc wget dkms bzip2 tar linux-headers-$(uname -r) \
nano gnupg git g++ gdb cmake perl libstdc++6 tcl expect \
dejagnu gnat binutils texinfo doxygen zlib1g zlib1g-dev \
libc6-dev autogen gettext gperf guile-2.0 flex texlive tar \
subversion diffutils patch uuid-dev gnulib glibc-source pkg-config

If you are going to compile an older version of GCC (such as GCC 4), you may need gnat-5 rather than gnat for Ada support. More on GCC Ada support below.

sudo apt-get update && sudo apt-get install make automake \
autoconf gcc wget dkms bzip2 tar linux-headers-$(uname -r) \
nano gnupg git g++ gdb cmake perl libstdc++6 tcl expect \
dejagnu gnat binutils texinfo doxygen zlib1g zlib1g-dev \
libc6-dev autogen gettext gperf guile-2.0 flex texlive tar \
subversion diffutils patch uuid-dev gnulib glibc-source pkg-config
sudo zypper install make automake autoconf gcc wget dkms bzip2 \
tar kernel-default-devel=$(uname -r | sed 's/-default.*//g') \
nano gpg git gcc-c++ gdb cmake perl libstdc++6 libstdc++-devel \
tcl expect dejagnu gcc-ada binutils texinfo doxygen libz1 \
zlib-devel glibc-devel autogen gettext-runtime gperf guile \
flex subversion diffutils patch libuuid-devel tar
sudo pacman -S make automake autoconf gcc wget dkms bzip2 \
tar linux-headers=$(uname -r | sed 's/-ARCH.*//g') nano gnupg \
git gdb cmake perl libstdc++5 tcl expect dejagnu gcc-ada \
binutils texinfo doxygen zlib glibc autogen gettext gperf \
guile flex svn diffutils patch libcrossguid tar

Since we are going to be downloading several archives from gnu.org we should verify their signatures. So download their GPG keyring and import it:

cd ~
wget http://ftp.gnu.org/gnu/gnu-keyring.gpg
gpg --import gnu-keyring.gpg
rm gnu-keyring.gpg

Lastly, since these tools will be installed to /usr/local, you should ensure the lib directory in there will be in your library path (many distributions do this automatically now, but it doesn’t hurt to make sure):

printf "/usr/local/lib\n/usr/local/lib64" | \
sudo tee /etc/ld.so.conf.d/usr-local.conf
sudo ldconfig

You should probably reboot at this point:

sudo reboot

Note On secure_path

Many distributions have the secure_path option set for sudo. This means your path variable will have no effect when running sudo, so the tools you compile will not be used by sudo commands. Normally, you could overcome this problem by adding the -E switch, but in many distributions the -E switch will not override secure_path. There are several ways to overcome this problem.

  1. Set the path environment every time you need it for sudo. Example: sudo env "PATH=$PATH" make. This is what most people recommend, but the downside is you have to try to remember when it is or isn’t necessary to set the path when running sudo. This is the only method that is guaranteed to work on all distros, so it is what I will focus on.
  2. Disable secure_path via visudo. This is not recommended for security reasons. It could break sudo.
  3. Edit the secure_path via visudo for every package you compile. This could also break sudo.

Make

Make sure you have the latest version of GNU Make installed. Some distributions ship with a different flavor (not GNU) of Make or an older version. To check:

make -v

The bare minimum you need for this tutorial is GNU Make 3.75, but you can check for the latest version via a GNU Make FTP mirror. There may be advantages to installing the latest version of GNU Make even if your distribution ships with 3.8x. So if your distribution has an older version do the following (change version number on first line as needed and copy/paste the rest into your SSH terminal).

TMPVER="4.2.1"
cd ~
wget ftpmirror.gnu.org/make/make-${TMPVER}.tar.gz
wget ftpmirror.gnu.org/make/make-${TMPVER}.tar.gz.sig
gpg --verify make-${TMPVER}.tar.gz.sig make-${TMPVER}.tar.gz

If you see "Good signature" in the results, then the file should be unaltered and you can continue. If you don’t, download again. Now configure and compile.

tar zxvf make-${TMPVER}.tar.gz
mkdir -v make-${TMPVER}/bld
cd make-${TMPVER}/bld

On Ubuntu and Debian, I had difficulty compiling Make 4.2.1. The issue has been reported as a bug and should be fixed in the next version. You can fix it yourself easily enough, but you must do it now, before running configure. So do:

sed -i \
"s/# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION/# if _GNU_GLOB_INTERFACE_VERSION >= GLOB_INTERFACE_VERSION/g" \
../configure.ac

You should now be able to compile Make 4.2.1 successfully on all platforms.

../configure prefix=/usr/local
make && make check

Assuming the tests passed, you are ready to install. See the next two paragraphs for expected failures first.

If you have a recent version of Perl installed, during testing you may see an error like "Can’t locate test_driver.pl in @INC," which is a known bug and you can safely ignore it. A patch has already been submitted to the source tree and should be in the next version of Make or, if you are really concerned, you could apply the patch manually or even install the latest development version (which I don’t recommend for stability).

On CentOS I had three reported test failures, but after manually comparing the files, I realized they were identical. I am guessing the reported failures were due to some bug in the diff check or perhaps the check occurred before the test had completed. In any case, these three errors could be safely ignored.

Now install Gnu Make:

sudo make install
cd ~
sudo mv make-${TMPVER} /usr/local/src/
rm make-*
hash -r
make -v
sudo env "PATH=$PATH" make -v

The last two commands will verify that you are using the correct version, both as yourself and when running commands via sudo.


CMake

You will want a fairly new version of CMake, which some distributions do not have in their official repositories. First, check your current version.

cmake --version

Find the latest release version on the CMake download page. If your version is outdated, do the following (change version number on first line as needed and copy/paste the rest into your SSH terminal).

TMPVER="3.11.1"
cd ~
wget cmake.org/files/v$(echo $TMPVER | \
sed -e 's/\.[^\.]*$//')/cmake-${TMPVER}.tar.gz
wget cmake.org/files/v$(echo $TMPVER | \
sed -e 's/\.[^\.]*$//')/cmake-${TMPVER}-SHA-256.txt
diff <(sha256sum cmake-${TMPVER}.tar.gz | \
sed 's/ .*//') <(cat cmake-${TMPVER}-SHA-256.txt | \
sed -n '/cmake-'${TMPVER}'.tar.gz/p' | \
sed 's/\(.*\)cmake-'${TMPVER}'.tar.gz$/\1/')

That last command will ensure the checksum is valid. If the two values are not identical, download it again. Otherwise continue:

tar zxvf cmake-${TMPVER}.tar.gz
mkdir -v cmake-${TMPVER}/bld
cd cmake-${TMPVER}/bld
../configure --prefix=/usr/local
make && make test

Assuming all tests passed, you are ready to install:

sudo -E env "PATH=$PATH" make install
cd ~
sudo mv cmake-${TMPVER} /usr/local/src/
rm cmake-*
hash -r
cmake --version
sudo env "PATH=$PATH" cmake --version

The last two commands will verify that you are using the correct version, both as yourself and when running commands via sudo.


Perl

I recommend installing the latest version of Perl. Find the latest non-development version number on the CPAN website. Then check your installed version with the following:

perl -v

If you aren’t running a recent version, you can build it from source with the following commands (change version number on first line as needed and copy/paste the rest into your SSH terminal):

TMPVER="5.26.2"
cd ~
wget www.cpan.org/src/$(echo $TMPVER | \
sed 's/\..*$//').0/perl-${TMPVER}.tar.gz
wget www.cpan.org/src/$(echo $TMPVER | \
sed 's/\..*$//').0/perl-${TMPVER}.tar.gz.sha256.txt
diff <(sha256sum perl-${TMPVER}.tar.gz | sed 's/ .*//') \
<(cat perl-${TMPVER}.tar.gz.sha256.txt)

That last command will check the sha256 checksum of the archive against the contents of the text file to ensure the download is valid. You may see a message about there being no newline, but ignore that. So long as both values are identical, the file is good. If the download checks out, continue to compile Perl.

tar xzvf perl-${TMPVER}.tar.gz
cd perl-${TMPVER}
./Configure -des -Dprefix=/usr/local
make && make test

Assuming all tests passed, you can continue installing.

sudo -E env "PATH=$PATH" make install
cd ~
rm perl-*.tar*
sudo mv perl-${TMPVER} /usr/local/src/
hash -r
perl -v
sudo env "PATH=$PATH" perl -v

The last two commands will verify that you are using the correct version, both as yourself and when running commands via sudo.


Glibc

Warning: installing a different version of glibc can break your system if not done properly! However, on some platforms it may be necessary to maintain a different version than that provided by your distribution in order to compile certain software. If you choose to do this, follow my steps carefully!

For this guide, I didn’t find it necessary to update glibc for any of my test platforms, though this could change in the future.

First, check your installed version:

ldd --version

See the list of glibc versions on the GNU website. For this example I will be installing glibc 2.27, though the process is the same for other versions. It is important that you install to the /opt directory and not /usr/local! Change the first two lines to match the desired version number and installation directory, then just copy/paste the rest.

TMPVER="2.27"
TMPPATH="/opt/glibc227"
cd ~
wget ftpmirror.gnu.org/glibc/glibc-${TMPVER}.tar.gz
wget ftpmirror.gnu.org/glibc/glibc-${TMPVER}.tar.gz.sig
gpg --verify glibc-${TMPVER}.tar.gz.sig glibc-${TMPVER}.tar.gz

If you see "Good signature" in the results, then the file should be unaltered and you can continue. If you don’t, download again. Now configure and compile.

tar zxvf glibc-${TMPVER}.tar.gz
mkdir -v glibc-${TMPVER}/bld
cd glibc-${TMPVER}/bld
../configure prefix=${TMPPATH}
make && make check

On some platforms, not all tests may pass (mostly nptl tests). You can look up the tests that failed if desired, but often they don’t matter.

sudo make install
cd ~
sudo mv glibc-${TMPVER} /usr/local/src/
rm glibc-*
${TMPPATH}/bin/ldd --version

The last command will verify that you are using the correct version in the new directory.

How to Use New glibc

There are several methods that might work to link against the new libraries, but the most reliable seems to be to manually edit the Makefile after running configure. The reason for this is so that you don’t risk altering any of the flags required by the software you are compiling. For example, after running configure (and before running make), you may do:

nano Makefile

Somewhere in this file you may find lines such as the following:

CFLAGS = -g -O2
CPPFLAGS =

You could then alter them as follows (changing paths as needed):

CFLAGS = -g -O2 -Wl,--rpath=/opt/glibc227/lib -Wl,--dynamic-linker=/opt/glibc227/lib/ld-linux-x86-64.so.2
CPPFLAGS = -Wl,--rpath=/opt/glibc227/lib -Wl,--dynamic-linker=/opt/glibc227/lib/ld-linux-x86-64.so.2

You could also pass the flags via configure:

../configure \
CFLAGS='-Wl,--rpath=/opt/glibc227/lib -Wl,--dynamic-linker=/opt/glibc227/lib/ld-linux-x86-64.so.2' \
CPPFLAGS='-Wl,--rpath=/opt/glibc227/lib -Wl,--dynamic-linker=/opt/glibc227/lib/ld-linux-x86-64.so.2'

Or via Make itself:

make \
CFLAGS='-Wl,--rpath=/opt/glibc227/lib -Wl,--dynamic-linker=/opt/glibc227/lib/ld-linux-x86-64.so.2' \
CPPFLAGS='-Wl,--rpath=/opt/glibc227/lib -Wl,--dynamic-linker=/opt/glibc227/lib/ld-linux-x86-64.so.2'

Those last two solutions should work, but in some rare cases it may conflict with the default flags as defined in the Makefile, which is why directly editing the Makefile itself is safest.


GCC

Warning: this can be very time-consuming. Please read these notes carefully to decide if you want to install a different version of GCC.

Check your installed version:

gcc -v

As of this writing, here are the versions installed on each distribution I tested:

CentOSFedoraUbuntuDebianopenSUSEArch Linux

4.8.5

8.0.1

7.3.0

6.3.0

4.8.5

7.3.1

As you can see, different distributions include very different versions of GCC, which is critical for compiling software. Check the GCC Releases page to see the latest releases in each branch.

Any of these versions of GCC will compile most software in this guide (see next paragraph). So it is up to you if you want to upgrade to the latest version. The advantage of upgrading is that you will have access to new C/C++ standards which may be required to compile some software (see this page for details). Using the method I cover here, you could always revert to your old version by either updating your path or pointing to a specific compiler. This process may vary slightly depending on what you are installing (example: ../configure CC=/usr/bin/cc).

THIS IS VERY IMPORTANT!!! If your system is running GCC 7+, some older versions of MariaDB may not compile (apparently no matter what flags you pass to it). This has been reported on Debian and is supposedly fixed on that distribution, but I encountered the same error on Fedora and Arch Linux. So you may want to install GCC 6 or older as a backup. More on this below and in the MySQL/MariaDB instructions, which we will get to in a bit.

Now, after reading all the warnings, if you want/need to install a different version of GCC, follow the instructions below carefully.

First of all, note that if you are installing an older version of GCC for compatibility, it is best to install to /opt rather than /usr/local. Since GCC 5/6 seemed best for compiling the software in this guide, I chose to install the following versions for each distribution:

CentOSFedoraUbuntuDebianopenSUSEArch Linux

6.4.0 to /usr/local.

5.5.0 (without Ada support) to /opt/gcc5 (6.4 would not compile due to a known bug which will be fixed in 6.5).

5.5.0 to /opt/gcc5 (6.4 would not compile due to a known bug which will be fixed in 6.5).

None, since Debian currently ships with 6.3.0 and that version seems to compile everything perfectly (I could have upgraded to 6.4.0).

6.4.0 to /usr/local.

5.5.0 (without Ada support) to /opt/gcc5 (6.4 would not compile due to a known bug which will be fixed in 6.5).

Here are the instructions for installing the current latest release in every branch from 4-8. Replace the version in the first line with whatever version you wish to install, replace the path in the second line with the location you wish to install to (see examples above), then copy/paste the rest into your SSH terminal.

GCC 4GCC 5GCC 6GCC 7GCC 8
TMPVER="4.9.4"
TMPPATH="/usr/local"
cd ~
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-4.3.2.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-2.4.2.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-0.8.1.tar.gz
tar xvjf gmp-4.3.2.tar.bz2
tar xvjf mpfr-2.4.2.tar.bz2
tar zxvf mpc-0.8.1.tar.gz
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz.sig
gpg --verify gcc-${TMPVER}.tar.gz.sig gcc-${TMPVER}.tar.gz

If you see "Good signature" in the results, then the file should be unaltered and you can continue. If you don’t, download again. Now create your source tree as recommended by the GCC team.

mkdir -vp gcc-${TMPVER}/bld
tar zxvf gcc-${TMPVER}.tar.gz -C gcc-${TMPVER}
mv gcc-${TMPVER}/gcc-${TMPVER} gcc-${TMPVER}/src
mv gmp-4.3.2 gcc-${TMPVER}/src/gmp
mv mpfr-2.4.2 gcc-${TMPVER}/src/mpfr
mv mpc-0.8.1 gcc-${TMPVER}/src/mpc
cd gcc-${TMPVER}/bld
TMPVER="5.5.0"
TMPPATH="/usr/local"
cd ~
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz
tar xvjf gmp-6.1.0.tar.bz2
tar xvjf mpfr-3.1.4.tar.bz2
tar zxvf mpc-1.0.3.tar.gz
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz.sig
gpg --verify gcc-${TMPVER}.tar.gz.sig gcc-${TMPVER}.tar.gz

If you see "Good signature" in the results, then the file should be unaltered and you can continue. If you don’t, download again. Now create your source tree as recommended by the GCC team.

mkdir -vp gcc-${TMPVER}/bld
tar zxvf gcc-${TMPVER}.tar.gz -C gcc-${TMPVER}
mv gcc-${TMPVER}/gcc-${TMPVER} gcc-${TMPVER}/src
mv gmp-6.1.0 gcc-${TMPVER}/src/gmp
mv mpfr-3.1.4 gcc-${TMPVER}/src/mpfr
mv mpc-1.0.3 gcc-${TMPVER}/src/mpc
cd gcc-${TMPVER}/bld
TMPVER="6.4.0"
TMPPATH="/usr/local"
cd ~
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.16.1.tar.bz2
tar xvjf gmp-6.1.0.tar.bz2
tar xvjf mpfr-3.1.4.tar.bz2
tar zxvf mpc-1.0.3.tar.gz
tar xvjf isl-0.16.1.tar.bz2
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz.sig
gpg --verify gcc-${TMPVER}.tar.gz.sig gcc-${TMPVER}.tar.gz

If you see "Good signature" in the results, then the file should be unaltered and you can continue. If you don’t, download again. Now create your source tree as recommended by the GCC team.

mkdir -vp gcc-${TMPVER}/bld
tar zxvf gcc-${TMPVER}.tar.gz -C gcc-${TMPVER}
mv gcc-${TMPVER}/gcc-${TMPVER} gcc-${TMPVER}/src
mv gmp-6.1.0 gcc-${TMPVER}/src/gmp
mv mpfr-3.1.4 gcc-${TMPVER}/src/mpfr
mv mpc-1.0.3 gcc-${TMPVER}/src/mpc
mv isl-0.16.1 gcc-${TMPVER}/src/isl
cd gcc-${TMPVER}/bld
TMPVER="7.3.0"
TMPPATH="/usr/local"
cd ~
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2
tar xvjf gmp-6.1.0.tar.bz2
tar xvjf mpfr-3.1.4.tar.bz2
tar zxvf mpc-1.0.3.tar.gz
tar xvjf isl-0.18.tar.bz2
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz.sig
gpg --verify gcc-${TMPVER}.tar.gz.sig gcc-${TMPVER}.tar.gz

If you see "Good signature" in the results, then the file should be unaltered and you can continue. If you don’t, download again. Now create your source tree as recommended by the GCC team.

mkdir -vp gcc-${TMPVER}/bld
tar zxvf gcc-${TMPVER}.tar.gz -C gcc-${TMPVER}
mv gcc-${TMPVER}/gcc-${TMPVER} gcc-${TMPVER}/src
mv gmp-6.1.0 gcc-${TMPVER}/src/gmp
mv mpfr-3.1.4 gcc-${TMPVER}/src/mpfr
mv mpc-1.0.3 gcc-${TMPVER}/src/mpc
mv isl-0.18 gcc-${TMPVER}/src/isl
cd gcc-${TMPVER}/bld
TMPVER="8.1.0"
TMPPATH="/usr/local"
cd ~
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-6.1.0.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-3.1.4.tar.bz2
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-1.0.3.tar.gz
wget ftp://gcc.gnu.org/pub/gcc/infrastructure/isl-0.18.tar.bz2
tar xvjf gmp-6.1.0.tar.bz2
tar xvjf mpfr-3.1.4.tar.bz2
tar zxvf mpc-1.0.3.tar.gz
tar xvjf isl-0.18.tar.bz2
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz
wget ftpmirror.gnu.org/gcc/gcc-${TMPVER}/gcc-${TMPVER}.tar.gz.sig
gpg --verify gcc-${TMPVER}.tar.gz.sig gcc-${TMPVER}.tar.gz

If you see "Good signature" in the results, then the file should be unaltered and you can continue. If you don’t, download again. Now create your source tree as recommended by the GCC team.

mkdir -vp gcc-${TMPVER}/bld
tar zxvf gcc-${TMPVER}.tar.gz -C gcc-${TMPVER}
mv gcc-${TMPVER}/gcc-${TMPVER} gcc-${TMPVER}/src
mv gmp-6.1.0 gcc-${TMPVER}/src/gmp
mv mpfr-3.1.4 gcc-${TMPVER}/src/mpfr
mv mpc-1.0.3 gcc-${TMPVER}/src/mpc
mv isl-0.18 gcc-${TMPVER}/src/isl
cd gcc-${TMPVER}/bld

Following is the configuration procedure I used.

If you have trouble running configure for Ada, you can probably safely remove it from the list and just use GNAT to compile Ada code instead. It isn’t necessary for anything in this guide. I am just including all languages in case you want to compile something else on this machine in the future.

../src/configure -v --prefix=${TMPPATH} \
--disable-multilib \
--enable-languages=c,ada,c++,fortran,go,objc,obj-c++,lto

Compile and check. The check process may appear to hang at certain points and can take hours to complete. I ran into a lot of timeouts testing GCC 5 on the latest version of Fedora. This could have been due to inadequate resources on the VMs (a common problem), so I ended up just skipping the tests on that platform, and everything else still compiled just fine.

SED=sed
make -j$(nproc) && ulimit -s 32768 && make -k check
../src/contrib/test_summary | grep -A7 Summ

Look over the summary of all tests. If you just want a summary of the unexpected failures, try this:

../src/contrib/test_summary | grep -B4 -A4 unexpected

If you see a lot of unexpected failures, then something may have gone wrong (some unexpected failures are normal depending on your platform and configure options). You can run the last command again (everything before the pipe) to find the details, then look up the errors if you’re concerned. If you have hundreds or thousands of unexpected failures, you’re probably missing some prerequisite. Otherwise you can usually ignore it even if there are a few dozen errors (especially on a slow system or virtual machine, this is normal).

Now, finally, install:

sudo -E env "PATH=$PATH" make install
sudo ldconfig
hash -r
gcc -v
sudo env "PATH=$PATH" gcc -v
${TMPPATH}/bin/gcc -v
sudo env "PATH=$PATH" ${TMPPATH}/bin/gcc -v

The last four commands will verify that you are using the correct version, both as yourself and when running commands via sudo. If you did not install to /usr/local then the first two will show your system-provided version and the last two will show the version you just installed. If you installed to /usr/local then all four should show this new version.

Create some symlinks next (ignore errors; I’m covering various distributions). Replace /usr/local with your prefix if you installed GCC somewhere else.

GCC 4GCC 5GCC 6GCC 7GCC 8
sudo ln -sv ../bin/cpp ${TMPPATH}/lib
sudo ln -sv gcc ${TMPPATH}/bin/cc
sudo install -v -dm755 ${TMPPATH}/lib/bfd-plugins
sudo ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/${TMPVER}/liblto_plugin.so \
${TMPPATH}/lib/bfd-plugins/
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.20-gdb.py \
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.20-gdb.py
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.20-gdb.py \
/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.20-gdb.py
sudo ln -sv ../bin/cpp ${TMPPATH}/lib
sudo ln -sv gcc ${TMPPATH}/bin/cc
sudo install -v -dm755 ${TMPPATH}/lib/bfd-plugins
sudo ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/${TMPVER}/liblto_plugin.so \
${TMPPATH}/lib/bfd-plugins/
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.21-gdb.py \
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.21-gdb.py
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.21-gdb.py \
/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.21-gdb.py
sudo ln -sv ../bin/cpp ${TMPPATH}/lib
sudo ln -sv gcc ${TMPPATH}/bin/cc
sudo install -v -dm755 ${TMPPATH}/lib/bfd-plugins
sudo ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/${TMPVER}/liblto_plugin.so \
${TMPPATH}/lib/bfd-plugins/
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.22-gdb.py \
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.22-gdb.py
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.22-gdb.py \
/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.22-gdb.py
sudo ln -sv ../bin/cpp ${TMPPATH}/lib
sudo ln -sv gcc ${TMPPATH}/bin/cc
sudo install -v -dm755 ${TMPPATH}/lib/bfd-plugins
sudo ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/${TMPVER}/liblto_plugin.so \
${TMPPATH}/lib/bfd-plugins/
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.24-gdb.py \
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.24-gdb.py
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.24-gdb.py \
/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.24-gdb.py
sudo ln -sv ../bin/cpp ${TMPPATH}/lib
sudo ln -sv gcc ${TMPPATH}/bin/cc
sudo install -v -dm755 ${TMPPATH}/lib/bfd-plugins
sudo ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/${TMPVER}/liblto_plugin.so \
${TMPPATH}/lib/bfd-plugins/
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.25-gdb.py \
/usr/share/gdb/auto-load/usr/lib64/libstdc++.so.6.0.25-gdb.py
sudo ln -sv ${TMPPATH}/lib64/libstdc++.so.6.0.25-gdb.py \
/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.25-gdb.py

Check that cc is pointing to the new version with:

${TMPPATH}/bin/cc -v

Test the installation with:

cd ~
echo 'int main(){}' > dummy.c
${TMPPATH}/bin/cc dummy.c -v -Wl,--verbose &> dummy.log
readelf -l a.out | grep ': /lib'

That last command should output something like:

[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

Now do:

grep -o '/lib.*/crt[1in].*succeeded' dummy.log

Which should output (note that .. may be replaced by something like x86_64-linux-gnu or something else depending on your distribution):

/lib/../lib64/crt1.o succeeded
/lib/../lib64/crti.o succeeded
/lib/../lib64/crtn.o succeeded

And now:

grep -B4 '^ /usr/include' dummy.log

Which should return (allowing for differences in architecture and GCC version number):

#include <...> search starts here:
 /usr/local/lib/gcc/x86_64-unknown-linux-gnu/7.2.0/include
 /usr/local/include
 /usr/local/lib/gcc/x86_64-unknown-linux-gnu/7.2.0/include-fixed
 /usr/include

Check the search paths:

grep 'SEARCH.*/usr/lib' dummy.log |sed 's|; |\n|g'

The output should be similar to the following (again, the architecture will vary depending on your distribution):

SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu")
SEARCH_DIR("=/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/lib/x86_64-linux-gnu")
SEARCH_DIR("=/usr/local/lib64")
SEARCH_DIR("=/lib64")
SEARCH_DIR("=/usr/lib64")
SEARCH_DIR("=/usr/local/lib")
SEARCH_DIR("=/lib")
SEARCH_DIR("=/usr/lib")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64")
SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");

Do some housecleaning:

sudo mv gcc-${TMPVER} /usr/local/src/
rm -v a.out dummy.c dummy.log gmp-*.tar* mpfr-*.tar* \
mpc-*.tar* isl-*.tar* gcc-*.tar*

Final Notes

It is a really good idea to reboot your system now:

sudo reboot

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.