#+TITLE: MORSE CMake "Find modules" documentation
#+AUTHOR: Florent Pruvost
#+LANGUAGE:  en
#+OPTIONS: H:3 num:t toc:t \n:nil @:t ::t |:t _:nil ^:nil -:t f:t *:t <:t
#+OPTIONS: TeX:t LaTeX:t skip:nil d:nil pri:nil tags:not-in-toc html-style:nil
#+EXPORT_SELECT_TAGS: export
#+EXPORT_EXCLUDE_TAGS: noexport
#+TAGS: noexport(n)
#+STARTUP: nolatexpreview

#+BEAMER_THEME: Rochester

#+HTML_HEAD:   <link rel="stylesheet" title="Standard" href="css/worg.css" type="text/css" />
#+HTML_HEAD:   <link rel="stylesheet" type="text/css" href="css/VisuGen.css" />
#+HTML_HEAD:   <link rel="stylesheet" type="text/css" href="css/VisuRubriqueEncadre.css" />

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>/...~.

* 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)
  #+BEGIN_EXAMPLE
  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
  #+END_EXAMPLE

  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
* How CMake is aware of these specific modules?
  To use MORSE modules you should call the *MorseInit* module as follows:
  #+BEGIN_EXAMPLE
  # 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)
  #+END_EXAMPLE
* 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 to define the correct search paths).

  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.

** 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.
** 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 ...~
* 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.
* Choose a specific BLAS/LAPACK
  See ~cmake --help-module FindBLAS~ or ~cmake --help-module FindLAPACK~
  to get all available BLA_VENDOR.
* 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~
  #+BEGIN_EXAMPLE
  # 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
  #+END_EXAMPLE
  or set BLA_VENDOR directly in your CMake files.
* Additional BLAS/LAPACK sequential/multi-threaded targets
  The Intel MKL distribution gives the ability to choose between
  sequential and multi-threaded libraries. We provide a FindBLASEXT
  and FindLAPACKEXT which define additionnal targets BLAS::BLAS_SEQ
  and BLAS::BLAS_MT (idem for LAPACK) to be able to use the two sets
  of libraries in the same project.
* To choose between BLAS/LAPACK sequential or multi-threaded for CBLAS, LAPACKE and TMG
  By default CBLAS, LAPACKE and TMG will use the BLAS/LAPACK libraries
  found by the standard find_package from cmake. To enfore the use of
  sequential or multi-threaded BLAS/LAPACK libraries, one can set the
  CMake variable *CBLAS_MT*, (respectively *LAPACKE_MT*, *TMG_MT*) to `TRUE`
  for a multi-threaded library, or `FALSE` for a sequential one.
* 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*.
