[Cmake-commits] CMake branch, master, updated. v3.13.3-1188-g9620cb9

Kitware Robot kwrobot at kitware.com
Tue Jan 29 09:23:04 EST 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, master has been updated
       via  9620cb935a49e7b4955f5b1d0ffa2e93b4327591 (commit)
       via  60c06620a690f0cbeeaa3fba762e19cd031669ca (commit)
       via  90ac5e6384735deb0ac523684010b2f4701d4f4d (commit)
       via  e7be5638a04ad6e47aafaed29139c6382fdea1cb (commit)
       via  5134e11ee4291c1eb53aa5014af2af75a2e33f3b (commit)
       via  66801f4d40227c46904ad54848bd1da959604cbf (commit)
       via  439fe2e253410305ff7018416ff5ff26aa851d53 (commit)
       via  186d9b083db0e3fc77d9d92821e3cf45e06271da (commit)
       via  2fc69ba0b33e8f5f1b6301f37fc1479fba420b93 (commit)
       via  0e2cdacf7b51c915acd1a2a9e58a080d2667b4cb (commit)
       via  f2ddedfa5802c8aece994bb643b5139212d87777 (commit)
       via  438651506a5417be70e71f54f4ed7add0c2604d3 (commit)
       via  b6a957c9696706a338cdeef63540bf8a4c42d22d (commit)
       via  638667efa2b0e5fff5c63bf936748a60b602ae90 (commit)
       via  3ca44029668c057fb208c5f153c4d398bee954cb (commit)
       via  cb6c233eccfbb600ec16716224062627df2ff2c0 (commit)
       via  1a45266cb544d73a7d7e46d6129ead1faf71fa85 (commit)
      from  fa7077e7411f4f85724deae3427acb29be729567 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9620cb935a49e7b4955f5b1d0ffa2e93b4327591
commit 9620cb935a49e7b4955f5b1d0ffa2e93b4327591
Merge: 60c0662 66801f4
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jan 29 14:19:31 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Tue Jan 29 09:19:39 2019 -0500

    Merge topic 'add_consistent_verbose_build_flag'
    
    66801f4d40 cmake: Add tests for verbose output to --build mode
    439fe2e253 cmake: Add options for verbose output to --build mode
    638667efa2 cmake: cmcmd.cxx fix "The arguments are" comments
    3ca4402966 ctest: Fix --build-and-test without --build-target on Xcode
    cb6c233ecc cmake: Add -hideShellScriptEnvironment xcodebuild option
    1a45266cb5 cmGlobalGenerator: Add a class that represent the build command
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !2708

diff --cc Source/cmGlobalUnixMakefileGenerator3.cxx
index 3ca2b17,6989b51..dac6ea6
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@@ -531,11 -532,11 +537,11 @@@ void cmGlobalUnixMakefileGenerator3::Ge
      if (fast) {
        tname += "/fast";
      }
 -    cmOutputConverter conv(mf->GetStateSnapshot());
      tname =
 -      conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname);
 +      mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained(
 +        mf->GetState()->GetBinaryDirectory(), tname);
      cmSystemTools::ConvertToOutputSlashes(tname);
-     makeCommand.push_back(std::move(tname));
+     makeCommand.add(std::move(tname));
    }
  }
  

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=60c06620a690f0cbeeaa3fba762e19cd031669ca
commit 60c06620a690f0cbeeaa3fba762e19cd031669ca
Merge: 90ac5e6 b6a957c
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jan 29 14:17:13 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Tue Jan 29 09:18:42 2019 -0500

    Merge topic 'cmoutputconverter-simplify'
    
    b6a957c969 cmOutputConverter: move ConvertToRelativePath to cmStateDirectory.
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !2831

diff --cc Source/cmGlobalUnixMakefileGenerator3.cxx
index 792adc0,9d176c3..3ca2b17
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@@ -363,9 -367,10 +367,10 @@@ void cmGlobalUnixMakefileGenerator3::Wr
      for (cmLocalGenerator* localGen : this->LocalGenerators) {
        lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
        tmpStr = lg->GetCurrentBinaryDirectory();
 -      tmpStr += cmake::GetCMakeFilesDirectory();
 +      tmpStr += "/CMakeFiles";
        tmpStr += "/CMakeDirectoryInformation.cmake";
-       cmakefileStream << "  \"" << lg->ConvertToRelativePath(binDir, tmpStr)
+       cmakefileStream << "  \""
+                       << lg->MaybeConvertToRelativePath(binDir, tmpStr)
                        << "\"\n";
      }
      cmakefileStream << "  )\n\n";

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=90ac5e6384735deb0ac523684010b2f4701d4f4d
commit 90ac5e6384735deb0ac523684010b2f4701d4f4d
Merge: e7be563 186d9b0
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jan 29 14:16:56 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Tue Jan 29 09:17:51 2019 -0500

    Merge topic 'message-stdstring'
    
    186d9b083d cmSystemTools::Message: Add overload accepting std::string
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !2869


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e7be5638a04ad6e47aafaed29139c6382fdea1cb
commit e7be5638a04ad6e47aafaed29139c6382fdea1cb
Merge: 5134e11 2fc69ba
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jan 29 14:16:51 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Tue Jan 29 09:16:58 2019 -0500

    Merge topic 'ftc-string'
    
    2fc69ba0b3 cmFileTimeComparison: use std::string arguments
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !2868


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=5134e11ee4291c1eb53aa5014af2af75a2e33f3b
commit 5134e11ee4291c1eb53aa5014af2af75a2e33f3b
Merge: fa7077e 0e2cdac
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Jan 29 14:15:31 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Tue Jan 29 09:15:44 2019 -0500

    Merge topic 'update-tutorial'
    
    0e2cdacf7b Tests: Update style of c++ code snippets in Tutorial directions
    f2ddedfa58 Tests: Update CMake tutorial
    438651506a Tests: Make ExternalProjectLocal independent of Tutorial directory
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !2731


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=66801f4d40227c46904ad54848bd1da959604cbf
commit 66801f4d40227c46904ad54848bd1da959604cbf
Author:     Robert Maynard <robert.maynard at kitware.com>
AuthorDate: Thu Jan 24 13:31:32 2019 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Jan 28 10:01:55 2019 -0500

    cmake: Add tests for verbose output to --build mode

diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index bf18efe..76dd997 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -123,7 +123,7 @@ if(NOT CMAKE_GENERATOR MATCHES "Visual Studio|Xcode")
   add_RunCMake_test(CMP0065)
 endif()
 if(CMAKE_GENERATOR MATCHES "Make")
-  add_RunCMake_test(Make)
+  add_RunCMake_test(Make -DMAKE_IS_GNU=${MAKE_IS_GNU})
 endif()
 if(CMAKE_GENERATOR STREQUAL "Ninja")
   set(Ninja_ARGS
diff --git a/Tests/RunCMake/Make/RunCMakeTest.cmake b/Tests/RunCMake/Make/RunCMakeTest.cmake
index 3b2b8f5..82db6b7 100644
--- a/Tests/RunCMake/Make/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Make/RunCMakeTest.cmake
@@ -16,5 +16,22 @@ run_TargetMessages(OFF)
 run_TargetMessages(VAR-ON -DCMAKE_TARGET_MESSAGES=ON)
 run_TargetMessages(VAR-OFF -DCMAKE_TARGET_MESSAGES=OFF)
 
+function(run_VerboseBuild)
+  run_cmake(VerboseBuild)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/VerboseBuild-build)
+  if(RunCMake_GENERATOR STREQUAL "Watcom WMake")
+    # wmake does not actually show the verbose output.
+    set(RunCMake-stdout-file VerboseBuild-build-watcom-stdout.txt)
+  endif()
+  run_cmake_command(VerboseBuild-build ${CMAKE_COMMAND} --build . -v --clean-first)
+  unset(RunCMake-stdout-file)
+  if(MAKE_IS_GNU)
+    set(RunCMake-stdout-file VerboseBuild-nowork-gnu-stdout.txt)
+  endif()
+  run_cmake_command(VerboseBuild-nowork ${CMAKE_COMMAND} --build . --verbose)
+endfunction()
+run_VerboseBuild()
+
 run_cmake(CustomCommandDepfile-ERROR)
 run_cmake(IncludeRegexSubdir)
diff --git a/Tests/RunCMake/Make/VerboseBuild-build-stdout.txt b/Tests/RunCMake/Make/VerboseBuild-build-stdout.txt
new file mode 100644
index 0000000..884bf95
--- /dev/null
+++ b/Tests/RunCMake/Make/VerboseBuild-build-stdout.txt
@@ -0,0 +1 @@
+.*DEFINE_FOR_VERBOSE_DETECTION.*hello.dir.*
diff --git a/Tests/RunCMake/Make/VerboseBuild-build-watcom-stdout.txt b/Tests/RunCMake/Make/VerboseBuild-build-watcom-stdout.txt
new file mode 100644
index 0000000..9c558e3
--- /dev/null
+++ b/Tests/RunCMake/Make/VerboseBuild-build-watcom-stdout.txt
@@ -0,0 +1 @@
+.
diff --git a/Tests/RunCMake/Make/VerboseBuild-nowork-gnu-stdout.txt b/Tests/RunCMake/Make/VerboseBuild-nowork-gnu-stdout.txt
new file mode 100644
index 0000000..3e65cd9
--- /dev/null
+++ b/Tests/RunCMake/Make/VerboseBuild-nowork-gnu-stdout.txt
@@ -0,0 +1 @@
+.*Nothing to be done for.*hello.*
diff --git a/Tests/RunCMake/Make/VerboseBuild.cmake b/Tests/RunCMake/Make/VerboseBuild.cmake
new file mode 100644
index 0000000..70a971d
--- /dev/null
+++ b/Tests/RunCMake/Make/VerboseBuild.cmake
@@ -0,0 +1,8 @@
+enable_language(C)
+
+# Make sure compile command is not hidden in a temp file.
+string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
+string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
+
+add_executable(hello hello.c)
+target_compile_definitions(hello PRIVATE "DEFINE_FOR_VERBOSE_DETECTION")
diff --git a/Tests/RunCMake/Make/hello.c b/Tests/RunCMake/Make/hello.c
new file mode 100644
index 0000000..aac8b4e
--- /dev/null
+++ b/Tests/RunCMake/Make/hello.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main(void)
+{
+  printf("Hello world!\n");
+  return 0;
+}
diff --git a/Tests/RunCMake/Ninja/RunCMakeTest.cmake b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
index 9e1e9a5..8fa650a 100644
--- a/Tests/RunCMake/Ninja/RunCMakeTest.cmake
+++ b/Tests/RunCMake/Ninja/RunCMakeTest.cmake
@@ -30,6 +30,15 @@ function(run_NoWorkToDo)
 endfunction()
 run_NoWorkToDo()
 
+function(run_VerboseBuild)
+  run_cmake(VerboseBuild)
+  set(RunCMake_TEST_NO_CLEAN 1)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/VerboseBuild-build)
+  run_cmake_command(VerboseBuild-build ${CMAKE_COMMAND} --build . -v --clean-first)
+  run_cmake_command(VerboseBuild-nowork ${CMAKE_COMMAND} --build . --verbose)
+endfunction()
+run_VerboseBuild()
+
 function(run_CMP0058 case)
   # Use a single build tree for a few tests without cleaning.
   set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0058-${case}-build)
diff --git a/Tests/RunCMake/Ninja/VerboseBuild-build-stdout.txt b/Tests/RunCMake/Ninja/VerboseBuild-build-stdout.txt
new file mode 100644
index 0000000..884bf95
--- /dev/null
+++ b/Tests/RunCMake/Ninja/VerboseBuild-build-stdout.txt
@@ -0,0 +1 @@
+.*DEFINE_FOR_VERBOSE_DETECTION.*hello.dir.*
diff --git a/Tests/RunCMake/Ninja/VerboseBuild-nowork-stdout.txt b/Tests/RunCMake/Ninja/VerboseBuild-nowork-stdout.txt
new file mode 100644
index 0000000..60a9228
--- /dev/null
+++ b/Tests/RunCMake/Ninja/VerboseBuild-nowork-stdout.txt
@@ -0,0 +1 @@
+^ninja: no work to do
diff --git a/Tests/RunCMake/Ninja/VerboseBuild.cmake b/Tests/RunCMake/Ninja/VerboseBuild.cmake
new file mode 100644
index 0000000..424e54e
--- /dev/null
+++ b/Tests/RunCMake/Ninja/VerboseBuild.cmake
@@ -0,0 +1,3 @@
+enable_language(C)
+add_executable(hello hello.c)
+target_compile_definitions(hello PRIVATE "DEFINE_FOR_VERBOSE_DETECTION")

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=439fe2e253410305ff7018416ff5ff26aa851d53
commit 439fe2e253410305ff7018416ff5ff26aa851d53
Author:     Florian Maushart <FloriansGit at online.ms>
AuthorDate: Thu Jan 24 13:31:18 2019 -0500
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Jan 28 09:44:50 2019 -0500

    cmake: Add options for verbose output to --build mode
    
    While we already support `VERBOSE` environment variable and
    `CMAKE_VERBOSE_MAKEFILE` cached variable, add `-v` and `--verbose`
    command line options to be able to activate verbose output directly from
    CMake's build tool mode command line.
    
    Also make `msbuild` honor the verbosity setting. `xcodebuild` still
    doesn't honor the verbosity setting as it will need a policy added
    and reworking of cmGlobalGenerator and cmsys to support
    multiple command invocation.

diff --git a/Help/envvar/CMAKE_NO_VERBOSE.rst b/Help/envvar/CMAKE_NO_VERBOSE.rst
new file mode 100644
index 0000000..149efbd
--- /dev/null
+++ b/Help/envvar/CMAKE_NO_VERBOSE.rst
@@ -0,0 +1,8 @@
+CMAKE_NO_VERBOSE
+----------------
+
+Disables verbose output from CMake when :envvar:`VERBOSE` environment variable
+is set.
+
+Only your build tool of choice will still print verbose output when you start
+to actually build your project.
diff --git a/Help/envvar/VERBOSE.rst b/Help/envvar/VERBOSE.rst
new file mode 100644
index 0000000..2d775a5
--- /dev/null
+++ b/Help/envvar/VERBOSE.rst
@@ -0,0 +1,10 @@
+VERBOSE
+-------
+
+Activates verbose output from CMake and your build tools of choice when
+you start to actually build your project.
+
+Note that any given value is ignored. It's just checked for existence.
+
+See also :ref:`Build Tool Mode <Build Tool Mode>` and
+:envvar:`CMAKE_NO_VERBOSE` environment variable
diff --git a/Help/manual/cmake-env-variables.7.rst b/Help/manual/cmake-env-variables.7.rst
index edf80f4..c433412 100644
--- a/Help/manual/cmake-env-variables.7.rst
+++ b/Help/manual/cmake-env-variables.7.rst
@@ -24,11 +24,13 @@ Environment Variables that Control the Build
    /envvar/CMAKE_BUILD_PARALLEL_LEVEL
    /envvar/CMAKE_CONFIG_TYPE
    /envvar/CMAKE_MSVCIDE_RUN_PATH
+   /envvar/CMAKE_NO_VERBOSE
    /envvar/CMAKE_OSX_ARCHITECTURES
    /envvar/DESTDIR
    /envvar/LDFLAGS
    /envvar/MACOSX_DEPLOYMENT_TARGET
    /envvar/PackageName_ROOT
+   /envvar/VERBOSE
 
 Environment Variables for Languages
 ===================================
diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst
index 915e0d4..77178b8 100644
--- a/Help/manual/cmake.1.rst
+++ b/Help/manual/cmake.1.rst
@@ -289,6 +289,14 @@ following options:
 ``--use-stderr``
   Ignored.  Behavior is default in CMake >= 3.0.
 
+``-v, --verbose``
+  Enable verbose output - if supported - including the build commands to be
+  executed.
+
+  This option can be omitted if :envvar:`VERBOSE` environment variable or
+  :variable:`CMAKE_VERBOSE_MAKEFILE` cached variable is set.
+
+
 ``--``
   Pass remaining options to the native tool.
 
diff --git a/Help/release/dev/cmake-build-verbose.rst b/Help/release/dev/cmake-build-verbose.rst
new file mode 100644
index 0000000..dee212e
--- /dev/null
+++ b/Help/release/dev/cmake-build-verbose.rst
@@ -0,0 +1,6 @@
+cmake-build-verbose
+-------------------
+
+* The :manual:`cmake(1)` :ref:`Build Tool Mode` (``cmake --build``) gained
+  ``--verbose`` and ``-v`` options to specify verbose build output. Some
+  generators such as Xcode don't support this option currently.
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 9fc60e7..6989b51 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -493,7 +493,7 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
   GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& /*projectName*/, const std::string& /*projectDir*/,
   const std::string& targetName, const std::string& /*config*/, bool fast,
-  int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
+  int jobs, bool verbose, std::vector<std::string> const& makeOptions)
 {
   std::unique_ptr<cmMakefile> mfu;
   cmMakefile* mf;
@@ -510,6 +510,13 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
     mf = mfu.get();
   }
 
+  // Make it possible to set verbosity also from command line
+  if (verbose) {
+    makeCommand.add(cmSystemTools::GetCMakeCommand());
+    makeCommand.add("-E");
+    makeCommand.add("env");
+    makeCommand.add("VERBOSE=1");
+  }
   makeCommand.add(this->SelectMakeProgram(makeProgram));
 
   if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 051ef18..60b2258 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -961,6 +961,10 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
     makeCommand.add("/p:CL_MPCount=1");
   }
 
+  // Respect the verbosity: 'n' normal will show build commands
+  //                        'm' minimal only the build step's title
+  makeCommand.add(std::string("/v:") + ((verbose) ? "n" : "m"));
+
   makeCommand.add(makeOptions.begin(), makeOptions.end());
 }
 
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 914c3b0..411ba3a 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2539,7 +2539,8 @@ cmMessenger* cmake::GetMessenger() const
 
 int cmake::Build(int jobs, const std::string& dir, const std::string& target,
                  const std::string& config,
-                 const std::vector<std::string>& nativeOptions, bool clean)
+                 const std::vector<std::string>& nativeOptions, bool clean,
+                 bool verbose)
 {
 
   this->SetHomeDirectory("");
@@ -2592,11 +2593,11 @@ int cmake::Build(int jobs, const std::string& dir, const std::string& target,
     return 1;
   }
   projName = cachedProjectName;
-  bool verbose = false;
+
   const char* cachedVerbose =
     this->State->GetCacheEntryValue("CMAKE_VERBOSE_MAKEFILE");
-  if (cachedVerbose) {
-    verbose = cmSystemTools::IsOn(cachedVerbose);
+  if (cmSystemTools::IsOn(cachedVerbose)) {
+    verbose = true;
   }
 
 #ifdef CMAKE_HAVE_VS_GENERATORS
diff --git a/Source/cmake.h b/Source/cmake.h
index 9478ad0e..7ec1b64 100644
--- a/Source/cmake.h
+++ b/Source/cmake.h
@@ -430,7 +430,8 @@ public:
   ///! run the --build option
   int Build(int jobs, const std::string& dir, const std::string& target,
             const std::string& config,
-            const std::vector<std::string>& nativeOptions, bool clean);
+            const std::vector<std::string>& nativeOptions, bool clean,
+            bool verbose);
 
   ///! run the --open option
   bool Open(const std::string& dir, bool dryRun);
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 0c25498..0ec2552 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -68,6 +68,8 @@ static const char* cmDocumentationUsageNote[][2] = {
     "  --clean-first  = Build target 'clean' first, then build.\n"            \
     "                   (To clean only, use --target 'clean'.)\n"             \
     "  --use-stderr   = Ignored.  Behavior is default in CMake >= 3.0.\n"     \
+    "  -v --verbose   = Enable verbose output - if supported - including\n"   \
+    "                   the build commands to be executed. \n"                \
     "  --             = Pass remaining options to the native tool.\n"
 
 static const char* cmDocumentationOptions[][2] = {
@@ -395,6 +397,7 @@ static int do_build(int ac, char const* const* av)
   std::string dir;
   std::vector<std::string> nativeOptions;
   bool clean = false;
+  bool verbose = cmSystemTools::HasEnv("VERBOSE");
   bool hasTarget = false;
 
   enum Doing
@@ -435,6 +438,10 @@ static int do_build(int ac, char const* const* av)
     } else if (strcmp(av[i], "--clean-first") == 0) {
       clean = true;
       doing = DoingNone;
+    } else if ((strcmp(av[i], "--verbose") == 0) ||
+               (strcmp(av[i], "-v") == 0)) {
+      verbose = true;
+      doing = DoingNone;
     } else if (strcmp(av[i], "--use-stderr") == 0) {
       /* tolerate legacy option */
     } else if (strcmp(av[i], "--") == 0) {
@@ -493,7 +500,7 @@ static int do_build(int ac, char const* const* av)
   cmake cm(cmake::RoleInternal, cmState::Unknown);
   cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm);
   cm.SetProgressCallback(cmakemainProgressCallback, &cm);
-  return cm.Build(jobs, dir, target, config, nativeOptions, clean);
+  return cm.Build(jobs, dir, target, config, nativeOptions, clean, verbose);
 #endif
 }
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=186d9b083db0e3fc77d9d92821e3cf45e06271da
commit 186d9b083db0e3fc77d9d92821e3cf45e06271da
Author:     Vitaly Stakhovsky <vvs31415 at gitlab.org>
AuthorDate: Mon Jan 28 09:35:51 2019 -0500
Commit:     Vitaly Stakhovsky <vvs31415 at gitlab.org>
CommitDate: Mon Jan 28 09:35:51 2019 -0500

    cmSystemTools::Message: Add overload accepting std::string

diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx
index ecfcfb9..ee5feee 100644
--- a/Source/cmCallVisualStudioMacro.cxx
+++ b/Source/cmCallVisualStudioMacro.cxx
@@ -46,7 +46,7 @@ static bool LogErrorsAsMessages;
                      << std::endl;                                            \
         _hresult_oss.flags(std::ios::dec);                                    \
         _hresult_oss << __FILE__ << "(" << __LINE__ << ")";                   \
-        cmSystemTools::Message(_hresult_oss.str().c_str());                   \
+        cmSystemTools::Message(_hresult_oss.str());                           \
       }                                                                       \
     }
 
@@ -446,7 +446,7 @@ int cmCallVisualStudioMacro::CallMacro(const std::string& slnFile,
   if (err && LogErrorsAsMessages) {
     std::ostringstream oss;
     oss << "cmCallVisualStudioMacro::CallMacro failed, err = " << err;
-    cmSystemTools::Message(oss.str().c_str());
+    cmSystemTools::Message(oss.str());
   }
 
   return 0;
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index c68bb21..3d61665 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -1282,7 +1282,7 @@ void cmComputeLinkInformation::DropDirectoryItem(std::string const& item)
     << "\" requests linking to directory \"" << item << "\".  "
     << "Targets may link only to libraries.  "
     << "CMake is dropping the item.";
-  cmSystemTools::Message(e.str().c_str());
+  cmSystemTools::Message(e.str());
 }
 
 void cmComputeLinkInformation::ComputeFrameworkInfo()
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index effb446..4b14d26 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -117,7 +117,7 @@ void cmFLTKWrapUICommand::FinalPass()
     msg += ".  The problem was found while processing the source directory: ";
     msg += this->Makefile->GetCurrentSourceDirectory();
     msg += ".  This FLTK_WRAP_UI call will be ignored.";
-    cmSystemTools::Message(msg.c_str(), "Warning");
+    cmSystemTools::Message(msg, "Warning");
     return;
   }
 }
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 19605e4..c253937 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -67,7 +67,7 @@ void cmGhsMultiTargetGenerator::Generate()
     case cmStateEnums::SHARED_LIBRARY: {
       std::string msg = "add_library(<name> SHARED ...) not supported: ";
       msg += this->Name;
-      cmSystemTools::Message(msg.c_str());
+      cmSystemTools::Message(msg);
       return;
     }
     case cmStateEnums::OBJECT_LIBRARY: {
@@ -84,13 +84,13 @@ void cmGhsMultiTargetGenerator::Generate()
     case cmStateEnums::MODULE_LIBRARY: {
       std::string msg = "add_library(<name> MODULE ...) not supported: ";
       msg += this->Name;
-      cmSystemTools::Message(msg.c_str());
+      cmSystemTools::Message(msg);
       return;
     }
     case cmStateEnums::UTILITY: {
       std::string msg = "add_custom_target(<name> ...) not supported: ";
       msg += this->Name;
-      cmSystemTools::Message(msg.c_str());
+      cmSystemTools::Message(msg);
       return;
     }
     default:
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 04af013..58d0971 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1060,7 +1060,7 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
   if (preference < 0) {
     std::string msg = linkerPrefVar;
     msg += " is negative, adjusting it to 0";
-    cmSystemTools::Message(msg.c_str(), "Warning");
+    cmSystemTools::Message(msg, "Warning");
     preference = 0;
   }
 
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 7963c8a..bb8b772 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -70,7 +70,7 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
       "Green Hills MULTI: -T <toolset> not specified; defaulting to \"";
     message += tsp;
     message += "\"";
-    cmSystemTools::Message(message.c_str());
+    cmSystemTools::Message(message);
 
     /* store the full toolset for later use
      * -- already done if -T<toolset> was specified
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index cbea3dd..e3dd2f9 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -268,7 +268,7 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
         std::ostringstream oss;
         oss << "Could not copy from: " << src << std::endl;
         oss << "                 to: " << dst << std::endl;
-        cmSystemTools::Message(oss.str().c_str(), "Warning");
+        cmSystemTools::Message(oss.str(), "Warning");
       }
     }
 
@@ -783,7 +783,7 @@ void RegisterVisualStudioMacros(const std::string& macrosFile,
           << "CMake needs to register Visual Studio macros when its macros"
           << " file is updated or when it detects that its current macros file"
           << " is no longer registered with Visual Studio." << std::endl;
-      cmSystemTools::Message(oss.str().c_str(), "Warning");
+      cmSystemTools::Message(oss.str(), "Warning");
 
       // Count them again now that the warning is over. In the case of a GUI
       // warning, the user may have gone to close Visual Studio and then come
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index c6f4064..8ef6441 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -712,7 +712,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
           std::ostringstream e;
           e << "INSTALL TARGETS - target " << target.GetName() << " has "
             << "RESOURCE files but no RESOURCE DESTINATION.";
-          cmSystemTools::Message(e.str().c_str(), "Warning");
+          cmSystemTools::Message(e.str(), "Warning");
         }
       }
     }
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index d1d4316..3497814 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -51,7 +51,7 @@ void cmInstallTargetGenerator::GenerateScript(std::ostream& os)
         << "\" has EXCLUDE_FROM_ALL set and will not be built by default "
         << "but an install rule has been provided for it.  CMake does "
         << "not define behavior for this case.";
-    cmSystemTools::Message(msg.str().c_str(), "Warning");
+    cmSystemTools::Message(msg.str(), "Warning");
   }
 
   // Perform the main install script generation.
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 62aff99..5b02823 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -2752,7 +2752,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const
         << "CMake is dropping a preprocessor definition: " << define << "\n"
         << "Consider defining the macro in a (configured) header file.\n";
       /* clang-format on */
-      cmSystemTools::Message(e.str().c_str());
+      cmSystemTools::Message(e.str());
       return false;
     }
   }
@@ -2767,7 +2767,7 @@ bool cmLocalGenerator::CheckDefinition(std::string const& define) const
       << "CMake is dropping a preprocessor definition: " << define << "\n"
       << "Consider defining the macro in a (configured) header file.\n";
     /* clang-format on */
-    cmSystemTools::Message(e.str().c_str());
+    cmSystemTools::Message(e.str());
     return false;
   }
 
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index b59a733..9bd3b01 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -322,7 +322,7 @@ void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const
     msg << " ";
   }
   msg << ")";
-  cmSystemTools::Message(msg.str().c_str());
+  cmSystemTools::Message(msg.str());
 }
 
 // Helper class to make sure the call stack is valid.
@@ -1622,7 +1622,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
   if (this->GetCMakeInstance()->GetDebugOutput()) {
     std::string msg = "   Entering             ";
     msg += currentStart;
-    cmSystemTools::Message(msg.c_str());
+    cmSystemTools::Message(msg);
   }
 
   std::string const currentStartFile = currentStart + "/CMakeLists.txt";
@@ -1665,7 +1665,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
   if (this->GetCMakeInstance()->GetDebugOutput()) {
     std::string msg = "   Returning to         ";
     msg += this->GetCurrentSourceDirectory();
-    cmSystemTools::Message(msg.c_str());
+    cmSystemTools::Message(msg);
   }
 }
 
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 0fad233..af34169 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -403,7 +403,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
     err << "Warning: Source file \"" << source.GetFullPath()
         << "\" is listed multiple times for target \""
         << this->GeneratorTarget->GetName() << "\".";
-    cmSystemTools::Message(err.str().c_str(), "Warning");
+    cmSystemTools::Message(err.str(), "Warning");
     return;
   }
 
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index 4c26c66..95f5fcb 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -70,7 +70,7 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args,
     if (status) {
       this->Makefile->DisplayStatus(message.c_str(), -1);
     } else {
-      cmSystemTools::Message(message.c_str());
+      cmSystemTools::Message(message);
     }
   }
   if (fatal) {
diff --git a/Source/cmMessenger.cxx b/Source/cmMessenger.cxx
index 3d788f6..1d790e2 100644
--- a/Source/cmMessenger.cxx
+++ b/Source/cmMessenger.cxx
@@ -124,9 +124,9 @@ void displayMessage(MessageType t, std::ostringstream& msg)
   if (t == MessageType::FATAL_ERROR || t == MessageType::INTERNAL_ERROR ||
       t == MessageType::DEPRECATION_ERROR || t == MessageType::AUTHOR_ERROR) {
     cmSystemTools::SetErrorOccured();
-    cmSystemTools::Message(msg.str().c_str(), "Error");
+    cmSystemTools::Message(msg.str(), "Error");
   } else {
-    cmSystemTools::Message(msg.str().c_str(), "Warning");
+    cmSystemTools::Message(msg.str(), "Warning");
   }
 }
 
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index a16460f..f7de3aa 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -267,14 +267,14 @@ void cmSystemTools::Error(const char* m1, const char* m2, const char* m3,
     message += m4;
   }
   cmSystemTools::s_ErrorOccured = true;
-  cmSystemTools::Message(message.c_str(), "Error");
+  cmSystemTools::Message(message, "Error");
 }
 
 void cmSystemTools::Error(const std::string& m)
 {
   std::string message = "CMake Error: " + m;
   cmSystemTools::s_ErrorOccured = true;
-  cmSystemTools::Message(message.c_str(), "Error");
+  cmSystemTools::Message(message, "Error");
 }
 
 void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData)
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index b30e4f7..b1d5751 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -76,6 +76,10 @@ public:
    * Display a message.
    */
   static void Message(const char* m, const char* title = nullptr);
+  static void Message(const std::string& m, const char* title = nullptr)
+  {
+    Message(m.c_str(), title);
+  }
 
   typedef void (*OutputCallback)(const char*, size_t length, void*);
 
diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx
index f374626..231bca4 100644
--- a/Source/cmUtilitySourceCommand.cxx
+++ b/Source/cmUtilitySourceCommand.cxx
@@ -40,7 +40,7 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
       msg += ". If your intention is to run this executable, you need to "
              "preload the cache with the full path to a version of that "
              "program, which runs on this build machine.";
