LAMP 2017Linux

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 only do so if you have no plans to install older versions of MySQL (which may be necessary for testing purposes). At the very least, see the Essentials, GCC, and Perl sections, even if you are using a bleeding edge distribution like Arch Linux.

Estimated time (this post only): 2 minutes to 5 hours
* varies depending on whether you choose to compile everything listed from source

Essentials

There are a few essential tools you will need that you should download from the repository first. You may already have all of these installed, but let’s check anyway.

CentOSFedoraUbuntu/DebianopenSUSEArch Linux
sudo yum install make automake autoconf gcc wget dkms bzip2 tar kernel-devel-$(uname -r) nano gpg gcc-c++ gdb cmake perl
sudo dnf install make automake autoconf gcc wget dkms bzip2 tar kernel-devel-$(uname -r) nano gpg gcc-c++ gdb cmake perl
sudo apt-get install make automake autoconf gcc wget dkms bzip2 tar linux-headers-$(uname -r) nano gnupg g++ gdb cmake perl
sudo zypper install make automake autoconf gcc wget dkms bzip2 tar kernel-default-devel=$(uname -r | sed 's/-default.*//g') nano gpg gcc-c++ gdb cmake perl
sudo pacman -S make automake autoconf gcc wget dkms bzip2 tar linux-headers=$(uname -r | sed 's/-ARCH.*//g') nano gnupg gdb cmake perl

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

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 as needed).

cd ~
wget ftpmirror.gnu.org/make/make-4.2.1.tar.gz
wget ftpmirror.gnu.org/make/make-4.2.1.tar.gz.sig
gpg --verify make-4.2.1.tar.gz.sig make-4.2.1.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.

tar zxvf make-4.2.1.tar.gz
mkdir -v make-4.2.1-bld
cd make-4.2.1-bld
../make-4.2.1/configure prefix=/usr/local
make
make check

Assuming the tests passed, you are ready to install. On at least one system I had three tests fail during make check, but they didn’t affect anything.

sudo make install
cd ..
sudo mv make-*-bld /usr/local/src/
rm -rf 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.


GCC

Warning: this can be very time-consuming. Technically you could skip this step, but on some platforms (most notably CentOS) you will be stuck with much older versions of GCC, which may cause performance issues or (in some cases) you may not be able to compile newer software. I highly recommend making a full system backup or (if running a virtual machine) a snapshot before beginning this process. And maybe make another snapshot right before running the install command itself, in case something goes wrong.

Check your installed version:

gcc -v

Some distributions ship with the 4.x branch of GCC, which hasn’t been maintained for several years now. The 4 release series will work in most cases, but is dated. Only the 5-7 series are fully supported at this time. Check the GCC Releases page to find the latest version. For this example I’m going to install GCC 7.2. The process should be similar for future versions, but be sure you read the documentation.

First, download some prerequisites. It is safer to use the ones from the GNU Infrastructure FTP page, even if a newer version exists on the GNU FTP mirrors. I won’t go into details about why this is, but you can read the documentation in the links I’ve provided if you’re interested. Or just follow my instructions.

CentOSFedoraUbuntu/DebianopenSUSEArch Linux
sudo yum install dejagnu tcl expect
sudo dnf install dejagnu tcl expect
sudo apt-get install dejagnu tcl expect
sudo zypper install dejagnu tcl expect
sudo pacman -S dejagnu tcl expect

Download everything you need for GCC from the GNU FTP sites:

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-7.2.0/gcc-7.2.0.tar.gz
wget ftpmirror.gnu.org/gcc/gcc-7.2.0/gcc-7.2.0.tar.gz.sig
gpg --verify gcc-7.2.0.tar.gz.sig gcc-7.2.0.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. We will mostly be following these instructions. My steps will differ slightly because I’m combining the source files so everything will be compiled together. Also, I’m recommending that you install to /usr/local rather than /usr, so you can switch back to your distribution’s included version of GCC if necessary.

