Thursday 2 February 2017

Build Clang & LLVM tooling on RHEL 7

Clang is a C (and C++) front-end for the LLVM compiler. It provides a fast compiler with really good error messages and great support for writing code analysis and formatting tools. Some of the official tools include:
Third party tools built on top of the clang tooling (and libclang libraries) include:
A good talk by Chandler Carruth about some of the above tools and the future direction for Clang tooling is available on YouTube

Installing Clang

Redhat 7

On RedHat 7, Clang is not included in the official repositories, however older versions (v3.4) are included in the epel repository.

If you are unable to use the epel repository, or want a newer version of clang, the below script can be used to get and install v3.9.1 of llvm, clang, clang tools and the include what you use tool.

mkdir clang_llvm_391_build
cd clang_llvm_391_build
svn co llvm
cd llvm/tools
svn co clang
cd ../..
cd llvm/tools/clang/tools
svn co extra
cd ../../../..
cd llvm/projects
svn co compiler-rt
cd ../..
#cd llvm/projects
#svn co libcxx
#cd ../..
cd llvm/tools/clang/tools
git clone
cd include-what-you-use
git checkout clang_3.9
cd ..
echo "" >> CMakeLists.txt
echo "add_subdirectory(include-what-you-use)" >> CMakeLists.txt
cd ../../../..
cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/opt/software/clang -DCMAKE_BUILD_TYPE=Release ../llvm
mkdir -p /opt/software/clang
cmake -DCMAKE_INSTALL_PREFIX=/opt/software/clang -P cmake_install.cmake

As you can see this installs the software to /opt/software/clang If you want to install to a different location change the CMAKE_INSTALL_PREFIX locations in the line 26 and 29.

The script doesn't compile the version of the C++ standard library (libcxx) available with Clang as I had compiler errors when building it with the default version of gcc (v4.8.5) available with RHEL 7.3

Redhat 6

For RHEL 6, there is also a epel repository with v3.4 available. However, if you want a later version of Clang you have some hoops to run through.

This is because Clang requires a C++11 compiler and Clang v3.9.1, mentioned above, requires at least v4.8 of gcc. The version of gcc available on RHEL 6 is too old and you have to manually build a later version before you can build Clang. You can find instructions on doing so from this blog post.

Using Clang


To build your software using Clang with CMake you should override the CMAKE_C_COMPILER and CMAKE_CXX_COMPILER variables. Using the install from my script above this would be done using

$ cmake -DCMAKE_C_COMPILER=/opt/software/clang/bin/clang -DCMAKE_CXX_COMPILER=/opt/software/clang/bin/clang++ ..
$ make

You can see more details in my cmake-examples GitHub repository.

Similar methods of overriding the C and C++ compiler environments may work with other build tools. e.g. using CC and CXX with Makefiles.

Using Clang Static Analyzer

Using the Clang Static Analyzer is easy too as it includes a tool scan-build which can be used to scan your source code at the same time as it builds it

$ /opt/software/clang/bin/scan-build cmake ..
$ /opt/software/clang/bin/scan-build make

On RedHat the above will use gcc to build your software while scanning it with the Clang Static Analyzer.

To get extra coverage for your code I also recommend to use clang to compile it. This can be done at the same time as your static analysis by using the --use-cc and --use-c++ flags for scan-build

$ /opt/software/clang/bin/scan-build --use-cc=/opt/software/clang/bin//clang --use-c++=/opt/software/clang/bin//clang++  cmake ..
$ /opt/software/clang/bin/scan-build --use-cc=/opt/software/clang/bin//clang --use-c++=/opt/software/clang/bin//clang++  make

Advantages of having Clang Available

The main reason I have for using Clang on RedHat is to get access to it's tooling and static analyzer.

However as a side effect of this it also makes the compiler available for use. Using this second compiler can give you more chance of finding errors. For example, when compiling with Clang I had an error:

 file included from /path/to/myclass.cpp:22:
/path/to/logger.h:1:9: warning: '_LIBMYLIB_LOGGER_H_' is used as a header guard here, followed by
      #define of a different macro [-Wheader-guard]
/path/to/logger.h:2:9: note: '_LINMYLIB_LOGGER_H_' is defined here; did you mean '_LIBMYLIB_LOGGER_H_'?
6 warnings generated.

This did not cause any errors or warnings on my version of GCC and while it didn't cause any issues (because I only included that header once), it could potentially have lead to a later error.

No comments:

Post a Comment