Tutorial: Improve "MultiPackage" example

Rename to Step 12 and ensure that it follows Step 11
This commit is contained in:
Betsy McPhail
2020-01-08 12:36:47 -05:00
parent 3a510a47b0
commit 77b515f3eb
17 changed files with 95 additions and 50 deletions

View File

@@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.15)
# set the project name and version
project(Tutorial VERSION 1.0)
set(CMAKE_DEBUG_POSTFIX d)
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
@@ -37,6 +39,8 @@ add_subdirectory(MathFunctions)
# add the executable
add_executable(Tutorial tutorial.cxx)
set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
target_link_libraries(Tutorial PUBLIC MathFunctions)
# add the binary tree to the search path for include files

View File

@@ -1,4 +1,3 @@
include("release/CPackConfig.cmake")
set(CPACK_INSTALL_CMAKE_PROJECTS

View File

@@ -1,6 +1,5 @@
// A simple program that computes the square root of a number
#include <iostream>
#include <sstream>
#include <string>
#include "MathFunctions.h"
@@ -9,6 +8,7 @@
int main(int argc, char* argv[])
{
if (argc < 2) {
// report version
std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
<< Tutorial_VERSION_MINOR << std::endl;
std::cout << "Usage: " << argv[0] << " number" << std::endl;
@@ -18,8 +18,8 @@ int main(int argc, char* argv[])
// convert input to double
const double inputValue = std::stod(argv[1]);
// calculate square root
const double outputValue = mathfunctions::sqrt(inputValue);
std::cout << "The square root of " << inputValue << " is " << outputValue
<< std::endl;
return 0;

View File

@@ -1,11 +1,19 @@
cmake_minimum_required(VERSION 3.10)
cmake_minimum_required(VERSION 3.15)
# set the project name and version
project(Tutorial VERSION 1.0)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
add_library(tutorial_compiler_flags INTERFACE)
target_compile_features(tutorial_compiler_flags INTERFACE cxx_std_11)
# add compiler warning flags just when building this project via
# the BUILD_INTERFACE genex
set(gcc_like_cxx "$<COMPILE_LANG_AND_ID:CXX,ARMClang,AppleClang,Clang,GNU>")
set(msvc_cxx "$<COMPILE_LANG_AND_ID:CXX,MSVC>")
target_compile_options(tutorial_compiler_flags INTERFACE
"$<${gcc_like_cxx}:$<BUILD_INTERFACE:-Wall;-Wextra;-Wshadow;-Wformat=2;-Wunused>>"
"$<${msvc_cxx}:$<BUILD_INTERFACE:-W3>>"
)
# control where the static and shared libraries are built so that on windows
# we don't need to tinker with the path to run the executable

View File

@@ -0,0 +1,7 @@
set(CTEST_PROJECT_NAME "CMakeTutorial")
set(CTEST_NIGHTLY_START_TIME "00:00:00 EST")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "my.cdash.org")
set(CTEST_DROP_LOCATION "/submit.php?project=CMakeTutorial")
set(CTEST_DROP_SITE_CDASH TRUE)

View File

@@ -17,6 +17,7 @@ if(USE_MYMATH)
# first we add the executable that generates the table
add_executable(MakeTable MakeTable.cxx)
target_link_libraries(MakeTable tutorial_compiler_flags)
# add the command to generate the source code
add_custom_command(
@@ -41,19 +42,18 @@ if(USE_MYMATH)
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
)
target_link_libraries(SqrtLibrary PUBLIC tutorial_compiler_flags)
target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
endif()
target_link_libraries(MathFunctions PUBLIC tutorial_compiler_flags)
# define the symbol stating we are using the declspec(dllexport) when
# building on windows
target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
# setup the version numbering
set_property(TARGET MathFunctions PROPERTY VERSION "1.0.0")
set_property(TARGET MathFunctions PROPERTY SOVERSION "1")
# install rules
install(TARGETS MathFunctions
install(TARGETS MathFunctions tutorial_compiler_flags
DESTINATION lib
EXPORT MathFunctionsTargets)
install(FILES MathFunctions.h DESTINATION include)

View File

@@ -17,11 +17,10 @@ double mysqrt(double x)
// use the table to help find an initial value
double result = x;
if (x >= 1 && x < 10) {
std::cout << "Use the table to help find an initial value " << std::endl;
result = sqrtTable[static_cast<int>(x)];
}
// if we have both log and exp then use them
// do ten iterations
for (int i = 0; i < 10; ++i) {
if (result <= 0) {

View File

@@ -1,3 +1,3 @@
// the configured version number
// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

View File

@@ -8,6 +8,7 @@
int main(int argc, char* argv[])
{
if (argc < 2) {
// report version
std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
<< Tutorial_VERSION_MINOR << std::endl;
std::cout << "Usage: " << argv[0] << " number" << std::endl;
@@ -15,7 +16,7 @@ int main(int argc, char* argv[])
}
// convert input to double
double inputValue = std::stod(argv[1]);
const double inputValue = std::stod(argv[1]);
const double outputValue = mathfunctions::sqrt(inputValue);

View File

@@ -830,7 +830,7 @@ different ``INTERFACE`` locations when being used from within the build
directory and from an install / package. This means converting the
:command:`target_include_directories` call for MathFunctions to look like:
.. literalinclude:: Complete/MathFunctions/CMakeLists.txt
.. literalinclude:: Step12/MathFunctions/CMakeLists.txt
:language: cmake
:start-after: # to find MathFunctions.h, while we don't.
:end-before: # should we use our own math functions
@@ -844,12 +844,12 @@ that the CMake :command:`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:
.. literalinclude:: Complete/Config.cmake.in
.. literalinclude:: Step12/Config.cmake.in
Then, to properly configure and install that file, add the following to the
bottom of the top-level ``CMakeLists.txt``:
.. literalinclude:: Complete/CMakeLists.txt
.. literalinclude:: Step12/CMakeLists.txt
:language: cmake
:start-after: # install the configuration targets
:end-before: # generate the export
@@ -859,7 +859,7 @@ 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.txt``:
.. literalinclude:: Complete/CMakeLists.txt
.. literalinclude:: Step12/CMakeLists.txt
:language: cmake
:start-after: # needs to be after the install(TARGETS ) command
@@ -867,55 +867,81 @@ 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.
Import a CMake Project (Consumer)
=================================
Packaging Debug and Release (Step 12)
=====================================
This example shows how a project can find other CMake packages that
generate ``Config.cmake`` files.
**Note:** This example is valid for single-configuration generators and will
not work for multi-configuration generators (e.g. Visual Studio).
It also shows how to state a project's external dependencies when generating
a ``Config.cmake``.
By default, CMake's model is that a build directory only contains a single
configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. It is
possible, however, to setup CPack to bundle multiple build directories and
construct a package that contains multiple configurations of the same project.
Packaging Debug and Release (MultiPackage)
==========================================
First, we want to ensure that the debug and release builds use different names
for the executables and libraries that will be installed. Let's use `d` as the
postfix for the debug executable and libraries.
By default CMake's model is that a build directory only contains a single
configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo.
Set :variable:`CMAKE_DEBUG_POSTFIX` near the beginning of the top-level
``CMakeLists.txt`` file:
But it is possible to setup CPack to bundle multiple build directories at the
same time to build a package that contains multiple configurations of the
same project.
.. literalinclude:: Complete/CMakeLists.txt
:language: cmake
:start-after: project(Tutorial VERSION 1.0)
:end-before: target_compile_features(tutorial_compiler_flags
First we need to construct a directory called ``multi_config``, which
will contain all the builds that we want to package together.
And the :prop_tgt:`DEBUG_POSTFIX` property on the tutorial executable:
Second create a ``debug`` and ``release`` directory underneath
``multi_config``. At the end you should have a layout that looks like:
.. literalinclude:: Complete/CMakeLists.txt
:language: cmake
:start-after: # add the executable
:end-before: # add the binary tree to the search path for include files
Let's also add version numbering to the MathFunctions library. In
``MathFunctions/CMakeLists.txt``, set the :prop_tgt:`VERSION` and
:prop_tgt:`SOVERSION` properties:
.. literalinclude:: Complete/MathFunctions/CMakeLists.txt
:language: cmake
:start-after: # setup the version numbering
:end-before: # install rules
From the ``Step12`` directory, create ``debug`` and ``release``
subbdirectories. The layout will look like:
.. code-block:: none
─ multi_config
── debug
└── release
- Step12
── debug
└── release
Now we need to setup debug and release builds, which would roughly entail
the following:
Now we need to setup debug and release builds. We can use
:variable:`CMAKE_BUILD_TYPE` to set the configuration type:
.. code-block:: console
cd debug
cmake -DCMAKE_BUILD_TYPE=Debug ../../MultiPackage/
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake --build .
cd ../release
cmake -DCMAKE_BUILD_TYPE=Release ../../MultiPackage/
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .
cd ..
Now that both the debug and release builds are complete, we can use a custom
configuration file to package both builds into a single release. In the
``Step12`` directory, create a file called ``MultiCPackConfig.cmake``. In this
file, first include the default configuration file that was created by the
:manual:`cmake <cmake(1)>` executable.
Now that both the debug and release builds are complete, we can use
a custom ``MultiCPackConfig.cmake`` file to package both builds into a single
release.
Next, use the ``CPACK_INSTALL_CMAKE_PROJECTS`` variable to specify which
projects to install. In this case, we want to install both debug and release.
.. literalinclude:: Complete/MultiCPackConfig.cmake
:language: cmake
From the ``Step12`` directory, run :manual:`cpack <cpack(1)>` specifying our
custom configuration file with the ``config`` option:
.. code-block:: console
cpack --config ../../MultiPackage/MultiCPackConfig.cmake
cpack --config MultiCPackConfig.cmake

View File

@@ -1595,6 +1595,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH
set(tutorial_build_options -DUSE_MYMATH:BOOL=OFF)
endif()
add_test(${tutorial_test_name} ${CMAKE_CTEST_COMMAND}
-C "Release"
--build-and-test
"${CMake_SOURCE_DIR}/Help/guide/tutorial/${step_name}"
${tutorial_build_dir}_Build
@@ -1606,11 +1607,11 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH
endfunction()
if(NOT CMake_TEST_EXTERNAL_CMAKE)
foreach(STP RANGE 2 11)
foreach(STP RANGE 2 12)
add_tutorial_test(Step${STP} TRUE)
endforeach()
add_tutorial_test(Complete TRUE)
foreach(STP RANGE 3 11)
foreach(STP RANGE 3 12)
add_tutorial_test(Step${STP} FALSE)
endforeach()
add_tutorial_test(Complete FALSE)