Compiling NucNet Tools with the clang and gcc compilers on a mac

In a previous post, I demonstrated how to compile NucNet Tools with clang and gcc. Since then, we have made NucNet Tools dependent on Boost program options, which are compiled libraries. This adds some difficulty in that the libraries compiled for gcc are not compatible with clang. In this post, I will show how I switch between gcc and clang to compile NucNet Tools.

A user does not need to do this, but I will begin by starting with a clean slate for Boost. I uninstall the Boost that I installed with mac ports by typing:

sudo port uninstall boost

and I remove the version of Boost I installed with git by typing

rm -fr boost

in the directory above my git installation of Boost. I also ensure that I am using clang by typing

sudo port select --set gcc none

as before. I now reinstall Boost by typing:

sudo port install boost

I now change into NucNet Tools, update, and try compiling examples/network/run_entropy.cpp:

cd nucnet-tools-code

svn up

cd examples/network

make clean

make run_entropy

I get an error

  clang: error: unsupported option '-fopenmp'

which reminds me that my current version of clang does not support OpenMP (though it seems more recent versions do). To fix this, I type

export NNT_NO_OPENMP=1

and try again:

make run_entropy

This proceeds with a lot of warnings, but the codes compile. I confirm successful compilation by typing

./run_entropy

which returns the usage statement.

I now try compiling with gcc. I type

sudo port select --list gcc

which in my case returned

 Available versions for gcc:
     mp-gcc5
     none (active)

If I had gotten no available gcc version, I could install it with mac ports, as before. For example, I could type

sudo port install gcc5

I select mp-gcc5

sudo port select --set gcc mp-gcc5

I then unset the NNT_NO_OPENMP environment variable

unset NNT_NO_OPENMP

and recompile

make clean

make run_entropy

The codes compile until they try to link with the program options library. I then get a bunch of errors that end with

   "boost::program_options::value_semantic_codecvt_helper<char>::parse(boost::any&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, bool) const", referenced from:
  vtable for boost::program_options::typed_value<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, char> in run_entropy.o
  ld: symbol(s) not found for architecture x86_64
  collect2: error: ld returned 1 exit status
  make: *** [run_entropy] Error 1

This is because the Boost I installed with mac ports has libraries compiled with clang but I'm trying to link to those libraries with the gcc compiler.

To compile with gcc, I need to link to libraries compiled with gcc. To do this, I reinstall Boost via git. I change into the parent directory (here, I choose my home directory) where I want this version of Boost and clone it:

cd ~

git clone --recursive https://github.com/boostorg/boost.git

Once this is done, I want to compile the program_options library with gcc. I again make sure I am using my installed gcc by typing

sudo port select --set gcc mp-gcc5

I then change into the boost directory and compile program_options

cd boost

./bootstrap.sh --with-toolset=gcc --with-libraries=program_options

Here I choose just to install the program_options library. Had I run ./bootstrap.sh without the --with-libraries option, I would have compiled all the libraries, which is ok but takes a while creating a lot of libraries NucNet Tools does not use. I then create the program_options library by typing

./b2

This script runs the compilations and produces static libraries--unfortunately, the current Boost script has an error for creating dynamic libraries with gcc. When the compilation is done, I see that the libraries are installed in boost/stage/lib (in my case, the full path is /Users/bradleymeyer/boost/stage/lib).

I now try compiling NucNet Tools with gcc again. I type

cd ~/nucnet-tools-code/examples/network

I set the appropriate environment variables to point gcc to the right directories:

export BOOST_LIB_DIR=/Users/bradleymeyer/boost/stage/lib

and recompile

make clean

make run_entropy

This succeeds. Since I'd already compiled the object files with gcc, I didn't even need to do the make clean.

I am now able to switch between clang and gcc. To set compilation with clang, I type

unset BOOST_LIB_DIR

export NNT_NO_OPENMP=1

sudo port select --set gcc none

I can now type

make clean

make run_entropy

This successfully compiles the code with clang. To again compile with gcc, I type

unset NNT_NO_OPENMP

export BOOST_LIB_DIR=/Users/bradleymeyer/boost/stage/lib

sudo port select --set gcc mp-gcc5

I now compile by typing

make clean

make run_entropy

This successfully compiles the code with gcc.

Remembering the commands to switch between clang and gcc is tedious, so I added the following lines to my ~/.bash_profile file:

 ##
 # set compiler
 ##

 alias set_clang='sudo port select --set gcc none; unset BOOST_LIB_DIR; export NNT_NO_OPENMP=1'

 alias set_gcc='sudo port select --set gcc mp-gcc5; unset NNT_NO_OPENMP; export BOOST_LIB_DIR=/Users/bradleymeyer/boost/stage/lib'

Now when I open a new bash shell, I can simply type (in nucnet-tools-code/examples/network, for example)

set_clang

make clean

make run_entropy

to compile with clang and then

set_gcc

make clean

make run_entropy

to compile with gcc. If you also do this, you might have to run

source ~/.bash_profile

to let the shell know about the commands (particularly, when you first edit .bash_profile).

Posted by Bradley S. Meyer 2016-07-27
  • Bradley S. Meyer

    With the edit to .bash_profile suggested above, you need to run set_clang or set_gcc each time you open a new bash shell. You can instead choose to make, say, clang your default by adding the line

     export NNT_NO_OPENMP=1
    

    above the lines

     ##
     # set compiler
     ##
    
     alias set_clang='sudo port select --set gcc none; unset BOOST_LIB_DIR; export NNT_NO_OPENMP=1'
    
     alias set_gcc='sudo port select --set gcc mp-gcc5; unset NNT_NO_OPENMP; export BOOST_LIB_DIR=/Users/bradleymeyer/boost/stage/lib'
    

    Then, if you last used clang when you closed your previous shell, you'll automatically have clang properly set in the next shell. Of course if you last used gcc when you closed your previous shell, you'll need to run set_clang in your new shell.

    To have gcc be your default, you instead add a line like

    export BOOST_LIB_DIR=/Users/bradleymeyer/boost/stage/lib
    

    before the lines in .bash_profile.

     
    • Bradley S. Meyer

      If you do

      set_clang

      make run_entropy

      and get

      ld: library not found for -lboost_program_options
      clang: error: linker command failed with exit code 1 (use -v to see invocation)
      

      this is probably because your compiled version of the program options library is multi-threaded and has the -mt flag. You can add export BOOST_MT=1 to set_clang and unset it in set_gcc:

       alias set_clang='sudo port select --set gcc none; source ~/.bash_profile; unset BOOST_LIB_DIR; export NNT_NO_OPENMP=1; export BOOST_MT=1'
      
       alias set_gcc='sudo port select --set gcc mp-gcc5; source ~/.bash_profile; unset NNT_NO_OPENMP; unset BOOST_MT; export BOOST_LIB_DIR=/Users/bradleymeyer/boost/stage/lib'
      

      Notice that I also added source ~/.bash_profile so that the command gcc -v will give the updated version.

       
      Last edit: Bradley S. Meyer 2016-08-15
  • Tianhong Yu

    Tianhong Yu - 2016-09-25

    When uninstalling boost with macports, it may be denied because of the packages depending on boost. To solve this problem one can do

    sudo port uninstall --follow-dependents boost

    as described here.

     


Anonymous

Cancel  Add attachments





Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks