3
\$\begingroup\$

I have written this script to install gcc (here in version 4.9.2) on Centos6.6. I am only interested in C and C++ support.

Please comment if this is any good and can I make it better before I get the packages for those.

#!/bin/bash

LOGFILE=/tmp/gcc_install.log

# $1 - package name
# $2 - status
errorIf(){
if [ $2 -ne 0 ]; then
    echo "Something was wrong with $1"
    exit 1
fi
}

################################################################################
################################# SCRIPT START #################################

if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root" 1>&2
   exit 1
fi

# only one param - gcc's source directory absolute location
if [ $# -ne 1 ]; then
    echo "Please give the gcc source directory as argument"
    exit 1
fi

if [ ! -d "$1" ]; then
    echo "gcc's source directory that you have passed doesn't exist!"
    exit 1
fi

SOURCE_DIR="$1"
SOURCE_DIR_NAME="${SOURCE_DIR##*/}"
cd "$SOURCE_DIR"/contrib/

################################################################################
################################# gmp, mpgr, mpc  ##############################
# this script assumes that you have ran download_prerequisites from gcc's contrib dir
# contrib with downloaded gmp, mpgr, mpc (used download_prerequisites)
if [ ! -d gmp ] || [ ! -d mpfr ] || [ ! -d mpc ]; then
    echo "There is no gmp or mpfr or mpc directory in `pwd`. Please run download_prerequisites."
    exit 1
fi

echo "Installing gcc and dependencies. You can check the status and results in $LOGFILE"

#gmp
cd gmp && ./configure --enable-shared --enable-static --prefix=/usr/local >$LOGFILE 2>&1 && make >$LOGFILE 2>&1 && make check >$LOGFILE 2>&1 && make install >$LOGFILE 2>&1 && cd ..
ret="$?"
errorIf gmp $ret
echo "gmp Installed!:)"

#mpfr
cd mpfr && ./configure --enable-shared --enable-static --prefix=/usr/local --with-gmp=/usr/local >$LOGFILE 2>&1 && make >$LOGFILE 2>&1 && make check >$LOGFILE 2>&1 && make install >$LOGFILE 2>&1 && cd ..
ret="$?"
errorIf mpfr $ret
echo "mpfr Installed!:)"

#mpc
cd mpc && ./configure --enable-shared --enable-static --prefix=/usr/local --with-gmp=/usr/local --with-mpfr=/usr/local >$LOGFILE 2>&1 && make >$LOGFILE 2>&1 && make check >$LOGFILE 2>&1 && make install >$LOGFILE 2>&1 && cd ..
ret="$?"
errorIf mpc $ret
echo "mpc Installed!:)"

echo /usr/local/lib/ >> /etc/ld.so.conf
echo /usr/local/lib64/ >> /etc/ld.so.conf
ldconfig

cd ../../
ulimit -s 32768 # for gcc tests
mkdir -p /usr/share/gdb/auto-load/usr/lib
mkdir -p gcc-build
cd gcc-build

# find mv .py command is due to this ldconfig error (gcc copies some .py files into /usr/local/lib64/)
# ldconfig: /usr/local/lib/../lib64/libstdc++.so.6.0.20-gdb.py is not an ELF file - it has the wrong magic bytes at the start.
../$SOURCE_DIR_NAME/configure --enable-shared --disable-bootstrap --with-system-zlib --enable-languages=c,c++ --enable-libgomp --enable-threads=posix --with-gmp=/usr/local --with-mpfr=/usr/local --with-mpc=/usr/local --with-fpmath=sse --disable-multilib >$LOGFILE 2>&1 && make >$LOGFILE 2>&1 && make install >$LOGFILE 2>&1 && find /usr/local/lib64 -iname "*.py" -exec mv {} /usr/share/gdb/auto-load/usr/lib/ \;  >$LOGFILE 2>&1 && ldconfig >$LOGFILE 2>&1

echo "gcc from $SOURCE_DIR_NAME Installed!:)"
\$\endgroup\$
3
\$\begingroup\$

For the most part, your script is quite fine.

Taming the long lines

These blocks of code have some issues:

cd gmp && ./configure --enable-shared --enable-static --prefix=/usr/local >$LOGFILE 2>&1 && make >$LOGFILE 2>&1 && make check >$LOGFILE 2>&1 && make install >$LOGFILE 2>&1 && cd ..

Issues:

  • The first line is too long
    • It's easy to be lazy to scroll to the right
    • Code that's less visible, is more error-prone, easy to overlook something
    • Long lines are harder to edit in practice
  • Wrapping a bunch of commands in cd somewhere; ...; cd .. is error prone: it's an extra mental burden to make sure that you'll end up in the right directory after the chain of commands, keeping in mind possible errors too. As much as possible, it's good to look for alternatives.
  • Too much repetition of >$LOGFILE 2>&1

It would be better this way:

(
    cd gmp && \
        ./configure --enable-shared --enable-static --prefix=/usr/local && \
        make && make check && make install
) >$LOGFILE 2>&1

The (...) is a sub-shell, so directory changes won't affect the enclosing script. Once the sub-shell is finished, you'll be back in the original directory. Grouping commands like this (also with {...}) makes it easier to redirect all output. I didn't break up the lines of make a b c, because the line was already short enough, and quite idiomatic that way. The exit code after the (...) will be as you would expect, the grouping won't affect it.

Do similarly for all the long lines.

Avoid changing directories in the middle of scripts. When you must do, consider wrapping the relevant commands within (...).

Simplifying the exit code handling

The exit code handling can be simpler:

ret="$?"
errorIf gmp $ret
echo "gmp Installed!:)"

There's no need to save $? in ret. You could use it directly. In fact, the function can use it directly, no need to pass it explicitly. You can rewrite the errorIf function like this:

errorIf() {
    if [ $? -ne 0 ]; then
        echo "Something was wrong with $1"
        exit 1
    fi
}

And then simplify the exit code handling to this:

errorIf gmp
echo "gmp Installed!:)"

ShellCheck

The http://www.shellcheck.net/# website is pretty awesome. It points out a few additional issues I recommend to fix.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.