Skip to content

Instantly share code, notes, and snippets.

@codingforfun
Last active October 14, 2015 15:31
Show Gist options
  • Save codingforfun/abc17efdb84137d95755 to your computer and use it in GitHub Desktop.
Save codingforfun/abc17efdb84137d95755 to your computer and use it in GitHub Desktop.
How to configure CMake based projects to flexible switch between use of GCC, CLang and IceCC

How to configure CMake based projects to flexible switch between use of GCC, CLang and IceCC

Idea

It would be nice to switch between different compiler systems based on current requirements. I.e. CLang is known to produce better error messages especially with C++ templates, GCC might be the reference compiler and Icecream supports faster development by reducing compile times.

Since all 3 system produce compatible binary outputs it would be nice to switch without the need to rebuild everything, i.e. dependencies etc. Ideally switch is possible to just run a single build.

Challenge: CMake doesn't support switching compiler for an already configured build system. Normally you would have to delete your build directory and reconfigure or maintain different build directories.

Solution:

  • Use CCache as a compiler wrapper.
  • Configure your CMake based build using CCache as the compiler
  • Before actual build set environment variables to tell CCache which compiler it should really use

Scripts

The scripts in this gist provide tools to setup a system as described above.

Setup

To use the system:

  • Setup Icecream, CCache, CMake, GCC and CLang according to the instructions given for your specific Linux distribution (This has been tested on Ubuntu 14.04)
  • Put all the scripts in a location accessible from your path. A good place would be $(HOME)/bin for example.

Configuring

  • Configure the buildsystem using CMake as usually but put ccache_env in front of your cmake command to modify paths to force CMake to find CCache first.

Example:

$myhome/mydev/project/build> ccache_env cmake ..

Building using GCC

  • This is the default.
  • Just use make to run your build using CCache and GCC

Building using Icecream

  • To use icecc as your compiler, wrap your call to make through the script below to setup the necessary environment variables for CCache
  • Note: Icecream has to be setup and working on your system already according to the requirements set by your Linux distribution.

Example:

$myhome/mydev/project/build> icecc_make 
  • I like to use another BASH alias to setup more detailed options for make:
  • alias icemake='nice -n 10 icecc_make -j -l6 ' and just call icemake instead of make

Building using CLang

  • Using CLang follows the same main principle but requires an extra wrapper script to properly wrap options for clang.
  • To use clang as your compiler, wrap your call to make through the script below to setup the necessary environment variables for CCache and use the clang-wrapper script
  • Note: CLang has to be setup and working on your system already according to the requirements set by your Linux distribution.

Example:

$myhome/mydev/project/build> clang_make
#!/bin/bash
# run in subprocess to keep changes to PATH local
# we do not want to run everything through CCache, only selected projects
(
export PATH=/usr/lib/ccache:$PATH
eval $@
)
#!/bin/bash
# Compiler wrapper for CLANG to use together with CCACHE
# When called with a complete complile line, this script eats up
# the first argument intepreting it as the original compiler.
# It then decides whether to compile C or C++ code based on this argument
# and calls the apropriate clang driver.
#
# Note: CLang doesn't link to lstdc++ by default. If you need this change
# your project configuration accordingly or just uncomment below to
# always link against lstd++
#
# Usage: export CCACHE_PREFIX variable with this script
DRIVER_NAME=$(basename $0)
## get first argument
## first argument is the compiler name that should get replaced
COMPILER_NAME=$(basename $1)
shift
## decide if compiling C or C++ code
if [[ $COMPILER_NAME =~ ^.*\+\+$ ]]
then
clang++ -Qunused-arguments ${CLANG_WRAPPER_OPTIONS} "$@" # -lstdc++
else
clang -Qunused-arguments ${CLANG_WRAPPER_OPTIONS} "$@"
fi
#!/bin/bash
## test if called on a terminal (for color output)
CLANG_WRAPPER_OPTIONS=$(test -t 2 && echo -fcolor-diagnostics)
# run in subprocess to keep changes to environment local
(
export CLANG_WRAPPER_OPTIONS=$CLANG_WRAPPER_OPTIONS
export CCACHE_CPP2=yes
export CCACHE_PREFIX=clang-wrapper
export CCACHE_COMPILERCHECK="%compiler% -v"
export PATH=/usr/lib/ccache:$PATH
make $@
)
#!/bin/bash
# run in subprocess to keep changes to environment local
(
export CCACHE_PREFIX=icecc
export PATH=/usr/lib/ccache:/usr/lib/icecc/bin:$PATH
make $@
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment