diff options
Diffstat (limited to 'Help')
37 files changed, 1295 insertions, 7 deletions
diff --git a/Help/command/add_library.rst b/Help/command/add_library.rst index f3df631..b7dfabc 100644 --- a/Help/command/add_library.rst +++ b/Help/command/add_library.rst @@ -14,7 +14,7 @@ Normal Libraries add_library(<name> [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] - [source1] [source2 ...]) + [<source>...]) Adds a library target called ``<name>`` to be built from the source files listed in the command invocation. (The source files can be omitted here @@ -69,7 +69,7 @@ Object Libraries .. code-block:: cmake - add_library(<name> OBJECT <src>...) + add_library(<name> OBJECT [<source>...]) Creates an :ref:`Object Library <Object Libraries>`. An object library compiles source files but does not archive or link their object files into a diff --git a/Help/guide/importing-exporting/Downstream/CMakeLists.txt b/Help/guide/importing-exporting/Downstream/CMakeLists.txt new file mode 100644 index 0000000..381c875 --- /dev/null +++ b/Help/guide/importing-exporting/Downstream/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.15) +project(Downstream) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# find MathFunctions +find_package(MathFunctions 3.4.1 EXACT) + +# create executable +add_executable(myexe main.cc) + +# use MathFunctions library +target_link_libraries(myexe PRIVATE MathFunctions::MathFunctions) diff --git a/Help/guide/importing-exporting/Downstream/main.cc b/Help/guide/importing-exporting/Downstream/main.cc new file mode 100644 index 0000000..8574373 --- /dev/null +++ b/Help/guide/importing-exporting/Downstream/main.cc @@ -0,0 +1,23 @@ +// A simple program that outputs the square root of a number +#include <iostream> +#include <string> + +#include "MathFunctions.h" + +int main(int argc, char* argv[]) +{ + if (argc < 2) { + std::cout << "Usage: " << argv[0] << " number" << std::endl; + return 1; + } + + // convert input to double + const double inputValue = std::stod(argv[1]); + + // calculate square root + const double sqrt = MathFunctions::sqrt(inputValue); + std::cout << "The square root of " << inputValue << " is " << sqrt + << std::endl; + + return 0; +} diff --git a/Help/guide/importing-exporting/DownstreamComponents/CMakeLists.txt b/Help/guide/importing-exporting/DownstreamComponents/CMakeLists.txt new file mode 100644 index 0000000..88b46c8 --- /dev/null +++ b/Help/guide/importing-exporting/DownstreamComponents/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.15) +project(DownstreamComponents) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# find MathFunctions +find_package(MathFunctions 3.4 COMPONENTS Addition SquareRoot) + +# create executable +add_executable(myexe main.cc) + +# use MathFunctions library +target_link_libraries(myexe PRIVATE MathFunctions::Addition MathFunctions::SquareRoot) + +# Workaround for GCC on AIX to avoid -isystem, not needed in general. +set_property(TARGET myexe PROPERTY NO_SYSTEM_FROM_IMPORTED 1) diff --git a/Help/guide/importing-exporting/DownstreamComponents/main.cc b/Help/guide/importing-exporting/DownstreamComponents/main.cc new file mode 100644 index 0000000..f5e8fa6 --- /dev/null +++ b/Help/guide/importing-exporting/DownstreamComponents/main.cc @@ -0,0 +1,28 @@ +// A simple program that outputs the square root of a number +#include <iostream> +#include <string> + +#include "Addition.h" +#include "SquareRoot.h" + +int main(int argc, char* argv[]) +{ + if (argc < 2) { + std::cout << "Usage: " << argv[0] << " number" << std::endl; + return 1; + } + + // convert input to double + const double inputValue = std::stod(argv[1]); + + // calculate square root + const double sqrt = MathFunctions::sqrt(inputValue); + std::cout << "The square root of " << inputValue << " is " << sqrt + << std::endl; + + // calculate sum + const double sum = MathFunctions::add(inputValue, inputValue); + std::cout << inputValue << " + " << inputValue << " = " << sum << std::endl; + + return 0; +} diff --git a/Help/guide/importing-exporting/Importing/CMakeLists.txt b/Help/guide/importing-exporting/Importing/CMakeLists.txt new file mode 100644 index 0000000..fe7d704 --- /dev/null +++ b/Help/guide/importing-exporting/Importing/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.15) +project(Importing) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# Add executable +add_executable(myexe IMPORTED) + +# Set imported location +set_property(TARGET myexe PROPERTY + IMPORTED_LOCATION "../InstallMyExe/bin/myexe") + +# Add custom command to create source file +add_custom_command(OUTPUT main.cc COMMAND myexe) + +# Use source file +add_executable(mynewexe main.cc) diff --git a/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt new file mode 100644 index 0000000..13c82dd --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctions/CMakeLists.txt @@ -0,0 +1,75 @@ +cmake_minimum_required(VERSION 3.15) +project(MathFunctions) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# create library +add_library(MathFunctions STATIC MathFunctions.cxx) + +# add include directories +target_include_directories(MathFunctions + PUBLIC + "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>" + "$<INSTALL_INTERFACE:include>" +) + +# install the target and create export-set +install(TARGETS MathFunctions + EXPORT MathFunctionsTargets + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin + INCLUDES DESTINATION include +) + +# install header file +install(FILES MathFunctions.h DESTINATION include) + +# generate and install export file +install(EXPORT MathFunctionsTargets + FILE MathFunctionsTargets.cmake + NAMESPACE MathFunctions:: + DESTINATION lib/cmake +) + +# include CMakePackageConfigHelpers macro +include(CMakePackageConfigHelpers) + +# set version +set(version 3.4.1) + +set_property(TARGET MathFunctions PROPERTY VERSION ${version}) +set_property(TARGET MathFunctions PROPERTY SOVERSION 3) +set_property(TARGET MathFunctions PROPERTY + INTERFACE_MathFunctions_MAJOR_VERSION 3) +set_property(TARGET MathFunctions APPEND PROPERTY + COMPATIBLE_INTERFACE_STRING MathFunctions_MAJOR_VERSION +) + +# generate the version file for the config file +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake" + VERSION "${version}" + COMPATIBILITY AnyNewerVersion +) + +# create config file +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake" + INSTALL_DESTINATION lib/cmake +) + +# install config files +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake" + DESTINATION lib/cmake +) + +# generate the export targets for the build tree +export(EXPORT MathFunctionsTargets + FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/MathFunctionsTargets.cmake" + NAMESPACE MathFunctions:: +) diff --git a/Help/guide/importing-exporting/MathFunctions/Config.cmake.in b/Help/guide/importing-exporting/MathFunctions/Config.cmake.in new file mode 100644 index 0000000..eba1ff6 --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctions/Config.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake") + +check_required_components(MathFunctions) diff --git a/Help/guide/importing-exporting/MathFunctions/MathFunctions.cxx b/Help/guide/importing-exporting/MathFunctions/MathFunctions.cxx new file mode 100644 index 0000000..e75fe74 --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctions/MathFunctions.cxx @@ -0,0 +1,10 @@ +#include "MathFunctions.h" + +#include <cmath> + +namespace MathFunctions { +double sqrt(double x) +{ + return std::sqrt(x); +} +} diff --git a/Help/guide/importing-exporting/MathFunctions/MathFunctions.h b/Help/guide/importing-exporting/MathFunctions/MathFunctions.h new file mode 100644 index 0000000..b38596d --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctions/MathFunctions.h @@ -0,0 +1,5 @@ +#pragma once + +namespace MathFunctions { +double sqrt(double x); +} diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/Addition/Addition.cxx b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/Addition.cxx new file mode 100644 index 0000000..0a6b98b --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/Addition.cxx @@ -0,0 +1,8 @@ +#include "Addition.h" + +namespace MathFunctions { +double add(double x, double y) +{ + return x + y; +} +} diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/Addition/Addition.h b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/Addition.h new file mode 100644 index 0000000..b061d5e --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/Addition.h @@ -0,0 +1,5 @@ +#pragma once + +namespace MathFunctions { +double add(double x, double y); +} diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt new file mode 100644 index 0000000..e3cf711 --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/Addition/CMakeLists.txt @@ -0,0 +1,30 @@ +# create library +add_library(Addition STATIC Addition.cxx) + +add_library(MathFunctions::Addition ALIAS Addition) + +# add include directories +target_include_directories(Addition + PUBLIC + "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>" + $<INSTALL_INTERFACE:include> +) + +# install the target and create export-set +install(TARGETS Addition + EXPORT AdditionTargets + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin + INCLUDES DESTINATION include +) + +# install header file +install(FILES Addition.h DESTINATION include) + +# generate and install export file +install(EXPORT AdditionTargets + FILE MathFunctionsAdditionTargets.cmake + NAMESPACE MathFunctions:: + DESTINATION lib/cmake +) diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt new file mode 100644 index 0000000..4e3496d --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.15) +project(MathFunctionsComponents) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +add_subdirectory(Addition) +add_subdirectory(SquareRoot) + +# include CMakePackageConfigHelpers macro +include(CMakePackageConfigHelpers) + +# set version +set(version 3.4.1) + +# generate the version file for the config file +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake" + VERSION "${version}" + COMPATIBILITY AnyNewerVersion +) + +# create config file +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake" + INSTALL_DESTINATION lib/cmake + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) + +# install config files +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake" + DESTINATION lib/cmake +) diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/Config.cmake.in b/Help/guide/importing-exporting/MathFunctionsComponents/Config.cmake.in new file mode 100644 index 0000000..09f6c35 --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/Config.cmake.in @@ -0,0 +1,11 @@ +@PACKAGE_INIT@ + +set(_supported_components Addition SquareRoot) + +foreach(_comp ${MathFunctions_FIND_COMPONENTS}) + if (NOT _comp IN_LIST _supported_components) + set(MathFunctions_FOUND False) + set(MathFunctions_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}") + endif() + include("${CMAKE_CURRENT_LIST_DIR}/MathFunctions${_comp}Targets.cmake") +endforeach() diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/MathFunctions.cxx b/Help/guide/importing-exporting/MathFunctionsComponents/MathFunctions.cxx new file mode 100644 index 0000000..e75fe74 --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/MathFunctions.cxx @@ -0,0 +1,10 @@ +#include "MathFunctions.h" + +#include <cmath> + +namespace MathFunctions { +double sqrt(double x) +{ + return std::sqrt(x); +} +} diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/MathFunctions.h b/Help/guide/importing-exporting/MathFunctionsComponents/MathFunctions.h new file mode 100644 index 0000000..b38596d --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/MathFunctions.h @@ -0,0 +1,5 @@ +#pragma once + +namespace MathFunctions { +double sqrt(double x); +} diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt new file mode 100644 index 0000000..ffa1e3d --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/CMakeLists.txt @@ -0,0 +1,30 @@ +# create library +add_library(SquareRoot STATIC SquareRoot.cxx) + +add_library(MathFunctions::SquareRoot ALIAS SquareRoot) + +# add include directories +target_include_directories(SquareRoot + PUBLIC + "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>" + "$<INSTALL_INTERFACE:include>" +) + +# install the target and create export-set +install(TARGETS SquareRoot + EXPORT SquareRootTargets + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin + INCLUDES DESTINATION include +) + +# install header file +install(FILES SquareRoot.h DESTINATION include) + +# generate and install export file +install(EXPORT SquareRootTargets + FILE MathFunctionsSquareRootTargets.cmake + NAMESPACE MathFunctions:: + DESTINATION lib/cmake +) diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/SquareRoot.cxx b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/SquareRoot.cxx new file mode 100644 index 0000000..29c0c4a --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/SquareRoot.cxx @@ -0,0 +1,10 @@ +#include "SquareRoot.h" + +#include <cmath> + +namespace MathFunctions { +double sqrt(double x) +{ + return std::sqrt(x); +} +} diff --git a/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/SquareRoot.h b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/SquareRoot.h new file mode 100644 index 0000000..b38596d --- /dev/null +++ b/Help/guide/importing-exporting/MathFunctionsComponents/SquareRoot/SquareRoot.h @@ -0,0 +1,5 @@ +#pragma once + +namespace MathFunctions { +double sqrt(double x); +} diff --git a/Help/guide/importing-exporting/MyExe/CMakeLists.txt b/Help/guide/importing-exporting/MyExe/CMakeLists.txt new file mode 100644 index 0000000..34e37a4 --- /dev/null +++ b/Help/guide/importing-exporting/MyExe/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.15) +project(MyExe) + +# specify the C++ standard +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED True) + +# Add executable +add_executable(myexe main.cxx) + +# install executable +install(TARGETS myexe) diff --git a/Help/guide/importing-exporting/MyExe/main.cxx b/Help/guide/importing-exporting/MyExe/main.cxx new file mode 100644 index 0000000..35ab2a7 --- /dev/null +++ b/Help/guide/importing-exporting/MyExe/main.cxx @@ -0,0 +1,16 @@ +// A simple program that outputs a file with the given name +#include <fstream> +#include <iostream> + +int main(int argc, char* argv[]) +{ + std::ofstream outfile("main.cc"); + outfile << "int main(int argc, char* argv[])" << std::endl; + outfile << "{" << std::endl; + outfile << " // Your code here" << std::endl; + outfile << " return 0;" << std::endl; + outfile << "}" << std::endl; + outfile.close(); + + return 0; +} diff --git a/Help/guide/importing-exporting/index.rst b/Help/guide/importing-exporting/index.rst new file mode 100644 index 0000000..b0cfb71 --- /dev/null +++ b/Help/guide/importing-exporting/index.rst @@ -0,0 +1,765 @@ +Importing and Exporting Targets +******************************* + +.. only:: html + + .. contents:: + +In this guide, we will present the concept of :prop_tgt:`IMPORTED` targets +and demonstrate how to import existing executable or library files from disk +into a CMake project. We will then show how CMake supports exporting targets +from one CMake-based project and importing them into another. Finally, we +will demonstrate how to package a project with a configuration file to allow +for easy integration into other CMake projects. This guide and the complete +example source code can be found in the ``Help/guide/importing-exporting`` +directory of the CMake source code tree. + + +Importing Targets +================= + +:prop_tgt:`IMPORTED` targets are used to convert files outside of a CMake +project into logical targets inside of the project. :prop_tgt:`IMPORTED` +targets are created using the ``IMPORTED`` option of the +:command:`add_executable` and :command:`add_library` commands. No build +files are generated for :prop_tgt:`IMPORTED` targets. Once imported, +:prop_tgt:`IMPORTED` targets may be referenced like any other target within +the project and provide a convenient, flexible reference to outside +executables and libraries. + +By default, the :prop_tgt:`IMPORTED` target name has scope in the directory in +which it is created and below. We can use the ``GLOBAL`` option to extended +visibility so that the target is accessible globally in the build system. + +Details about the :prop_tgt:`IMPORTED` target are specified by setting +properties whose names begin in ``IMPORTED_`` and ``INTERFACE_``. For example, +:prop_tgt:`IMPORTED_LOCATION` contains the full path to the target on +disk. + +Importing Executables +--------------------- + +To start, we will walk through a simple example that creates an +:prop_tgt:`IMPORTED` executable target and then references it from the +:command:`add_custom_command` command. + +We'll need to do some setup to get started. We want to create an executable +that when run creates a basic ``main.cc`` file in the current directory. The +details of this project are not important. Navigate to +``Help/guide/importing-exporting/MyExe``, create a build directory, run +:manual:`cmake <cmake(1)>` and build and install the project. + +.. code-block:: console + + $ cd Help/guide/importing-exporting/MyExe + $ mkdir build + $ cd build + $ cmake .. + $ cmake --build . + $ cmake --install . --prefix <install location> + $ <install location>/myexe + $ ls + [...] main.cc [...] + +Now we can import this executable into another CMake project. The source code +for this section is available in ``Help/guide/importing-exporting/Importing``. +In the CMakeLists file, use the :command:`add_executable` command to create a +new target called ``myexe``. Use the ``IMPORTED`` option to tell CMake that +this target references an executable file located outside of the project. No +rules will be generated to build it and the :prop_tgt:`IMPORTED` target +property will be set to ``true``. + +.. literalinclude:: Importing/CMakeLists.txt + :language: cmake + :start-after: # Add executable + :end-before: # Set imported location + +Next, set the :prop_tgt:`IMPORTED_LOCATION` property of the target using +the :command:`set_property` command. This will tell CMake the location of the +target on disk. The location may need to be adjusted to the +``<install location>`` specified in the previous step. + +.. literalinclude:: Importing/CMakeLists.txt + :language: cmake + :start-after: # Set imported location + :end-before: # Add custom command + +We can now reference this :prop_tgt:`IMPORTED` target just like any target +built within the project. In this instance, let's imagine that we want to use +the generated source file in our project. Use the :prop_tgt:`IMPORTED` +target in the :command:`add_custom_command` command: + +.. literalinclude:: Importing/CMakeLists.txt + :language: cmake + :start-after: # Add custom command + :end-before: # Use source file + +As ``COMMAND`` specifies an executable target name, it will automatically be +replaced by the location of the executable given by the +:prop_tgt:`IMPORTED_LOCATION` property above. + +Finally, use the output from :command:`add_custom_command`: + +.. literalinclude:: Importing/CMakeLists.txt + :language: cmake + :start-after: # Use source file + +Importing Libraries +------------------- + +In a similar manner, libraries from other projects may be accessed through +:prop_tgt:`IMPORTED` targets. + +Note: The full source code for the examples in this section is not provided +and is left as an exercise for the reader. + +In the CMakeLists file, add an :prop_tgt:`IMPORTED` library and specify its +location on disk: + +.. code-block:: cmake + + add_library(foo STATIC IMPORTED) + set_property(TARGET foo PROPERTY + IMPORTED_LOCATION "/path/to/libfoo.a") + +Then use the :prop_tgt:`IMPORTED` library inside of our project: + +.. code-block:: cmake + + add_executable(myexe src1.c src2.c) + target_link_libraries(myexe PRIVATE foo) + + +On Windows, a .dll and its .lib import library may be imported together: + +.. code-block:: cmake + + add_library(bar SHARED IMPORTED) + set_property(TARGET bar PROPERTY + IMPORTED_LOCATION "c:/path/to/bar.dll") + set_property(TARGET bar PROPERTY + IMPORTED_IMPLIB "c:/path/to/bar.lib") + add_executable(myexe src1.c src2.c) + target_link_libraries(myexe PRIVATE bar) + +A library with multiple configurations may be imported with a single target: + +.. code-block:: cmake + + find_library(math_REL NAMES m) + find_library(math_DBG NAMES md) + add_library(math STATIC IMPORTED GLOBAL) + set_target_properties(math PROPERTIES + IMPORTED_LOCATION "${math_REL}" + IMPORTED_LOCATION_DEBUG "${math_DBG}" + IMPORTED_CONFIGURATIONS "RELEASE;DEBUG" + ) + add_executable(myexe src1.c src2.c) + target_link_libraries(myexe PRIVATE math) + +The generated build system will link ``myexe`` to ``m.lib`` when built in the +release configuration, and ``md.lib`` when built in the debug configuration. + +Exporting Targets +================= + +While :prop_tgt:`IMPORTED` targets on their own are useful, they still +require that the project that imports them knows the locations of the target +files on disk. The real power of :prop_tgt:`IMPORTED` targets is when the +project providing the target files also provides a CMake file to help import +them. A project can be setup to produce the necessary information so that it +can easily be used by other CMake projects be it from a build directory, a +local install or when packaged. + +In the remaining sections, we will walk through a set of example projects +step-by-step. The first project will create and install a library and +corresponding CMake configuration and package files. The second project will +use the generated package. + +Let's start by looking at the ``MathFunctions`` project in the +``Help/guide/importing-exporting/MathFunctions`` directory. Here we have a +header file ``MathFunctions.h`` that declares a ``sqrt`` function: + +.. literalinclude:: MathFunctions/MathFunctions.h + :language: c++ + +And a corresponding source file ``MathFunctions.cxx``: + +.. literalinclude:: MathFunctions/MathFunctions.cxx + :language: c++ + +Don't worry too much about the specifics of the C++ files, they are just meant +to be a simple example that will compile and run on many build systems. + +Now we can create a ``CMakeLists.txt`` file for the ``MathFunctions`` +project. Start by specifying the :command:`cmake_minimum_required` version and +:command:`project` name: + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :end-before: # create library + +Create a library called ``MathFunctions`` with the :command:`add_library` +command: + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # create library + :end-before: # add include directories + +And then use the :command:`target_include_directories` command to specify the +include directories for the target: + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # add include directories + :end-before: # install the target and create export-set + +We need to tell CMake that we want to use different include directories +depending on if we're building the library or using it from an installed +location. If we don't do this, when CMake creates the export information it +will export a path that is specific to the current build directory +and will not be valid for other projects. We can use +:manual:`generator expressions <cmake-generator-expressions(7)>` to specify +that if we're building the library include the current source directory. +Otherwise, when installed, include the ``include`` directory. See the `Creating +Relocatable Packages`_ section for more details. + +The :command:`install(TARGETS)` and :command:`install(EXPORT)` commands +work together to install both targets (a library in our case) and a CMake +file designed to make it easy to import the targets into another CMake project. + +First, in the :command:`install(TARGETS)` command we will specify the target, +the ``EXPORT`` name and the destinations that tell CMake where to install the +targets. + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # install the target and create export-set + :end-before: # install header file + +Here, the ``EXPORT`` option tells CMake to create an export called +``MathFunctionsTargets``. The generated :prop_tgt:`IMPORTED` targets have +appropriate properties set to define their +:ref:`usage requirements <Target Usage Requirements>`, such as +:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES`, +:prop_tgt:`INTERFACE_COMPILE_DEFINITIONS` and other relevant built-in +``INTERFACE_`` properties. The ``INTERFACE`` variant of user-defined +properties listed in :prop_tgt:`COMPATIBLE_INTERFACE_STRING` and other +:ref:`Compatible Interface Properties` are also propagated to the +generated :prop_tgt:`IMPORTED` targets. For example, in this case, the +:prop_tgt:`IMPORTED` target will have its +:prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` property populated with +the directory specified by the ``INCLUDES DESTINATION`` property. As a +relative path was given, it is treated as relative to the +:variable:`CMAKE_INSTALL_PREFIX`. + +Note, we have *not* asked CMake to install the export yet. + +We don't want to forget to install the ``MathFunctions.h`` header file with the +:command:`install(FILES)` command. The header file should be installed to the +``include`` directory, as specified by the +:command:`target_include_directories` command above. + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # install header file + :end-before: # generate and install export file + +Now that the ``MathFunctions`` library and header file are installed, we also +need to explicitly install the ``MathFunctionsTargets`` export details. Use +the :command:`install(EXPORT)` command to export the targets in +``MathFunctionsTargets``, as defined by the :command:`install(TARGETS)` +command. + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # generate and install export file + :end-before: # include CMakePackageConfigHelpers macro + +This command generates the ``MathFunctionsTargets.cmake`` file and arranges +to install it to ``lib/cmake``. The file contains code suitable for +use by downstreams to import all targets listed in the install command from +the installation tree. + +The ``NAMESPACE`` option will prepend ``MathFunctions::`` to the target names +as they are written to the export file. This convention of double-colons +gives CMake a hint that the name is an :prop_tgt:`IMPORTED` target when it +is used by downstream projects. This way, CMake can issue a diagnostic +message if the package providing it was not found. + +The generated export file contains code that creates an :prop_tgt:`IMPORTED` library. + +.. code-block:: cmake + + # Create imported target MathFunctions::MathFunctions + add_library(MathFunctions::MathFunctions STATIC IMPORTED) + + set_target_properties(MathFunctions::MathFunctions PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" + ) + +This code is very similar to the example we created by hand in the +`Importing Libraries`_ section. Note that ``${_IMPORT_PREFIX}`` is computed +relative to the file location. + +An outside project may load this file with the :command:`include` command and +reference the ``MathFunctions`` library from the installation tree as if it +were built in its own tree. For example: + +.. code-block:: cmake + :linenos: + + include(${INSTALL_PREFIX}/lib/cmake/MathFunctionTargets.cmake) + add_executable(myexe src1.c src2.c ) + target_link_libraries(myexe PRIVATE MathFunctions::MathFunctions) + +Line 1 loads the target CMake file. Although we only exported a single +target, this file may import any number of targets. Their locations are +computed relative to the file location so that the install tree may be +easily moved. Line 3 references the imported ``MathFunctions`` library. The +resulting build system will link to the library from its installed location. + +Executables may also be exported and imported using the same process. + +Any number of target installations may be associated with the same +export name. Export names are considered global so any directory may +contribute a target installation. The :command:`install(EXPORT)` command only +needs to be called once to install a file that references all targets. Below +is an example of how multiple exports may be combined into a single +export file, even if they are in different subdirectories of the project. + +.. code-block:: cmake + + # A/CMakeLists.txt + add_executable(myexe src1.c) + install(TARGETS myexe DESTINATION lib/myproj + EXPORT myproj-targets) + + # B/CMakeLists.txt + add_library(foo STATIC foo1.c) + install(TARGETS foo DESTINATION lib EXPORTS myproj-targets) + + # Top CMakeLists.txt + add_subdirectory (A) + add_subdirectory (B) + install(EXPORT myproj-targets DESTINATION lib/myproj) + +Creating Packages +----------------- + +At this point, the ``MathFunctions`` project is exporting the target +information required to be used by other projects. We can make this project +even easier for other projects to use by generating a configuration file so +that the CMake :command:`find_package` command can find our project. + +To start, we will need to make a few additions to the ``CMakeLists.txt`` +file. First, include the :module:`CMakePackageConfigHelpers` module to get +access to some helper functions for creating config files. + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # include CMakePackageConfigHelpers macro + :end-before: # set version + +Then we will create a package configuration file and a package version file. + +Creating a Package Configuration File +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Use the :command:`configure_package_config_file` command provided by the +:module:`CMakePackageConfigHelpers` to generate the package configuration +file. Note that this command should be used instead of the plain +:command:`configure_file` command. It helps to ensure that the resulting +package is relocatable by avoiding hardcoded paths in the installed +configuration file. The path given to ``INSTALL_DESTINATION`` must be the +destination where the ``MathFunctionsConfig.cmake`` file will be installed. +We will examine the contents of the package configuration file in the next +section. + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # create config file + :end-before: # install config files + +Install the generated configuration files with the :command:`INSTALL(files)` +command. Both ``MathFunctionsConfigVersion.cmake`` and +``MathFunctionsConfig.cmake`` are installed to the same location, completing +the package. + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # install config files + :end-before: # generate the export targets for the build tree + +Now we need to create the package configuration file itself. In this case, the +``Config.cmake.in`` file is very simple but sufficient to allow downstreams +to use the :prop_tgt:`IMPORTED` targets. + +.. literalinclude:: MathFunctions/Config.cmake.in + +The first line of the file contains only the string ``@PACKAGE_INIT@``. This +expands when the file is configured and allows the use of relocatable paths +prefixed with ``PACKAGE_``. It also provides the ``set_and_check()`` and +``check_required_components()`` macros. + +The ``check_required_components`` helper macro ensures that all requested, +non-optional components have been found by checking the +``<Package>_<Component>_FOUND`` variables for all required components. This +macro should be called at the end of the package configuration file even if the +package does not have any components. This way, CMake can make sure that the +downstream project hasn't specified any non-existent components. If +``check_required_components`` fails, the ``<Package>_FOUND`` variable is set to +FALSE, and the package is considered to be not found. + +The ``set_and_check()`` macro should be used in configuration files instead +of the normal ``set()`` command for setting directories and file locations. +If a referenced file or directory does not exist, the macro will fail. + +If any macros should be provided by the ``MathFunctions`` package, they should +be in a separate file which is installed to the same location as the +``MathFunctionsConfig.cmake`` file, and included from there. + +**All required dependencies of a package must also be found in the package +configuration file.** Let's imagine that we require the ``Stats`` library in +our project. In the CMakeLists file, we would add: + +.. code-block:: cmake + + find_package(Stats 2.6.4 REQUIRED) + target_link_libraries(MathFunctions PUBLIC Stats::Types) + +As the ``Stats::Types`` target is a ``PUBLIC`` dependency of ``MathFunctions``, +downstreams must also find the ``Stats`` package and link to the +``Stats::Types`` library. The ``Stats`` package should be found in the +configuration file to ensure this. + +.. code-block:: cmake + + include(CMakeFindDependencyMacro) + find_dependency(Stats 2.6.4) + +The ``find_dependency`` macro from the :module:`CMakeFindDependencyMacro` +module helps by propagating whether the package is ``REQUIRED``, or +``QUIET``, etc. The ``find_dependency`` macro also sets +``MathFunctions_FOUND`` to ``False`` if the dependency is not found, along +with a diagnostic that the ``MathFunctions`` package cannot be used without +the ``Stats`` package. + +**Exercise:** Add a required library to the ``MathFunctions`` project. + +Creating a Package Version File +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The :module:`CMakePackageConfigHelpers` module provides the +:command:`write_basic_package_version_file` command for creating a simple +package version file. This file is read by CMake when :command:`find_package` +is called to determine the compatibility with the requested version, and to set +some version-specific variables such as ``<PackageName>_VERSION``, +``<PackageName>_VERSION_MAJOR``, ``<PackageName>_VERSION_MINOR``, etc. See +:manual:`cmake-packages <cmake-packages(7)>` documentation for more details. + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # set version + :end-before: # create config file + +In our example, ``MathFunctions_MAJOR_VERSION`` is defined as a +:prop_tgt:`COMPATIBLE_INTERFACE_STRING` which means that it must be +compatible among the dependencies of any depender. By setting this +custom defined user property in this version and in the next version of +``MathFunctions``, :manual:`cmake <cmake(1)>` will issue a diagnostic if +there is an attempt to use version 3 together with version 4. Packages can +choose to employ such a pattern if different major versions of the package +are designed to be incompatible. + + +Exporting Targets from the Build Tree +------------------------------------- + +Typically, projects are built and installed before being used by an outside +project. However, in some cases, it is desirable to export targets directly +from a build tree. The targets may then be used by an outside project that +references the build tree with no installation involved. The :command:`export` +command is used to generate a file exporting targets from a project build tree. + +If we want our example project to also be used from a build directory we only +have to add the following to ``CMakeLists.txt``: + +.. literalinclude:: MathFunctions/CMakeLists.txt + :language: cmake + :start-after: # generate the export targets for the build tree + +Here we use the :command:`export` command to generate the export targets for +the build tree. In this case, we'll create a file called +``MathFunctionsTargets.cmake`` in the ``cmake`` subdirectory of the build +directory. The generated file contains the required code to import the target +and may be loaded by an outside project that is aware of the project build +tree. This file is specific to the build-tree, and **is not relocatable**. + +It is possible to create a suitable package configuration file and package +version file to define a package for the build tree which may be used without +installation. Consumers of the build tree can simply ensure that the +:variable:`CMAKE_PREFIX_PATH` contains the build directory, or set the +``MathFunctions_DIR`` to ``<build_dir>/MathFunctions`` in the cache. + +An example application of this feature is for building an executable on a host +platform when cross-compiling. The project containing the executable may be +built on the host platform and then the project that is being cross-compiled +for another platform may load it. + +Building and Installing a Package +--------------------------------- + +At this point, we have generated a relocatable CMake configuration for our +project that can be used after the project has been installed. Let's try to +build the ``MathFunctions`` project: + +.. code-block:: console + + mkdir MathFunctions_build + cd MathFunctions_build + cmake ../MathFunctions + cmake --build . + +In the build directory, notice that the file ``MathFunctionsTargets.cmake`` +has been created in the ``cmake`` subdirectory. + +Now install the project: + +.. code-block:: console + + $ cmake --install . --prefix "/home/myuser/installdir" + +Creating Relocatable Packages +============================= + +Packages created by :command:`install(EXPORT)` are designed to be relocatable, +using paths relative to the location of the package itself. They must not +reference absolute paths of files on the machine where the package is built +that will not exist on the machines where the package may be installed. + +When defining the interface of a target for ``EXPORT``, keep in mind that the +include directories should be specified as relative paths to the +:variable:`CMAKE_INSTALL_PREFIX` but should not explicitly include the +:variable:`CMAKE_INSTALL_PREFIX`: + +.. code-block:: cmake + + target_include_directories(tgt INTERFACE + # Wrong, not relocatable: + $<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/TgtName> + ) + + target_include_directories(tgt INTERFACE + # Ok, relocatable: + $<INSTALL_INTERFACE:include/TgtName> + ) + +The ``$<INSTALL_PREFIX>`` +:manual:`generator expression <cmake-generator-expressions(7)>` may be used as +a placeholder for the install prefix without resulting in a non-relocatable +package. This is necessary if complex generator expressions are used: + +.. code-block:: cmake + + target_include_directories(tgt INTERFACE + # Ok, relocatable: + $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include/TgtName> + ) + +This also applies to paths referencing external dependencies. +It is not advisable to populate any properties which may contain +paths, such as :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` or +:prop_tgt:`INTERFACE_LINK_LIBRARIES`, with paths relevant to dependencies. +For example, this code may not work well for a relocatable package: + +.. code-block:: cmake + + target_link_libraries(MathFunctions INTERFACE + ${Foo_LIBRARIES} ${Bar_LIBRARIES} + ) + target_include_directories(MathFunctions INTERFACE + "$<INSTALL_INTERFACE:${Foo_INCLUDE_DIRS};${Bar_INCLUDE_DIRS}>" + ) + +The referenced variables may contain the absolute paths to libraries +and include directories **as found on the machine the package was made on**. +This would create a package with hard-coded paths to dependencies not +suitable for relocation. + +Ideally such dependencies should be used through their own +:ref:`IMPORTED targets <Imported Targets>` that have their own +:prop_tgt:`IMPORTED_LOCATION` and usage requirement properties +such as :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` populated +appropriately. Those imported targets may then be used with +the :command:`target_link_libraries` command for ``MathFunctions``: + +.. code-block:: cmake + + target_link_libraries(MathFunctions INTERFACE Foo::Foo Bar::Bar) + +With this approach the package references its external dependencies +only through the names of :ref:`IMPORTED targets <Imported Targets>`. +When a consumer uses the installed package, the consumer will run the +appropriate :command:`find_package` commands (via the ``find_dependency`` +macro described above) to find the dependencies and populate the +imported targets with appropriate paths on their own machine. + +Using the Package Configuration File +==================================== + +Now we're ready to create a project to use the installed ``MathFunctions`` +library. In this section we will be using source code from +``Help\guide\importing-exporting\Downstream``. In this directory, there is a +source file called ``main.cc`` that uses the ``MathFunctions`` library to +calculate the square root of a given number and then prints the results: + +.. literalinclude:: Downstream/main.cc + :language: c++ + +As before, we'll start with the :command:`cmake_minimum_required` and +:command:`project` commands in the ``CMakeLists.txt`` file. For this project, +we'll also specify the C++ standard. + +.. literalinclude:: Downstream/CMakeLists.txt + :language: cmake + :end-before: # find MathFunctions + +We can use the :command:`find_package` command: + +.. literalinclude:: Downstream/CMakeLists.txt + :language: cmake + :start-after: # find MathFunctions + :end-before: # create executable + +Create an exectuable: + +.. literalinclude:: Downstream/CMakeLists.txt + :language: cmake + :start-after: # create executable + :end-before: # use MathFunctions library + +And link to the ``MathFunctions`` library: + +.. literalinclude:: Downstream/CMakeLists.txt + :language: cmake + :start-after: # use MathFunctions library + +That's it! Now let's try to build the ``Downstream`` project. + +.. code-block:: console + + mkdir Downstream_build + cd Downstream_build + cmake ../Downstream + cmake --build . + +A warning may have appeared during CMake configuration: + +.. code-block:: console + + CMake Warning at CMakeLists.txt:4 (find_package): + By not providing "FindMathFunctions.cmake" in CMAKE_MODULE_PATH this + project has asked CMake to find a package configuration file provided by + "MathFunctions", but CMake did not find one. + + Could not find a package configuration file provided by "MathFunctions" + with any of the following names: + + MathFunctionsConfig.cmake + mathfunctions-config.cmake + + Add the installation prefix of "MathFunctions" to CMAKE_PREFIX_PATH or set + "MathFunctions_DIR" to a directory containing one of the above files. If + "MathFunctions" provides a separate development package or SDK, be sure it + has been installed. + +Set the ``CMAKE_PREFIX_PATH`` to where MathFunctions was installed previously +and try again. Ensure that the newly created executable runs as expected. + +Adding Components +================= + +Let's edit the ``MathFunctions`` project to use components. The source code for +this section can be found in +``Help\guide\importing-exporting\MathFunctionsComponents``. The CMakeLists file +for this project adds two subdirectories: ``Addition`` and ``SquareRoot``. + +.. literalinclude:: MathFunctionsComponents/CMakeLists.txt + :language: cmake + :end-before: # include CMakePackageConfigHelpers macro + +Generate and install the package configuration and package version files: + +.. literalinclude:: MathFunctionsComponents/CMakeLists.txt + :language: cmake + :start-after: # include CMakePackageConfigHelpers macro + +If ``COMPONENTS`` are specified when the downstream uses +:command:`find_package`, they are listed in the +``<PackageName>_FIND_COMPONENTS`` variable. We can use this variable to verify +that all necessary component targets are included in ``Config.cmake.in``. At +the same time, this function will act as a custom ``check_required_components`` +macro to ensure that the downstream only attempts to use supported components. + +.. literalinclude:: MathFunctionsComponents/Config.cmake.in + +Here, the ``MathFunctions_NOT_FOUND_MESSAGE`` is set to a diagnosis that the +package could not be found because an invalid component was specified. This +message variable can be set for any case where the ``_FOUND`` variable is set +to ``False``, and will be displayed to the user. + +The ``Addition`` and ``SquareRoot`` directories are similar. Let's look at one +of the CMakeLists files: + +.. literalinclude:: MathFunctionsComponents/SquareRoot/CMakeLists.txt + :language: cmake + +Now we can build the project as described in earlier sections. To test using +this package, we can use the project in +``Help\guide\importing-exporting\DownstreamComponents``. There's two +differences from the previous ``Downstream`` project. First, we need to find +the package components. Change the ``find_package`` line from: + +.. literalinclude:: Downstream/CMakeLists.txt + :language: cmake + :start-after: # find MathFunctions + :end-before: # create executable + +To: + +.. literalinclude:: DownstreamComponents/CMakeLists.txt + :language: cmake + :start-after: # find MathFunctions + :end-before: # create executable + +and the ``target_link_libraries`` line from: + +.. literalinclude:: Downstream/CMakeLists.txt + :language: cmake + :start-after: # use MathFunctions library + +To: + +.. literalinclude:: DownstreamComponents/CMakeLists.txt + :language: cmake + :start-after: # use MathFunctions library + :end-before: # Workaround for GCC on AIX to avoid -isystem + +In ``main.cc``, replace ``#include MathFunctions.h`` with: + +.. literalinclude:: DownstreamComponents/main.cc + :language: c + :start-after: #include <string> + :end-before: int main + +Finally, use the ``Addition`` library: + +.. literalinclude:: DownstreamComponents/main.cc + :language: c + :start-after: // calculate sum + :end-before: return 0; + +Build the ``Downstream`` project and confirm that it can find and use the +package components. diff --git a/Help/index.rst b/Help/index.rst index 4d9a9c8..616769e 100644 --- a/Help/index.rst +++ b/Help/index.rst @@ -84,6 +84,7 @@ Reference Manuals /guide/tutorial/index /guide/user-interaction/index /guide/using-dependencies/index + /guide/importing-exporting/index .. only:: html or text diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index 3821dc3..0392325 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -57,6 +57,7 @@ Policies Introduced by CMake 3.19 .. toctree:: :maxdepth: 1 + CMP0114: ExternalProject step targets fully adopt their steps. </policy/CMP0114> CMP0113: Makefile generators do not repeat custom commands from target dependencies. </policy/CMP0113> CMP0112: Target file component generator expressions do not add target dependencies. </policy/CMP0112> CMP0111: An imported target with a missing location fails during generation. </policy/CMP0111> diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 73130b6..cb9579e 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -315,6 +315,7 @@ Properties on Targets /prop_tgt/OUTPUT_NAME_CONFIG /prop_tgt/OUTPUT_NAME /prop_tgt/PCH_WARN_INVALID + /prop_tgt/PCH_INSTANTIATE_TEMPLATES /prop_tgt/PDB_NAME_CONFIG /prop_tgt/PDB_NAME /prop_tgt/PDB_OUTPUT_DIRECTORY_CONFIG diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index f776018..d50005c 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -444,6 +444,7 @@ Variables that Control the Build /variable/CMAKE_OSX_DEPLOYMENT_TARGET /variable/CMAKE_OSX_SYSROOT /variable/CMAKE_PCH_WARN_INVALID + /variable/CMAKE_PCH_INSTANTIATE_TEMPLATES /variable/CMAKE_PDB_OUTPUT_DIRECTORY /variable/CMAKE_PDB_OUTPUT_DIRECTORY_CONFIG /variable/CMAKE_POSITION_INDEPENDENT_CODE diff --git a/Help/policy/CMP0114.rst b/Help/policy/CMP0114.rst new file mode 100644 index 0000000..1bc1216 --- /dev/null +++ b/Help/policy/CMP0114.rst @@ -0,0 +1,85 @@ +CMP0114 +------- + +.. versionadded:: 3.19 + +:module:`ExternalProject` step targets fully adopt their steps. + +The :command:`ExternalProject_Add` ``STEP_TARGETS`` option, and the +:command:`ExternalProject_Add_StepTargets` function, can be used to +create build targets for individual steps of an external project. + +In CMake 3.18 and below, step targets have some limitations: + +* Step targets always depend on targets named by the + :command:`ExternalProject_Add` ``DEPENDS`` option even though + not all steps need them. In order to allow step targets to be created + without those dependencies, the :command:`ExternalProject_Add` + ``INDEPENDENT_STEP_TARGETS`` option or the + :command:`ExternalProject_Add_StepTargets` ``NO_DEPENDS`` option may + be used. However, adding such "independent" step targets makes sense + only for specific steps such as ``download``, ``update``, and ``patch`` + because they do not need any of the external project's build dependencies. + Furthermore, it does not make sense to create independent step targets + for steps that depend on non-independent steps. Such rules are not + enforced, and projects that do not follow them can generate build systems + with confusing and generator-specific behavior. + +* Step targets hold copies of the custom commands implementing their + steps that are separate from the copies in the primary target created + by :command:`ExternalProject_Add`, and the primary target does not + depend on the step targets. In parallel builds that drive the primary + target and step targets concurrently, multiple copies of the steps' + commands may run concurrently and race each other. + + Also, prior to policy :policy:`CMP0113`, the step targets generated + by :ref:`Makefile Generators` also contain all the custom commands + on which their step depends. This can lead to repeated execution of + those steps even in serial builds. + +In CMake 3.19 and above, the :module:`ExternalProject` module prefers +a revised design to address these problems: + +* Each step is classified as "independent" if it does not depend + on other targets named by the :command:`ExternalProject_Add` ``DEPENDS``. + The predefined steps are automatically classified by default: + + * The ``download``, ``update``, and ``patch`` steps are independent. + * The ``configure``, ``build``, ``test``, and ``install`` steps are not. + + For custom steps, the :command:`ExternalProject_Add_Step` command provies + an ``INDEPENDENT`` option to mark them as independent. It is an error to + mark a step as independent if it depends on other steps that are not. Note + that this use of the term "independent" refers only to independence from + external targets and is orthogonal to a step's dependencies on other steps. + +* Step targets created by the :command:`ExternalProject_Add` ``STEP_TARGETS`` + option or the :command:`ExternalProject_Add_Step` function are now + independent if and only if their steps are marked as independent. + The :command:`ExternalProject_Add` ``INDEPENDENT_STEP_TARGETS`` option + and :command:`ExternalProject_Add_StepTargets` ``NO_DEPENDS`` option + are no longer allowed. + +* Step targets, when created, are fully responsible for holding the + custom commands implementing their steps. The primary target created + by :command:`ExternalProject_Add` depends on the step targets, and the + step targets depend on each other. The target-level dependencies match + the file-level dependencies used by the custom commands for each step. + + When the :command:`ExternalProject_Add` ``UPDATE_DISCONNECTED`` or + ``TEST_EXCLUDE_FROM_MAIN`` option is used, or the + :command:`ExternalProject_Add_Step` ``EXCLUDE_FROM_MAIN`` option is used + for a custom step, some step targets may be created automatically. + These are needed to hold the steps commonly depended upon by the primary + target and the disconnected step targets. + +Policy ``CMP0114`` provides compatibility for projects that have not been +updated to expect the new behavior. The ``OLD`` behavior for this policy +is to use the above-documented behavior from 3.18 and below. The ``NEW`` +behavior for this policy is to use the above-documented behavior preferred +by 3.19 and above. + +This policy was introduced in CMake version 3.19. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. diff --git a/Help/prop_tgt/PCH_INSTANTIATE_TEMPLATES.rst b/Help/prop_tgt/PCH_INSTANTIATE_TEMPLATES.rst new file mode 100644 index 0000000..7c1af2a --- /dev/null +++ b/Help/prop_tgt/PCH_INSTANTIATE_TEMPLATES.rst @@ -0,0 +1,13 @@ +PCH_INSTANTIATE_TEMPLATES +------------------------- + +.. versionadded:: 3.19 + +When this property is set to true, the precompiled header compiler options +will contain a flag to instantiate templates during the generation of the PCH +if supported. This can significantly improve compile times. Supported in Clang +since version 11. + +This property is initialized by the value of the +:variable:`CMAKE_PCH_INSTANTIATE_TEMPLATES` variable if it is set when a target +is created. If that variable is not set, the property defaults to ``ON``. diff --git a/Help/release/3.16.rst b/Help/release/3.16.rst index f3fdb08..84d96cd 100644 --- a/Help/release/3.16.rst +++ b/Help/release/3.16.rst @@ -178,17 +178,15 @@ Modules Autogen ------- -* When using :prop_tgt:`AUTOMOC`, CMake now generates the ``-p`` path prefix +* When using :prop_tgt:`AUTOMOC`, the new :variable:`CMAKE_AUTOMOC_PATH_PREFIX` + variable or :prop_tgt:`AUTOMOC_PATH_PREFIX` target property may be enabled + to generate the ``-p`` path prefix option for ``moc``. This ensures that ``moc`` output files are identical on different build setups (given, that the headers compiled by ``moc`` are in an :command:`include directory <target_include_directories>`). Also it ensures that ``moc`` output files will compile correctly when the source and/or build directory is a symbolic link. - The ``moc`` path prefix generation behavior can be configured by setting - the new :variable:`CMAKE_AUTOMOC_PATH_PREFIX` variable and/or - :prop_tgt:`AUTOMOC_PATH_PREFIX` target property. - CTest ----- @@ -316,3 +314,11 @@ Changes made since CMake 3.16.0 include the following. :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` target properties. Previously they would be places in ``*_CFLAGS_OTHER`` variables and :prop_tgt:`INTERFACE_COMPILE_OPTIONS` target properties. + +3.16.9 +------ + +* The default value of :variable:`CMAKE_AUTOMOC_PATH_PREFIX` was changed to + ``OFF`` because this feature can break existing projects that have + identically named header files in different include directories. + This restores compatibility with behavior of CMake 3.15 and below. diff --git a/Help/release/3.17.rst b/Help/release/3.17.rst index b7c66d8..abd7463 100644 --- a/Help/release/3.17.rst +++ b/Help/release/3.17.rst @@ -346,3 +346,12 @@ Changes made since CMake 3.17.0 include the following. :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` target properties. Previously they would be places in ``*_CFLAGS_OTHER`` variables and :prop_tgt:`INTERFACE_COMPILE_OPTIONS` target properties. + +3.17.5 +------ + +* The default value of :variable:`CMAKE_AUTOMOC_PATH_PREFIX` was changed to + ``OFF`` because this feature can break existing projects that have + identically named header files in different include directories. + This restores compatibility with behavior of CMake 3.15 and below. + The default was also changed to ``OFF`` in 3.16.9. diff --git a/Help/release/3.18.rst b/Help/release/3.18.rst index 099e9b5..f97e4df 100644 --- a/Help/release/3.18.rst +++ b/Help/release/3.18.rst @@ -352,6 +352,7 @@ Changes made since CMake 3.18.0 include the following. ``OFF`` because this feature can break existing projects that have identically named header files in different include directories. This restores compatibility with behavior of CMake 3.15 and below. + The default was also changed to ``OFF`` in 3.16.9 and 3.17.5. * The :manual:`Compile Features <cmake-compile-features(7)>` functionality was updated for MSVC 19.27 as mentioned above (``c_restrict``). diff --git a/Help/release/dev/ExternalProject-steps-refinement.rst b/Help/release/dev/ExternalProject-steps-refinement.rst new file mode 100644 index 0000000..9762927 --- /dev/null +++ b/Help/release/dev/ExternalProject-steps-refinement.rst @@ -0,0 +1,5 @@ +ExternalProject-steps-refinement +-------------------------------- + +* The :module:`ExternalProject` module handling of step target dependencies + has been revised. See policy :policy:`CMP0114`. diff --git a/Help/release/dev/PCH_INSTANTIATE_TEMPLATES.rst b/Help/release/dev/PCH_INSTANTIATE_TEMPLATES.rst new file mode 100644 index 0000000..0334204 --- /dev/null +++ b/Help/release/dev/PCH_INSTANTIATE_TEMPLATES.rst @@ -0,0 +1,7 @@ +PCH_INSTANTIATE_TEMPLATES +------------------------- + +* The :prop_tgt:`PCH_INSTANTIATE_TEMPLATES` target property was added to enable + template instantiation in the precompiled header. This is enabled by default + and offers a roughly 20% compile time improvement. Currently only supported + by Clang 11. diff --git a/Help/release/dev/clang-windows-system-includes.rst b/Help/release/dev/clang-windows-system-includes.rst new file mode 100644 index 0000000..d1a3be2 --- /dev/null +++ b/Help/release/dev/clang-windows-system-includes.rst @@ -0,0 +1,5 @@ +clang-windows-system-includes +----------------------------- + +* The ``Clang`` compiler gained support for handling system include directories + when running on Windows. diff --git a/Help/release/dev/cuda-clang-scattered-cross.rst b/Help/release/dev/cuda-clang-scattered-cross.rst new file mode 100644 index 0000000..7278dcb --- /dev/null +++ b/Help/release/dev/cuda-clang-scattered-cross.rst @@ -0,0 +1,5 @@ +cuda-clang-scattered-cross +-------------------------- + +* Scattered toolkit installations are now recognized when crosscompiling + ``CUDA`` using Clang. diff --git a/Help/variable/CMAKE_PCH_INSTANTIATE_TEMPLATES.rst b/Help/variable/CMAKE_PCH_INSTANTIATE_TEMPLATES.rst new file mode 100644 index 0000000..9867f17 --- /dev/null +++ b/Help/variable/CMAKE_PCH_INSTANTIATE_TEMPLATES.rst @@ -0,0 +1,7 @@ +CMAKE_PCH_INSTANTIATE_TEMPLATES +------------------------------- + +.. versionadded:: 3.19 + +This variable is used to initialize the :prop_tgt:`PCH_INSTANTIATE_TEMPLATES` +property of targets when they are created. |