MORSE CMake "Find modules" documentation

Table of Contents

This document aims at documenting MORSE find_package CMake modules which allow to detect library dependencies on UNIX systems (mainly Linux and MAC OS X). These additional modules have been written because either, they are not distributed by the CMake community, or, they already exist but some are outdated or miss the requirements we need.

1 CMake find modules: what is it, why is it useful?

The CMake modules being here can be used to "find" some installed libraries on the system through the invocation of the find_package CMake command ("MODULE" mode signature, cf. CMake documentation of find_package command)

find_package(BLAS) # look for BLAS libraries and compiler/linker flags
add_executable(foo ${FOO_SOURCES}) # define an executable from sources
target_link_libraries(foo ${BLAS_LIBRARIES}) # add BLAS libraries for the link

It allows to find efficiently the libraries we depend on. The modules are generally written by the library developers or very active users so that they know very well how the library is built how it is installed, etc.

2 How CMake is aware of these specific modules?

find_package(LIBNAME) rely on a CMake module file called FindLIBNAME.cmake which should lies in a directory set in the CMake variable CMAKE_MODULE_PATH. For example, FindLIBNAME.cmake is in the relative path ./cmake_modules/FindLIBNAME.cmake

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(LIBNAME)

To use MORSE modules you can add the path to the modules in your CMake project like this

list(APPEND CMAKE_MODULE_PATH "${MORSE_DISTRIB_DIR}/cmake_modules/morse/find" )

3 Internal mechanism: what a "find" mainly do, what are the paths scanned?

The general process consists in looking into some system paths known from CMake to find headers and libraries and define in output some CMake variables the user need to link with his dependency. Additionaly to the system paths, some environment variable can also be scanned like LD_LIBRARY_PATH and CPATH. A custom CMake cache variable LIBNAME_DIR is also introduced in our modules in order to let users indicate directly during the "configure" step a specific installation directory for the library (e.g. where are located the include/, lib/, etc, sub-directories). The priority order is the following:

  1. The CMake variable LIBNAME_DIR is set or both LIBNAME_INCDIR and LIBNAME_LIBDIR are set
  2. The environment variable LIBNAME_DIR is set or both LIBNAME_INCDIR and LIBNAME_LIBDIR
  3. A pkg-config .pc file (hwloc.pc) of the library is available in the environment (cf. PKG_CONFIG_PATH environment variable) and is used
  4. Look into the following paths
    1. for headers:
      • scan the paths present in the following environment variables INCLUDE, C_INCLUDE_PATH, CPATH, INCLUDE_PATH
      • scan the system paths for headers: look into path present in the CMake variables CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES and CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES
    2. for libraries:
      • scan the paths present in the following environment variables LIB (Windows), DYLD_LIBRARY_PATH (Mac OS X), LD_LIBRARY_PATH (Linux)
      • scan the system paths for headers: look into path present in the CMake variables CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES, CMAKE_C_IMPLICIT_LINK_DIRECTORIES

When it is possible, compiler flags are also given to users. This last point suggest that the information can be found in the library installation, e.g. through a pkg-config file.

In some cases, the library can be searched for a specific configuration, e.g "I want to find an installation of this library coming with all these components enabled" such as: MUMPS linear solver must be able to use SCOTCH graph partitioner. See the "COMPONENTS" option of the find_package command and look for the header of the module file to get more information about possible components.

Once some header files and libraries have been found the module tries to call a basic function of the library to test the link step. During this process, the CMake check_function_exists is used. If the test fails a message is given with the compiler and linker flags used during the test. The precise error can also be found in the CMakeFiles/CMakeError.log file of the build directory.

3.1 How to act on the searching process?

If the user does not change the environment (do not modify environment variables like LD_LIBRARY_PATH), and gives no hint at all about the location of the libraries, the module will match the situation 4.2 and will look into system paths.

To give an "exotic" locations, i.e. not in system paths, the user can use scripts or a module like system to set the paths in environment variables (LD_LIBRARY_PATH, INCLUDE, …), cf. situation 4.1 and 2.

For some libraries it is possible to rely on pkg-config if the .pc file path is in the PKG_CONFIG_PATH environment variable, cf. situation 3.

Finally, to directly give "by hand" the path, the user can set a CMake variable LIBNAME_DIR, or the pair LIBNAME_INCDIR and LIBNAME_LIBDIR, cf. situation 1.

3.2 A version of the library is found but I want another one, how to change?

If a first configuration has found a library somewhere but you are not satisfied with this one and want to give some hints to look for it:

  • update your environment or give the location "by hand" (LIBNAME_DIR)
  • delete the CMake cache file to make it "forget" the libraries already found: rm CMakeCache.txt
  • configure again: cmake path/to/your/CMakeLists.txt ...

4 How to get more information about a specific module usage?

Specific information about a precise Find module are given directly at the head of the module file. The usage, the optional parameters that can be used and the output variables are explained here.

Author: HiePACS

Created: 2016-09-15 jeu. 08:01

Emacs 24.5.1 (Org mode 8.2.10)

Validate