# Adding Export Configuration #

During Step 4 of the tutorial we added the ability for CMake to install the
library and headers of the project. During Step 7 we added the ability
to package up this information so it could be distributed to other people.

The next step is to add the necessary information so that other CMake projects
can use our project, be it from a build directory, a local install or when
packaged.

The first step is to update our install(TARGETS) commands to not only specify
a DESTINATION but also an EXPORT. The EXPORT keyword generates and installs a
CMake file containing code to import all targets listed in the install command
from the installation tree. So let's go ahead and explicitly EXPORT the
MathFunctions library by updating the install command in
MathFunctions/CMakeLists.txt to look like:

  install(TARGETS MathFunctions DESTINATION lib EXPORT MathFunctionsTargets)

Now that we have MathFunctions being exported, we also need to explicitly install
the generated MathFunctionsTargets.cmake file. This is done by adding
the following to the bottom of the top-level CMakeLists.txt:

  # install the configuration targets
  install(EXPORT MathFunctionsTargets
    FILE MathFunctionsTargets.cmake
    DESTINATION lib/cmake/MathFunctions
  )

At this point you should try and run CMake. If everything is setup properly
you will see that CMake will generate an error that looks like:

  Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
  path:

    "/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"

  which is prefixed in the source directory.

What CMake is trying to say is that during generating the export information
it will export a path that is intrinsically tied to the current machine and
will not be valid on other machines. The solution to this is to update the
MathFunctions target_include_directories to understand that it needs different
INTERFACE locations when being used from within the build directory and from an
install / package. This means converting the target_include_directories
call for MathFunctions to look like:

  target_include_directories(MathFunctions
                             INTERFACE
                              $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
                              $<INSTALL_INTERFACE:include>
                             )

Once this has been updated, we can re-run CMake and see verify that it doesn't
warn anymore.

At this point, we have CMake properly packaging the target information that is
required but we will still need to generate a MathFunctionsConfig.cmake, so
that the CMake find_package command can find our project. So let's go ahead and
add a new file to the top-level of the project called Config.cmake.in with the
following contents:

  @PACKAGE_INIT@

  include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" )

Then, to properly configure and install that file, add the following to the
bottom of the top-level CMakeLists:

  include(CMakePackageConfigHelpers)
  # generate the config file that is includes the exports
  configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
    "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
    INSTALL_DESTINATION "lib/cmake/example"
    NO_SET_AND_CHECK_MACRO
    NO_CHECK_REQUIRED_COMPONENTS_MACRO
    )
  # generate the version file for the config file
  write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
    VERSION "${Tutorial_VERSION_MAJOR}.${Tutorial_VERSION_MINOR}"
    COMPATIBILITY AnyNewerVersion
  )

  # install the configuration file
  install(FILES
    ${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
    DESTINATION lib/cmake/MathFunctions
    )

At this point, we have generated a relocatable CMake Configuration for our project
that can be used after the project has been installed or packaged. If we want
our project to also be used from a build directory we only have to add
the following to the bottom of the top level CMakeLists:

  # generate the export targets for the build tree
  # needs to be after the install(TARGETS ) command
  export(EXPORT MathFunctionsTargets
    FILE "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake"
  )

With this export call we now generate a Targets.cmake, allowing the configured
MathFunctionsConfig.cmake in the build directory to be used by other projects,
without needing it to be installed.
