Installation Commands and Concepts.rst 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596
  1. Step 9: Installation Commands and Concepts
  2. ==========================================
  3. Projects need to do more than build and test their code, they need to make it
  4. available to consumers. The layout of files in the build tree is unsuitable
  5. for consumption by other projects, binaries are in unexpected places, header
  6. files are located far away in the source tree, and there's no clear way
  7. to discover what targets are provided or how to use them.
  8. This translation, moving artifacts from the source and build trees into a final
  9. layout suitable for consumption, is known as installation. CMake supports a
  10. complete installation workflow as part of the project description, controlling
  11. both the layout of artifacts in the install tree, and reconstructing targets
  12. for other CMake projects which want to consume the libraries provided by the
  13. install tree.
  14. Background
  15. ^^^^^^^^^^
  16. All CMake installation goes through a single command, :command:`install`, which
  17. is split into many subcommands responsible for various aspects of the
  18. installation process. For target-based CMake workflows, it is mostly sufficient
  19. to rely on installing targets themselves with :command:`install(TARGETS)`
  20. instead of resorting to manually moving files with :command:`install(FILES)`
  21. or :command:`install(DIRECTORY)`.
  22. .. note::
  23. This is why we need to add ``FILES`` to header sets which are intended to be
  24. installed. CMake needs to be able to locate the files when their associated
  25. target is installed.
  26. CMake divides target-based installation into various artifact kinds. The
  27. available artifact kinds (in CMake 3.23) are:
  28. ``ARCHIVE``
  29. Static libraries (``.a`` / ``.lib``), DLL import libraries (``.lib``), and
  30. a handful of other "archive-like" objects.
  31. ``LIBRARY``
  32. Shared libraries (``.so``), modules, and other dynamically loadable
  33. objects. **Not** Window's DLL files (``.dll``) or MacOS frameworks.
  34. ``RUNTIME``
  35. Executables of all kinds except MacOS bundles; and Window's DLLs (``.dll``).
  36. ``OBJECT``
  37. Objects from ``OBJECT`` libraries.
  38. ``FRAMEWORK``
  39. Both static and shared MacOS frameworks
  40. ``BUNDLE``
  41. MacOS bundle executables
  42. ``PUBLIC_HEADER`` / ``PRIVATE_HEADER`` / ``RESOURCE``
  43. Files described by the :prop_tgt:`PUBLIC_HEADER`, :prop_tgt:`PRIVATE_HEADER`
  44. and :prop_tgt:`RESOURCE` target properties, typically used with MacOS
  45. frameworks
  46. ``FILE_SET <set-name>``
  47. A file set associated with the target. This is how headers are typically
  48. installed.
  49. Most important artifact kinds have known destinations which CMake will default
  50. to unless instructed to do otherwise. For example, ``RUNTIME`` will be installed
  51. to the location named by :module:`CMAKE_INSTALL_BINDIR <GNUInstallDirs>`, if
  52. the variable is available, otherwise they default to ``bin``.
  53. The full list of artifact kind default destinations is described in the
  54. following table.
  55. =============================== =============================== ======================
  56. Target Type Variable Built-In Default
  57. =============================== =============================== ======================
  58. ``RUNTIME`` ``${CMAKE_INSTALL_BINDIR}`` ``bin``
  59. ``LIBRARY`` ``${CMAKE_INSTALL_LIBDIR}`` ``lib``
  60. ``ARCHIVE`` ``${CMAKE_INSTALL_LIBDIR}`` ``lib``
  61. ``PRIVATE_HEADER`` ``${CMAKE_INSTALL_INCLUDEDIR}`` ``include``
  62. ``PUBLIC_HEADER`` ``${CMAKE_INSTALL_INCLUDEDIR}`` ``include``
  63. ``FILE_SET`` (type ``HEADERS``) ``${CMAKE_INSTALL_INCLUDEDIR}`` ``include``
  64. =============================== =============================== ======================
  65. For the most part, projects should leave the defaults alone unless they need to
  66. install to a specific subdirectory of a default location.
  67. CMake does not define the ``CMAKE_INSTALL_<dir>`` variables by default. If a
  68. project wishes to dictate installing to a subdirectory of one of these
  69. locations, it is necessary to include the :module:`GNUInstallDirs` module, which
  70. will provide values for all ``CMAKE_INSTALL_<dir>`` variables that have not
  71. already been defined.
  72. Exercise 1 - Installing Artifacts
  73. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  74. For modern, target-based CMake projects installation of artifacts is trivial
  75. and consists of a single call to :command:`install(targets)`.
  76. .. code-block:: cmake
  77. install(
  78. TARGETS MyApp MyLib
  79. FILE_SET HEADERS
  80. FILE_SET AnotherHeaderFileSet
  81. )
  82. Most artifact kinds are installed by default and do not need to be listed in
  83. the :command:`install` command. However, ``FILE_SET``\ s must be named to let
  84. CMake know you want to install. In the above example we install two file
  85. sets, one named ``HEADERS`` and another named ``AnotherHeaderFileSet``.
  86. When named, an artifact kind can be given various options, such as a destination.
  87. .. code-block:: cmake
  88. include(GNUInstallDirs)
  89. install(
  90. TARGETS MyApp MyLib
  91. RUNTIME
  92. DESTINATION ${CMAKE_INSTALL_BINDIR}/Subfolder
  93. FILE_SET HEADERS
  94. )
  95. This will install the ``MyApp`` target to ``bin/Subfolder`` (if the packager
  96. hasn't changed :module:`CMAKE_INSTALL_BINDIR <GNUInstallDirs>`).
  97. Importantly, if the ``OBJECT`` artifact kind is never given a destination, it
  98. will act like an ``INTERFACE`` library, only installing its headers.
  99. Goal
  100. ----
  101. Install the artifacts for the libraries and executables (except tests) described
  102. in the tutorial project.
  103. Helpful Resources
  104. -----------------
  105. * :command:`install`
  106. Files to Edit
  107. -------------
  108. * ``CMakeLists.txt``
  109. Getting Started
  110. ---------------
  111. The ``Help/guide/tutorial/Step9`` directory contains the complete, recommended
  112. solution to ``Step8``. Complete ``TODO 1`` and ``TODO 2``.
  113. Build and Run
  114. -------------
  115. No special configuration is needed, configure and build as usual.
  116. .. code-block:: console
  117. cmake --preset tutorial
  118. cmake --build build
  119. We can verify the installation is correct with :option:`cmake --install`.
  120. .. code-block:: console
  121. cmake --install build --prefix install
  122. The ``install`` folder should be populated correctly for our artifacts.
  123. Solution
  124. --------
  125. First we add an :command:`install(TARGETS)` for the conditionally built,
  126. thus conditionally installed, ``Tutorial`` executable.
  127. .. raw:: html
  128. <details><summary>TODO 1 Click to show/hide answer</summary>
  129. .. code-block:: cmake
  130. :caption: TODO 1: CMakeLists.txt
  131. :name: CMakeLists.txt-install-tutorial
  132. if(TUTORIAL_BUILD_UTILITIES)
  133. add_subdirectory(Tutorial)
  134. install(
  135. TARGETS Tutorial
  136. )
  137. endif()
  138. .. raw:: html
  139. </details>
  140. Then we can install the rest of the targets.
  141. .. raw:: html
  142. <details><summary>TODO 2 Click to show/hide answer</summary>
  143. .. code-block:: cmake
  144. :caption: TODO 2: CMakeLists.txt
  145. :name: CMakeLists.txt-install-libs
  146. install(
  147. TARGETS MathFunctions OpAdd OpMul OpSub MathLogger SqrtTable
  148. FILE_SET HEADERS
  149. )
  150. .. raw:: html
  151. </details>
  152. .. note::
  153. We could add :command:`install(TARGETS)` commands locally to each subfolder
  154. where the targets are defined. This would be typical in very large projects
  155. where keeping track of all the installable targets is difficult.
  156. It might seem unnecessary to install the ``SqrtTable`` and ``MathLogger``,
  157. and it is at this stage. Due to how CMake models target relationships, when we
  158. reconstruct the target model in the next exercise we will need these targets to
  159. be available.
  160. Exercise 2 - Exporting Targets
  161. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  162. This raw collection of installed files is a good start, but we lose the CMake
  163. target model. These are effectively no better than the pre-compiled vendored
  164. libraries we discussed in ``Step 4``. We need some way for other projects to
  165. reconstruct our targets from what we have provided in the install tree.
  166. The mechanism CMake provides to solve this is a CMakeLang file known as a
  167. "target export file". It is created by the :command:`install(EXPORT)`
  168. command.
  169. .. code-block:: cmake
  170. install(
  171. TARGETS MyApp MyLib
  172. EXPORT MyProjectTargets
  173. )
  174. include(GNUInstallDirs)
  175. install(
  176. EXPORT MyProjectTargets
  177. DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyProject
  178. NAMESPACE MyProject::
  179. )
  180. There are several parts to the above example. Firstly the
  181. :command:`install(TARGETS)` command takes an export name, basically a list to
  182. add the installed targets to.
  183. Later, the :command:`install(EXPORT)` command consumes this list of targets
  184. to generate the target export file. This will be a file named
  185. ``<ExportName>.cmake`` located in the provided ``DESTINATION``. The
  186. ``DESTINATION`` provided in this example is the conventional one, but any
  187. location searched by the :command:`find_package` command is valid.
  188. Finally, the targets created by the target export file will be prefixed with the
  189. ``NAMESPACE`` string, ie they will be of the form ``<NAMESPACE><TargetName>``.
  190. It is conventional for this to be the project name followed by two colons.
  191. For reasons that will become more obvious in future steps, we typically don't
  192. consume this file directly. Instead we have a file named
  193. ``<ProjectName>Config.cmake`` consume it via :command:`include()`.
  194. .. code-block:: cmake
  195. include(${CMAKE_CURRENT_LIST_DIR}/MyProjectTargets.cmake)
  196. .. note::
  197. The :variable:`CMAKE_CURRENT_LIST_DIR` variable names the directory that the
  198. currently running CMake Language file is inside of, regardless of how that
  199. file was included or launched.
  200. Then this file is installed alongside the target export with
  201. :command:`install(FILES)`.
  202. .. code-block:: cmake
  203. install(
  204. FILES
  205. cmake/MyProjectConfig.cmake
  206. DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/MyProject
  207. )
  208. .. note::
  209. The name of this file and its location are dictated by the discovery
  210. semantics of the :command:`find_package` command, which we will discuss more
  211. in the next step.
  212. Goal
  213. ----
  214. Export the Tutorial project targets so other projects may consume them.
  215. Helpful Resources
  216. -----------------
  217. * :command:`install`
  218. * :module:`GNUInstallDirs`
  219. * :variable:`CMAKE_CURRENT_LIST_DIR`
  220. Files to Edit
  221. -------------
  222. * ``CMakeLists.txt``
  223. * ``cmake/TutorialConfig.cmake``
  224. Getting Started
  225. ---------------
  226. Continue editing the files in the ``Help/guide/tutorial/Step9`` directory.
  227. Complete ``TODO 3`` through ``TODO 8``.
  228. Build and Run
  229. -------------
  230. The build command is sufficient to reconfigure the project.
  231. .. code-block:: console
  232. cmake --build build
  233. We can verify the installation is correct with :option:`cmake --install`.
  234. .. note::
  235. As with CTest, when using multi-config generator, eg Visual Studio, it will be
  236. necessary to specify a configuration with
  237. ``cmake --install --config <config> <remaining flags>``, where
  238. ``<config>`` is a value like ``Debug`` or ``Release``. This is true whenever
  239. using a multi-config generator, and won't be called out specifically in
  240. future commands.
  241. .. code-block:: console
  242. cmake --install build --prefix install
  243. .. note::
  244. CMake won't update files which have not changed, only installing new or
  245. updated files from the build and source trees.
  246. The ``install`` folder should be populated correctly for our artifacts and
  247. export files. We'll demonstrate how to use these files in the next step.
  248. Solution
  249. --------
  250. First we add the ``Tutorial`` target to the ``TutorialTargets`` export.
  251. .. raw:: html
  252. <details><summary>TODO 3 Click to show/hide answer</summary>
  253. .. literalinclude:: Step10/TutorialProject/CMakeLists.txt
  254. :caption: TODO 3: CMakeLists.txt
  255. :name: CMakeLists.txt-install-tutorial-export
  256. :language: cmake
  257. :start-at: install(
  258. :end-at: )
  259. .. raw:: html
  260. </details>
  261. Soon we will need access to the ``CMAKE_INSTALL_<dir>`` variables, so next
  262. we include the :module:`GNUInstallDirs` module.
  263. .. raw:: html
  264. <details><summary>TODO 4 Click to show/hide answer</summary>
  265. .. literalinclude:: Step10/TutorialProject/CMakeLists.txt
  266. :caption: TODO 4: CMakeLists.txt
  267. :name: CMakeLists.txt-gnuinstalldirss
  268. :language: cmake
  269. :start-at: include(GNUInstallDirs)
  270. :end-at: include(GNUInstallDirs)
  271. .. raw:: html
  272. </details>
  273. Now we add the rest of our targets to the ``TutorialTargets`` export.
  274. .. raw:: html
  275. <details><summary>TODO 5 Click to show/hide answer</summary>
  276. .. literalinclude:: Step10/TutorialProject/CMakeLists.txt
  277. :caption: TODO 5: CMakeLists.txt
  278. :name: CMakeLists.txt-install-libs-export
  279. :language: cmake
  280. :start-at: TARGETS MathFunctions
  281. :end-at: )
  282. :prepend: install(
  283. .. raw:: html
  284. </details>
  285. Next we install the export itself, to generate our target export file.
  286. .. raw:: html
  287. <details><summary>TODO 6 Click to show/hide answer</summary>
  288. .. code-block:: cmake
  289. :caption: TODO 6: CMakeLists.txt
  290. :name: CMakeLists.txt-install-export
  291. install(
  292. EXPORT TutorialTargets
  293. DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Tutorial
  294. NAMESPACE Tutorial::
  295. )
  296. .. raw:: html
  297. </details>
  298. And then we install our "config" file, which we will use to include our target
  299. export file.
  300. .. raw:: html
  301. <details><summary>TODO 7 Click to show/hide answer</summary>
  302. .. code-block:: cmake
  303. :caption: TODO 7: CMakeLists.txt
  304. :name: CMakeLists.txt-install-config
  305. install(
  306. FILES
  307. cmake/TutorialConfig.cmake
  308. DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Tutorial
  309. )
  310. .. raw:: html
  311. </details>
  312. Finally we can add the necessary :command:`include` command to the config file.
  313. .. raw:: html
  314. <details><summary>TODO 8 Click to show/hide answer</summary>
  315. .. literalinclude:: Step10/TutorialProject/cmake/TutorialConfig.cmake
  316. :caption: TODO 8: cmake/TutorialConfig.cmake
  317. :name: cmake/TutorialConfig.cmake
  318. :language: cmake
  319. :start-at: include
  320. :end-at: include
  321. .. raw:: html
  322. </details>
  323. Exercise 3 - Exporting a Version File
  324. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  325. When importing CMake targets from a target export file, there is no way to
  326. "bail out" or "undo" the operation. If it turns out a package is a wrong or
  327. incompatible version for the one we requested, we'll be stuck with any
  328. side-effects incurred while we learned that version information.
  329. The answer CMake provides for this problem is a light-weight version file which
  330. only describes this version compatibility information, which can be checked
  331. before CMake commits to fully importing the file.
  332. CMake provides helper modules and scripts for generating these version files,
  333. namely the :module:`CMakePackageConfigHelpers` module.
  334. .. code-block:: cmake
  335. include(CMakePackageConfigHelpers)
  336. write_basic_package_version_file(
  337. ${CMAKE_CURRENT_BINARY_DIR}/MyProjectConfigVersion.cmake
  338. COMPATIBILITY ExactVersion
  339. )
  340. The available versions are:
  341. * ``AnyNewerVersion``
  342. * ``SameMajorVersion``
  343. * ``SameMinorVersion``
  344. * ``ExactVersion``
  345. Additionally packages can mark themselves as ``ARCH_INDEPENDENT``, intended for
  346. packages which ship no binaries which would tie them to a specific machine
  347. architecture.
  348. By default, the ``VERSION`` used by ``write_basic_package_version_file()`` is
  349. the ``VERSION`` number given to the :command:`project` command.
  350. Goal
  351. ----
  352. Export a version file for the Tutorial project.
  353. Helpful Resources
  354. -----------------
  355. * :command:`project`
  356. * :command:`install`
  357. * :module:`CMakePackageConfigHelpers`
  358. * :variable:`PROJECT_VERSION`
  359. Files to Edit
  360. -------------
  361. * ``CMakeLists.txt``
  362. Getting Started
  363. ---------------
  364. Continue editing the files in the ``Help/guide/tutorial/Step9`` directory.
  365. Complete ``TODO 9`` through ``TODO 12``.
  366. Build and Run
  367. -------------
  368. Rebuild and install as done previously.
  369. .. code-block:: console
  370. cmake --build build
  371. cmake --install build --prefix install
  372. The ``install`` folder should be populated correctly with our newly generated
  373. and installed version file.
  374. Solution
  375. --------
  376. First we add a ``VERSION`` parameter to the :command:`project` command.
  377. .. raw:: html
  378. <details><summary>TODO 9 Click to show/hide answer</summary>
  379. .. literalinclude:: Step10/TutorialProject/CMakeLists.txt
  380. :caption: TODO 9: CMakeLists.txt
  381. :name: CMakeLists.txt-project-version
  382. :language: cmake
  383. :start-at: project(
  384. :end-at: )
  385. .. raw:: html
  386. </details>
  387. Next we include the :module:`CMakePackageConfigHelpers` modules and use it
  388. to generate the config version file.
  389. .. raw:: html
  390. <details><summary>TODO 10-11 Click to show/hide answer</summary>
  391. .. literalinclude:: Step10/TutorialProject/CMakeLists.txt
  392. :caption: TODO 10-11: CMakeLists.txt
  393. :name: CMakeLists.txt-write_basic_package_version_file
  394. :language: cmake
  395. :start-at: include(CMakePackageConfigHelpers
  396. :end-at: COMPATIBILITY ExactVersion
  397. :append: )
  398. .. raw:: html
  399. </details>
  400. Finally we add the config version file to the list of files to be installed.
  401. .. raw:: html
  402. <details><summary>TODO 12 Click to show/hide answer</summary>
  403. .. literalinclude:: Step10/TutorialProject/CMakeLists.txt
  404. :caption: TODO 12: CMakeLists.txt
  405. :name: CMakeLists.txt-install-version-config
  406. :language: cmake
  407. :start-at: FILES
  408. :end-at: )
  409. :prepend: install(
  410. .. raw:: html
  411. </details>