How to change default GCC compiler to be used with MPI on Linux CentOS - c++

I have two GCC compilers installed on a Linux (CentOS) machine. The old version of GCC (4.4.7) is in the default folder (came with CentOS) and the newer one that I intend to use is in /usr/local/gcc/4.9.3/. My code utilizes MPI and LAPACK/LAPACKE/BLAS libraries and with the old GCC I used to compile source (for example “main.cpp”) like this:
mpiCC main.cpp -o main -L/home/USER1/lapack-3.6.1 -llapacke -llapack -lblas -lm –Wall
This still invokes the old GCC 4.4.7. What should I modify so the above MPI compilation (mpiCC) invokes GCC 4.9.3 executable from the new location at /usr/local/gcc/4.9.3/el6/bin/ ?
From MPICH Installer's Guide version 3.2 (page 6):
"The MPICH configure step will attempt to find the C, C++, and Fortran compilers for you, but if you either want to override the default or need to specify a compiler that configure doesn't recognize, you can specify them on the command line [...]. For example, to select the Intel compilers instead of the GNU compilers on a system with both, use"
./configure CC=icc CXX=icpc F77=ifort FC=ifort ...
Is there a way to dicriminate between different version of GCC compilers in ./configure ?

I guess mpiCC uses the first gcc compiler found in the $PATH variable.
You should be able to set the new version of gcc by running:
PATH="/usr/local/gcc/4.9.3/el6/bin:$PATH" mpiCC main.cpp -o main -L/home/USER1/lapack-3.6.1 -llapacke -llapack -lblas -lm –Wall

If you really want two versions of GCC installed at the same time and use both of them here is a good link that explains how to do this:
http://gcc.gnu.org/faq.html#multiple

Finally found how. Here is the recipe:
1) check your if you shell is bash, if not set it to bash: $ echo $SHELL
/bin/tcsh
It was tcsh and needed to be set to bash.
2) Switch to bash: $ bash
bash-4.1$
3) Add new version of GCC to the front of the PATH:
bash-4.1$ export PATH=/usr/local/gcc/4.9.3/el6/bin:$PATH
4) Check the PATH: bash-4.1$ echo $PATH
/usr/local/gcc/4.9.3/el6/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin
5) Check version of GCC used (It picks up the first GCC from the PATH):
bash-4.1$ gcc --version
gcc (GCC) 4.9.3
Note: this is just for the current session.

Related

G++ 4.9.2 and 8.2.0 - final binary's dependency with default lib path searching ./../lib directory (implicit RPATH issue)

