Salome HOME
b316e8292c752c333dde5f0f11e1f6d2608f7654
[tools/documentation.git] / dev / cmake / source / pkg.rst
1 .. _package:
2
3 Package detection mechanism
4 ===========================
5
6 Philosophy
7 ----------
8
9 The philosophy of the SALOME package detection is to rely as 
10 much as possible on the standard CMake modules.
11 It is assumed those modules will get better and better with newer releases of CMake
12 and doing so ensures future compatibility with newer versions of CMake.
13
14 Root dir variables and priority order
15 -------------------------------------
16
17 The detection is however guided through a variable of the form XYZ_ROOT_DIR which
18 gives the root directory of an installation of the package. For example, to indicate
19 that we wish to use the Python installed in our home directory, one sets PYTHON_ROOT_DIR to
20 "/home/smith/Python-2.7.0".
21
22 The variable guiding the detection is always builts as::
23
24   XYZ_ROOT_DIR
25
26 where <XYZ> is (*exactly*) the upper case name of the standard CMake module. For example, the
27 detection of Qt4 is guided by setting QT4_ROOT_DIR. The variables \*_ROOT_DIR are only there to guide the process, not to force it. Typically under Linux, one would never set PTHREAD_ROOT_DIR, thus leaving the logic find the system installation. 
28
29 Beware that package names in the CMakeLists.txt are case-sensitive, but the corresponding variables are always upper-case (because on some platforms environment variables are not case-sensitive).
30
31 The order of priority for the detection of a package is (from high to low priority):
32
33 1. CMake variables explicitly set by the user (typically on the command line with -DXYZ_ROOT_DIR=...)
34 2. Environment variables set by the user (with the same name XYZ_ROOT_DIR)
35 3. Default value based on a previous dependency using the tool already
36 4. Detection direclty in the host system by the standard CMake logic
37
38 CMake has two possible modes of detection, CONFIG mode and MODULE mode. The order of priority is explicitly set in SALOME to:
39
40 1. CONFIG (also called NO_MODULE) mode: this tries to load a xyz-config.cmake file from the package installation itself
41 2. MODULE mode: this relies on the logic written in a FindXyz.cmake macro, looking directly for representative libraries, binaries or headers of the package.
42
43 The first mode is preferred as it allows to directly include the CMake targets of the prerequisite.
44
45 The package detection is only made in the root CMakeLists.txt, potentially conditionned on some
46 user options. 
47
48 Writing the detection macro of a new SALOME prerequisite
49 --------------------------------------------------------
50
51 All detection macros are located under the soure directory::
52
53   salome_adm/cmake_files
54
55 or::
56
57   adm_local/cmake_files
58
59 All prerequisite detection in SALOME should be implemented by:
60
61 * writing a file FindSalome<Xyz>.cmake (note the extra ''Salome''), where <Xyz> matches *exactly* the name of the standard CMake module (see below if there is no standard module for <Xyz>)
62 * invoking FIND_PACKAGE() command in the root CMakeLists.txt::
63   
64     FIND_PACKAGE(SalomeLibXml2 REQUIRED)
65
66 Typically the FindSalome<Xyz>.cmake file looks like this::
67
68     SALOME_FIND_PACKAGE_AND_DETECT_CONFLICTS(CppUnit CPPUNIT_INCLUDE_DIRS 1)
69     MARK_AS_ADVANCED(CPPUNIT_INCLUDE_DIRS CPPUNIT_LIBRARIES CPPUNIT_CONFIG_BIN CPPUNIT_SUBLIB_cppunit CPPUNIT_SUBLIB_dl)
70
71 It invokes the SALOME macro SALOME_FIND_PACKAGE_AND_DETECT_CONFLICTS() which takes:
72
73 * as first argument the name of the package (here CppUnit), 
74 * as second argument, the name of a (path) variable set when the package is found properly, 
75 * as third argument, the number of levels this variable should be browsed up to reach the root directory of the package installation.
76     
77
78 In the example above,
79
80 * we look for the package CppUnit (note that this is case-sensitive). There is already a standard CMake module to detect CppUnit, which sets the CMake variable CPPUNIT_INCLUDE_DIRS to the (list of) directories to include when compiling with CppUnit. Going one level up from the include directory (typically /usr/include) gives the root directory of the installation (/usr).
81 * all the variables exposed in the cache by the standard detection logic (CPPUNIT_INCLUDE_DIRS, CPPUNIT_LIBRARIES, etc ...) are marked as "advanced" so that they do not automatically appear in ccmake or cmake-gui.
82
83 Note that the reference variable may be a list, only its first element is then considered.
84
85 Writing a new generic detection macro (advanced)
86 ------------------------------------------------
87
88 If you need to include in SALOME a prerequisite for which the standard CMake distribution 
89 doesn't provide the FindXyz.cmake module, you will need to write it yourself.
90 This also applies if you judge that the standard FindXyz.cmake CMake module doesn't do its job
91 properly (yes, it can happen).
92
93 The following guidelines apply:
94
95 * make the module as generic as possible, considering that it should also run properly outside SALOME. This separates clearly the basic detection of the package from the SALOME logic. Basically the module represents the point 4. in the order of priority given above and should behave as much as possible like any standard CMake module
96 * invoking the FIND_LIBRARY(), FIND_PROGRAM(), FIND_PATH() and FIND_FILE() commands should be done without specifying an explicit PATH option to the command (this is not always possible - see for example FindOmniORBPy.cmake). The idea is that the root directory for the search is set by the SALOME encapsulation (by setting CMAKE_PREFIX_PATH)
97 * document properly which variables you are setting, respecting the CMake standard (see for example FindOmniORB.cmake)
98 * use the CMake code found in many standard modules::
99
100     INCLUDE(FindPackageHandleStandardArgs)
101     FIND_PACKAGE_HANDLE_STANDARD_ARGS(Graphviz REQUIRED_VARS GRAPHVIZ_EXECUTABLE)
102
103
104 * This macro takes care (among other things) of setting the XYZ_FOUND variable (upper case), and of displaying a message if not in QUIET mode (TBC).
105 * the macro should be saved in the same directory as above
106 * respect the naming conventions for the variables you set (start with the package name, upper case - see :ref:`naming_conventions`)
107 * do not do any ADD_DEFINITIONS() or INCLUDE_DIRECTORIES() in such a macro. This should be done by the caller or in a UseXYZ.cmake file. The purpose of a FindXXX.cmake macro is to detect, not to make usable. This rule does not apply to FindSalomeXXX.cmake macros where we know we are always in the SALOME context.
108 * here is a simple example of the detection of Sphinx::
109
110     # - Sphinx detection
111     #
112     # Output variable: SPHINX_EXECUTABLE
113     #                  
114     # 
115     # The executable 'sphinx-build' is looked for and returned in the above variable.
116     #
117
118     ###########################################################################
119     # Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
120     <...>
121     ###########################################################################
122
123     FIND_PROGRAM(SPHINX_EXECUTABLE sphinx-build)
124
125     # Handle the standard arguments of the find_package() command:
126     INCLUDE(FindPackageHandleStandardArgs)
127     FIND_PACKAGE_HANDLE_STANDARD_ARGS(Sphinx REQUIRED_VARS SPHINX_EXECUTABLE)
128
129
130 .. _pkg_impl:
131
132 Implementation details (advanced)
133 ---------------------------------
134
135 The core of the SALOME detection logic is located in the macro
136 SALOME_FIND_PACKAGE_AND_DETECT_CONFLICTS() implemented in KERNEL/salome_adm/cmake_files/SalomeMacros.cmake.
137
138 All the logic is thus concentrated in one (hopefully well documented) macro. This means: one place to fix if there is a bug, and better, one place to amend if we ever want to define a new behaviour (for example if we want to change the order of priorities between CONFIG and MODULE mode). The end user (someone developing in SALOME) just needs to call it. It is the responsability of the core SALOME developpers to understand and maintain this macro.
139
140 The reader is invited to have the code at hand when reading the following.
141
142 The macro signature is
143 ::
144
145   SALOME_FIND_PACKAGE_DETECT_CONFLICTS(pkg referenceVariable upCount)
146
147 where:
148
149 * *pkg*              : name of the system package to be detected
150 * *referenceVariable*: variable containing a path that can be browsed up to retrieve the package root directory (xxx_ROOT_DIR)
151 * *upCount*          : number of times we have to go up from the path <referenceVariable> to obtain the package root directory.
152
153 For example::  
154
155   SALOME_FIND_PACKAGE_DETECT_CONFLICTS(SWIG SWIG_EXECUTABLE 2) 
156
157 The macro has a significant size but is very linear:
158
159 1. Load a potential env variable XYZ_ROOT_DIR as a default choice for the cache entry XYZ_ROOT_DIR.
160    If empty, load a potential XYZ_ROOT_DIR_EXP as default value (path exposed by another package depending
161    directly on XYZ)
162 2. Invoke FIND_PACKAGE() in this order:
163
164   * in CONFIG mode first (if possible): priority is given to a potential "XYZ-config.cmake" file. In this mode, the standard system paths are skipped. If you however want to force a detection in CONFIG mode into a system path, you have to set explicitly the XYZ_ROOT_DIR variable to "/usr".
165   * then switch to the standard MODULE mode, appending on CMAKE_PREFIX_PATH the above XYZ_ROOT_DIR variable.
166
167 3. Extract the path actually found into a temp variable _XYZ_TMP_DIR
168 4. Warn if XYZ_ROOT_DIR is set and doesn't match what was found (e.g. when CMake found the system installation
169    instead of what is pointed to by XYZ_ROOT_DIR - happens when there is a typo in the content of XYZ_ROOT_DIR).
170 5. Conflict detection: check the temporary variable against a potentially existing XYZ_ROOT_DIR_EXP
171 6. Finally expose what was *actually* found in XYZ_ROOT_DIR.  This might be different from the initial XYZ_ROOT_DIR, but there has been a warning in such a case.
172
173
174 The specific stuff (for example exposing a prerequisite of XYZ to the rest of the world for future conflict detection) is added after the call to the macro by the callee. See for example the FindSalomeHDF5.cmake macro which exposes the MPI_ROOT_DIR if HDF5 was compiled with parallel support.
175
176 If the invokation of FIND_PACKAGE() was done with some options:
177
178 * QUIET, REQUIRED
179 * COMPONENTS
180 * VERSION [EXACT]
181
182 those options are completly handled through the analysis of the standard CMake variables (which are automatically set when those options are given):
183
184 * Xyz_FIND_QUIETLY and Xyz_FIND_REQUIRED
185 * Xyz_FIND_COMPONENTS
186 * Xyz_FIND_VERSION and Xyz_FIND_VERSION_EXACT
187
188
189
190
191