# MORSE CMake "Find modules" documentation
Author: HiePACS

## Table of Contents

- 1. CMake find modules: what is it, why is it useful?
- 2. How CMake is aware of these specific modules?
- 3. Internal mechanism: what a "find" mainly do, what are the paths scanned?
  - 3.1. How to act on the searching process?
  - 3.2. A version of the library is found but I want another one, how to change?
- 4. How to get more information about a specific module usage?

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