I encountered an odd difference between the binary produced by a 4.9.2 G++ and a 8.2.0 G++ on a Linux, when upgrading from the former to the latter. I was able to narrow it down to the below minimized snippet
//main.cpp
int main(){}
//emptylib.cpp
#!/bin/sh
#to build and verify output
rm -rf bin lib *.o
gcc_bin=/path/to/gcc_4.9.2/bin
#gcc_bin=/path/to/gcc_8.2.0/bin
${gcc_bin}/g++ -B${gcc_bin} -c main.cpp
${gcc_bin}/g++ -B${gcc_bin} -c emptylib.cpp
${gcc_bin}/g++ -B${gcc_bin} -shared emptylib.o -o libemptylib.so
${gcc_bin}/g++ -B${gcc_bin} main.o -o main -L. -lemptylib
mkdir bin
mkdir lib
mv libemptylib.so lib/
mv main bin/
ldd bin/main
The result is a bit strange, because I have provided no -rpath=../lib, but all the same, with the 4.9.2 compiler driver I end up with (in the output of ldd):
libemptylib.so => /path/to/bin/../lib/libemptylib.so
and with 8.2.0
libemptylib.so => not found
the lib does not resolve, as I would expect. I haven't been able to see any documentation that hints at a search for ../lib in any version, but I would not expect this to be a behavior by any version. Was this a bug in 4.9.2 or some earlier version or something that shouldn't have happened in the first place?
As a side note, the 8.2.0 and the 4.9.2 don't have an ld inside of their bin directory (despite me putting the -B in the code snippet), so both compiler drivers are using the /usr/bin/ld (I've verified as much) and producing different results based on the compiler driver alone.
Update:
On request, I ran readelf -d bin/main on both binaries and I did receive different output for rpath. GCC 4.9.2 gave me:
0x000000000000000f (RPATH) Library rpath: [$ORIGIN:$ORIGIN/../lib64:$ORIGIN/../lib:/path/to/gcc_libs/lib64:/path/to/gcc_libs/lib:/path/to/gcc_4.9.2/lib64:/path/to/gcc_4.9.2/lib]
where 8.2.0 did not have that
0x0000000000000001 (NEEDED) Shared Library: [libemptylib.so]
So I guess I have an answer to what happened. So how did this end up in my binary in 4.9.2, and why did it change between the two versions where now it doesn't in 8.2.0?
I did receive different output for rpath.
rpath: [$ORIGIN:$ORIGIN/../lib64:$ORIGIN/../lib:/path/to/gcc_libs/lib64:/path/to/gcc_libs/lib:/path/to/gcc_4.9.2/lib64:/path/to/gcc_4.9.2/lib]
So the difference is in how GCC 4.9.2 vs. 8.2.0 were configured.
I am guessing that 8.2 came from your distribution (or at least was configured with default installation paths), whereas 4.9 was configured to be installed into /path/to/gcc_4.9.2.
That explains why 4.9 adds -rpath with /path/to/gcc_4.9.2/lib64 for a 64-bit builds. It does not however explain where $ORIGIN of /path/to/gcc_4.9.2/lib (the latter shouldn't be part of a 64-bit build) come from.
Configuring GCC so that it puts exactly what's necessary, no more and no less, is a bit of a black magic. I wouldn't be surprised if 4.9 had some bugs in that area.

Automatically select a C++11-compatible g++ version in the Makefile

The problem:
2 version of g++ installed on a computer running Ubuntu 12.04. They are the versions 4.6 and 5.2.
I have to compile a C++11 program using a Makefile. If I use g++ as compiler it calls automatically the version 4.6, it does not support c++11 so the compilation fails. I've followed a tutorial online, so that now if I call g++ it calls automatically the version 5.2 and now it works.
I find this solution not so good, since it works only on my PC. Is there a way to recognize in the Makefile if the default g++ version support C++11 and, in case not, switch to a more recent version?
Thank you!
Is there a way to recognize in the Makefile if the default g++ version support C++11 and, in case not, switch to a more recent version?
You can certainly detect the version of the default compiler available in PATH in your makefile. However, where do you search for another version?
The standard approach is to let the user specify the C compiler through CC and C++ compiler through CXX make variables, e.g.: make CC=/path/to/my/gcc CXX=/path/to/my/g++.
You can always select which gcc to use while invoking make
make CXX=/gcc/path/of/your/choice
otherwise you can detect gcc version using
ifdef CXX
GCC_VERSION = $(shell $(CXX) -dumpversion)
else
GCC_VERSION = $(shell g++ -dumpversion)
endif
in Makefile and while using, you can test if your gcc is >=4.6
ifeq ($(shell expr $(GCC_VERSION) '>=' 4.6), 1)
UPDATE: newer gcc needs -dumpfullversion together (icx is the CC from Intel OneAPI)
$ icx -dumpversion
14.0.0
$ gcc -dumpversion
9
$ icx -dumpfullversion -dumpversion
14.0.0
$ gcc -dumpfullversion -dumpversion
9.3.1
One very simple way is to use conditional statements in your makefile, and go for versions which you know are compatible, and only use the default gcc as a fallback. Here's a basic example:
CXX=g++
ifeq (/usr/bin/g++-4.9,$(wildcard /usr/bin/g++-4.9*))
CXX=g++-4.9
# else if... (a list of known-to-be-ok versions)
endif
The other, more robust method, is to generate your makefile using a script that checks for capabilities using test compilations, kind of like what ./configure usually does. I really don't mean to recommend autotools, though.
The thing to do is build your Makefile to use as many implicit rules as possible. By default compilation uses various environment variables.
The variable $(CXX) is the C++ compiler command and defaults to g++ on Linux systems. So clanging CXX to a different compiler executable will change the compiler for all implicit compile commands.
When you write explicit rules use the same variable that the implicit rules use. So instead of this:
program: program.cpp
g++ -o program program.cpp
Do this:
program: program.cpp
$(CXX) -o program program.cpp
Other variables you should use are:
CPPFLAGS = -Iinclude
CXXFLAGS = -std=c++14 -g3 -O0
Those are for pre-processing flags CPPFLAGS and compiler flags CXXFLAGS and library linking flags LDLIBS.
Using the default environment variables allows the person compiling the project the freedom to control the compilation for their desired environment.
See the GNU make manual
This works for me:
cmake_minimum_required(VERSION 2.8.11)
project(test)
if (${CMAKE_CXX_COMPILER_VERSION} LESS 5.0)
message(FATAL_ERROR "You need a version of gcc > 5.0")
endif (${CMAKE_CXX_COMPILER_VERSION} LESS 5.0)
add_executable(test test.cpp)
You can check in your source code the gcc version and abort compilation if you don't like it. Here is how it works:
/* Test for GCC > 4.6 */
#if !(__GNUC__ > 3 && __GNUC_MINOR__ > 6)
#error gcc above version 4.6 required!
#endif

Debug symbol bug with MacPorts installed GCC 4.9?

I have recently installed GCC 4.9.2 (port name gcc49) through MacPorts. I am quite happy with its new features such as colorized diagnostics and C++1y/C++14 support improvements, etc.
However, since I started to compile code using GCC 4.9.2, I realized that it is not generating debug symbol directory *.dSYM and gdb says "no debugging symbols found" when I try to debug a program I compiled with -g flag.
Is this a MacPorts specific bug or is there a problem with GCC 4.9?
Thanks
It is not a MacPorts specific issue. MacPorts doesn't really do much to customize the gcc ports.
If you want to create a dSYM bundle and strip your executable, you should just do something like:
gcc-mp-4.9 -g3 -c example.c
gcc-mp-4.9 example.o -o example
dsymutil --out example.dSYM example
strip -S -x example
As a side note, if you want C++11/C++14 support, I suggest you use the clang-3.5 port as that will allow you to use libc++ from the system instead of libstdc++ from MacPorts (and allow you to use system and MacPorts C++ libraries rather than just the STL). Also, lldb is really the preferred debugger for OS X these days.

Linking g++ 4.8 to libstdc++

I downloaded and built gcc 4.8.1 on my desktop, running 64-bit Ubuntu 12.04. I built it out of source, like the docs recommend, and with the commands
../../gcc-4.8.1/configure --prefix=$HOME --program-suffix=-4.8
make
make -k check
make install
It seemed to pass all the tests, and I installed everything into my home directory w/ the suffix -4.8 to distinguish from the system gcc, which is version 4.6.3.
Unfortunately when I compile c++ programs using g++-4.8 it links to the system libc and libstdc++ rather than the newer ones compiled from gcc-4.8.1. I downloaded and built gcc 4.8 because I wanted to play around with the new C++11 features in the standard library, so this behaviour is definitely not what I wanted. What can I do to get gcc-4.8 to automatically link to the standard libraries that came with it rather than the system standard libraries?
When you link with your own gcc you need to add an extra run-time linker search path(s) with -Wl,-rpath,$(PREFIX)/lib64 so that at run-time it finds the shared libraries corresponding to your gcc.
I normally create a wrapper named gcc and g++ in the same directory as gcc-4.8 and g++-4.8 which I invoke instead of gcc-4.8 and g++-4.8, as prescribed in Dynamic linker is unable to find GCC libraries:
#!/bin/bash
exec ${0}SUFFIX -Wl,-rpath,PREFIX/lib64 "$#"
When installing SUFFIX and PREFIX should be replaced with what was passed to configure:
cd ${PREFIX}/bin && rm -f gcc g++ c++ gfortran
sed -e 's#PREFIX#${PREFIX}#g' -e 's#SUFFIX#${SUFFIX}#g' gcc-wrapper.sh > ${PREFIX}/bin/gcc
chmod +x ${PREFIX}/bin/gcc
cd ${PREFIX}/bin && ln gcc g++ && ln gcc c++ && ln gcc gfortran
(gcc-wrapper.sh is that bash snippet).
The above solution does not work with some versions of libtool because g++ -Wl,... -v assumes linking mode and fails with an error.
A better solution is to use specs file. Once gcc/g++ is built, invoke the following command to make gcc/g++ add -rpath to the linker command line (replace ${PREFIX}/lib64 as necessary):
g++ -dumpspecs | awk '/^\*link:/ { print; getline; print "-rpath=${PREFIX}/lib64", $0; next } { print }' > $(dirname $(g++ -print-libgcc-file-name))/specs
I just had the same problem when building gcc-4.8.2. I don't have root access on that machine and therefore need to install to my home directory. It took several attempts before I figured out the magic required to get this to work so I will reproduce it here so other people will have an easier time. These are the commands that I used to configure gcc:
prefix=/user/grc/packages
export LDFLAGS=-Wl,-rpath,$prefix/lib
export LD_RUN_PATH=$prefix/lib
export LD_LIBRARY_PATH=$prefix/lib
../../src/gmp-4.3.2/configure --prefix=$prefix
../../src/mpfr-2.4.2/configure --prefix=$prefix
../../src/mpc-0.8.1/configure --prefix=$prefix --with-mpfr=$prefix --with-gmp=$prefix
../../src/gcc-4.8.2/configure --prefix=$prefix --with-mpfr=$prefix --with-gmp=$prefix --with-mpc=$prefix --enable-languages=c,c++
That got me a working binary but any program I built with that version of g++ wouldn't run correctly unless I built it with the -Wl,-rpath,$prefix/lib64 option. It is possible to get g++ to automatically add that option by providing a specs file. If you run
strace g++ 2>&1 | grep specs
you can see which directories it checks for a specs file. In my case it was $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2/specs so I ran g++ -dumpspecs to create a new specs file:
cd $prefix/lib/gcc/x86_64-unknown-linux-gnu/4.8.2
$prefix/bin/g++ -dumpspecs > xx
mv xx specs
and then edited that file to provide the -rpath option. Search for the lines like this:
*link_libgcc:
%D
and edit to add the rpath option:
*link_libgcc:
%D -rpath /user/grc/packages/lib/%M
The %M expands to either ../lib or ../lib64 depending on whether you are building a 32-bit or a 64-bit executable.
Note that when I tried this same trick on an older gcc-4.7 build it didn't work because it didn't expand the %M. For older versions you can remove the %M and just hardcode lib or lib64 but that is only a viable solution if you only ever build 32-bit executables (with lib) or only ever build 64-bit executables (with lib64).
gcc -print-search-dirs will tell you where your compiler is looking for runtime libraries, etc. You can override this with the -B<prefix> option.

PARI/GP and gcc

I am trying to install PARI/GP and in the configuration step I get:
$ ./Configure
[...]
Looking for the compilers ...
...cc is /usr/bin/cc
...gcc is /usr/local/bin/gcc
GNU compiler version 4.8.0 20120705 (experimental) (GCC)
###
### C compiler does not work. PARI/GP requires an ANSI C compiler! Aborting.
###
### Compiler was: /usr/local/bin/gcc
$ gcc --version
gcc (GCC) 4.8.0 20120705 (experimental)
This is strange because the documentation says:
"Only ANSI C and C++ compilers are supported. Choosing the GNU compiler
gcc/g++ enables the inlining of kernel routines (about 20% speedup; if you
use g++, it is a good idea to include the -fpermissive flag). If you choose
not to use gcc, the C++ version of Pari will be a little faster because of
general inlining, but can be used in library mode only with C++ programs.
We strongly recommand using gcc all the way through."
I have also tried with g++ with the same result.
I am trying to compile on a linux x86_64.
Any ideas?
Thanks in advance,
M;
The config/get_cc script in PARI's top level tried to compile a test program
and failed.
Look for the line
$CC $CFLAGS $extraflag -o $exe ansi.c 2>/dev/null && $RUNTEST $exe
and remove the 2>/dev/null. Configure should now print out explicit error
messages from the compiler. They should provide a hint.
I had the same problem. Here is the solution for Linux Mint 17.1 64-bit:
sudo apt-get install gcc libc6-dev libgmp-dev
This command also installs the GMP library (recommended for PARI/GP).
Thanks to K.B. for the hint on how to see the problem.