Author: Florent Pruvost

# MORSE CMake "Find modules" documentation

## 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?
- 5. Choose a specific BLAS/LAPACK
- 6. Hint for Intel MKL
- 7. To prefer static libraries if both static and dynamic are available

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. The modules correspond to packages that do not fully rely on CMake or which do not provide a "PACKAGE"Config.cmake file. Ideally these modules should not exist and packages should be compliant with CMake by providing the cmake config file installed in `<prefix>/lib/cmake/<package>/...`.

## 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(STARPU) # look for STARPU libraries and compiler/linker flags
    add_executable(foo ${FOO_SOURCES}) # define an executable from sources
    target_link_libraries(foo PRIVATE MORSE::STARPU) # add STARPU libraries for the link
    # target_link_libraries(foo ${STARPU_LIBRARIES}) old school cmake with variables and not target

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.

The `find_package(FOO)` command looks for the library(ies), the header directory(ies) and compiler/linker flags. If found the following CMake variables are set:

- FOO_FOUND: set if package is found
- FOO_PREFIX: root of the package installation (usually one directory above lib/ one)
- FOO_VERSION: version of the package if found with pkg-config
- FOO_INCLUDE_DIRS: path to headers
- FOO_LIBRARY_DIRS: library directories
- FOO_LIBRARIES: list of libraries necessary to link with the package (absolute paths given)
- FOO_CFLAGS_OTHER: required compiler flags
- FOO_LDLAGS_OTHER: required linker flags
- FOO_STATIC: to force using static libraries when exist or is set to 1 if the only library found is static

In addition the find_package command define an imported target MORSE::FOO to be used in modern CMake fashion. The target defines the following CMake properties:

- INTERFACE_INCLUDE_DIRECTORIES
- INTERFACE_LINK_DIRECTORIES
- INTERFACE_LINK_LIBRARIES
- INTERFACE_COMPILE_OPTIONS
- INTERFACE_LINK_OPTIONS

## 2 How CMake is aware of these specific modules?

To use MORSE modules you should call the MorseInit module as follows:

    # For example if Morse CMake modules are located in ./cmake_modules/morse_cmake
    # append this directory to the list of directories containing CMake modules
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_modules/morse_cmake/modules" )
    # Include the init module
    include(MorseInit)

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

We try to enforce using pkg-config file if provided (update your PKG_CONFIG_PATH environment variable).

List of packages relying only on pkg-config file: EZTRACE, FXT, GTG, HWLOC, PAPI, SIMGRID, PARSEC, STARPU.

For packages which do not provide any pkg-config file 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 `LIBRARY_PATH` `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 a) 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 variable `CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES`

   b) for libraries:

   - scan the paths present in the following environment variables `LIBRARY_PATH`, `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 variable `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 `LIBRARY_PATH`, `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.

## 5 Choose a specific BLAS/LAPACK

See `cmake --help-module FindBLAS` or `cmake --help-module FindLAPACK` to get all available BLA_VENDOR.

## 6 Hint for Intel MKL

To look for the Intel MKL BLAS, LAPACK (or CBLAS, LAPACKE), one can enforce Intel MKL search with the CMake variable BLA_VENDOR as it is documented in BLAS and LAPACK officiel modules `cmake --help-module FindLAPACK`

    # for sequential blas/lapack
    cmake .. -DBLA_VENDOR=Intel10_64lp_seq
    # for multithreaded blas/lapack
    cmake .. -DBLA_VENDOR=Intel10_64lp
    # play with MKL_NUM_THREADS env. var. to set number of threads used internally

or set BLA_VENDOR directly in your CMake files.

## 7 To prefer static libraries if both static and dynamic are available

Set "PACKAGE"_STATIC=1 at cmake configure. For BLAS/LAPACK/SCALAPACK use BLA_STATIC=1.

Author: Florent Pruvost

Created: 2020-12-11 ven. 10:34

Validate