Saturday, June 27, 2015

Install the latest gcc 5.3 on Ubuntu 12.04(Build from source code)

Steps to Build GCC 5.3 From Source Code

<1> Pre-Knowledge
The regular procedure to build any program from source code is simply the below three steps:
① ./configure
make
③ make install
Note: Make sure you run ③ as root, which means: sudo make install

Besides the above step,  the non-trivial part of building a lib or application from source on Ubuntu( or any other Unix/Linux) systems is that you need to deal with the dependencies, otherwise you will suffer from a bunch of headache problems. 

Usually, ./configure will help you check the dependency that you have in your system, this help you identify what you are missing. However, according to my experience, it sometimes give false positive, which means, even if it says that the everything are ready, and when you do a make command, it tell you that something failed to be built, and even worse it doesn't even tell what the reason of failure, it simply gives a failure message and nothing else, this make it very hard to track what is the reason it failed.

So, same with the process of building GCC,  we need to be care of the dependencies, so let's go. 

<2> Build & Installation:

Dependency installation:
1) First, we need to build dependencies before we can install gcc: apt-get install build-essential
2) Second, we need to install these three libs, check this out: install gmp mpfr mpc

STEP 1: 
So first of all, we should get the latest version of gcc from its offical site or any mirror site.
You can manually download from the mirror site or use command:
sudo wget http://www.netgull.com/gcc/release/gcc-5.3/gcc-5.3.tar.bz2
STEP 2:
After we download the source code, we unzip(for *tar.bz2 files, use command: tar -xjf filename) it to a temporary directory, usually $HOME/Downloads or /opt. actually it doesn't matter where you put because we will delete them after we compile the source successfully.

STEP 3:
Enter the directory that you unzipped just now, say in $HOME/Downloads/gcc-5.3, then type command:
./configure --disable-checking --enable-languages=c,c++,objc 
--disable-multilib --with-system-zlib prefix=/usr/bin/gcc-5.3