-      cmSystemTools::Message(msg.c_str(), "Warning");
+      cmSystemTools::Message(msg, "Warning");
     }
   } else {
     cmState* state = this->Makefile->GetState();
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 744b8fc..cf4dfc4 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -1252,7 +1252,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
   for (SaveCacheEntry const& i : saved) {
     this->AddCacheEntry(i.key, i.value.c_str(), i.help.c_str(), i.type);
   }
-  cmSystemTools::Message(warning.str().c_str());
+  cmSystemTools::Message(warning.str());
   // avoid reconfigure if there were errors
   if (!cmSystemTools::GetErrorOccuredFlag()) {
     // re-run configure

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2fc69ba0b33e8f5f1b6301f37fc1479fba420b93
commit 2fc69ba0b33e8f5f1b6301f37fc1479fba420b93
Author:     Vitaly Stakhovsky <vvs31415 at gitlab.org>
AuthorDate: Mon Jan 28 09:00:28 2019 -0500
Commit:     Vitaly Stakhovsky <vvs31415 at gitlab.org>
CommitDate: Mon Jan 28 09:09:59 2019 -0500

    cmFileTimeComparison: use std::string arguments

diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index d07bd21..948547f 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -513,8 +513,7 @@ public:
     // Order files by modification time.  Use lexicographic order
     // among files with the same time.
     int result;
-    if (this->FTC->FileTimeCompare(l.c_str(), r.c_str(), &result) &&
-        result != 0) {
+    if (this->FTC->FileTimeCompare(l, r, &result) && result != 0) {
       return result < 0;
     }
     return l < r;
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index 976ba57..7d1d316 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -156,8 +156,8 @@ bool cmDepends::CheckDependencies(
     // * if the depender does not exist, but the dependee is newer than the
     //   depends file
     bool regenerate = false;
-    const char* dependee = this->Dependee + 1;
-    const char* depender = this->Depender;
+    const std::string dependee(this->Dependee + 1);
+    const std::string depender(this->Depender);
     if (currentDependencies != nullptr) {
       currentDependencies->push_back(dependee);
     }
@@ -195,8 +195,8 @@ bool cmDepends::CheckDependencies(
         // The dependee exists, but the depender doesn't. Regenerate if the
         // internalDepends file is older than the dependee.
         int result = 0;
-        if ((!this->FileComparison->FileTimeCompare(
-               internalDependsFileName.c_str(), dependee, &result) ||
+        if ((!this->FileComparison->FileTimeCompare(internalDependsFileName,
+                                                    dependee, &result) ||
              result < 0)) {
           // The depends-file is older than the dependee.
           regenerate = true;
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index f6ac4f2..ea24f09 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -268,8 +268,7 @@ void cmDependsC::ReadCacheFile()
       haveFileName = true;
       int newer = 0;
       cmFileTimeComparison comp;
-      bool res = comp.FileTimeCompare(this->CacheFileName.c_str(),
-                                      line.c_str(), &newer);
+      bool res = comp.FileTimeCompare(this->CacheFileName, line, &newer);
 
       if (res && newer == 1) // cache is newer than the parsed file
       {
diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx
index 8f6993d..8b3911e 100644
--- a/Source/cmFileTimeComparison.cxx
+++ b/Source/cmFileTimeComparison.cxx
@@ -21,9 +21,10 @@ class cmFileTimeComparisonInternal
 {
 public:
   // Internal comparison method.
-  inline bool FileTimeCompare(const char* f1, const char* f2, int* result);
+  inline bool FileTimeCompare(const std::string& f1, const std::string& f2,
+                              int* result);
 
-  bool FileTimesDiffer(const char* f1, const char* f2);
+  bool FileTimesDiffer(const std::string& f1, const std::string& f2);
 
 private:
   typedef std::unordered_map<std::string, cmFileTimeComparison_Type>
@@ -31,14 +32,14 @@ private:
   FileStatsMap Files;
 
   // Internal methods to lookup and compare modification times.
-  inline bool Stat(const char* fname, cmFileTimeComparison_Type* st);
+  inline bool Stat(const std::string& fname, cmFileTimeComparison_Type* st);
   inline int Compare(cmFileTimeComparison_Type* st1,
                      cmFileTimeComparison_Type* st2);
   inline bool TimesDiffer(cmFileTimeComparison_Type* st1,
                           cmFileTimeComparison_Type* st2);
 };
 
-bool cmFileTimeComparisonInternal::Stat(const char* fname,
+bool cmFileTimeComparisonInternal::Stat(const std::string& fname,
                                         cmFileTimeComparison_Type* st)
 {
   // Use the stored time if available.
@@ -51,7 +52,7 @@ bool cmFileTimeComparisonInternal::Stat(const char* fname,
 
 #if !defined(_WIN32) || defined(__CYGWIN__)
   // POSIX version.  Use the stat function.
-  int res = ::stat(fname, st);
+  int res = ::stat(fname.c_str(), st);
   if (res != 0) {
     return false;
   }
@@ -83,13 +84,14 @@ cmFileTimeComparison::~cmFileTimeComparison()
   delete this->Internals;
 }
 
-bool cmFileTimeComparison::FileTimeCompare(const char* f1, const char* f2,
-                                           int* result)
+bool cmFileTimeComparison::FileTimeCompare(const std::string& f1,
+                                           const std::string& f2, int* result)
 {
   return this->Internals->FileTimeCompare(f1, f2, result);
 }
 
-bool cmFileTimeComparison::FileTimesDiffer(const char* f1, const char* f2)
+bool cmFileTimeComparison::FileTimesDiffer(const std::string& f1,
+                                           const std::string& f2)
 {
   return this->Internals->FileTimesDiffer(f1, f2);
 }
@@ -199,8 +201,9 @@ bool cmFileTimeComparisonInternal::TimesDiffer(cmFileTimeComparison_Type* s1,
 #endif
 }
 
-bool cmFileTimeComparisonInternal::FileTimeCompare(const char* f1,
-                                                   const char* f2, int* result)
+bool cmFileTimeComparisonInternal::FileTimeCompare(const std::string& f1,
+                                                   const std::string& f2,
+                                                   int* result)
 {
   // Get the modification time for each file.
   cmFileTimeComparison_Type s1;
@@ -215,8 +218,8 @@ bool cmFileTimeComparisonInternal::FileTimeCompare(const char* f1,
   return false;
 }
 
-bool cmFileTimeComparisonInternal::FileTimesDiffer(const char* f1,
-                                                   const char* f2)
+bool cmFileTimeComparisonInternal::FileTimesDiffer(const std::string& f1,
+                                                   const std::string& f2)
 {
   // Get the modification time for each file.
   cmFileTimeComparison_Type s1;
diff --git a/Source/cmFileTimeComparison.h b/Source/cmFileTimeComparison.h
index 114989b..5f74e34 100644
--- a/Source/cmFileTimeComparison.h
+++ b/Source/cmFileTimeComparison.h
@@ -5,6 +5,8 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <string>
+
 class cmFileTimeComparisonInternal;
 
 /** \class cmFileTimeComparison
@@ -24,13 +26,14 @@ public:
    *  When true is returned, result has -1, 0, +1 for
    *  f1 older, same, or newer than f2.
    */
-  bool FileTimeCompare(const char* f1, const char* f2, int* result);
+  bool FileTimeCompare(const std::string& f1, const std::string& f2,
+                       int* result);
 
   /**
    *  Compare file modification times.  Return true unless both files
    *  exist and have modification times less than 1 second apart.
    */
-  bool FileTimesDiffer(const char* f1, const char* f2);
+  bool FileTimesDiffer(const std::string& f1, const std::string& f2);
 
 protected:
   cmFileTimeComparisonInternal* Internals;
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 7cb98b9..173ac7a 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1278,8 +1278,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
     this->GlobalGenerator->GetCMakeInstance()->GetFileComparison();
   {
     int result;
-    if (!ftc->FileTimeCompare(internalDependFile.c_str(), tgtInfo.c_str(),
-                              &result) ||
+    if (!ftc->FileTimeCompare(internalDependFile, tgtInfo, &result) ||
         result < 0) {
       if (verbose) {
         std::ostringstream msg;
@@ -1299,8 +1298,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
   dirInfoFile += "/CMakeDirectoryInformation.cmake";
   {
     int result;
-    if (!ftc->FileTimeCompare(internalDependFile.c_str(), dirInfoFile.c_str(),
-                              &result) ||
+    if (!ftc->FileTimeCompare(internalDependFile, dirInfoFile, &result) ||
         result < 0) {
       if (verbose) {
         std::ostringstream msg;
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 744b8fc..10cbb6e 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -2146,8 +2146,7 @@ int cmake::CheckBuildSystem()
   std::string dep_newest = *dep++;
   for (; dep != depends.end(); ++dep) {
     int result = 0;
-    if (this->FileComparison->FileTimeCompare(dep_newest.c_str(), dep->c_str(),
-                                              &result)) {
+    if (this->FileComparison->FileTimeCompare(dep_newest, *dep, &result)) {
       if (result < 0) {
         dep_newest = *dep;
       }
@@ -2166,8 +2165,7 @@ int cmake::CheckBuildSystem()
   std::string out_oldest = *out++;
   for (; out != outputs.end(); ++out) {
     int result = 0;
-    if (this->FileComparison->FileTimeCompare(out_oldest.c_str(), out->c_str(),
-                                              &result)) {
+    if (this->FileComparison->FileTimeCompare(out_oldest, *out, &result)) {
       if (result > 0) {
         out_oldest = *out;
       }
@@ -2184,8 +2182,8 @@ int cmake::CheckBuildSystem()
   // If any output is older than any dependency then rerun.
   {
     int result = 0;
-    if (!this->FileComparison->FileTimeCompare(out_oldest.c_str(),
-                                               dep_newest.c_str(), &result) ||
+    if (!this->FileComparison->FileTimeCompare(out_oldest, dep_newest,
+                                               &result) ||
         result < 0) {
       if (verbose) {
         std::ostringstream msg;
@@ -2446,8 +2444,7 @@ static bool cmakeCheckStampFile(const std::string& stampName, bool verbose)
   while (cmSystemTools::GetLineFromStream(fin, dep)) {
     int result;
     if (!dep.empty() && dep[0] != '#' &&
-        (!ftc.FileTimeCompare(stampDepends.c_str(), dep.c_str(), &result) ||
-         result < 0)) {
+        (!ftc.FileTimeCompare(stampDepends, dep, &result) || result < 0)) {
       // The stamp depends file is older than this dependency.  The
       // build system is really out of date.
       std::cout << "CMake is re-running because " << stampName

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0e2cdacf7b51c915acd1a2a9e58a080d2667b4cb
commit 0e2cdacf7b51c915acd1a2a9e58a080d2667b4cb
Author:     Zack Galbreath <zack.galbreath at kitware.com>
AuthorDate: Fri Jan 11 11:31:12 2019 -0500
Commit:     Betsy McPhail <betsy.mcphail at kitware.com>
CommitDate: Sun Jan 27 16:03:00 2019 -0500

    Tests: Update style of c++ code snippets in Tutorial directions

diff --git a/Tests/Tutorial/Step1/directions.txt b/Tests/Tutorial/Step1/directions.txt
index 10f2583..827d775 100644
--- a/Tests/Tutorial/Step1/directions.txt
+++ b/Tests/Tutorial/Step1/directions.txt
@@ -52,14 +52,13 @@ make use of the version numbers. The resulting source code is listed below.
 
   int main (int argc, char *argv[])
   {
-    if (argc < 2)
-      {
+    if (argc < 2) {
       std::cout << argv[0] << " Version "
                 << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR
                 << std::endl;
       std::cout << "Usage: " << argv[0] << " number" << std::endl;
       return 1;
-      }
+    }
 
     double inputValue = atof(argv[1]);
 
diff --git a/Tests/Tutorial/Step6/directions.txt b/Tests/Tutorial/Step6/directions.txt
index d3e7b05..42b9f06 100644
--- a/Tests/Tutorial/Step6/directions.txt
+++ b/Tests/Tutorial/Step6/directions.txt
@@ -16,24 +16,21 @@ MathFunctions subdirectory a new source file named MakeTable.cxx will do just th
   int main (int argc, char *argv[])
   {
     // make sure we have enough arguments
-    if (argc < 2)
-      {
+    if (argc < 2) {
       return 1;
-      }
+    }
 
     std::ofstream fout(argv[1],std::ios_base::out);
     const bool fileOpen = fout.is_open();
-    if(fileOpen)
-      {
+    if(fileOpen) {
       fout << "double sqrtTable[] = {" << std::endl;
-      for (int i = 0; i < 10; ++i)
-        {
+      for (int i = 0; i < 10; ++i) {
         fout << sqrt(static_cast<double>(i)) << "," << std::endl;
-        }
+      }
       // close the table with a zero
       fout << "0};" << std::endl;
       fout.close();
-      }
+    }
     return fileOpen ? 0 : 1; // return 0 if wrote the file
   }
 
@@ -81,29 +78,25 @@ found and included by mysqrt.cxx.
 Now let's use the generated table. First, modify mysqrt.cxx to include Table.h.
 Next, we can rewrite the mysqrt function to use the table:
 
-  if (x <= 0)
-      {
-      return 0;
-      }
+  if (x <= 0) {
+    return 0;
+  }
 
   // use the table to help find an initial value
   double result = x;
-  if (x >= 1 && x < 10)
-    {
+  if (x >= 1 && x < 10) {
     result = sqrtTable[static_cast<int>(x)];
-    }
+  }
 
   // do ten iterations
-  for (int i = 0; i < 10; ++i)
-    {
-    if (result <= 0)
-      {
+  for (int i = 0; i < 10; ++i) {
+    if (result <= 0) {
       result = 0.1;
-      }
+    }
     double delta = x - (result*result);
     result = result + 0.5*delta/result;
     std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
-    }
+  }
 
 Run cmake or cmake-gui to configure the project and then build it with your
 chosen build tool. When this project is built it will first build the MakeTable

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f2ddedfa5802c8aece994bb643b5139212d87777
commit f2ddedfa5802c8aece994bb643b5139212d87777
Author:     Betsy McPhail <betsy.mcphail at kitware.com>
AuthorDate: Sun Jan 20 11:28:39 2019 -0500
Commit:     Betsy McPhail <betsy.mcphail at kitware.com>
CommitDate: Sun Jan 27 16:03:00 2019 -0500

    Tests: Update CMake tutorial
    
    Latest material from data.kitware.com -> Collections -> Courses -> CMake.

diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 0c6eabc..ed98d97 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1704,18 +1704,37 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     DEPENDS ExternalProjectUpdateSetup )
 
   # do each of the tutorial steps
-  foreach(STP RANGE 1 7)
-    add_test(TutorialStep${STP} ${CMAKE_CTEST_COMMAND}
+  function(add_tutorial_test step_name use_mymath)
+    set(tutorial_test_name Tutorial${step_name})
+    set(tutorial_build_dir "${CMake_BINARY_DIR}/Tests/Tutorial/${step_name}")
+    if (use_mymath)
+      set(tutorial_build_options "")
+    else()
+      set(tutorial_test_name ${tutorial_test_name}_MYMATH)
+      set(tutorial_build_dir "${tutorial_build_dir}_MYMATH")
+      set(tutorial_build_options -DUSE_MYMATH:BOOL=OFF)
+    endif()
+    add_test(${tutorial_test_name} ${CMAKE_CTEST_COMMAND}
       --build-and-test
-      "${CMake_SOURCE_DIR}/Tests/Tutorial/Step${STP}"
-      "${CMake_BINARY_DIR}/Tests/Tutorial/Step${STP}"
-      --build-two-config
+      "${CMake_SOURCE_DIR}/Tests/Tutorial/${step_name}"
+      ${tutorial_build_dir}_Build
       ${build_generator_args}
       --build-project Tutorial
-      --build-options ${build_options}
+      --build-options ${build_options} ${tutorial_build_options}
       --test-command Tutorial 25.0)
-  endforeach()
-  list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Tutorial")
+    list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/${tutorial_build_dir}_Build")
+  endfunction()
+
+  if(NOT CMake_TEST_EXTERNAL_CMAKE)
+    foreach(STP RANGE 1 11)
+      add_tutorial_test(Step${STP} TRUE)
+    endforeach()
+    add_tutorial_test(Complete TRUE)
+    foreach(STP RANGE 3 11)
+      add_tutorial_test(Step${STP} FALSE)
+    endforeach()
+    add_tutorial_test(Complete FALSE)
+  endif()
 
   add_test(testing ${CMAKE_CTEST_COMMAND} -C \${CTEST_CONFIGURATION_TYPE}
     --build-and-test
diff --git a/Tests/Tutorial/Complete/CMakeLists.txt b/Tests/Tutorial/Complete/CMakeLists.txt
new file mode 100644
index 0000000..9658e65
--- /dev/null
+++ b/Tests/Tutorial/Complete/CMakeLists.txt
@@ -0,0 +1,116 @@
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
+
+# 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
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
+
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
+if(APPLE)
+  set(CMAKE_INSTALL_RPATH "@executable_path/../lib")
+elseif(UNIX)
+  set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
+endif()
+
+# configure a header file to pass the version number only
+configure_file(
+  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  )
+
+# add the MathFunctions library
+add_subdirectory(MathFunctions)
+
+# add the executable
+add_executable(Tutorial tutorial.cxx)
+target_link_libraries(Tutorial MathFunctions)
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
+
+# add the install targets
+install(TARGETS Tutorial DESTINATION bin)
+install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include
+  )
+
+# enable testing
+enable_testing()
+
+# does the application run
+add_test(NAME Runs COMMAND Tutorial 25)
+
+# does the usage message work?
+add_test(NAME Usage COMMAND Tutorial)
+set_tests_properties(Usage
+  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
+  )
+
+# define a function to simplify adding tests
+function(do_test target arg result)
+  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+  set_tests_properties(Comp${arg}
+    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
+    )
+endfunction(do_test)
+
+# do a bunch of result based tests
+do_test(Tutorial 4 "4 is 2")
+do_test(Tutorial 9 "9 is 3")
+do_test(Tutorial 5 "5 is 2.236")
+do_test(Tutorial 7 "7 is 2.645")
+do_test(Tutorial 25 "25 is 5")
+do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial 0.0001 "0.0001 is 0.01")
+
+include(InstallRequiredSystemLibraries)
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
+set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
+include(CPack)
+
+# install the configuration targets
+install(EXPORT MathFunctionsTargets
+  FILE MathFunctionsTargets.cmake
+  DESTINATION lib/cmake/MathFunctions
+)
+
+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
+  )
+
+# 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"
+)
diff --git a/Tests/Tutorial/Complete/Config.cmake.in b/Tests/Tutorial/Complete/Config.cmake.in
new file mode 100644
index 0000000..17cbabd
--- /dev/null
+++ b/Tests/Tutorial/Complete/Config.cmake.in
@@ -0,0 +1,4 @@
+
+ at PACKAGE_INIT@
+
+include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" )
diff --git a/Tests/Tutorial/Step6/License.txt b/Tests/Tutorial/Complete/License.txt
similarity index 64%
copy from Tests/Tutorial/Step6/License.txt
copy to Tests/Tutorial/Complete/License.txt
index 673d724..c62d00b 100644
--- a/Tests/Tutorial/Step6/License.txt
+++ b/Tests/Tutorial/Complete/License.txt
@@ -1,2 +1,2 @@
 This is the open source License.txt file introduced in
-CMake/Tests/Tutorial/Step6...
+CMake/Tutorial/Step7...
diff --git a/Tests/Tutorial/Complete/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Complete/MathFunctions/CMakeLists.txt
new file mode 100644
index 0000000..161ad64
--- /dev/null
+++ b/Tests/Tutorial/Complete/MathFunctions/CMakeLists.txt
@@ -0,0 +1,68 @@
+
+# add the library that runs
+add_library(MathFunctions MathFunctions.cxx)
+
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+target_include_directories(MathFunctions
+                           INTERFACE
+                            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+                            $<INSTALL_INTERFACE:include>
+                           )
+
+# should we use our own math functions
+option(USE_MYMATH "Use tutorial provided math implementation" ON)
+if(USE_MYMATH)
+
+  # does this system provide the log and exp functions?
+  include(CheckSymbolExists)
+  set(CMAKE_REQUIRED_LIBRARIES "m")
+  check_symbol_exists(log "math.h" HAVE_LOG)
+  check_symbol_exists(exp "math.h" HAVE_EXP)
+
+  # first we add the executable that generates the table
+  add_executable(MakeTable MakeTable.cxx)
+
+  # add the command to generate the source code
+  add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    DEPENDS MakeTable
+    )
+
+  # library that just does sqrt
+  add_library(SqrtLibrary STATIC
+              mysqrt.cxx
+              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+              )
+
+  # state that we depend on our binary dir to find Table.h
+  target_include_directories(SqrtLibrary PRIVATE
+                             ${CMAKE_CURRENT_BINARY_DIR}
+                             )
+
+  set_target_properties(SqrtLibrary PROPERTIES
+                        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
+                        )
+
+  target_compile_definitions(SqrtLibrary PRIVATE
+                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
+                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
+                             )
+  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
+endif()
+
+target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>")
+
+# 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(TARGETS MathFunctions
+        DESTINATION lib
+        EXPORT MathFunctionsTargets)
+install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Complete/MathFunctions/MakeTable.cxx b/Tests/Tutorial/Complete/MathFunctions/MakeTable.cxx
new file mode 100644
index 0000000..ee58556
--- /dev/null
+++ b/Tests/Tutorial/Complete/MathFunctions/MakeTable.cxx
@@ -0,0 +1,25 @@
+// A simple program that builds a sqrt table
+#include <cmath>
+#include <fstream>
+#include <iostream>
+
+int main(int argc, char* argv[])
+{
+  // make sure we have enough arguments
+  if (argc < 2) {
+    return 1;
+  }
+
+  std::ofstream fout(argv[1], std::ios_base::out);
+  const bool fileOpen = fout.is_open();
+  if (fileOpen) {
+    fout << "double sqrtTable[] = {" << std::endl;
+    for (int i = 0; i < 10; ++i) {
+      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+    }
+    // close the table with a zero
+    fout << "0};" << std::endl;
+    fout.close();
+  }
+  return fileOpen ? 0 : 1; // return 0 if wrote the file
+}
diff --git a/Tests/Tutorial/Complete/MathFunctions/MathFunctions.cxx b/Tests/Tutorial/Complete/MathFunctions/MathFunctions.cxx
new file mode 100644
index 0000000..5351184
--- /dev/null
+++ b/Tests/Tutorial/Complete/MathFunctions/MathFunctions.cxx
@@ -0,0 +1,18 @@
+
+#include "MathFunctions.h"
+#include <cmath>
+
+#ifdef USE_MYMATH
+#  include "mysqrt.h"
+#endif
+
+namespace mathfunctions {
+double sqrt(double x)
+{
+#ifdef USE_MYMATH
+  return detail::mysqrt(x);
+#else
+  return std::sqrt(x);
+#endif
+}
+}
diff --git a/Tests/Tutorial/Complete/MathFunctions/MathFunctions.h b/Tests/Tutorial/Complete/MathFunctions/MathFunctions.h
new file mode 100644
index 0000000..3fb547b
--- /dev/null
+++ b/Tests/Tutorial/Complete/MathFunctions/MathFunctions.h
@@ -0,0 +1,14 @@
+
+#if defined(_WIN32)
+#  if defined(EXPORTING_MYMATH)
+#    define DECLSPEC __declspec(dllexport)
+#  else
+#    define DECLSPEC __declspec(dllimport)
+#  endif
+#else // non windows
+#  define DECLSPEC
+#endif
+
+namespace mathfunctions {
+double DECLSPEC sqrt(double x);
+}
diff --git a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Complete/MathFunctions/mysqrt.cxx
similarity index 50%
copy from Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
copy to Tests/Tutorial/Complete/MathFunctions/mysqrt.cxx
index 458ed63..96d9421 100644
--- a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Complete/MathFunctions/mysqrt.cxx
@@ -1,12 +1,13 @@
 #include "MathFunctions.h"
-#include "TutorialConfig.h"
-#include <stdio.h>
+#include <iostream>
 
 // include the generated table
 #include "Table.h"
 
-#include <math.h>
+#include <cmath>
 
+namespace mathfunctions {
+namespace detail {
 // a hack square root calculation using simple operations
 double mysqrt(double x)
 {
@@ -14,27 +15,31 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
   // if we have both log and exp then use them
-  double delta;
-
+#if defined(HAVE_LOG) && defined(HAVE_EXP)
+  double result = exp(log(x) * 0.5);
+  std::cout << "Computing sqrt of " << x << " to be " << result << " using log"
+            << std::endl;
+#else
   // use the table to help find an initial value
-  result = x;
+  double result = x;
   if (x >= 1 && x < 10) {
     result = sqrtTable[static_cast<int>(x)];
   }
 
+  // if we have both log and exp then use them
+
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
-
+#endif
   return result;
 }
+}
+}
diff --git a/Tests/Tutorial/Complete/MathFunctions/mysqrt.h b/Tests/Tutorial/Complete/MathFunctions/mysqrt.h
new file mode 100644
index 0000000..e1c42ef
--- /dev/null
+++ b/Tests/Tutorial/Complete/MathFunctions/mysqrt.h
@@ -0,0 +1,6 @@
+
+namespace mathfunctions {
+namespace detail {
+double mysqrt(double x);
+}
+}
diff --git a/Tests/Tutorial/Step2/TutorialConfig.h.in b/Tests/Tutorial/Complete/TutorialConfig.h.in
similarity index 59%
copy from Tests/Tutorial/Step2/TutorialConfig.h.in
copy to Tests/Tutorial/Complete/TutorialConfig.h.in
index 25a0602..8cd2fc9 100644
--- a/Tests/Tutorial/Step2/TutorialConfig.h.in
+++ b/Tests/Tutorial/Complete/TutorialConfig.h.in
@@ -1,5 +1,3 @@
-// the configured options and settings for Tutorial
+// the configured version number
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-#cmakedefine USE_MYMATH
-
diff --git a/Tests/Tutorial/Complete/tutorial.cxx b/Tests/Tutorial/Complete/tutorial.cxx
new file mode 100644
index 0000000..443d195
--- /dev/null
+++ b/Tests/Tutorial/Complete/tutorial.cxx
@@ -0,0 +1,25 @@
+// A simple program that computes the square root of a number
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "MathFunctions.h"
+#include "TutorialConfig.h"
+
+int main(int argc, char* argv[])
+{
+  if (argc < 2) {
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
+    return 1;
+  }
+
+  double inputValue = std::stod(argv[1]);
+
+  const double outputValue = mathfunctions::sqrt(inputValue);
+
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
+  return 0;
+}
diff --git a/Tests/Tutorial/Consumer/CMakeLists.txt b/Tests/Tutorial/Consumer/CMakeLists.txt
new file mode 100644
index 0000000..4033b4d
--- /dev/null
+++ b/Tests/Tutorial/Consumer/CMakeLists.txt
@@ -0,0 +1,51 @@
+cmake_minimum_required(VERSION 3.3)
+
+if(NOT DEFINED CMAKE_CXX_STANDARD)
+  set(CMAKE_CXX_STANDARD 11)
+  set(CMAKE_CXX_STANDARD_REQUIRED True)
+endif()
+
+
+function(find_external_dependency name)
+  set(${name}_ROOT ""  CACHE PATH "Root directory to find ${name}")
+  mark_as_advanced(${name}_DIR)
+  find_package(${name} PATHS ${${name}_ROOT} REQUIRED)
+endfunction()
+
+
+project(Consumer)
+
+find_external_dependency(MathFunctions)
+
+add_library(consumer consumer.cxx)
+target_link_libraries(consumer PUBLIC MathFunctions)
+
+# install the consumer library
+install(TARGETS consumer DESTINATION bin EXPORT ConsumerTargets)
+
+# install the configuration targets
+install(EXPORT ConsumerTargets
+  FILE ConsumerTargets.cmake
+  DESTINATION lib/cmake/Consumer
+)
+
+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}/ConsumerConfig.cmake"
+  INSTALL_DESTINATION "lib/cmake/example"
+  NO_SET_AND_CHECK_MACRO
+  NO_CHECK_REQUIRED_COMPONENTS_MACRO
+  )
+
+# install the configuration file
+install(FILES
+  ${CMAKE_CURRENT_BINARY_DIR}/ConsumerConfig.cmake
+  DESTINATION lib/cmake/Consumer
+  )
+
+# generate the export targets for the build tree
+# needs to be after the install(TARGETS ) command
+export(EXPORT ConsumerTargets
+  FILE "${CMAKE_CURRENT_BINARY_DIR}/ConsumerTargets.cmake"
+)
diff --git a/Tests/Tutorial/Consumer/Config.cmake.in b/Tests/Tutorial/Consumer/Config.cmake.in
new file mode 100644
index 0000000..0b3f1e4
--- /dev/null
+++ b/Tests/Tutorial/Consumer/Config.cmake.in
@@ -0,0 +1,14 @@
+
+ at PACKAGE_INIT@
+
+include(CMakeFindDependencyMacro)
+
+function(find_external_dependency name)
+  set(${name}_ROOT ""  CACHE PATH "Root directory to find ${name}")
+  mark_as_advanced(${name}_DIR)
+  find_dependency(${name} PATHS ${${name}_ROOT} REQUIRED)
+endfunction()
+
+find_external_dependency(MathFunctions)
+
+include ( "${CMAKE_CURRENT_LIST_DIR}/ConsumerTargets.cmake" )
diff --git a/Tests/Tutorial/Consumer/consumer.cxx b/Tests/Tutorial/Consumer/consumer.cxx
new file mode 100644
index 0000000..ae7877b
--- /dev/null
+++ b/Tests/Tutorial/Consumer/consumer.cxx
@@ -0,0 +1,11 @@
+// A simple function that computes the square root of a number
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "MathFunctions.h"
+
+double string_square_root(std::string const& value)
+{
+  return mathfunctions::sqrt(std::stod(value));
+}
diff --git a/Tests/Tutorial/Consumer/directions.txt b/Tests/Tutorial/Consumer/directions.txt
new file mode 100644
index 0000000..6a70aab
--- /dev/null
+++ b/Tests/Tutorial/Consumer/directions.txt
@@ -0,0 +1,6 @@
+# Import a CMake Project#
+
+This examples shows how a project can find other CMake packages that
+generated Config.cmake files.
+
+It also shows how to state a projects external dependencies when generating a Config.cmake.
diff --git a/Tests/Tutorial/MultiPackage/CMakeLists.txt b/Tests/Tutorial/MultiPackage/CMakeLists.txt
new file mode 100644
index 0000000..067e807
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/CMakeLists.txt
@@ -0,0 +1,109 @@
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
+
+# control how we mark up Debug libraries compared to Release libraries
+set(CMAKE_DEBUG_POSTFIX "-d")
+
+# 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
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+
+option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
+
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
+# configure a header file to pass the version number only
+configure_file(
+  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  )
+
+# add the MathFunctions library
+add_subdirectory(MathFunctions)
+
+# add the executable
+add_executable(Tutorial tutorial.cxx)
+target_link_libraries(Tutorial MathFunctions)
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
+
+# add the install targets
+install(TARGETS Tutorial DESTINATION bin)
+install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include
+  )
+
+# enable testing
+enable_testing()
+
+# does the application run
+add_test(NAME Runs COMMAND Tutorial 25)
+
+# does the usage message work?
+add_test(NAME Usage COMMAND Tutorial)
+set_tests_properties(Usage
+  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
+  )
+
+# define a function to simplify adding tests
+function(do_test target arg result)
+  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+  set_tests_properties(Comp${arg}
+    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
+    )
+endfunction(do_test)
+
+# do a bunch of result based tests
+do_test(Tutorial 4 "4 is 2")
+do_test(Tutorial 9 "9 is 3")
+do_test(Tutorial 5 "5 is 2.236")
+do_test(Tutorial 7 "7 is 2.645")
+do_test(Tutorial 25 "25 is 5")
+do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial 0.0001 "0.0001 is 0.01")
+
+include(InstallRequiredSystemLibraries)
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
+set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
+include(CPack)
+
+# install the configuration targets
+install(EXPORT MathFunctionsTargets
+  FILE MathFunctionsTargets.cmake
+  DESTINATION lib/cmake/MathFunctions
+)
+
+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
+  )
+
+# 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"
+)
diff --git a/Tests/Tutorial/MultiPackage/Config.cmake.in b/Tests/Tutorial/MultiPackage/Config.cmake.in
new file mode 100644
index 0000000..17cbabd
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/Config.cmake.in
@@ -0,0 +1,4 @@
+
+ at PACKAGE_INIT@
+
+include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" )
diff --git a/Tests/Tutorial/Step6/License.txt b/Tests/Tutorial/MultiPackage/License.txt
similarity index 64%
copy from Tests/Tutorial/Step6/License.txt
copy to Tests/Tutorial/MultiPackage/License.txt
index 673d724..c62d00b 100644
--- a/Tests/Tutorial/Step6/License.txt
+++ b/Tests/Tutorial/MultiPackage/License.txt
@@ -1,2 +1,2 @@
 This is the open source License.txt file introduced in
-CMake/Tests/Tutorial/Step6...
+CMake/Tutorial/Step7...
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/CMakeLists.txt b/Tests/Tutorial/MultiPackage/MathFunctions/CMakeLists.txt
new file mode 100644
index 0000000..161ad64
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/MathFunctions/CMakeLists.txt
@@ -0,0 +1,68 @@
+
+# add the library that runs
+add_library(MathFunctions MathFunctions.cxx)
+
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+target_include_directories(MathFunctions
+                           INTERFACE
+                            $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+                            $<INSTALL_INTERFACE:include>
+                           )
+
+# should we use our own math functions
+option(USE_MYMATH "Use tutorial provided math implementation" ON)
+if(USE_MYMATH)
+
+  # does this system provide the log and exp functions?
+  include(CheckSymbolExists)
+  set(CMAKE_REQUIRED_LIBRARIES "m")
+  check_symbol_exists(log "math.h" HAVE_LOG)
+  check_symbol_exists(exp "math.h" HAVE_EXP)
+
+  # first we add the executable that generates the table
+  add_executable(MakeTable MakeTable.cxx)
+
+  # add the command to generate the source code
+  add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    DEPENDS MakeTable
+    )
+
+  # library that just does sqrt
+  add_library(SqrtLibrary STATIC
+              mysqrt.cxx
+              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+              )
+
+  # state that we depend on our binary dir to find Table.h
+  target_include_directories(SqrtLibrary PRIVATE
+                             ${CMAKE_CURRENT_BINARY_DIR}
+                             )
+
+  set_target_properties(SqrtLibrary PROPERTIES
+                        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
+                        )
+
+  target_compile_definitions(SqrtLibrary PRIVATE
+                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
+                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
+                             )
+  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
+endif()
+
+target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>")
+
+# 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(TARGETS MathFunctions
+        DESTINATION lib
+        EXPORT MathFunctionsTargets)
+install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/MakeTable.cxx b/Tests/Tutorial/MultiPackage/MathFunctions/MakeTable.cxx
new file mode 100644
index 0000000..ee58556
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/MathFunctions/MakeTable.cxx
@@ -0,0 +1,25 @@
+// A simple program that builds a sqrt table
+#include <cmath>
+#include <fstream>
+#include <iostream>
+
+int main(int argc, char* argv[])
+{
+  // make sure we have enough arguments
+  if (argc < 2) {
+    return 1;
+  }
+
+  std::ofstream fout(argv[1], std::ios_base::out);
+  const bool fileOpen = fout.is_open();
+  if (fileOpen) {
+    fout << "double sqrtTable[] = {" << std::endl;
+    for (int i = 0; i < 10; ++i) {
+      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+    }
+    // close the table with a zero
+    fout << "0};" << std::endl;
+    fout.close();
+  }
+  return fileOpen ? 0 : 1; // return 0 if wrote the file
+}
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.cxx b/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.cxx
new file mode 100644
index 0000000..5351184
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.cxx
@@ -0,0 +1,18 @@
+
+#include "MathFunctions.h"
+#include <cmath>
+
+#ifdef USE_MYMATH
+#  include "mysqrt.h"
+#endif
+
+namespace mathfunctions {
+double sqrt(double x)
+{
+#ifdef USE_MYMATH
+  return detail::mysqrt(x);
+#else
+  return std::sqrt(x);
+#endif
+}
+}
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.h b/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.h
new file mode 100644
index 0000000..3fb547b
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.h
@@ -0,0 +1,14 @@
+
+#if defined(_WIN32)
+#  if defined(EXPORTING_MYMATH)
+#    define DECLSPEC __declspec(dllexport)
+#  else
+#    define DECLSPEC __declspec(dllimport)
+#  endif
+#else // non windows
+#  define DECLSPEC
+#endif
+
+namespace mathfunctions {
+double DECLSPEC sqrt(double x);
+}
diff --git a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx b/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.cxx
similarity index 50%
copy from Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
copy to Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.cxx
index 458ed63..96d9421 100644
--- a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.cxx
@@ -1,12 +1,13 @@
 #include "MathFunctions.h"
-#include "TutorialConfig.h"
-#include <stdio.h>
+#include <iostream>
 
 // include the generated table
 #include "Table.h"
 
-#include <math.h>
+#include <cmath>
 
+namespace mathfunctions {
+namespace detail {
 // a hack square root calculation using simple operations
 double mysqrt(double x)
 {
@@ -14,27 +15,31 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
   // if we have both log and exp then use them
-  double delta;
-
+#if defined(HAVE_LOG) && defined(HAVE_EXP)
+  double result = exp(log(x) * 0.5);
+  std::cout << "Computing sqrt of " << x << " to be " << result << " using log"
+            << std::endl;
+#else
   // use the table to help find an initial value
-  result = x;
+  double result = x;
   if (x >= 1 && x < 10) {
     result = sqrtTable[static_cast<int>(x)];
   }
 
+  // if we have both log and exp then use them
+
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
-
+#endif
   return result;
 }
+}
+}
diff --git a/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.h b/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.h
new file mode 100644
index 0000000..e1c42ef
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.h
@@ -0,0 +1,6 @@
+
+namespace mathfunctions {
+namespace detail {
+double mysqrt(double x);
+}
+}
diff --git a/Tests/Tutorial/MultiPackage/MultiCPackConfig.cmake b/Tests/Tutorial/MultiPackage/MultiCPackConfig.cmake
new file mode 100644
index 0000000..403b633
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/MultiCPackConfig.cmake
@@ -0,0 +1,7 @@
+
+include("release/CPackConfig.cmake")
+
+set(CPACK_INSTALL_CMAKE_PROJECTS
+    "debug;Tutorial;ALL;/"
+    "release;Tutorial;ALL;/"
+    )
diff --git a/Tests/Tutorial/Step2/TutorialConfig.h.in b/Tests/Tutorial/MultiPackage/TutorialConfig.h.in
similarity index 59%
copy from Tests/Tutorial/Step2/TutorialConfig.h.in
copy to Tests/Tutorial/MultiPackage/TutorialConfig.h.in
index 25a0602..8cd2fc9 100644
--- a/Tests/Tutorial/Step2/TutorialConfig.h.in
+++ b/Tests/Tutorial/MultiPackage/TutorialConfig.h.in
@@ -1,5 +1,3 @@
-// the configured options and settings for Tutorial
+// the configured version number
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-#cmakedefine USE_MYMATH
-
diff --git a/Tests/Tutorial/MultiPackage/directions.txt b/Tests/Tutorial/MultiPackage/directions.txt
new file mode 100644
index 0000000..c3102bb
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/directions.txt
@@ -0,0 +1,34 @@
+# Packaging Debug and Release #
+
+By default CMake is model is that a build directory only contains a single
+configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo.
+
+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.
+
+First we need to ahead and construct a directory called 'multi_config' this
+will contain all the builds that we want to package together.
+
+Second create a 'debug' and 'release' directory underneath 'multi_config'. At
+the end you should have a layout that looks like:
+
+─ multi_config
+    ├── debug
+    └── release
+
+Now we need to setup debug and release builds, which would roughly entail
+the following:
+
+  cd debug
+  cmake -DCMAKE_BUILD_TYPE=Debug ../../MultiPackage/
+  cmake --build .
+  cd ../release
+  cmake -DCMAKE_BUILD_TYPE=Release ../../MultiPackage/
+  cmake --build .
+  cd ..
+
+
+Now that both the debug and release builds are complete we can now use
+the custom MultiCPackConfig to package both builds into a single release.
+
+  cpack --config ../../MultiPackage/MultiCPackConfig.cmake
diff --git a/Tests/Tutorial/MultiPackage/tutorial.cxx b/Tests/Tutorial/MultiPackage/tutorial.cxx
new file mode 100644
index 0000000..443d195
--- /dev/null
+++ b/Tests/Tutorial/MultiPackage/tutorial.cxx
@@ -0,0 +1,25 @@
+// A simple program that computes the square root of a number
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "MathFunctions.h"
+#include "TutorialConfig.h"
+
+int main(int argc, char* argv[])
+{
+  if (argc < 2) {
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
+    return 1;
+  }
+
+  double inputValue = std::stod(argv[1]);
+
+  const double outputValue = mathfunctions::sqrt(inputValue);
+
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
+  return 0;
+}
diff --git a/Tests/Tutorial/Readme.txt b/Tests/Tutorial/Readme.txt
new file mode 100644
index 0000000..74eb01a
--- /dev/null
+++ b/Tests/Tutorial/Readme.txt
@@ -0,0 +1,16 @@
+
+Step 0: A Starting Point
+Step 1: Configure a File and C++11 Controls
+Step 2: Adding a Library
+Step 3: Usage Requirements for Library
+Step 4: Installing and Testing
+Step 5: System Introspection
+Step 6: Custom Command and Generated File
+Step 7: Building an Installer
+Step 8: CDash submission
+Step 9: Mixing Static and Shared
+Step 10: Generator Expressions
+Step 11: Adding Export Configuration
+Complete: End result of Step 11
+Consumer: Example of Import Packages
+MultiPackage: How to package Debug and Release versions
diff --git a/Tests/Tutorial/Step1/CMakeLists.txt b/Tests/Tutorial/Step1/CMakeLists.txt
index e461d3c..141f0c2 100644
--- a/Tests/Tutorial/Step1/CMakeLists.txt
+++ b/Tests/Tutorial/Step1/CMakeLists.txt
@@ -1,20 +1,3 @@
-cmake_minimum_required (VERSION 2.6)
-project (Tutorial)
+project(Tutorial)
 
-# The version number.
-set (Tutorial_VERSION_MAJOR 1)
-set (Tutorial_VERSION_MINOR 0)
-
-# configure a header file to pass some of the CMake settings
-# to the source code
-configure_file (
-  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
-  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  )
-
-# add the binary tree to the search path for include files
-# so that we will find TutorialConfig.h
-include_directories("${PROJECT_BINARY_DIR}")
-
-# add the executable
 add_executable(Tutorial tutorial.cxx)
diff --git a/Tests/Tutorial/Step1/directions.txt b/Tests/Tutorial/Step1/directions.txt
new file mode 100644
index 0000000..10f2583
--- /dev/null
+++ b/Tests/Tutorial/Step1/directions.txt
@@ -0,0 +1,96 @@
+# Adding a Version Number and Configured Header File #
+
+The first feature we will add is to provide our executable and project with a
+version number. While we could do this exclusively in the source code, using
+CMakeLists provides more flexibility.
+
+To add a version number we modify the CMakeLists file as follows:
+
+  cmake_minimum_required(VERSION 3.3)
+  project(Tutorial)
+
+  # the version number.
+  set(Tutorial_VERSION_MAJOR 1)
+  set(Tutorial_VERSION_MINOR 0)
+
+  # configure a header file to pass some of the CMake settings
+  # to the source code
+  configure_file(
+    "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+    "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+    )
+
+  # add the executable
+  add_executable(Tutorial tutorial.cxx)
+
+  # add the binary tree to the search path for include files
+  # so that we will find TutorialConfig.h
+  target_include_directories(Tutorial PUBLIC
+                             "${PROJECT_BINARY_DIR}"
+                             )
+
+
+We then create a TutorialConfig.h.in file in the source tree with the
+following contents:
+
+  // the configured options and settings for Tutorial
+  #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
+  #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
+
+When CMake configures this header file the values for @Tutorial_VERSION_MAJOR@
+and @Tutorial_VERSION_MINOR@ will be replaced by the values from the CMakeLists
+file. Next we modify tutorial.cxx to include the configured header file and to
+make use of the version numbers. The resulting source code is listed below.
+
+  // A simple program that computes the square root of a number
+  #include <cmath>
+  #include <iostream>
+  #include <string>
+  #include <sstream>
+
+  #include "TutorialConfig.h"
+
+  int main (int argc, char *argv[])
+  {
+    if (argc < 2)
+      {
+      std::cout << argv[0] << " Version "
+                << Tutorial_VERSION_MAJOR << "." << Tutorial_VERSION_MINOR
+                << std::endl;
+      std::cout << "Usage: " << argv[0] << " number" << std::endl;
+      return 1;
+      }
+
+    double inputValue = atof(argv[1]);
+
+    double outputValue = sqrt(inputValue);
+    std::cout << "The square root of "
+              << inputValue << " is " << outputValue << std::endl;
+    return 0;
+  }
+
+# Adding C++11 support #
+
+Let's add some C++11 features to our project. We will need to explicitly state
+in the CMake code that it should use the correct flags. The easiest way to
+enable C++11 support for CMake is by using the CMAKE_CXX_STANDARD
+and CMAKE_CXX_STANDARD_REQUIRED variables.
+
+First, replace `atof` with `std::stod` in tutorial.cxx.
+
+Then, add the CMAKE_CXX_STANDARD and CMAKE_CXX_STANDARD_REQUIRED variables to
+the CMakeLists file. The STANADARD value should be set to 11, and REQUIRED
+should be set to True.
+
+
+# Build and Test #
+
+Run cmake or cmake-gui to configure the project and then build it with your
+chosen build tool
+
+cd to the directory where Tutorial was built (likely the make directory or
+a Debug or Release build configuration subdirectory) and run these commands:
+
+  Tutorial 4294967296
+  Tutorial 10
+  Tutorial
diff --git a/Tests/Tutorial/Step1/tutorial.cxx b/Tests/Tutorial/Step1/tutorial.cxx
index 7a13376..f8dd0c6 100644
--- a/Tests/Tutorial/Step1/tutorial.cxx
+++ b/Tests/Tutorial/Step1/tutorial.cxx
@@ -1,19 +1,20 @@
 // A simple program that computes the square root of a number
-#include "TutorialConfig.h"
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <cmath>
+#include <cstdlib>
+#include <iostream>
+#include <string>
 
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
-    fprintf(stdout, "%s Version %d.%d\n", argv[0], Tutorial_VERSION_MAJOR,
-            Tutorial_VERSION_MINOR);
-    fprintf(stdout, "Usage: %s number\n", argv[0]);
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
+
   double inputValue = atof(argv[1]);
+
   double outputValue = sqrt(inputValue);
-  fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
   return 0;
 }
diff --git a/Tests/Tutorial/Step10/CMakeLists.txt b/Tests/Tutorial/Step10/CMakeLists.txt
new file mode 100644
index 0000000..b1d46c4
--- /dev/null
+++ b/Tests/Tutorial/Step10/CMakeLists.txt
@@ -0,0 +1,77 @@
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
+
+# 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
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
+
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
+# configure a header file to pass the version number only
+configure_file(
+  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  )
+
+# add the MathFunctions library
+add_subdirectory(MathFunctions)
+
+# add the executable
+add_executable(Tutorial tutorial.cxx)
+target_link_libraries(Tutorial MathFunctions)
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
+
+# add the install targets
+install(TARGETS Tutorial DESTINATION bin)
+install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include
+  )
+
+# enable testing
+enable_testing()
+
+# does the application run
+add_test(NAME Runs COMMAND Tutorial 25)
+
+# does the usage message work?
+add_test(NAME Usage COMMAND Tutorial)
+set_tests_properties(Usage
+  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
+  )
+
+# define a function to simplify adding tests
+function(do_test target arg result)
+  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+  set_tests_properties(Comp${arg}
+    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
+    )
+endfunction(do_test)
+
+# do a bunch of result based tests
+do_test(Tutorial 4 "4 is 2")
+do_test(Tutorial 9 "9 is 3")
+do_test(Tutorial 5 "5 is 2.236")
+do_test(Tutorial 7 "7 is 2.645")
+do_test(Tutorial 25 "25 is 5")
+do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial 0.0001 "0.0001 is 0.01")
+
+include(InstallRequiredSystemLibraries)
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
+set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
+include(CPack)
diff --git a/Tests/Tutorial/Step6/License.txt b/Tests/Tutorial/Step10/License.txt
similarity index 64%
copy from Tests/Tutorial/Step6/License.txt
copy to Tests/Tutorial/Step10/License.txt
index 673d724..c62d00b 100644
--- a/Tests/Tutorial/Step6/License.txt
+++ b/Tests/Tutorial/Step10/License.txt
@@ -1,2 +1,2 @@
 This is the open source License.txt file introduced in
-CMake/Tests/Tutorial/Step6...
+CMake/Tutorial/Step7...
diff --git a/Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt
new file mode 100644
index 0000000..7a23505
--- /dev/null
+++ b/Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt
@@ -0,0 +1,61 @@
+
+# add the library that runs
+add_library(MathFunctions MathFunctions.cxx)
+
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+target_include_directories(MathFunctions
+                           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+                           )
+
+# should we use our own math functions
+option(USE_MYMATH "Use tutorial provided math implementation" ON)
+if(USE_MYMATH)
+
+  # does this system provide the log and exp functions?
+  include(CheckSymbolExists)
+  set(CMAKE_REQUIRED_LIBRARIES "m")
+  check_symbol_exists(log "math.h" HAVE_LOG)
+  check_symbol_exists(exp "math.h" HAVE_EXP)
+
+  # first we add the executable that generates the table
+  add_executable(MakeTable MakeTable.cxx)
+
+  # add the command to generate the source code
+  add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    DEPENDS MakeTable
+    )
+
+  # library that just does sqrt
+  add_library(SqrtLibrary STATIC
+              mysqrt.cxx
+              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+              )
+
+  # state that we depend on our binary dir to find Table.h
+  target_include_directories(SqrtLibrary PRIVATE
+                             ${CMAKE_CURRENT_BINARY_DIR}
+                             )
+
+  # state that SqrtLibrary need PIC when the default is shared libraries
+  set_target_properties(SqrtLibrary PROPERTIES
+                        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
+                        )
+
+  target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
+  if(HAVE_LOG AND HAVE_EXP)
+    target_compile_definitions(SqrtLibrary
+                               PRIVATE "HAVE_LOG" "HAVE_EXP")
+  endif()
+
+  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
+endif()
+
+# define the symbol stating we are using the declspec(dllexport) when
+# building on windows
+target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
+
+install(TARGETS MathFunctions DESTINATION lib)
+install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step10/MathFunctions/MakeTable.cxx b/Tests/Tutorial/Step10/MathFunctions/MakeTable.cxx
new file mode 100644
index 0000000..ee58556
--- /dev/null
+++ b/Tests/Tutorial/Step10/MathFunctions/MakeTable.cxx
@@ -0,0 +1,25 @@
+// A simple program that builds a sqrt table
+#include <cmath>
+#include <fstream>
+#include <iostream>
+
+int main(int argc, char* argv[])
+{
+  // make sure we have enough arguments
+  if (argc < 2) {
+    return 1;
+  }
+
+  std::ofstream fout(argv[1], std::ios_base::out);
+  const bool fileOpen = fout.is_open();
+  if (fileOpen) {
+    fout << "double sqrtTable[] = {" << std::endl;
+    for (int i = 0; i < 10; ++i) {
+      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+    }
+    // close the table with a zero
+    fout << "0};" << std::endl;
+    fout.close();
+  }
+  return fileOpen ? 0 : 1; // return 0 if wrote the file
+}
diff --git a/Tests/Tutorial/Step10/MathFunctions/MathFunctions.cxx b/Tests/Tutorial/Step10/MathFunctions/MathFunctions.cxx
new file mode 100644
index 0000000..5351184
--- /dev/null
+++ b/Tests/Tutorial/Step10/MathFunctions/MathFunctions.cxx
@@ -0,0 +1,18 @@
+
+#include "MathFunctions.h"
+#include <cmath>
+
+#ifdef USE_MYMATH
+#  include "mysqrt.h"
+#endif
+
+namespace mathfunctions {
+double sqrt(double x)
+{
+#ifdef USE_MYMATH
+  return detail::mysqrt(x);
+#else
+  return std::sqrt(x);
+#endif
+}
+}
diff --git a/Tests/Tutorial/Step10/MathFunctions/MathFunctions.h b/Tests/Tutorial/Step10/MathFunctions/MathFunctions.h
new file mode 100644
index 0000000..3fb547b
--- /dev/null
+++ b/Tests/Tutorial/Step10/MathFunctions/MathFunctions.h
@@ -0,0 +1,14 @@
+
+#if defined(_WIN32)
+#  if defined(EXPORTING_MYMATH)
+#    define DECLSPEC __declspec(dllexport)
+#  else
+#    define DECLSPEC __declspec(dllimport)
+#  endif
+#else // non windows
+#  define DECLSPEC
+#endif
+
+namespace mathfunctions {
+double DECLSPEC sqrt(double x);
+}
diff --git a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step10/MathFunctions/mysqrt.cxx
similarity index 50%
copy from Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
copy to Tests/Tutorial/Step10/MathFunctions/mysqrt.cxx
index 458ed63..96d9421 100644
--- a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step10/MathFunctions/mysqrt.cxx
@@ -1,12 +1,13 @@
 #include "MathFunctions.h"
-#include "TutorialConfig.h"
-#include <stdio.h>
+#include <iostream>
 
 // include the generated table
 #include "Table.h"
 
-#include <math.h>
+#include <cmath>
 
+namespace mathfunctions {
+namespace detail {
 // a hack square root calculation using simple operations
 double mysqrt(double x)
 {
@@ -14,27 +15,31 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
   // if we have both log and exp then use them
-  double delta;
-
+#if defined(HAVE_LOG) && defined(HAVE_EXP)
+  double result = exp(log(x) * 0.5);
+  std::cout << "Computing sqrt of " << x << " to be " << result << " using log"
+            << std::endl;
+#else
   // use the table to help find an initial value
-  result = x;
+  double result = x;
   if (x >= 1 && x < 10) {
     result = sqrtTable[static_cast<int>(x)];
   }
 
+  // if we have both log and exp then use them
+
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
-
+#endif
   return result;
 }
+}
+}
diff --git a/Tests/Tutorial/Step10/MathFunctions/mysqrt.h b/Tests/Tutorial/Step10/MathFunctions/mysqrt.h
new file mode 100644
index 0000000..e1c42ef
--- /dev/null
+++ b/Tests/Tutorial/Step10/MathFunctions/mysqrt.h
@@ -0,0 +1,6 @@
+
+namespace mathfunctions {
+namespace detail {
+double mysqrt(double x);
+}
+}
diff --git a/Tests/Tutorial/Step2/TutorialConfig.h.in b/Tests/Tutorial/Step10/TutorialConfig.h.in
similarity index 59%
copy from Tests/Tutorial/Step2/TutorialConfig.h.in
copy to Tests/Tutorial/Step10/TutorialConfig.h.in
index 25a0602..8cd2fc9 100644
--- a/Tests/Tutorial/Step2/TutorialConfig.h.in
+++ b/Tests/Tutorial/Step10/TutorialConfig.h.in
@@ -1,5 +1,3 @@
-// the configured options and settings for Tutorial
+// the configured version number
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-#cmakedefine USE_MYMATH
-
diff --git a/Tests/Tutorial/Step10/directions.txt b/Tests/Tutorial/Step10/directions.txt
new file mode 100644
index 0000000..5317b54
--- /dev/null
+++ b/Tests/Tutorial/Step10/directions.txt
@@ -0,0 +1,38 @@
+# Adding Generator Expressions #
+
+Generator expressions are evaluated during build system generation to produce
+information specific to each build configuration.
+
+Generator expressions are allowed in the context of many target properties, such
+as LINK_LIBRARIES, INCLUDE_DIRECTORIES, COMPILE_DEFINITIONS and others. They may
+also be used when using commands to populate those properties, such as
+target_link_libraries(), target_include_directories(),
+target_compile_definitions() and others.
+
+Generator expressions may to used to enable conditional linking, conditional
+definitions used when compiling, and conditional include directories and more.
+The conditions may be based on the build configuration, target properties,
+platform information or any other queryable information.
+
+There are different types of generator expressions including Logical,
+Informational, and Output expressions.
+
+Logical expressions are used to create conditional output. The basic expressions
+are the 0 and 1 expressions. A "$<0:...>" results in the empty string, and
+"$<1:...>" results in the content of "...".  They can also be nested.
+For example:
+
+  if(HAVE_LOG AND HAVE_EXP)
+    target_compile_definitions(SqrtLibrary
+                               PRIVATE "HAVE_LOG" "HAVE_EXP")
+  endif()
+
+Can be rewritten with generator expressions:
+
+  target_compile_definitions(SqrtLibrary PRIVATE
+                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
+                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
+                            )
+
+Note that "${HAVE_LOG}" is evaluated at CMake configure time while
+"$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>" is evaluated at build system generation time.
diff --git a/Tests/Tutorial/Step10/tutorial.cxx b/Tests/Tutorial/Step10/tutorial.cxx
new file mode 100644
index 0000000..443d195
--- /dev/null
+++ b/Tests/Tutorial/Step10/tutorial.cxx
@@ -0,0 +1,25 @@
+// A simple program that computes the square root of a number
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "MathFunctions.h"
+#include "TutorialConfig.h"
+
+int main(int argc, char* argv[])
+{
+  if (argc < 2) {
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
+    return 1;
+  }
+
+  double inputValue = std::stod(argv[1]);
+
+  const double outputValue = mathfunctions::sqrt(inputValue);
+
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
+  return 0;
+}
diff --git a/Tests/Tutorial/Step11/CMakeLists.txt b/Tests/Tutorial/Step11/CMakeLists.txt
new file mode 100644
index 0000000..b1d46c4
--- /dev/null
+++ b/Tests/Tutorial/Step11/CMakeLists.txt
@@ -0,0 +1,77 @@
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
+
+# 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
+set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
+
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
+# configure a header file to pass the version number only
+configure_file(
+  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  )
+
+# add the MathFunctions library
+add_subdirectory(MathFunctions)
+
+# add the executable
+add_executable(Tutorial tutorial.cxx)
+target_link_libraries(Tutorial MathFunctions)
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
+
+# add the install targets
+install(TARGETS Tutorial DESTINATION bin)
+install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include
+  )
+
+# enable testing
+enable_testing()
+
+# does the application run
+add_test(NAME Runs COMMAND Tutorial 25)
+
+# does the usage message work?
+add_test(NAME Usage COMMAND Tutorial)
+set_tests_properties(Usage
+  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
+  )
+
+# define a function to simplify adding tests
+function(do_test target arg result)
+  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+  set_tests_properties(Comp${arg}
+    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
+    )
+endfunction(do_test)
+
+# do a bunch of result based tests
+do_test(Tutorial 4 "4 is 2")
+do_test(Tutorial 9 "9 is 3")
+do_test(Tutorial 5 "5 is 2.236")
+do_test(Tutorial 7 "7 is 2.645")
+do_test(Tutorial 25 "25 is 5")
+do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial 0.0001 "0.0001 is 0.01")
+
+include(InstallRequiredSystemLibraries)
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
+set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
+include(CPack)
diff --git a/Tests/Tutorial/Step6/License.txt b/Tests/Tutorial/Step11/License.txt
similarity index 64%
copy from Tests/Tutorial/Step6/License.txt
copy to Tests/Tutorial/Step11/License.txt
index 673d724..c62d00b 100644
--- a/Tests/Tutorial/Step6/License.txt
+++ b/Tests/Tutorial/Step11/License.txt
@@ -1,2 +1,2 @@
 This is the open source License.txt file introduced in
-CMake/Tests/Tutorial/Step6...
+CMake/Tutorial/Step7...
diff --git a/Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt
new file mode 100644
index 0000000..760d6a5
--- /dev/null
+++ b/Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt
@@ -0,0 +1,60 @@
+
+# add the library that runs
+add_library(MathFunctions MathFunctions.cxx)
+
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+target_include_directories(MathFunctions
+                           INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+                           )
+
+# should we use our own math functions
+option(USE_MYMATH "Use tutorial provided math implementation" ON)
+if(USE_MYMATH)
+
+  # does this system provide the log and exp functions?
+  include(CheckSymbolExists)
+  set(CMAKE_REQUIRED_LIBRARIES "m")
+  check_symbol_exists(log "math.h" HAVE_LOG)
+  check_symbol_exists(exp "math.h" HAVE_EXP)
+
+  # first we add the executable that generates the table
+  add_executable(MakeTable MakeTable.cxx)
+
+  # add the command to generate the source code
+  add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    DEPENDS MakeTable
+    )
+
+  # library that just does sqrt
+  add_library(SqrtLibrary STATIC
+              mysqrt.cxx
+              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+              )
+
+  # state that we depend on our binary dir to find Table.h
+  target_include_directories(SqrtLibrary PRIVATE
+                             ${CMAKE_CURRENT_BINARY_DIR}
+                             )
+
+  set_target_properties(SqrtLibrary PROPERTIES
+                        POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS}
+                        )
+
+  target_compile_definitions(SqrtLibrary PRIVATE
+                             "$<$<BOOL:${HAVE_LOG}>:HAVE_LOG>"
+                             "$<$<BOOL:${HAVE_EXP}>:HAVE_EXP>"
+                             )
+  target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
+endif()
+
+target_compile_definitions(MathFunctions PRIVATE "$<$<BOOL:${USE_MYMATH}>:USE_MYMATH>")
+
+# define the symbol stating we are using the declspec(dllexport) when
+#building on windows
+target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
+
+install(TARGETS MathFunctions DESTINATION lib)
+install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step11/MathFunctions/MakeTable.cxx b/Tests/Tutorial/Step11/MathFunctions/MakeTable.cxx
new file mode 100644
index 0000000..ee58556
--- /dev/null
+++ b/Tests/Tutorial/Step11/MathFunctions/MakeTable.cxx
@@ -0,0 +1,25 @@
+// A simple program that builds a sqrt table
+#include <cmath>
+#include <fstream>
+#include <iostream>
+
+int main(int argc, char* argv[])
+{
+  // make sure we have enough arguments
+  if (argc < 2) {
+    return 1;
+  }
+
+  std::ofstream fout(argv[1], std::ios_base::out);
+  const bool fileOpen = fout.is_open();
+  if (fileOpen) {
+    fout << "double sqrtTable[] = {" << std::endl;
+    for (int i = 0; i < 10; ++i) {
+      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+    }
+    // close the table with a zero
+    fout << "0};" << std::endl;
+    fout.close();
+  }
+  return fileOpen ? 0 : 1; // return 0 if wrote the file
+}
diff --git a/Tests/Tutorial/Step11/MathFunctions/MathFunctions.cxx b/Tests/Tutorial/Step11/MathFunctions/MathFunctions.cxx
new file mode 100644
index 0000000..5351184
--- /dev/null
+++ b/Tests/Tutorial/Step11/MathFunctions/MathFunctions.cxx
@@ -0,0 +1,18 @@
+
+#include "MathFunctions.h"
+#include <cmath>
+
+#ifdef USE_MYMATH
+#  include "mysqrt.h"
+#endif
+
+namespace mathfunctions {
+double sqrt(double x)
+{
+#ifdef USE_MYMATH
+  return detail::mysqrt(x);
+#else
+  return std::sqrt(x);
+#endif
+}
+}
diff --git a/Tests/Tutorial/Step11/MathFunctions/MathFunctions.h b/Tests/Tutorial/Step11/MathFunctions/MathFunctions.h
new file mode 100644
index 0000000..3fb547b
--- /dev/null
+++ b/Tests/Tutorial/Step11/MathFunctions/MathFunctions.h
@@ -0,0 +1,14 @@
+
+#if defined(_WIN32)
+#  if defined(EXPORTING_MYMATH)
+#    define DECLSPEC __declspec(dllexport)
+#  else
+#    define DECLSPEC __declspec(dllimport)
+#  endif
+#else // non windows
+#  define DECLSPEC
+#endif
+
+namespace mathfunctions {
+double DECLSPEC sqrt(double x);
+}
diff --git a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step11/MathFunctions/mysqrt.cxx
similarity index 50%
copy from Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
copy to Tests/Tutorial/Step11/MathFunctions/mysqrt.cxx
index 458ed63..96d9421 100644
--- a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step11/MathFunctions/mysqrt.cxx
@@ -1,12 +1,13 @@
 #include "MathFunctions.h"
-#include "TutorialConfig.h"
-#include <stdio.h>
+#include <iostream>
 
 // include the generated table
 #include "Table.h"
 
-#include <math.h>
+#include <cmath>
 
+namespace mathfunctions {
+namespace detail {
 // a hack square root calculation using simple operations
 double mysqrt(double x)
 {
@@ -14,27 +15,31 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
   // if we have both log and exp then use them
-  double delta;
-
+#if defined(HAVE_LOG) && defined(HAVE_EXP)
+  double result = exp(log(x) * 0.5);
+  std::cout << "Computing sqrt of " << x << " to be " << result << " using log"
+            << std::endl;
+#else
   // use the table to help find an initial value
-  result = x;
+  double result = x;
   if (x >= 1 && x < 10) {
     result = sqrtTable[static_cast<int>(x)];
   }
 
+  // if we have both log and exp then use them
+
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
-
+#endif
   return result;
 }
+}
+}
diff --git a/Tests/Tutorial/Step11/MathFunctions/mysqrt.h b/Tests/Tutorial/Step11/MathFunctions/mysqrt.h
new file mode 100644
index 0000000..e1c42ef
--- /dev/null
+++ b/Tests/Tutorial/Step11/MathFunctions/mysqrt.h
@@ -0,0 +1,6 @@
+
+namespace mathfunctions {
+namespace detail {
+double mysqrt(double x);
+}
+}
diff --git a/Tests/Tutorial/Step2/TutorialConfig.h.in b/Tests/Tutorial/Step11/TutorialConfig.h.in
similarity index 59%
copy from Tests/Tutorial/Step2/TutorialConfig.h.in
copy to Tests/Tutorial/Step11/TutorialConfig.h.in
index 25a0602..8cd2fc9 100644
--- a/Tests/Tutorial/Step2/TutorialConfig.h.in
+++ b/Tests/Tutorial/Step11/TutorialConfig.h.in
@@ -1,5 +1,3 @@
-// the configured options and settings for Tutorial
+// the configured version number
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-#cmakedefine USE_MYMATH
-
diff --git a/Tests/Tutorial/Step11/directions.txt b/Tests/Tutorial/Step11/directions.txt
new file mode 100644
index 0000000..ebb5def
--- /dev/null
+++ b/Tests/Tutorial/Step11/directions.txt
@@ -0,0 +1,104 @@
+# 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.
diff --git a/Tests/Tutorial/Step11/tutorial.cxx b/Tests/Tutorial/Step11/tutorial.cxx
new file mode 100644
index 0000000..3768855
--- /dev/null
+++ b/Tests/Tutorial/Step11/tutorial.cxx
@@ -0,0 +1,25 @@
+// A simple program that computes the square root of a number
+#include <cmath>
+#include <iostream>
+#include <string>
+
+#include "MathFunctions.h"
+#include "TutorialConfig.h"
+
+int main(int argc, char* argv[])
+{
+  if (argc < 2) {
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
+    return 1;
+  }
+
+  double inputValue = std::stod(argv[1]);
+
+  const double outputValue = mathfunctions::sqrt(inputValue);
+
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
+  return 0;
+}
diff --git a/Tests/Tutorial/Step2/CMakeLists.txt b/Tests/Tutorial/Step2/CMakeLists.txt
index cf1d30e..48afaa3 100644
--- a/Tests/Tutorial/Step2/CMakeLists.txt
+++ b/Tests/Tutorial/Step2/CMakeLists.txt
@@ -1,31 +1,25 @@
-cmake_minimum_required (VERSION 2.6)
-project (Tutorial)
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
 
-# The version number.
-set (Tutorial_VERSION_MAJOR 1)
-set (Tutorial_VERSION_MINOR 0)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
 
-# should we use our own math functions
-option(USE_MYMATH "Use tutorial provided math implementation" ON)
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
 
 # configure a header file to pass some of the CMake settings
 # to the source code
-configure_file (
+configure_file(
   "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
   "${PROJECT_BINARY_DIR}/TutorialConfig.h"
   )
 
+# add the executable
+add_executable(Tutorial tutorial.cxx)
+
 # add the binary tree to the search path for include files
 # so that we will find TutorialConfig.h
-include_directories ("${PROJECT_BINARY_DIR}")
-
-# add the MathFunctions library?
-if (USE_MYMATH)
-  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
-  add_subdirectory (MathFunctions)
-  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
-endif ()
-
-# add the executable
-add_executable (Tutorial tutorial.cxx)
-target_link_libraries (Tutorial  ${EXTRA_LIBS})
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
diff --git a/Tests/Tutorial/Step2/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step2/MathFunctions/mysqrt.cxx
index 2710f92..7d9379e 100644
--- a/Tests/Tutorial/Step2/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step2/MathFunctions/mysqrt.cxx
@@ -1,5 +1,5 @@
 #include "MathFunctions.h"
-#include <stdio.h>
+#include <iostream>
 
 // a hack square root calculation using simple operations
 double mysqrt(double x)
@@ -8,19 +8,16 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-  double delta;
-  result = x;
+  double result = x;
 
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
   return result;
 }
diff --git a/Tests/Tutorial/Step2/TutorialConfig.h.in b/Tests/Tutorial/Step2/TutorialConfig.h.in
index 25a0602..5395a06 100644
--- a/Tests/Tutorial/Step2/TutorialConfig.h.in
+++ b/Tests/Tutorial/Step2/TutorialConfig.h.in
@@ -1,5 +1,4 @@
 // the configured options and settings for Tutorial
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-#cmakedefine USE_MYMATH
 
diff --git a/Tests/Tutorial/Step2/directions.txt b/Tests/Tutorial/Step2/directions.txt
new file mode 100644
index 0000000..bb6662c
--- /dev/null
+++ b/Tests/Tutorial/Step2/directions.txt
@@ -0,0 +1,102 @@
+# Adding a Library #
+
+Now we will add a library to our project. This library will contain our own
+implementation for computing the square root of a number. The executable can
+then use this library instead of the standard square root function provided by
+the compiler.
+
+For this tutorial we will put the library into a subdirectory
+called MathFunctions. It will have the following one line CMakeLists file:
+
+  add_library(MathFunctions mysqrt.cxx)
+
+The source file mysqrt.cxx has one function called mysqrt that provides similar
+functionality to the compiler’s sqrt function. To make use of the new library
+we add an add_subdirectory call in the top-level CMakeLists file so that the
+library will get built. We add the new library to the executable, and add the
+MathFunctions as an include directory so that mqsqrt.h header file can be
+found. The last few lines of the top-level CMakeLists file now look like:
+
+
+  add_subdirectory(MathFunctions)
+
+  #add the executable
+  add_executable(Tutorial tutorial.cxx)
+
+  target_link_libraries(Tutorial ${EXTRA_LIBS})
+
+
+Now let us make the MathFunctions library optional. While for the tutorial
+there really isn’t any need to do so, but with larger projects this is a common
+occurrence. The first step is to add an option to the top-level CMakeLists file.
+
+  option (USE_MYMATH
+          "Use tutorial provided math implementation" ON)
+
+This will show up in CMake GUI and ccmake with a default value of ON that can
+be changed by the user. This setting will be stored so that the user does not
+need to set the value each time they run CMake on this build directory.
+
+The next change is to make building and linking the MathFunctions library
+conditional. To do this we change the top-level CMakeLists file to look like
+the following:
+
+  cmake_minimum_required(VERSION 3.3)
+  project(Tutorial)
+
+  set(CMAKE_CXX_STANDARD 11)
+  set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+  # the version number.
+  set(Tutorial_VERSION_MAJOR 1)
+  set(Tutorial_VERSION_MINOR 0)
+
+  # configure a header file to pass some of the CMake settings
+  # to the source code
+  configure_file(
+    "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+    "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+    )
+
+  # should we use our own math functions
+  option(USE_MYMATH "Use tutorial provided math implementation" ON)
+
+  # add the MathFunctions library?
+  if(USE_MYMATH)
+    add_subdirectory(MathFunctions)
+    list(APPEND EXTRA_LIBS MathFunctions)
+    list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
+  endif(USE_MYMATH)
+
+  # add the executable
+  add_executable(Tutorial tutorial.cxx)
+
+  target_link_libraries(Tutorial ${EXTRA_LIBS})
+
+  # add the binary tree to the search path for include files
+  # so that we will find TutorialConfig.h
+  target_include_directories(Tutorial PUBLIC
+                             "${PROJECT_BINARY_DIR}"
+                             ${EXTRA_INCLUDES}
+                             )
+
+Note the use of the variables EXTRA_LIBS, and EXTRA_INCLUDES to collect
+up any optional libraries to later be linked into the executable. This is a
+classic approach when dealing with many optional components, we will cover the
+modern approach in the next step. For now the corresponding changes to the
+source code are fairly straightforward and leave us with:
+
+  #ifdef USE_MYMATH
+    double outputValue = mysqrt(inputValue);
+  #else
+    double outputValue = sqrt(inputValue);
+  #endif
+
+Since the source code now requires USE_MYMATH we can add it to the
+TutorialConfig.h.in. Simply add the following line:
+  #cmakedefine USE_MYMATH
+
+Run cmake or cmake-gui to configure the project and then build it with your
+chosen build tool and then run the built Tutorial executable.
+
+Which function gives better results, Step1’s sqrt or Step2’s mysqrt?
diff --git a/Tests/Tutorial/Step2/tutorial.cxx b/Tests/Tutorial/Step2/tutorial.cxx
index 37f6ac4..75b7d67 100644
--- a/Tests/Tutorial/Step2/tutorial.cxx
+++ b/Tests/Tutorial/Step2/tutorial.cxx
@@ -1,33 +1,23 @@
 // A simple program that computes the square root of a number
-#include "TutorialConfig.h"
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
+#include <cmath>
+#include <iostream>
+#include <string>
 
-#ifdef USE_MYMATH
-#  include "MathFunctions.h"
-#endif
+#include "TutorialConfig.h"
 
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
-    fprintf(stdout, "%s Version %d.%d\n", argv[0], Tutorial_VERSION_MAJOR,
-            Tutorial_VERSION_MINOR);
-    fprintf(stdout, "Usage: %s number\n", argv[0]);
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
-  double inputValue = atof(argv[1]);
-  double outputValue = 0;
-
-  if (inputValue >= 0) {
-#ifdef USE_MYMATH
-    outputValue = mysqrt(inputValue);
-#else
-    outputValue = sqrt(inputValue);
-#endif
-  }
+  double inputValue = std::stod(argv[1]);
 
-  fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
+  double outputValue = sqrt(inputValue);
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
   return 0;
 }
diff --git a/Tests/Tutorial/Step3/CMakeLists.txt b/Tests/Tutorial/Step3/CMakeLists.txt
index 762302b..f904ea7 100644
--- a/Tests/Tutorial/Step3/CMakeLists.txt
+++ b/Tests/Tutorial/Step3/CMakeLists.txt
@@ -1,68 +1,38 @@
-cmake_minimum_required (VERSION 2.6)
-project (Tutorial)
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
 
-# The version number.
-set (Tutorial_VERSION_MAJOR 1)
-set (Tutorial_VERSION_MINOR 0)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
 
 # should we use our own math functions
 option(USE_MYMATH "Use tutorial provided math implementation" ON)
 
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
 # configure a header file to pass some of the CMake settings
 # to the source code
-configure_file (
+configure_file(
   "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
   "${PROJECT_BINARY_DIR}/TutorialConfig.h"
   )
 
-# add the binary tree to the search path for include files
-# so that we will find TutorialConfig.h
-include_directories ("${PROJECT_BINARY_DIR}")
-
 # add the MathFunctions library?
-if (USE_MYMATH)
-  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
-  add_subdirectory (MathFunctions)
-  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
-endif ()
+if(USE_MYMATH)
+  add_subdirectory(MathFunctions)
+  list(APPEND EXTRA_LIBS MathFunctions)
+  list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
+endif(USE_MYMATH)
 
 # add the executable
-add_executable (Tutorial tutorial.cxx)
-target_link_libraries (Tutorial  ${EXTRA_LIBS})
-
-# add the install targets
-install (TARGETS Tutorial DESTINATION bin)
-install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  DESTINATION include)
-
-
-# enable testing
-enable_testing ()
-
-# does the application run
-add_test (TutorialRuns Tutorial 25)
+add_executable(Tutorial tutorial.cxx)
 
-# does it sqrt of 25
-add_test (TutorialComp25 Tutorial 25)
-set_tests_properties (TutorialComp25
-  PROPERTIES PASS_REGULAR_EXPRESSION "25 is 5"
-  )
-
-# does it handle negative numbers
-add_test (TutorialNegative Tutorial -25)
-set_tests_properties (TutorialNegative
-  PROPERTIES PASS_REGULAR_EXPRESSION "-25 is 0"
-  )
-
-# does it handle small numbers
-add_test (TutorialSmall Tutorial 0.0001)
-set_tests_properties (TutorialSmall
-  PROPERTIES PASS_REGULAR_EXPRESSION "0.0001 is 0.01"
-  )
+target_link_libraries(Tutorial ${EXTRA_LIBS})
 
-# does the usage message work?
-add_test (TutorialUsage Tutorial)
-set_tests_properties (TutorialUsage
-  PROPERTIES
-  PASS_REGULAR_EXPRESSION "Usage:.*number"
-  )
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           ${EXTRA_INCLUDES}
+                           )
diff --git a/Tests/Tutorial/Step3/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step3/MathFunctions/CMakeLists.txt
index f386036..8b443a6 100644
--- a/Tests/Tutorial/Step3/MathFunctions/CMakeLists.txt
+++ b/Tests/Tutorial/Step3/MathFunctions/CMakeLists.txt
@@ -1,4 +1 @@
 add_library(MathFunctions mysqrt.cxx)
-
-install (TARGETS MathFunctions DESTINATION bin)
-install (FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step3/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step3/MathFunctions/mysqrt.cxx
index 2710f92..7d9379e 100644
--- a/Tests/Tutorial/Step3/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step3/MathFunctions/mysqrt.cxx
@@ -1,5 +1,5 @@
 #include "MathFunctions.h"
-#include <stdio.h>
+#include <iostream>
 
 // a hack square root calculation using simple operations
 double mysqrt(double x)
@@ -8,19 +8,16 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-  double delta;
-  result = x;
+  double result = x;
 
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
   return result;
 }
diff --git a/Tests/Tutorial/Step3/directions.txt b/Tests/Tutorial/Step3/directions.txt
new file mode 100644
index 0000000..54d0318
--- /dev/null
+++ b/Tests/Tutorial/Step3/directions.txt
@@ -0,0 +1,26 @@
+# Adding Usage Requirements for Library #
+
+Usage requirements allow for far better control over a library / executable's
+link and include line. While also giving more control over the transitive
+property of targets inside CMake. The primary commands that leverage usage
+requirements are:
+
+  - target_compile_definitions
+  - target_compile_options
+  - target_include_directories
+  - target_link_libraries
+
+First up is MathFunctions. We first state that anybody linking to MathFunctions
+needs to include the current source directory, while MathFunctions itself
+doesn't. So this can become an INTERFACE usage requirement.
+
+Remember INTERFACE means things that consumers require but the producer doesn't.
+
+  target_include_directories(MathFunctions
+            INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
+
+Now that we've specified usage requirements for MathFunctions we can safely remove
+our uses of the EXTRA_INCLUDES variable.
+
+Run cmake or cmake-gui to configure the project and then build it with your
+chosen build tool.
diff --git a/Tests/Tutorial/Step3/tutorial.cxx b/Tests/Tutorial/Step3/tutorial.cxx
index 37f6ac4..1d5742d 100644
--- a/Tests/Tutorial/Step3/tutorial.cxx
+++ b/Tests/Tutorial/Step3/tutorial.cxx
@@ -1,8 +1,9 @@
 // A simple program that computes the square root of a number
+#include <cmath>
+#include <iostream>
+#include <string>
+
 #include "TutorialConfig.h"
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
 
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
@@ -11,23 +12,21 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
-    fprintf(stdout, "%s Version %d.%d\n", argv[0], Tutorial_VERSION_MAJOR,
-            Tutorial_VERSION_MINOR);
-    fprintf(stdout, "Usage: %s number\n", argv[0]);
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
-  double inputValue = atof(argv[1]);
-  double outputValue = 0;
+  double inputValue = std::stod(argv[1]);
 
-  if (inputValue >= 0) {
 #ifdef USE_MYMATH
-    outputValue = mysqrt(inputValue);
+  double outputValue = mysqrt(inputValue);
 #else
-    outputValue = sqrt(inputValue);
+  double outputValue = sqrt(inputValue);
 #endif
-  }
 
-  fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
   return 0;
 }
diff --git a/Tests/Tutorial/Step4/CMakeLists.txt b/Tests/Tutorial/Step4/CMakeLists.txt
index 6994aa1..34eab55 100644
--- a/Tests/Tutorial/Step4/CMakeLists.txt
+++ b/Tests/Tutorial/Step4/CMakeLists.txt
@@ -1,68 +1,36 @@
-cmake_minimum_required (VERSION 2.6)
-project (Tutorial)
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
 
-# The version number.
-set (Tutorial_VERSION_MAJOR 1)
-set (Tutorial_VERSION_MINOR 0)
-
-# does this system provide the log and exp functions?
-include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
-check_function_exists (log HAVE_LOG)
-check_function_exists (exp HAVE_EXP)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
 
 # should we use our own math functions
 option(USE_MYMATH "Use tutorial provided math implementation" ON)
 
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
 # configure a header file to pass some of the CMake settings
 # to the source code
-configure_file (
+configure_file(
   "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
   "${PROJECT_BINARY_DIR}/TutorialConfig.h"
   )
 
-# add the binary tree to the search path for include files
-# so that we will find TutorialConfig.h
-include_directories ("${PROJECT_BINARY_DIR}")
-
 # add the MathFunctions library?
-if (USE_MYMATH)
-  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
-  add_subdirectory (MathFunctions)
-  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
-endif ()
+if(USE_MYMATH)
+  add_subdirectory(MathFunctions)
+  list(APPEND EXTRA_LIBS MathFunctions)
+endif(USE_MYMATH)
 
 # add the executable
-add_executable (Tutorial tutorial.cxx)
-target_link_libraries (Tutorial  ${EXTRA_LIBS})
-
-# add the install targets
-install (TARGETS Tutorial DESTINATION bin)
-install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  DESTINATION include)
-
-# enable testing
-enable_testing ()
+add_executable(Tutorial tutorial.cxx)
 
-# does the application run
-add_test (TutorialRuns Tutorial 25)
-
-# does the usage message work?
-add_test (TutorialUsage Tutorial)
-set_tests_properties (TutorialUsage
-  PROPERTIES
-  PASS_REGULAR_EXPRESSION "Usage:.*number"
-  )
-
-#define a macro to simplify adding tests
-macro (do_test arg result)
-  add_test (TutorialComp${arg} Tutorial ${arg})
-  set_tests_properties (TutorialComp${arg}
-    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
-    )
-endmacro ()
-
-# do a bunch of result based tests
-do_test (25 "25 is 5")
-do_test (-25 "-25 is 0")
-do_test (0.0001 "0.0001 is 0.01")
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
 
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
diff --git a/Tests/Tutorial/Step4/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step4/MathFunctions/CMakeLists.txt
index f386036..0515852 100644
--- a/Tests/Tutorial/Step4/MathFunctions/CMakeLists.txt
+++ b/Tests/Tutorial/Step4/MathFunctions/CMakeLists.txt
@@ -1,4 +1,7 @@
 add_library(MathFunctions mysqrt.cxx)
 
-install (TARGETS MathFunctions DESTINATION bin)
-install (FILES MathFunctions.h DESTINATION include)
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+target_include_directories(MathFunctions
+          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+          )
diff --git a/Tests/Tutorial/Step4/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step4/MathFunctions/mysqrt.cxx
index 6ca264f..7d9379e 100644
--- a/Tests/Tutorial/Step4/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step4/MathFunctions/mysqrt.cxx
@@ -1,8 +1,5 @@
 #include "MathFunctions.h"
-#include "TutorialConfig.h"
-#include <stdio.h>
-
-#include <math.h>
+#include <iostream>
 
 // a hack square root calculation using simple operations
 double mysqrt(double x)
@@ -11,26 +8,16 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
-// if we have both log and exp then use them
-#if defined(HAVE_LOG) && defined(HAVE_EXP)
-  result = exp(log(x) * 0.5);
-  fprintf(stdout, "Computing sqrt of %g to be %g using log\n", x, result);
-#else
-  double delta;
-  result = x;
+  double result = x;
 
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
-#endif
   return result;
 }
diff --git a/Tests/Tutorial/Step4/TutorialConfig.h.in b/Tests/Tutorial/Step4/TutorialConfig.h.in
index a091265..25a0602 100644
--- a/Tests/Tutorial/Step4/TutorialConfig.h.in
+++ b/Tests/Tutorial/Step4/TutorialConfig.h.in
@@ -3,7 +3,3 @@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
 #cmakedefine USE_MYMATH
 
-// does the platform provide exp and log functions?
-#cmakedefine HAVE_LOG
-#cmakedefine HAVE_EXP
-
diff --git a/Tests/Tutorial/Step4/directions.txt b/Tests/Tutorial/Step4/directions.txt
new file mode 100644
index 0000000..91e4043
--- /dev/null
+++ b/Tests/Tutorial/Step4/directions.txt
@@ -0,0 +1,72 @@
+# Installing and Testing #
+
+Now we can start adding testing support and install rules to our project.
+
+The install rules are fairly simple; for MathFunctions we install the library
+and header file, for the application we install the executable and configured
+header.
+
+So to MathFunctions/CMakeLists.txt we add:
+
+  install (TARGETS MathFunctions DESTINATION bin)
+  install (FILES MathFunctions.h DESTINATION include)
+
+And the to top-level CMakeLists.txt we add:
+
+  install(TARGETS Tutorial DESTINATION bin)
+  install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+          DESTINATION include
+          )
+
+That is all that is needed to create a basic local install of the tutorial.
+
+Run cmake or cmake-gui to configure the project and then build it with your
+chosen build tool. Then build the “install” target by typing 'make install'
+from the command line or build the INSTALL target from an IDE. This will
+install the appropriate header files, libraries, and executables.
+
+Verify that the installed Tutorial runs. Note: The CMake variable
+CMAKE_INSTALL_PREFIX is used to determine the root of where the files will
+be installed.
+
+Next let's test our application. Adding testing is an easy process. At the
+end of the top-level CMakeLists file we can add a number of basic tests to
+verify that the application is working correctly.
+
+  # enable testing
+  enable_testing()
+
+  # does the application run
+  add_test(NAME Runs COMMAND Tutorial 25)
+
+  # does the usage message work?
+  add_test(NAME Usage COMMAND Tutorial)
+  set_tests_properties(Usage
+    PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
+    )
+
+  # define a function to simplify adding tests
+  function(do_test target arg result)
+    add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+    set_tests_properties(Comp${arg}
+      PROPERTIES PASS_REGULAR_EXPRESSION ${result}
+      )
+  endfunction(do_test)
+
+  # do a bunch of result based tests
+  do_test(Tutorial 25 "25 is 5")
+  do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+  do_test(Tutorial 0.0001 "0.0001 is 0.01")
+
+The first test simply verifies that the application runs, does not segfault or
+otherwise crash, and has a zero return value. This is the basic form of a CTest
+test.
+
+The Usage test uses a regular expression to verify that the usage message
+is printed when an incorrect number of arguments are provided.
+
+Lastly, we have a function called do_test that simplifies running the
+application and verifying that the computed square root is correct for given
+input.
+
+To run tests, cd to the binary directory and run “ctest -N” and “ctest -VV”.
diff --git a/Tests/Tutorial/Step4/tutorial.cxx b/Tests/Tutorial/Step4/tutorial.cxx
index 37f6ac4..1d5742d 100644
--- a/Tests/Tutorial/Step4/tutorial.cxx
+++ b/Tests/Tutorial/Step4/tutorial.cxx
@@ -1,8 +1,9 @@
 // A simple program that computes the square root of a number
+#include <cmath>
+#include <iostream>
+#include <string>
+
 #include "TutorialConfig.h"
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
 
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
@@ -11,23 +12,21 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
-    fprintf(stdout, "%s Version %d.%d\n", argv[0], Tutorial_VERSION_MAJOR,
-            Tutorial_VERSION_MINOR);
-    fprintf(stdout, "Usage: %s number\n", argv[0]);
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
-  double inputValue = atof(argv[1]);
-  double outputValue = 0;
+  double inputValue = std::stod(argv[1]);
 
-  if (inputValue >= 0) {
 #ifdef USE_MYMATH
-    outputValue = mysqrt(inputValue);
+  double outputValue = mysqrt(inputValue);
 #else
-    outputValue = sqrt(inputValue);
+  double outputValue = sqrt(inputValue);
 #endif
-  }
 
-  fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
   return 0;
 }
diff --git a/Tests/Tutorial/Step5/CMakeLists.txt b/Tests/Tutorial/Step5/CMakeLists.txt
index e40b676..63e5410 100644
--- a/Tests/Tutorial/Step5/CMakeLists.txt
+++ b/Tests/Tutorial/Step5/CMakeLists.txt
@@ -1,72 +1,70 @@
-cmake_minimum_required (VERSION 2.6)
-project (Tutorial)
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
 
-# The version number.
-set (Tutorial_VERSION_MAJOR 1)
-set (Tutorial_VERSION_MINOR 0)
-
-# does this system provide the log and exp functions?
-include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
-check_function_exists (log HAVE_LOG)
-check_function_exists (exp HAVE_EXP)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
 
 # should we use our own math functions
 option(USE_MYMATH "Use tutorial provided math implementation" ON)
 
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
 # configure a header file to pass some of the CMake settings
 # to the source code
-configure_file (
+configure_file(
   "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
   "${PROJECT_BINARY_DIR}/TutorialConfig.h"
   )
 
-# add the binary tree to the search path for include files
-# so that we will find TutorialConfig.h
-include_directories ("${PROJECT_BINARY_DIR}")
-
 # add the MathFunctions library?
-if (USE_MYMATH)
-  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
-  add_subdirectory (MathFunctions)
-  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
-endif ()
+if(USE_MYMATH)
+  add_subdirectory(MathFunctions)
+  list(APPEND EXTRA_LIBS MathFunctions)
+endif()
 
 # add the executable
-add_executable (Tutorial tutorial.cxx)
-target_link_libraries (Tutorial  ${EXTRA_LIBS})
+add_executable(Tutorial tutorial.cxx)
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
 
 # add the install targets
-install (TARGETS Tutorial DESTINATION bin)
-install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  DESTINATION include)
+install(TARGETS Tutorial DESTINATION bin)
+install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include
+  )
 
 # enable testing
-enable_testing ()
+enable_testing()
 
 # does the application run
-add_test (TutorialRuns Tutorial 25)
+add_test(NAME Runs COMMAND Tutorial 25)
 
 # does the usage message work?
-add_test (TutorialUsage Tutorial)
-set_tests_properties (TutorialUsage
-  PROPERTIES
-  PASS_REGULAR_EXPRESSION "Usage:.*number"
+add_test(NAME Usage COMMAND Tutorial)
+set_tests_properties(Usage
+  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
   )
 
-#define a macro to simplify adding tests
-macro (do_test arg result)
-  add_test (TutorialComp${arg} Tutorial ${arg})
-  set_tests_properties (TutorialComp${arg}
+# define a function to simplify adding tests
+function(do_test target arg result)
+  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+  set_tests_properties(Comp${arg}
     PROPERTIES PASS_REGULAR_EXPRESSION ${result}
     )
-endmacro ()
+endfunction(do_test)
 
 # do a bunch of result based tests
-do_test (4 "4 is 2")
-do_test (9 "9 is 3")
-do_test (5 "5 is 2.236")
-do_test (7 "7 is 2.645")
-do_test (25 "25 is 5")
-do_test (-25 "-25 is 0")
-do_test (0.0001 "0.0001 is 0.01")
-
+do_test(Tutorial 4 "4 is 2")
+do_test(Tutorial 9 "9 is 3")
+do_test(Tutorial 5 "5 is 2.236")
+do_test(Tutorial 7 "7 is 2.645")
+do_test(Tutorial 25 "25 is 5")
+do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial 0.0001 "0.0001 is 0.01")
diff --git a/Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt
index 453a463..11cf412 100644
--- a/Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt
+++ b/Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt
@@ -1,17 +1,10 @@
-# first we add the executable that generates the table
-# add the binary tree directory to the search path for include files
-include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
+add_library(MathFunctions mysqrt.cxx)
 
-add_executable(MakeTable MakeTable.cxx )
-# add the command to generate the source code
-add_custom_command (
-  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-  DEPENDS MakeTable
-  )
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+target_include_directories(MathFunctions
+          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+          )
 
-# add the main library
-add_library(MathFunctions mysqrt.cxx ${CMAKE_CURRENT_BINARY_DIR}/Table.h  )
-
-install (TARGETS MathFunctions DESTINATION bin)
-install (FILES MathFunctions.h DESTINATION include)
+install(TARGETS MathFunctions DESTINATION lib)
+install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step5/MathFunctions/MakeTable.cxx b/Tests/Tutorial/Step5/MathFunctions/MakeTable.cxx
index cebd50f..ee58556 100644
--- a/Tests/Tutorial/Step5/MathFunctions/MakeTable.cxx
+++ b/Tests/Tutorial/Step5/MathFunctions/MakeTable.cxx
@@ -1,32 +1,25 @@
 // A simple program that builds a sqrt table
-#include <math.h>
-#include <stdio.h>
+#include <cmath>
+#include <fstream>
+#include <iostream>
 
 int main(int argc, char* argv[])
 {
-  int i;
-  double result;
-
   // make sure we have enough arguments
   if (argc < 2) {
     return 1;
   }
 
-  // open the output file
-  FILE* fout = fopen(argv[1], "w");
-  if (!fout) {
-    return 1;
+  std::ofstream fout(argv[1], std::ios_base::out);
+  const bool fileOpen = fout.is_open();
+  if (fileOpen) {
+    fout << "double sqrtTable[] = {" << std::endl;
+    for (int i = 0; i < 10; ++i) {
+      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+    }
+    // close the table with a zero
+    fout << "0};" << std::endl;
+    fout.close();
   }
-
-  // create a source file with a table of square roots
-  fprintf(fout, "double sqrtTable[] = {\n");
-  for (i = 0; i < 10; ++i) {
-    result = sqrt(static_cast<double>(i));
-    fprintf(fout, "%g,\n", result);
-  }
-
-  // close the table with a zero
-  fprintf(fout, "0};\n");
-  fclose(fout);
-  return 0;
+  return fileOpen ? 0 : 1; // return 0 if wrote the file
 }
diff --git a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
index 458ed63..7d9379e 100644
--- a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
@@ -1,11 +1,5 @@
 #include "MathFunctions.h"
-#include "TutorialConfig.h"
-#include <stdio.h>
-
-// include the generated table
-#include "Table.h"
-
-#include <math.h>
+#include <iostream>
 
 // a hack square root calculation using simple operations
 double mysqrt(double x)
@@ -14,27 +8,16 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
-  // if we have both log and exp then use them
-  double delta;
-
-  // use the table to help find an initial value
-  result = x;
-  if (x >= 1 && x < 10) {
-    result = sqrtTable[static_cast<int>(x)];
-  }
+  double result = x;
 
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
-
   return result;
 }
diff --git a/Tests/Tutorial/Step5/TutorialConfig.h.in b/Tests/Tutorial/Step5/TutorialConfig.h.in
index a091265..25a0602 100644
--- a/Tests/Tutorial/Step5/TutorialConfig.h.in
+++ b/Tests/Tutorial/Step5/TutorialConfig.h.in
@@ -3,7 +3,3 @@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
 #cmakedefine USE_MYMATH
 
-// does the platform provide exp and log functions?
-#cmakedefine HAVE_LOG
-#cmakedefine HAVE_EXP
-
diff --git a/Tests/Tutorial/Step5/directions.txt b/Tests/Tutorial/Step5/directions.txt
new file mode 100644
index 0000000..e6f5197
--- /dev/null
+++ b/Tests/Tutorial/Step5/directions.txt
@@ -0,0 +1,69 @@
+# Adding System Introspection #
+
+Let us consider adding some code to our project that depends on features the
+target platform may not have. For this example, we will add some code that
+depends on whether or not the target platform has the log and exp functions. Of
+course almost every platform has these functions but for this tutorial assume
+that they are not common.
+
+If the platform has log and exp then we will use them to compute the square
+root in the mysqrt function. We first test for the availability of these
+functions using the CheckSymbolExists.cmake macro in the top-level CMakeLists
+file as follows:
+
+  # does this system provide the log and exp functions?
+  include(CheckSymbolExists)
+  set(CMAKE_REQUIRED_LIBRARIES "m")
+  check_symbol_exists(log "math.h" HAVE_LOG)
+  check_symbol_exists(exp "math.h" HAVE_EXP)
+
+Now let's add these defines to TutorialConfig.h.in so that we can use them
+from mysqrt.cxx:
+
+  // does the platform provide exp and log functions?
+  #cmakedefine HAVE_LOG
+  #cmakedefine HAVE_EXP
+
+Modify mysqrt.cxx to include math.h. Next, in the mysqrt function we can
+provide an alternate implementation based on log and exp if they are available
+on the system using the following code:
+
+  // if we have both log and exp then use them
+  #if defined(HAVE_LOG) && defined (HAVE_EXP)
+    double result = exp(log(x)*0.5);
+    std::cout << "Computing sqrt of " << x << " to be " << result << " using log" << std::endl;
+  #else
+    ...
+
+Run cmake or cmake-gui to configure the project and then build it with your
+chosen build tool.
+
+You will notice that even though HAVE_LOG and HAVE_EXP are both defined mysqrt
+isn't using them. We should realize quickly that we have forgotten to include
+TutorialConfig.h in mysqrt.cxx. We will also need to update
+MathFunctions/CMakeLists.txt with where it is located.
+
+So let's go ahead and update MathFunctions/CMakeLists.txt to look like:
+
+  add_library(MathFunctions mysqrt.cxx)
+
+  target_include_directories(MathFunctions
+            INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+            PRIVATE ${Tutorial_BINARY_DIR}
+            )
+
+  install(TARGETS MathFunctions DESTINATION lib)
+  install(FILES MathFunctions.h DESTINATION include)
+
+Now all we need to do is include TutorialConfig.h in mysqrt.cxx
+
+At this point you should go ahead and build the project again.
+
+Run the built Tutorial executable. Which function gives better results now,
+Step1’s sqrt or Step5’s mysqrt?
+
+Exercise: Why is it important that we configure TutorialConfig.h.in after the
+checks for HAVE_LOG and HAVE_EXP? What would happen if we inverted the two?
+
+Exercise: Is there a better place for us to save the HAVE_LOG and HAVE_EXP
+values other than in TutorialConfig.h?
diff --git a/Tests/Tutorial/Step5/tutorial.cxx b/Tests/Tutorial/Step5/tutorial.cxx
index 37f6ac4..1d5742d 100644
--- a/Tests/Tutorial/Step5/tutorial.cxx
+++ b/Tests/Tutorial/Step5/tutorial.cxx
@@ -1,8 +1,9 @@
 // A simple program that computes the square root of a number
+#include <cmath>
+#include <iostream>
+#include <string>
+
 #include "TutorialConfig.h"
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
 
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
@@ -11,23 +12,21 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
-    fprintf(stdout, "%s Version %d.%d\n", argv[0], Tutorial_VERSION_MAJOR,
-            Tutorial_VERSION_MINOR);
-    fprintf(stdout, "Usage: %s number\n", argv[0]);
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
-  double inputValue = atof(argv[1]);
-  double outputValue = 0;
+  double inputValue = std::stod(argv[1]);
 
-  if (inputValue >= 0) {
 #ifdef USE_MYMATH
-    outputValue = mysqrt(inputValue);
+  double outputValue = mysqrt(inputValue);
 #else
-    outputValue = sqrt(inputValue);
+  double outputValue = sqrt(inputValue);
 #endif
-  }
 
-  fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
   return 0;
 }
diff --git a/Tests/Tutorial/Step6/CMakeLists.txt b/Tests/Tutorial/Step6/CMakeLists.txt
index 0fb7cac..503a312 100644
--- a/Tests/Tutorial/Step6/CMakeLists.txt
+++ b/Tests/Tutorial/Step6/CMakeLists.txt
@@ -1,78 +1,76 @@
-cmake_minimum_required (VERSION 2.6)
-project (Tutorial)
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
 
-# The version number.
-set (Tutorial_VERSION_MAJOR 1)
-set (Tutorial_VERSION_MINOR 0)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
 
 # does this system provide the log and exp functions?
-include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
-check_function_exists (log HAVE_LOG)
-check_function_exists (exp HAVE_EXP)
+include(CheckSymbolExists)
+set(CMAKE_REQUIRED_LIBRARIES "m")
+check_symbol_exists(log "math.h" HAVE_LOG)
+check_symbol_exists(exp "math.h" HAVE_EXP)
 
 # should we use our own math functions
 option(USE_MYMATH "Use tutorial provided math implementation" ON)
 
 # configure a header file to pass some of the CMake settings
 # to the source code
-configure_file (
+configure_file(
   "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
   "${PROJECT_BINARY_DIR}/TutorialConfig.h"
   )
 
-# add the binary tree to the search path for include files
-# so that we will find TutorialConfig.h
-include_directories ("${PROJECT_BINARY_DIR}")
-
 # add the MathFunctions library?
-if (USE_MYMATH)
-  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
-  add_subdirectory (MathFunctions)
-  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
-endif ()
+if(USE_MYMATH)
+  add_subdirectory(MathFunctions)
+  list(APPEND EXTRA_LIBS MathFunctions)
+endif()
 
 # add the executable
-add_executable (Tutorial tutorial.cxx)
-target_link_libraries (Tutorial  ${EXTRA_LIBS})
+add_executable(Tutorial tutorial.cxx)
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
 
 # add the install targets
-install (TARGETS Tutorial DESTINATION bin)
-install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  DESTINATION include)
+install(TARGETS Tutorial DESTINATION bin)
+install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include
+  )
 
 # enable testing
-enable_testing ()
+enable_testing()
 
 # does the application run
-add_test (TutorialRuns Tutorial 25)
+add_test(NAME Runs COMMAND Tutorial 25)
 
 # does the usage message work?
-add_test (TutorialUsage Tutorial)
-set_tests_properties (TutorialUsage
-  PROPERTIES
-  PASS_REGULAR_EXPRESSION "Usage:.*number"
+add_test(NAME Usage COMMAND Tutorial)
+set_tests_properties(Usage
+  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
   )
 
-#define a macro to simplify adding tests
-macro (do_test arg result)
-  add_test (TutorialComp${arg} Tutorial ${arg})
-  set_tests_properties (TutorialComp${arg}
+# define a function to simplify adding tests
+function(do_test target arg result)
+  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+  set_tests_properties(Comp${arg}
     PROPERTIES PASS_REGULAR_EXPRESSION ${result}
     )
-endmacro ()
+endfunction(do_test)
 
 # do a bunch of result based tests
-do_test (4 "4 is 2")
-do_test (9 "9 is 3")
-do_test (5 "5 is 2.236")
-do_test (7 "7 is 2.645")
-do_test (25 "25 is 5")
-do_test (-25 "-25 is 0")
-do_test (0.0001 "0.0001 is 0.01")
-
-# build a CPack driven installer package
-include (InstallRequiredSystemLibraries)
-set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
-set (CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
-set (CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
-include (CPack)
+do_test(Tutorial 4 "4 is 2")
+do_test(Tutorial 9 "9 is 3")
+do_test(Tutorial 5 "5 is 2.236")
+do_test(Tutorial 7 "7 is 2.645")
+do_test(Tutorial 25 "25 is 5")
+do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial 0.0001 "0.0001 is 0.01")
diff --git a/Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt
index 70a35f6..2946075 100644
--- a/Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt
+++ b/Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt
@@ -1,24 +1,14 @@
-# first we add the executable that generates the table
-add_executable(MakeTable MakeTable.cxx)
-
-# add the command to generate the source code
-add_custom_command (
-  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-  DEPENDS MakeTable
-  COMMAND MakeTable
-  ARGS ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-  )
-
-set_source_files_properties (
-  mysqrt.cxx PROPERTIES
-  OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-  )
+add_library(MathFunctions mysqrt.cxx)
 
-# add the binary tree directory to the search path for include files
-include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
+# TutorialConfig.h include is an implementation detail
 
-# add the main library
-add_library(MathFunctions mysqrt.cxx)
+target_include_directories(MathFunctions
+          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+          PRIVATE ${Tutorial_BINARY_DIR}
+          )
 
-install (TARGETS MathFunctions DESTINATION bin)
-install (FILES MathFunctions.h DESTINATION include)
+install(TARGETS MathFunctions DESTINATION lib)
+install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step6/MathFunctions/MakeTable.cxx b/Tests/Tutorial/Step6/MathFunctions/MakeTable.cxx
index cebd50f..ee58556 100644
--- a/Tests/Tutorial/Step6/MathFunctions/MakeTable.cxx
+++ b/Tests/Tutorial/Step6/MathFunctions/MakeTable.cxx
@@ -1,32 +1,25 @@
 // A simple program that builds a sqrt table
-#include <math.h>
-#include <stdio.h>
+#include <cmath>
+#include <fstream>
+#include <iostream>
 
 int main(int argc, char* argv[])
 {
-  int i;
-  double result;
-
   // make sure we have enough arguments
   if (argc < 2) {
     return 1;
   }
 
-  // open the output file
-  FILE* fout = fopen(argv[1], "w");
-  if (!fout) {
-    return 1;
+  std::ofstream fout(argv[1], std::ios_base::out);
+  const bool fileOpen = fout.is_open();
+  if (fileOpen) {
+    fout << "double sqrtTable[] = {" << std::endl;
+    for (int i = 0; i < 10; ++i) {
+      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+    }
+    // close the table with a zero
+    fout << "0};" << std::endl;
+    fout.close();
   }
-
-  // create a source file with a table of square roots
-  fprintf(fout, "double sqrtTable[] = {\n");
-  for (i = 0; i < 10; ++i) {
-    result = sqrt(static_cast<double>(i));
-    fprintf(fout, "%g,\n", result);
-  }
-
-  // close the table with a zero
-  fprintf(fout, "0};\n");
-  fclose(fout);
-  return 0;
+  return fileOpen ? 0 : 1; // return 0 if wrote the file
 }
diff --git a/Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx
index 458ed63..b9ad20a 100644
--- a/Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx
@@ -1,11 +1,8 @@
 #include "MathFunctions.h"
 #include "TutorialConfig.h"
-#include <stdio.h>
+#include <iostream>
 
-// include the generated table
-#include "Table.h"
-
-#include <math.h>
+#include <cmath>
 
 // a hack square root calculation using simple operations
 double mysqrt(double x)
@@ -14,27 +11,23 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
   // if we have both log and exp then use them
-  double delta;
-
-  // use the table to help find an initial value
-  result = x;
-  if (x >= 1 && x < 10) {
-    result = sqrtTable[static_cast<int>(x)];
-  }
+#if defined(HAVE_LOG) && defined(HAVE_EXP)
+  double result = exp(log(x) * 0.5);
+  std::cout << "Computing sqrt of " << x << " to be " << result << " using log"
+            << std::endl;
+#else
+  double result = x;
 
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
-
+#endif
   return result;
 }
diff --git a/Tests/Tutorial/Step6/directions.txt b/Tests/Tutorial/Step6/directions.txt
new file mode 100644
index 0000000..d3e7b05
--- /dev/null
+++ b/Tests/Tutorial/Step6/directions.txt
@@ -0,0 +1,111 @@
+# Adding a Custom Command and Generated File #
+
+In this section we will show how you can add a generated source file into the
+build process of an application. For this example, we will create a table of
+precomputed square roots as part of the build process, and then compile that
+table into our application.
+
+To accomplish this, we first need a program that will generate the table. In the
+MathFunctions subdirectory a new source file named MakeTable.cxx will do just that.
+
+  // A simple program that builds a sqrt table
+  #include <iostream>
+  #include <fstream>
+  #include <cmath>
+
+  int main (int argc, char *argv[])
+  {
+    // make sure we have enough arguments
+    if (argc < 2)
+      {
+      return 1;
+      }
+
+    std::ofstream fout(argv[1],std::ios_base::out);
+    const bool fileOpen = fout.is_open();
+    if(fileOpen)
+      {
+      fout << "double sqrtTable[] = {" << std::endl;
+      for (int i = 0; i < 10; ++i)
+        {
+        fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+        }
+      // close the table with a zero
+      fout << "0};" << std::endl;
+      fout.close();
+      }
+    return fileOpen ? 0 : 1; // return 0 if wrote the file
+  }
+
+Note that the table is produced as valid C++ code and that the output filename
+is passed in as an argument.
+
+The next step is to add the appropriate commands to MathFunctions’ CMakeLists
+file to build the MakeTable executable and then run it as part of the build
+process. A few commands are needed to accomplish this, as shown below:
+
+  # first we add the executable that generates the table
+  add_executable(MakeTable MakeTable.cxx)
+
+  # add the command to generate the source code
+  add_custom_command(
+    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+    DEPENDS MakeTable
+    )
+
+  # add the main library
+  add_library(MathFunctions
+              mysqrt.cxx
+              ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+              )
+
+  target_include_directories(MathFunctions
+          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+          PUBLIC ${Tutorial_BINARY_DIR}
+                 # add the binary tree directory to the search path for include files
+                 ${CMAKE_CURRENT_BINARY_DIR}
+          )
+
+  install(TARGETS MathFunctions DESTINATION lib)
+  install(FILES MathFunctions.h DESTINATION include)
+
+First, the executable for MakeTable is added as any other executable would be
+added. Then we add a custom command that specifies how to produce Table.h by
+running MakeTable. Next we have to let CMake know that mysqrt.cxx depends on
+the generated file Table.h. This is done by adding the generated Table.h to the
+list of sources for the library MathFunctions. We also have to add the current
+binary directory to the list of include directories so that Table.h can be
+found and included by mysqrt.cxx.
+
+Now let's use the generated table. First, modify mysqrt.cxx to include Table.h.
+Next, we can rewrite the mysqrt function to use the table:
+
+  if (x <= 0)
+      {
+      return 0;
+      }
+
+  // use the table to help find an initial value
+  double result = x;
+  if (x >= 1 && x < 10)
+    {
+    result = sqrtTable[static_cast<int>(x)];
+    }
+
+  // do ten iterations
+  for (int i = 0; i < 10; ++i)
+    {
+    if (result <= 0)
+      {
+      result = 0.1;
+      }
+    double delta = x - (result*result);
+    result = result + 0.5*delta/result;
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
+    }
+
+Run cmake or cmake-gui to configure the project and then build it with your
+chosen build tool. When this project is built it will first build the MakeTable
+executable. It will then run MakeTable to produce Table.h. Finally, it will
+compile mysqrt.cxx which includes Table.h to produce the MathFunctions library.
diff --git a/Tests/Tutorial/Step6/tutorial.cxx b/Tests/Tutorial/Step6/tutorial.cxx
index 37f6ac4..1d5742d 100644
--- a/Tests/Tutorial/Step6/tutorial.cxx
+++ b/Tests/Tutorial/Step6/tutorial.cxx
@@ -1,8 +1,9 @@
 // A simple program that computes the square root of a number
+#include <cmath>
+#include <iostream>
+#include <string>
+
 #include "TutorialConfig.h"
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
 
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
@@ -11,23 +12,21 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
-    fprintf(stdout, "%s Version %d.%d\n", argv[0], Tutorial_VERSION_MAJOR,
-            Tutorial_VERSION_MINOR);
-    fprintf(stdout, "Usage: %s number\n", argv[0]);
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
-  double inputValue = atof(argv[1]);
-  double outputValue = 0;
+  double inputValue = std::stod(argv[1]);
 
-  if (inputValue >= 0) {
 #ifdef USE_MYMATH
-    outputValue = mysqrt(inputValue);
+  double outputValue = mysqrt(inputValue);
 #else
-    outputValue = sqrt(inputValue);
+  double outputValue = sqrt(inputValue);
 #endif
-  }
 
-  fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
   return 0;
 }
diff --git a/Tests/Tutorial/Step7/CMakeLists.txt b/Tests/Tutorial/Step7/CMakeLists.txt
index d9a92fb..f2d3839 100644
--- a/Tests/Tutorial/Step7/CMakeLists.txt
+++ b/Tests/Tutorial/Step7/CMakeLists.txt
@@ -1,82 +1,76 @@
-cmake_minimum_required (VERSION 2.6)
-project (Tutorial)
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
 
-# The version number.
-set (Tutorial_VERSION_MAJOR 1)
-set (Tutorial_VERSION_MINOR 0)
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
 
 # does this system provide the log and exp functions?
-include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
-check_function_exists (log HAVE_LOG)
-check_function_exists (exp HAVE_EXP)
+include(CheckSymbolExists)
+set(CMAKE_REQUIRED_LIBRARIES "m")
+check_symbol_exists(log "math.h" HAVE_LOG)
+check_symbol_exists(exp "math.h" HAVE_EXP)
 
 # should we use our own math functions
 option(USE_MYMATH "Use tutorial provided math implementation" ON)
 
 # configure a header file to pass some of the CMake settings
 # to the source code
-configure_file (
+configure_file(
   "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
   "${PROJECT_BINARY_DIR}/TutorialConfig.h"
   )
 
-# add the binary tree to the search path for include files
-# so that we will find TutorialConfig.h
-include_directories ("${PROJECT_BINARY_DIR}")
-
 # add the MathFunctions library?
-if (USE_MYMATH)
-  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
-  add_subdirectory (MathFunctions)
-  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
-endif ()
+if(USE_MYMATH)
+  add_subdirectory(MathFunctions)
+  list(APPEND EXTRA_LIBS MathFunctions)
+endif(USE_MYMATH)
 
 # add the executable
-add_executable (Tutorial tutorial.cxx)
-target_link_libraries (Tutorial  ${EXTRA_LIBS})
+add_executable(Tutorial tutorial.cxx)
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                            )
 
 # add the install targets
-install (TARGETS Tutorial DESTINATION bin)
-install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
-  DESTINATION include)
+install(TARGETS Tutorial DESTINATION bin)
+install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include
+  )
 
 # enable testing
-enable_testing ()
+enable_testing()
 
 # does the application run
-add_test (TutorialRuns Tutorial 25)
+add_test(NAME Runs COMMAND Tutorial 25)
 
 # does the usage message work?
-add_test (TutorialUsage Tutorial)
-set_tests_properties (TutorialUsage
-  PROPERTIES
-  PASS_REGULAR_EXPRESSION "Usage:.*number"
+add_test(NAME Usage COMMAND Tutorial)
+set_tests_properties(Usage
+  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
   )
 
-#define a macro to simplify adding tests
-macro (do_test arg result)
-  add_test (TutorialComp${arg} Tutorial ${arg})
-  set_tests_properties (TutorialComp${arg}
+# define a function to simplify adding tests
+function(do_test target arg result)
+  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+  set_tests_properties(Comp${arg}
     PROPERTIES PASS_REGULAR_EXPRESSION ${result}
     )
-endmacro ()
+endfunction(do_test)
 
 # do a bunch of result based tests
-do_test (4 "4 is 2")
-do_test (9 "9 is 3")
-do_test (5 "5 is 2.236")
-do_test (7 "7 is 2.645")
-do_test (25 "25 is 5")
-do_test (-25 "-25 is 0")
-do_test (0.0001 "0.0001 is 0.01")
-
-# build a CPack driven installer package
-include (InstallRequiredSystemLibraries)
-set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
-set (CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
-set (CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
-set (CPACK_PACKAGE_CONTACT       "foo at bar.org")
-include (CPack)
-
-# enable dashboard scripting
-include (CTest)
+do_test(Tutorial 4 "4 is 2")
+do_test(Tutorial 9 "9 is 3")
+do_test(Tutorial 5 "5 is 2.236")
+do_test(Tutorial 7 "7 is 2.645")
+do_test(Tutorial 25 "25 is 5")
+do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial 0.0001 "0.0001 is 0.01")
diff --git a/Tests/Tutorial/Step7/License.txt b/Tests/Tutorial/Step7/License.txt
index 673d724..c62d00b 100644
--- a/Tests/Tutorial/Step7/License.txt
+++ b/Tests/Tutorial/Step7/License.txt
@@ -1,2 +1,2 @@
 This is the open source License.txt file introduced in
-CMake/Tests/Tutorial/Step6...
+CMake/Tutorial/Step7...
diff --git a/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt
index 70a35f6..dc3eb98 100644
--- a/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt
+++ b/Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt
@@ -2,23 +2,28 @@
 add_executable(MakeTable MakeTable.cxx)
 
 # add the command to generate the source code
-add_custom_command (
+add_custom_command(
   OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
   DEPENDS MakeTable
-  COMMAND MakeTable
-  ARGS ${CMAKE_CURRENT_BINARY_DIR}/Table.h
   )
 
-set_source_files_properties (
-  mysqrt.cxx PROPERTIES
-  OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Table.h
-  )
-
-# add the binary tree directory to the search path for include files
-include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
-
 # add the main library
-add_library(MathFunctions mysqrt.cxx)
+add_library(MathFunctions
+            mysqrt.cxx
+            ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+            )
+
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
+# TutorialConfig.h include is an implementation detail
+# state that we depend on our binary dir to find Table.h
+target_include_directories(MathFunctions
+          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+          PRIVATE ${Tutorial_BINARY_DIR}
+                  ${CMAKE_CURRENT_BINARY_DIR}
+          )
 
-install (TARGETS MathFunctions DESTINATION bin)
-install (FILES MathFunctions.h DESTINATION include)
+install(TARGETS MathFunctions DESTINATION lib)
+install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step7/MathFunctions/MakeTable.cxx b/Tests/Tutorial/Step7/MathFunctions/MakeTable.cxx
index cebd50f..ee58556 100644
--- a/Tests/Tutorial/Step7/MathFunctions/MakeTable.cxx
+++ b/Tests/Tutorial/Step7/MathFunctions/MakeTable.cxx
@@ -1,32 +1,25 @@
 // A simple program that builds a sqrt table
-#include <math.h>
-#include <stdio.h>
+#include <cmath>
+#include <fstream>
+#include <iostream>
 
 int main(int argc, char* argv[])
 {
-  int i;
-  double result;
-
   // make sure we have enough arguments
   if (argc < 2) {
     return 1;
   }
 
-  // open the output file
-  FILE* fout = fopen(argv[1], "w");
-  if (!fout) {
-    return 1;
+  std::ofstream fout(argv[1], std::ios_base::out);
+  const bool fileOpen = fout.is_open();
+  if (fileOpen) {
+    fout << "double sqrtTable[] = {" << std::endl;
+    for (int i = 0; i < 10; ++i) {
+      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+    }
+    // close the table with a zero
+    fout << "0};" << std::endl;
+    fout.close();
   }
-
-  // create a source file with a table of square roots
-  fprintf(fout, "double sqrtTable[] = {\n");
-  for (i = 0; i < 10; ++i) {
-    result = sqrt(static_cast<double>(i));
-    fprintf(fout, "%g,\n", result);
-  }
-
-  // close the table with a zero
-  fprintf(fout, "0};\n");
-  fclose(fout);
-  return 0;
+  return fileOpen ? 0 : 1; // return 0 if wrote the file
 }
diff --git a/Tests/Tutorial/Step7/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step7/MathFunctions/mysqrt.cxx
index 458ed63..5272f56 100644
--- a/Tests/Tutorial/Step7/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step7/MathFunctions/mysqrt.cxx
@@ -1,11 +1,11 @@
 #include "MathFunctions.h"
 #include "TutorialConfig.h"
-#include <stdio.h>
+#include <iostream>
 
 // include the generated table
 #include "Table.h"
 
-#include <math.h>
+#include <cmath>
 
 // a hack square root calculation using simple operations
 double mysqrt(double x)
@@ -14,26 +14,20 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
-  // if we have both log and exp then use them
-  double delta;
-
   // use the table to help find an initial value
-  result = x;
+  double result = x;
   if (x >= 1 && x < 10) {
     result = sqrtTable[static_cast<int>(x)];
   }
 
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
 
   return result;
diff --git a/Tests/Tutorial/Step7/directions.txt b/Tests/Tutorial/Step7/directions.txt
new file mode 100644
index 0000000..7d7c2ea
--- /dev/null
+++ b/Tests/Tutorial/Step7/directions.txt
@@ -0,0 +1,40 @@
+# Building an Installer #
+
+Next suppose that we want to distribute our project to other people so that they
+can use it. We want to provide both binary and source distributions on a variety
+of platforms. This is a little different from the install we did previously in
+the Installing and Testing section (Step 4), where we were installing the
+binaries that we had built from the source code. In this example we will be
+building installation packages that support binary installations and package
+management features. To accomplish this we will use CPack to create platform
+specific installers. Specifically we need to add a few lines to the bottom of
+our top-level CMakeLists.txt file.
+
+  include(InstallRequiredSystemLibraries)
+  set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
+  set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
+  set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
+  include(CPack)
+
+That is all there is to it. We start by including InstallRequiredSystemLibraries.
+This module will include any runtime libraries that are needed by the project
+for the current platform. Next we set some CPack variables to where we have
+stored the license and version information for this project. The version
+information makes use of the variables we set earlier in this tutorial. Finally
+we include the CPack module which will use these variables and some other
+properties of the system you are on to setup an installer.
+
+The next step is to build the project in the usual manner and then run CPack
+on it. To build a binary distribution you would run:
+
+  cpack
+
+To create a source distribution you would type:
+
+  cpack -C CPackSourceConfig.cmake
+
+Alternatively, run “make package” or right click the Package target and
+“Build Project” from an IDE.
+
+Run the installer executable found  in the binary directory. Then run the
+installed executable and verify that it works.
diff --git a/Tests/Tutorial/Step7/tutorial.cxx b/Tests/Tutorial/Step7/tutorial.cxx
index 37f6ac4..1d5742d 100644
--- a/Tests/Tutorial/Step7/tutorial.cxx
+++ b/Tests/Tutorial/Step7/tutorial.cxx
@@ -1,8 +1,9 @@
 // A simple program that computes the square root of a number
+#include <cmath>
+#include <iostream>
+#include <string>
+
 #include "TutorialConfig.h"
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
 
 #ifdef USE_MYMATH
 #  include "MathFunctions.h"
@@ -11,23 +12,21 @@
 int main(int argc, char* argv[])
 {
   if (argc < 2) {
-    fprintf(stdout, "%s Version %d.%d\n", argv[0], Tutorial_VERSION_MAJOR,
-            Tutorial_VERSION_MINOR);
-    fprintf(stdout, "Usage: %s number\n", argv[0]);
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
     return 1;
   }
 
-  double inputValue = atof(argv[1]);
-  double outputValue = 0;
+  double inputValue = std::stod(argv[1]);
 
-  if (inputValue >= 0) {
 #ifdef USE_MYMATH
-    outputValue = mysqrt(inputValue);
+  double outputValue = mysqrt(inputValue);
 #else
-    outputValue = sqrt(inputValue);
+  double outputValue = sqrt(inputValue);
 #endif
-  }
 
-  fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
   return 0;
 }
diff --git a/Tests/Tutorial/Step8/CMakeLists.txt b/Tests/Tutorial/Step8/CMakeLists.txt
new file mode 100644
index 0000000..c66bf96
--- /dev/null
+++ b/Tests/Tutorial/Step8/CMakeLists.txt
@@ -0,0 +1,82 @@
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
+# does this system provide the log and exp functions?
+include(CheckSymbolExists)
+set(CMAKE_REQUIRED_LIBRARIES "m")
+check_symbol_exists(log "math.h" HAVE_LOG)
+check_symbol_exists(exp "math.h" HAVE_EXP)
+
+# should we use our own math functions
+option(USE_MYMATH "Use tutorial provided math implementation" ON)
+
+# configure a header file to pass some of the CMake settings
+# to the source code
+configure_file(
+  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  )
+
+# add the MathFunctions library?
+if(USE_MYMATH)
+  add_subdirectory(MathFunctions)
+  list(APPEND EXTRA_LIBS MathFunctions)
+endif(USE_MYMATH)
+
+# add the executable
+add_executable(Tutorial tutorial.cxx)
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
+
+# add the install targets
+install(TARGETS Tutorial DESTINATION bin)
+install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include
+  )
+
+# enable testing
+enable_testing()
+
+# does the application run
+add_test(NAME Runs COMMAND Tutorial 25)
+
+# does the usage message work?
+add_test(NAME Usage COMMAND Tutorial)
+set_tests_properties(Usage
+  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
+  )
+
+# define a function to simplify adding tests
+function(do_test target arg result)
+add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+  set_tests_properties(Comp${arg}
+    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
+    )
+endfunction(do_test)
+
+# do a bunch of result based tests
+do_test(Tutorial 4 "4 is 2")
+do_test(Tutorial 9 "9 is 3")
+do_test(Tutorial 5 "5 is 2.236")
+do_test(Tutorial 7 "7 is 2.645")
+do_test(Tutorial 25 "25 is 5")
+do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial 0.0001 "0.0001 is 0.01")
+
+include(InstallRequiredSystemLibraries)
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
+set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
+include(CPack)
diff --git a/Tests/Tutorial/Step6/License.txt b/Tests/Tutorial/Step8/License.txt
similarity index 64%
copy from Tests/Tutorial/Step6/License.txt
copy to Tests/Tutorial/Step8/License.txt
index 673d724..c62d00b 100644
--- a/Tests/Tutorial/Step6/License.txt
+++ b/Tests/Tutorial/Step8/License.txt
@@ -1,2 +1,2 @@
 This is the open source License.txt file introduced in
-CMake/Tests/Tutorial/Step6...
+CMake/Tutorial/Step7...
diff --git a/Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt
new file mode 100644
index 0000000..dc3eb98
--- /dev/null
+++ b/Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt
@@ -0,0 +1,29 @@
+# first we add the executable that generates the table
+add_executable(MakeTable MakeTable.cxx)
+
+# add the command to generate the source code
+add_custom_command(
+  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+  DEPENDS MakeTable
+  )
+
+# add the main library
+add_library(MathFunctions
+            mysqrt.cxx
+            ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+            )
+
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+# state that we depend on Tutorial_BINARY_DIR but consumers don't, as the
+# TutorialConfig.h include is an implementation detail
+# state that we depend on our binary dir to find Table.h
+target_include_directories(MathFunctions
+          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+          PRIVATE ${Tutorial_BINARY_DIR}
+                  ${CMAKE_CURRENT_BINARY_DIR}
+          )
+
+install(TARGETS MathFunctions DESTINATION lib)
+install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step8/MathFunctions/MakeTable.cxx b/Tests/Tutorial/Step8/MathFunctions/MakeTable.cxx
new file mode 100644
index 0000000..ee58556
--- /dev/null
+++ b/Tests/Tutorial/Step8/MathFunctions/MakeTable.cxx
@@ -0,0 +1,25 @@
+// A simple program that builds a sqrt table
+#include <cmath>
+#include <fstream>
+#include <iostream>
+
+int main(int argc, char* argv[])
+{
+  // make sure we have enough arguments
+  if (argc < 2) {
+    return 1;
+  }
+
+  std::ofstream fout(argv[1], std::ios_base::out);
+  const bool fileOpen = fout.is_open();
+  if (fileOpen) {
+    fout << "double sqrtTable[] = {" << std::endl;
+    for (int i = 0; i < 10; ++i) {
+      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+    }
+    // close the table with a zero
+    fout << "0};" << std::endl;
+    fout.close();
+  }
+  return fileOpen ? 0 : 1; // return 0 if wrote the file
+}
diff --git a/Tests/Tutorial/Step8/MathFunctions/MathFunctions.h b/Tests/Tutorial/Step8/MathFunctions/MathFunctions.h
new file mode 100644
index 0000000..cd36bcc
--- /dev/null
+++ b/Tests/Tutorial/Step8/MathFunctions/MathFunctions.h
@@ -0,0 +1 @@
+double mysqrt(double x);
diff --git a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step8/MathFunctions/mysqrt.cxx
similarity index 54%
copy from Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
copy to Tests/Tutorial/Step8/MathFunctions/mysqrt.cxx
index 458ed63..5b862fb 100644
--- a/Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step8/MathFunctions/mysqrt.cxx
@@ -1,11 +1,11 @@
 #include "MathFunctions.h"
 #include "TutorialConfig.h"
-#include <stdio.h>
+#include <iostream>
 
 // include the generated table
 #include "Table.h"
 
-#include <math.h>
+#include <cmath>
 
 // a hack square root calculation using simple operations
 double mysqrt(double x)
@@ -14,27 +14,29 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
   // if we have both log and exp then use them
-  double delta;
-
+#if defined(HAVE_LOG) && defined(HAVE_EXP)
+  double result = exp(log(x) * 0.5);
+  std::cout << "Computing sqrt of " << x << " to be " << result << " using log"
+            << std::endl;
+#else
   // use the table to help find an initial value
-  result = x;
+  double result = x;
   if (x >= 1 && x < 10) {
     result = sqrtTable[static_cast<int>(x)];
   }
 
+  // if we have both log and exp then use them
+
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
-
+#endif
   return result;
 }
diff --git a/Tests/Tutorial/Step5/TutorialConfig.h.in b/Tests/Tutorial/Step8/TutorialConfig.h.in
similarity index 99%
copy from Tests/Tutorial/Step5/TutorialConfig.h.in
copy to Tests/Tutorial/Step8/TutorialConfig.h.in
index a091265..e97ce24 100644
--- a/Tests/Tutorial/Step5/TutorialConfig.h.in
+++ b/Tests/Tutorial/Step8/TutorialConfig.h.in
@@ -6,4 +6,3 @@
 // does the platform provide exp and log functions?
 #cmakedefine HAVE_LOG
 #cmakedefine HAVE_EXP
-
diff --git a/Tests/Tutorial/Step8/directions.txt b/Tests/Tutorial/Step8/directions.txt
new file mode 100644
index 0000000..588d9c6
--- /dev/null
+++ b/Tests/Tutorial/Step8/directions.txt
@@ -0,0 +1,38 @@
+# Adding Support for a Dashboard #
+
+Adding support for submitting our test results to a dashboard is very easy. We
+already defined a number of tests for our project in the earlier steps of this
+tutorial. We just have to run those tests and submit them to a dashboard. To
+include support for dashboards we include the CTest module in our top-level
+CMakeLists.txt.
+
+Replace:
+  # enable testing
+  enable_testing()
+
+With:
+  # enable dashboard scripting
+  include(CTest)
+
+The CTest module will automatically call enable_testing(), so
+we can remove it from our CMake files.
+
+We will also need to create a CTestConfig.cmake file where we can specify the
+name of the project and where to submit the dashboard.
+
+  set(CTEST_PROJECT_NAME "CMakeTutorial")
+  set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
+
+  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)
+
+CTest will read in this file when it runs. To create a simple dashboard you can
+run cmake or cmake-gui to configure the project, but do not build it yet.
+Instead, change directory to the binary tree, and then run:
+ 'ctest [-VV] –D Experimental'. On Windows, build the EXPERIMENTAL target.
+
+Ctest will build and test the project and submit results to the Kitware public
+dashboard. The results of your dashboard will be uploaded to Kitware's public
+dashboard here: https://my.cdash.org/index.php?project=CMakeTutorial.
diff --git a/Tests/Tutorial/Step8/tutorial.cxx b/Tests/Tutorial/Step8/tutorial.cxx
new file mode 100644
index 0000000..1d5742d
--- /dev/null
+++ b/Tests/Tutorial/Step8/tutorial.cxx
@@ -0,0 +1,32 @@
+// A simple program that computes the square root of a number
+#include <cmath>
+#include <iostream>
+#include <string>
+
+#include "TutorialConfig.h"
+
+#ifdef USE_MYMATH
+#  include "MathFunctions.h"
+#endif
+
+int main(int argc, char* argv[])
+{
+  if (argc < 2) {
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
+    return 1;
+  }
+
+  double inputValue = std::stod(argv[1]);
+
+#ifdef USE_MYMATH
+  double outputValue = mysqrt(inputValue);
+#else
+  double outputValue = sqrt(inputValue);
+#endif
+
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
+  return 0;
+}
diff --git a/Tests/Tutorial/Step9/CMakeLists.txt b/Tests/Tutorial/Step9/CMakeLists.txt
new file mode 100644
index 0000000..309d513
--- /dev/null
+++ b/Tests/Tutorial/Step9/CMakeLists.txt
@@ -0,0 +1,81 @@
+cmake_minimum_required(VERSION 3.3)
+project(Tutorial)
+
+set(CMAKE_CXX_STANDARD 11)
+set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+# the version number.
+set(Tutorial_VERSION_MAJOR 1)
+set(Tutorial_VERSION_MINOR 0)
+
+# does this system provide the log and exp functions?
+include(CheckSymbolExists)
+set(CMAKE_REQUIRED_LIBRARIES "m")
+check_symbol_exists(log "math.h" HAVE_LOG)
+check_symbol_exists(exp "math.h" HAVE_EXP)
+
+# should we use our own math functions
+option(USE_MYMATH "Use tutorial provided math implementation" ON)
+
+# configure a header file to pass the version number only
+configure_file(
+  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  )
+
+# add the MathFunctions library?
+if(USE_MYMATH)
+  add_subdirectory(MathFunctions)
+  list(APPEND EXTRA_LIBS MathFunctions)
+endif()
+
+# add the executable
+add_executable(Tutorial tutorial.cxx)
+target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+target_include_directories(Tutorial PUBLIC
+                           "${PROJECT_BINARY_DIR}"
+                           )
+
+# add the install targets
+install(TARGETS Tutorial DESTINATION bin)
+install(FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include
+  )
+
+# enable testing
+include(CTest)
+
+# does the application run
+add_test(NAME Runs COMMAND Tutorial 25)
+
+# does the usage message work?
+add_test(NAME Usage COMMAND Tutorial)
+set_tests_properties(Usage
+  PROPERTIES PASS_REGULAR_EXPRESSION "Usage:.*number"
+  )
+
+# define a function to simplify adding tests
+function(do_test target arg result)
+  add_test(NAME Comp${arg} COMMAND ${target} ${arg})
+  set_tests_properties(Comp${arg}
+    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
+    )
+endfunction(do_test)
+
+# do a bunch of result based tests
+do_test(Tutorial 4 "4 is 2")
+do_test(Tutorial 9 "9 is 3")
+do_test(Tutorial 5 "5 is 2.236")
+do_test(Tutorial 7 "7 is 2.645")
+do_test(Tutorial 25 "25 is 5")
+do_test(Tutorial -25 "-25 is [-nan|nan|0]")
+do_test(Tutorial 0.0001 "0.0001 is 0.01")
+
+include(InstallRequiredSystemLibraries)
+set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
+set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
+set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
+include(CPack)
diff --git a/Tests/Tutorial/Step9/CTestConfig.cmake b/Tests/Tutorial/Step9/CTestConfig.cmake
new file mode 100644
index 0000000..7a927ac
--- /dev/null
+++ b/Tests/Tutorial/Step9/CTestConfig.cmake
@@ -0,0 +1,15 @@
+## This file should be placed in the root directory of your project.
+## Then modify the CMakeLists.txt file in the root directory of your
+## project to incorporate the testing dashboard.
+##
+## # The following are required to submit to the CDash dashboard:
+##   ENABLE_TESTING()
+##   INCLUDE(CTest)
+
+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)
diff --git a/Tests/Tutorial/Step6/License.txt b/Tests/Tutorial/Step9/License.txt
similarity index 64%
rename from Tests/Tutorial/Step6/License.txt
rename to Tests/Tutorial/Step9/License.txt
index 673d724..c62d00b 100644
--- a/Tests/Tutorial/Step6/License.txt
+++ b/Tests/Tutorial/Step9/License.txt
@@ -1,2 +1,2 @@
 This is the open source License.txt file introduced in
-CMake/Tests/Tutorial/Step6...
+CMake/Tutorial/Step7...
diff --git a/Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt b/Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt
new file mode 100644
index 0000000..e651a57
--- /dev/null
+++ b/Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt
@@ -0,0 +1,35 @@
+# first we add the executable that generates the table
+add_executable(MakeTable MakeTable.cxx)
+
+# add the command to generate the source code
+add_custom_command(
+  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+  DEPENDS MakeTable
+  )
+
+# add the main library
+add_library(MathFunctions
+            mysqrt.cxx
+            ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+            )
+
+# state that anybody linking to us needs to include the current source dir
+# to find MathFunctions.h, while we don't.
+# state that we depend on our binary dir to find Table.h
+target_include_directories(MathFunctions
+          INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+          PRIVATE   ${CMAKE_CURRENT_BINARY_DIR}
+          )
+
+# use compile definitions to state if we have enabled USE_MYMATH
+# and that anything that links to use will get this define
+target_compile_definitions(MathFunctions INTERFACE "USE_MYMATH")
+
+if(HAVE_LOG AND HAVE_EXP)
+  target_compile_definitions(MathFunctions
+                             PRIVATE "HAVE_LOG" "HAVE_EXP")
+endif()
+
+install(TARGETS MathFunctions DESTINATION lib)
+install(FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/Tutorial/Step9/MathFunctions/MakeTable.cxx b/Tests/Tutorial/Step9/MathFunctions/MakeTable.cxx
new file mode 100644
index 0000000..ee58556
--- /dev/null
+++ b/Tests/Tutorial/Step9/MathFunctions/MakeTable.cxx
@@ -0,0 +1,25 @@
+// A simple program that builds a sqrt table
+#include <cmath>
+#include <fstream>
+#include <iostream>
+
+int main(int argc, char* argv[])
+{
+  // make sure we have enough arguments
+  if (argc < 2) {
+    return 1;
+  }
+
+  std::ofstream fout(argv[1], std::ios_base::out);
+  const bool fileOpen = fout.is_open();
+  if (fileOpen) {
+    fout << "double sqrtTable[] = {" << std::endl;
+    for (int i = 0; i < 10; ++i) {
+      fout << sqrt(static_cast<double>(i)) << "," << std::endl;
+    }
+    // close the table with a zero
+    fout << "0};" << std::endl;
+    fout.close();
+  }
+  return fileOpen ? 0 : 1; // return 0 if wrote the file
+}
diff --git a/Tests/Tutorial/Step9/MathFunctions/MathFunctions.cxx b/Tests/Tutorial/Step9/MathFunctions/MathFunctions.cxx
new file mode 100644
index 0000000..5351184
--- /dev/null
+++ b/Tests/Tutorial/Step9/MathFunctions/MathFunctions.cxx
@@ -0,0 +1,18 @@
+
+#include "MathFunctions.h"
+#include <cmath>
+
+#ifdef USE_MYMATH
+#  include "mysqrt.h"
+#endif
+
+namespace mathfunctions {
+double sqrt(double x)
+{
+#ifdef USE_MYMATH
+  return detail::mysqrt(x);
+#else
+  return std::sqrt(x);
+#endif
+}
+}
diff --git a/Tests/Tutorial/Step9/MathFunctions/MathFunctions.h b/Tests/Tutorial/Step9/MathFunctions/MathFunctions.h
new file mode 100644
index 0000000..cd36bcc
--- /dev/null
+++ b/Tests/Tutorial/Step9/MathFunctions/MathFunctions.h
@@ -0,0 +1 @@
+double mysqrt(double x);
diff --git a/Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx b/Tests/Tutorial/Step9/MathFunctions/mysqrt.cxx
similarity index 52%
copy from Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx
copy to Tests/Tutorial/Step9/MathFunctions/mysqrt.cxx
index 458ed63..8b82141 100644
--- a/Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx
+++ b/Tests/Tutorial/Step9/MathFunctions/mysqrt.cxx
@@ -1,11 +1,10 @@
 #include "MathFunctions.h"
-#include "TutorialConfig.h"
-#include <stdio.h>
+#include <iostream>
 
 // include the generated table
 #include "Table.h"
 
-#include <math.h>
+#include <cmath>
 
 // a hack square root calculation using simple operations
 double mysqrt(double x)
@@ -14,27 +13,29 @@ double mysqrt(double x)
     return 0;
   }
 
-  double result;
-
   // if we have both log and exp then use them
-  double delta;
-
+#if defined(HAVE_LOG) && defined(HAVE_EXP)
+  double result = exp(log(x) * 0.5);
+  std::cout << "Computing sqrt of " << x << " to be " << result << " using log"
+            << std::endl;
+#else
   // use the table to help find an initial value
-  result = x;
+  double result = x;
   if (x >= 1 && x < 10) {
     result = sqrtTable[static_cast<int>(x)];
   }
 
+  // if we have both log and exp then use them
+
   // do ten iterations
-  int i;
-  for (i = 0; i < 10; ++i) {
+  for (int i = 0; i < 10; ++i) {
     if (result <= 0) {
       result = 0.1;
     }
-    delta = x - (result * result);
+    double delta = x - (result * result);
     result = result + 0.5 * delta / result;
-    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+    std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
   }
-
+#endif
   return result;
 }
diff --git a/Tests/Tutorial/Step9/MathFunctions/mysqrt.h b/Tests/Tutorial/Step9/MathFunctions/mysqrt.h
new file mode 100644
index 0000000..e1c42ef
--- /dev/null
+++ b/Tests/Tutorial/Step9/MathFunctions/mysqrt.h
@@ -0,0 +1,6 @@
+
+namespace mathfunctions {
+namespace detail {
+double mysqrt(double x);
+}
+}
diff --git a/Tests/Tutorial/Step2/TutorialConfig.h.in b/Tests/Tutorial/Step9/TutorialConfig.h.in
similarity index 59%
copy from Tests/Tutorial/Step2/TutorialConfig.h.in
copy to Tests/Tutorial/Step9/TutorialConfig.h.in
index 25a0602..8cd2fc9 100644
--- a/Tests/Tutorial/Step2/TutorialConfig.h.in
+++ b/Tests/Tutorial/Step9/TutorialConfig.h.in
@@ -1,5 +1,3 @@
-// the configured options and settings for Tutorial
+// the configured version number
 #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
 #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
-#cmakedefine USE_MYMATH
-
diff --git a/Tests/Tutorial/Step9/directions.txt b/Tests/Tutorial/Step9/directions.txt
new file mode 100644
index 0000000..8771637
--- /dev/null
+++ b/Tests/Tutorial/Step9/directions.txt
@@ -0,0 +1,166 @@
+# Mixing Static and Shared #
+
+In this section we will show how by using the BUILD_SHARED_LIBS variable we can
+control the default behavior of add_library, and allow control over how
+libraries without an explicit type ( STATIC/SHARED/MODULE/OBJECT ) are built.
+
+To accomplish this we need to add BUILD_SHARED_LIBS to the top level
+CMakeLists.txt. We use the option command as it allows users to optionally
+select if the value should be On or Off.
+
+Next we are going to refactor MathFunctions to become a real library that
+encapsulates using mysqrt or sqrt, instead of requiring the calling code
+to do this logic. This will also mean that USE_MYMATH will not control building
+MathFuctions, but instead will control the behavior of this library.
+
+The first step is to update the starting section of the top level CMakeLists.txt
+to look like:
+
+  cmake_minimum_required(VERSION 3.3)
+  project(Tutorial)
+
+  # 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
+  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}")
+
+  set(CMAKE_CXX_STANDARD 11)
+  set(CMAKE_CXX_STANDARD_REQUIRED True)
+
+  option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
+
+  # the version number.
+  set(Tutorial_VERSION_MAJOR 1)
+  set(Tutorial_VERSION_MINOR 0)
+
+  # configure a header file to pass the version number only
+  configure_file(
+    "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+    "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+    )
+
+  # add the MathFunctions library
+  add_subdirectory(MathFunctions)
+
+  # add the executable
+  add_executable(Tutorial tutorial.cxx)
+  target_link_libraries(Tutorial PUBLIC MathFunctions)
+
+Now that we have made MathFunctions always be used, we will need to update
+the logic of that library. So, in MathFunctions/CMakeLists.txt we need to
+create a SqrtLibrary that will conditionally be built when USE_MYMATH is
+enabled. Now, since this is a tutorial, we are going to explicitly require
+that SqrtLibrary is built statically.
+
+The end result is that MathFunctions/CMakeLists.txt should look like:
+
+  # add the library that runs
+  add_library(MathFunctions MathFunctions.cxx)
+
+  # state that anybody linking to us needs to include the current source dir
+  # to find MathFunctions.h, while we don't.
+  target_include_directories(MathFunctions
+                             INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
+                             )
+
+  # should we use our own math functions
+  option(USE_MYMATH "Use tutorial provided math implementation" ON)
+  if(USE_MYMATH)
+
+    # does this system provide the log and exp functions?
+    include(CheckSymbolExists)
+    set(CMAKE_REQUIRED_LIBRARIES "m")
+    check_symbol_exists(log "math.h" HAVE_LOG)
+    check_symbol_exists(exp "math.h" HAVE_EXP)
+
+    # first we add the executable that generates the table
+    add_executable(MakeTable MakeTable.cxx)
+
+    # add the command to generate the source code
+    add_custom_command(
+      OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+      COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+      DEPENDS MakeTable
+      )
+
+    # library that just does sqrt
+    add_library(SqrtLibrary STATIC
+                mysqrt.cxx
+                ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+                )
+
+    # state that we depend on our binary dir to find Table.h
+    target_include_directories(SqrtLibrary PRIVATE
+                               ${CMAKE_CURRENT_BINARY_DIR}
+                               )
+
+    target_compile_definitions(MathFunctions PRIVATE "USE_MYMATH")
+    if(HAVE_LOG AND HAVE_EXP)
+      target_compile_definitions(SqrtLibrary
+                                 PRIVATE "HAVE_LOG" "HAVE_EXP")
+    endif()
+
+    target_link_libraries(MathFunctions PRIVATE SqrtLibrary)
+  endif()
+
+  # define the symbol stating we are using the declspec(dllexport) when
+  # building on windows
+  target_compile_definitions(MathFunctions PRIVATE "EXPORTING_MYMATH")
+
+  install(TARGETS MathFunctions DESTINATION lib)
+  install(FILES MathFunctions.h DESTINATION include)
+
+Next, update MathFunctions/mysqrt.cxx to use the mathfunctions and detail namespaces:
+
+  #include <iostream>
+  #include "MathFunctions.h"
+
+  // include the generated table
+  #include "Table.h"
+
+  #include <cmath>
+
+  namespace mathfunctions {
+  namespace detail {
+  // a hack square root calculation using simple operations
+  double mysqrt(double x)
+  {
+    ...
+
+    return result;
+  }
+  }
+  }
+
+We also need to make some changes in tutorial.cxx, so that it no longer uses USE_MYMATH:
+1. Always include MathFunctions.h
+2. Always use mathfunctions::sqrt
+
+Finally, update MathFunctions/MathFunctions.h to use dll export defines:
+
+  #if defined(_WIN32)
+  #if defined(EXPORTING_MYMATH)
+    #define DECLSPEC  __declspec(dllexport)
+  #else
+    #define DECLSPEC  __declspec(dllimport)
+  #endif
+  #else //non windows
+    #define DECLSPEC
+  #endif
+
+  namespace mathfunctions
+  {
+    double DECLSPEC sqrt(double x);
+  }
+
+At this point, if you build everything, you will notice that linking fails
+as we are combining a static library without position enabled code with a
+library that has position enabled code. This solution to this is to explicitly
+set the POSITION_INDEPENDENT_CODE target property of SqrtLibrary to be True no
+matter the build type.
+
+Exercise: We modified MathFunctions.h to use dll export defines. Using CMake
+documentation can you find a helper module to simplify this?
+
+Exercise: Determine what command is enabling PIC for SqrtLibrary.
+What happens if we remove said command?
diff --git a/Tests/Tutorial/Step9/tutorial.cxx b/Tests/Tutorial/Step9/tutorial.cxx
new file mode 100644
index 0000000..73e67a9
--- /dev/null
+++ b/Tests/Tutorial/Step9/tutorial.cxx
@@ -0,0 +1,33 @@
+// A simple program that computes the square root of a number
+#include <cmath>
+#include <iostream>
+#include <sstream>
+#include <string>
+
+#include "TutorialConfig.h"
+
+#ifdef USE_MYMATH
+#  include "MathFunctions.h"
+#endif
+
+int main(int argc, char* argv[])
+{
+  if (argc < 2) {
+    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
+              << Tutorial_VERSION_MAJOR << std::endl;
+    std::cout << "Usage: " << argv[0] << " number" << std::endl;
+    return 1;
+  }
+
+  double inputValue = std::stod(argv[1]);
+
+#ifdef USE_MYMATH
+  double outputValue = mysqrt(inputValue);
+#else
+  double outputValue = sqrt(inputValue);
+#endif
+
+  std::cout << "The square root of " << inputValue << " is " << outputValue
+            << std::endl;
+  return 0;
+}

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=438651506a5417be70e71f54f4ed7add0c2604d3
commit 438651506a5417be70e71f54f4ed7add0c2604d3
Author:     Betsy McPhail <betsy.mcphail at kitware.com>
AuthorDate: Sun Jan 20 11:28:39 2019 -0500
Commit:     Betsy McPhail <betsy.mcphail at kitware.com>
CommitDate: Sun Jan 27 16:03:00 2019 -0500

    Tests: Make ExternalProjectLocal independent of Tutorial directory
    
    Adopt a copy of the needed content so we can modify the original
    independent of this test.

diff --git a/Tests/ExternalProjectLocal/CMakeLists.txt b/Tests/ExternalProjectLocal/CMakeLists.txt
index 55fd713..1075a9d 100644
--- a/Tests/ExternalProjectLocal/CMakeLists.txt
+++ b/Tests/ExternalProjectLocal/CMakeLists.txt
@@ -20,71 +20,55 @@ set(binary_base "${base}/Build")
 set_property(DIRECTORY PROPERTY EP_BASE ${base})
 set_property(DIRECTORY PROPERTY EP_STEP_TARGETS configure build test)
 
-if(NOT DEFINED can_build_tutorial_step5)
-  set(can_build_tutorial_step5 1)
-
-  # The ExternalProject builds of Tutorial Step5 cannot be built
-  # correctly 2nd and later times in an in-source build...
-  # (because the CMakeCache.txt from the real in-source build of
-  # the Tests/Tutorial/Step5 directory gets copied when we do
-  # the "source directory copy" step... but it still refers to
-  # its original path which yields a configure error.) So:
-  #
-  if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
-    set(can_build_tutorial_step5 0)
-  endif()
-endif()
 
 # Local DIR:
 #
-if(can_build_tutorial_step5)
-  set(proj TutorialStep5-Local)
-  ExternalProject_Add(${proj}
-    URL "${CMAKE_CURRENT_SOURCE_DIR}/../Tutorial/Step5"
-    CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-    CMAKE_ARGS -G ${CMAKE_GENERATOR} <SOURCE_DIR>
-    TEST_BEFORE_INSTALL 1
-    LOG_INSTALL 1
-  )
-  set_property(TARGET ${proj} PROPERTY FOLDER "Local")
-  ExternalProject_Get_Property(${proj} install_dir)
-  set(TutorialStep5_install_dir ${install_dir})
-
-  set(proj TutorialStep5-Local-TestAfterInstall)
-  ExternalProject_Add(${proj}
-    URL "${CMAKE_CURRENT_SOURCE_DIR}/../Tutorial/Step5"
-    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
-    CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
-    TEST_AFTER_INSTALL 1
-    LOG_TEST 1
-  )
-  set_property(TARGET ${proj} PROPERTY FOLDER "Local")
-
-  set(proj TutorialStep5-Local-TestExcludeFromMainBefore)
-  ExternalProject_Add(${proj}
-    URL "${CMAKE_CURRENT_SOURCE_DIR}/../Tutorial/Step5"
-    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>  -G ${CMAKE_GENERATOR} <SOURCE_DIR>
-    CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
-    TEST_BEFORE_INSTALL 1
-    TEST_EXCLUDE_FROM_MAIN 1
-    STEP_TARGETS test
-    LOG_TEST 1
-  )
-  set_property(TARGET ${proj} PROPERTY FOLDER "Local")
-
-  set(proj TutorialStep5-Local-TestExcludeFromMainAfter)
-  ExternalProject_Add(${proj}
-    URL "${CMAKE_CURRENT_SOURCE_DIR}/../Tutorial/Step5"
-    CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>  -G ${CMAKE_GENERATOR} <SOURCE_DIR>
-    CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
-    TEST_AFTER_INSTALL 1
-    TEST_EXCLUDE_FROM_MAIN 1
-    STEP_TARGETS test
-    LOG_TEST 1
-  )
-  set_property(TARGET ${proj} PROPERTY FOLDER "Local")
+set(proj TutorialStep5-Local)
+ExternalProject_Add(${proj}
+URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
+CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
+CMAKE_ARGS -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+TEST_BEFORE_INSTALL 1
+LOG_INSTALL 1
+)
+set_property(TARGET ${proj} PROPERTY FOLDER "Local")
+ExternalProject_Get_Property(${proj} install_dir)
+set(TutorialStep5_install_dir ${install_dir})
+
+set(proj TutorialStep5-Local-TestAfterInstall)
+ExternalProject_Add(${proj}
+URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
+CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
+TEST_AFTER_INSTALL 1
+LOG_TEST 1
+)
+set_property(TARGET ${proj} PROPERTY FOLDER "Local")
+
+set(proj TutorialStep5-Local-TestExcludeFromMainBefore)
+ExternalProject_Add(${proj}
+URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
+CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>  -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
+TEST_BEFORE_INSTALL 1
+TEST_EXCLUDE_FROM_MAIN 1
+STEP_TARGETS test
+LOG_TEST 1
+)
+set_property(TARGET ${proj} PROPERTY FOLDER "Local")
+
+set(proj TutorialStep5-Local-TestExcludeFromMainAfter)
+ExternalProject_Add(${proj}
+URL "${CMAKE_CURRENT_SOURCE_DIR}/Step5"
+CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>  -G ${CMAKE_GENERATOR} <SOURCE_DIR>
+CMAKE_CACHE_DEFAULT_ARGS -DUSE_MYMATH:BOOL=OFF
+TEST_AFTER_INSTALL 1
+TEST_EXCLUDE_FROM_MAIN 1
+STEP_TARGETS test
+LOG_TEST 1
+)
+set_property(TARGET ${proj} PROPERTY FOLDER "Local")
 
-endif()
 
 
 # Local TAR:
@@ -209,12 +193,10 @@ enable_testing()
 #
 # BuildTree tests:
 #
-if(can_build_tutorial_step5)
-  add_test(TutorialStep5-Local-BuildTreeTest
-    "${binary_base}/TutorialStep5-Local/Tutorial" 42)
-  set_property(TEST TutorialStep5-Local-BuildTreeTest
-    APPEND PROPERTY LABELS Step5 BuildTree)
-endif()
+add_test(TutorialStep5-Local-BuildTreeTest
+"${binary_base}/TutorialStep5-Local/Tutorial" 42)
+set_property(TEST TutorialStep5-Local-BuildTreeTest
+APPEND PROPERTY LABELS Step5 BuildTree)
 
 add_test(TutorialStep1-LocalTAR-BuildTreeTest
   "${binary_base}/TutorialStep1-LocalTAR/EP-Tutorial" 36)
@@ -234,12 +216,7 @@ add_test(TutorialStep1-LocalNoDirTGZ-BuildTreeTest
 
 # InstallTree tests:
 #
-if(can_build_tutorial_step5)
-  add_test(TutorialStep5-InstallTreeTest
-    "${TutorialStep5_install_dir}/bin/Tutorial" 49)
-  set_property(TEST TutorialStep5-InstallTreeTest
-    APPEND PROPERTY LABELS Step5 InstallTree)
-endif()
-
-
-message(STATUS "can_build_tutorial_step5='${can_build_tutorial_step5}'")
+add_test(TutorialStep5-InstallTreeTest
+"${TutorialStep5_install_dir}/bin/Tutorial" 49)
+set_property(TEST TutorialStep5-InstallTreeTest
+APPEND PROPERTY LABELS Step5 InstallTree)
diff --git a/Tests/ExternalProjectLocal/Step5/CMakeLists.txt b/Tests/ExternalProjectLocal/Step5/CMakeLists.txt
new file mode 100644
index 0000000..93b3880
--- /dev/null
+++ b/Tests/ExternalProjectLocal/Step5/CMakeLists.txt
@@ -0,0 +1,71 @@
+cmake_minimum_required (VERSION 2.6)
+project (Tutorial)
+
+# The version number.
+set (Tutorial_VERSION_MAJOR 1)
+set (Tutorial_VERSION_MINOR 0)
+
+# does this system provide the log and exp functions?
+include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
+check_function_exists (log HAVE_LOG)
+check_function_exists (exp HAVE_EXP)
+
+# should we use our own math functions
+option(USE_MYMATH "Use tutorial provided math implementation" ON)
+
+# configure a header file to pass some of the CMake settings
+# to the source code
+configure_file (
+  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
+  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  )
+
+# add the binary tree to the search path for include files
+# so that we will find TutorialConfig.h
+include_directories ("${PROJECT_BINARY_DIR}")
+
+# add the MathFunctions library?
+if (USE_MYMATH)
+  include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
+  add_subdirectory (MathFunctions)
+  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
+endif ()
+
+# add the executable
+add_executable (Tutorial tutorial.cxx)
+target_link_libraries (Tutorial  ${EXTRA_LIBS})
+
+# add the install targets
+install (TARGETS Tutorial DESTINATION bin)
+install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h"
+  DESTINATION include)
+
+# enable testing
+enable_testing ()
+
+# does the application run
+add_test (TutorialRuns Tutorial 25)
+
+# does the usage message work?
+add_test (TutorialUsage Tutorial)
+set_tests_properties (TutorialUsage
+  PROPERTIES
+  PASS_REGULAR_EXPRESSION "Usage:.*number"
+  )
+
+#define a macro to simplify adding tests
+macro (do_test arg result)
+  add_test (TutorialComp${arg} Tutorial ${arg})
+  set_tests_properties (TutorialComp${arg}
+    PROPERTIES PASS_REGULAR_EXPRESSION ${result}
+    )
+endmacro ()
+
+# do a bunch of result based tests
+do_test (4 "4 is 2")
+do_test (9 "9 is 3")
+do_test (5 "5 is 2.236")
+do_test (7 "7 is 2.645")
+do_test (25 "25 is 5")
+do_test (-25 "-25 is 0")
+do_test (0.0001 "0.0001 is 0.01")
diff --git a/Tests/ExternalProjectLocal/Step5/MathFunctions/CMakeLists.txt b/Tests/ExternalProjectLocal/Step5/MathFunctions/CMakeLists.txt
new file mode 100644
index 0000000..453a463
--- /dev/null
+++ b/Tests/ExternalProjectLocal/Step5/MathFunctions/CMakeLists.txt
@@ -0,0 +1,17 @@
+# first we add the executable that generates the table
+# add the binary tree directory to the search path for include files
+include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
+
+add_executable(MakeTable MakeTable.cxx )
+# add the command to generate the source code
+add_custom_command (
+  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+  COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
+  DEPENDS MakeTable
+  )
+
+# add the main library
+add_library(MathFunctions mysqrt.cxx ${CMAKE_CURRENT_BINARY_DIR}/Table.h  )
+
+install (TARGETS MathFunctions DESTINATION bin)
+install (FILES MathFunctions.h DESTINATION include)
diff --git a/Tests/ExternalProjectLocal/Step5/MathFunctions/MakeTable.cxx b/Tests/ExternalProjectLocal/Step5/MathFunctions/MakeTable.cxx
new file mode 100644
index 0000000..cebd50f
--- /dev/null
+++ b/Tests/ExternalProjectLocal/Step5/MathFunctions/MakeTable.cxx
@@ -0,0 +1,32 @@
+// A simple program that builds a sqrt table
+#include <math.h>
+#include <stdio.h>
+
+int main(int argc, char* argv[])
+{
+  int i;
+  double result;
+
+  // make sure we have enough arguments
+  if (argc < 2) {
+    return 1;
+  }
+
+  // open the output file
+  FILE* fout = fopen(argv[1], "w");
+  if (!fout) {
+    return 1;
+  }
+
+  // create a source file with a table of square roots
+  fprintf(fout, "double sqrtTable[] = {\n");
+  for (i = 0; i < 10; ++i) {
+    result = sqrt(static_cast<double>(i));
+    fprintf(fout, "%g,\n", result);
+  }
+
+  // close the table with a zero
+  fprintf(fout, "0};\n");
+  fclose(fout);
+  return 0;
+}
diff --git a/Tests/ExternalProjectLocal/Step5/MathFunctions/MathFunctions.h b/Tests/ExternalProjectLocal/Step5/MathFunctions/MathFunctions.h
new file mode 100644
index 0000000..cd36bcc
--- /dev/null
+++ b/Tests/ExternalProjectLocal/Step5/MathFunctions/MathFunctions.h
@@ -0,0 +1 @@
+double mysqrt(double x);
diff --git a/Tests/ExternalProjectLocal/Step5/MathFunctions/mysqrt.cxx b/Tests/ExternalProjectLocal/Step5/MathFunctions/mysqrt.cxx
new file mode 100644
index 0000000..458ed63
--- /dev/null
+++ b/Tests/ExternalProjectLocal/Step5/MathFunctions/mysqrt.cxx
@@ -0,0 +1,40 @@
+#include "MathFunctions.h"
+#include "TutorialConfig.h"
+#include <stdio.h>
+
+// include the generated table
+#include "Table.h"
+
+#include <math.h>
+
+// a hack square root calculation using simple operations
+double mysqrt(double x)
+{
+  if (x <= 0) {
+    return 0;
+  }
+
+  double result;
+
+  // if we have both log and exp then use them
+  double delta;
+
+  // use the table to help find an initial value
+  result = x;
+  if (x >= 1 && x < 10) {
+    result = sqrtTable[static_cast<int>(x)];
+  }
+
+  // do ten iterations
+  int i;
+  for (i = 0; i < 10; ++i) {
+    if (result <= 0) {
+      result = 0.1;
+    }
+    delta = x - (result * result);
+    result = result + 0.5 * delta / result;
+    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
+  }
+
+  return result;
+}
diff --git a/Tests/ExternalProjectLocal/Step5/TutorialConfig.h.in b/Tests/ExternalProjectLocal/Step5/TutorialConfig.h.in
new file mode 100644
index 0000000..e97ce24
--- /dev/null
+++ b/Tests/ExternalProjectLocal/Step5/TutorialConfig.h.in
@@ -0,0 +1,8 @@
+// the configured options and settings for Tutorial
+#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
+#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
+#cmakedefine USE_MYMATH
+
+// does the platform provide exp and log functions?
+#cmakedefine HAVE_LOG
+#cmakedefine HAVE_EXP
diff --git a/Tests/ExternalProjectLocal/Step5/tutorial.cxx b/Tests/ExternalProjectLocal/Step5/tutorial.cxx
new file mode 100644
index 0000000..37f6ac4
--- /dev/null
+++ b/Tests/ExternalProjectLocal/Step5/tutorial.cxx
@@ -0,0 +1,33 @@
+// A simple program that computes the square root of a number
+#include "TutorialConfig.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifdef USE_MYMATH
+#  include "MathFunctions.h"
+#endif
+
+int main(int argc, char* argv[])
+{
+  if (argc < 2) {
+    fprintf(stdout, "%s Version %d.%d\n", argv[0], Tutorial_VERSION_MAJOR,
+            Tutorial_VERSION_MINOR);
+    fprintf(stdout, "Usage: %s number\n", argv[0]);
+    return 1;
+  }
+
+  double inputValue = atof(argv[1]);
+  double outputValue = 0;
+
+  if (inputValue >= 0) {
+#ifdef USE_MYMATH
+    outputValue = mysqrt(inputValue);
+#else
+    outputValue = sqrt(inputValue);
+#endif
+  }
+
+  fprintf(stdout, "The square root of %g is %g\n", inputValue, outputValue);
+  return 0;
+}

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b6a957c9696706a338cdeef63540bf8a4c42d22d
commit b6a957c9696706a338cdeef63540bf8a4c42d22d
Author:     Bruno Manganelli <bruno.manga95 at gmail.com>
AuthorDate: Fri Nov 23 18:52:26 2018 +0000
Commit:     Bruno Manganelli <bruno.manga95 at gmail.com>
CommitDate: Sun Jan 27 15:48:57 2019 +0000

    cmOutputConverter: move ConvertToRelativePath to cmStateDirectory.

diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index a1df271..0414817 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -198,7 +198,7 @@ std::string cmCommonTargetGenerator::GetManifests()
   manifests.reserve(manifest_srcs.size());
   for (cmSourceFile const* manifest_src : manifest_srcs) {
     manifests.push_back(this->LocalCommonGenerator->ConvertToOutputFormat(
-      this->LocalCommonGenerator->ConvertToRelativePath(
+      this->LocalCommonGenerator->MaybeConvertToRelativePath(
         this->LocalCommonGenerator->GetWorkingDirectory(),
         manifest_src->GetFullPath()),
       cmOutputConverter::SHELL));
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 072d116..dcf9cdf 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -100,7 +100,8 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
   // Compute a path to the object file to write to the internal depend file.
   // Any existing content of the internal depend file has already been
   // loaded in ValidDeps with this path as a key.
-  std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj);
+  std::string obj_i =
+    this->LocalGenerator->MaybeConvertToRelativePath(binDir, obj);
 
   if (this->ValidDeps != nullptr) {
     std::map<std::string, DependencyVector>::const_iterator tmpIt =
@@ -234,7 +235,8 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
   for (std::string const& dep : dependencies) {
     makeDepends << obj_m << ": "
                 << cmSystemTools::ConvertToOutputPath(
-                     this->LocalGenerator->ConvertToRelativePath(binDir, dep))
+                     this->LocalGenerator->MaybeConvertToRelativePath(binDir,
+                                                                      dep))
                 << std::endl;
     internalDepends << " " << dep << std::endl;
   }
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 5833631..30067b7 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -899,7 +899,7 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
   for (cmLocalGenerator* lgen : this->GlobalGenerator->GetLocalGenerators()) {
     const std::vector<cmGeneratorTarget*>& targets =
       lgen->GetGeneratorTargets();
-    std::string subdir = lgen->ConvertToRelativePath(
+    std::string subdir = lgen->MaybeConvertToRelativePath(
       this->HomeOutputDirectory, lgen->GetCurrentBinaryDirectory());
     if (subdir == ".") {
       subdir.clear();
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 19605e4..3a65ecc 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -150,7 +150,8 @@ void cmGhsMultiTargetGenerator::WriteTargetSpecifics(std::ostream& fout,
   if (this->TagType != GhsMultiGpj::SUBPROJECT) {
     // set target binary file destination
     outpath = this->GeneratorTarget->GetDirectory(config);
-    outpath = this->LocalGenerator->ConvertToRelativePath(rootpath, outpath);
+    outpath =
+      this->LocalGenerator->MaybeConvertToRelativePath(rootpath, outpath);
     fout << "    :binDirRelative=\"" << outpath << "\"" << std::endl;
     fout << "    -o \"" << this->TargetNameReal << "\"" << std::endl;
   }
@@ -550,7 +551,7 @@ void cmGhsMultiTargetGenerator::WriteReferences(std::ostream& fout)
     std::string tpath = t->LocalGenerator->GetCurrentBinaryDirectory();
     std::string rootpath = this->LocalGenerator->GetCurrentBinaryDirectory();
     std::string outpath =
-      this->LocalGenerator->ConvertToRelativePath(rootpath, tpath) + "/" +
+      this->LocalGenerator->MaybeConvertToRelativePath(rootpath, tpath) + "/" +
       tname + "REF" + cmGlobalGhsMultiGenerator::FILE_EXTENSION;
 
     fout << outpath;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 2d36315..fff99b8 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -33,7 +33,6 @@
 #include "cmMSVC60LinkLineComputer.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
-#include "cmOutputConverter.h"
 #include "cmPolicies.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
@@ -2804,8 +2803,9 @@ void cmGlobalGenerator::AddRuleHash(const std::vector<std::string>& outputs,
   }
 
   // Shorten the output name (in expected use case).
-  cmOutputConverter converter(this->GetMakefiles()[0]->GetStateSnapshot());
-  std::string fname = converter.ConvertToRelativePath(
+  cmStateDirectory cmDir =
+    this->GetMakefiles()[0]->GetStateSnapshot().GetDirectory();
+  std::string fname = cmDir.ConvertToRelPathIfNotContained(
     this->GetMakefiles()[0]->GetState()->GetBinaryDirectory(), outputs[0]);
 
   // Associate the hash with this output.
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 557efec..ff4c3a3 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -297,7 +297,7 @@ void cmGlobalGhsMultiGenerator::WriteSubProjects(
     if (projName && projType) {
       cmLocalGenerator* lg = target->GetLocalGenerator();
       std::string dir = lg->GetCurrentBinaryDirectory();
-      dir = root->ConvertToRelativePath(rootBinaryDir, dir.c_str());
+      dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir.c_str());
       if (dir == ".") {
         dir.clear();
       } else {
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 23dbd76..8f09566 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -861,7 +861,7 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
   cmLocalNinjaGenerator* ng =
     static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
   std::string const& bin_dir = ng->GetState()->GetBinaryDirectory();
-  std::string convPath = ng->ConvertToRelativePath(bin_dir, path);
+  std::string convPath = ng->MaybeConvertToRelativePath(bin_dir, path);
   convPath = this->NinjaOutputPath(convPath);
 #ifdef _WIN32
   std::replace(convPath.begin(), convPath.end(), '/', '\\');
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 52bb046..9d176c3 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -325,7 +325,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
     << "set(CMAKE_MAKEFILE_DEPENDS\n"
     << "  \"CMakeCache.txt\"\n";
   for (std::string const& f : lfiles) {
-    cmakefileStream << "  \"" << lg->ConvertToRelativePath(currentBinDir, f)
+    cmakefileStream << "  \""
+                    << lg->MaybeConvertToRelativePath(currentBinDir, f)
                     << "\"\n";
   }
   cmakefileStream << "  )\n\n";
@@ -339,9 +340,11 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
   cmakefileStream << "# The corresponding makefile is:\n"
                   << "set(CMAKE_MAKEFILE_OUTPUTS\n"
                   << "  \""
-                  << lg->ConvertToRelativePath(currentBinDir, makefileName)
+                  << lg->MaybeConvertToRelativePath(currentBinDir,
+                                                    makefileName)
                   << "\"\n"
-                  << "  \"" << lg->ConvertToRelativePath(currentBinDir, check)
+                  << "  \""
+                  << lg->MaybeConvertToRelativePath(currentBinDir, check)
                   << "\"\n";
   cmakefileStream << "  )\n\n";
 
@@ -354,7 +357,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
     const std::vector<std::string>& outfiles =
       lg->GetMakefile()->GetOutputFiles();
     for (std::string const& outfile : outfiles) {
-      cmakefileStream << "  \"" << lg->ConvertToRelativePath(binDir, outfile)
+      cmakefileStream << "  \""
+                      << lg->MaybeConvertToRelativePath(binDir, outfile)
                       << "\"\n";
     }
 
@@ -365,7 +369,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
       tmpStr = lg->GetCurrentBinaryDirectory();
       tmpStr += cmake::GetCMakeFilesDirectory();
       tmpStr += "/CMakeDirectoryInformation.cmake";
-      cmakefileStream << "  \"" << lg->ConvertToRelativePath(binDir, tmpStr)
+      cmakefileStream << "  \""
+                      << lg->MaybeConvertToRelativePath(binDir, tmpStr)
                       << "\"\n";
     }
     cmakefileStream << "  )\n\n";
@@ -474,7 +479,7 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
 
   // Begin the directory-level rules section.
   std::string dir =
-    cmSystemTools::ConvertToOutputPath(lg->ConvertToRelativePath(
+    cmSystemTools::ConvertToOutputPath(lg->MaybeConvertToRelativePath(
       lg->GetBinaryDirectory(), lg->GetCurrentBinaryDirectory()));
   lg->WriteDivider(ruleFileStream);
   ruleFileStream << "# Directory level rules for directory " << dir << "\n\n";
@@ -526,9 +531,9 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
     if (fast) {
       tname += "/fast";
     }
-    cmOutputConverter conv(mf->GetStateSnapshot());
     tname =
-      conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname);
+      mf->GetStateSnapshot().GetDirectory().ConvertToRelPathIfNotContained(
+        mf->GetState()->GetBinaryDirectory(), tname);
     cmSystemTools::ConvertToOutputSlashes(tname);
     makeCommand.push_back(std::move(tname));
   }
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index cae46e1..c267a7b 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -367,7 +367,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
       if (vcprojName) {
         cmLocalGenerator* lg = target->GetLocalGenerator();
         std::string dir = lg->GetCurrentBinaryDirectory();
-        dir = root->ConvertToRelativePath(rootBinaryDir, dir.c_str());
+        dir = root->MaybeConvertToRelativePath(rootBinaryDir, dir.c_str());
         if (dir == ".") {
           dir.clear(); // msbuild cannot handle ".\" prefix
         }
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 80ccd73..3d6f36e 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -3570,7 +3570,7 @@ std::string cmGlobalXCodeGenerator::RelativeToSource(const char* p)
 
 std::string cmGlobalXCodeGenerator::RelativeToBinary(const char* p)
 {
-  return this->CurrentLocalGenerator->ConvertToRelativePath(
+  return this->CurrentLocalGenerator->MaybeConvertToRelativePath(
     cmSystemTools::JoinPath(this->ProjectOutputDirectoryComponents), p);
 }
 
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 9aa1f32..aa53552 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -5,8 +5,8 @@
 #include "cmListFileLexer.h"
 #include "cmMessageType.h"
 #include "cmMessenger.h"
-#include "cmOutputConverter.h"
 #include "cmState.h"
+#include "cmStateDirectory.h"
 #include "cmSystemTools.h"
 
 #include <assert.h>
@@ -390,9 +390,8 @@ void cmListFileBacktrace::PrintTitle(std::ostream& out) const
   }
   cmListFileContext lfc = this->TopEntry->Context;
   cmStateSnapshot bottom = this->GetBottom();
-  cmOutputConverter converter(bottom);
   if (!bottom.GetState()->GetIsInTryCompile()) {
-    lfc.FilePath = converter.ConvertToRelativePath(
+    lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
       bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
   }
   out << (lfc.Line ? " at " : " in ") << lfc;
@@ -409,7 +408,6 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
 
   bool first = true;
   cmStateSnapshot bottom = this->GetBottom();
-  cmOutputConverter converter(bottom);
   for (Entry const* cur = this->TopEntry->Parent.get(); !cur->IsBottom();
        cur = cur->Parent.get()) {
     if (cur->Context.Name.empty()) {
@@ -423,7 +421,7 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
     }
     cmListFileContext lfc = cur->Context;
     if (!bottom.GetState()->GetIsInTryCompile()) {
-      lfc.FilePath = converter.ConvertToRelativePath(
+      lfc.FilePath = bottom.GetDirectory().ConvertToRelPathIfNotContained(
         bottom.GetState()->GetSourceDirectory(), lfc.FilePath);
     }
     out << "  " << lfc << "\n";
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
index 7ce2c82..ad89335 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -47,7 +47,7 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
     target->GetFortranModuleDirectory(this->WorkingDirectory);
   if (!mod_dir.empty()) {
     mod_dir = this->ConvertToOutputFormat(
-      this->ConvertToRelativePath(this->WorkingDirectory, mod_dir),
+      this->MaybeConvertToRelativePath(this->WorkingDirectory, mod_dir),
       cmOutputConverter::SHELL);
   } else {
     mod_dir =
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 97e684b..89ad96d 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -316,7 +316,7 @@ void cmLocalGenerator::GenerateTestFiles()
   for (cmStateSnapshot const& i : children) {
     // TODO: Use add_subdirectory instead?
     std::string outP = i.GetDirectory().GetCurrentBinary();
-    outP = this->ConvertToRelativePath(parentBinDir, outP);
+    outP = this->MaybeConvertToRelativePath(parentBinDir, outP);
     outP = cmOutputConverter::EscapeForCMake(outP);
     fout << "subdirs(" << outP << ")" << std::endl;
   }
@@ -2294,7 +2294,7 @@ std::string cmLocalGenerator::ConstructComment(
     std::string currentBinaryDir = this->GetCurrentBinaryDirectory();
     for (std::string const& o : ccg.GetOutputs()) {
       comment += sep;
-      comment += this->ConvertToRelativePath(currentBinaryDir, o);
+      comment += this->MaybeConvertToRelativePath(currentBinaryDir, o);
       sep = ", ";
     }
     return comment;
@@ -2551,15 +2551,15 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
   std::string const& fullPath = source.GetFullPath();
 
   // Try referencing the source relative to the source tree.
-  std::string relFromSource =
-    this->ConvertToRelativePath(this->GetCurrentSourceDirectory(), fullPath);
+  std::string relFromSource = this->MaybeConvertToRelativePath(
+    this->GetCurrentSourceDirectory(), fullPath);
   assert(!relFromSource.empty());
   bool relSource = !cmSystemTools::FileIsFullPath(relFromSource);
   bool subSource = relSource && relFromSource[0] != '.';
 
   // Try referencing the source relative to the binary tree.
-  std::string relFromBinary =
-    this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), fullPath);
+  std::string relFromBinary = this->MaybeConvertToRelativePath(
+    this->GetCurrentBinaryDirectory(), fullPath);
   assert(!relFromBinary.empty());
   bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary);
   bool subBinary = relBinary && relFromBinary[0] != '.';
@@ -2658,6 +2658,13 @@ std::string const& cmLocalGenerator::GetCurrentSourceDirectory() const
   return this->StateSnapshot.GetDirectory().GetCurrentSource();
 }
 
+std::string cmLocalGenerator::MaybeConvertToRelativePath(
+  std::string const& local_path, std::string const& remote_path) const
+{
+  return this->StateSnapshot.GetDirectory().ConvertToRelPathIfNotContained(
+    local_path, remote_path);
+}
+
 std::string cmLocalGenerator::GetTargetDirectory(
   const cmGeneratorTarget* /*unused*/) const
 {
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index dc54314..4be3905 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -302,6 +302,16 @@ public:
   std::string const& GetCurrentSourceDirectory() const;
 
   /**
+   * Convert the given remote path to a relative path with respect to
+   * the given local path.  Both paths must use forward slashes and not
+   * already be escaped or quoted.
+   * The conversion is skipped if the paths are not both in the source
+   * or both in the binary tree.
+   */
+  std::string MaybeConvertToRelativePath(std::string const& local_path,
+                                         std::string const& remote_path) const;
+
+  /**
    * Generate a macOS application bundle Info.plist file.
    */
   void GenerateAppleInfoPList(cmGeneratorTarget* target,
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index a8647b1..f252045 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -54,7 +54,7 @@ void cmLocalNinjaGenerator::Generate()
 {
   // Compute the path to use when referencing the current output
   // directory from the top output directory.
-  this->HomeRelativeOutputPath = this->ConvertToRelativePath(
+  this->HomeRelativeOutputPath = this->MaybeConvertToRelativePath(
     this->GetBinaryDirectory(), this->GetCurrentBinaryDirectory());
   if (this->HomeRelativeOutputPath == ".") {
     this->HomeRelativeOutputPath.clear();
@@ -141,7 +141,8 @@ std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
                                        format);
   }
   return this->ConvertToOutputFormat(
-    this->ConvertToRelativePath(this->GetBinaryDirectory(), path), format);
+    this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), path),
+    format);
 }
 
 // Private methods.
@@ -584,8 +585,8 @@ std::string cmLocalNinjaGenerator::MakeCustomLauncher(
   if (!outputs.empty()) {
     output = outputs[0];
     if (ccg.GetWorkingDirectory().empty()) {
-      output =
-        this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), output);
+      output = this->MaybeConvertToRelativePath(
+        this->GetCurrentBinaryDirectory(), output);
     }
     output = this->ConvertToOutputFormat(output, cmOutputConverter::SHELL);
   }
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index e590e52..1d4793a 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -2088,12 +2088,3 @@ void cmLocalUnixMakefileGenerator3::CreateCDCommand(
                    [&prefix](std::string const& s) { return prefix + s; });
   }
 }
-
-std::string cmLocalUnixMakefileGenerator3::MaybeConvertToRelativePath(
-  std::string const& base, std::string const& path)
-{
-  if (!this->GetStateSnapshot().GetDirectory().ContainsBoth(base, path)) {
-    return path;
-  }
-  return cmSystemTools::ForceToRelativePath(base, path);
-}
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index ee6b37b..b256fdc 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -183,9 +183,6 @@ public:
   // Eclipse generator.
   void GetIndividualFileTargets(std::vector<std::string>& targets);
 
-  std::string MaybeConvertToRelativePath(std::string const& base,
-                                         std::string const& path);
-
 protected:
   void WriteLocalMakefile();
 
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 677d033..cd97dc4 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -803,8 +803,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
       target->GetProperty("Fortran_MODULE_DIRECTORY");
     std::string modDir;
     if (target_mod_dir) {
-      modDir = this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(),
-                                           target_mod_dir);
+      modDir = this->MaybeConvertToRelativePath(
+        this->GetCurrentBinaryDirectory(), target_mod_dir);
     } else {
       modDir = ".";
     }
@@ -1306,7 +1306,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputLibraries(
   for (ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) {
     if (l->IsPath) {
       std::string rel =
-        lg->ConvertToRelativePath(currentBinDir, l->Value.c_str());
+        lg->MaybeConvertToRelativePath(currentBinDir, l->Value.c_str());
       fout << lg->ConvertToXMLOutputPath(rel.c_str()) << " ";
     } else if (!l->Target ||
                l->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
@@ -1332,7 +1332,7 @@ void cmLocalVisualStudio7GeneratorInternals::OutputObjects(
        i != objs.end(); ++i) {
     if (!(*i)->GetObjectLibrary().empty()) {
       std::string const& objFile = (*i)->GetFullPath();
-      std::string rel = lg->ConvertToRelativePath(currentBinDir, objFile);
+      std::string rel = lg->MaybeConvertToRelativePath(currentBinDir, objFile);
       fout << sep << lg->ConvertToXMLOutputPath(rel.c_str());
       sep = " ";
     }
@@ -1358,7 +1358,7 @@ void cmLocalVisualStudio7Generator::OutputLibraryDirectories(
     // Switch to a relative path specification if it is shorter.
     if (cmSystemTools::FileIsFullPath(dir.c_str())) {
       std::string rel =
-        this->ConvertToRelativePath(currentBinDir, dir.c_str());
+        this->MaybeConvertToRelativePath(currentBinDir, dir.c_str());
       if (rel.size() < dir.size()) {
         dir = rel;
       }
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 2237da7..660729c 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -210,9 +210,10 @@ std::string cmLocalVisualStudioGenerator::ConstructScript(
     }
 
     if (workingDirectory.empty()) {
-      script += this->ConvertToOutputFormat(
-        this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), cmd),
-        cmOutputConverter::SHELL);
+      script +=
+        this->ConvertToOutputFormat(this->MaybeConvertToRelativePath(
+                                      this->GetCurrentBinaryDirectory(), cmd),
+                                    cmOutputConverter::SHELL);
     } else {
       script += this->ConvertToOutputFormat(cmd.c_str(), SHELL);
     }
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index 011c7d8..7d88b08 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -10,7 +10,6 @@
 #include <vector>
 
 #include "cmState.h"
-#include "cmStateDirectory.h"
 #include "cmSystemTools.h"
 
 cmOutputConverter::cmOutputConverter(cmStateSnapshot const& snapshot)
@@ -72,17 +71,6 @@ std::string cmOutputConverter::ConvertDirectorySeparatorsForShell(
   return result;
 }
 
-std::string cmOutputConverter::ConvertToRelativePath(
-  std::string const& local_path, std::string const& remote_path) const
-{
-  if (!this->StateSnapshot.GetDirectory().ContainsBoth(local_path,
-                                                       remote_path)) {
-    return remote_path;
-  }
-
-  return cmSystemTools::ForceToRelativePath(local_path, remote_path);
-}
-
 static bool cmOutputConverterIsShellOperator(const std::string& str)
 {
   static std::set<std::string> shellOperators;
diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h
index 5a4f879..6438c7b 100644
--- a/Source/cmOutputConverter.h
+++ b/Source/cmOutputConverter.h
@@ -91,16 +91,6 @@ public:
   };
   static FortranFormat GetFortranFormat(const char* value);
 
-  /**
-   * Convert the given remote path to a relative path with respect to
-   * the given local path.  Both paths must use forward slashes and not
-   * already be escaped or quoted.
-   * The conversion is skipped if the paths are not both in the source
-   * or both in the binary tree.
-   */
-  std::string ConvertToRelativePath(std::string const& local_path,
-                                    std::string const& remote_path) const;
-
 private:
   cmState* GetState() const;
 
diff --git a/Source/cmStateDirectory.cxx b/Source/cmStateDirectory.cxx
index 40f694c..6752743 100644
--- a/Source/cmStateDirectory.cxx
+++ b/Source/cmStateDirectory.cxx
@@ -155,6 +155,15 @@ bool cmStateDirectory::ContainsBoth(std::string const& local_path,
   return bothInBinary || bothInSource;
 }
 
+std::string cmStateDirectory::ConvertToRelPathIfNotContained(
+  std::string const& local_path, std::string const& remote_path) const
+{
+  if (!this->ContainsBoth(local_path, remote_path)) {
+    return remote_path;
+  }
+  return cmSystemTools::ForceToRelativePath(local_path, remote_path);
+}
+
 cmStateDirectory::cmStateDirectory(
   cmLinkedTree<cmStateDetail::BuildsystemDirectoryStateType>::iterator iter,
   const cmStateSnapshot& snapshot)
diff --git a/Source/cmStateDirectory.h b/Source/cmStateDirectory.h
index c4b18ad..6956594 100644
--- a/Source/cmStateDirectory.h
+++ b/Source/cmStateDirectory.h
@@ -35,6 +35,9 @@ public:
   bool ContainsBoth(std::string const& local_path,
                     std::string const& remote_path) const;
 
+  std::string ConvertToRelPathIfNotContained(
+    std::string const& local_path, std::string const& remote_path) const;
+
   cmStringRange GetIncludeDirectoriesEntries() const;
   cmBacktraceRange GetIncludeDirectoriesEntryBacktraces() const;
   void AppendIncludeDirectoriesEntry(std::string const& vec,
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index fe48934..93cdd46 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -19,7 +19,6 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmMessenger.h"
-#include "cmOutputConverter.h"
 #include "cmProperty.h"
 #include "cmSourceFile.h"
 #include "cmSourceFileLocation.h"
@@ -747,11 +746,12 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const
   const char* sigString =
     (sig == cmTarget::KeywordTLLSignature ? "keyword" : "plain");
   s << "The uses of the " << sigString << " signature are here:\n";
-  cmOutputConverter converter(this->GetMakefile()->GetStateSnapshot());
+  cmStateDirectory cmDir =
+    this->GetMakefile()->GetStateSnapshot().GetDirectory();
   for (auto const& cmd : this->TLLCommands) {
     if (cmd.first == sig) {
       cmListFileContext lfc = cmd.second;
-      lfc.FilePath = converter.ConvertToRelativePath(
+      lfc.FilePath = cmDir.ConvertToRelPathIfNotContained(
         this->Makefile->GetState()->GetSourceDirectory(), lfc.FilePath);
       s << " * " << lfc << std::endl;
     }
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index ac4a4f5..9d7dd07 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -3584,8 +3584,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
     this->LocalGenerator->GetCurrentBinaryDirectory();
   for (cmComputeLinkInformation::Item const& l : libs) {
     if (l.IsPath && cmVS10IsTargetsFile(l.Value)) {
-      std::string path =
-        this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value);
+      std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
+        currentBinDir, l.Value);
       ConvertToWindowsSlash(path);
       this->AddTargetsFileAndConfigPair(path, config);
     }
@@ -3668,8 +3668,8 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
     }
 
     if (l.IsPath) {
-      std::string path =
-        this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value);
+      std::string path = this->LocalGenerator->MaybeConvertToRelativePath(
+        currentBinDir, l.Value);
       ConvertToWindowsSlash(path);
       if (cmVS10IsTargetsFile(l.Value)) {
         vsTargetVec.push_back(path);

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=638667efa2b0e5fff5c63bf936748a60b602ae90
commit 638667efa2b0e5fff5c63bf936748a60b602ae90
Author:     Florian Maushart <FloriansGit at online.ms>
AuthorDate: Sun Jul 15 08:44:23 2018 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Jan 25 08:21:14 2019 -0500

    cmake: cmcmd.cxx fix "The arguments are" comments
    
    Changed "argv" to "args" in comments to match parameter names

diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 26f7509..5ae0ea4 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -1351,8 +1351,8 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num)
 int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
 {
   // The arguments are
-  //   argv[0] == <cmake-executable>
-  //   argv[1] == cmake_echo_color
+  //   args[0] == <cmake-executable>
+  //   args[1] == cmake_echo_color
 
   bool enabled = true;
   int color = cmsysTerminal_Color_Normal;
@@ -1409,10 +1409,10 @@ int cmcmd::ExecuteEchoColor(std::vector<std::string>& args)
 int cmcmd::ExecuteLinkScript(std::vector<std::string>& args)
 {
   // The arguments are
-  //   argv[0] == <cmake-executable>
-  //   argv[1] == cmake_link_script
-  //   argv[2] == <link-script-name>
-  //   argv[3] == --verbose=?
+  //   args[0] == <cmake-executable>
+  //   args[1] == cmake_link_script
+  //   args[2] == <link-script-name>
+  //   args[3] == --verbose=?
   bool verbose = false;
   if (args.size() >= 4) {
     if (args[3].find("--verbose=") == 0) {

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=3ca44029668c057fb208c5f153c4d398bee954cb
commit 3ca44029668c057fb208c5f153c4d398bee954cb
Author:     Florian Maushart <FloriansGit at online.ms>
AuthorDate: Tue Jun 26 21:24:19 2018 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Jan 25 08:21:13 2019 -0500

    ctest: Fix --build-and-test without --build-target on Xcode

diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index e9b82cf..97d8bdb 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -348,11 +348,13 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand(
   makeCommand.add(
     this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand()));
 
-  makeCommand.add("-project");
-  std::string projectArg = projectName;
-  projectArg += ".xcode";
-  projectArg += "proj";
-  makeCommand.add(projectArg);
+  if (!projectName.empty()) {
+    makeCommand.add("-project");
+    std::string projectArg = projectName;
+    projectArg += ".xcode";
+    projectArg += "proj";
+    makeCommand.add(projectArg);
+  }
 
   bool clean = false;
   std::string realTarget = targetName;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cb6c233eccfbb600ec16716224062627df2ff2c0
commit cb6c233eccfbb600ec16716224062627df2ff2c0
Author:     Florian Maushart <FloriansGit at online.ms>
AuthorDate: Sun Jun 10 21:39:01 2018 +0200
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Jan 25 08:20:51 2019 -0500

    cmake: Add -hideShellScriptEnvironment xcodebuild option
    
    For CMake's build tool mode add -hideShellScriptEnvironment if version
    is XCode 7.0 or above

diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index b8aa5a6..e9b82cf 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -372,6 +372,9 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand(
     }
   }
 
+  if (this->XcodeVersion >= 70) {
+    makeCommand.add("-hideShellScriptEnvironment");
+  }
   makeCommand.add(makeOptions.begin(), makeOptions.end());
 }
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1a45266cb544d73a7d7e46d6129ead1faf71fa85
commit 1a45266cb544d73a7d7e46d6129ead1faf71fa85
Author:     Robert Maynard <robert.maynard at kitware.com>
AuthorDate: Tue Oct 30 16:13:33 2018 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Jan 25 08:20:02 2019 -0500

    cmGlobalGenerator: Add a class that represent the build command
    
    This refactors a std::vector<std::string> into a class so that
    we can extend the features to represent things such as multiple
    chained commands in the future.

diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 56714b1..c2eb583 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -54,7 +54,7 @@ void cmGlobalBorlandMakefileGenerator::GetDocumentation(
 }
 
 void cmGlobalBorlandMakefileGenerator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& projectDir,
   const std::string& targetName, const std::string& config, bool fast,
   int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions)
diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h
index 27de6cc..ca04b7b 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.h
+++ b/Source/cmGlobalBorlandMakefileGenerator.h
@@ -46,7 +46,7 @@ public:
   bool AllowDeleteOnError() const override { return false; }
 
 protected:
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index b2b0e38..239b326 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1751,14 +1751,13 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir,
 }
 
 void cmGlobalGenerator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& /*unused*/,
+  GeneratedMakeCommand& makeCommand, const std::string& /*unused*/,
   const std::string& /*unused*/, const std::string& /*unused*/,
   const std::string& /*unused*/, const std::string& /*unused*/,
   bool /*unused*/, int /*unused*/, bool /*unused*/,
   std::vector<std::string> const& /*unused*/)
 {
-  makeCommand.emplace_back(
-    "cmGlobalGenerator::GenerateBuildCommand not implemented");
+  makeCommand.add("cmGlobalGenerator::GenerateBuildCommand not implemented");
 }
 
 void cmGlobalGenerator::PrintBuildCommandAdvice(std::ostream& /*os*/,
@@ -1802,31 +1801,29 @@ int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/,
   std::string outputBuffer;
   std::string* outputPtr = &outputBuffer;
 
-  std::vector<std::string> makeCommand;
+  GeneratedMakeCommand makeCommand;
   this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName, bindir,
                              target, config, fast, jobs, verbose,
                              nativeOptions);
 
-  // Workaround to convince VCExpress.exe to produce output.
+  // Workaround to convince some commands to produce output.
   if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH &&
-      !makeCommand.empty() &&
-      cmSystemTools::LowerCase(
-        cmSystemTools::GetFilenameName(makeCommand[0])) == "vcexpress.exe") {
+      makeCommand.RequiresOutputForward) {
     outputflag = cmSystemTools::OUTPUT_FORWARD;
   }
 
   // should we do a clean first?
   if (clean) {
-    std::vector<std::string> cleanCommand;
+    GeneratedMakeCommand cleanCommand;
     this->GenerateBuildCommand(cleanCommand, makeCommandCSTR, projectName,
                                bindir, "clean", config, fast, jobs, verbose);
     output += "\nRun Clean Command:";
-    output += cmSystemTools::PrintSingleCommand(cleanCommand);
+    output += cleanCommand.printable();
     output += "\n";
 
-    if (!cmSystemTools::RunSingleCommand(cleanCommand, outputPtr, outputPtr,
-                                         &retVal, nullptr, outputflag,
-                                         timeout)) {
+    if (!cmSystemTools::RunSingleCommand(cleanCommand.PrimaryCommand,
+                                         outputPtr, outputPtr, &retVal,
+                                         nullptr, outputflag, timeout)) {
       cmSystemTools::SetRunCommandHideConsole(hideconsole);
       cmSystemTools::Error("Generator: execution of make clean failed.");
       output += *outputPtr;
@@ -1838,13 +1835,13 @@ int cmGlobalGenerator::Build(int jobs, const std::string& /*unused*/,
   }
 
   // now build
-  std::string makeCommandStr = cmSystemTools::PrintSingleCommand(makeCommand);
-  output += "\nRun Build Command:";
+  std::string makeCommandStr = makeCommand.printable();
+  output += "\nRun Build Command(s):";
   output += makeCommandStr;
   output += "\n";
 
-  if (!cmSystemTools::RunSingleCommand(makeCommand, outputPtr, outputPtr,
-                                       &retVal, nullptr, outputflag,
+  if (!cmSystemTools::RunSingleCommand(makeCommand.PrimaryCommand, outputPtr,
+                                       outputPtr, &retVal, nullptr, outputflag,
                                        timeout)) {
     cmSystemTools::SetRunCommandHideConsole(hideconsole);
     cmSystemTools::Error(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 36d3d10..ca5708b 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -41,6 +41,54 @@ class cmSourceFile;
 class cmStateDirectory;
 class cmake;
 
+namespace detail {
+inline void AppendStrs(std::vector<std::string>&)
+{
+}
+template <typename T, typename... Ts>
+inline void AppendStrs(std::vector<std::string>& command, T&& s, Ts&&... ts)
+{
+  command.emplace_back(std::forward<T>(s));
+  AppendStrs(command, std::forward<Ts>(ts)...);
+}
+
+struct GeneratedMakeCommand
+{
+  // Add each argument as a separate element to the vector
+  template <typename... T>
+  void add(T&&... args)
+  {
+    // iterate the args and append each one
+    AppendStrs(PrimaryCommand, std::forward<T>(args)...);
+  }
+
+  // Add each value in the iterators as a separate element to the vector
+  void add(std::vector<std::string>::const_iterator start,
+           std::vector<std::string>::const_iterator end)
+  {
+    PrimaryCommand.insert(PrimaryCommand.end(), start, end);
+  }
+
+  std::string printable() const
+  {
+    std::size_t size = PrimaryCommand.size();
+    for (auto&& i : PrimaryCommand) {
+      size += i.size();
+    }
+    std::string buffer;
+    buffer.reserve(size);
+    for (auto&& i : PrimaryCommand) {
+      buffer.append(i);
+      buffer.append(1, ' ');
+    }
+    return buffer;
+  }
+
+  std::vector<std::string> PrimaryCommand;
+  bool RequiresOutputForward = false;
+};
+}
+
 /** \class cmGlobalGenerator
  * \brief Responsible for overseeing the generation process for the entire tree
  *
@@ -182,8 +230,12 @@ public:
   virtual bool Open(const std::string& bindir, const std::string& projectName,
                     bool dryRun);
 
+  struct GeneratedMakeCommand final : public detail::GeneratedMakeCommand
+  {
+  };
+
   virtual void GenerateBuildCommand(
-    std::vector<std::string>& makeCommand, const std::string& makeProgram,
+    GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
     const std::string& projectName, const std::string& projectDir,
     const std::string& targetName, const std::string& config, bool fast,
     int jobs, bool verbose,
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 557efec..2a1506f 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -370,25 +370,23 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
 }
 
 void cmGlobalGhsMultiGenerator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& projectDir,
   const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
   int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
 {
   const char* gbuild =
     this->CMakeInstance->GetCacheDefinition("CMAKE_MAKE_PROGRAM");
-  makeCommand.push_back(
-    this->SelectMakeProgram(makeProgram, (std::string)gbuild));
+  makeCommand.add(this->SelectMakeProgram(makeProgram, (std::string)gbuild));
 
   if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
-    makeCommand.push_back("-parallel");
+    makeCommand.add("-parallel");
     if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
-      makeCommand.push_back(std::to_string(jobs));
+      makeCommand.add(std::to_string(jobs));
     }
   }
 
-  makeCommand.insert(makeCommand.end(), makeOptions.begin(),
-                     makeOptions.end());
+  makeCommand.add(makeOptions.begin(), makeOptions.end());
 
   /* determine which top-project file to use */
   std::string proj = projectName + ".top" + FILE_EXTENSION;
@@ -401,16 +399,15 @@ void cmGlobalGhsMultiGenerator::GenerateBuildCommand(
     }
   }
 
-  makeCommand.push_back("-top");
-  makeCommand.push_back(proj);
+  makeCommand.add("-top", proj);
   if (!targetName.empty()) {
     if (targetName == "clean") {
-      makeCommand.push_back("-clean");
+      makeCommand.add("-clean");
     } else {
       if (targetName.compare(targetName.size() - 4, 4, ".gpj") == 0) {
-        makeCommand.push_back(targetName);
+        makeCommand.add(targetName);
       } else {
-        makeCommand.push_back(targetName + ".gpj");
+        makeCommand.add(targetName + ".gpj");
       }
     }
   }
diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h
index 9332567..bc2b199 100644
--- a/Source/cmGlobalGhsMultiGenerator.h
+++ b/Source/cmGlobalGhsMultiGenerator.h
@@ -88,7 +88,7 @@ public:
 
 protected:
   void Generate() override;
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,
diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx
index 9c805a8..2b7f486 100644
--- a/Source/cmGlobalJOMMakefileGenerator.cxx
+++ b/Source/cmGlobalJOMMakefileGenerator.cxx
@@ -55,7 +55,7 @@ void cmGlobalJOMMakefileGenerator::PrintCompilerAdvice(
 }
 
 void cmGlobalJOMMakefileGenerator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& projectDir,
   const std::string& targetName, const std::string& config, bool fast,
   int jobs, bool verbose, std::vector<std::string> const& makeOptions)
diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h
index bcf46d0..aa8b5fb 100644
--- a/Source/cmGlobalJOMMakefileGenerator.h
+++ b/Source/cmGlobalJOMMakefileGenerator.h
@@ -40,7 +40,7 @@ public:
                       bool optional) override;
 
 protected:
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,
diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx
index 5235be7..ffe95f9 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.cxx
+++ b/Source/cmGlobalNMakeMakefileGenerator.cxx
@@ -55,7 +55,7 @@ void cmGlobalNMakeMakefileGenerator::PrintCompilerAdvice(
 }
 
 void cmGlobalNMakeMakefileGenerator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& projectDir,
   const std::string& targetName, const std::string& config, bool fast,
   int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions)
diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h
index 62dea6e..06c48e2 100644
--- a/Source/cmGlobalNMakeMakefileGenerator.h
+++ b/Source/cmGlobalNMakeMakefileGenerator.h
@@ -45,7 +45,7 @@ public:
                       bool optional) override;
 
 protected:
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 23dbd76..abeecc7 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -673,31 +673,28 @@ void cmGlobalNinjaGenerator::EnableLanguage(
 // Called by:
 //   cmGlobalGenerator::Build()
 void cmGlobalNinjaGenerator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& /*projectName*/, const std::string& /*projectDir*/,
   const std::string& targetName, const std::string& /*config*/, bool /*fast*/,
   int jobs, bool verbose, std::vector<std::string> const& makeOptions)
 {
-  makeCommand.push_back(this->SelectMakeProgram(makeProgram));
+  makeCommand.add(this->SelectMakeProgram(makeProgram));
 
   if (verbose) {
-    makeCommand.emplace_back("-v");
+    makeCommand.add("-v");
   }
 
   if ((jobs != cmake::NO_BUILD_PARALLEL_LEVEL) &&
       (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL)) {
-    makeCommand.emplace_back("-j");
-    makeCommand.push_back(std::to_string(jobs));
+    makeCommand.add("-j", std::to_string(jobs));
   }
 
-  makeCommand.insert(makeCommand.end(), makeOptions.begin(),
-                     makeOptions.end());
+  makeCommand.add(makeOptions.begin(), makeOptions.end());
   if (!targetName.empty()) {
     if (targetName == "clean") {
-      makeCommand.emplace_back("-t");
-      makeCommand.emplace_back("clean");
+      makeCommand.add("-t", "clean");
     } else {
-      makeCommand.push_back(targetName);
+      makeCommand.add(targetName);
     }
   }
 }
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 00fa348..63b2f38 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -202,7 +202,7 @@ public:
   void EnableLanguage(std::vector<std::string> const& languages,
                       cmMakefile* mf, bool optional) override;
 
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 52bb046..9fc60e7 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -490,7 +490,7 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
 }
 
 void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& /*projectName*/, const std::string& /*projectDir*/,
   const std::string& targetName, const std::string& /*config*/, bool fast,
   int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
@@ -510,17 +510,16 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
     mf = mfu.get();
   }
 
-  makeCommand.push_back(this->SelectMakeProgram(makeProgram));
+  makeCommand.add(this->SelectMakeProgram(makeProgram));
 
   if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
-    makeCommand.emplace_back("-j");
+    makeCommand.add("-j");
     if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
-      makeCommand.push_back(std::to_string(jobs));
+      makeCommand.add(std::to_string(jobs));
     }
   }
 
-  makeCommand.insert(makeCommand.end(), makeOptions.begin(),
-                     makeOptions.end());
+  makeCommand.add(makeOptions.begin(), makeOptions.end());
   if (!targetName.empty()) {
     std::string tname = targetName;
     if (fast) {
@@ -530,7 +529,7 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
     tname =
       conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname);
     cmSystemTools::ConvertToOutputSlashes(tname);
-    makeCommand.push_back(std::move(tname));
+    makeCommand.add(std::move(tname));
   }
 }
 
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 6199586..9fd407f 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -127,7 +127,7 @@ public:
   std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; }
 
   // change the build command for speed
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index dbe582b..051ef18 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -864,7 +864,7 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
 }
 
 void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& projectDir,
   const std::string& targetName, const std::string& config, bool fast,
   int jobs, bool verbose, std::vector<std::string> const& makeOptions)
@@ -879,6 +879,10 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
   bool useDevEnv = (makeProgramLower.find("devenv") != std::string::npos ||
                     makeProgramLower.find("vcexpress") != std::string::npos);
 
+  // Workaround to convince VCExpress.exe to produce output.
+  makeCommand.RequiresOutputForward =
+    (makeProgramLower.find("vcexpress") != std::string::npos);
+
   // MSBuild is preferred (and required for VS Express), but if the .sln has
   // an Intel Fortran .vfproj then we have to use devenv. Parse it to find out.
   cmSlnData slnData;
@@ -912,7 +916,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
     return;
   }
 
-  makeCommand.push_back(makeProgramSelected);
+  makeCommand.add(makeProgramSelected);
 
   std::string realTarget = targetName;
   // msbuild.exe CxxOnly.sln /t:Build /p:Configuration=Debug /target:ALL_BUILD
@@ -921,8 +925,8 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
     realTarget = "ALL_BUILD";
   }
   if (realTarget == "clean") {
-    makeCommand.push_back(std::string(projectName) + ".sln");
-    makeCommand.push_back("/t:Clean");
+    makeCommand.add(std::string(projectName) + ".sln");
+    makeCommand.add("/t:Clean");
   } else {
     std::string targetProject(realTarget);
     targetProject += ".vcxproj";
@@ -934,7 +938,7 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
         cmSystemTools::ConvertToUnixSlashes(targetProject);
       }
     }
-    makeCommand.push_back(targetProject);
+    makeCommand.add(std::move(targetProject));
   }
   std::string configArg = "/p:Configuration=";
   if (!config.empty()) {
@@ -942,23 +946,22 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
   } else {
     configArg += "Debug";
   }
-  makeCommand.push_back(configArg);
-  makeCommand.push_back("/p:Platform=" + this->GetPlatformName());
-  makeCommand.push_back(std::string("/p:VisualStudioVersion=") +
-                        this->GetIDEVersion());
+  makeCommand.add(configArg);
+  makeCommand.add(std::string("/p:Platform=") + this->GetPlatformName());
+  makeCommand.add(std::string("/p:VisualStudioVersion=") +
+                  this->GetIDEVersion());
 
   if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
     if (jobs == cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
-      makeCommand.push_back("/m");
+      makeCommand.add("/m");
     } else {
-      makeCommand.push_back(std::string("/m:") + std::to_string(jobs));
+      makeCommand.add(std::string("/m:") + std::to_string(jobs));
     }
     // Having msbuild.exe and cl.exe using multiple jobs is discouraged
-    makeCommand.push_back("/p:CL_MPCount=1");
+    makeCommand.add("/p:CL_MPCount=1");
   }
 
-  makeCommand.insert(makeCommand.end(), makeOptions.begin(),
-                     makeOptions.end());
+  makeCommand.add(makeOptions.begin(), makeOptions.end());
 }
 
 bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 7c8918a..0b11569 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -22,7 +22,7 @@ public:
   bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
   bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
 
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index cae46e1..997d33f 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -191,7 +191,7 @@ const char* cmGlobalVisualStudio7Generator::ExternalProjectType(
   return "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942";
 }
 void cmGlobalVisualStudio7Generator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& /*projectDir*/,
   const std::string& targetName, const std::string& config, bool /*fast*/,
   int /*jobs*/, bool /*verbose*/, std::vector<std::string> const& makeOptions)
