Build a specific version of the GNU Compiler Collection GCC

The script below facilitates building your own version of GCC in a location of your choosing.
It was tested with the default gcc and g++ compiler installed with Debian Buster, Debian 8.3.0-6 and successfully builds versions 13.2.0, 12.2.0, 12.1.0, 11.3.0, 11.2.0, 10.3.0, 9.4.0, 8.5.0, 7.5.0, 6.5.0.

build_gcc.sh

#!/bin/bash

# Install a specific gcc version in user space

PROD='gcc'

# Show usage of this script
function usage {
    echo "Usage: ${BASH_SOURCE[0]}  [--gcc-version=<version>] [--prefix=<directory>] [--build-dir=<directory>]"
    echo '  --gcc-version=<version>  Supply the gcc version to build'
    echo '  --prefix=<directory>     The installation directory'
    echo '  --build-dir=<directory>  The build directory'
    echo '  --help                   Display this usage information'
    echo
    echo 'For every unset option a default is used'
    echo 'All options (set or defaults) are shown at build start.'
    echo
    echo 'This script was tested with the following versions of gcc:'
    echo '13.2.0, 12.2.0, 12.1.0, 11.3.0, 11.2.0, 10.3.0, 9.4.0, 8.5.0, 7.5.0, 6.5.0'
}

# Returns true, if version of $1 is greater than $2
function version_gt() {
    test "$(printf '%s\n' "$@" |
        sort -V |
        head -n 1)" != "${1}"
}

# Iterate over options and set them
shopt -s extglob
while (($#)); do
    case "${1}" in
    --gcc-version=*)
        VERSION="${1##*=}"
        shift
        ;;
    --prefix=*)
        PREFIX="${1##*=}"
        shift
        ;;
    --build-dir=*)
        BUILDDIR="${1##*=}"
        shift
        ;;
    --help)
        usage
        shift
        exit 0
        ;;
    *)
        echo "Unknown argument '${1}' ignored"
        echo
        usage
        shift
        exit 1
        ;;
    esac
done

# Set default if no option was given
if [[ -z ${VERSION} ]]; then
    VERSION="7.5.0"
fi

if [[ ${VERSION} =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
    # The option matches a version string
    WORKDIR="/scratch/${USER}/${PROD}-${VERSION}"
    # Set defaults if no options were given
    if [[ -z ${PREFIX} ]]; then
        PREFIX="${WORKDIR}/install"
    fi
    if [[ -z ${BUILDDIR} ]]; then
        BUILDDIR="${WORKDIR}/build"
    fi
    # Summarize options
    echo 'Using options:'
    echo "- gcc version:       ${VERSION}"
    echo "- prefix directory:  ${PREFIX}"
    echo "- build directory:   ${BUILDDIR}"

    # Create paths used for building and installation
    mkdir -v -p "${WORKDIR}" "${BUILDDIR}" "${PREFIX}" &&
        cd "${WORKDIR}" &&
        # Download gcc
        wget -c "https://ftpmirror.gnu.org/${PROD}/${PROD}-${VERSION}/${PROD}-${VERSION}.tar.gz" &&
        # Extract gcc archive
        tar --overwrite -vxzf "${PROD}-${VERSION}.tar.gz" &&
        cd "${WORKDIR}/${PROD}-${VERSION}" &&
        # Download prerequisites
        contrib/download_prerequisites &&
        cd "${WORKDIR}/build" &&
        # Configure build
        ../${PROD}-"${VERSION}"/configure \
            --build=x86_64-linux-gnu \
            --host=x86_64-linux-gnu \
            --target=x86_64-linux-gnu \
            --prefix="${PREFIX}" \
            --enable-checking=release \
            --enable-languages=c,c++ \
            --disable-nls \
            --disable-multilib \
            --program-suffix="-${VERSION}" &&
        # Start build
        make -s -j "$(nproc)" &&
        # Install
        make install-strip &&
        echo &&
        echo "${PROD}-${VERSION} was successfully built and installed in ${PREFIX}" &&
        exit 0
else
    echo "Version '${VERSION}' does not match a version string of the form n.m.p"
    exit 1
fi

The build script generates binaries with a version suffix referred to as -n.m.p in this article, for example the GCC compiler may be called gcc-11.3.0.

Using your new GCC

To use your new version of the GCC:

  1. Prepend its installation path (what you used in the --prefix option above) to your PATH environment variable:

    export PATH=/path/to/my/gcc/bin:$PATH
    
  2. And set the CC and CXX environment variables to the full path of your gcc and g++ binaries:

    export CC=/path/to/my/gcc/bin/gcc-n.m.p
    export CXX=/path/to/my/gcc/bin/g++<n.m.p
    

If you intend to use only the version you built now, you may set convenient versionless links for each GCC binary:

cd /path/to/my/gcc/bin
version=11.3.0; for binary in *-"$version"; do ln -s $binary ${binary%-$version}; done

Show gcc in your PATH

The following alias lists all found gcc's in your PATH, which is helpful for troubleshooting:

alias showgccs='{ echo "PATH;VERSION" && compgen -c |grep -E "^gcc(-[0-9.-]+|)$" |sort -u |xargs -r which -a |while read -r gcc_; do echo $gcc_ && $gcc_ --version |head -n1; done |paste -d";" - - ;} |column -t -s";"'

Without having installed any additional GCC versions yourself this shows only the system gcc:

PATH            VERSION
/usr/bin/gcc    gcc (Debian 8.3.0-6) 8.3.0
/usr/bin/gcc-8  gcc-8 (Debian 8.3.0-6) 8.3.0

Building gcc 5.5.0

The following patch enables building gcc 5.5.0 with gcc 8.3.0:

--- x86_64-linux-gnu/libgcc/md-unwind-support.h.orig    2021-08-26 13:55:12.152350756 +0200
+++ x86_64-linux-gnu/libgcc/md-unwind-support.h 2021-08-26 14:03:59.361317827 +0200
@@ -58,7 +58,7 @@
   if (*(unsigned char *)(pc+0) == 0x48
       && *(unsigned long long *)(pc+1) == RT_SIGRETURN_SYSCALL)
     {
-      struct ucontext *uc_ = context->cfa;
+      struct ucontext_t *uc_ = context->cfa;
       /* The void * cast is necessary to avoid an aliasing warning.
          The aliasing warning is correct, but should not be a problem
          because it does not alias anything.  */
@@ -138,7 +138,7 @@
        siginfo_t *pinfo;
        void *puc;
        siginfo_t info;
-       struct ucontext uc;
+       ucontext_t uc;
       } *rt_ = context->cfa;
       /* The void * cast is necessary to avoid an aliasing warning.
          The aliasing warning is correct, but should not be a problem

In case you need this version of gcc, apply the patch to the source before running the configure part of the script.

Programming/DevTools/BuildGCC (last edited 2023-08-15 12:49:54 by stroth)