options explaining:
--prefix=/usr/bin/gcc-5.3 means you want to install GCC in /usr/bin/gcc-5.3 directory, this happens when you want to custom the installation place and preserve the old compiler(in case you want keep two versions of compiler so that you can test some changes).
(GCC will be installed in /usr/local by default if you don't specify a --prefix=your_dir, If you want to override the old GCC, you should set --prefix=/usr because the default gcc that comes with Ubuntu is located at /usr/bin)

If nothing errors happened during above process, configuration should be successful now and we can jump to step 4. However, if errors happened, then we should see how we deal with them:

(1)error: build GCC requires GMP4.2+, MPFR 2.4.0+, and MPC 0.8.0+

This means it cannot find these libraries and if you are sure you have them and you know where they were installed, you can try the --with-gmp, --with-mpfr and/or --with-mpc options to specify their respective hosting sites.

or if you don't understand what exactly wrong, you can do:
sudo apt-get install libgmp-dev libmpfr-dev libmpc-dev libc6-dev
this will simply update these libraries and after that you should be okay now.

or if you want to build the latest version of above libraries, you can read this tutorial:http://juniway.blogspot.com/2015/08/building-gcc-requires-gmp-42-mpfr-231.html

(2) it says you don't have for 32bit, but only have necessary file for 64bit system, which means you need to specify whether you build only for 64bit programs, you add options:
--disable-multilib
(3) it says that it cannot find some specific libs for language GO or JAVA, blablabla, this is because when build gcc, it automatically build the compiler for other language also, if you missing some lib for those language then error will happen, the simplest way is to specify a option the you don't build compiler for those languge:

--enable-languages=c,c++,objc
this means you only build compiler for c, c++ and objc.

(4) it says some error associating with zlib, add this options will fix it:

--with-system-zlib
and also, if you still get errors message like "Failed to build lto-compress.c, zlib.h not found!"
you can do the below to fix it:
apt-get install zlib1g-dev

STEP 4:
make 
If an error happens like this:

it means that you are trying to build gcc without a C++ compiler.
To solve this, we need to install a C++ compiler first:
sudo apt-get install g++
after this, you should be good to sudo make
and then:
sudo make install
If you encounter an error like this:
error while loading shared libraries: libmpc.so.3: cannot open shared object file: 
No such file or directory
make[5]: *** [install-exec-hook] Error 1
this is probably because your /usr/local/lib directory is not in your system search path, therefore when it was linked it say can't find the target so file. the solution is to add the lib directory where you installed in to the system path:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH

STEP 5:
Now gcc-5.3 should be installed successfully!
You can check that you have /usr/bin/gcc-5.3.0 directory now, and the gcc executable file should be in /usr/bin/gcc-5.3.0/bin.



<2>Post-Installation Configuration:
Note: if you install gcc into a default directory, the below operations may not be necessary.
However, if you specific a different target installation directory instead of the default, when you type gcc --version, it still says a old version information, this is because the user-defined directory is either not in the system search path or its path is placed after the path of the old version of GCC(e.g. PATH=/usr/bin;/usr/local/new_gcc_dir, you type gcc, it will search this PATH in order, if your old GCC is in /usr/bin/gcc, your new gcc won't get executed),  usually, /usr/bin/gcc is a symbolic link which points to a executable /usr/bin/gcc_oldversion, and if our new gcc executable is /usr/local/new_gcc_dir/gcc5.3, we can do this to update the gcc link:
remove old links first:
sudo update-alternatives --remove-all gcc 
sudo update-alternatives --remove-all g++
then update:
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5.3/bin/gcc 50
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/gcc-5.3/bin/g++ 50
Note: alternatives are located in /etc/alternatives

How to enable c++11 features?
Compile your *.cpp files, use -std=c++11 options(use gcc -std=c11 if you compile *.c file) to specify that you need c++11 feature supports.
a more complete command may look like this:
g++ -std=c++11 -O2 -Wall -pedantic -lpthread main.cpp
Note: If you want to enable -std=c++11 as default, you can type command: g++='g++ -std=c++11'
so every time when you use g++ to compile *.cpp files, c++11 features are enabled.

If you want this config to be permanent(which means when you reboot the system or open a new session window it still works), you can open ~/.bashrc file, and add one line: alias g++="g++ -std=c++11'.

However, there are some on whether you should enable c++11 features as default, since it may lead to unpleasant surprises when you work with some old codes or code from others, which make this option not portable.
My solution is to specify a different name for g++ command.
e.g :alias g++11 = "g++ -std=c++11 -O2 -Wall -pedantic'
by doing this you avoid polluting the global g++, and still can use g++11 for off-line programming, or you can specify the c++11 option in a Makefile for your specific project.(Makefile Tutorial)
Note:
As the new ISO C++ standard published in 2011, most of new features have been implemented in an experimental C++11 mode in GCC, therefore, to select this standard in GCC, use the option '-std=c++11 or std=c++14'; also, to obtain all the diagnostics required by the standard, you should specify '-pedantic' (or '-pedantic-errors' if you want them to be errors rather than warnings).

Also, as the official gnu site noted, C++14 features are available as part of "mainline" GCC in the trunk of GCC's repository and in GCC 4.8 and later. To enable C++14 support, add the command-line parameter -std=c++14 to your g++ command line. Or, to enable GNU extensions in addition to C++14 extensions, add -std=gnu++14.

In gcc6.0, -std=gnu++14 is specified by default, which means you don't need to manually add an alias for this.

C++ 2014
In this implementation the -std=gnu++14 or -std=c++14 flag must be used to enable language and library features. 


C++ 2017
In this implementation the -std=gnu++1z or -std=c++1z flag must be used to enable language and library features.


Run your test program:
./a.out

If an error happened like this:
/usr/lib/x86_64_linux-gnu/libstdc++.so.6: version 'GLIBCXX_3.4.21' not found

this is because you old libstdc++.so.6 file is located at /usr/lib/x86_64_linux-gnu/ directory(we can try command: locate libstdc++.so.6  to find all the references in file system),


but after you intall the newest gcc-5.3 to a user-defined location, for example, the lib files are installed in /usr/bin/gcc-5.3/lib64, however the old symbolic link isn't updated, that's why it says it cannot find *.so, blablabla

we need to remove the old links
cd /usr/lib/x86_64_linux-gnu
sudo mv libstdc++.so.6.libstdc++.so.6_bak
sudo mv libstdc++.so.6.0.16 libstdc++.so.6.0.16_bak
(1) then, add this directory in our system lib search path:
export LD_LIBRARY_PATH=/usr/lib/gcc-5.3/lib64:$LD_LIBRARY_PATH
or
(2) relink old links to the right place:
sudo ln -s /usr/bin/gcc-5.3/lib64/libstdc++.so.6
sudo ln -s /usr/bin/gcc-5.3./lib64/libstdc++.so.6.0.16

A useful method to deal with lib not found problem
When you install(build) other libs, it may use dependent libs for its building process, and it's highly possible you will see error messages like :"libstdc++.so.6: version `GLIBCXX_3.4.20`" not found(required by ...somefile), this is because the dependent lib GLIBCXX_3.4.20 is not found in libstdc++.so.6, and therefore your target lib or exe cannot be built.



use the below command to list all the `GLIBC` libs that libstdc++.so.6 contains:
strings /usr/lib/libstdc++.so.6|grep "GLIBC"


usually after you install the latest gcc compiler, all the dependencies should possibly be latest version, all you need to do is to find where they are located. usually they are located in /usr/lib/YOUR_GCC_INSTALLATION_DIRECTORY/lib64/

and make sure this directory is in your system path, so the system can find it automatically.
if you don't konw how to do it, just copy the files to some system-recognized location, say:

sudo cp /usr/bin/gcc-5.3/lib64/libstdc++.so.6 /usr/lib/x86_64_linux-gnu/
sudo cp /usr/bin/gcc-5.3/lib64/libstdc++.so.6.0.21 /usr/lib/x86_64_linux-gnu/

another, use  -static-libstdc++ options to compile source code if you don't fix the problem using the above ways.

Finally, if all errors are solved, remove the source code files you put in $HOME/Download directory if you don't want to save them for the future re-install of gcc



<3> GDB Debugger update!
Don't forget this step if you use GDB to debug your program.
When you update your gcc compiler, if the gdb is not updated accordingly, it will not work because of the new symbols and new features. So update your gdb the similar way as you do to the gcc.
The lastest GDB source: http://www.gnu.org/software/gdb/download/

Done! Now enjoy the latest GCC!







11 comments:

  1. thanks, it helped me a lot. Fix update-alternatives, you forgot to write priority.

    ReplyDelete
  2. This comment has been removed by the author.

    ReplyDelete
  3. Thank you so much. I am unexperienced in Linux and have to port a C++11 based app to ubuntu 12.04. Your instructioons worked perfectly for me and saved me days of investigation.

    ReplyDelete
  4. Excellent tutorial, very complete and well explained, thanks.

    ReplyDelete
  5. Chunhui Shi, excelent work! Thank you.

    ReplyDelete
  6. Very well explained. Pretty helpful. Thanks

    ReplyDelete
  7. Thanks for this. I got exactly the errors you predicted I would get ;)

    ReplyDelete
  8. QUOTE:
    STEP 1:
    So first of all, we should get the latest version of gcc from its offical site or any mirror site.
    You can manually download from the mirror site or use command:
    sudo wget http://www.netgull.com/gcc/release/gcc-5.3/gcc-5.3.tar.bz2

    Link was changed! Please, check it.
    now it: sudo wget http://www.netgull.com/gcc/releases/gcc-5.3.0/gcc-5.3.0.tar.bz2

    ReplyDelete