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:
- 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
- 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
andCMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES
- scan the paths present in the following environment variables
- 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
- scan the paths present in the following environment variables
- for headers:
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.