index.rst 33 KB

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