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?
- 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:
- The CMake variable
LIBNAME_DIR
is set or bothLIBNAME_INCDIR
andLIBNAME_LIBDIR
are set - The environment variable
LIBNAME_DIR
is set or bothLIBNAME_INCDIR
andLIBNAME_LIBDIR
- A pkg-config .pc file (hwloc.pc) of the library is available in the environment (cf. PKG_CONFIG_PATH environment variable) and is used
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
- scan the paths present in the following environment variables
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.