Contents
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
- Download the script
Save it as build_gcc.sh
Make it executable with:
chmod +x ./build_gcc.sh
Check the script's options by executing it as
./build_gcc.sh --help
- Then execute the script with the options of your choice
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:
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
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.