@@ -209,35 +209,25 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand(
     makeProgramSelected = this->GetDevEnvCommand();
   }
 
-  makeCommand.push_back(makeProgramSelected);
+  // Workaround to convince VCExpress.exe to produce output.
+  makeCommand.RequiresOutputForward =
+    (makeProgramLower.find("vcexpress") != std::string::npos);
 
-  makeCommand.push_back(std::string(projectName) + ".sln");
+  makeCommand.add(makeProgramSelected);
+
+  makeCommand.add(std::string(projectName) + ".sln");
   std::string realTarget = targetName;
   bool clean = false;
   if (realTarget == "clean") {
     clean = true;
     realTarget = "ALL_BUILD";
   }
-  if (clean) {
-    makeCommand.push_back("/clean");
-  } else {
-    makeCommand.push_back("/build");
-  }
-
-  if (!config.empty()) {
-    makeCommand.push_back(config);
-  } else {
-    makeCommand.push_back("Debug");
-  }
-  makeCommand.push_back("/project");
 
-  if (!realTarget.empty()) {
-    makeCommand.push_back(realTarget);
-  } else {
-    makeCommand.push_back("ALL_BUILD");
-  }
-  makeCommand.insert(makeCommand.end(), makeOptions.begin(),
-                     makeOptions.end());
+  makeCommand.add((clean ? "/clean" : "/build"));
+  makeCommand.add((config.empty() ? "Debug" : config));
+  makeCommand.add("/project");
+  makeCommand.add((realTarget.empty() ? "ALL_BUILD" : realTarget));
+  makeCommand.add(makeOptions.begin(), makeOptions.end());
 }
 
 ///! Create a local generator appropriate to this Global Generator
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index d2a2a38..3f1c173 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -52,7 +52,7 @@ public:
    * Try running cmake and building a file. This is used for dynamically
    * loaded commands, not as part of the usual build process.
    */
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,
diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx
index 558ef15..c02c471 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.cxx
+++ b/Source/cmGlobalWatcomWMakeGenerator.cxx
@@ -51,7 +51,7 @@ void cmGlobalWatcomWMakeGenerator::GetDocumentation(
 }
 
 void cmGlobalWatcomWMakeGenerator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& projectDir,
   const std::string& targetName, const std::string& config, bool fast,
   int /*jobs*/, bool verbose, std::vector<std::string> const& makeOptions)
diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h
index 0d10d58..6680b19 100644
--- a/Source/cmGlobalWatcomWMakeGenerator.h
+++ b/Source/cmGlobalWatcomWMakeGenerator.h
@@ -50,7 +50,7 @@ public:
   bool AllowDeleteOnError() const override { return false; }
 
 protected:
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 79d77e7..b8aa5a6 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -339,20 +339,20 @@ bool cmGlobalXCodeGenerator::Open(const std::string& bindir,
 }
 
 void cmGlobalXCodeGenerator::GenerateBuildCommand(
-  std::vector<std::string>& makeCommand, const std::string& makeProgram,
+  GeneratedMakeCommand& makeCommand, const std::string& makeProgram,
   const std::string& projectName, const std::string& /*projectDir*/,
   const std::string& targetName, const std::string& config, bool /*fast*/,
   int jobs, bool /*verbose*/, std::vector<std::string> const& makeOptions)
 {
   // now build the test
-  makeCommand.emplace_back(
+  makeCommand.add(
     this->SelectMakeProgram(makeProgram, this->GetXcodeBuildCommand()));
 
-  makeCommand.emplace_back("-project");
+  makeCommand.add("-project");
   std::string projectArg = projectName;
   projectArg += ".xcode";
   projectArg += "proj";
-  makeCommand.emplace_back(projectArg);
+  makeCommand.add(projectArg);
 
   bool clean = false;
   std::string realTarget = targetName;
@@ -360,29 +360,19 @@ void cmGlobalXCodeGenerator::GenerateBuildCommand(
     clean = true;
     realTarget = "ALL_BUILD";
   }
-  if (clean) {
-    makeCommand.emplace_back("clean");
-  } else {
-    makeCommand.emplace_back("build");
-  }
-  makeCommand.emplace_back("-target");
-  if (!realTarget.empty()) {
-    makeCommand.emplace_back(realTarget);
-  } else {
-    makeCommand.emplace_back("ALL_BUILD");
-  }
-  makeCommand.emplace_back("-configuration");
-  makeCommand.emplace_back(!config.empty() ? config : "Debug");
+
+  makeCommand.add((clean ? "clean" : "build"));
+  makeCommand.add("-target", (realTarget.empty() ? "ALL_BUILD" : realTarget));
+  makeCommand.add("-configuration", (config.empty() ? "Debug" : config));
 
   if (jobs != cmake::NO_BUILD_PARALLEL_LEVEL) {
-    makeCommand.emplace_back("-jobs");
+    makeCommand.add("-jobs");
     if (jobs != cmake::DEFAULT_BUILD_PARALLEL_LEVEL) {
-      makeCommand.emplace_back(std::to_string(jobs));
+      makeCommand.add(std::to_string(jobs));
     }
   }
 
-  makeCommand.insert(makeCommand.end(), makeOptions.begin(),
-                     makeOptions.end());
+  makeCommand.add(makeOptions.begin(), makeOptions.end());
 }
 
 ///! Create a local generator appropriate to this Global Generator
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 9b0d4fe..92ff258 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -66,7 +66,7 @@ public:
    * Try running cmake and building a file. This is used for dynalically
    * loaded commands, not as part of the usual build process.
    */
-  void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+  void GenerateBuildCommand(GeneratedMakeCommand& makeCommand,
                             const std::string& makeProgram,
                             const std::string& projectName,
                             const std::string& projectDir,

-----------------------------------------------------------------------

Summary of changes:
 Help/envvar/CMAKE_NO_VERBOSE.rst                   |   8 +
 Help/envvar/VERBOSE.rst                            |  10 ++
 Help/manual/cmake-env-variables.7.rst              |   2 +
 Help/manual/cmake.1.rst                            |   8 +
 Help/release/dev/cmake-build-verbose.rst           |   6 +
 Source/CTest/cmCTestBuildHandler.cxx               |   3 +-
 Source/cmCallVisualStudioMacro.cxx                 |   4 +-
 Source/cmCommonTargetGenerator.cxx                 |   2 +-
 Source/cmComputeLinkInformation.cxx                |   2 +-
 Source/cmDepends.cxx                               |   8 +-
 Source/cmDependsC.cxx                              |   9 +-
 Source/cmExtraEclipseCDT4Generator.cxx             |   2 +-
 Source/cmFLTKWrapUICommand.cxx                     |   2 +-
 Source/cmFileTimeComparison.cxx                    |  27 ++--
 Source/cmFileTimeComparison.h                      |   7 +-
 Source/cmGhsMultiTargetGenerator.cxx               |  11 +-
 Source/cmGlobalBorlandMakefileGenerator.cxx        |   2 +-
 Source/cmGlobalBorlandMakefileGenerator.h          |   2 +-
 Source/cmGlobalGenerator.cxx                       |  39 +++--
 Source/cmGlobalGenerator.h                         |  54 ++++++-
 Source/cmGlobalGhsMultiGenerator.cxx               |  25 ++--
 Source/cmGlobalGhsMultiGenerator.h                 |   2 +-
 Source/cmGlobalJOMMakefileGenerator.cxx            |   2 +-
 Source/cmGlobalJOMMakefileGenerator.h              |   2 +-
 Source/cmGlobalNMakeMakefileGenerator.cxx          |   2 +-
 Source/cmGlobalNMakeMakefileGenerator.h            |   2 +-
 Source/cmGlobalNinjaGenerator.cxx                  |  19 +--
 Source/cmGlobalNinjaGenerator.h                    |   2 +-
 Source/cmGlobalUnixMakefileGenerator3.cxx          |  43 ++++--
 Source/cmGlobalUnixMakefileGenerator3.h            |   2 +-
 Source/cmGlobalVisualStudio10Generator.cxx         |  35 +++--
 Source/cmGlobalVisualStudio10Generator.h           |   2 +-
 Source/cmGlobalVisualStudio7Generator.cxx          |  36 ++---
 Source/cmGlobalVisualStudio7Generator.h            |   2 +-
 Source/cmGlobalVisualStudioGenerator.cxx           |   4 +-
 Source/cmGlobalWatcomWMakeGenerator.cxx            |   2 +-
 Source/cmGlobalWatcomWMakeGenerator.h              |   2 +-
 Source/cmGlobalXCodeGenerator.cxx                  |  45 +++---
 Source/cmGlobalXCodeGenerator.h                    |   2 +-
 Source/cmInstallCommand.cxx                        |   2 +-
 Source/cmInstallTargetGenerator.cxx                |   2 +-
 Source/cmListFileCache.cxx                         |   8 +-
 Source/cmLocalCommonGenerator.cxx                  |   2 +-
 Source/cmLocalGenerator.cxx                        |  23 ++-
 Source/cmLocalGenerator.h                          |  10 ++
 Source/cmLocalNinjaGenerator.cxx                   |   9 +-
 Source/cmLocalUnixMakefileGenerator3.cxx           |  15 +-
 Source/cmLocalUnixMakefileGenerator3.h             |   3 -
 Source/cmLocalVisualStudio7Generator.cxx           |  10 +-
 Source/cmLocalVisualStudioGenerator.cxx            |   7 +-
 Source/cmMakefile.cxx                              |   6 +-
 Source/cmMakefileTargetGenerator.cxx               |   2 +-
 Source/cmMessageCommand.cxx                        |   2 +-
 Source/cmMessenger.cxx                             |   4 +-
 Source/cmOutputConverter.cxx                       |  12 --
 Source/cmOutputConverter.h                         |  10 --
 Source/cmStateDirectory.cxx                        |   9 ++
 Source/cmStateDirectory.h                          |   3 +
 Source/cmSystemTools.cxx                           |   4 +-
 Source/cmSystemTools.h                             |   4 +
 Source/cmTarget.cxx                                |   6 +-
 Source/cmUtilitySourceCommand.cxx                  |   2 +-
 Source/cmVisualStudio10TargetGenerator.cxx         |   8 +-
 Source/cmake.cxx                                   |  24 ++-
 Source/cmake.h                                     |   3 +-
 Source/cmakemain.cxx                               |   9 +-
 Source/cmcmd.cxx                                   |  12 +-
 Tests/CMakeLists.txt                               |  35 ++++-
 Tests/ExternalProjectLocal/CMakeLists.txt          | 129 +++++++---------
 .../Step5/CMakeLists.txt                           |   1 -
 .../Step5/MathFunctions/CMakeLists.txt             |   0
 .../Step5}/MathFunctions/MakeTable.cxx             |   0
 .../Step5}/MathFunctions/MathFunctions.h           |   0
 .../Step5}/MathFunctions/mysqrt.cxx                |   0
 .../Step5}/TutorialConfig.h.in                     |   1 -
 .../Step5}/tutorial.cxx                            |   0
 Tests/RunCMake/CMakeLists.txt                      |   2 +-
 Tests/RunCMake/Make/RunCMakeTest.cmake             |  17 +++
 Tests/RunCMake/Make/VerboseBuild-build-stdout.txt  |   1 +
 .../VerboseBuild-build-watcom-stdout.txt}          |   0
 .../Make/VerboseBuild-nowork-gnu-stdout.txt        |   1 +
 Tests/RunCMake/Make/VerboseBuild.cmake             |   8 +
 Tests/RunCMake/{Ninja => Make}/hello.c             |   0
 Tests/RunCMake/Ninja/RunCMakeTest.cmake            |   9 ++
 Tests/RunCMake/Ninja/VerboseBuild-build-stdout.txt |   1 +
 ...k-stdout.txt => VerboseBuild-nowork-stdout.txt} |   0
 Tests/RunCMake/Ninja/VerboseBuild.cmake            |   3 +
 Tests/Tutorial/Complete/CMakeLists.txt             | 116 ++++++++++++++
 Tests/Tutorial/Complete/Config.cmake.in            |   4 +
 Tests/Tutorial/{Step6 => Complete}/License.txt     |   2 +-
 .../Tutorial/Complete/MathFunctions/CMakeLists.txt |  68 +++++++++
 .../Tutorial/Complete/MathFunctions/MakeTable.cxx  |  25 ++++
 .../Complete/MathFunctions/MathFunctions.cxx       |  18 +++
 .../Complete/MathFunctions/MathFunctions.h         |  14 ++
 .../{Step5 => Complete}/MathFunctions/mysqrt.cxx   |  31 ++--
 Tests/Tutorial/Complete/MathFunctions/mysqrt.h     |   6 +
 .../{Step2 => Complete}/TutorialConfig.h.in        |   4 +-
 Tests/Tutorial/Complete/tutorial.cxx               |  25 ++++
 Tests/Tutorial/Consumer/CMakeLists.txt             |  51 +++++++
 Tests/Tutorial/Consumer/Config.cmake.in            |  14 ++
 Tests/Tutorial/Consumer/consumer.cxx               |  11 ++
 Tests/Tutorial/Consumer/directions.txt             |   6 +
 Tests/Tutorial/MultiPackage/CMakeLists.txt         | 109 ++++++++++++++
 Tests/Tutorial/MultiPackage/Config.cmake.in        |   4 +
 Tests/Tutorial/{Step6 => MultiPackage}/License.txt |   2 +-
 .../MultiPackage/MathFunctions/CMakeLists.txt      |  68 +++++++++
 .../MultiPackage/MathFunctions/MakeTable.cxx       |  25 ++++
 .../MultiPackage/MathFunctions/MathFunctions.cxx   |  18 +++
 .../MultiPackage/MathFunctions/MathFunctions.h     |  14 ++
 .../MathFunctions/mysqrt.cxx                       |  31 ++--
 Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.h |   6 +
 Tests/Tutorial/MultiPackage/MultiCPackConfig.cmake |   7 +
 .../{Step2 => MultiPackage}/TutorialConfig.h.in    |   4 +-
 Tests/Tutorial/MultiPackage/directions.txt         |  34 +++++
 Tests/Tutorial/MultiPackage/tutorial.cxx           |  25 ++++
 Tests/Tutorial/Readme.txt                          |  16 ++
 Tests/Tutorial/Step1/CMakeLists.txt                |  19 +--
 Tests/Tutorial/Step1/directions.txt                |  95 ++++++++++++
 Tests/Tutorial/Step1/tutorial.cxx                  |  17 ++-
 Tests/Tutorial/Step10/CMakeLists.txt               |  77 ++++++++++
 Tests/Tutorial/{Step6 => Step10}/License.txt       |   2 +-
 Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt |  61 ++++++++
 Tests/Tutorial/Step10/MathFunctions/MakeTable.cxx  |  25 ++++
 .../Step10/MathFunctions/MathFunctions.cxx         |  18 +++
 .../Tutorial/Step10/MathFunctions/MathFunctions.h  |  14 ++
 .../{Step5 => Step10}/MathFunctions/mysqrt.cxx     |  31 ++--
 Tests/Tutorial/Step10/MathFunctions/mysqrt.h       |   6 +
 .../Tutorial/{Step2 => Step10}/TutorialConfig.h.in |   4 +-
 Tests/Tutorial/Step10/directions.txt               |  38 +++++
 Tests/Tutorial/Step10/tutorial.cxx                 |  25 ++++
 Tests/Tutorial/Step11/CMakeLists.txt               |  77 ++++++++++
 Tests/Tutorial/{Step6 => Step11}/License.txt       |   2 +-
 Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt |  60 ++++++++
 Tests/Tutorial/Step11/MathFunctions/MakeTable.cxx  |  25 ++++
 .../Step11/MathFunctions/MathFunctions.cxx         |  18 +++
 .../Tutorial/Step11/MathFunctions/MathFunctions.h  |  14 ++
 .../{Step5 => Step11}/MathFunctions/mysqrt.cxx     |  31 ++--
 Tests/Tutorial/Step11/MathFunctions/mysqrt.h       |   6 +
 .../Tutorial/{Step2 => Step11}/TutorialConfig.h.in |   4 +-
 Tests/Tutorial/Step11/directions.txt               | 104 +++++++++++++
 Tests/Tutorial/Step11/tutorial.cxx                 |  25 ++++
 Tests/Tutorial/Step2/CMakeLists.txt                |  34 ++---
 Tests/Tutorial/Step2/MathFunctions/mysqrt.cxx      |  13 +-
 Tests/Tutorial/Step2/TutorialConfig.h.in           |   1 -
 Tests/Tutorial/Step2/directions.txt                | 102 +++++++++++++
 Tests/Tutorial/Step2/tutorial.cxx                  |  32 ++--
 Tests/Tutorial/Step3/CMakeLists.txt                |  74 +++------
 Tests/Tutorial/Step3/MathFunctions/CMakeLists.txt  |   3 -
 Tests/Tutorial/Step3/MathFunctions/mysqrt.cxx      |  13 +-
 Tests/Tutorial/Step3/directions.txt                |  26 ++++
 Tests/Tutorial/Step3/tutorial.cxx                  |  25 ++--
 Tests/Tutorial/Step4/CMakeLists.txt                |  72 +++------
 Tests/Tutorial/Step4/MathFunctions/CMakeLists.txt  |   7 +-
 Tests/Tutorial/Step4/MathFunctions/mysqrt.cxx      |  23 +--
 Tests/Tutorial/Step4/TutorialConfig.h.in           |   4 -
 Tests/Tutorial/Step4/directions.txt                |  72 +++++++++
 Tests/Tutorial/Step4/tutorial.cxx                  |  25 ++--
 Tests/Tutorial/Step5/CMakeLists.txt                |  86 ++++++-----
 Tests/Tutorial/Step5/MathFunctions/CMakeLists.txt  |  23 +--
 Tests/Tutorial/Step5/MathFunctions/MakeTable.cxx   |  35 ++---
 Tests/Tutorial/Step5/MathFunctions/mysqrt.cxx      |  27 +---
 Tests/Tutorial/Step5/TutorialConfig.h.in           |   4 -
 Tests/Tutorial/Step5/directions.txt                |  69 +++++++++
 Tests/Tutorial/Step5/tutorial.cxx                  |  25 ++--
 Tests/Tutorial/Step6/CMakeLists.txt                |  94 ++++++------
 Tests/Tutorial/Step6/MathFunctions/CMakeLists.txt  |  32 ++--
 Tests/Tutorial/Step6/MathFunctions/MakeTable.cxx   |  35 ++---
 Tests/Tutorial/Step6/MathFunctions/mysqrt.cxx      |  31 ++--
 Tests/Tutorial/Step6/directions.txt                | 104 +++++++++++++
 Tests/Tutorial/Step6/tutorial.cxx                  |  25 ++--
 Tests/Tutorial/Step7/CMakeLists.txt                |  98 ++++++------
 Tests/Tutorial/Step7/License.txt                   |   2 +-
 Tests/Tutorial/Step7/MathFunctions/CMakeLists.txt  |  33 ++--
 Tests/Tutorial/Step7/MathFunctions/MakeTable.cxx   |  35 ++---
 Tests/Tutorial/Step7/MathFunctions/mysqrt.cxx      |  18 +--
 Tests/Tutorial/Step7/directions.txt                |  40 +++++
 Tests/Tutorial/Step7/tutorial.cxx                  |  25 ++--
 Tests/Tutorial/Step8/CMakeLists.txt                |  82 ++++++++++
 Tests/Tutorial/{Step6 => Step8}/License.txt        |   2 +-
 Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt  |  29 ++++
 Tests/Tutorial/Step8/MathFunctions/MakeTable.cxx   |  25 ++++
 .../{Step7 => Step8}/MathFunctions/MathFunctions.h |   0
 .../{Step5 => Step8}/MathFunctions/mysqrt.cxx      |  26 ++--
 .../Tutorial/{Step4 => Step8}/TutorialConfig.h.in  |   1 -
 Tests/Tutorial/Step8/directions.txt                |  38 +++++
 Tests/Tutorial/Step8/tutorial.cxx                  |  32 ++++
 Tests/Tutorial/Step9/CMakeLists.txt                |  81 ++++++++++
 Tests/Tutorial/Step9/CTestConfig.cmake             |  15 ++
 Tests/Tutorial/{Step6 => Step9}/License.txt        |   2 +-
 Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt  |  35 +++++
 Tests/Tutorial/Step9/MathFunctions/MakeTable.cxx   |  25 ++++
 .../Tutorial/Step9/MathFunctions/MathFunctions.cxx |  18 +++
 .../{Step7 => Step9}/MathFunctions/MathFunctions.h |   0
 .../{Step6 => Step9}/MathFunctions/mysqrt.cxx      |  27 ++--
 Tests/Tutorial/Step9/MathFunctions/mysqrt.h        |   6 +
 .../Tutorial/{Step2 => Step9}/TutorialConfig.h.in  |   4 +-
 Tests/Tutorial/Step9/directions.txt                | 166 +++++++++++++++++++++
 Tests/Tutorial/Step9/tutorial.cxx                  |  33 ++++
 198 files changed, 3367 insertions(+), 1061 deletions(-)
 create mode 100644 Help/envvar/CMAKE_NO_VERBOSE.rst
 create mode 100644 Help/envvar/VERBOSE.rst
 create mode 100644 Help/release/dev/cmake-build-verbose.rst
 copy Tests/{Tutorial => ExternalProjectLocal}/Step5/CMakeLists.txt (99%)
 copy Tests/{Tutorial => ExternalProjectLocal}/Step5/MathFunctions/CMakeLists.txt (100%)
 copy Tests/{Tutorial/Step7 => ExternalProjectLocal/Step5}/MathFunctions/MakeTable.cxx (100%)
 copy Tests/{Tutorial/Step7 => ExternalProjectLocal/Step5}/MathFunctions/MathFunctions.h (100%)
 copy Tests/{Tutorial/Step7 => ExternalProjectLocal/Step5}/MathFunctions/mysqrt.cxx (100%)
 copy Tests/{Tutorial/Step4 => ExternalProjectLocal/Step5}/TutorialConfig.h.in (99%)
 copy Tests/{Tutorial/Step7 => ExternalProjectLocal/Step5}/tutorial.cxx (100%)
 create mode 100644 Tests/RunCMake/Make/VerboseBuild-build-stdout.txt
 copy Tests/RunCMake/{CTestCommandLine/TestOutputSize-result.txt => Make/VerboseBuild-build-watcom-stdout.txt} (100%)
 create mode 100644 Tests/RunCMake/Make/VerboseBuild-nowork-gnu-stdout.txt
 create mode 100644 Tests/RunCMake/Make/VerboseBuild.cmake
 copy Tests/RunCMake/{Ninja => Make}/hello.c (100%)
 create mode 100644 Tests/RunCMake/Ninja/VerboseBuild-build-stdout.txt
 copy Tests/RunCMake/Ninja/{NoWorkToDo-nowork-stdout.txt => VerboseBuild-nowork-stdout.txt} (100%)
 create mode 100644 Tests/RunCMake/Ninja/VerboseBuild.cmake
 create mode 100644 Tests/Tutorial/Complete/CMakeLists.txt
 create mode 100644 Tests/Tutorial/Complete/Config.cmake.in
 copy Tests/Tutorial/{Step6 => Complete}/License.txt (64%)
 create mode 100644 Tests/Tutorial/Complete/MathFunctions/CMakeLists.txt
 create mode 100644 Tests/Tutorial/Complete/MathFunctions/MakeTable.cxx
 create mode 100644 Tests/Tutorial/Complete/MathFunctions/MathFunctions.cxx
 create mode 100644 Tests/Tutorial/Complete/MathFunctions/MathFunctions.h
 copy Tests/Tutorial/{Step5 => Complete}/MathFunctions/mysqrt.cxx (50%)
 create mode 100644 Tests/Tutorial/Complete/MathFunctions/mysqrt.h
 copy Tests/Tutorial/{Step2 => Complete}/TutorialConfig.h.in (59%)
 create mode 100644 Tests/Tutorial/Complete/tutorial.cxx
 create mode 100644 Tests/Tutorial/Consumer/CMakeLists.txt
 create mode 100644 Tests/Tutorial/Consumer/Config.cmake.in
 create mode 100644 Tests/Tutorial/Consumer/consumer.cxx
 create mode 100644 Tests/Tutorial/Consumer/directions.txt
 create mode 100644 Tests/Tutorial/MultiPackage/CMakeLists.txt
 create mode 100644 Tests/Tutorial/MultiPackage/Config.cmake.in
 copy Tests/Tutorial/{Step6 => MultiPackage}/License.txt (64%)
 create mode 100644 Tests/Tutorial/MultiPackage/MathFunctions/CMakeLists.txt
 create mode 100644 Tests/Tutorial/MultiPackage/MathFunctions/MakeTable.cxx
 create mode 100644 Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.cxx
 create mode 100644 Tests/Tutorial/MultiPackage/MathFunctions/MathFunctions.h
 copy Tests/Tutorial/{Step5 => MultiPackage}/MathFunctions/mysqrt.cxx (50%)
 create mode 100644 Tests/Tutorial/MultiPackage/MathFunctions/mysqrt.h
 create mode 100644 Tests/Tutorial/MultiPackage/MultiCPackConfig.cmake
 copy Tests/Tutorial/{Step2 => MultiPackage}/TutorialConfig.h.in (59%)
 create mode 100644 Tests/Tutorial/MultiPackage/directions.txt
 create mode 100644 Tests/Tutorial/MultiPackage/tutorial.cxx
 create mode 100644 Tests/Tutorial/Readme.txt
 create mode 100644 Tests/Tutorial/Step1/directions.txt
 create mode 100644 Tests/Tutorial/Step10/CMakeLists.txt
 copy Tests/Tutorial/{Step6 => Step10}/License.txt (64%)
 create mode 100644 Tests/Tutorial/Step10/MathFunctions/CMakeLists.txt
 create mode 100644 Tests/Tutorial/Step10/MathFunctions/MakeTable.cxx
 create mode 100644 Tests/Tutorial/Step10/MathFunctions/MathFunctions.cxx
 create mode 100644 Tests/Tutorial/Step10/MathFunctions/MathFunctions.h
 copy Tests/Tutorial/{Step5 => Step10}/MathFunctions/mysqrt.cxx (50%)
 create mode 100644 Tests/Tutorial/Step10/MathFunctions/mysqrt.h
 copy Tests/Tutorial/{Step2 => Step10}/TutorialConfig.h.in (59%)
 create mode 100644 Tests/Tutorial/Step10/directions.txt
 create mode 100644 Tests/Tutorial/Step10/tutorial.cxx
 create mode 100644 Tests/Tutorial/Step11/CMakeLists.txt
 copy Tests/Tutorial/{Step6 => Step11}/License.txt (64%)
 create mode 100644 Tests/Tutorial/Step11/MathFunctions/CMakeLists.txt
 create mode 100644 Tests/Tutorial/Step11/MathFunctions/MakeTable.cxx
 create mode 100644 Tests/Tutorial/Step11/MathFunctions/MathFunctions.cxx
 create mode 100644 Tests/Tutorial/Step11/MathFunctions/MathFunctions.h
 copy Tests/Tutorial/{Step5 => Step11}/MathFunctions/mysqrt.cxx (50%)
 create mode 100644 Tests/Tutorial/Step11/MathFunctions/mysqrt.h
 copy Tests/Tutorial/{Step2 => Step11}/TutorialConfig.h.in (59%)
 create mode 100644 Tests/Tutorial/Step11/directions.txt
 create mode 100644 Tests/Tutorial/Step11/tutorial.cxx
 create mode 100644 Tests/Tutorial/Step2/directions.txt
 create mode 100644 Tests/Tutorial/Step3/directions.txt
 create mode 100644 Tests/Tutorial/Step4/directions.txt
 create mode 100644 Tests/Tutorial/Step5/directions.txt
 create mode 100644 Tests/Tutorial/Step6/directions.txt
 create mode 100644 Tests/Tutorial/Step7/directions.txt
 create mode 100644 Tests/Tutorial/Step8/CMakeLists.txt
 copy Tests/Tutorial/{Step6 => Step8}/License.txt (64%)
 create mode 100644 Tests/Tutorial/Step8/MathFunctions/CMakeLists.txt
 create mode 100644 Tests/Tutorial/Step8/MathFunctions/MakeTable.cxx
 copy Tests/Tutorial/{Step7 => Step8}/MathFunctions/MathFunctions.h (100%)
 copy Tests/Tutorial/{Step5 => Step8}/MathFunctions/mysqrt.cxx (54%)
 copy Tests/Tutorial/{Step4 => Step8}/TutorialConfig.h.in (99%)
 create mode 100644 Tests/Tutorial/Step8/directions.txt
 create mode 100644 Tests/Tutorial/Step8/tutorial.cxx
 create mode 100644 Tests/Tutorial/Step9/CMakeLists.txt
 create mode 100644 Tests/Tutorial/Step9/CTestConfig.cmake
 rename Tests/Tutorial/{Step6 => Step9}/License.txt (64%)
 create mode 100644 Tests/Tutorial/Step9/MathFunctions/CMakeLists.txt
 create mode 100644 Tests/Tutorial/Step9/MathFunctions/MakeTable.cxx
 create mode 100644 Tests/Tutorial/Step9/MathFunctions/MathFunctions.cxx
 copy Tests/Tutorial/{Step7 => Step9}/MathFunctions/MathFunctions.h (100%)
 copy Tests/Tutorial/{Step6 => Step9}/MathFunctions/mysqrt.cxx (52%)
 create mode 100644 Tests/Tutorial/Step9/MathFunctions/mysqrt.h
 copy Tests/Tutorial/{Step2 => Step9}/TutorialConfig.h.in (59%)
 create mode 100644 Tests/Tutorial/Step9/directions.txt
 create mode 100644 Tests/Tutorial/Step9/tutorial.cxx


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list