tar zxvf gcc-7.2.0.tar.gz
mv gmp-6.1.0 gcc-7.2.0/gmp
mv mpfr-3.1.4 gcc-7.2.0/mpfr
mv mpc-1.0.3 gcc-7.2.0/mpc
mv isl-0.18 gcc-7.2.0/isl
mkdir -v gcc-7.2.0-bld
cd gcc-7.2.0-bld
../gcc-7.2.0/configure --prefix=/usr/local \
--disable-multilib \
--enable-languages=c,c++,fortran,go,objc,obj-c++
SED=sed
make
make -k check
../gcc-7.2.0/contrib/test_summary | grep -A7 Summ

Look over the summary of the tests. 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.

sudo -E env "PATH=$PATH" make install
sudo ldconfig
hash -r
gcc -v
sudo env "PATH=$PATH" gcc -v

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

Create some symlinks for compatibility (ignore errors; I’m covering various distributions):

sudo ln -sv ../bin/cpp /usr/local/lib
sudo ln -sv gcc /usr/local/bin/cc
sudo install -v -dm755 /usr/local/lib/bfd-plugins
sudo ln -sfv ../../libexec/gcc/$(gcc -dumpmachine)/7.2.0/liblto_plugin.so \
/usr/local/lib/bfd-plugins/
sudo ln -sv /usr/local/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 /usr/local/lib64/libstdc++.so.6.0.24-gdb.py \
/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.24-gdb.py

Check that cc is pointing to the new version with:

cc -v
sudo env "PATH=$PATH" cc -v

Test the new version with:

echo 'int main(){}' > dummy.c
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

There are various other tests you can run (see the LSF link I provided earlier), but the output will vary greatly by distribution, so I won’t go into them here.

Cleanup your test files:

rm -v a.out dummy.c dummy.log

GCC 4.9

But wait! We aren’t done yet. For compatibility purposes, we also need an older version of GCC. So let’s install that to the opt directory for the rare cases where it’s needed.

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-4.9.4/gcc-4.9.4.tar.gz
wget ftpmirror.gnu.org/gcc/gcc-4.9.4/gcc-4.9.4.tar.gz.sig
gpg --verify gcc-4.9.4.tar.gz.sig gcc-4.9.4.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.

tar zxvf gcc-4.9.4.tar.gz
mv gmp-4.3.2 gcc-4.9.4/gmp
mv mpfr-2.4.2 gcc-4.9.4/mpfr
mv mpc-0.8.1 gcc-4.9.4/mpc
mkdir -v gcc-4.9.4-bld
cd gcc-4.9.4-bld
../gcc-4.9.4/configure --prefix=/opt/gcc49 \
--disable-multilib \
--enable-languages=c,c++,fortran,go,objc,obj-c++
SED=sed
make

You can run make -k check if you want, but it will take forever and you will have a lot of failed tests (which is normal when compiling old software on newer platforms). I recommend just skipping it and continuing with the installation. After all, this is only a fallback version we will invoke for compiling outdated software packages. Ignore any errors for creating symlinks since I’m covering various distributions with these commands.

sudo -E env "PATH=$PATH" make install
sudo ln -sv ../bin/cpp /opt/gcc49/lib
sudo ln -sv gcc /opt/gcc49/bin/cc
sudo install -v -dm755 /opt/gcc49/lib/bfd-plugins
sudo ln -sfv ../../libexec/gcc/x86_64-unknown-linux-gnu/4.9.4/liblto_plugin.so \
/opt/gcc49/lib/bfd-plugins/
sudo ln -sv /opt/gcc49/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 /opt/gcc49/lib64/libstdc++.so.6.0.20-gdb.py \
/usr/share/gdb/auto-load/usr/lib/libstdc++.so.6.0.20-gdb.py

GCC Cleanup

Now let’s do some housekeeping:

cd ~
rm gcc-*.tar*
rm gmp-*.tar*
rm mpfr-*.tar*
rm mpc-*.tar*
rm isl-*.tar*
sudo mv gcc-*-bld /usr/local/src/
rm -rf gcc-*

That’s it. You’re finally done installing GCC for any application you may need to compile. It’s a lengthy process, but an important one for this guide.


Glibc

Warning: this can break your system if you do not follow my instructions precisely! Glibc contains libraries which are central to the operating system. If you screw this up in any way, your system may not boot! On most distributions, you can probably safely skip this step. However, if you try to compile a newer program and it requires newer versions of the libraries than your distro ships with, you will be unable to compile it without creating a patch (which is beyond the scope of this guide). The process I lay out here should be safe and will not overwrite any system files.

Unlike GCC, we will be installing this to /opt rather than /usr/local due to issues the latter can cause. See the official FAQ if you want more information.

Check your currently installed version to see if you even need to install a new version:

ldd --version

Compare that to the newest version on the glibc website. In my testing, CentOS is still stuck using 2.17, but some newer software packages insist on version 2.18 or even newer. I will be installing 2.26, so change the commands below if needed.

cd ~
wget ftpmirror.gnu.org/glibc/glibc-2.26.tar.bz2
wget ftpmirror.gnu.org/glibc/glibc-2.26.tar.bz2.sig
gpg --verify glibc-2.26.tar.bz2.sig glibc-2.26.tar.bz2

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

tar xvjf glibc-2.26.tar.bz2
mkdir -v glibc-2.26-bld
cd glibc-2.26-bld
CC="gcc -isystem /usr/local/lib/gcc/x86_64-pc-linux-gnu/7.2.0/include -isystem /usr/include" \
../glibc-2.26/configure \
--prefix=/opt/glibc
make
make check
sudo -E env "PATH=$PATH" make install

Some tests will fail because it was installed outside the /usr directory (mostly nptl tests). If you have a concern, search the Internet for the specific errors you received. It is important that you do not add /opt/glibc/lib to the system library path!

Do some cleanup:

cd ..
sudo mv glibc-*-bld /usr/local/src/
rm -rf glibc-*

You are now done installing the latest glibc libraries. If the ones provided by your system are insufficient for compiling future software, you can link to the new ones by prepending your command with env "LD_LIBRARY_PATH=/opt/glibc/lib:$LD_LIBRARY_PATH".


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 as needed).

cd ~
wget cmake.org/files/v3.10/cmake-3.10.0.tar.gz
wget cmake.org/files/v3.10/cmake-3.10.0-SHA-256.txt
diff <(sha256sum cmake-3.10.0.tar.gz | \
sed 's/ .*//') <(cat cmake-3.10.0-SHA-256.txt | \
sed -n '/cmake-3.10.0.tar.gz/p' | \
sed 's/\(.*\)cmake-3.10.0.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-3.10.0.tar.gz
mkdir -v cmake-3.10.0-bld
cd cmake-3.10.0-bld
../cmake-3.10.0/configure --prefix=/usr/local
make
make test

Assuming all tests passed, you are ready to install (I had 4 Fortran tests fail under openSUSE; not sure why, and the other 445 tests passed):

sudo env "PATH=$PATH" make install
cd ..
sudo mv cmake-*-bld /usr/local/src/
rm -rf 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 highly recommend installing the latest version of Perl at this point. 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 as needed):

cd ~
wget www.cpan.org/src/5.0/perl-5.26.1.tar.gz
wget www.cpan.org/src/5.0/perl-5.26.1.tar.gz.sha256.txt
diff <(sha256sum perl-5.26.1.tar.gz | sed 's/ .*//') \
<(cat perl-5.26.1.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-5.26.1.tar.gz
cd perl-5.26.1
./Configure -des -Dprefix=/usr/local
make
make test

Assuming all tests passed, you can continue installing.

sudo env "PATH=$PATH" make install
cd ..
rm perl-*tar*
sudo mv perl-* /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.

Leave a Reply