CMake

Introduction

CMake is a tool which permits automation of the software compilation process. As with Autotools, it consists of a build automation with the goal of simplifying the multi-platform compilation of a source code.

Starting from a CMakeLists.txt configuration file, CMake generates Makefile files adapted to the target machine. In theory, in order to compile a software using CMake, you simply need to follow these steps:

$ mkdir build; cd build/ # creation of a temporary directory for the compilation
$ cmake ../src/          # equivalent of the script ./configure the autotools
$ make                   # compilation
$ make install           # installation

CMake also permits generating the configuration of other projects (Eclipse, Visual Studio, …)

CMake is one of a suite of programming tools developed by Kitware which integrates CTest (test driver program), CDash (testing server) and CPack (packaging distribution system).

Using CMake at IDRIS

Using CMake at IDRIS requires certain adaptations. CMake automatically detects the compilation environment and this can be problematic on the IDRIS machines. In addition, the CMake configuration files provided with the software are not always written in a way which is portable. The following documentation explains how to use CMake at IDRIS. If you have any problems you may contact the user support team.

The CMake module

CMake is available in the default environment of the IDRIS machines but we advise you to use a more recent version of CMake which is available in the form of a module :

$ module load cmake

Choice of compilers

The IDRIS Ada and Turing machines use (respectively) the Intel and IBM compilers. However, by default, CMake seeks to use the GNU compilers which are also available on the machines. To avoid this, it is necessary to indicate to CMake which compilers to use. Therefore, it is recommended to use the environment variables (CC, …) rather than the CMake variables (-DCMAKE_C_COMPILER, …)1). Each time you change compilers, you must begin by entirely deleting the temporary directory used by the compilation because the variables associated to the compilers cannot be modified after the first execution of CMake 2).

On Ada, to specify Intel compilers:

$ rm -rf build; mkdir build; cd build
$ CC=icc CXX=icpc cmake ../src/

Detecting libraries

CMake automatically detects the libraries of the product to be installed as it uses internal commands which describe how to find libraries. These command files can also be supplied with the product to be installed. The command file names are in this form: FindLIBRARY.cmake.

At IDRIS, the libraries are managed with the module tool. The modules directly add the access paths for the include and library files to the compiler arguments. However, they do not necessarily set the same environment variables which CMake uses to find libraries. This is why CMake does not always find the access paths to the libraries.

When the library has already been installed on the IDRIS machine, you can try loading the modules necessary for the compilation before the execution of CMake but this will not be sufficient. You must help CMake find the libraries by setting the CMake variables or by adapting the command files.

Example:

$ cmake -DFFTW_INCLUDE_DIR=/smplocal/pub/FFTW/3.3.2/include -DFFTW_LIBRARY=/smplocal/pub/FFTW/3.3.2/lib ../src/

The names of the CMake variables depend on the libraries to be used. They are often shown in the error message. If not, you must consult the cache file, the CMakeLists.txt files or use the GUI (graphical user interface) to list the variables.

The module show command allows obtaining information about the installation paths of the products (libraries, tools, …) provided by IDRIS. If the CMake variables have been set, it is not necessary to load the corresponding module.

If the library is not available on the machine, you can install it on your account or contact us.

Cross compilation on Turing

When creating an executable file on the BG/Q machine, you must cross compile on the front-end cross compilation.

With CMake, you must create a file which describes the toolchain.

bgq-toolchain.cmake
set(CMAKE_SYSTEM_NAME BlueGeneQ-static)
 
set(COMPILER_SEARCH_PATHS /bglocal/fe/pub/Modules/IDRIS/wrappers/)
 
find_program(CMAKE_C_COMPILER       mpixlc_r   ${COMPILER_SEARCH_PATHS})
find_program(CMAKE_CXX_COMPILER     mpixlcxx_r ${COMPILER_SEARCH_PATHS})
find_program(CMAKE_Fortran_COMPILER mpixlf90_r ${COMPILER_SEARCH_PATHS})
find_program(CMAKE_LINKER           mpixlcxx_r ${COMPILER_SEARCH_PATHS})
 
find_program(MPI_C_COMPILER         mpixlc_r   ${COMPILER_SEARCH_PATHS})
find_program(MPI_CXX_COMPILER       mpixlcxx_r ${COMPILER_SEARCH_PATHS})
find_program(MPI_Fortran_COMPILER   mpixlf90_r ${COMPILER_SEARCH_PATHS})
 
