index.rst 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760
  1. CMake Tutorial
  2. **************
  3. .. only:: html
  4. .. contents::
  5. This tutorial provides a step-by-step guide that covers common build
  6. system issues that CMake helps address. Seeing how various topics all
  7. work together in an example project can be very helpful. This tutorial
  8. can be found in the ``Help/guide/tutorial`` directory of the CMake
  9. source code tree. Each topic has its own subdirectory containing code
  10. that may be used as a starting point for that step. The tutorial
  11. examples are progressive so that each step provides the complete
  12. solution for the previous step.
  13. A Basic Starting Point (Step 1)
  14. ===============================
  15. The most basic project is an executable built from source code files.
  16. For simple projects, a two line CMakeLists file is all that is required.
  17. This will be the starting point for our tutorial. The CMakeLists file
  18. looks like:
  19. .. literalinclude:: Step1/CMakeLists.txt
  20. :language: cmake
  21. Note that this example uses lower case commands in the CMakeLists file.
  22. Upper, lower, and mixed case commands are supported by CMake. The source
  23. code for ``tutorial.cxx`` will compute the square root of a number and
  24. the first version of it is very simple, as follows:
  25. .. literalinclude:: Step1/tutorial.cxx
  26. :language: c++
  27. Adding a Version Number and Configured Header File
  28. --------------------------------------------------
  29. The first feature we will add is to provide our executable and project with a
  30. version number. While we could do this exclusively in the source code, using
  31. CMakeLists provides more flexibility.
  32. To add a version number we modify the CMakeLists file as follows:
  33. .. literalinclude:: Step2/CMakeLists.txt
  34. :language: cmake
  35. :start-after: # set the version number
  36. :end-before: # configure a header file
  37. Since the configured file will be written into the binary tree, we
  38. must add that directory to the list of paths to search for include
  39. files.
  40. .. literalinclude:: Step2/CMakeLists.txt
  41. :language: cmake
  42. :start-after: # so that we will find TutorialConfig.h
  43. We then create a ``TutorialConfig.h.in`` file in the source tree with the
  44. following contents:
  45. .. literalinclude:: Step1/TutorialConfig.h.in
  46. :language: cmake
  47. When CMake configures this header file the values for
  48. ``@Tutorial_VERSION_MAJOR@`` and ``@Tutorial_VERSION_MINOR@`` will be
  49. replaced by the values from the CMakeLists file. Next we modify
  50. ``tutorial.cxx`` to include the configured header file and to make use of the
  51. version numbers. The updated source code is listed below.
  52. .. literalinclude:: Step2/tutorial.cxx
  53. :language: c++
  54. :start-after: // report version
  55. :end-before: return 1;
  56. The main changes are the inclusion of the ``TutorialConfig.h`` header
  57. file and printing out a version number as part of the usage message.
  58. Specify the C++ Standard
  59. -------------------------
  60. Next let's add some C++11 features to our project. We will need to explicitly
  61. state in the CMake code that it should use the correct flags. The easiest way
  62. to enable C++11 support for CMake is by using the ``CMAKE_CXX_STANDARD``
  63. variable.
  64. First, replace ``atof`` with ``std::stod`` in ``tutorial.cxx``.
  65. Then, set the ``CMAKE_CXX_STANDARD`` variable in the CMakeLists file.
  66. Which variable can we set in the CMakeLists file to treat the
  67. ``CMAKE_CXX_STANDARD`` value as a requirement?
  68. Build and Test
  69. --------------
  70. Run **cmake** or **cmake-gui** to configure the project and then build it
  71. with your chosen build tool.
  72. cd to the directory where Tutorial was built (likely the make directory or
  73. a Debug or Release build configuration subdirectory) and run these commands:
  74. .. code-block:: console
  75. Tutorial 4294967296
  76. Tutorial 10
  77. Tutorial
  78. Adding a Library (Step 2)
  79. =========================
  80. Now we will add a library to our project. This library will contain our own
  81. implementation for computing the square root of a number. The executable can
  82. then use this library instead of the standard square root function provided by
  83. the compiler.
  84. For this tutorial we will put the library into a subdirectory
  85. called MathFunctions. It will have the following one line CMakeLists file:
  86. .. literalinclude:: Step2/MathFunctions/CMakeLists.txt
  87. :language: cmake
  88. The source file ``mysqrt.cxx`` has one function called ``mysqrt`` that
  89. provides similar functionality to the compiler’s ``sqrt`` function. To make use
  90. of the new library we add an ``add_subdirectory`` call in the top-level
  91. CMakeLists file so that the library will get built. We add the new library to
  92. the executable, and add MathFunctions as an include directory so that the
  93. ``mqsqrt.h`` header file can be found. The last few lines of the top-level
  94. CMakeLists file now look like:
  95. .. code-block:: cmake
  96. # add the MathFunctions library
  97. add_subdirectory(MathFunctions)
  98. # add the executable
  99. add_executable(Tutorial tutorial.cxx)
  100. target_link_libraries(Tutorial MathFunctions)
  101. # add the binary tree to the search path for include files
  102. # so that we will find TutorialConfig.h
  103. target_include_directories(Tutorial PUBLIC
  104. "${PROJECT_BINARY_DIR}"
  105. "${PROJECT_SOURCE_DIR}/MathFunctions"
  106. )
  107. Now let us make the MathFunctions library optional. While for the tutorial
  108. there really isn’t any need to do so, for larger projects this is a common
  109. occurrence. The first step is to add an option to the top-level CMakeLists
  110. file.
  111. .. literalinclude:: Step3/CMakeLists.txt
  112. :language: cmake
  113. :start-after: # should we use our own math functions
  114. :end-before: # set the version number
  115. This will show up in the CMake GUI and ccmake with a default value of ON
  116. that can be changed by the user. This setting will be stored in the cache so
  117. that the user does not need to set the value each time they run CMake on this
  118. build directory.
  119. The next change is to make building and linking the MathFunctions library
  120. conditional. To do this we change the end of the top-level CMakeLists file to
  121. look like the following:
  122. .. literalinclude:: Step3/CMakeLists.txt
  123. :language: cmake
  124. :start-after: # add the MathFunctions library?
  125. Note the use of the variables ``EXTRA_LIBS`` and ``EXTRA_INCLUDES`` to collect
  126. up any optional libraries to later be linked into the executable. This is a
  127. classic approach when dealing with many optional components, we will cover the
  128. modern approach in the next step.
  129. The corresponding changes to the source code are fairly straightforward. First,
  130. include the MathFunctions header if we need it:
  131. .. literalinclude:: Step3/tutorial.cxx
  132. :language: c++
  133. :start-after: // should we include the MathFunctions header
  134. :end-before: int main
  135. Then make which square root function is used dependent on ``USE_MYMATH``:
  136. .. literalinclude:: Step3/tutorial.cxx
  137. :language: c++
  138. :start-after: // which square root function should we use?
  139. :end-before: std::cout << "The square root of
  140. Since the source code now requires ``USE_MYMATH`` we can add it to
  141. ``TutorialConfig.h.in`` with the following line:
  142. .. literalinclude:: Step3/TutorialConfig.h.in
  143. :language: c
  144. :lines: 4
  145. Run **cmake** or **cmake-gui** to configure the project and then build it
  146. with your chosen build tool. Then run the built Tutorial executable.
  147. Which function gives better results, Step1’s sqrt or Step2’s mysqrt?
  148. Adding Usage Requirements for Library (Step 3)
  149. ==============================================
  150. Usage requirements allow for far better control over a library or executable's
  151. link and include line while also giving more control over the transitive
  152. property of targets inside CMake. The primary commands that leverage usage
  153. requirements are:
  154. - ``target_compile_definitions``
  155. - ``target_compile_options``
  156. - ``target_include_directories``
  157. - ``target_link_libraries``
  158. First up is MathFunctions. We first state that anybody linking to MathFunctions
  159. needs to include the current source directory, while MathFunctions itself
  160. doesn't. So this can become an ``INTERFACE`` usage requirement.
  161. Remember ``INTERFACE`` means things that consumers require but the producer
  162. doesn't. Update ``MathFunctions/CMakeLists.txt`` with:
  163. .. literalinclude:: Step4/MathFunctions/CMakeLists.txt
  164. :language: cmake
  165. :start-after: # to find MathFunctions.h
  166. Now that we've specified usage requirements for MathFunctions we can safely
  167. remove our uses of the ``EXTRA_INCLUDES`` variable from the top-level
  168. CMakeLists.
  169. Once this is done, run **cmake** or **cmake-gui** to configure the project
  170. and then build it with your chosen build tool or by using ``cmake --build .``
  171. from the build directory.
  172. Installing and Testing (Step 4)
  173. ===============================
  174. Now we can start adding install rules and testing support to our project.
  175. Install Rules
  176. -------------
  177. The install rules are fairly simple for MathFunctions we want to install the
  178. library and header file and for the application we want to install the
  179. executable and configured header.
  180. So to ``MathFunctions/CMakeLists.txt`` we add:
  181. .. literalinclude:: Step5/MathFunctions/CMakeLists.txt
  182. :language: cmake
  183. :start-after: # install rules
  184. And the to top-level ``CMakeLists.txt`` we add:
  185. .. literalinclude:: Step5/CMakeLists.txt
  186. :language: cmake
  187. :start-after: # add the install targets
  188. :end-before: # enable testing
  189. That is all that is needed to create a basic local install of the tutorial.
  190. Run **cmake** or **cmake-gui** to configure the project and then build it
  191. with your chosen build tool. Run the install step by typing
  192. ``cmake --install .`` or from the command line, or build the ``INSTALL``
  193. target from an IDE. This will install the appropriate header files, libraries,
  194. and executables.
  195. Verify that the installed Tutorial runs. Note: The CMake variable
  196. ``CMAKE_INSTALL_PREFIX`` is used to determine the root of where the files will
  197. be installed. If using ``cmake --install`` a custom installation directory can
  198. be given via ``--prefix`` argument.
  199. Testing Support
  200. ---------------
  201. Next let's test our application. At the end of the top-level CMakeLists file we
  202. can add a number of basic tests to verify that the application is
  203. working correctly.
  204. .. literalinclude:: Step5/CMakeLists.txt
  205. :language: cmake
  206. :start-after: # enable testing
  207. The first test simply verifies that the application runs, does not segfault or
  208. otherwise crash, and has a zero return value. This is the basic form of a CTest
  209. test.
  210. The next test makes use of the ``PASS_REGULAR_EXPRESSION`` test property to
  211. verify that the output of the test contains certain strings, in this case:
  212. verifying that the the usage message is printed when an incorrect number of
  213. arguments are provided.
  214. Lastly, we have a function called ``do_test`` that runs the application and
  215. verifies that the computed square root is correct for given input. For each
  216. invocation of ``do_test``, another test is added to the project with a name,
  217. input, and expected results based on the passed arguments.
  218. Rebuild the application and then cd to the binary directory and run
  219. ``ctest -N`` and ``ctest -VV``.
  220. Adding System Introspection (Step 5)
  221. ====================================
  222. Let us consider adding some code to our project that depends on features the
  223. target platform may not have. For this example, we will add some code that
  224. depends on whether or not the target platform has the ``log`` and ``exp``
  225. functions. Of course almost every platform has these functions but for this
  226. tutorial assume that they are not common.
  227. If the platform has ``log`` and ``exp`` then we will use them to compute the
  228. square root in the ``mysqrt`` function. We first test for the availability of
  229. these functions using the ``CheckSymbolExists.cmake`` macro in the top-level
  230. CMakeLists file as follows:
  231. .. literalinclude:: Step6/CMakeLists.txt
  232. :language: cmake
  233. :start-after: # does this system provide the log and exp functions?
  234. :end-before: # should we use our own math functions
  235. Now let's add these defines to ``TutorialConfig.h.in`` so that we can use them
  236. from ``mysqrt.cxx``:
  237. .. literalinclude:: Step6/TutorialConfig.h.in
  238. :language: c
  239. :start-after: // does the platform provide exp and log functions?
  240. Finally, in the ``mysqrt`` function we can provide an alternate implementation
  241. based on ``log`` and ``exp`` if they are available on the system using the
  242. following code:
  243. .. literalinclude:: Step6/MathFunctions/mysqrt.cxx
  244. :language: c++
  245. :start-after: // if we have both log and exp then use them
  246. :end-before: #else
  247. Run **cmake** or **cmake-gui** to configure the project and then build it
  248. with your chosen build tool.
  249. You will notice that even though ``HAVE_LOG`` and ``HAVE_EXP`` are both
  250. defined ``mysqrt`` isn't using them. We should realize quickly that we have
  251. forgotten to include ``TutorialConfig.h`` in ``mysqrt.cxx``.
  252. After making this update, go ahead and build the project again.
  253. Run the built Tutorial executable. Which function gives better results now,
  254. Step1’s sqrt or Step5’s mysqrt?
  255. **Exercise**: Why is it important that we configure ``TutorialConfig.h.in``
  256. after the checks for ``HAVE_LOG`` and ``HAVE_EXP``? What would happen if we
  257. inverted the two?
  258. **Exercise**: Is there a better place for us to save the ``HAVE_LOG`` and
  259. ``HAVE_EXP`` values other than in ``TutorialConfig.h``?
  260. Adding a Custom Command and Generated File (Step 6)
  261. ===================================================
  262. In this section, we will add a generated source file into the build process
  263. of an application. For this example, we will create a table of precomputed
  264. square roots as part of the build process, and then compile that
  265. table into our application.
  266. To accomplish this, we first need a program that will generate the table. In
  267. the MathFunctions subdirectory a new source file named ``MakeTable.cxx`` will
  268. do just that.
  269. .. literalinclude:: Step7/MathFunctions/MakeTable.cxx
  270. :language: c++
  271. Note that the table is produced as valid C++ code and that the output filename
  272. is passed in as an argument.
  273. The next step is to add the appropriate commands to MathFunctions' CMakeLists
  274. file to build the MakeTable executable and then run it as part of the build
  275. process. A few commands are needed to accomplish this.
  276. First, the executable for ``MakeTable`` is added as any other executable would
  277. be added.
  278. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt
  279. :language: cmake
  280. :start-after: # first we add the executable that generates the table
  281. :end-before: # add the command to generate the source code
  282. Then we add a custom command that specifies how to produce ``Table.h``
  283. by running MakeTable.
  284. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt
  285. :language: cmake
  286. :start-after: # add the command to generate the source code
  287. :end-before: # add the main library
  288. Next we have to let CMake know that ``mysqrt.cxx`` depends on the generated
  289. file ``Table.h``. This is done by adding the generated ``Table.h`` to the list
  290. of sources for the library MathFunctions.
  291. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt
  292. :language: cmake
  293. :start-after: # add the main library
  294. :end-before: # state that anybody linking
  295. We also have to add the current binary directory to the list of include
  296. directories so that ``Table.h`` can be found and included by ``mysqrt.cxx``.
  297. .. literalinclude:: Step7/MathFunctions/CMakeLists.txt
  298. :start-after: # state that we depend on our bin
  299. :end-before: # install rules
  300. Now let's use the generated table. First, modify ``mysqrt.cxx`` to include
  301. ``Table.h``. Next, we can rewrite the mysqrt function to use the table:
  302. .. literalinclude:: Step7/MathFunctions/mysqrt.cxx
  303. :language: c++
  304. :start-after: // a hack square root calculation using simple operations
  305. Run **cmake** or **cmake-gui** to configure the project and then build it
  306. with your chosen build tool. When this project is built it will first build
  307. the ``MakeTable`` executable. It will then run ``MakeTable`` to produce
  308. ``Table.h``. Finally, it will compile ``mysqrt.cxx`` which includes
  309. ``Table.h`` to produce the MathFunctions library.
  310. Building an Installer (Step 7)
  311. ==============================
  312. Next suppose that we want to distribute our project to other people so that
  313. they can use it. We want to provide both binary and source distributions on a
  314. variety of platforms. This is a little different from the install we did
  315. previously in `Installing and Testing (Step 4)`_ , where we were
  316. installing the binaries that we had built from the source code. In this
  317. example we will be building installation packages that support binary
  318. installations and package management features. To accomplish this we will use
  319. CPack to create platform specific installers. Specifically we need to add
  320. a few lines to the bottom of our top-level ``CMakeLists.txt`` file.
  321. .. literalinclude:: Step8/CMakeLists.txt
  322. :language: cmake
  323. :start-after: # setup installer
  324. That is all there is to it. We start by including
  325. ``InstallRequiredSystemLibraries``. This module will include any runtime
  326. libraries that are needed by the project for the current platform. Next we
  327. set some CPack variables to where we have stored the license and version
  328. information for this project. The version information makes use of the
  329. variables we set earlier in this tutorial. Finally we include the CPack
  330. module which will use these variables and some other properties of the system
  331. you are on to setup an installer.
  332. The next step is to build the project in the usual manner and then run
  333. CPack on it. To build a binary distribution you would run:
  334. .. code-block:: console
  335. cpack
  336. To create a source distribution you would type:
  337. .. code-block:: console
  338. cpack -C CPackSourceConfig.cmake
  339. Alternatively, run ``make package`` or right click the ``Package`` target and
  340. ``Build Project`` from an IDE.
  341. Run the installer executable found in the binary directory. Then run the
  342. installed executable and verify that it works.
  343. Adding Support for a Dashboard (Step 8)
  344. =======================================
  345. Adding support for submitting our test results to a dashboard is very easy. We
  346. already defined a number of tests for our project in the earlier steps of this
  347. tutorial. We just have to run those tests and submit them to a dashboard. To
  348. include support for dashboards we include the CTest module in our top-level
  349. ``CMakeLists.txt``.
  350. Replace:
  351. .. code-block:: cmake
  352. # enable testing
  353. enable_testing()
  354. With:
  355. .. code-block:: cmake
  356. # enable dashboard scripting
  357. include(CTest)
  358. The CTest module will automatically call ``enable_testing()``, so
  359. we can remove it from our CMake files.
  360. We will also need to create a ``CTestConfig.cmake`` file where we can specify
  361. the name of the project and where to submit the dashboard.
  362. .. literalinclude:: Step9/CTestConfig.cmake
  363. :language: cmake
  364. CTest will read in this file when it runs. To create a simple dashboard you can
  365. run **cmake** or **cmake-gui** to configure the project, but do not build it
  366. yet. Instead, change directory to the binary tree, and then run:
  367. .. code-block:: console
  368. 'ctest [-VV] –D Experimental'
  369. On Windows, build the EXPERIMENTAL target.
  370. Ctest will build and test the project and submit the results to the Kitware
  371. public dashboard. The results of your dashboard will be uploaded to Kitware's
  372. public dashboard here: https://my.cdash.org/index.php?project=CMakeTutorial.
  373. Mixing Static and Shared (Step 9)
  374. =================================
  375. In this section we will show how by using the ``BUILD_SHARED_LIBS`` variable
  376. we can control the default behavior of ``add_library``, and allow control
  377. over how libraries without an explicit type (STATIC/SHARED/MODULE/OBJECT) are
  378. built.
  379. To accomplish this we need to add ``BUILD_SHARED_LIBS`` to the top-level
  380. ``CMakeLists.txt``. We use the ``option`` command as it allows users to
  381. optionally select if the value should be On or Off.
  382. Next we are going to refactor MathFunctions to become a real library that
  383. encapsulates using ``mysqrt`` or ``sqrt``, instead of requiring the calling
  384. code to do this logic. This will also mean that ``USE_MYMATH`` will not control
  385. building MathFuctions, but instead will control the behavior of this library.
  386. The first step is to update the starting section of the top-level
  387. ``CMakeLists.txt`` to look like:
  388. .. literalinclude:: Step10/CMakeLists.txt
  389. :language: cmake
  390. :start-after: set(Tutorial_VERSION_MINOR
  391. :end-before: # add the binary tree
  392. Now that we have made MathFunctions always be used, we will need to update
  393. the logic of that library. So, in ``MathFunctions/CMakeLists.txt`` we need to
  394. create a SqrtLibrary that will conditionally be built when ``USE_MYMATH`` is
  395. enabled. Now, since this is a tutorial, we are going to explicitly require
  396. that SqrtLibrary is built statically.
  397. The end result is that ``MathFunctions/CMakeLists.txt`` should look like:
  398. .. literalinclude:: Step10/MathFunctions/CMakeLists.txt
  399. :language: cmake
  400. :lines: 1-40,46-
  401. Next, update ``MathFunctions/mysqrt.cxx`` to use the ``mathfunctions`` and
  402. ``detail`` namespaces:
  403. .. literalinclude:: Step10/MathFunctions/mysqrt.cxx
  404. :language: c++
  405. We also need to make some changes in ``tutorial.cxx``, so that it no longer
  406. uses ``USE_MYMATH``:
  407. #. Always include ``MathFunctions.h``
  408. #. Always use ``mathfunctions::sqrt``
  409. Finally, update ``MathFunctions/MathFunctions.h`` to use dll export defines:
  410. .. literalinclude:: Step10/MathFunctions/MathFunctions.h
  411. :language: c++
  412. At this point, if you build everything, you will notice that linking fails
  413. as we are combining a static library without position enabled code with a
  414. library that has position enabled code. The solution to this is to explicitly
  415. set the ``POSITION_INDEPENDENT_CODE`` target property of SqrtLibrary to be
  416. True no matter the build type.
  417. **Exercise**: We modified ``MathFunctions.h`` to use dll export defines.
  418. Using CMake documentation can you find a helper module to simplify this?
  419. Adding Generator Expressions (Step 10)
  420. ======================================
  421. Generator expressions are evaluated during build system generation to produce
  422. information specific to each build configuration.
  423. Generator expressions are allowed in the context of many target properties,
  424. such as ``LINK_LIBRARIES``, ``INCLUDE_DIRECTORIES``, ``COMPILE_DEFINITIONS``
  425. and others. They may also be used when using commands to populate those
  426. properties, such as ``target_link_libraries()``,
  427. ``target_include_directories()``,
  428. ``target_compile_definitions()`` and others.
  429. Generator expressions may be used to enable conditional linking, conditional
  430. definitions used when compiling, conditional include directories and more.
  431. The conditions may be based on the build configuration, target properties,
  432. platform information or any other queryable information.
  433. There are different types of generator expressions including Logical,
  434. Informational, and Output expressions.
  435. Logical expressions are used to create conditional output. The basic
  436. expressions are the 0 and 1 expressions. A ``$<0:...>`` results in the empty
  437. string, and ``<1:...>`` results in the content of "...". They can also be
  438. nested.
  439. For example:
  440. .. code-block:: cmake
  441. if(HAVE_LOG AND HAVE_EXP)
  442. target_compile_definitions(SqrtLibrary
  443. PRIVATE "HAVE_LOG" "HAVE_EXP")
  444. endif()
  445. Can be rewritten with generator expressions:
  446. .. code-block:: cmake
  447. target_compile_definitions(SqrtLibrary PRIVATE
  448. "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
  449. "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
  450. )
  451. Note that ``${HAVE_LOG}`` is evaluated at CMake configure time while
  452. ``$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>`` is evaluated at build system generation
  453. time.
  454. Adding Export Configuration (Step 11)
  455. =====================================
  456. During `Installing and Testing (Step 4)`_ of the tutorial we added the ability
  457. for CMake to install the library and headers of the project. During
  458. `Building an Installer (Step 7)`_ we added the ability to package up this
  459. information so it could be distributed to other people.
  460. The next step is to add the necessary information so that other CMake projects
  461. can use our project, be it from a build directory, a local install or when
  462. packaged.
  463. The first step is to update our ``install(TARGETS)`` commands to not only
  464. specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword
  465. generates and installs a CMake file containing code to import all targets
  466. listed in the install command from the installation tree. So let's go ahead
  467. and explicitly ``EXPORT`` the MathFunctions library by updating the
  468. ``install`` command in ``MathFunctions/CMakeLists.txt`` to look like:
  469. .. literalinclude:: Complete/MathFunctions/CMakeLists.txt
  470. :language: cmake
  471. :start-after: # install rules
  472. Now that we have MathFunctions being exported, we also need to explicitly
  473. install the generated ``MathFunctionsTargets.cmake`` file. This is done by
  474. adding the following to the bottom of the top-level ``CMakeLists.txt``:
  475. .. literalinclude:: Complete/CMakeLists.txt
  476. :language: cmake
  477. :start-after: # install the configuration targets
  478. :end-before: include(CMakePackageConfigHelpers)
  479. At this point you should try and run CMake. If everything is setup properly
  480. you will see that CMake will generate an error that looks like:
  481. .. code-block:: console
  482. Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
  483. path:
  484. "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
  485. which is prefixed in the source directory.
  486. What CMake is trying to say is that during generating the export information
  487. it will export a path that is intrinsically tied to the current machine and
  488. will not be valid on other machines. The solution to this is to update the
  489. MathFunctions ``target_include_directories`` to understand that it needs
  490. different ``INTERFACE`` locations when being used from within the build
  491. directory and from an install / package. This means converting the
  492. ``target_include_directories`` call for MathFunctions to look like:
  493. .. literalinclude:: Complete/MathFunctions/CMakeLists.txt
  494. :language: cmake
  495. :start-after: # to find MathFunctions.h, while we don't.
  496. :end-before: # should we use our own math functions
  497. Once this has been updated, we can re-run CMake and see verify that it doesn't
  498. warn anymore.
  499. At this point, we have CMake properly packaging the target information that is
  500. required but we will still need to generate a ``MathFunctionsConfig.cmake`` so
  501. that the CMake ``find_package command`` can find our project. So let's go
  502. ahead and add a new file to the top-level of the project called
  503. ``Config.cmake.in`` with the following contents:
  504. .. literalinclude:: Complete/Config.cmake.in
  505. Then, to properly configure and install that file, add the following to the
  506. bottom of the top-level CMakeLists:
  507. .. literalinclude:: Complete/CMakeLists.txt
  508. :language: cmake
  509. :start-after: # install the configuration targets
  510. :end-before: # generate the export
  511. At this point, we have generated a relocatable CMake Configuration for our
  512. project that can be used after the project has been installed or packaged. If
  513. we want our project to also be used from a build directory we only have to add
  514. the following to the bottom of the top level CMakeLists:
  515. .. literalinclude:: Complete/CMakeLists.txt
  516. :language: cmake
  517. :start-after: # needs to be after the install(TARGETS ) command
  518. With this export call we now generate a ``Targets.cmake``, allowing the
  519. configured ``MathFunctionsConfig.cmake`` in the build directory to be used by
  520. other projects, without needing it to be installed.
  521. Import a CMake Project (Consumer)
  522. =================================
  523. This examples shows how a project can find other CMake packages that
  524. generate ``Config.cmake`` files.
  525. It also shows how to state a project's external dependencies when generating
  526. a ``Config.cmake``.
  527. Packaging Debug and Release (MultiPackage)
  528. ==========================================
  529. By default CMake is model is that a build directory only contains a single
  530. configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo.
  531. But it is possible to setup CPack to bundle multiple build directories at the
  532. same time to build a package that contains multiple configurations of the
  533. same project.
  534. First we need to ahead and construct a directory called ``multi_config`` this
  535. will contain all the builds that we want to package together.
  536. Second create a ``debug`` and ``release`` directory underneath
  537. ``multi_config``. At the end you should have a layout that looks like:
  538. ─ multi_config
  539. ├── debug
  540. └── release
  541. Now we need to setup debug and release builds, which would roughly entail
  542. the following:
  543. .. code-block:: console
  544. cd debug
  545. cmake -DCMAKE_BUILD_TYPE=Debug ../../MultiPackage/
  546. cmake --build .
  547. cd ../release
  548. cmake -DCMAKE_BUILD_TYPE=Release ../../MultiPackage/
  549. cmake --build .
  550. cd ..
  551. Now that both the debug and release builds are complete we can now use
  552. the custom MultiCPackConfig to package both builds into a single release.
  553. .. code-block:: console
  554. cpack --config ../../MultiPackage/MultiCPackConfig.cmake