1 Step 11: Adding Export Configuration
2 ====================================
4 During :guide:`tutorial/Installing and Testing` of the tutorial we added the
5 ability for CMake to install the library and headers of the project. During
6 :guide:`tutorial/Packaging an Installer` we added the ability to package up
7 this information so it could be distributed to other people.
9 The next step is to add the necessary information so that other CMake projects
10 can use our project, be it from a build directory, a local install or when
13 The first step is to update our :command:`install(TARGETS)` commands to not
14 only specify a ``DESTINATION`` but also an ``EXPORT``. The ``EXPORT`` keyword
15 generates a CMake file containing code to import all targets listed in the
16 install command from the installation tree. So let's go ahead and explicitly
17 ``EXPORT`` the ``MathFunctions`` library by updating the ``install`` command
18 in ``MathFunctions/CMakeLists.txt`` to look like:
20 .. literalinclude:: Complete/MathFunctions/CMakeLists.txt
21 :caption: MathFunctions/CMakeLists.txt
22 :name: MathFunctions/CMakeLists.txt-install-TARGETS-EXPORT
24 :start-after: # install rules
26 Now that we have ``MathFunctions`` being exported, we also need to explicitly
27 install the generated ``MathFunctionsTargets.cmake`` file. This is done by
28 adding the following to the bottom of the top-level ``CMakeLists.txt``:
30 .. literalinclude:: Complete/CMakeLists.txt
31 :caption: CMakeLists.txt
32 :name: CMakeLists.txt-install-EXPORT
34 :start-after: # install the configuration targets
35 :end-before: include(CMakePackageConfigHelpers)
37 At this point you should try and run CMake. If everything is setup properly
38 you will see that CMake will generate an error that looks like:
40 .. code-block:: console
42 Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
45 "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
47 which is prefixed in the source directory.
49 What CMake is trying to say is that during generating the export information
50 it will export a path that is intrinsically tied to the current machine and
51 will not be valid on other machines. The solution to this is to update the
52 ``MathFunctions`` :command:`target_include_directories` to understand that it
53 needs different ``INTERFACE`` locations when being used from within the build
54 directory and from an install / package. This means converting the
55 :command:`target_include_directories` call for ``MathFunctions`` to look like:
57 .. literalinclude:: Step12/MathFunctions/CMakeLists.txt
58 :caption: MathFunctions/CMakeLists.txt
59 :name: MathFunctions/CMakeLists.txt-target_include_directories
61 :start-after: # to find MathFunctions.h, while we don't.
62 :end-before: # should we use our own math functions
64 Once this has been updated, we can re-run CMake and verify that it doesn't
67 At this point, we have CMake properly packaging the target information that is
68 required but we will still need to generate a ``MathFunctionsConfig.cmake`` so
69 that the CMake :command:`find_package` command can find our project. So let's go
70 ahead and add a new file to the top-level of the project called
71 ``Config.cmake.in`` with the following contents:
73 .. literalinclude:: Step12/Config.cmake.in
74 :caption: Config.cmake.in
75 :name: Config.cmake.in
77 Then, to properly configure and install that file, add the following to the
78 bottom of the top-level ``CMakeLists.txt``:
80 .. literalinclude:: Step12/CMakeLists.txt
81 :caption: CMakeLists.txt
82 :name: CMakeLists.txt-install-Config.cmake
84 :start-after: # install the configuration targets
85 :end-before: # generate the config file
88 Next, we execute the :command:`configure_package_config_file`. This command
89 will configure a provided file but with a few specific differences from the
90 standard :command:`configure_file` way.
91 To properly utilize this function, the input file should have a single line
92 with the text ``@PACKAGE_INIT@`` in addition to the content that is desired.
93 That variable will be replaced with a block of code which turns set values into
94 relative paths. These values which are new can be referenced by the same name
95 but prepended with a ``PACKAGE_`` prefix.
97 .. literalinclude:: Step12/CMakeLists.txt
98 :caption: CMakeLists.txt
99 :name: CMakeLists.txt-configure-package-config.cmake
101 :start-after: # install the configuration targets
102 :end-before: # generate the version file
104 The :command:`write_basic_package_version_file` is next. This command writes
105 a file which is used by the "find_package" document the version and
106 compatibility of the desired package. Here, we use the ``Tutorial_VERSION_*``
107 variables and say that it is compatible with ``AnyNewerVersion``, which
108 denotes that this version or any higher one are compatible with the requested
111 .. literalinclude:: Step12/CMakeLists.txt
112 :caption: CMakeLists.txt
113 :name: CMakeLists.txt-basic-version-file.cmake
115 :start-after: # generate the version file
116 :end-before: # install the generated configuration files
118 Finally, set both generated files to be installed:
120 .. literalinclude:: Step12/CMakeLists.txt
121 :caption: CMakeLists.txt
122 :name: CMakeLists.txt-install-configured-files.cmake
124 :start-after: # install the generated configuration files
125 :end-before: # generate the export
127 At this point, we have generated a relocatable CMake Configuration for our
128 project that can be used after the project has been installed or packaged. If
129 we want our project to also be used from a build directory we only have to add
130 the following to the bottom of the top level ``CMakeLists.txt``:
132 .. literalinclude:: Step12/CMakeLists.txt
133 :caption: CMakeLists.txt
134 :name: CMakeLists.txt-export
136 :start-after: # needs to be after the install(TARGETS ) command
138 With this export call we now generate a ``Targets.cmake``, allowing the
139 configured ``MathFunctionsConfig.cmake`` in the build directory to be used by
140 other projects, without needing it to be installed.