SET_PROPERTY(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
SET_PROPERTY(GLOBAL PROPERTY TARGET_ARCHIVES_MAY_BE_SHARED_LIBS FALSE)
 
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

Use the above command file by entering:

$ cmake -DCMAKE_TOOLCHAIN_FILE=../bgq-toolchain.cmake ../src/

Attention: CMake does not re-execute the configuration phase after the file containing the compilation chain configuration has been modified.

See also:

Additional information

Configuration options

The compilation options are stored in the CMake variables. These can be set on the command line by using option -D or by using the GUI.

Example :

$ cmake -DCMAKE_C_FLAGS="-O3 -xAVX" ../src/

The list of CMake variables is available here but each library adds its own options. You must consult the cache file, the CMakeLists.txt files or use the GUI to manage the variables.

The cache system

After having launched cmake the first time, the compilation parameters are saved in the cache file, CMakeCache.txt. Following this, it is possible to modify the configuration by re-launching cmake. During the first launching, the source directory must be used as an argument of cmake. Subsequently, you must indicate the temporary compilation directory:

$ cd build/
$ cmake -DCMAKE_CXX_FLAGS="-O3 -xAVX" .

After each modification, the configuration phase is repeated by using the cache inputs as initialisation values of the CMake variables.

As a complicated logic can exist between the compilation variables, it is sometimes less difficult to restart at zero when the first configuration phase does not take place correctly. In this case, it is necessary to delete the directory and set the CMake variables directly on the command line.

The graphical user interface (GUI)

The ccmake command allows accessing the CMake curses interface curses. Like the cmake command, ccmake takes a directory as argument.

$ cd build/
$ ccmake .

The ccmake interface displays all of the CMake variables which have an influence on the compilation. The variables can be modified and the Makefile files will consequently be regenerated.

The menu of available commands is found in the bottom section of the interface. To modify a variable, you must go on a line 3) and press [Enter].

After modifying a variable, the configuration phase can be relaunched by using [c]. The interface displays the result and you must type [e] to return to the menu of commands. By typing [g], you may validate the modifications and leave the interface. The hidden variables are displayed by [t].

Compilation in a new directory

CMake allows carrying out the compilation in a new directory which contains a copy of the source file. In this way, you can avoid polluting the source directory, easily delete the files generated by the compilation or install several versions of a library from the orginal source files.

To use this functionality, you simply need to call the cmake command from a directory dedicated to the compilation (e.g. the build directory). The cmake command takes the path to the source directory as argument.

The following example shows the usual organisation:

$ ls
  src/  build-optim/  install-optim/
        build-debug/  install-debug/
        build-seq/    install-seq/
$ cd build-seq; cmake ../src/

Choice of installation directory

The CMake variable CMAKE_INSTALL_PREFIX allows choosing the directory to use for the library installation. This is the equivalent of the --prefix option of the ./configure script of Autotools.

$ cmake -DCMAKE_INSTALL_PREFIX=../install/ ../src/

Compiler options

As do most of the integrated development environments (IDE), CMake allows managing a project with a compilation configuration which is adapted to the developments (Debug mode) or to the production phase (Release mode).

The CMake variable CMAKE_BUILD_TYPE allows switching from one mode to the other. It is also possible to change each of the compiler options associated to the compilation modes individually.

$ cmake -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_C_FLAGS_RELEASE="-O3 -xAVX" \
        -DCMAKE_CXX_FLAGS_RELEASE="-O3 -xAVX" \
        -DCMAKE_C_FLAGS_DEBUG="-g" \
        -DCMAKE_CXX_FLAGS_DEBUG="-g"

The Intel compiler options and the IBM compiler options are described on the IDRIS website.

To display the commands executed by make (built by CMake)

Use the environment variable VERBOSE. Example:

$ VERBOSE=1 make

Save the configuration

To facilitate the reinstallation of a library on a target machine, the best way is to save a small script in order to replicate the configuration phase.

do-configure.sh
CC=icc CXX=icpc cmake -DCMAKE_BUILD_TYPE:STRING=Release  \
                      -DCMAKE_INSTALL_PREFIX:PATH="$WORKDIR/opt/" \
                      -DCMAKE_CXX_FLAGS_RELEASE:STRING="-O3 -xAVX" \
                      -DCMAKE_C_FLAGS_RELEASE:STRING="-O3 -xAVX" \
                      ../src/

It is also possible to use the -C option of cmake to initialise the variables from a script written in CMake language.

Note that CMake works with absolute (full) pathnames which does not allow moving the directories after configuration 4).

Documentation

1) See also: How do I use a different compiler? in the FAQ of CMake
3) Note that the description of the current variable is displayed just before the menu of commands on the interface.