[Cmake-commits] CMake branch, master, updated. v3.15.3-1261-g8aa5f6b

Kitware Robot kwrobot at kitware.com
Mon Sep 30 10:28:08 EDT 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  8aa5f6ba446dd8ff817e54979f466b8a247f967a (commit)
       via  9b03baee308d78db119554def6e34fd9db9683ac (commit)
       via  b24e501bc289956867b6104aac9d07afb75c906e (commit)
       via  c2d1ea58bfbee75fe509e0c9745a66cb1e924b77 (commit)
       via  45507eeb6aa9e9caf01cc4852a6fcb06b73cc207 (commit)
       via  dce58afd30b781bd99a1af5c6860583577d58a1f (commit)
       via  013d7dd48420b7040355066724ede9eb7050c94a (commit)
       via  61103c0bac4e9ef264d87fe9b23087ed8f5291c4 (commit)
       via  1fe450159278fd30138ef5133daf26f931537de4 (commit)
       via  05d7ca14e99ee8ad36da01ddb314d0b90ab41874 (commit)
       via  62d45d91e83f537b19d9bfc7b1e8d909a0c5c322 (commit)
       via  b3b1c7bf3afc8f33fa69b79f47f778cb781ac3c7 (commit)
       via  6bd40ccf8424a6e8c3a77857d48600ed7c624a07 (commit)
       via  e0e9be3d575a255add19169d174c869fdebebbeb (commit)
       via  820962edc9dd7481c440068dd894c1026abf671d (commit)
       via  dd0f304613b1661754d9cccf5829087a8bb19a12 (commit)
       via  b515af782bccf147e8bd62444c9f1808668f12ac (commit)
       via  9e66397c28110f015e5b044dfe9782cd5f11c8c3 (commit)
       via  80f120a85fb0992e3f06ad69ebdad881bea9af8c (commit)
       via  156b56480a786db4d967bde5eb6d5edee56a27d0 (commit)
       via  60473cc660cc37c922b0ff93112deeb34d51f2ca (commit)
       via  7d6e08b438a187e89735ae6aad749a14137f34be (commit)
       via  0833486d62e8ed3ae9f0219f9924c4e78d74f781 (commit)
       via  cf01d3d2bd649ab1157641b3212a360b06db747f (commit)
       via  21442d72a44c2bd732f2ff19ed89ce488854d25d (commit)
       via  bc71b253cb372cc6c0ae50406a11b81fe4259559 (commit)
       via  36875ff419240a5a60b1b13ff190a5824a8363a5 (commit)
       via  2b1607114985e56a7847eb6081d5656f73c230d0 (commit)
       via  0cfbd85e7b0d61affda6450b1cc081860b5543a6 (commit)
      from  3f7829fc4f2e30105f6d37c9509b7bfe77ae3c67 (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=8aa5f6ba446dd8ff817e54979f466b8a247f967a
commit 8aa5f6ba446dd8ff817e54979f466b8a247f967a
Merge: 9b03bae dce58af
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Sep 30 14:26:37 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Mon Sep 30 10:27:15 2019 -0400

    Merge topic 'fix-EXCLUDE_FROM_ALL-subdir-all'
    
    dce58afd30 Merge branch 'backport-3.15-fix-EXCLUDE_FROM_ALL-subdir-all'
    013d7dd484 Help: Mention 3.14.7 EXCLUDE_FROM_ALL fix in 3.15.4 release note
    61103c0bac Merge branch 'backport-3.14-fix-EXCLUDE_FROM_ALL-subdir-all'
    1fe4501592 Help: Add release note for EXCLUDE_FROM_ALL fix in 3.15.4
    05d7ca14e9 Merge branch 'backport-3.14-fix-EXCLUDE_FROM_ALL-subdir-all'
    62d45d91e8 Help: Add release note for EXCLUDE_FROM_ALL fix in 3.14.7
    b3b1c7bf3a Restore "all" target in subdirectories marked EXCLUDE_FROM_ALL
    156b56480a Makefiles: Revert "Make build root targets ... recursive"
    ...
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3863


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9b03baee308d78db119554def6e34fd9db9683ac
commit 9b03baee308d78db119554def6e34fd9db9683ac
Merge: b24e501 dd0f304
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Sep 30 14:24:55 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Mon Sep 30 10:25:19 2019 -0400

    Merge topic 'objective-c-cxx'
    
    dd0f304613 Objective C/C++: Add compiler standard detection
    b515af782b Help: Add release note for Objective-C/C++ language support
    9e66397c28 Languages: Add support for Objective-C++
    80f120a85f Languages: Add support for Objective-C
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3811

diff --cc Source/cmMakefile.cxx
index a528fc6,85ba38c..264a73a
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@@ -38,8 -38,8 +38,9 @@@
  #include "cmState.h"
  #include "cmStateDirectory.h"
  #include "cmStateTypes.h"
+ #include "cmStringAlgorithms.h"
  #include "cmSystemTools.h"
 +#include "cmTarget.h"
  #include "cmTargetLinkLibraryType.h"
  #include "cmTest.h"
  #include "cmTestGenerator.h" // IWYU pragma: keep

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b24e501bc289956867b6104aac9d07afb75c906e
commit b24e501bc289956867b6104aac9d07afb75c906e
Merge: c2d1ea5 6bd40cc
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Sep 30 14:23:27 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Mon Sep 30 10:23:42 2019 -0400

    Merge topic 'autogen_free_functions'
    
    6bd40ccf84 Autogen: Make cmQtAutoMocUic a free function
    e0e9be3d57 Autogen: Make cmQtAutoRcc a free function
    820962edc9 Autogen: Refactor json info file reading interface
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3867


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c2d1ea58bfbee75fe509e0c9745a66cb1e924b77
commit c2d1ea58bfbee75fe509e0c9745a66cb1e924b77
Merge: 45507ee 60473cc
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Sep 30 14:22:13 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Mon Sep 30 10:22:35 2019 -0400

    Merge topic 'FPHSA-reason-failure-message'
    
    60473cc660 FPHSA: add capability to specify message explaining reason of failure
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3866


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=45507eeb6aa9e9caf01cc4852a6fcb06b73cc207
commit 45507eeb6aa9e9caf01cc4852a6fcb06b73cc207
Merge: 3f7829f 7d6e08b
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Sep 30 14:21:27 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Mon Sep 30 10:21:38 2019 -0400

    Merge topic 'smart_ptr/cmCurses'
    
    7d6e08b438 cmCursesMainForm: change Entries to object vector
    0833486d62 cmCursesStringWidget: remove manual delete
    bc71b253cb cmCursesCacheEntryComposite: default destructor
    36875ff419 cmCursesMainForm: cleanup manual allocation
    2b16071149 CursesDialog: modernize CMake usage
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3849


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dce58afd30b781bd99a1af5c6860583577d58a1f
commit dce58afd30b781bd99a1af5c6860583577d58a1f
Merge: c88cf48 013d7dd
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Sep 30 09:34:57 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Sep 30 09:34:57 2019 -0400

    Merge branch 'backport-3.15-fix-EXCLUDE_FROM_ALL-subdir-all'
    
    Resolve conflicts with changes since the 3.15 series:
    
    * Convert `cmSystemTools::IsOn` => `cmIsOn`.
    * Move one "EXCLUDE_FROM_ALL" target property logic fix to
      its new location in `cmMakefile::AddNewUtilityTarget`.

diff --cc Source/cmGlobalGenerator.cxx
index c4974f3,ea898e1..a75e2ed
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@@ -2037,10 -2088,18 +2037,18 @@@ bool cmGlobalGenerator::IsExcluded(cmLo
    return this->IsExcluded(rootSnp, snp);
  }
  
- bool cmGlobalGenerator::IsExcluded(cmGeneratorTarget* target) const
+ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
+                                    cmGeneratorTarget* target) const
  {
-   return target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
-     target->GetPropertyAsBool("EXCLUDE_FROM_ALL");
+   if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+     return true;
+   }
+   if (const char* exclude = target->GetProperty("EXCLUDE_FROM_ALL")) {
 -    return cmSystemTools::IsOn(exclude);
++    return cmIsOn(exclude);
+   }
+   // This target is included in its directory.  Check whether the
+   // directory is excluded.
+   return this->IsExcluded(root, target->GetLocalGenerator());
  }
  
  void cmGlobalGenerator::GetEnabledLanguages(
diff --cc Source/cmGlobalXCodeGenerator.cxx
index 4202175,9d72528..f42218b
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@@ -554,16 -560,18 +554,16 @@@ void cmGlobalXCodeGenerator::AddExtraTa
        // this will make sure that when the next target is built
        // things are up-to-date
        if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
 -        makeHelper.back() = // fill placeholder
 +        commandLines.front().back() = // fill placeholder
            this->PostBuildMakeTarget(target->GetName(), "$(CONFIGURATION)");
 -        cmCustomCommandLines commandLines;
 -        commandLines.push_back(makeHelper);
 -        std::vector<std::string> no_byproducts;
          gen->GetMakefile()->AddCustomCommandToTarget(
            target->GetName(), no_byproducts, no_depends, commandLines,
 -          cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true,
 -          false, "", "", false, cmMakefile::AcceptObjectLibraryCommands);
 +          cmCustomCommandType::POST_BUILD, "Depend check for xcode",
 +          dir.c_str(), true, false, "", "", false,
 +          cmObjectLibraryCommands::Accept);
        }
  
-       if (!this->IsExcluded(target)) {
+       if (!this->IsExcluded(gens[0], target)) {
          allbuild->AddUtility(target->GetName());
        }
      }
diff --cc Source/cmMakefile.cxx
index a528fc6,3f8bd4e..640f823
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@@ -2087,85 -2043,26 +2085,85 @@@ cmTarget* cmMakefile::AddNewTarget(cmSt
    return &it->second;
  }
  
 +cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName,
 +                                          cmCommandOrigin origin,
 +                                          bool excludeFromAll)
 +{
 +  cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
 +  target->SetIsGeneratorProvided(origin == cmCommandOrigin::Generator);
-   if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
++  if (excludeFromAll) {
 +    target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
 +  }
 +  return target;
 +}
 +
 +namespace {
 +bool AnyOutputMatches(const std::string& name,
 +                      const std::vector<std::string>& outputs)
 +{
 +  for (std::string const& output : outputs) {
 +    std::string::size_type pos = output.rfind(name);
 +    // If the output matches exactly
 +    if (pos != std::string::npos && pos == output.size() - name.size() &&
 +        (pos == 0 || output[pos - 1] == '/')) {
 +      return true;
 +    }
 +  }
 +  return false;
 +}
 +
 +bool AnyTargetCommandOutputMatches(
 +  const std::string& name, const std::vector<cmCustomCommand>& commands)
 +{
 +  for (cmCustomCommand const& command : commands) {
 +    if (AnyOutputMatches(name, command.GetByproducts())) {
 +      return true;
 +    }
 +  }
 +  return false;
 +}
 +}
 +
 +cmTarget* cmMakefile::LinearGetTargetWithOutput(const std::string& name) const
 +{
 +  // We go through the ordered vector of targets to get reproducible results
 +  // should multiple names match.
 +  for (cmTarget* t : this->OrderedTargets) {
 +    // Does the output of any command match the source file name?
 +    if (AnyTargetCommandOutputMatches(name, t->GetPreBuildCommands())) {
 +      return t;
 +    }
 +    if (AnyTargetCommandOutputMatches(name, t->GetPreLinkCommands())) {
 +      return t;
 +    }
 +    if (AnyTargetCommandOutputMatches(name, t->GetPostBuildCommands())) {
 +      return t;
 +    }
 +  }
 +  return nullptr;
 +}
 +
  cmSourceFile* cmMakefile::LinearGetSourceFileWithOutput(
 -  const std::string& name) const
 +  const std::string& name, cmSourceOutputKind kind, bool& byproduct) const
  {
 -  std::string out;
 +  // Outputs take precedence over byproducts.
 +  byproduct = false;
 +  cmSourceFile* fallback = nullptr;
  
 -  // look through all the source files that have custom commands
 -  // and see if the custom command has the passed source file as an output
 +  // Look through all the source files that have custom commands and see if the
 +  // custom command has the passed source file as an output.
    for (cmSourceFile* src : this->SourceFiles) {
 -    // does this source file have a custom command?
 +    // Does this source file have a custom command?
      if (src->GetCustomCommand()) {
        // Does the output of the custom command match the source file name?
 -      const std::vector<std::string>& outputs =
 -        src->GetCustomCommand()->GetOutputs();
 -      for (std::string const& output : outputs) {
 -        out = output;
 -        std::string::size_type pos = out.rfind(name);
 -        // If the output matches exactly
 -        if (pos != std::string::npos && pos == out.size() - name.size() &&
 -            (pos == 0 || out[pos - 1] == '/')) {
 -          return src;
 +      if (AnyOutputMatches(name, src->GetCustomCommand()->GetOutputs())) {
 +        // Return the first matching output.
 +        return src;
 +      }
 +      if (kind == cmSourceOutputKind::OutputOrByproduct) {
 +        if (AnyOutputMatches(name, src->GetCustomCommand()->GetByproducts())) {
 +          // Do not return the source yet as there might be a matching output.
 +          fallback = src;
          }
        }
      }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=013d7dd48420b7040355066724ede9eb7050c94a
commit 013d7dd48420b7040355066724ede9eb7050c94a
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Sep 24 14:31:23 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Sep 30 09:20:55 2019 -0400

    Help: Mention 3.14.7 EXCLUDE_FROM_ALL fix in 3.15.4 release note

diff --git a/Help/release/3.15.rst b/Help/release/3.15.rst
index 148c2d2..957e6e9 100644
--- a/Help/release/3.15.rst
+++ b/Help/release/3.15.rst
@@ -384,3 +384,4 @@ Changes made since CMake 3.15.0 include the following.
   directory property was regressed from pre-3.14 behavior and caused
   targets within the directory to be excluded even from its own "all".
   This has been fixed.
+  The bug also existed in 3.14.0 through 3.14.6 and is fixed in 3.14.7.

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=61103c0bac4e9ef264d87fe9b23087ed8f5291c4
commit 61103c0bac4e9ef264d87fe9b23087ed8f5291c4
Merge: 1fe4501 62d45d9
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Sep 30 09:20:40 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Sep 30 09:20:40 2019 -0400

    Merge branch 'backport-3.14-fix-EXCLUDE_FROM_ALL-subdir-all'


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1fe450159278fd30138ef5133daf26f931537de4
commit 1fe450159278fd30138ef5133daf26f931537de4
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Sep 24 14:31:00 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Sep 30 09:20:35 2019 -0400

    Help: Add release note for EXCLUDE_FROM_ALL fix in 3.15.4

diff --git a/Help/release/3.15.rst b/Help/release/3.15.rst
index 48f3aa4..148c2d2 100644
--- a/Help/release/3.15.rst
+++ b/Help/release/3.15.rst
@@ -376,3 +376,11 @@ Changes made since CMake 3.15.0 include the following.
 * ``CrayPrgEnv`` compiler wrapper support has been updated for the 19.06
   release of the Cray Programming Environment for which the default linking
   mode on XC Cray systems is now dynamic instead of static.
+
+3.15.4
+------
+
+* In CMake 3.15.0 through 3.15.3, the :prop_dir:`EXCLUDE_FROM_ALL`
+  directory property was regressed from pre-3.14 behavior and caused
+  targets within the directory to be excluded even from its own "all".
+  This has been fixed.

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=05d7ca14e99ee8ad36da01ddb314d0b90ab41874
commit 05d7ca14e99ee8ad36da01ddb314d0b90ab41874
Merge: 156b564 b3b1c7b
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Sep 30 09:19:21 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Sep 30 09:19:21 2019 -0400

    Merge branch 'backport-3.14-fix-EXCLUDE_FROM_ALL-subdir-all'

diff --cc Source/cmGlobalXCodeGenerator.cxx
index 7c2bcd3,dc63ce6..9d72528
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@@ -568,10 -564,10 +568,10 @@@ void cmGlobalXCodeGenerator::AddExtraTa
          gen->GetMakefile()->AddCustomCommandToTarget(
            target->GetName(), no_byproducts, no_depends, commandLines,
            cmTarget::POST_BUILD, "Depend check for xcode", dir.c_str(), true,
 -          false, "", false, cmMakefile::AcceptObjectLibraryCommands);
 +          false, "", "", false, cmMakefile::AcceptObjectLibraryCommands);
        }
  
-       if (!this->IsExcluded(target)) {
+       if (!this->IsExcluded(gens[0], target)) {
          allbuild->AddUtility(target->GetName());
        }
      }
diff --cc Source/cmLocalNinjaGenerator.cxx
index 81cafa3,69656a2..90666fc
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@@ -88,9 -88,12 +88,11 @@@ void cmLocalNinjaGenerator::Generate(
      if (tg) {
        tg->Generate();
        // Add the target to "all" if required.
-       if (!this->GetGlobalNinjaGenerator()->IsExcluded(target)) {
+       if (!this->GetGlobalNinjaGenerator()->IsExcluded(
+             this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0],
+             target)) {
          this->GetGlobalNinjaGenerator()->AddDependencyToAll(target);
        }
 -      delete tg;
      }
    }
  

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=62d45d91e83f537b19d9bfc7b1e8d909a0c5c322
commit 62d45d91e83f537b19d9bfc7b1e8d909a0c5c322
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Sep 24 14:24:55 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Sep 30 09:18:20 2019 -0400

    Help: Add release note for EXCLUDE_FROM_ALL fix in 3.14.7

diff --git a/Help/release/3.14.rst b/Help/release/3.14.rst
index 229d8dc..8a9738c 100644
--- a/Help/release/3.14.rst
+++ b/Help/release/3.14.rst
@@ -428,3 +428,11 @@ Changes made since CMake 3.14.0 include the following.
   policy :policy:`CMP0088` ``NEW`` behavior accidentally interpreted
   a relative path to the ``.y`` input as relative to the build tree
   directory instead of the source tree directory.  This has been fixed.
+
+3.14.7
+------
+
+* In CMake 3.14.0 through 3.14.6, the :prop_dir:`EXCLUDE_FROM_ALL`
+  directory property was regressed from pre-3.14 behavior and caused
+  targets within the directory to be excluded even from its own "all".
+  This has been fixed.

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b3b1c7bf3afc8f33fa69b79f47f778cb781ac3c7
commit b3b1c7bf3afc8f33fa69b79f47f778cb781ac3c7
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Sep 24 11:50:18 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Sep 30 09:18:20 2019 -0400

    Restore "all" target in subdirectories marked EXCLUDE_FROM_ALL
    
    The "all" target in each directory is supposed to have targets from that
    directory even if the directory itself is marked `EXCLUDE_FROM_ALL` in
    its parent.  This was broken by commit dc6888573d (Pass EXCLUDE_FROM_ALL
    from directory to targets, 2019-01-15, v3.14.0-rc1~83^2) which made the
    participation of a target in "all" independent of context.  Revert much
    of the logic change from that commit to restore the old behavior.  Then
    re-implement the behavior intended by the commit to keep its test
    working.  Extend the test to cover the old behavior too.
    
    Fixes: #19753

diff --git a/Help/prop_dir/EXCLUDE_FROM_ALL.rst b/Help/prop_dir/EXCLUDE_FROM_ALL.rst
index 9d3192c..8e3cca0 100644
--- a/Help/prop_dir/EXCLUDE_FROM_ALL.rst
+++ b/Help/prop_dir/EXCLUDE_FROM_ALL.rst
@@ -1,15 +1,13 @@
 EXCLUDE_FROM_ALL
 ----------------
 
-Exclude the directory from the all target of its parent.
+Set this directory property to a true value on a subdirectory to exclude
+its targets from the "all" target of its ancestors.  If excluded, running
+e.g. ``make`` in the parent directory will not build targets the
+subdirectory by default.  This does not affect the "all" target of the
+subdirectory itself.  Running e.g. ``make`` inside the subdirectory will
+still build its targets.
 
-A property on a directory that indicates if its targets are excluded
-from the default build target.  If it is not, then with a Makefile for
-example typing make will cause the targets to be built.  The same
-concept applies to the default build of other generators.
-
-Targets inherit the :prop_tgt:`EXCLUDE_FROM_ALL` property from the directory
-that they are created in. When a directory is excluded, all of its targets will
-have :prop_tgt:`EXCLUDE_FROM_ALL` set to ``TRUE``. After creating such a target
-you can change its :prop_tgt:`EXCLUDE_FROM_ALL` property to ``FALSE``. This
-will cause the target to be included in the default build target.
+If the :prop_tgt:`EXCLUDE_FROM_ALL` target property is set on a target
+then its value determines whether the target is included in the "all"
+target of this directory and its ancestors.
diff --git a/Help/prop_tgt/EXCLUDE_FROM_ALL.rst b/Help/prop_tgt/EXCLUDE_FROM_ALL.rst
index 0eee297..3aa296d 100644
--- a/Help/prop_tgt/EXCLUDE_FROM_ALL.rst
+++ b/Help/prop_tgt/EXCLUDE_FROM_ALL.rst
@@ -1,12 +1,15 @@
 EXCLUDE_FROM_ALL
 ----------------
 
-Exclude the target from the all target.
+Set this target property to a true (or false) value to exclude (or include)
+the target from the "all" target of the containing directory and its
+ancestors.  If excluded, running e.g. ``make`` in the containing directory
+or its ancestors will not build the target by default.
 
-A property on a target that indicates if the target is excluded from
-the default build target.  If it is not, then with a Makefile for
-example typing make will cause this target to be built.  The same
-concept applies to the default build of other generators.
+If this target property is not set then the target will be included in
+the "all" target of the containing directory.  Furthermore, it will be
+included in the "all" target of its ancestor directories unless the
+:prop_dir:`EXCLUDE_FROM_ALL` directory property is set.
 
 With ``EXCLUDE_FROM_ALL`` set to false or not set at all, the target
 will be brought up to date as part of doing a ``make install`` or its
@@ -16,6 +19,3 @@ target has undefined behavior.  Note that such a target can still safely
 be listed in an :command:`install(TARGETS)` command as long as the install
 components the target belongs to are not part of the set of components
 that anything tries to install.
-
-This property is enabled by default for targets that are created in
-directories that have :prop_dir:`EXCLUDE_FROM_ALL` set to ``TRUE``.
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 386a3f7..8a3720f 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2029,10 +2029,18 @@ bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
   return this->IsExcluded(rootSnp, snp);
 }
 
-bool cmGlobalGenerator::IsExcluded(cmGeneratorTarget* target) const
+bool cmGlobalGenerator::IsExcluded(cmLocalGenerator* root,
+                                   cmGeneratorTarget* target) const
 {
-  return target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
-    target->GetPropertyAsBool("EXCLUDE_FROM_ALL");
+  if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+    return true;
+  }
+  if (const char* exclude = target->GetProperty("EXCLUDE_FROM_ALL")) {
+    return cmSystemTools::IsOn(exclude);
+  }
+  // This target is included in its directory.  Check whether the
+  // directory is excluded.
+  return this->IsExcluded(root, target->GetLocalGenerator());
 }
 
 void cmGlobalGenerator::GetEnabledLanguages(
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index ac01326..0e40610 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -522,7 +522,7 @@ protected:
   bool IsExcluded(cmStateSnapshot const& root,
                   cmStateSnapshot const& snp) const;
   bool IsExcluded(cmLocalGenerator* root, cmLocalGenerator* gen) const;
-  bool IsExcluded(cmGeneratorTarget* target) const;
+  bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target) const;
   virtual void InitializeProgressMarks() {}
 
   struct GlobalTargetInfo
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index c619e67..226b73d 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -329,9 +329,9 @@ public:
     return LocalGenerators;
   }
 
-  bool IsExcluded(cmGeneratorTarget* target)
+  bool IsExcluded(cmLocalGenerator* root, cmGeneratorTarget* target)
   {
-    return cmGlobalGenerator::IsExcluded(target);
+    return cmGlobalGenerator::IsExcluded(root, target);
   }
 
   int GetRuleCmdLength(const std::string& name) { return RuleCmdLength[name]; }
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index dac6ea6..f1a128a 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -713,7 +713,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
                         localName, depends, commands, true);
 
       // add the all/all dependency
-      if (!this->IsExcluded(gtarget)) {
+      if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) {
         depends.clear();
         depends.push_back(localName);
         commands.clear();
@@ -777,7 +777,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
                           "Pre-install relink rule for target.", localName,
                           depends, commands, true);
 
-        if (!this->IsExcluded(gtarget)) {
+        if (!this->IsExcluded(this->LocalGenerators[0], gtarget)) {
           depends.clear();
           depends.push_back(localName);
           commands.clear();
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index f3ed76b..cc5a880 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -209,7 +209,7 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
               tgt->IsImported()) {
             continue;
           }
-          if (!this->IsExcluded(tgt)) {
+          if (!this->IsExcluded(gen[0], tgt)) {
             allBuild->AddUtility(tgt->GetName());
           }
         }
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 57de60e..dc63ce6 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -567,7 +567,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
           false, "", false, cmMakefile::AcceptObjectLibraryCommands);
       }
 
-      if (!this->IsExcluded(target)) {
+      if (!this->IsExcluded(gens[0], target)) {
         allbuild->AddUtility(target->GetName());
       }
     }
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index c0afc25..69656a2 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -88,7 +88,9 @@ void cmLocalNinjaGenerator::Generate()
     if (tg) {
       tg->Generate();
       // Add the target to "all" if required.
-      if (!this->GetGlobalNinjaGenerator()->IsExcluded(target)) {
+      if (!this->GetGlobalNinjaGenerator()->IsExcluded(
+            this->GetGlobalNinjaGenerator()->GetLocalGenerators()[0],
+            target)) {
         this->GetGlobalNinjaGenerator()->AddDependencyToAll(target);
       }
       delete tg;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 7e33bda..2735122 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -1151,7 +1151,7 @@ cmTarget* cmMakefile::AddUtilityCommand(
   // Create a target instance for this utility.
   cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
   target->SetIsGeneratorProvided(origin == TargetOrigin::Generator);
-  if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+  if (excludeFromAll) {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
   if (!comment) {
@@ -1689,7 +1689,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
   cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot);
   this->GetGlobalGenerator()->AddMakefile(subMf);
 
-  if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+  if (excludeFromAll) {
     subMf->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
 
@@ -1985,9 +1985,7 @@ cmTarget* cmMakefile::AddLibrary(const std::string& lname,
   // over changes in CMakeLists.txt, making the information stale and
   // hence useless.
   target->ClearDependencyInformation(*this);
-  if (excludeFromAll ||
-      (type != cmStateEnums::INTERFACE_LIBRARY &&
-       this->GetPropertyAsBool("EXCLUDE_FROM_ALL"))) {
+  if (excludeFromAll) {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
   target->AddSources(srcs);
@@ -2000,7 +1998,7 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName,
                                     bool excludeFromAll)
 {
   cmTarget* target = this->AddNewTarget(cmStateEnums::EXECUTABLE, exeName);
-  if (excludeFromAll || this->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
+  if (excludeFromAll) {
     target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
   }
   target->AddSources(srcs);
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll-build-sub-stderr.txt b/Tests/RunCMake/add_subdirectory/ExcludeFromAll-build-sub-stderr.txt
new file mode 100644
index 0000000..8d98f9d
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll-build-sub-stderr.txt
@@ -0,0 +1 @@
+.*
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
index 16f39d9..ff676a6 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
@@ -9,5 +9,6 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.c
 set(main_exe \"$<TARGET_FILE:main>\")
 set(foo_lib \"$<TARGET_FILE:foo>\")
 set(bar_lib \"$<TARGET_FILE:bar>\")
+set(zot_lib \"$<TARGET_FILE:zot>\")
 set(subinc_lib \"$<TARGET_FILE:subinc>\")
 ")
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
index 9d7922f..790da54 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
@@ -1,4 +1,8 @@
-add_library(bar STATIC bar.cpp)
+project(ExcludeFromAllSub NONE)
+
+add_library(bar STATIC EXCLUDE_FROM_ALL bar.cpp)
+
+add_library(zot STATIC zot.cpp)
 
 add_library(foo STATIC foo.cpp)
 target_include_directories(foo PUBLIC .)
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check-sub.cmake
similarity index 97%
copy from Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
copy to Tests/RunCMake/add_subdirectory/ExcludeFromAll/check-sub.cmake
index 56a8abd..297ad1e 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check-sub.cmake
@@ -7,7 +7,7 @@ if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
   foreach(file
       "${foo_lib}"
       "${subinc_lib}"
-      "${main_exe}"
+      "${zot_lib}"
       )
     if(NOT EXISTS "${file}")
       set(RunCMake_TEST_FAILED
@@ -16,6 +16,7 @@ if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
     endif()
   endforeach()
   foreach(file
+      "${main_exe}"
       "${bar_lib}"
       )
     if(EXISTS "${file}")
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
index 56a8abd..433c032 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
@@ -9,13 +9,17 @@ if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
       "${subinc_lib}"
       "${main_exe}"
       )
-    if(NOT EXISTS "${file}")
+    if(EXISTS "${file}")
+      # Remove for next step of test.
+      file(REMOVE "${file}")
+    else()
       set(RunCMake_TEST_FAILED
         "Artifact should exist but is missing:\n  ${file}")
       return()
     endif()
   endforeach()
   foreach(file
+      "${zot_lib}"
       "${bar_lib}"
       )
     if(EXISTS "${file}")
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/zot.cpp b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/zot.cpp
new file mode 100644
index 0000000..ba7e966
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/zot.cpp
@@ -0,0 +1,4 @@
+int zot()
+{
+  return 0;
+}
diff --git a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
index e9ba92f..951e03c 100644
--- a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
@@ -34,6 +34,26 @@ run_cmake(ExcludeFromAll)
 set(RunCMake_TEST_NO_CLEAN 1)
 set(RunCMake-check-file ExcludeFromAll/check.cmake)
 run_cmake_command(ExcludeFromAll-build ${CMAKE_COMMAND} --build . --config Debug)
+if(RunCMake_GENERATOR STREQUAL "Ninja")
+  if(WIN32)
+    set(slash [[\]])
+  else()
+    set(slash [[/]])
+  endif()
+  set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
+  run_cmake_command(ExcludeFromAll-build-sub ${CMAKE_COMMAND} --build . --target "ExcludeFromAll${slash}all")
+elseif(RunCMake_GENERATOR MATCHES "Make")
+  set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
+  set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY ${RunCMake_BINARY_DIR}/ExcludeFromAll-build/ExcludeFromAll)
+  run_cmake_command(ExcludeFromAll-build-sub "${RunCMake_MAKE_PROGRAM}")
+elseif(RunCMake_GENERATOR MATCHES "^Visual Studio [1-9][0-9]")
+  set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
+  run_cmake_command(ExcludeFromAll-build-sub ${CMAKE_COMMAND} --build ExcludeFromAll --config Debug)
+elseif(RunCMake_GENERATOR STREQUAL "Xcode")
+  set(RunCMake-check-file ExcludeFromAll/check-sub.cmake)
+  set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY ${RunCMake_BINARY_DIR}/ExcludeFromAll-build/ExcludeFromAll)
+  run_cmake_command(ExcludeFromAll-build-sub xcodebuild -configuration Debug)
+endif()
 unset(RunCMake-check-file)
 unset(RunCMake_TEST_NO_CLEAN)
 unset(RunCMake_TEST_OPTIONS)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=6bd40ccf8424a6e8c3a77857d48600ed7c624a07
commit 6bd40ccf8424a6e8c3a77857d48600ed7c624a07
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Sep 27 15:57:29 2019 +0200
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Sep 29 00:07:32 2019 +0200

    Autogen: Make cmQtAutoMocUic a free function

diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index ab91af4..3b0f717 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -2,20 +2,33 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmQtAutoMocUic.h"
 
-#include <algorithm>
-#include <set>
-#include <utility>
-
-#include <cm/memory>
-
 #include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
+#include "cmFileTime.h"
 #include "cmGeneratedFileStream.h"
 #include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
+#include "cmWorkerPool.h"
 #include "cm_jsoncpp_value.h"
 #include "cmsys/FStream.hxx"
+#include "cmsys/RegularExpression.hxx"
+
+#include <cm/memory>
+#include <cm/string_view>
+
+#include <algorithm>
+#include <atomic>
+#include <cstddef>
+#include <map>
+#include <mutex>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
 
 #if defined(__APPLE__)
 #  include <unistd.h>
@@ -26,10 +39,533 @@ namespace {
 constexpr std::size_t MocUnderscoreLength = 4; // Length of "moc_"
 constexpr std::size_t UiUnderscoreLength = 3;  // Length of "ui_"
 
-} // End of unnamed namespace
+/** \class cmQtAutoMocUicT
+ * \brief AUTOMOC and AUTOUIC generator
+ */
+class cmQtAutoMocUicT : public cmQtAutoGenerator
+{
+public:
+  cmQtAutoMocUicT();
+  ~cmQtAutoMocUicT() override;
+
+  cmQtAutoMocUicT(cmQtAutoMocUicT const&) = delete;
+  cmQtAutoMocUicT& operator=(cmQtAutoMocUicT const&) = delete;
+
+public:
+  // -- Types
+
+  /** Include string with sub parts.  */
+  struct IncludeKeyT
+  {
+    IncludeKeyT(std::string const& key, std::size_t basePrefixLength);
+
+    std::string Key;  // Full include string
+    std::string Dir;  // Include directory
+    std::string Base; // Base part of the include file name
+  };
+
+  /** Search key plus regular expression pair.  */
+  struct KeyExpT
+  {
+    KeyExpT(std::string key, std::string const& exp)
+      : Key(std::move(key))
+      , Exp(exp)
+    {
+    }
+
+    std::string Key;
+    cmsys::RegularExpression Exp;
+  };
+
+  /** Source file parsing cache.  */
+  class ParseCacheT
+  {
+  public:
+    // -- Types
+
+    /** Entry of the file parsing cache.  */
+    struct FileT
+    {
+      void Clear();
+
+      struct MocT
+      {
+        std::string Macro;
+        struct IncludeT
+        {
+          std::vector<IncludeKeyT> Underscore;
+          std::vector<IncludeKeyT> Dot;
+        } Include;
+        std::vector<std::string> Depends;
+      } Moc;
+
+      struct UicT
+      {
+        std::vector<IncludeKeyT> Include;
+        std::vector<std::string> Depends;
+      } Uic;
+    };
+    using FileHandleT = std::shared_ptr<FileT>;
+    using GetOrInsertT = std::pair<FileHandleT, bool>;
+
+  public:
+    ParseCacheT();
+    ~ParseCacheT();
+
+    bool ReadFromFile(std::string const& fileName);
+    bool WriteToFile(std::string const& fileName);
+
+    //! Always returns a valid handle
+    GetOrInsertT GetOrInsert(std::string const& fileName);
+
+  private:
+    std::unordered_map<std::string, FileHandleT> Map_;
+  };
+
+  /** Source file data.  */
+  class SourceFileT
+  {
+  public:
+    SourceFileT(std::string fileName)
+      : FileName(std::move(fileName))
+    {
+    }
+
+  public:
+    std::string FileName;
+    cmFileTime FileTime;
+    ParseCacheT::FileHandleT ParseData;
+    std::string BuildPath;
+    bool IsHeader = false;
+    bool Moc = false;
+    bool Uic = false;
+  };
+  using SourceFileHandleT = std::shared_ptr<SourceFileT>;
+  using SourceFileMapT = std::map<std::string, SourceFileHandleT>;
+
+  /** Meta compiler file mapping information.  */
+  struct MappingT
+  {
+    SourceFileHandleT SourceFile;
+    std::string OutputFile;
+    std::string IncludeString;
+    std::vector<SourceFileHandleT> IncluderFiles;
+  };
+  using MappingHandleT = std::shared_ptr<MappingT>;
+  using MappingMapT = std::map<std::string, MappingHandleT>;
+
+  /** Common settings.  */
+  class BaseSettingsT
+  {
+  public:
+    // -- Constructors
+    BaseSettingsT();
+    ~BaseSettingsT();
+
+    BaseSettingsT(BaseSettingsT const&) = delete;
+    BaseSettingsT& operator=(BaseSettingsT const&) = delete;
+
+    // -- Attributes
+    // - Config
+    bool MultiConfig = false;
+    unsigned int QtVersionMajor = 4;
+    unsigned int ThreadCount = 0;
+    // - Directories
+    std::string AutogenBuildDir;
+    std::string AutogenIncludeDir;
+    // - Files
+    std::string CMakeExecutable;
+    cmFileTime CMakeExecutableTime;
+    std::string ParseCacheFile;
+    std::vector<std::string> HeaderExtensions;
+  };
+
+  /** Shared common variables.  */
+  class BaseEvalT
+  {
+  public:
+    // -- Parse Cache
+    bool ParseCacheChanged = false;
+    cmFileTime ParseCacheTime;
+    ParseCacheT ParseCache;
+
+    // -- Sources
+    SourceFileMapT Headers;
+    SourceFileMapT Sources;
+  };
+
+  /** Moc settings.  */
+  class MocSettingsT
+  {
+  public:
+    // -- Constructors
+    MocSettingsT();
+    ~MocSettingsT();
+
+    MocSettingsT(MocSettingsT const&) = delete;
+    MocSettingsT& operator=(MocSettingsT const&) = delete;
+
+    // -- Const methods
+    bool skipped(std::string const& fileName) const;
+    std::string MacrosString() const;
+
+    // -- Attributes
+    bool Enabled = false;
+    bool SettingsChanged = false;
+    bool RelaxedMode = false;
+    bool PathPrefix = false;
+    cmFileTime ExecutableTime;
+    std::string Executable;
+    std::string CompFileAbs;
+    std::string PredefsFileAbs;
+    std::unordered_set<std::string> SkipList;
+    std::vector<std::string> IncludePaths;
+    std::vector<std::string> Definitions;
+    std::vector<std::string> OptionsIncludes;
+    std::vector<std::string> OptionsDefinitions;
+    std::vector<std::string> OptionsExtra;
+    std::vector<std::string> PredefsCmd;
+    std::vector<KeyExpT> DependFilters;
+    std::vector<KeyExpT> MacroFilters;
+    cmsys::RegularExpression RegExpInclude;
+  };
+
+  /** Moc shared variables.  */
+  class MocEvalT
+  {
+  public:
+    // -- predefines file
+    cmFileTime PredefsTime;
+    // -- Mappings
+    MappingMapT HeaderMappings;
+    MappingMapT SourceMappings;
+    MappingMapT Includes;
+    // -- Discovered files
+    SourceFileMapT HeadersDiscovered;
+    // -- Output directories
+    std::unordered_set<std::string> OutputDirs;
+    // -- Mocs compilation
+    bool CompUpdated = false;
+    std::vector<std::string> CompFiles;
+  };
+
+  /** Uic settings.  */
+  class UicSettingsT
+  {
+  public:
+    struct UiFile
+    {
+      std::vector<std::string> Options;
+    };
+
+  public:
+    UicSettingsT();
+    ~UicSettingsT();
+
+    UicSettingsT(UicSettingsT const&) = delete;
+    UicSettingsT& operator=(UicSettingsT const&) = delete;
+
+    // -- Const methods
+    bool skipped(std::string const& fileName) const;
+
+    // -- Attributes
+    bool Enabled = false;
+    bool SettingsChanged = false;
+    cmFileTime ExecutableTime;
+    std::string Executable;
+    std::unordered_set<std::string> SkipList;
+    std::vector<std::string> Options;
+    std::unordered_map<std::string, UiFile> UiFiles;
+    std::vector<std::string> SearchPaths;
+    cmsys::RegularExpression RegExpInclude;
+  };
+
+  /** Uic shared variables.  */
+  class UicEvalT
+  {
+  public:
+    // -- Discovered files
+    SourceFileMapT UiFiles;
+    // -- Mappings
+    MappingMapT Includes;
+    // -- Output directories
+    std::unordered_set<std::string> OutputDirs;
+  };
+
+  /** Abstract job class for concurrent job processing.  */
+  class JobT : public cmWorkerPool::JobT
+  {
+  protected:
+    /** Protected default constructor.  */
+    JobT(bool fence = false)
+      : cmWorkerPool::JobT(fence)
+    {
+    }
+
+    //! Get the generator. Only valid during Process() call!
+    cmQtAutoMocUicT* Gen() const
+    {
+      return static_cast<cmQtAutoMocUicT*>(UserData());
+    };
+
+    // -- Accessors. Only valid during Process() call!
+    Logger const& Log() const { return Gen()->Log(); }
+    BaseSettingsT const& BaseConst() const { return Gen()->BaseConst(); }
+    BaseEvalT& BaseEval() const { return Gen()->BaseEval(); }
+    MocSettingsT const& MocConst() const { return Gen()->MocConst(); }
+    MocEvalT& MocEval() const { return Gen()->MocEval(); }
+    UicSettingsT const& UicConst() const { return Gen()->UicConst(); }
+    UicEvalT& UicEval() const { return Gen()->UicEval(); }
+
+    // -- Logging
+    std::string MessagePath(cm::string_view path) const
+    {
+      return Gen()->MessagePath(path);
+    }
+    // - Error logging with automatic abort
+    void LogError(GenT genType, cm::string_view message) const;
+    void LogCommandError(GenT genType, cm::string_view message,
+                         std::vector<std::string> const& command,
+                         std::string const& output) const;
+
+    /** @brief Run an external process. Use only during Process() call!  */
+    bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
+                    std::vector<std::string> const& command,
+                    std::string* infoMessage = nullptr);
+  };
+
+  /** Fence job utility class.  */
+  class JobFenceT : public JobT
+  {
+  public:
+    JobFenceT()
+      : JobT(true)
+    {
+    }
+    void Process() override{};
+  };
+
+  /** Generate moc_predefs.h.  */
+  class JobMocPredefsT : public JobFenceT
+  {
+    void Process() override;
+    bool Update(std::string* reason) const;
+  };
+
+  /** File parse job base class.  */
+  class JobParseT : public JobT
+  {
+  public:
+    JobParseT(SourceFileHandleT fileHandle)
+      : FileHandle(std::move(fileHandle))
+    {
+    }
+
+  protected:
+    bool ReadFile();
+    void CreateKeys(std::vector<IncludeKeyT>& container,
+                    std::set<std::string> const& source,
+                    std::size_t basePrefixLength);
+    void MocMacro();
+    void MocDependecies();
+    void MocIncludes();
+    void UicIncludes();
+
+  protected:
+    SourceFileHandleT FileHandle;
+    std::string Content;
+  };
+
+  /** Header file parse job.  */
+  class JobParseHeaderT : public JobParseT
+  {
+  public:
+    using JobParseT::JobParseT;
+    void Process() override;
+  };
 
-cmQtAutoMocUic::IncludeKeyT::IncludeKeyT(std::string const& key,
-                                         std::size_t basePrefixLength)
+  /** Source file parse job.  */
+  class JobParseSourceT : public JobParseT
+  {
+  public:
+    using JobParseT::JobParseT;
+    void Process() override;
+  };
+
+  /** Evaluate cached file parse data - moc.  */
+  class JobEvalCacheT : public JobT
+  {
+  protected:
+    std::string MessageSearchLocations() const;
+    std::vector<std::string> SearchLocations;
+  };
+
+  /** Evaluate cached file parse data - moc.  */
+  class JobEvalCacheMocT : public JobEvalCacheT
+  {
+    void Process() override;
+    bool EvalHeader(SourceFileHandleT source);
+    bool EvalSource(SourceFileHandleT const& source);
+    bool FindIncludedHeader(SourceFileHandleT& headerHandle,
+                            cm::string_view includerDir,
+                            cm::string_view includeBase);
+    bool RegisterIncluded(std::string const& includeString,
+                          SourceFileHandleT includerFileHandle,
+                          SourceFileHandleT sourceFileHandle) const;
+    void RegisterMapping(MappingHandleT mappingHandle) const;
+    std::string MessageHeader(cm::string_view headerBase) const;
+  };
+
+  /** Evaluate cached file parse data - uic.  */
+  class JobEvalCacheUicT : public JobEvalCacheT
+  {
+    void Process() override;
+    bool EvalFile(SourceFileHandleT const& sourceFileHandle);
+    bool FindIncludedUi(cm::string_view sourceDirPrefix,
+                        cm::string_view includePrefix);
+    bool RegisterMapping(std::string const& includeString,
+                         SourceFileHandleT includerFileHandle);
+
+    std::string UiName;
+    SourceFileHandleT UiFileHandle;
+  };
+
+  /** Evaluate cached file parse data - finish  */
+  class JobEvalCacheFinishT : public JobFenceT
+  {
+    void Process() override;
+  };
+
+  /** Dependency probing base job.  */
+  class JobProbeDepsT : public JobT
+  {
+  };
+
+  /** Probes file dependencies and generates moc compile jobs.  */
+  class JobProbeDepsMocT : public JobProbeDepsT
+  {
+    void Process() override;
+    bool Generate(MappingHandleT const& mapping, bool compFile) const;
+    bool Probe(MappingT const& mapping, std::string* reason) const;
+    std::pair<std::string, cmFileTime> FindDependency(
+      std::string const& sourceDir, std::string const& includeString) const;
+  };
+
+  /** Probes file dependencies and generates uic compile jobs.  */
+  class JobProbeDepsUicT : public JobProbeDepsT
+  {
+    void Process() override;
+    bool Probe(MappingT const& mapping, std::string* reason) const;
+  };
+
+  /** Dependency probing finish job.  */
+  class JobProbeDepsFinishT : public JobFenceT
+  {
+    void Process() override;
+  };
+
+  /** Meta compiler base job.  */
+  class JobCompileT : public JobT
+  {
+  public:
+    JobCompileT(MappingHandleT uicMapping, std::unique_ptr<std::string> reason)
+      : Mapping(std::move(uicMapping))
+      , Reason(std::move(reason))
+    {
+    }
+
+  protected:
+    MappingHandleT Mapping;
+    std::unique_ptr<std::string> Reason;
+  };
+
+  /** moc compiles a file.  */
+  class JobCompileMocT : public JobCompileT
+  {
+  public:
+    using JobCompileT::JobCompileT;
+    void Process() override;
+  };
+
+  /** uic compiles a file.  */
+  class JobCompileUicT : public JobCompileT
+  {
+  public:
+    using JobCompileT::JobCompileT;
+    void Process() override;
+  };
+
+  /** Generate mocs_compilation.cpp.  */
+  class JobMocsCompilationT : public JobFenceT
+  {
+  private:
+    void Process() override;
+  };
+
+  /** @brief The last job.  */
+  class JobFinishT : public JobFenceT
+  {
+  private:
+    void Process() override;
+  };
+
+  // -- Const settings interface
+  BaseSettingsT const& BaseConst() const { return this->BaseConst_; }
+  BaseEvalT& BaseEval() { return this->BaseEval_; }
+  MocSettingsT const& MocConst() const { return this->MocConst_; }
+  MocEvalT& MocEval() { return this->MocEval_; }
+  UicSettingsT const& UicConst() const { return this->UicConst_; }
+  UicEvalT& UicEval() { return this->UicEval_; }
+
+  // -- Parallel job processing interface
+  cmWorkerPool& WorkerPool() { return WorkerPool_; }
+  void AbortError() { Abort(true); }
+  void AbortSuccess() { Abort(false); }
+
+  // -- Utility
+  std::string AbsoluteBuildPath(cm::string_view relativePath) const;
+  std::string AbsoluteIncludePath(cm::string_view relativePath) const;
+  template <class JOBTYPE>
+  void CreateParseJobs(SourceFileMapT const& sourceMap);
+  std::string CollapseFullPathTS(std::string const& path) const;
+
+private:
+  // -- Abstract processing interface
+  bool InitFromInfo(InfoT const& info) override;
+  void InitJobs();
+  bool Process() override;
+  // -- Settings file
+  void SettingsFileRead();
+  bool SettingsFileWrite();
+  // -- Parse cache
+  void ParseCacheRead();
+  bool ParseCacheWrite();
+  // -- Thread processing
+  void Abort(bool error);
+  // -- Generation
+  bool CreateDirectories();
+
+private:
+  // -- Settings
+  BaseSettingsT BaseConst_;
+  BaseEvalT BaseEval_;
+  MocSettingsT MocConst_;
+  MocEvalT MocEval_;
+  UicSettingsT UicConst_;
+  UicEvalT UicEval_;
+  // -- Settings file
+  std::string SettingsFile_;
+  std::string SettingsStringMoc_;
+  std::string SettingsStringUic_;
+  // -- Worker thread pool
+  std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
+  cmWorkerPool WorkerPool_;
+  // -- Concurrent processing
+  mutable std::mutex CMakeLibMutex_;
+};
+
+cmQtAutoMocUicT::IncludeKeyT::IncludeKeyT(std::string const& key,
+                                          std::size_t basePrefixLength)
   : Key(key)
   , Dir(SubDirPrefix(key))
   , Base(cmSystemTools::GetFilenameWithoutLastExtension(key))
@@ -39,7 +575,7 @@ cmQtAutoMocUic::IncludeKeyT::IncludeKeyT(std::string const& key,
   }
 }
 
-void cmQtAutoMocUic::ParseCacheT::FileT::Clear()
+void cmQtAutoMocUicT::ParseCacheT::FileT::Clear()
 {
   Moc.Macro.clear();
   Moc.Include.Underscore.clear();
@@ -50,18 +586,8 @@ void cmQtAutoMocUic::ParseCacheT::FileT::Clear()
   Uic.Depends.clear();
 }
 
-cmQtAutoMocUic::ParseCacheT::FileHandleT cmQtAutoMocUic::ParseCacheT::Get(
-  std::string const& fileName) const
-{
-  auto it = Map_.find(fileName);
-  if (it != Map_.end()) {
-    return it->second;
-  }
-  return FileHandleT();
-}
-
-cmQtAutoMocUic::ParseCacheT::GetOrInsertT
-cmQtAutoMocUic::ParseCacheT::GetOrInsert(std::string const& fileName)
+cmQtAutoMocUicT::ParseCacheT::GetOrInsertT
+cmQtAutoMocUicT::ParseCacheT::GetOrInsert(std::string const& fileName)
 {
   // Find existing entry
   {
@@ -77,15 +603,10 @@ cmQtAutoMocUic::ParseCacheT::GetOrInsert(std::string const& fileName)
   };
 }
 
-cmQtAutoMocUic::ParseCacheT::ParseCacheT() = default;
-cmQtAutoMocUic::ParseCacheT::~ParseCacheT() = default;
+cmQtAutoMocUicT::ParseCacheT::ParseCacheT() = default;
+cmQtAutoMocUicT::ParseCacheT::~ParseCacheT() = default;
 
-void cmQtAutoMocUic::ParseCacheT::Clear()
-{
-  Map_.clear();
-}
-
-bool cmQtAutoMocUic::ParseCacheT::ReadFromFile(std::string const& fileName)
+bool cmQtAutoMocUicT::ParseCacheT::ReadFromFile(std::string const& fileName)
 {
   cmsys::ifstream fin(fileName.c_str());
   if (!fin) {
@@ -148,7 +669,7 @@ bool cmQtAutoMocUic::ParseCacheT::ReadFromFile(std::string const& fileName)
   return true;
 }
 
-bool cmQtAutoMocUic::ParseCacheT::WriteToFile(std::string const& fileName)
+bool cmQtAutoMocUicT::ParseCacheT::WriteToFile(std::string const& fileName)
 {
   cmGeneratedFileStream ofs(fileName);
   if (!ofs) {
@@ -180,24 +701,24 @@ bool cmQtAutoMocUic::ParseCacheT::WriteToFile(std::string const& fileName)
   return ofs.Close();
 }
 
-cmQtAutoMocUic::BaseSettingsT::BaseSettingsT() = default;
-cmQtAutoMocUic::BaseSettingsT::~BaseSettingsT() = default;
+cmQtAutoMocUicT::BaseSettingsT::BaseSettingsT() = default;
+cmQtAutoMocUicT::BaseSettingsT::~BaseSettingsT() = default;
 
-cmQtAutoMocUic::MocSettingsT::MocSettingsT()
+cmQtAutoMocUicT::MocSettingsT::MocSettingsT()
 {
   RegExpInclude.compile(
     "(^|\n)[ \t]*#[ \t]*include[ \t]+"
     "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
 }
 
-cmQtAutoMocUic::MocSettingsT::~MocSettingsT() = default;
+cmQtAutoMocUicT::MocSettingsT::~MocSettingsT() = default;
 
-bool cmQtAutoMocUic::MocSettingsT::skipped(std::string const& fileName) const
+bool cmQtAutoMocUicT::MocSettingsT::skipped(std::string const& fileName) const
 {
   return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
 }
 
-std::string cmQtAutoMocUic::MocSettingsT::MacrosString() const
+std::string cmQtAutoMocUicT::MocSettingsT::MacrosString() const
 {
   std::string res;
   const auto itB = MacroFilters.cbegin();
@@ -219,27 +740,27 @@ std::string cmQtAutoMocUic::MocSettingsT::MacrosString() const
   return res;
 }
 
-cmQtAutoMocUic::UicSettingsT::UicSettingsT()
+cmQtAutoMocUicT::UicSettingsT::UicSettingsT()
 {
   RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
                         "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
 }
 
-cmQtAutoMocUic::UicSettingsT::~UicSettingsT() = default;
+cmQtAutoMocUicT::UicSettingsT::~UicSettingsT() = default;
 
-bool cmQtAutoMocUic::UicSettingsT::skipped(std::string const& fileName) const
+bool cmQtAutoMocUicT::UicSettingsT::skipped(std::string const& fileName) const
 {
   return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
 }
 
-void cmQtAutoMocUic::JobT::LogError(GenT genType,
-                                    cm::string_view message) const
+void cmQtAutoMocUicT::JobT::LogError(GenT genType,
+                                     cm::string_view message) const
 {
   Gen()->AbortError();
   Gen()->Log().Error(genType, message);
 }
 
-void cmQtAutoMocUic::JobT::LogCommandError(
+void cmQtAutoMocUicT::JobT::LogCommandError(
   GenT genType, cm::string_view message,
   std::vector<std::string> const& command, std::string const& output) const
 {
@@ -247,10 +768,10 @@ void cmQtAutoMocUic::JobT::LogCommandError(
   Gen()->Log().ErrorCommand(genType, message, command, output);
 }
 
-bool cmQtAutoMocUic::JobT::RunProcess(GenT genType,
-                                      cmWorkerPool::ProcessResultT& result,
-                                      std::vector<std::string> const& command,
-                                      std::string* infoMessage)
+bool cmQtAutoMocUicT::JobT::RunProcess(GenT genType,
+                                       cmWorkerPool::ProcessResultT& result,
+                                       std::vector<std::string> const& command,
+                                       std::string* infoMessage)
 {
   // Log command
   if (Log().Verbose()) {
@@ -268,7 +789,7 @@ bool cmQtAutoMocUic::JobT::RunProcess(GenT genType,
                                         BaseConst().AutogenBuildDir);
 }
 
-void cmQtAutoMocUic::JobMocPredefsT::Process()
+void cmQtAutoMocUicT::JobMocPredefsT::Process()
 {
   // (Re)generate moc_predefs.h on demand
   std::unique_ptr<std::string> reason;
@@ -330,7 +851,7 @@ void cmQtAutoMocUic::JobMocPredefsT::Process()
   }
 }
 
-bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
+bool cmQtAutoMocUicT::JobMocPredefsT::Update(std::string* reason) const
 {
   // Test if the file exists
   if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) {
@@ -369,7 +890,7 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
   return false;
 }
 
-bool cmQtAutoMocUic::JobParseT::ReadFile()
+bool cmQtAutoMocUicT::JobParseT::ReadFile()
 {
   // Clear old parse information
   FileHandle->ParseData->Clear();
@@ -396,9 +917,9 @@ bool cmQtAutoMocUic::JobParseT::ReadFile()
   return true;
 }
 
-void cmQtAutoMocUic::JobParseT::CreateKeys(std::vector<IncludeKeyT>& container,
-                                           std::set<std::string> const& source,
-                                           std::size_t basePrefixLength)
+void cmQtAutoMocUicT::JobParseT::CreateKeys(
+  std::vector<IncludeKeyT>& container, std::set<std::string> const& source,
+  std::size_t basePrefixLength)
 {
   if (source.empty()) {
     return;
@@ -409,7 +930,7 @@ void cmQtAutoMocUic::JobParseT::CreateKeys(std::vector<IncludeKeyT>& container,
   }
 }
 
-void cmQtAutoMocUic::JobParseT::MocMacro()
+void cmQtAutoMocUicT::JobParseT::MocMacro()
 {
   for (KeyExpT const& filter : MocConst().MacroFilters) {
     // Run a simple find string check
@@ -426,7 +947,7 @@ void cmQtAutoMocUic::JobParseT::MocMacro()
   }
 }
 
-void cmQtAutoMocUic::JobParseT::MocDependecies()
+void cmQtAutoMocUicT::JobParseT::MocDependecies()
 {
   if (MocConst().DependFilters.empty()) {
     return;
@@ -467,7 +988,7 @@ void cmQtAutoMocUic::JobParseT::MocDependecies()
   }
 }
 
-void cmQtAutoMocUic::JobParseT::MocIncludes()
+void cmQtAutoMocUicT::JobParseT::MocIncludes()
 {
   if (Content.find("moc") == std::string::npos) {
     return;
@@ -500,7 +1021,7 @@ void cmQtAutoMocUic::JobParseT::MocIncludes()
   CreateKeys(Include.Dot, dot, 0);
 }
 
-void cmQtAutoMocUic::JobParseT::UicIncludes()
+void cmQtAutoMocUicT::JobParseT::UicIncludes()
 {
   if (Content.find("ui_") == std::string::npos) {
     return;
@@ -520,7 +1041,7 @@ void cmQtAutoMocUic::JobParseT::UicIncludes()
   CreateKeys(FileHandle->ParseData->Uic.Include, includes, UiUnderscoreLength);
 }
 
-void cmQtAutoMocUic::JobParseHeaderT::Process()
+void cmQtAutoMocUicT::JobParseHeaderT::Process()
 {
   if (!ReadFile()) {
     return;
@@ -536,7 +1057,7 @@ void cmQtAutoMocUic::JobParseHeaderT::Process()
   }
 }
 
-void cmQtAutoMocUic::JobParseSourceT::Process()
+void cmQtAutoMocUicT::JobParseSourceT::Process()
 {
   if (!ReadFile()) {
     return;
@@ -553,7 +1074,7 @@ void cmQtAutoMocUic::JobParseSourceT::Process()
   }
 }
 
-std::string cmQtAutoMocUic::JobEvalCacheT::MessageSearchLocations() const
+std::string cmQtAutoMocUicT::JobEvalCacheT::MessageSearchLocations() const
 {
   std::string res;
   res.reserve(512);
@@ -565,7 +1086,7 @@ std::string cmQtAutoMocUic::JobEvalCacheT::MessageSearchLocations() const
   return res;
 }
 
-void cmQtAutoMocUic::JobEvalCacheMocT::Process()
+void cmQtAutoMocUicT::JobEvalCacheMocT::Process()
 {
   // Evaluate headers
   for (auto const& pair : BaseEval().Headers) {
@@ -581,7 +1102,7 @@ void cmQtAutoMocUic::JobEvalCacheMocT::Process()
   }
 }
 
-bool cmQtAutoMocUic::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
+bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
 {
   SourceFileT const& sourceFile = *source;
   auto const& parseData = sourceFile.ParseData->Moc;
@@ -608,7 +1129,7 @@ bool cmQtAutoMocUic::JobEvalCacheMocT::EvalHeader(SourceFileHandleT source)
   return true;
 }
 
-bool cmQtAutoMocUic::JobEvalCacheMocT::EvalSource(
+bool cmQtAutoMocUicT::JobEvalCacheMocT::EvalSource(
   SourceFileHandleT const& source)
 {
   SourceFileT const& sourceFile = *source;
@@ -809,7 +1330,7 @@ bool cmQtAutoMocUic::JobEvalCacheMocT::EvalSource(
   return true;
 }
 
-bool cmQtAutoMocUic::JobEvalCacheMocT::FindIncludedHeader(
+bool cmQtAutoMocUicT::JobEvalCacheMocT::FindIncludedHeader(
   SourceFileHandleT& headerHandle, cm::string_view includerDir,
   cm::string_view includeBase)
 {
@@ -874,7 +1395,7 @@ bool cmQtAutoMocUic::JobEvalCacheMocT::FindIncludedHeader(
   return false;
 }
 
-bool cmQtAutoMocUic::JobEvalCacheMocT::RegisterIncluded(
+bool cmQtAutoMocUicT::JobEvalCacheMocT::RegisterIncluded(
   std::string const& includeString, SourceFileHandleT includerFileHandle,
   SourceFileHandleT sourceFileHandle) const
 {
@@ -922,7 +1443,7 @@ bool cmQtAutoMocUic::JobEvalCacheMocT::RegisterIncluded(
   return true;
 }
 
-void cmQtAutoMocUic::JobEvalCacheMocT::RegisterMapping(
+void cmQtAutoMocUicT::JobEvalCacheMocT::RegisterMapping(
   MappingHandleT mappingHandle) const
 {
   auto& regMap = mappingHandle->SourceFile->IsHeader
@@ -941,14 +1462,14 @@ void cmQtAutoMocUic::JobEvalCacheMocT::RegisterMapping(
   }
 }
 
-std::string cmQtAutoMocUic::JobEvalCacheMocT::MessageHeader(
+std::string cmQtAutoMocUicT::JobEvalCacheMocT::MessageHeader(
   cm::string_view headerBase) const
 {
   return MessagePath(cmStrCat(
     headerBase, ".{", cmJoin(this->BaseConst().HeaderExtensions, ","), '}'));
 }
 
-void cmQtAutoMocUic::JobEvalCacheUicT::Process()
+void cmQtAutoMocUicT::JobEvalCacheUicT::Process()
 {
   // Prepare buffers
   SearchLocations.reserve((UicConst().SearchPaths.size() + 1) * 2);
@@ -967,7 +1488,7 @@ void cmQtAutoMocUic::JobEvalCacheUicT::Process()
   }
 }
 
-bool cmQtAutoMocUic::JobEvalCacheUicT::EvalFile(
+bool cmQtAutoMocUicT::JobEvalCacheUicT::EvalFile(
   SourceFileHandleT const& sourceFileHandle)
 {
   SourceFileT const& sourceFile = *sourceFileHandle;
@@ -1002,7 +1523,7 @@ bool cmQtAutoMocUic::JobEvalCacheUicT::EvalFile(
   return true;
 }
 
-bool cmQtAutoMocUic::JobEvalCacheUicT::FindIncludedUi(
+bool cmQtAutoMocUicT::JobEvalCacheUicT::FindIncludedUi(
   cm::string_view sourceDirPrefix, cm::string_view includePrefix)
 {
   // Clear locations buffer
@@ -1056,7 +1577,7 @@ bool cmQtAutoMocUic::JobEvalCacheUicT::FindIncludedUi(
   return false;
 }
 
-bool cmQtAutoMocUic::JobEvalCacheUicT::RegisterMapping(
+bool cmQtAutoMocUicT::JobEvalCacheUicT::RegisterMapping(
   std::string const& includeString, SourceFileHandleT includerFileHandle)
 {
   auto& Includes = Gen()->UicEval().Includes;
@@ -1101,7 +1622,7 @@ bool cmQtAutoMocUic::JobEvalCacheUicT::RegisterMapping(
   return true;
 }
 
-void cmQtAutoMocUic::JobEvalCacheFinishT::Process()
+void cmQtAutoMocUicT::JobEvalCacheFinishT::Process()
 {
   // Add discovered header parse jobs
   Gen()->CreateParseJobs<JobParseHeaderT>(MocEval().HeadersDiscovered);
@@ -1121,7 +1642,7 @@ void cmQtAutoMocUic::JobEvalCacheFinishT::Process()
   }
 }
 
-void cmQtAutoMocUic::JobProbeDepsMocT::Process()
+void cmQtAutoMocUicT::JobProbeDepsMocT::Process()
 {
   // Create moc header jobs
   for (auto const& pair : MocEval().HeaderMappings) {
@@ -1143,8 +1664,8 @@ void cmQtAutoMocUic::JobProbeDepsMocT::Process()
   }
 }
 
-bool cmQtAutoMocUic::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
-                                                bool compFile) const
+bool cmQtAutoMocUicT::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
+                                                 bool compFile) const
 {
   std::unique_ptr<std::string> reason;
   if (Log().Verbose()) {
@@ -1163,8 +1684,8 @@ bool cmQtAutoMocUic::JobProbeDepsMocT::Generate(MappingHandleT const& mapping,
   return true;
 }
 
-bool cmQtAutoMocUic::JobProbeDepsMocT::Probe(MappingT const& mapping,
-                                             std::string* reason) const
+bool cmQtAutoMocUicT::JobProbeDepsMocT::Probe(MappingT const& mapping,
+                                              std::string* reason) const
 {
   std::string const& sourceFile = mapping.SourceFile->FileName;
   std::string const& outputFile = mapping.OutputFile;
@@ -1254,7 +1775,7 @@ bool cmQtAutoMocUic::JobProbeDepsMocT::Probe(MappingT const& mapping,
 }
 
 std::pair<std::string, cmFileTime>
-cmQtAutoMocUic::JobProbeDepsMocT::FindDependency(
+cmQtAutoMocUicT::JobProbeDepsMocT::FindDependency(
   std::string const& sourceDir, std::string const& includeString) const
 {
   using ResPair = std::pair<std::string, cmFileTime>;
@@ -1276,7 +1797,7 @@ cmQtAutoMocUic::JobProbeDepsMocT::FindDependency(
   return ResPair();
 }
 
-void cmQtAutoMocUic::JobProbeDepsUicT::Process()
+void cmQtAutoMocUicT::JobProbeDepsUicT::Process()
 {
   for (auto const& pair : Gen()->UicEval().Includes) {
     MappingHandleT const& mapping = pair.second;
@@ -1295,8 +1816,8 @@ void cmQtAutoMocUic::JobProbeDepsUicT::Process()
   }
 }
 
-bool cmQtAutoMocUic::JobProbeDepsUicT::Probe(MappingT const& mapping,
-                                             std::string* reason) const
+bool cmQtAutoMocUicT::JobProbeDepsUicT::Probe(MappingT const& mapping,
+                                              std::string* reason) const
 {
   std::string const& sourceFile = mapping.SourceFile->FileName;
   std::string const& outputFile = mapping.OutputFile;
@@ -1345,7 +1866,7 @@ bool cmQtAutoMocUic::JobProbeDepsUicT::Probe(MappingT const& mapping,
   return false;
 }
 
-void cmQtAutoMocUic::JobProbeDepsFinishT::Process()
+void cmQtAutoMocUicT::JobProbeDepsFinishT::Process()
 {
   // Create output directories
   {
@@ -1381,7 +1902,7 @@ void cmQtAutoMocUic::JobProbeDepsFinishT::Process()
   Gen()->WorkerPool().EmplaceJob<JobFinishT>();
 }
 
-void cmQtAutoMocUic::JobCompileMocT::Process()
+void cmQtAutoMocUicT::JobCompileMocT::Process()
 {
   std::string const& sourceFile = Mapping->SourceFile->FileName;
   std::string const& outputFile = Mapping->OutputFile;
@@ -1458,7 +1979,7 @@ void cmQtAutoMocUic::JobCompileMocT::Process()
   }
 }
 
-void cmQtAutoMocUic::JobCompileUicT::Process()
+void cmQtAutoMocUicT::JobCompileUicT::Process()
 {
   std::string const& sourceFile = Mapping->SourceFile->FileName;
   std::string const& outputFile = Mapping->OutputFile;
@@ -1501,7 +2022,7 @@ void cmQtAutoMocUic::JobCompileUicT::Process()
   }
 }
 
-void cmQtAutoMocUic::JobMocsCompilationT::Process()
+void cmQtAutoMocUicT::JobMocsCompilationT::Process()
 {
   // Compose mocs compilation file content
   std::string content =
@@ -1546,18 +2067,18 @@ void cmQtAutoMocUic::JobMocsCompilationT::Process()
   }
 }
 
-void cmQtAutoMocUic::JobFinishT::Process()
+void cmQtAutoMocUicT::JobFinishT::Process()
 {
   Gen()->AbortSuccess();
 }
 
-cmQtAutoMocUic::cmQtAutoMocUic()
+cmQtAutoMocUicT::cmQtAutoMocUicT()
   : cmQtAutoGenerator(GenT::GEN)
 {
 }
-cmQtAutoMocUic::~cmQtAutoMocUic() = default;
+cmQtAutoMocUicT::~cmQtAutoMocUicT() = default;
 
-bool cmQtAutoMocUic::InitFromInfo(InfoT const& info)
+bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
 {
   // -- Required settings
   if (!info.GetBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
@@ -1894,7 +2415,7 @@ bool cmQtAutoMocUic::InitFromInfo(InfoT const& info)
 }
 
 template <class JOBTYPE>
-void cmQtAutoMocUic::CreateParseJobs(SourceFileMapT const& sourceMap)
+void cmQtAutoMocUicT::CreateParseJobs(SourceFileMapT const& sourceMap)
 {
   cmFileTime const parseCacheTime = BaseEval().ParseCacheTime;
   ParseCacheT& parseCache = BaseEval().ParseCache;
@@ -1911,13 +2432,13 @@ void cmQtAutoMocUic::CreateParseJobs(SourceFileMapT const& sourceMap)
 }
 
 /** Concurrently callable implementation of cmSystemTools::CollapseFullPath */
-std::string cmQtAutoMocUic::CollapseFullPathTS(std::string const& path) const
+std::string cmQtAutoMocUicT::CollapseFullPathTS(std::string const& path) const
 {
   std::lock_guard<std::mutex> guard(CMakeLibMutex_);
   return cmSystemTools::CollapseFullPath(path, ProjectDirs().CurrentSource);
 }
 
-void cmQtAutoMocUic::InitJobs()
+void cmQtAutoMocUicT::InitJobs()
 {
   // Add moc_predefs.h job
   if (MocConst().Enabled && !MocConst().PredefsCmd.empty()) {
@@ -1944,7 +2465,7 @@ void cmQtAutoMocUic::InitJobs()
   }
 }
 
-bool cmQtAutoMocUic::Process()
+bool cmQtAutoMocUicT::Process()
 {
   SettingsFileRead();
   ParseCacheRead();
@@ -1967,7 +2488,7 @@ bool cmQtAutoMocUic::Process()
   return true;
 }
 
-void cmQtAutoMocUic::SettingsFileRead()
+void cmQtAutoMocUicT::SettingsFileRead()
 {
   // Compose current settings strings
   {
@@ -2046,7 +2567,7 @@ void cmQtAutoMocUic::SettingsFileRead()
   }
 }
 
-bool cmQtAutoMocUic::SettingsFileWrite()
+bool cmQtAutoMocUicT::SettingsFileWrite()
 {
   // Only write if any setting changed
   if (MocConst().SettingsChanged || UicConst().SettingsChanged) {
@@ -2081,7 +2602,7 @@ bool cmQtAutoMocUic::SettingsFileWrite()
   return true;
 }
 
-void cmQtAutoMocUic::ParseCacheRead()
+void cmQtAutoMocUicT::ParseCacheRead()
 {
   cm::string_view reason;
   // Don't read the cache if it is invalid
@@ -2107,7 +2628,7 @@ void cmQtAutoMocUic::ParseCacheRead()
   }
 }
 
-bool cmQtAutoMocUic::ParseCacheWrite()
+bool cmQtAutoMocUicT::ParseCacheWrite()
 {
   if (BaseEval().ParseCacheChanged) {
     if (Log().Verbose()) {
@@ -2126,7 +2647,7 @@ bool cmQtAutoMocUic::ParseCacheWrite()
   return true;
 }
 
-bool cmQtAutoMocUic::CreateDirectories()
+bool cmQtAutoMocUicT::CreateDirectories()
 {
   // Create AUTOGEN include directory
   if (!cmSystemTools::MakeDirectory(BaseConst().AutogenIncludeDir)) {
@@ -2139,7 +2660,7 @@ bool cmQtAutoMocUic::CreateDirectories()
   return true;
 }
 
-void cmQtAutoMocUic::Abort(bool error)
+void cmQtAutoMocUicT::Abort(bool error)
 {
   if (error) {
     JobError_.store(true);
@@ -2147,14 +2668,21 @@ void cmQtAutoMocUic::Abort(bool error)
   WorkerPool_.Abort();
 }
 
-std::string cmQtAutoMocUic::AbsoluteBuildPath(
+std::string cmQtAutoMocUicT::AbsoluteBuildPath(
   cm::string_view relativePath) const
 {
   return cmStrCat(BaseConst().AutogenBuildDir, '/', relativePath);
 }
 
-std::string cmQtAutoMocUic::AbsoluteIncludePath(
+std::string cmQtAutoMocUicT::AbsoluteIncludePath(
   cm::string_view relativePath) const
 {
   return cmStrCat(BaseConst().AutogenIncludeDir, '/', relativePath);
 }
+
+} // End of unnamed namespace
+
+bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config)
+{
+  return cmQtAutoMocUicT().Run(infoFile, config);
+}
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index 53946ef..ffcc2db 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -5,555 +5,12 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include "cmFileTime.h"
-#include "cmQtAutoGen.h"
-#include "cmQtAutoGenerator.h"
-#include "cmWorkerPool.h"
-#include "cmsys/RegularExpression.hxx"
-
 #include <cm/string_view>
 
-#include <atomic>
-#include <cstddef>
-#include <map>
-#include <memory>
-#include <mutex>
-#include <set>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-/** \class cmQtAutoMocUic
- * \brief AUTOMOC and AUTOUIC generator
+/**
+ * Process AUTOMOC and AUTOUIC
+ * @return true on success
  */
-class cmQtAutoMocUic : public cmQtAutoGenerator
-{
-public:
-  cmQtAutoMocUic();
-  ~cmQtAutoMocUic() override;
-
-  cmQtAutoMocUic(cmQtAutoMocUic const&) = delete;
-  cmQtAutoMocUic& operator=(cmQtAutoMocUic const&) = delete;
-
-public:
-  // -- Types
-
-  /** Include string with sub parts.  */
-  struct IncludeKeyT
-  {
-    IncludeKeyT(std::string const& key, std::size_t basePrefixLength);
-
-    std::string Key;  // Full include string
-    std::string Dir;  // Include directory
-    std::string Base; // Base part of the include file name
-  };
-
-  /** Search key plus regular expression pair.  */
-  struct KeyExpT
-  {
-    KeyExpT() = default;
-
-    KeyExpT(std::string key, std::string const& exp)
-      : Key(std::move(key))
-      , Exp(exp)
-    {
-    }
-
-    std::string Key;
-    cmsys::RegularExpression Exp;
-  };
-
-  /** Source file parsing cache.  */
-  class ParseCacheT
-  {
-  public:
-    // -- Types
-
-    /** Entry of the file parsing cache.  */
-    struct FileT
-    {
-      void Clear();
-
-      struct MocT
-      {
-        std::string Macro;
-        struct IncludeT
-        {
-          std::vector<IncludeKeyT> Underscore;
-          std::vector<IncludeKeyT> Dot;
-        } Include;
-        std::vector<std::string> Depends;
-      } Moc;
-
-      struct UicT
-      {
-        std::vector<IncludeKeyT> Include;
-        std::vector<std::string> Depends;
-      } Uic;
-    };
-    using FileHandleT = std::shared_ptr<FileT>;
-    using GetOrInsertT = std::pair<FileHandleT, bool>;
-
-  public:
-    ParseCacheT();
-    ~ParseCacheT();
-
-    void Clear();
-
-    bool ReadFromFile(std::string const& fileName);
-    bool WriteToFile(std::string const& fileName);
-
-    //! Might return an invalid handle
-    FileHandleT Get(std::string const& fileName) const;
-    //! Always returns a valid handle
-    GetOrInsertT GetOrInsert(std::string const& fileName);
-
-  private:
-    std::unordered_map<std::string, FileHandleT> Map_;
-  };
-
-  /** Source file data.  */
-  class SourceFileT
-  {
-  public:
-    SourceFileT(std::string fileName)
-      : FileName(std::move(fileName))
-    {
-    }
-
-  public:
-    std::string FileName;
-    cmFileTime FileTime;
-    ParseCacheT::FileHandleT ParseData;
-    std::string BuildPath;
-    bool IsHeader = false;
-    bool Moc = false;
-    bool Uic = false;
-  };
-  using SourceFileHandleT = std::shared_ptr<SourceFileT>;
-  using SourceFileMapT = std::map<std::string, SourceFileHandleT>;
-
-  /** Meta compiler file mapping information.  */
-  struct MappingT
-  {
-    SourceFileHandleT SourceFile;
-    std::string OutputFile;
-    std::string IncludeString;
-    std::vector<SourceFileHandleT> IncluderFiles;
-  };
-  using MappingHandleT = std::shared_ptr<MappingT>;
-  using MappingMapT = std::map<std::string, MappingHandleT>;
-
-  /** Common settings.  */
-  class BaseSettingsT
-  {
-  public:
-    // -- Constructors
-    BaseSettingsT();
-    ~BaseSettingsT();
-
-    BaseSettingsT(BaseSettingsT const&) = delete;
-    BaseSettingsT& operator=(BaseSettingsT const&) = delete;
-
-    // -- Attributes
-    // - Config
-    bool MultiConfig = false;
-    unsigned int QtVersionMajor = 4;
-    unsigned int ThreadCount = 0;
-    // - Directories
-    std::string AutogenBuildDir;
-    std::string AutogenIncludeDir;
-    // - Files
-    std::string CMakeExecutable;
-    cmFileTime CMakeExecutableTime;
-    std::string ParseCacheFile;
-    std::vector<std::string> HeaderExtensions;
-  };
-
-  /** Shared common variables.  */
-  class BaseEvalT
-  {
-  public:
-    // -- Parse Cache
-    bool ParseCacheChanged = false;
-    cmFileTime ParseCacheTime;
-    ParseCacheT ParseCache;
-
-    // -- Sources
-    SourceFileMapT Headers;
-    SourceFileMapT Sources;
-  };
-
-  /** Moc settings.  */
-  class MocSettingsT
-  {
-  public:
-    // -- Constructors
-    MocSettingsT();
-    ~MocSettingsT();
-
-    MocSettingsT(MocSettingsT const&) = delete;
-    MocSettingsT& operator=(MocSettingsT const&) = delete;
-
-    // -- Const methods
-    bool skipped(std::string const& fileName) const;
-    std::string MacrosString() const;
-
-    // -- Attributes
-    bool Enabled = false;
-    bool SettingsChanged = false;
-    bool RelaxedMode = false;
-    bool PathPrefix = false;
-    cmFileTime ExecutableTime;
-    std::string Executable;
-    std::string CompFileAbs;
-    std::string PredefsFileAbs;
-    std::unordered_set<std::string> SkipList;
-    std::vector<std::string> IncludePaths;
-    std::vector<std::string> Definitions;
-    std::vector<std::string> OptionsIncludes;
-    std::vector<std::string> OptionsDefinitions;
-    std::vector<std::string> OptionsExtra;
-    std::vector<std::string> PredefsCmd;
-    std::vector<KeyExpT> DependFilters;
-    std::vector<KeyExpT> MacroFilters;
-    cmsys::RegularExpression RegExpInclude;
-  };
-
-  /** Moc shared variables.  */
-  class MocEvalT
-  {
-  public:
-    // -- predefines file
-    cmFileTime PredefsTime;
-    // -- Mappings
-    MappingMapT HeaderMappings;
-    MappingMapT SourceMappings;
-    MappingMapT Includes;
-    // -- Discovered files
-    SourceFileMapT HeadersDiscovered;
-    // -- Output directories
-    std::unordered_set<std::string> OutputDirs;
-    // -- Mocs compilation
-    bool CompUpdated = false;
-    std::vector<std::string> CompFiles;
-  };
-
-  /** Uic settings.  */
-  class UicSettingsT
-  {
-  public:
-    struct UiFile
-    {
-      std::vector<std::string> Options;
-    };
-
-  public:
-    UicSettingsT();
-    ~UicSettingsT();
-
-    UicSettingsT(UicSettingsT const&) = delete;
-    UicSettingsT& operator=(UicSettingsT const&) = delete;
-
-    // -- Const methods
-    bool skipped(std::string const& fileName) const;
-
-    // -- Attributes
-    bool Enabled = false;
-    bool SettingsChanged = false;
-    cmFileTime ExecutableTime;
-    std::string Executable;
-    std::unordered_set<std::string> SkipList;
-    std::vector<std::string> Options;
-    std::unordered_map<std::string, UiFile> UiFiles;
-    std::vector<std::string> SearchPaths;
-    cmsys::RegularExpression RegExpInclude;
-  };
-
-  /** Uic shared variables.  */
-  class UicEvalT
-  {
-  public:
-    // -- Discovered files
-    SourceFileMapT UiFiles;
-    // -- Mappings
-    MappingMapT Includes;
-    // -- Output directories
-    std::unordered_set<std::string> OutputDirs;
-  };
-
-  /** Abstract job class for concurrent job processing.  */
-  class JobT : public cmWorkerPool::JobT
-  {
-  protected:
-    /** Protected default constructor.  */
-    JobT(bool fence = false)
-      : cmWorkerPool::JobT(fence)
-    {
-    }
-
-    //! Get the generator. Only valid during Process() call!
-    cmQtAutoMocUic* Gen() const
-    {
-      return static_cast<cmQtAutoMocUic*>(UserData());
-    };
-
-    // -- Accessors. Only valid during Process() call!
-    Logger const& Log() const { return Gen()->Log(); }
-    BaseSettingsT const& BaseConst() const { return Gen()->BaseConst(); }
-    BaseEvalT& BaseEval() const { return Gen()->BaseEval(); }
-    MocSettingsT const& MocConst() const { return Gen()->MocConst(); }
-    MocEvalT& MocEval() const { return Gen()->MocEval(); }
-    UicSettingsT const& UicConst() const { return Gen()->UicConst(); }
-    UicEvalT& UicEval() const { return Gen()->UicEval(); }
-
-    // -- Logging
-    std::string MessagePath(cm::string_view path) const
-    {
-      return Gen()->MessagePath(path);
-    }
-    // - Error logging with automatic abort
-    void LogError(GenT genType, cm::string_view message) const;
-    void LogCommandError(GenT genType, cm::string_view message,
-                         std::vector<std::string> const& command,
-                         std::string const& output) const;
-
-    /** @brief Run an external process. Use only during Process() call!  */
-    bool RunProcess(GenT genType, cmWorkerPool::ProcessResultT& result,
-                    std::vector<std::string> const& command,
-                    std::string* infoMessage = nullptr);
-  };
-
-  /** Fence job utility class.  */
-  class JobFenceT : public JobT
-  {
-  public:
-    JobFenceT()
-      : JobT(true)
-    {
-    }
-    void Process() override{};
-  };
-
-  /** Generate moc_predefs.h.  */
-  class JobMocPredefsT : public JobFenceT
-  {
-    void Process() override;
-    bool Update(std::string* reason) const;
-  };
-
-  /** File parse job base class.  */
-  class JobParseT : public JobT
-  {
-  public:
-    JobParseT(SourceFileHandleT fileHandle)
-      : FileHandle(std::move(fileHandle))
-    {
-    }
-
-  protected:
-    bool ReadFile();
-    void CreateKeys(std::vector<IncludeKeyT>& container,
-                    std::set<std::string> const& source,
-                    std::size_t basePrefixLength);
-    void MocMacro();
-    void MocDependecies();
-    void MocIncludes();
-    void UicIncludes();
-
-  protected:
-    SourceFileHandleT FileHandle;
-    std::string Content;
-  };
-
-  /** Header file parse job.  */
-  class JobParseHeaderT : public JobParseT
-  {
-  public:
-    using JobParseT::JobParseT;
-    void Process() override;
-  };
-
-  /** Source file parse job.  */
-  class JobParseSourceT : public JobParseT
-  {
-  public:
-    using JobParseT::JobParseT;
-    void Process() override;
-  };
-
-  /** Evaluate cached file parse data - moc.  */
-  class JobEvalCacheT : public JobT
-  {
-  protected:
-    std::string MessageSearchLocations() const;
-    std::vector<std::string> SearchLocations;
-  };
-
-  /** Evaluate cached file parse data - moc.  */
-  class JobEvalCacheMocT : public JobEvalCacheT
-  {
-    void Process() override;
-    bool EvalHeader(SourceFileHandleT source);
-    bool EvalSource(SourceFileHandleT const& source);
-    bool FindIncludedHeader(SourceFileHandleT& headerHandle,
-                            cm::string_view includerDir,
-                            cm::string_view includeBase);
-    bool RegisterIncluded(std::string const& includeString,
-                          SourceFileHandleT includerFileHandle,
-                          SourceFileHandleT sourceFileHandle) const;
-    void RegisterMapping(MappingHandleT mappingHandle) const;
-    std::string MessageHeader(cm::string_view headerBase) const;
-  };
-
-  /** Evaluate cached file parse data - uic.  */
-  class JobEvalCacheUicT : public JobEvalCacheT
-  {
-    void Process() override;
-    bool EvalFile(SourceFileHandleT const& sourceFileHandle);
-    bool FindIncludedUi(cm::string_view sourceDirPrefix,
-                        cm::string_view includePrefix);
-    bool RegisterMapping(std::string const& includeString,
-                         SourceFileHandleT includerFileHandle);
-
-    std::string UiName;
-    SourceFileHandleT UiFileHandle;
-  };
-
-  /** Evaluate cached file parse data - finish  */
-  class JobEvalCacheFinishT : public JobFenceT
-  {
-    void Process() override;
-  };
-
-  /** Dependency probing base job.  */
-  class JobProbeDepsT : public JobT
-  {
-  };
-
-  /** Probes file dependencies and generates moc compile jobs.  */
-  class JobProbeDepsMocT : public JobProbeDepsT
-  {
-    void Process() override;
-    bool Generate(MappingHandleT const& mapping, bool compFile) const;
-    bool Probe(MappingT const& mapping, std::string* reason) const;
-    std::pair<std::string, cmFileTime> FindDependency(
-      std::string const& sourceDir, std::string const& includeString) const;
-  };
-
-  /** Probes file dependencies and generates uic compile jobs.  */
-  class JobProbeDepsUicT : public JobProbeDepsT
-  {
-    void Process() override;
-    bool Probe(MappingT const& mapping, std::string* reason) const;
-  };
-
-  /** Dependency probing finish job.  */
-  class JobProbeDepsFinishT : public JobFenceT
-  {
-    void Process() override;
-  };
-
-  /** Meta compiler base job.  */
-  class JobCompileT : public JobT
-  {
-  public:
-    JobCompileT(MappingHandleT uicMapping, std::unique_ptr<std::string> reason)
-      : Mapping(std::move(uicMapping))
-      , Reason(std::move(reason))
-    {
-    }
-
-  protected:
-    MappingHandleT Mapping;
-    std::unique_ptr<std::string> Reason;
-  };
-
-  /** moc compiles a file.  */
-  class JobCompileMocT : public JobCompileT
-  {
-  public:
-    using JobCompileT::JobCompileT;
-    void Process() override;
-  };
-
-  /** uic compiles a file.  */
-  class JobCompileUicT : public JobCompileT
-  {
-  public:
-    using JobCompileT::JobCompileT;
-    void Process() override;
-  };
-
-  /** Generate mocs_compilation.cpp.  */
-  class JobMocsCompilationT : public JobFenceT
-  {
-  private:
-    void Process() override;
-  };
-
-  /** @brief The last job.  */
-  class JobFinishT : public JobFenceT
-  {
-  private:
-    void Process() override;
-  };
-
-  // -- Const settings interface
-  BaseSettingsT const& BaseConst() const { return this->BaseConst_; }
-  BaseEvalT& BaseEval() { return this->BaseEval_; }
-  MocSettingsT const& MocConst() const { return this->MocConst_; }
-  MocEvalT& MocEval() { return this->MocEval_; }
-  UicSettingsT const& UicConst() const { return this->UicConst_; }
-  UicEvalT& UicEval() { return this->UicEval_; }
-
-  // -- Parallel job processing interface
-  cmWorkerPool& WorkerPool() { return WorkerPool_; }
-  void AbortError() { Abort(true); }
-  void AbortSuccess() { Abort(false); }
-
-  // -- Utility
-  std::string AbsoluteBuildPath(cm::string_view relativePath) const;
-  std::string AbsoluteIncludePath(cm::string_view relativePath) const;
-  template <class JOBTYPE>
-  void CreateParseJobs(SourceFileMapT const& sourceMap);
-  std::string CollapseFullPathTS(std::string const& path) const;
-
-private:
-  // -- Abstract processing interface
-  bool InitFromInfo(InfoT const& info) override;
-  void InitJobs();
-  bool Process() override;
-  // -- Settings file
-  void SettingsFileRead();
-  bool SettingsFileWrite();
-  // -- Parse cache
-  void ParseCacheRead();
-  bool ParseCacheWrite();
-  // -- Thread processing
-  void Abort(bool error);
-  // -- Generation
-  bool CreateDirectories();
-
-private:
-  // -- Settings
-  BaseSettingsT BaseConst_;
-  BaseEvalT BaseEval_;
-  MocSettingsT MocConst_;
-  MocEvalT MocEval_;
-  UicSettingsT UicConst_;
-  UicEvalT UicEval_;
-  // -- Settings file
-  std::string SettingsFile_;
-  std::string SettingsStringMoc_;
-  std::string SettingsStringUic_;
-  // -- Worker thread pool
-  std::atomic<bool> JobError_ = ATOMIC_VAR_INIT(false);
-  cmWorkerPool WorkerPool_;
-  // -- Concurrent processing
-  mutable std::mutex CMakeLibMutex_;
-};
+bool cmQtAutoMocUic(cm::string_view infoFile, cm::string_view config);
 
 #endif
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index f075e21..7bb3dce 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -27,6 +27,7 @@
 
 #if !defined(CMAKE_BOOTSTRAP) && defined(_WIN32)
 #  include "bindexplib.h"
+#  include "cmFileTime.h"
 #  include "cmsys/ConsoleBuf.hxx"
 #endif
 
@@ -1059,10 +1060,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
 
 #ifndef CMAKE_BOOTSTRAP
     if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
-      cmQtAutoMocUic autoGen;
       cm::string_view const infoFile = args[2];
       cm::string_view const config = args[3];
-      return autoGen.Run(infoFile, config) ? 0 : 1;
+      return cmQtAutoMocUic(infoFile, config) ? 0 : 1;
     }
     if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
       cm::string_view const infoFile = args[2];

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e0e9be3d575a255add19169d174c869fdebebbeb
commit e0e9be3d575a255add19169d174c869fdebebbeb
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Sep 27 15:49:13 2019 +0200
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Sep 29 00:07:32 2019 +0200

    Autogen: Make cmQtAutoRcc a free function

diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index 579cda7..4a3ecfa 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -5,23 +5,91 @@
 #include "cmAlgorithms.h"
 #include "cmCryptoHash.h"
 #include "cmDuration.h"
+#include "cmFileLock.h"
 #include "cmFileLockResult.h"
+#include "cmFileTime.h"
 #include "cmProcessOutput.h"
 #include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
-#include <cm/string_view>
-
 #include <algorithm>
+#include <string>
+#include <vector>
+
+namespace {
 
-cmQtAutoRcc::cmQtAutoRcc()
+/** \class cmQtAutoRccT
+ * \brief AUTORCC generator
+ */
+class cmQtAutoRccT : public cmQtAutoGenerator
+{
+public:
+  cmQtAutoRccT();
+  ~cmQtAutoRccT() override;
+
+  cmQtAutoRccT(cmQtAutoRccT const&) = delete;
+  cmQtAutoRccT& operator=(cmQtAutoRccT const&) = delete;
+
+private:
+  // -- Utility
+  bool IsMultiConfig() const { return MultiConfig_; }
+  std::string MultiConfigOutput() const;
+
+  // -- Abstract processing interface
+  bool InitFromInfo(InfoT const& info) override;
+  bool Process() override;
+  // -- Settings file
+  bool SettingsFileRead();
+  bool SettingsFileWrite();
+  // -- Tests
+  bool TestQrcRccFiles(bool& generate);
+  bool TestResources(bool& generate);
+  bool TestInfoFile();
+  // -- Generation
+  bool GenerateRcc();
+  bool GenerateWrapper();
+
+private:
+  // -- Config settings
+  bool MultiConfig_ = false;
+  // -- Directories
+  std::string AutogenBuildDir_;
+  std::string IncludeDir_;
+  // -- Qt environment
+  std::string RccExecutable_;
+  cmFileTime RccExecutableTime_;
+  std::vector<std::string> RccListOptions_;
+  // -- Job
+  std::string LockFile_;
+  cmFileLock LockFileLock_;
+  std::string QrcFile_;
+  std::string QrcFileName_;
+  std::string QrcFileDir_;
+  cmFileTime QrcFileTime_;
+  std::string RccPathChecksum_;
+  std::string RccFileName_;
+  std::string RccFileOutput_;
+  std::string RccFilePublic_;
+  cmFileTime RccFileTime_;
+  std::string Reason;
+  std::vector<std::string> Options_;
+  std::vector<std::string> Inputs_;
+  // -- Settings file
+  std::string SettingsFile_;
+  std::string SettingsString_;
+  bool SettingsChanged_ = false;
+  bool BuildFileChanged_ = false;
+};
+
+cmQtAutoRccT::cmQtAutoRccT()
   : cmQtAutoGenerator(GenT::RCC)
 {
 }
-cmQtAutoRcc::~cmQtAutoRcc() = default;
+cmQtAutoRccT::~cmQtAutoRccT() = default;
 
-bool cmQtAutoRcc::InitFromInfo(InfoT const& info)
+bool cmQtAutoRccT::InitFromInfo(InfoT const& info)
 {
   // -- Required settings
   if (!info.GetBool("MULTI_CONFIG", MultiConfig_, true) ||
@@ -61,7 +129,7 @@ bool cmQtAutoRcc::InitFromInfo(InfoT const& info)
   return true;
 }
 
-bool cmQtAutoRcc::Process()
+bool cmQtAutoRccT::Process()
 {
   if (!SettingsFileRead()) {
     return false;
@@ -94,13 +162,13 @@ bool cmQtAutoRcc::Process()
   return SettingsFileWrite();
 }
 
-std::string cmQtAutoRcc::MultiConfigOutput() const
+std::string cmQtAutoRccT::MultiConfigOutput() const
 {
   return cmStrCat(RccPathChecksum_, '/',
                   AppendFilenameSuffix(RccFileName_, "_CMAKE_"));
 }
 
-bool cmQtAutoRcc::SettingsFileRead()
+bool cmQtAutoRccT::SettingsFileRead()
 {
   // Compose current settings strings
   {
@@ -178,7 +246,7 @@ bool cmQtAutoRcc::SettingsFileRead()
   return true;
 }
 
-bool cmQtAutoRcc::SettingsFileWrite()
+bool cmQtAutoRccT::SettingsFileWrite()
 {
   // Only write if any setting changed
   if (SettingsChanged_) {
@@ -205,7 +273,7 @@ bool cmQtAutoRcc::SettingsFileWrite()
 }
 
 /// Do basic checks if rcc generation is required
-bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
+bool cmQtAutoRccT::TestQrcRccFiles(bool& generate)
 {
   // Test if the rcc input file exists
   if (!QrcFileTime_.Load(QrcFile_)) {
@@ -262,7 +330,7 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
   return true;
 }
 
-bool cmQtAutoRcc::TestResources(bool& generate)
+bool cmQtAutoRccT::TestResources(bool& generate)
 {
   // Read resource files list
   if (Inputs_.empty()) {
@@ -301,7 +369,7 @@ bool cmQtAutoRcc::TestResources(bool& generate)
   return true;
 }
 
-bool cmQtAutoRcc::TestInfoFile()
+bool cmQtAutoRccT::TestInfoFile()
 {
   // Test if the rcc output file is older than the info file
   if (RccFileTime_.Older(InfoFileTime())) {
@@ -324,7 +392,7 @@ bool cmQtAutoRcc::TestInfoFile()
   return true;
 }
 
-bool cmQtAutoRcc::GenerateRcc()
+bool cmQtAutoRccT::GenerateRcc()
 {
   // Make parent directory
   if (!MakeParentDirectory(RccFileOutput_)) {
@@ -376,7 +444,7 @@ bool cmQtAutoRcc::GenerateRcc()
   return true;
 }
 
-bool cmQtAutoRcc::GenerateWrapper()
+bool cmQtAutoRccT::GenerateWrapper()
 {
   // Generate a wrapper source file on demand
   if (IsMultiConfig()) {
@@ -426,3 +494,10 @@ bool cmQtAutoRcc::GenerateWrapper()
   }
   return true;
 }
+
+} // End of unnamed namespace
+
+bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config)
+{
+  return cmQtAutoRccT().Run(infoFile, config);
+}
diff --git a/Source/cmQtAutoRcc.h b/Source/cmQtAutoRcc.h
index 33c7960..a74b33a 100644
--- a/Source/cmQtAutoRcc.h
+++ b/Source/cmQtAutoRcc.h
@@ -5,74 +5,12 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
-#include "cmFileLock.h"
-#include "cmFileTime.h"
-#include "cmQtAutoGenerator.h"
+#include <cm/string_view>
 
-#include <string>
-#include <vector>
-
-/** \class cmQtAutoRcc
- * \brief AUTORCC generator
+/**
+ * Process AUTORCC
+ * @return true on success
  */
-class cmQtAutoRcc : public cmQtAutoGenerator
-{
-public:
-  cmQtAutoRcc();
-  ~cmQtAutoRcc() override;
-
-  cmQtAutoRcc(cmQtAutoRcc const&) = delete;
-  cmQtAutoRcc& operator=(cmQtAutoRcc const&) = delete;
-
-private:
-  // -- Utility
-  bool IsMultiConfig() const { return MultiConfig_; }
-  std::string MultiConfigOutput() const;
-
-  // -- Abstract processing interface
-  bool InitFromInfo(InfoT const& info) override;
-  bool Process() override;
-  // -- Settings file
-  bool SettingsFileRead();
-  bool SettingsFileWrite();
-  // -- Tests
-  bool TestQrcRccFiles(bool& generate);
-  bool TestResources(bool& generate);
-  bool TestInfoFile();
-  // -- Generation
-  bool GenerateRcc();
-  bool GenerateWrapper();
-
-private:
-  // -- Config settings
-  bool MultiConfig_ = false;
-  // -- Directories
-  std::string AutogenBuildDir_;
-  std::string IncludeDir_;
-  // -- Qt environment
-  std::string RccExecutable_;
-  cmFileTime RccExecutableTime_;
-  std::vector<std::string> RccListOptions_;
-  // -- Job
-  std::string LockFile_;
-  cmFileLock LockFileLock_;
-  std::string QrcFile_;
-  std::string QrcFileName_;
-  std::string QrcFileDir_;
-  cmFileTime QrcFileTime_;
-  std::string RccPathChecksum_;
-  std::string RccFileName_;
-  std::string RccFileOutput_;
-  std::string RccFilePublic_;
-  cmFileTime RccFileTime_;
-  std::string Reason;
-  std::vector<std::string> Options_;
-  std::vector<std::string> Inputs_;
-  // -- Settings file
-  std::string SettingsFile_;
-  std::string SettingsString_;
-  bool SettingsChanged_ = false;
-  bool BuildFileChanged_ = false;
-};
+bool cmQtAutoRcc(cm::string_view infoFile, cm::string_view config);
 
 #endif
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index b6076db..f075e21 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -1065,11 +1065,10 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
       return autoGen.Run(infoFile, config) ? 0 : 1;
     }
     if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
-      cmQtAutoRcc autoRcc;
       cm::string_view const infoFile = args[2];
       cm::string_view const config =
         (args.size() > 3) ? cm::string_view(args[3]) : cm::string_view();
-      return autoRcc.Run(infoFile, config) ? 0 : 1;
+      return cmQtAutoRcc(infoFile, config) ? 0 : 1;
     }
 #endif
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=820962edc9dd7481c440068dd894c1026abf671d
commit 820962edc9dd7481c440068dd894c1026abf671d
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Sep 27 14:47:05 2019 +0200
Commit:     Sebastian Holtermann <sebholt at xwmw.org>
CommitDate: Sun Sep 29 00:07:32 2019 +0200

    Autogen: Refactor json info file reading interface

diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index a9d4fee..1320b07 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -210,79 +210,18 @@ cmQtAutoGenerator::cmQtAutoGenerator(GenT genType)
 
 cmQtAutoGenerator::~cmQtAutoGenerator() = default;
 
-bool cmQtAutoGenerator::Run(std::string const& infoFile,
-                            std::string const& config)
+bool cmQtAutoGenerator::InfoT::Read(std::istream& istr)
 {
-  // Info settings
-  InfoFile_ = infoFile;
-  cmSystemTools::CollapseFullPath(InfoFile_);
-  if (!InfoFileTime_.Load(InfoFile_)) {
-    cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
-                                   Quoted(InfoFile_), " is not readable\n"));
-    return false;
-  }
-  InfoDir_ = cmSystemTools::GetFilenamePath(infoFile);
-  InfoConfig_ = config;
-
-  // Read info file
-  {
-    cmsys::ifstream ifs(InfoFile_.c_str(), (std::ios::in | std::ios::binary));
-    if (!ifs) {
-      Log().Error(GenType_,
-                  cmStrCat("Could not to open info file ", Quoted(InfoFile_)));
-      return false;
-    }
-    try {
-      ifs >> Info_;
-    } catch (...) {
-      Log().Error(GenType_,
-                  cmStrCat("Could not read info file ", Quoted(InfoFile_)));
-      return false;
-    }
-  }
-  // Info: setup logger
-  {
-    unsigned int value = 0;
-    if (!InfoUInt("VERBOSITY", value, false)) {
-      return false;
-    }
-    Logger_.RaiseVerbosity(value);
-  }
-  // Info: setup project directories
-  if (!InfoString("CMAKE_SOURCE_DIR", ProjectDirs_.Source, true) ||
-      !InfoString("CMAKE_BINARY_DIR", ProjectDirs_.Binary, true) ||
-      !InfoString("CMAKE_CURRENT_SOURCE_DIR", ProjectDirs_.CurrentSource,
-                  true) ||
-      !InfoString("CMAKE_CURRENT_BINARY_DIR", ProjectDirs_.CurrentBinary,
-                  true)) {
-    return false;
-  }
-
-  if (!this->InitFromInfo()) {
+  try {
+    istr >> Json_;
+  } catch (...) {
     return false;
   }
-  // Clear info
-  Info_ = Json::nullValue;
-
-  return this->Process();
-}
-
-bool cmQtAutoGenerator::LogInfoError(GenT genType,
-                                     cm::string_view message) const
-{
-  this->Log().Error(
-    genType,
-    cmStrCat("Info error in info file\n", Quoted(InfoFile()), ":\n", message));
-  return false;
-}
-
-bool cmQtAutoGenerator::LogInfoError(cm::string_view message) const
-{
-  return LogInfoError(GenType_, message);
+  return true;
 }
 
-bool cmQtAutoGenerator::JsonGetArray(std::vector<std::string>& list,
-                                     Json::Value const& jval)
+bool cmQtAutoGenerator::InfoT::GetJsonArray(std::vector<std::string>& list,
+                                            Json::Value const& jval)
 {
   Json::ArrayIndex const arraySize = jval.size();
   if (arraySize == 0) {
@@ -301,8 +240,8 @@ bool cmQtAutoGenerator::JsonGetArray(std::vector<std::string>& list,
   return picked;
 }
 
-bool cmQtAutoGenerator::JsonGetArray(std::unordered_set<std::string>& list,
-                                     Json::Value const& jval)
+bool cmQtAutoGenerator::InfoT::GetJsonArray(
+  std::unordered_set<std::string>& list, Json::Value const& jval)
 {
   Json::ArrayIndex const arraySize = jval.size();
   if (arraySize == 0) {
@@ -321,141 +260,157 @@ bool cmQtAutoGenerator::JsonGetArray(std::unordered_set<std::string>& list,
   return picked;
 }
 
-std::string cmQtAutoGenerator::InfoConfigKey(std::string const& key) const
+std::string cmQtAutoGenerator::InfoT::ConfigKey(cm::string_view key) const
 {
-  return cmStrCat(key, '_', InfoConfig());
+  return cmStrCat(key, '_', Gen_.InfoConfig());
 }
 
-bool cmQtAutoGenerator::InfoString(std::string const& key, std::string& value,
-                                   bool required) const
+bool cmQtAutoGenerator::InfoT::GetString(std::string const& key,
+                                         std::string& value,
+                                         bool required) const
 {
-  Json::Value const& jval = Info()[key];
+  Json::Value const& jval = Json_[key];
   if (!jval.isString()) {
     if (!jval.isNull() || required) {
-      return LogInfoError(cmStrCat(key, " is not a string."));
+      return LogError(cmStrCat(key, " is not a string."));
     }
   } else {
     value = jval.asString();
     if (value.empty() && required) {
-      return LogInfoError(cmStrCat(key, " is empty."));
+      return LogError(cmStrCat(key, " is empty."));
     }
   }
   return true;
 }
 
-bool cmQtAutoGenerator::InfoStringConfig(std::string const& key,
-                                         std::string& value,
-
-                                         bool required) const
+bool cmQtAutoGenerator::InfoT::GetStringConfig(std::string const& key,
+                                               std::string& value,
+                                               bool required) const
 {
   { // Try config
-    std::string const configKey = InfoConfigKey(key);
-    Json::Value const& jval = Info_[configKey];
+    std::string const configKey = ConfigKey(key);
+    Json::Value const& jval = Json_[configKey];
     if (!jval.isNull()) {
       if (!jval.isString()) {
-        return LogInfoError(cmStrCat(configKey, " is not a string."));
+        return LogError(cmStrCat(configKey, " is not a string."));
       }
       value = jval.asString();
       if (required && value.empty()) {
-        return LogInfoError(cmStrCat(configKey, " is empty."));
+        return LogError(cmStrCat(configKey, " is empty."));
       }
       return true;
     }
   }
   // Try plain
-  return InfoString(key, value, required);
+  return GetString(key, value, required);
 }
 
-bool cmQtAutoGenerator::InfoBool(std::string const& key, bool& value,
-                                 bool required) const
+bool cmQtAutoGenerator::InfoT::GetBool(std::string const& key, bool& value,
+                                       bool required) const
 {
-  Json::Value const& jval = Info()[key];
+  Json::Value const& jval = Json_[key];
   if (jval.isBool()) {
     value = jval.asBool();
   } else {
     if (!jval.isNull() || required) {
-      return LogInfoError(cmStrCat(key, " is not a boolean."));
+      return LogError(cmStrCat(key, " is not a boolean."));
     }
   }
   return true;
 }
 
-bool cmQtAutoGenerator::InfoUInt(std::string const& key, unsigned int& value,
-                                 bool required) const
+bool cmQtAutoGenerator::InfoT::GetUInt(std::string const& key,
+                                       unsigned int& value,
+                                       bool required) const
 {
-  Json::Value const& jval = Info()[key];
+  Json::Value const& jval = Json_[key];
   if (jval.isUInt()) {
     value = jval.asUInt();
   } else {
     if (!jval.isNull() || required) {
-      return LogInfoError(cmStrCat(key, " is not an unsigned integer."));
+      return LogError(cmStrCat(key, " is not an unsigned integer."));
     }
   }
   return true;
 }
 
-bool cmQtAutoGenerator::InfoArray(std::string const& key,
-                                  std::vector<std::string>& list,
-                                  bool required) const
+bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
+                                        std::vector<std::string>& list,
+                                        bool required) const
 {
-  Json::Value const& jval = Info()[key];
+  Json::Value const& jval = Json_[key];
   if (!jval.isArray()) {
     if (!jval.isNull() || required) {
-      return LogInfoError(cmStrCat(key, " is not an array."));
+      return LogError(cmStrCat(key, " is not an array."));
     }
   }
-  return JsonGetArray(list, jval) || !required;
+  return GetJsonArray(list, jval) || !required;
 }
 
-bool cmQtAutoGenerator::InfoArray(std::string const& key,
-                                  std::unordered_set<std::string>& list,
-                                  bool required) const
+bool cmQtAutoGenerator::InfoT::GetArray(std::string const& key,
+                                        std::unordered_set<std::string>& list,
+                                        bool required) const
 {
-  Json::Value const& jval = Info()[key];
+  Json::Value const& jval = Json_[key];
   if (!jval.isArray()) {
     if (!jval.isNull() || required) {
-      return LogInfoError(cmStrCat(key, " is not an array."));
+      return LogError(cmStrCat(key, " is not an array."));
     }
   }
-  return JsonGetArray(list, jval) || !required;
+  return GetJsonArray(list, jval) || !required;
 }
 
-bool cmQtAutoGenerator::InfoArrayConfig(std::string const& key,
-                                        std::vector<std::string>& list,
-                                        bool required) const
+bool cmQtAutoGenerator::InfoT::GetArrayConfig(std::string const& key,
+                                              std::vector<std::string>& list,
+                                              bool required) const
 {
   { // Try config
-    std::string const configKey = InfoConfigKey(key);
-    Json::Value const& jval = Info()[configKey];
+    std::string const configKey = ConfigKey(key);
+    Json::Value const& jval = Json_[configKey];
     if (!jval.isNull()) {
       if (!jval.isArray()) {
-        return LogInfoError(cmStrCat(configKey, " is not an array string."));
+        return LogError(cmStrCat(configKey, " is not an array string."));
       }
-      if (!JsonGetArray(list, jval) && required) {
-        return LogInfoError(cmStrCat(configKey, " is empty."));
+      if (!GetJsonArray(list, jval) && required) {
+        return LogError(cmStrCat(configKey, " is empty."));
       }
       return true;
     }
   }
   // Try plain
-  return InfoArray(key, list, required);
+  return GetArray(key, list, required);
+}
+
+bool cmQtAutoGenerator::InfoT::LogError(GenT genType,
+                                        cm::string_view message) const
+{
+  Gen_.Log().Error(genType,
+                   cmStrCat("Info error in info file\n",
+                            Quoted(Gen_.InfoFile()), ":\n", message));
+  return false;
 }
 
-std::string cmQtAutoGenerator::SettingsFind(std::string const& content,
-                                            const char* key)
+bool cmQtAutoGenerator::InfoT::LogError(cm::string_view message) const
 {
-  std::string prefix = cmStrCat(key, ':');
-  std::string::size_type pos = content.find(prefix);
-  if (pos != std::string::npos) {
+  return LogError(Gen_.GenType_, message);
+}
+
+std::string cmQtAutoGenerator::SettingsFind(cm::string_view content,
+                                            cm::string_view key)
+{
+  cm::string_view res;
+  std::string const prefix = cmStrCat(key, ':');
+  cm::string_view::size_type pos = content.find(prefix);
+  if (pos != cm::string_view::npos) {
     pos += prefix.size();
     if (pos < content.size()) {
-      std::string::size_type posE = content.find('\n', pos);
-      if ((posE != std::string::npos) && (posE != pos)) {
-        return content.substr(pos, posE - pos);
+      cm::string_view::size_type posE = content.find('\n', pos);
+      if ((posE != cm::string_view::npos) && (posE != pos)) {
+        res = content.substr(pos, posE - pos);
       }
     }
   }
-  return std::string();
+  return std::string(res);
 }
 
 std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const
@@ -470,3 +425,66 @@ std::string cmQtAutoGenerator::MessagePath(cm::string_view path) const
   }
   return cmQtAutoGen::Quoted(res);
 }
+
+bool cmQtAutoGenerator::Run(cm::string_view infoFile, cm::string_view config)
+{
+  // Info config
+  InfoConfig_ = std::string(config);
+
+  // Info file
+  InfoFile_ = std::string(infoFile);
+  cmSystemTools::CollapseFullPath(InfoFile_);
+  InfoDir_ = cmSystemTools::GetFilenamePath(InfoFile_);
+
+  // Load info file time
+  if (!InfoFileTime_.Load(InfoFile_)) {
+    cmSystemTools::Stderr(cmStrCat("AutoGen: The info file ",
+                                   Quoted(InfoFile_), " is not readable\n"));
+    return false;
+  }
+
+  {
+    InfoT info(*this);
+
+    // Read info file
+    {
+      cmsys::ifstream ifs(InfoFile_.c_str(),
+                          (std::ios::in | std::ios::binary));
+      if (!ifs) {
+        Log().Error(
+          GenType_,
+          cmStrCat("Could not to open info file ", Quoted(InfoFile_)));
+        return false;
+      }
+      if (!info.Read(ifs)) {
+        Log().Error(GenType_,
+                    cmStrCat("Could not read info file ", Quoted(InfoFile_)));
+        return false;
+      }
+    }
+
+    // -- Read common info settings
+    {
+      unsigned int verbosity = 0;
+      // Info: setup project directories
+      if (!info.GetUInt("VERBOSITY", verbosity, false) ||
+          !info.GetString("CMAKE_SOURCE_DIR", ProjectDirs_.Source, true) ||
+          !info.GetString("CMAKE_BINARY_DIR", ProjectDirs_.Binary, true) ||
+          !info.GetString("CMAKE_CURRENT_SOURCE_DIR",
+                          ProjectDirs_.CurrentSource, true) ||
+          !info.GetString("CMAKE_CURRENT_BINARY_DIR",
+                          ProjectDirs_.CurrentBinary, true)) {
+        return false;
+      }
+      Logger_.RaiseVerbosity(verbosity);
+    }
+
+    // -- Call virtual init from info method.
+    if (!this->InitFromInfo(info)) {
+      return false;
+    }
+  }
+
+  // Call virtual process method.
+  return this->Process();
+}
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
index 7f83fc6..71ee9ce 100644
--- a/Source/cmQtAutoGenerator.h
+++ b/Source/cmQtAutoGenerator.h
@@ -11,6 +11,7 @@
 
 #include <cm/string_view>
 
+#include <istream>
 #include <mutex>
 #include <string>
 #include <unordered_set>
@@ -86,54 +87,78 @@ public:
   cmQtAutoGenerator(cmQtAutoGenerator const&) = delete;
   cmQtAutoGenerator& operator=(cmQtAutoGenerator const&) = delete;
 
-  // -- Run
-  bool Run(std::string const& infoFile, std::string const& config);
-
-  // -- InfoFile
+  // -- Info options
   std::string const& InfoFile() const { return InfoFile_; }
-  Json::Value const& Info() const { return Info_; }
-  cmFileTime const& InfoFileTime() const { return InfoFileTime_; }
   std::string const& InfoDir() const { return InfoDir_; }
+  cmFileTime const& InfoFileTime() const { return InfoFileTime_; }
   std::string const& InfoConfig() const { return InfoConfig_; }
 
-  bool LogInfoError(GenT genType, cm::string_view message) const;
-  bool LogInfoError(cm::string_view message) const;
+  // -- Info file parsing
+  /** Info file reader class. */
+  class InfoT
+  {
+  public:
+    InfoT(cmQtAutoGenerator& gen)
+      : Gen_(gen)
+    {
+    }
+
+    /** Read json data from a stream.  */
+    bool Read(std::istream& istr);
+
+    /** Returns false if the JSON value isn't a string.  */
+    bool GetString(std::string const& key, std::string& value,
+                   bool required) const;
+    bool GetStringConfig(std::string const& key, std::string& value,
+                         bool required) const;
+    bool GetBool(std::string const& key, bool& value, bool required) const;
+    bool GetUInt(std::string const& key, unsigned int& value,
+                 bool required) const;
+    /** Returns false if the JSON value isn't an array.  */
+    bool GetArray(std::string const& key, std::vector<std::string>& list,
+                  bool required) const;
+    bool GetArray(std::string const& key,
+                  std::unordered_set<std::string>& list, bool required) const;
+    bool GetArrayConfig(std::string const& key, std::vector<std::string>& list,
+                        bool required) const;
 
-  /** Returns true if strings were appended to the list.  */
-  static bool JsonGetArray(std::vector<std::string>& list,
-                           Json::Value const& jval);
-  /** Returns true if strings were found in the JSON array.  */
-  static bool JsonGetArray(std::unordered_set<std::string>& list,
-                           Json::Value const& jval);
+    Json::Value const& GetValue(std::string const& key) const
+    {
+      return Json_[key];
+    }
 
-  std::string InfoConfigKey(std::string const& key) const;
+    /** Returns true if strings were appended to the list.  */
+    static bool GetJsonArray(std::vector<std::string>& list,
+                             Json::Value const& jval);
+    /** Returns true if strings were found in the JSON array.  */
+    static bool GetJsonArray(std::unordered_set<std::string>& list,
+                             Json::Value const& jval);
 
-  /** Returns false if the JSON value isn't a string.  */
-  bool InfoString(std::string const& key, std::string& value,
-                  bool required) const;
-  bool InfoStringConfig(std::string const& key, std::string& value,
-                        bool required) const;
-  bool InfoBool(std::string const& key, bool& value, bool required) const;
-  bool InfoUInt(std::string const& key, unsigned int& value,
-                bool required) const;
-  /** Returns false if the JSON value isn't an array.  */
-  bool InfoArray(std::string const& key, std::vector<std::string>& list,
-                 bool required) const;
-  bool InfoArray(std::string const& key, std::unordered_set<std::string>& list,
-                 bool required) const;
-  bool InfoArrayConfig(std::string const& key, std::vector<std::string>& list,
-                       bool required) const;
+    bool LogError(GenT genType, cm::string_view message) const;
+    bool LogError(cm::string_view message) const;
+
+  private:
+    std::string ConfigKey(cm::string_view key) const;
+
+  private:
+    Json::Value Json_;
+    cmQtAutoGenerator& Gen_;
+  };
+
+  // -- Settings file
+  static std::string SettingsFind(cm::string_view content,
+                                  cm::string_view key);
 
   // -- Directories
   ProjectDirsT const& ProjectDirs() const { return ProjectDirs_; }
-
-  // -- Utility
-  static std::string SettingsFind(std::string const& content, const char* key);
   std::string MessagePath(cm::string_view path) const;
 
+  // -- Run
+  bool Run(cm::string_view infoFile, cm::string_view config);
+
 protected:
   // -- Abstract processing interface
-  virtual bool InitFromInfo() = 0;
+  virtual bool InitFromInfo(InfoT const& info) = 0;
   virtual bool Process() = 0;
   // - Utility classes
   Logger const& Log() const { return Logger_; }
@@ -145,10 +170,9 @@ private:
   Logger Logger_;
   // -- Info file
   std::string InfoFile_;
-  cmFileTime InfoFileTime_;
   std::string InfoDir_;
+  cmFileTime InfoFileTime_;
   std::string InfoConfig_;
-  Json::Value Info_;
   // -- Directories
   ProjectDirsT ProjectDirs_;
 };
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 5f3cd5f..ab91af4 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -1557,28 +1557,30 @@ cmQtAutoMocUic::cmQtAutoMocUic()
 }
 cmQtAutoMocUic::~cmQtAutoMocUic() = default;
 
-bool cmQtAutoMocUic::InitFromInfo()
+bool cmQtAutoMocUic::InitFromInfo(InfoT const& info)
 {
   // -- Required settings
-  if (!InfoBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
-      !InfoUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) ||
-      !InfoUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
-      !InfoString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
-      !InfoStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir, true) ||
-      !InfoString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
-      !InfoStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile, true) ||
-      !InfoStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
-      !InfoArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
-      !InfoString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
-      !InfoString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
+  if (!info.GetBool("MULTI_CONFIG", BaseConst_.MultiConfig, true) ||
+      !info.GetUInt("QT_VERSION_MAJOR", BaseConst_.QtVersionMajor, true) ||
+      !info.GetUInt("PARALLEL", BaseConst_.ThreadCount, false) ||
+      !info.GetString("BUILD_DIR", BaseConst_.AutogenBuildDir, true) ||
+      !info.GetStringConfig("INCLUDE_DIR", BaseConst_.AutogenIncludeDir,
+                            true) ||
+      !info.GetString("CMAKE_EXECUTABLE", BaseConst_.CMakeExecutable, true) ||
+      !info.GetStringConfig("PARSE_CACHE_FILE", BaseConst_.ParseCacheFile,
+                            true) ||
+      !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
+      !info.GetArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
+      !info.GetString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
+      !info.GetString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
     return false;
   }
 
   // -- Checks
   if (!BaseConst_.CMakeExecutableTime.Load(BaseConst_.CMakeExecutable)) {
-    return LogInfoError(cmStrCat("The CMake executable ",
-                                 MessagePath(BaseConst_.CMakeExecutable),
-                                 " does not exist."));
+    return info.LogError(cmStrCat("The CMake executable ",
+                                  MessagePath(BaseConst_.CMakeExecutable),
+                                  " does not exist."));
   }
 
   // -- Evaluate values
@@ -1598,19 +1600,20 @@ bool cmQtAutoMocUic::InitFromInfo()
     } tmp;
 
     // -- Required settings
-    if (!InfoBool("MOC_RELAXED_MODE", MocConst_.RelaxedMode, false) ||
-        !InfoBool("MOC_PATH_PREFIX", MocConst_.PathPrefix, true) ||
-        !InfoArray("MOC_SKIP", MocConst_.SkipList, false) ||
-        !InfoArrayConfig("MOC_DEFINITIONS", MocConst_.Definitions, false) ||
-        !InfoArrayConfig("MOC_INCLUDES", MocConst_.IncludePaths, false) ||
-        !InfoArray("MOC_OPTIONS", MocConst_.OptionsExtra, false) ||
-        !InfoStringConfig("MOC_COMPILATION_FILE", MocConst_.CompFileAbs,
-                          true) ||
-        !InfoArray("MOC_PREDEFS_CMD", MocConst_.PredefsCmd, false) ||
-        !InfoStringConfig("MOC_PREDEFS_FILE", MocConst_.PredefsFileAbs,
-                          !MocConst_.PredefsCmd.empty()) ||
-        !InfoArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
-        !InfoArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
+    if (!info.GetBool("MOC_RELAXED_MODE", MocConst_.RelaxedMode, false) ||
+        !info.GetBool("MOC_PATH_PREFIX", MocConst_.PathPrefix, true) ||
+        !info.GetArray("MOC_SKIP", MocConst_.SkipList, false) ||
+        !info.GetArrayConfig("MOC_DEFINITIONS", MocConst_.Definitions,
+                             false) ||
+        !info.GetArrayConfig("MOC_INCLUDES", MocConst_.IncludePaths, false) ||
+        !info.GetArray("MOC_OPTIONS", MocConst_.OptionsExtra, false) ||
+        !info.GetStringConfig("MOC_COMPILATION_FILE", MocConst_.CompFileAbs,
+                              true) ||
+        !info.GetArray("MOC_PREDEFS_CMD", MocConst_.PredefsCmd, false) ||
+        !info.GetStringConfig("MOC_PREDEFS_FILE", MocConst_.PredefsFileAbs,
+                              !MocConst_.PredefsCmd.empty()) ||
+        !info.GetArray("MOC_MACRO_NAMES", tmp.MacroNames, true) ||
+        !info.GetArray("MOC_DEPEND_FILTERS", tmp.DependFilters, false)) {
       return false;
     }
 
@@ -1621,18 +1624,17 @@ bool cmQtAutoMocUic::InitFromInfo()
     }
     // Dependency filters
     {
-      Json::Value const& val = Info()["MOC_DEPEND_FILTERS"];
+      Json::Value const& val = info.GetValue("MOC_DEPEND_FILTERS");
       if (!val.isArray()) {
-        return LogInfoError("MOC_DEPEND_FILTERS JSON value is not an array.");
+        return info.LogError("MOC_DEPEND_FILTERS JSON value is not an array.");
       }
       Json::ArrayIndex const arraySize = val.size();
       for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
         // Test entry closure
-        auto testEntry = [this, ii](bool test,
-                                    cm::string_view message) -> bool {
+        auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
           if (!test) {
-            this->LogInfoError(
-              cmStrCat("MOC_DEPEND_FILTERS filter ", ii, ": ", message));
+            info.LogError(
+              cmStrCat("MOC_DEPEND_FILTERS filter ", ii, ": ", msg));
           }
           return !test;
         };
@@ -1671,9 +1673,9 @@ bool cmQtAutoMocUic::InitFromInfo()
     }
     // Check if moc executable exists (by reading the file time)
     if (!MocConst_.ExecutableTime.Load(MocConst_.Executable)) {
-      return LogInfoError(cmStrCat("The moc executable ",
-                                   MessagePath(MocConst_.Executable),
-                                   " does not exist."));
+      return info.LogError(cmStrCat("The moc executable ",
+                                    MessagePath(MocConst_.Executable),
+                                    " does not exist."));
     }
   }
 
@@ -1683,25 +1685,23 @@ bool cmQtAutoMocUic::InitFromInfo()
     UicConst_.Enabled = true;
 
     // -- Required settings
-    if (!InfoArray("UIC_SKIP", UicConst_.SkipList, false) ||
-        !InfoArray("UIC_SEARCH_PATHS", UicConst_.SearchPaths, false) ||
-        !InfoArrayConfig("UIC_OPTIONS", UicConst_.Options, false)) {
+    if (!info.GetArray("UIC_SKIP", UicConst_.SkipList, false) ||
+        !info.GetArray("UIC_SEARCH_PATHS", UicConst_.SearchPaths, false) ||
+        !info.GetArrayConfig("UIC_OPTIONS", UicConst_.Options, false)) {
       return false;
     }
     // .ui files
     {
-      Json::Value const& val = Info()["UIC_UI_FILES"];
+      Json::Value const& val = info.GetValue("UIC_UI_FILES");
       if (!val.isArray()) {
-        return LogInfoError("UIC_UI_FILES JSON value is not an array.");
+        return info.LogError("UIC_UI_FILES JSON value is not an array.");
       }
       Json::ArrayIndex const arraySize = val.size();
       for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
         // Test entry closure
-        auto testEntry = [this, ii](bool test,
-                                    cm::string_view message) -> bool {
+        auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
           if (!test) {
-            this->LogInfoError(
-              cmStrCat("UIC_UI_FILES entry ", ii, ": ", message));
+            info.LogError(cmStrCat("UIC_UI_FILES entry ", ii, ": ", msg));
           }
           return !test;
         };
@@ -1722,31 +1722,31 @@ bool cmQtAutoMocUic::InitFromInfo()
         }
 
         auto& uiFile = UicConst_.UiFiles[entryName.asString()];
-        JsonGetArray(uiFile.Options, entryOptions);
+        InfoT::GetJsonArray(uiFile.Options, entryOptions);
       }
     }
 
     // -- Evaluate settings
     // Check if uic executable exists (by reading the file time)
     if (!UicConst_.ExecutableTime.Load(UicConst_.Executable)) {
-      return LogInfoError(cmStrCat("The uic executable ",
-                                   MessagePath(UicConst_.Executable),
-                                   " does not exist."));
+      return info.LogError(cmStrCat("The uic executable ",
+                                    MessagePath(UicConst_.Executable),
+                                    " does not exist."));
     }
   }
 
   // -- Headers
   {
-    Json::Value const& val = Info()["HEADERS"];
+    Json::Value const& val = info.GetValue("HEADERS");
     if (!val.isArray()) {
-      return LogInfoError("HEADERS JSON value is not an array.");
+      return info.LogError("HEADERS JSON value is not an array.");
     }
     Json::ArrayIndex const arraySize = val.size();
     for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
       // Test entry closure
-      auto testEntry = [this, ii](bool test, cm::string_view message) -> bool {
+      auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
         if (!test) {
-          this->LogInfoError(cmStrCat("HEADERS entry ", ii, ": ", message));
+          info.LogError(cmStrCat("HEADERS entry ", ii, ": ", msg));
         }
         return !test;
       };
@@ -1778,9 +1778,8 @@ bool cmQtAutoMocUic::InitFromInfo()
 
       cmFileTime fileTime;
       if (!fileTime.Load(name)) {
-        LogInfoError(cmStrCat("The header file ", this->MessagePath(name),
-                              " does not exist."));
-        return false;
+        return info.LogError(cmStrCat(
+          "The header file ", this->MessagePath(name), " does not exist."));
       }
 
       SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
@@ -1790,7 +1789,7 @@ bool cmQtAutoMocUic::InitFromInfo()
       sourceHandle->Uic = (flags[1] == 'U');
       if (sourceHandle->Moc && MocConst().Enabled) {
         if (build.empty()) {
-          return LogInfoError(
+          return info.LogError(
             cmStrCat("Header file ", ii, " build path is empty"));
         }
         sourceHandle->BuildPath = std::move(build);
@@ -1801,16 +1800,16 @@ bool cmQtAutoMocUic::InitFromInfo()
 
   // -- Sources
   {
-    Json::Value const& val = Info()["SOURCES"];
+    Json::Value const& val = info.GetValue("SOURCES");
     if (!val.isArray()) {
-      return LogInfoError("SOURCES JSON value is not an array.");
+      return info.LogError("SOURCES JSON value is not an array.");
     }
     Json::ArrayIndex const arraySize = val.size();
     for (Json::ArrayIndex ii = 0; ii != arraySize; ++ii) {
       // Test entry closure
-      auto testEntry = [this, ii](bool test, cm::string_view message) -> bool {
+      auto testEntry = [&info, ii](bool test, cm::string_view msg) -> bool {
         if (!test) {
-          this->LogInfoError(cmStrCat("SOURCES entry ", ii, ": ", message));
+          info.LogError(cmStrCat("SOURCES entry ", ii, ": ", msg));
         }
         return !test;
       };
@@ -1838,9 +1837,8 @@ bool cmQtAutoMocUic::InitFromInfo()
 
       cmFileTime fileTime;
       if (!fileTime.Load(name)) {
-        LogInfoError(cmStrCat("The source file ", this->MessagePath(name),
-                              " does not exist."));
-        return false;
+        return info.LogError(cmStrCat(
+          "The source file ", this->MessagePath(name), " does not exist."));
       }
 
       SourceFileHandleT sourceHandle = std::make_shared<SourceFileT>(name);
diff --git a/Source/cmQtAutoMocUic.h b/Source/cmQtAutoMocUic.h
index 7101b8f..53946ef 100644
--- a/Source/cmQtAutoMocUic.h
+++ b/Source/cmQtAutoMocUic.h
@@ -523,7 +523,7 @@ public:
 
 private:
   // -- Abstract processing interface
-  bool InitFromInfo() override;
+  bool InitFromInfo(InfoT const& info) override;
   void InitJobs();
   bool Process() override;
   // -- Settings file
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index b0b15d4..579cda7 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -21,21 +21,21 @@ cmQtAutoRcc::cmQtAutoRcc()
 }
 cmQtAutoRcc::~cmQtAutoRcc() = default;
 
-bool cmQtAutoRcc::InitFromInfo()
+bool cmQtAutoRcc::InitFromInfo(InfoT const& info)
 {
   // -- Required settings
-  if (!InfoBool("MULTI_CONFIG", MultiConfig_, true) ||
-      !InfoString("BUILD_DIR", AutogenBuildDir_, true) ||
-      !InfoStringConfig("INCLUDE_DIR", IncludeDir_, true) ||
-      !InfoString("RCC_EXECUTABLE", RccExecutable_, true) ||
-      !InfoArray("RCC_LIST_OPTIONS", RccListOptions_, false) ||
-      !InfoString("LOCK_FILE", LockFile_, true) ||
-      !InfoStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
-      !InfoString("SOURCE", QrcFile_, true) ||
-      !InfoString("OUTPUT_CHECKSUM", RccPathChecksum_, true) ||
-      !InfoString("OUTPUT_NAME", RccFileName_, true) ||
-      !InfoArray("OPTIONS", Options_, false) ||
-      !InfoArray("INPUTS", Inputs_, false)) {
+  if (!info.GetBool("MULTI_CONFIG", MultiConfig_, true) ||
+      !info.GetString("BUILD_DIR", AutogenBuildDir_, true) ||
+      !info.GetStringConfig("INCLUDE_DIR", IncludeDir_, true) ||
+      !info.GetString("RCC_EXECUTABLE", RccExecutable_, true) ||
+      !info.GetArray("RCC_LIST_OPTIONS", RccListOptions_, false) ||
+      !info.GetString("LOCK_FILE", LockFile_, true) ||
+      !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
+      !info.GetString("SOURCE", QrcFile_, true) ||
+      !info.GetString("OUTPUT_CHECKSUM", RccPathChecksum_, true) ||
+      !info.GetString("OUTPUT_NAME", RccFileName_, true) ||
+      !info.GetArray("OPTIONS", Options_, false) ||
+      !info.GetArray("INPUTS", Inputs_, false)) {
     return false;
   }
 
@@ -54,7 +54,7 @@ bool cmQtAutoRcc::InitFromInfo()
 
   // -- Checks
   if (!RccExecutableTime_.Load(RccExecutable_)) {
-    return LogInfoError(cmStrCat(
+    return info.LogError(cmStrCat(
       "The rcc executable ", MessagePath(RccExecutable_), " does not exist."));
   }
 
diff --git a/Source/cmQtAutoRcc.h b/Source/cmQtAutoRcc.h
index 945b68f..33c7960 100644
--- a/Source/cmQtAutoRcc.h
+++ b/Source/cmQtAutoRcc.h
@@ -30,7 +30,7 @@ private:
   std::string MultiConfigOutput() const;
 
   // -- Abstract processing interface
-  bool InitFromInfo() override;
+  bool InitFromInfo(InfoT const& info) override;
   bool Process() override;
   // -- Settings file
   bool SettingsFileRead();
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index bf856d7..b6076db 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -48,6 +48,8 @@
 #include <sstream>
 #include <utility>
 
+#include <cm/string_view>
+
 class cmConnection;
 
 int cmcmd_cmake_ninja_depends(std::vector<std::string>::const_iterator argBeg,
@@ -1058,17 +1060,15 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
 #ifndef CMAKE_BOOTSTRAP
     if ((args[1] == "cmake_autogen") && (args.size() >= 4)) {
       cmQtAutoMocUic autoGen;
-      std::string const& infoFile = args[2];
-      std::string const& config = args[3];
+      cm::string_view const infoFile = args[2];
+      cm::string_view const config = args[3];
       return autoGen.Run(infoFile, config) ? 0 : 1;
     }
     if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) {
       cmQtAutoRcc autoRcc;
-      std::string const& infoFile = args[2];
-      std::string config;
-      if (args.size() > 3) {
-        config = args[3];
-      }
+      cm::string_view const infoFile = args[2];
+      cm::string_view const config =
+        (args.size() > 3) ? cm::string_view(args[3]) : cm::string_view();
       return autoRcc.Run(infoFile, config) ? 0 : 1;
     }
 #endif

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=dd0f304613b1661754d9cccf5829087a8bb19a12
commit dd0f304613b1661754d9cccf5829087a8bb19a12
Author:     Cristian Adam <cristian.adam at gmail.com>
AuthorDate: Tue Sep 17 19:21:09 2019 +0200
Commit:     Cristian Adam <cristian.adam at gmail.com>
CommitDate: Sat Sep 28 15:56:53 2019 +0200

    Objective C/C++: Add compiler standard detection

diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 3583dc9..303a484 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1941,10 +1941,20 @@ void cmLocalGenerator::AddCompilerRequirementFlag(
     langStdMap["CXX"].emplace_back("11");
     langStdMap["CXX"].emplace_back("98");
 
+    langStdMap["OBJCXX"].emplace_back("20");
+    langStdMap["OBJCXX"].emplace_back("17");
+    langStdMap["OBJCXX"].emplace_back("14");
+    langStdMap["OBJCXX"].emplace_back("11");
+    langStdMap["OBJCXX"].emplace_back("98");
+
     langStdMap["C"].emplace_back("11");
     langStdMap["C"].emplace_back("99");
     langStdMap["C"].emplace_back("90");
 
+    langStdMap["OBJC"].emplace_back("11");
+    langStdMap["OBJC"].emplace_back("99");
+    langStdMap["OBJC"].emplace_back("90");
+
     langStdMap["CUDA"].emplace_back("14");
     langStdMap["CUDA"].emplace_back("11");
     langStdMap["CUDA"].emplace_back("98");
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 34081ed..85ba38c 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -38,6 +38,7 @@
 #include "cmState.h"
 #include "cmStateDirectory.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTargetLinkLibraryType.h"
 #include "cmTest.h"
@@ -4615,9 +4616,9 @@ bool cmMakefile::AddRequiredTargetFeature(cmTarget* target,
 
   target->AppendProperty("COMPILE_FEATURES", feature.c_str());
 
-  return lang == "C"
-    ? this->AddRequiredTargetCFeature(target, feature, error)
-    : this->AddRequiredTargetCxxFeature(target, feature, error);
+  return lang == "C" || lang == "OBJC"
+    ? this->AddRequiredTargetCFeature(target, feature, lang, error)
+    : this->AddRequiredTargetCxxFeature(target, feature, lang, error);
 }
 
 bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
@@ -4709,30 +4710,33 @@ bool cmMakefile::HaveStandardAvailable(cmTarget const* target,
                                        std::string const& lang,
                                        const std::string& feature) const
 {
-  return lang == "C" ? this->HaveCStandardAvailable(target, feature)
-                     : this->HaveCxxStandardAvailable(target, feature);
+  return lang == "C" || lang == "OBJC"
+    ? this->HaveCStandardAvailable(target, feature, lang)
+    : this->HaveCxxStandardAvailable(target, feature, lang);
 }
 
 bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
-                                        const std::string& feature) const
+                                        const std::string& feature,
+                                        std::string const& lang) const
 {
   const char* defaultCStandard =
-    this->GetDefinition("CMAKE_C_STANDARD_DEFAULT");
+    this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
   if (!defaultCStandard) {
     this->IssueMessage(
       MessageType::INTERNAL_ERROR,
-      "CMAKE_C_STANDARD_DEFAULT is not set.  COMPILE_FEATURES support "
-      "not fully configured for this compiler.");
+      cmStrCat("CMAKE_", lang,
+               "_STANDARD_DEFAULT is not set.  COMPILE_FEATURES support "
+               "not fully configured for this compiler."));
     // Return true so the caller does not try to lookup the default standard.
     return true;
   }
   if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
                    cmStrCmp(defaultCStandard)) == cm::cend(C_STANDARDS)) {
-    std::ostringstream e;
-    e << "The CMAKE_C_STANDARD_DEFAULT variable contains an "
-         "invalid value: \""
-      << defaultCStandard << "\".";
-    this->IssueMessage(MessageType::INTERNAL_ERROR, e.str());
+    const std::string e = cmStrCat("The CMAKE_", lang,
+                                   "_STANDARD_DEFAULT variable contains an "
+                                   "invalid value: \"",
+                                   defaultCStandard, "\".");
+    this->IssueMessage(MessageType::INTERNAL_ERROR, e);
     return false;
   }
 
@@ -4740,19 +4744,20 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
   bool needC99 = false;
   bool needC11 = false;
 
-  this->CheckNeededCLanguage(feature, needC90, needC99, needC11);
+  this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
 
-  const char* existingCStandard = target->GetProperty("C_STANDARD");
+  const char* existingCStandard =
+    target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (!existingCStandard) {
     existingCStandard = defaultCStandard;
   }
 
   if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
                    cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
-    std::ostringstream e;
-    e << "The C_STANDARD property on target \"" << target->GetName()
-      << "\" contained an invalid value: \"" << existingCStandard << "\".";
-    this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+    const std::string e = cmStrCat(
+      "The ", lang, "_STANDARD property on target \"", target->GetName(),
+      "\" contained an invalid value: \"", existingCStandard, "\".");
+    this->IssueMessage(MessageType::FATAL_ERROR, e);
     return false;
   }
 
@@ -4783,7 +4788,7 @@ bool cmMakefile::IsLaterStandard(std::string const& lang,
                                  std::string const& lhs,
                                  std::string const& rhs)
 {
-  if (lang == "C") {
+  if (lang == "C" || lang == "OBJC") {
     const char* const* rhsIt = std::find_if(
       cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(rhs));
 
@@ -4798,25 +4803,26 @@ bool cmMakefile::IsLaterStandard(std::string const& lang,
 }
 
 bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
-                                          const std::string& feature) const
+                                          const std::string& feature,
+                                          std::string const& lang) const
 {
   const char* defaultCxxStandard =
-    this->GetDefinition("CMAKE_CXX_STANDARD_DEFAULT");
+    this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
   if (!defaultCxxStandard) {
     this->IssueMessage(
       MessageType::INTERNAL_ERROR,
-      "CMAKE_CXX_STANDARD_DEFAULT is not set.  COMPILE_FEATURES support "
-      "not fully configured for this compiler.");
+      cmStrCat("CMAKE_", lang,
+               "_STANDARD_DEFAULT is not set.  COMPILE_FEATURES support "
+               "not fully configured for this compiler."));
     // Return true so the caller does not try to lookup the default standard.
     return true;
   }
   if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
                    cmStrCmp(defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) {
-    std::ostringstream e;
-    e << "The CMAKE_CXX_STANDARD_DEFAULT variable contains an "
-         "invalid value: \""
-      << defaultCxxStandard << "\".";
-    this->IssueMessage(MessageType::INTERNAL_ERROR, e.str());
+    const std::string e =
+      cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ",
+               "invalid value: \"", defaultCxxStandard, "\".");
+    this->IssueMessage(MessageType::INTERNAL_ERROR, e);
     return false;
   }
 
@@ -4825,10 +4831,11 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
   bool needCxx14 = false;
   bool needCxx17 = false;
   bool needCxx20 = false;
-  this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
+  this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
                                needCxx17, needCxx20);
 
-  const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
+  const char* existingCxxStandard =
+    target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (!existingCxxStandard) {
     existingCxxStandard = defaultCxxStandard;
   }
@@ -4837,10 +4844,10 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
     std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
                  cmStrCmp(existingCxxStandard));
   if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
-    std::ostringstream e;
-    e << "The CXX_STANDARD property on target \"" << target->GetName()
-      << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
-    this->IssueMessage(MessageType::FATAL_ERROR, e.str());
+    const std::string e = cmStrCat(
+      "The ", lang, "_STANDARD property on target \"", target->GetName(),
+      "\" contained an invalid value: \"", existingCxxStandard, "\".");
+    this->IssueMessage(MessageType::FATAL_ERROR, e);
     return false;
   }
 
@@ -4858,32 +4865,33 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
 }
 
 void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
+                                        std::string const& lang,
                                         bool& needCxx98, bool& needCxx11,
                                         bool& needCxx14, bool& needCxx17,
                                         bool& needCxx20) const
 {
   if (const char* propCxx98 =
-        this->GetDefinition("CMAKE_CXX98_COMPILE_FEATURES")) {
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "98_COMPILE_FEATURES"))) {
     std::vector<std::string> props = cmExpandedList(propCxx98);
     needCxx98 = cmContains(props, feature);
   }
   if (const char* propCxx11 =
-        this->GetDefinition("CMAKE_CXX11_COMPILE_FEATURES")) {
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
     std::vector<std::string> props = cmExpandedList(propCxx11);
     needCxx11 = cmContains(props, feature);
   }
   if (const char* propCxx14 =
-        this->GetDefinition("CMAKE_CXX14_COMPILE_FEATURES")) {
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "14_COMPILE_FEATURES"))) {
     std::vector<std::string> props = cmExpandedList(propCxx14);
     needCxx14 = cmContains(props, feature);
   }
   if (const char* propCxx17 =
-        this->GetDefinition("CMAKE_CXX17_COMPILE_FEATURES")) {
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "17_COMPILE_FEATURES"))) {
     std::vector<std::string> props = cmExpandedList(propCxx17);
     needCxx17 = cmContains(props, feature);
   }
   if (const char* propCxx20 =
-        this->GetDefinition("CMAKE_CXX20_COMPILE_FEATURES")) {
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "20_COMPILE_FEATURES"))) {
     std::vector<std::string> props = cmExpandedList(propCxx20);
     needCxx20 = cmContains(props, feature);
   }
@@ -4891,6 +4899,7 @@ void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
 
 bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
                                              const std::string& feature,
+                                             std::string const& lang,
                                              std::string* error) const
 {
   bool needCxx98 = false;
@@ -4899,13 +4908,14 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
   bool needCxx17 = false;
   bool needCxx20 = false;
 
-  this->CheckNeededCxxLanguage(feature, needCxx98, needCxx11, needCxx14,
+  this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
                                needCxx17, needCxx20);
 
-  const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
+  const char* existingCxxStandard =
+    target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (existingCxxStandard == nullptr) {
     const char* defaultCxxStandard =
-      this->GetDefinition("CMAKE_CXX_STANDARD_DEFAULT");
+      this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
     if (defaultCxxStandard && *defaultCxxStandard) {
       existingCxxStandard = defaultCxxStandard;
     }
@@ -4916,14 +4926,14 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
       std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
                    cmStrCmp(existingCxxStandard));
     if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
-      std::ostringstream e;
-      e << "The CXX_STANDARD property on target \"" << target->GetName()
-        << "\" contained an invalid value: \"" << existingCxxStandard << "\".";
+      const std::string e = cmStrCat(
+        "The ", lang, "_STANDARD property on target \"", target->GetName(),
+        "\" contained an invalid value: \"", existingCxxStandard, "\".");
       if (error) {
-        *error = e.str();
+        *error = e;
       } else {
-        this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
-                                               e.str(), this->Backtrace);
+        this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
+                                               this->Backtrace);
       }
       return false;
     }
@@ -4964,7 +4974,7 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
     // Ensure the C++ language level is high enough to support
     // the needed C++ features.
     if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
-      target->SetProperty("CXX_STANDARD", *needCxxLevel);
+      target->SetProperty(cmStrCat(lang, "_STANDARD"), *needCxxLevel);
     }
 
     // Ensure the CUDA language level is high enough to support
@@ -4978,21 +4988,21 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
 }
 
 void cmMakefile::CheckNeededCLanguage(const std::string& feature,
-                                      bool& needC90, bool& needC99,
-                                      bool& needC11) const
+                                      std::string const& lang, bool& needC90,
+                                      bool& needC99, bool& needC11) const
 {
   if (const char* propC90 =
-        this->GetDefinition("CMAKE_C90_COMPILE_FEATURES")) {
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "90_COMPILE_FEATURES"))) {
     std::vector<std::string> props = cmExpandedList(propC90);
     needC90 = cmContains(props, feature);
   }
   if (const char* propC99 =
-        this->GetDefinition("CMAKE_C99_COMPILE_FEATURES")) {
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "99_COMPILE_FEATURES"))) {
     std::vector<std::string> props = cmExpandedList(propC99);
     needC99 = cmContains(props, feature);
   }
   if (const char* propC11 =
-        this->GetDefinition("CMAKE_C11_COMPILE_FEATURES")) {
+        this->GetDefinition(cmStrCat("CMAKE_", lang, "11_COMPILE_FEATURES"))) {
     std::vector<std::string> props = cmExpandedList(propC11);
     needC11 = cmContains(props, feature);
   }
@@ -5000,18 +5010,20 @@ void cmMakefile::CheckNeededCLanguage(const std::string& feature,
 
 bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
                                            const std::string& feature,
+                                           std::string const& lang,
                                            std::string* error) const
 {
   bool needC90 = false;
   bool needC99 = false;
   bool needC11 = false;
 
-  this->CheckNeededCLanguage(feature, needC90, needC99, needC11);
+  this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
 
-  const char* existingCStandard = target->GetProperty("C_STANDARD");
+  const char* existingCStandard =
+    target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (existingCStandard == nullptr) {
     const char* defaultCStandard =
-      this->GetDefinition("CMAKE_C_STANDARD_DEFAULT");
+      this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
     if (defaultCStandard && *defaultCStandard) {
       existingCStandard = defaultCStandard;
     }
@@ -5019,14 +5031,14 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
   if (existingCStandard) {
     if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
                      cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
-      std::ostringstream e;
-      e << "The C_STANDARD property on target \"" << target->GetName()
-        << "\" contained an invalid value: \"" << existingCStandard << "\".";
+      const std::string e = cmStrCat(
+        "The ", lang, "_STANDARD property on target \"", target->GetName(),
+        "\" contained an invalid value: \"", existingCStandard, "\".");
       if (error) {
-        *error = e.str();
+        *error = e;
       } else {
-        this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
-                                               e.str(), this->Backtrace);
+        this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e,
+                                               this->Backtrace);
       }
       return false;
     }
@@ -5057,11 +5069,11 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
   }
 
   if (setC11) {
-    target->SetProperty("C_STANDARD", "11");
+    target->SetProperty(cmStrCat(lang, "_STANDARD"), "11");
   } else if (setC99) {
-    target->SetProperty("C_STANDARD", "99");
+    target->SetProperty(cmStrCat(lang, "_STANDARD"), "99");
   } else if (setC90) {
-    target->SetProperty("C_STANDARD", "90");
+    target->SetProperty(cmStrCat(lang, "_STANDARD"), "90");
   }
   return true;
 }
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index db37477..1dc83b4 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -1135,22 +1135,28 @@ private:
   bool MightHaveCustomCommand(const std::string& name) const;
 
   bool AddRequiredTargetCFeature(cmTarget* target, const std::string& feature,
+                                 std::string const& lang,
                                  std::string* error = nullptr) const;
 
   bool AddRequiredTargetCxxFeature(cmTarget* target,
                                    const std::string& feature,
+                                   std::string const& lang,
                                    std::string* error = nullptr) const;
 
-  void CheckNeededCLanguage(const std::string& feature, bool& needC90,
+  void CheckNeededCLanguage(const std::string& feature,
+                            std::string const& lang, bool& needC90,
                             bool& needC99, bool& needC11) const;
-  void CheckNeededCxxLanguage(const std::string& feature, bool& needCxx98,
+  void CheckNeededCxxLanguage(const std::string& feature,
+                              std::string const& lang, bool& needCxx98,
                               bool& needCxx11, bool& needCxx14,
                               bool& needCxx17, bool& needCxx20) const;
 
   bool HaveCStandardAvailable(cmTarget const* target,
-                              const std::string& feature) const;
+                              const std::string& feature,
+                              std::string const& lang) const;
   bool HaveCxxStandardAvailable(cmTarget const* target,
-                                const std::string& feature) const;
+                                const std::string& feature,
+                                std::string const& lang) const;
 
   void CheckForUnusedVariables() const;
 
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 1b88db6..f65a018 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -332,6 +332,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
     initProp("C_STANDARD");
     initProp("C_STANDARD_REQUIRED");
     initProp("C_EXTENSIONS");
+    initProp("OBJC_STANDARD");
+    initProp("OBJC_STANDARD_REQUIRED");
+    initProp("OBJC_EXTENSIONS");
     initProp("CXX_CLANG_TIDY");
     initProp("CXX_COMPILER_LAUNCHER");
     initProp("CXX_CPPLINT");
@@ -340,6 +343,9 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
     initProp("CXX_STANDARD");
     initProp("CXX_STANDARD_REQUIRED");
     initProp("CXX_EXTENSIONS");
+    initProp("OBJCXX_STANDARD");
+    initProp("OBJCXX_STANDARD_REQUIRED");
+    initProp("OBJCXX_EXTENSIONS");
     initProp("CUDA_STANDARD");
     initProp("CUDA_STANDARD_REQUIRED");
     initProp("CUDA_EXTENSIONS");
@@ -452,6 +458,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
       this->GetType() != cmStateEnums::UTILITY) {
     initProp("C_VISIBILITY_PRESET");
     initProp("CXX_VISIBILITY_PRESET");
+    initProp("OBJC_VISIBILITY_PRESET");
+    initProp("OBJCXX_VISIBILITY_PRESET");
     initProp("CUDA_VISIBILITY_PRESET");
     initProp("VISIBILITY_INLINES_HIDDEN");
   }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b515af782bccf147e8bd62444c9f1808668f12ac
commit b515af782bccf147e8bd62444c9f1808668f12ac
Author:     Cristian Adam <cristian.adam at gmail.com>
AuthorDate: Fri Sep 13 20:21:23 2019 +0200
Commit:     Cristian Adam <cristian.adam at gmail.com>
CommitDate: Sat Sep 28 15:56:53 2019 +0200

    Help: Add release note for Objective-C/C++ language support

diff --git a/Help/release/dev/objective-c-cxx.rst b/Help/release/dev/objective-c-cxx.rst
new file mode 100644
index 0000000..218af4e
--- /dev/null
+++ b/Help/release/dev/objective-c-cxx.rst
@@ -0,0 +1,9 @@
+Objective C/C++
+---------------
+
+* CMake learned to support the Objective C (``OBJC``) and Objective C++
+  (``OBJCXX``) languages.  They may be enabled via the :command:`project`
+  and :command:`enable_language` commands.  When ``OBJC`` or ``OBJCXX``
+  is enabled, source files with the ``.m`` or ``.mm``, respectively,
+  will be compiled as Objective C or C++.  Otherwise they will be treated
+  as plain C++ sources as they were before.

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9e66397c28110f015e5b044dfe9782cd5f11c8c3
commit 9e66397c28110f015e5b044dfe9782cd5f11c8c3
Author:     Steve Wilson <stevew at wolfram.com>
AuthorDate: Fri Sep 13 18:12:15 2019 +0100
Commit:     Cristian Adam <cristian.adam at gmail.com>
CommitDate: Sat Sep 28 15:56:53 2019 +0200

    Languages: Add support for Objective-C++
    
    Add entries in Modules and Modules/Platform to support
    Objective-C++ compiler determination and identification.
    Add Modules to check Objective-C++ compiler flags, source
    compilations, program checks, etc...
    
    Use OBJCXX as the designator of the language, eg:
    
    project(foo OBJCXX)
    
    Add various tests for Objective-C++ language features.  Add
    tests to preserve C++ handling of .M and .mm files when
    Objective-C++ is not a configured language.
    
    Co-authored-by: Cristian Adam <cristian.adam at gmail.com>

diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst
index 44beb54..fdc44f2 100644
--- a/Help/command/enable_language.rst
+++ b/Help/command/enable_language.rst
@@ -1,7 +1,6 @@
 enable_language
 ---------------
-
-Enable a language (CXX/C/OBJC/Fortran/etc)
+Enable a language (CXX/C/OBJC/OBJCXX/Fortran/etc)
 
 .. code-block:: cmake
 
@@ -10,7 +9,7 @@ Enable a language (CXX/C/OBJC/Fortran/etc)
 Enables support for the named language in CMake.  This is
 the same as the :command:`project` command but does not create any of the extra
 variables that are created by the project command.  Example languages
-are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``Fortran``, and ``ASM``.
+are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``OBJCXX``, ``Fortran``, and ``ASM``.
 
 If enabling ``ASM``, enable it last so that CMake can check whether
 compilers for other languages like ``C`` work for assembly too.
diff --git a/Help/command/project.rst b/Help/command/project.rst
index 2bbb3f4..3951456 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -87,8 +87,8 @@ The options are:
   Can also be specified without ``LANGUAGES`` keyword per the first, short signature.
 
   Selects which programming languages are needed to build the project.
-  Supported languages include ``C``, ``CXX`` (i.e.  C++), ``CUDA``, ``OBJC`` (i.e. Objective-C),
-  ``Fortran``, and ``ASM``.
+  Supported languages include ``C``, ``CXX`` (i.e.  C++), ``CUDA``,
+  ``OBJC`` (i.e. Objective-C), ``OBJCXX``, ``Fortran``, and ``ASM``.
   By default ``C`` and ``CXX`` are enabled if no language options are given.
   Specify language ``NONE``, or use the ``LANGUAGES`` keyword and list no languages,
   to skip enabling any languages.
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index 8890433..6e7f9b5 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -135,6 +135,11 @@ Variable Queries
   ``1`` if the CMake's compiler id of the Objective-C compiler matches any one
   of the entries in ``compiler_ids``, otherwise ``0``.
   See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+``$<OBJCXX_COMPILER_ID:compiler_ids>``
+  where ``compiler_ids`` is a comma-separated list.
+  ``1`` if the CMake's compiler id of the Objective-C++ compiler matches any one
+  of the entries in ``compiler_ids``, otherwise ``0``.
+  See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
 ``$<Fortran_COMPILER_ID:compiler_ids>``
   where ``compiler_ids`` is a comma-separated list.
   ``1`` if the CMake's compiler id of the Fortran compiler matches any one
@@ -149,6 +154,12 @@ Variable Queries
 ``$<CUDA_COMPILER_VERSION:version>``
   ``1`` if the version of the CXX compiler matches ``version``, otherwise ``0``.
   See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+``$<OBJC_COMPILER_VERSION:version>``
+  ``1`` if the version of the OBJC compiler matches ``version``, otherwise ``0``.
+  See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+``$<OBJCXX_COMPILER_VERSION:version>``
+  ``1`` if the version of the OBJCXX compiler matches ``version``, otherwise ``0``.
+  See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
 ``$<Fortran_COMPILER_VERSION:version>``
   ``1`` if the version of the Fortran compiler matches ``version``, otherwise ``0``.
   See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
@@ -406,6 +417,12 @@ Variable Queries
 ``$<CUDA_COMPILER_ID>``
   The CMake's compiler id of the CUDA compiler used.
   See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+``$<OBJC_COMPILER_ID>``
+  The CMake's compiler id of the OBJC compiler used.
+  See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+``$<OBJCXX_COMPILER_ID>``
+  The CMake's compiler id of the OBJCXX compiler used.
+  See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
 ``$<Fortran_COMPILER_ID>``
   The CMake's compiler id of the Fortran compiler used.
   See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
@@ -421,6 +438,9 @@ Variable Queries
 ``$<OBJC_COMPILER_VERSION>``
   The version of the OBJC compiler used.
   See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+``$<OBJCXX_COMPILER_VERSION>``
+  The version of the OBJCXX compiler used.
+  See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
 ``$<Fortran_COMPILER_VERSION>``
   The version of the Fortran compiler used.
   See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index 78881e6..c60dc40 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -39,6 +39,9 @@ These modules are loaded using the :command:`include` command.
    /module/CheckOBJCCompilerFlag
    /module/CheckOBJCSourceCompiles
    /module/CheckOBJCSourceRuns
+   /module/CheckOBJCXXCompilerFlag
+   /module/CheckOBJCXXSourceCompiles
+   /module/CheckOBJCXXSourceRuns
    /module/CheckPIESupported
    /module/CheckPrototypeDefinition
    /module/CheckStructHasMember
diff --git a/Help/module/CheckOBJCXXCompilerFlag.rst b/Help/module/CheckOBJCXXCompilerFlag.rst
new file mode 100644
index 0000000..1518a48
--- /dev/null
+++ b/Help/module/CheckOBJCXXCompilerFlag.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCXXCompilerFlag.cmake
diff --git a/Help/module/CheckOBJCXXSourceCompiles.rst b/Help/module/CheckOBJCXXSourceCompiles.rst
new file mode 100644
index 0000000..a1c8ae9
--- /dev/null
+++ b/Help/module/CheckOBJCXXSourceCompiles.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCXXSourceCompiles.cmake
diff --git a/Help/module/CheckOBJCXXSourceRuns.rst b/Help/module/CheckOBJCXXSourceRuns.rst
new file mode 100644
index 0000000..5198e1b
--- /dev/null
+++ b/Help/module/CheckOBJCXXSourceRuns.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCXXSourceRuns.cmake
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index 6936cd4..ef65021 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -45,7 +45,7 @@ set(CMAKE_CXX_COMPILER_ID_RUN 1)
 set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP)
 set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
 
-foreach (lang OBJC)
+foreach (lang OBJC OBJCXX)
   if (CMAKE_${lang}_COMPILER_ID_RUN)
     foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
       list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
diff --git a/Modules/CMakeDetermineOBJCXXCompiler.cmake b/Modules/CMakeDetermineOBJCXXCompiler.cmake
new file mode 100644
index 0000000..60fcbb3
--- /dev/null
+++ b/Modules/CMakeDetermineOBJCXXCompiler.cmake
@@ -0,0 +1,197 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# determine the compiler to use for Objective-C++ programs
+# NOTE, a generator may set CMAKE_OBJCXX_COMPILER before
+# loading this file to force a compiler.
+# use environment variable OBJCXX first if defined by user, next use
+# the cmake variable CMAKE_GENERATOR_OBJCXX which can be defined by a generator
+# as a default compiler
+# If the internal cmake variable _CMAKE_TOOLCHAIN_PREFIX is set, this is used
+# as prefix for the tools (e.g. arm-elf-g++, arm-elf-ar etc.)
+#
+# Sets the following variables:
+#   CMAKE_OBJCXX_COMPILER
+#   CMAKE_COMPILER_IS_GNUOBJCXX
+#   CMAKE_COMPILER_IS_CLANGOBJCXX
+#   CMAKE_AR
+#   CMAKE_RANLIB
+#
+# If not already set before, it also sets
+#   _CMAKE_TOOLCHAIN_PREFIX
+
+include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
+
+# Load system-specific compiler preferences for this language.
+include(Platform/${CMAKE_SYSTEM_NAME}-Determine-OBJCXX OPTIONAL)
+include(Platform/${CMAKE_SYSTEM_NAME}-OBJCXX OPTIONAL)
+if(NOT CMAKE_OBJCXX_COMPILER_NAMES)
+  set(CMAKE_OBJCXX_COMPILER_NAMES clang++)
+endif()
+
+if("${CMAKE_GENERATOR}" MATCHES "Xcode")
+  set(CMAKE_OBJCXX_COMPILER_XCODE_TYPE sourcecode.cpp.objcpp)
+else()
+  if(NOT CMAKE_OBJCXX_COMPILER)
+    set(CMAKE_OBJCXX_COMPILER_INIT NOTFOUND)
+
+    # prefer the environment variable OBJCXX
+    if($ENV{OBJCXX} MATCHES ".+")
+      get_filename_component(CMAKE_OBJCXX_COMPILER_INIT $ENV{OBJCXX} PROGRAM PROGRAM_ARGS CMAKE_OBJCXX_FLAGS_ENV_INIT)
+      if(CMAKE_OBJCXX_FLAGS_ENV_INIT)
+        set(CMAKE_OBJCXX_COMPILER_ARG1 "${CMAKE_OBJCXX_FLAGS_ENV_INIT}" CACHE STRING "First argument to Objective-C++ compiler")
+      endif()
+      if(NOT EXISTS ${CMAKE_OBJCXX_COMPILER_INIT})
+        message(FATAL_ERROR "Could not find compiler set in environment variable OBJCXX:\n$ENV{OBJCXX}.\n${CMAKE_OBJCXX_COMPILER_INIT}")
+      endif()
+    endif()
+
+    # next prefer the generator specified compiler
+    if(CMAKE_GENERATOR_OBJCXX)
+      if(NOT CMAKE_OBJCXX_COMPILER_INIT)
+        set(CMAKE_OBJCXX_COMPILER_INIT ${CMAKE_GENERATOR_OBJCXX})
+      endif()
+    endif()
+
+    # finally list compilers to try
+    if(NOT CMAKE_OBJCXX_COMPILER_INIT)
+      set(CMAKE_OBJCXX_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}c++ ${_CMAKE_TOOLCHAIN_PREFIX}g++ clang++)
+    endif()
+
+    _cmake_find_compiler(OBJCXX)
+
+  else()
+    # we only get here if CMAKE_OBJCXX_COMPILER was specified using -D or a pre-made CMakeCache.txt
+    # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
+    # if CMAKE_OBJCXX_COMPILER is a list of length 2, use the first item as
+    # CMAKE_OBJCXX_COMPILER and the 2nd one as CMAKE_OBJCXX_COMPILER_ARG1
+
+    list(LENGTH CMAKE_OBJCXX_COMPILER _CMAKE_OBJCXX_COMPILER_LIST_LENGTH)
+    if("${_CMAKE_OBJCXX_COMPILER_LIST_LENGTH}" EQUAL 2)
+      list(GET CMAKE_OBJCXX_COMPILER 1 CMAKE_OBJCXX_COMPILER_ARG1)
+      list(GET CMAKE_OBJCXX_COMPILER 0 CMAKE_OBJCXX_COMPILER)
+    endif()
+
+    # if a compiler was specified by the user but without path,
+    # now try to find it with the full path
+    # if it is found, force it into the cache,
+    # if not, don't overwrite the setting (which was given by the user) with "NOTFOUND"
+    # if the C compiler already had a path, reuse it for searching the CXX compiler
+    get_filename_component(_CMAKE_USER_OBJCXX_COMPILER_PATH "${CMAKE_OBJCXX_COMPILER}" PATH)
+    if(NOT _CMAKE_USER_OBJCXX_COMPILER_PATH)
+      find_program(CMAKE_OBJCXX_COMPILER_WITH_PATH NAMES ${CMAKE_OBJCXX_COMPILER})
+      if(CMAKE_OBJCXX_COMPILER_WITH_PATH)
+        set(CMAKE_OBJCXX_COMPILER ${CMAKE_OBJCXX_COMPILER_WITH_PATH} CACHE STRING "Objective-C++ compiler" FORCE)
+      endif()
+      unset(CMAKE_OBJCXX_COMPILER_WITH_PATH CACHE)
+    endif()
+
+  endif()
+  mark_as_advanced(CMAKE_OBJCXX_COMPILER)
+
+  # Each entry in this list is a set of extra flags to try
+  # adding to the compile line to see if it helps produce
+  # a valid identification file.
+  set(CMAKE_OBJCXX_COMPILER_ID_TEST_FLAGS_FIRST)
+  set(CMAKE_OBJCXX_COMPILER_ID_TEST_FLAGS
+    # Try compiling to an object file only.
+    "-c"
+
+    # ARMClang need target options
+    "--target=arm-arm-none-eabi -mcpu=cortex-m3"
+    )
+endif()
+
+# Build a small source file to identify the compiler.
+if(NOT CMAKE_OBJCXX_COMPILER_ID_RUN)
+  set(CMAKE_OBJCXX_COMPILER_ID_RUN 1)
+
+  # Try to identify the compiler.
+  set(CMAKE_OBJCXX_COMPILER_ID)
+  file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
+    CMAKE_OBJCXX_COMPILER_ID_PLATFORM_CONTENT)
+
+  # Match the link line from xcodebuild output of the form
+  #  Ld ...
+  #      ...
+  #      /path/to/cc ...CompilerIdOBJCXX/...
+  # to extract the compiler front-end for the language.
+  set(CMAKE_OBJCXX_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdOBJCXX/(\\./)?(CompilerIdOBJCXX.(framework|xctest)/)?CompilerIdOBJCXX[ \t\n\\\"]")
+  set(CMAKE_OBJCXX_COMPILER_ID_TOOL_MATCH_INDEX 2)
+
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
+  CMAKE_DETERMINE_COMPILER_ID(OBJCXX OBJCXXFLAGS CMakeOBJCXXCompilerId.mm)
+
+  # Set old compiler and platform id variables.
+  if(CMAKE_OBJCXX_COMPILER_ID MATCHES "GNU")
+    set(CMAKE_COMPILER_IS_GNUOBJCXX 1)
+  endif()
+  if(CMAKE_OBJCXX_COMPILER_ID MATCHES "Clang")
+    set(CMAKE_COMPILER_IS_CLANGOBJCXX 1)
+  endif()
+endif()
+
+if (NOT _CMAKE_TOOLCHAIN_LOCATION)
+  get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_OBJCXX_COMPILER}" PATH)
+endif ()
+
+# if we have a g++ cross compiler, they have usually some prefix, like
+# e.g. powerpc-linux-g++, arm-elf-g++ or i586-mingw32msvc-g++ , optionally
+# with a 3-component version number at the end (e.g. arm-eabi-gcc-4.5.2).
+# The other tools of the toolchain usually have the same prefix
+# NAME_WE cannot be used since then this test will fail for names like
+# "arm-unknown-nto-qnx6.3.0-gcc.exe", where BASENAME would be
+# "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
+
+
+if (CMAKE_CROSSCOMPILING  AND NOT  _CMAKE_TOOLCHAIN_PREFIX)
+
+  if("${CMAKE_OBJCXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC")
+    get_filename_component(COMPILER_BASENAME "${CMAKE_OBJCXX_COMPILER}" NAME)
+    if (COMPILER_BASENAME MATCHES "^(.+-)(clan)?[gc]\\+\\+(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
+      set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+      set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
+    elseif("${CMAKE_OBJCXX_COMPILER_ID}" MATCHES "Clang")
+      if(CMAKE_OBJCXX_COMPILER_TARGET)
+        set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_OBJCXX_COMPILER_TARGET}-)
+      endif()
+    elseif(COMPILER_BASENAME MATCHES "QCC(\\.exe)?$")
+      if(CMAKE_OBJCXX_COMPILER_TARGET MATCHES "gcc_nto([a-z0-9]+_[0-9]+|[^_le]+)(le)")
+        set(_CMAKE_TOOLCHAIN_PREFIX nto${CMAKE_MATCH_1}-)
+      endif()
+    endif ()
+
+    # if "llvm-" is part of the prefix, remove it, since llvm doesn't have its own binutils
+    # but uses the regular ar, objcopy, etc. (instead of llvm-objcopy etc.)
+    if ("${_CMAKE_TOOLCHAIN_PREFIX}" MATCHES "(.+-)?llvm-$")
+      set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+    endif ()
+  endif()
+
+endif ()
+
+set(_CMAKE_PROCESSING_LANGUAGE "OBJCXX")
+include(CMakeFindBinUtils)
+include(Compiler/${CMAKE_OBJCXX_COMPILER_ID}-FindBinUtils OPTIONAL)
+unset(_CMAKE_PROCESSING_LANGUAGE)
+
+if(CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID)
+  set(_SET_CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID
+    "set(CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID ${CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID})")
+else()
+  set(_SET_CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID "")
+endif()
+
+if(CMAKE_OBJCXX_XCODE_ARCHS)
+  set(SET_CMAKE_XCODE_ARCHS
+    "set(CMAKE_XCODE_ARCHS \"${CMAKE_OBJCXX_XCODE_ARCHS}\")")
+endif()
+
+# configure all variables set in this file
+configure_file(${CMAKE_ROOT}/Modules/CMakeOBJCXXCompiler.cmake.in
+  ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCXXCompiler.cmake
+  @ONLY
+  )
+
+set(CMAKE_OBJCXX_COMPILER_ENV_VAR "OBJCXX")
diff --git a/Modules/CMakeOBJCXXCompiler.cmake.in b/Modules/CMakeOBJCXXCompiler.cmake.in
new file mode 100644
index 0000000..b6452c4
--- /dev/null
+++ b/Modules/CMakeOBJCXXCompiler.cmake.in
@@ -0,0 +1,79 @@
+set(CMAKE_OBJCXX_COMPILER "@CMAKE_OBJCXX_COMPILER@")
+set(CMAKE_OBJCXX_COMPILER_ARG1 "@CMAKE_OBJCXX_COMPILER_ARG1@")
+set(CMAKE_OBJCXX_COMPILER_ID "@CMAKE_OBJCXX_COMPILER_ID@")
+set(CMAKE_OBJCXX_COMPILER_VERSION "@CMAKE_OBJCXX_COMPILER_VERSION@")
+set(CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL "@CMAKE_OBJCXX_COMPILER_VERSION_INTERNAL@")
+set(CMAKE_OBJCXX_COMPILER_WRAPPER "@CMAKE_OBJCXX_COMPILER_WRAPPER@")
+set(CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJCXX_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_OBJCXX_COMPILE_FEATURES "@CMAKE_OBJCXX_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX98_COMPILE_FEATURES "@CMAKE_OBJCXX98_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX11_COMPILE_FEATURES "@CMAKE_OBJCXX11_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX14_COMPILE_FEATURES "@CMAKE_OBJCXX14_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX17_COMPILE_FEATURES "@CMAKE_OBJCXX17_COMPILE_FEATURES@")
+set(CMAKE_OBJCXX20_COMPILE_FEATURES "@CMAKE_OBJCXX20_COMPILE_FEATURES@")
+
+set(CMAKE_OBJCXX_PLATFORM_ID "@CMAKE_OBJCXX_PLATFORM_ID@")
+set(CMAKE_OBJCXX_SIMULATE_ID "@CMAKE_OBJCXX_SIMULATE_ID@")
+set(CMAKE_OBJCXX_COMPILER_FRONTEND_VARIANT "@CMAKE_OBJCXX_COMPILER_FRONTEND_VARIANT@")
+set(CMAKE_OBJCXX_SIMULATE_VERSION "@CMAKE_OBJCXX_SIMULATE_VERSION@")
+ at _SET_CMAKE_OBJCXX_COMPILER_ARCHITECTURE_ID@
+ at SET_CMAKE_XCODE_ARCHS@
+set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_OBJCXX_COMPILER_AR "@CMAKE_OBJCXX_COMPILER_AR@")
+set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_OBJCXX_COMPILER_RANLIB "@CMAKE_OBJCXX_COMPILER_RANLIB@")
+set(CMAKE_LINKER "@CMAKE_LINKER@")
+set(CMAKE_MT "@CMAKE_MT@")
+set(CMAKE_COMPILER_IS_GNUOBJCXX @CMAKE_COMPILER_IS_GNUOBJCXX@)
+set(CMAKE_OBJCXX_COMPILER_LOADED 1)
+set(CMAKE_OBJCXX_COMPILER_WORKS @CMAKE_OBJCXX_COMPILER_WORKS@)
+set(CMAKE_OBJCXX_ABI_COMPILED @CMAKE_OBJCXX_ABI_COMPILED@)
+
+set(CMAKE_OBJCXX_COMPILER_ENV_VAR "OBJCXX")
+
+set(CMAKE_OBJCXX_COMPILER_ID_RUN 1)
+set(CMAKE_OBJCXX_SOURCE_FILE_EXTENSIONS M;m;mm)
+set(CMAKE_OBJCXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O)
+
+if (CMAKE_OBJC_COMPILER_ID_RUN)
+  foreach(extension IN LISTS CMAKE_OBJC_SOURCE_FILE_EXTENSIONS)
+    list(REMOVE_ITEM CMAKE_OBJCXX_SOURCE_FILE_EXTENSIONS ${extension})
+  endforeach()
+endif()
+
+foreach (lang C CXX OBJC)
+  foreach(extension IN LISTS CMAKE_OBJCXX_SOURCE_FILE_EXTENSIONS)
+    if (CMAKE_${lang}_COMPILER_ID_RUN)
+      list(REMOVE_ITEM CMAKE_${lang}_SOURCE_FILE_EXTENSIONS ${extension})
+    endif()
+  endforeach()
+endforeach()
+
+set(CMAKE_OBJCXX_LINKER_PREFERENCE 25)
+set(CMAKE_OBJCXX_LINKER_PREFERENCE_PROPAGATES 1)
+
+# Save compiler ABI information.
+set(CMAKE_OBJCXX_SIZEOF_DATA_PTR "@CMAKE_OBJCXX_SIZEOF_DATA_PTR@")
+set(CMAKE_OBJCXX_COMPILER_ABI "@CMAKE_OBJCXX_COMPILER_ABI@")
+set(CMAKE_OBJCXX_LIBRARY_ARCHITECTURE "@CMAKE_OBJCXX_LIBRARY_ARCHITECTURE@")
+
+if(CMAKE_OBJCXX_SIZEOF_DATA_PTR)
+  set(CMAKE_SIZEOF_VOID_P "${CMAKE_OBJCXX_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_OBJCXX_COMPILER_ABI)
+  set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_OBJCXX_COMPILER_ABI}")
+endif()
+
+if(CMAKE_OBJCXX_LIBRARY_ARCHITECTURE)
+  set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_OBJCXX_LIBRARY_ARCHITECTURE@")
+endif()
+
+ at CMAKE_OBJCXX_COMPILER_CUSTOM_CODE@
+ at CMAKE_OBJCXX_SYSROOT_FLAG_CODE@
+ at CMAKE_OBJCXX_OSX_DEPLOYMENT_TARGET_FLAG_CODE@
+
+set(CMAKE_OBJCXX_IMPLICIT_INCLUDE_DIRECTORIES "@CMAKE_OBJCXX_IMPLICIT_INCLUDE_DIRECTORIES@")
+set(CMAKE_OBJCXX_IMPLICIT_LINK_LIBRARIES "@CMAKE_OBJCXX_IMPLICIT_LINK_LIBRARIES@")
+set(CMAKE_OBJCXX_IMPLICIT_LINK_DIRECTORIES "@CMAKE_OBJCXX_IMPLICIT_LINK_DIRECTORIES@")
+set(CMAKE_OBJCXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_OBJCXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")
diff --git a/Modules/CMakeOBJCXXCompilerABI.mm b/Modules/CMakeOBJCXXCompilerABI.mm
new file mode 100644
index 0000000..288a58c
--- /dev/null
+++ b/Modules/CMakeOBJCXXCompilerABI.mm
@@ -0,0 +1,20 @@
+#ifndef __cplusplus
+# error "A C compiler has been selected for Objective-C++."
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#include "CMakeCompilerABI.h"
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  int require = 0;
+  require += info_sizeof_dptr[argc];
+#if defined(ABI_ID)
+  require += info_abi[argc];
+#endif
+  (void)argv;
+  return require;
+}
diff --git a/Modules/CMakeOBJCXXCompilerId.mm.in b/Modules/CMakeOBJCXXCompilerId.mm.in
new file mode 100644
index 0000000..fe04de1
--- /dev/null
+++ b/Modules/CMakeOBJCXXCompilerId.mm.in
@@ -0,0 +1,68 @@
+/* This source file must have a .cpp extension so that all C++ compilers
+   recognize the extension without flags.  Borland does not know .cxx for
+   example.  */
+#ifndef __cplusplus
+# error "An Objective-C compiler has been selected for Objective-C++."
+#endif
+
+ at CMAKE_OBJCXX_COMPILER_ID_CONTENT@
+
+/* Construct the string literal in pieces to prevent the source from
+   getting matched.  Store it in a pointer rather than an array
+   because some compilers will just produce instructions to fill the
+   array rather than assigning a pointer to a static array.  */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+ at CMAKE_OBJCXX_COMPILER_ID_PLATFORM_CONTENT@
+ at CMAKE_OBJCXX_COMPILER_ID_ERROR_FOR_TEST@
+
+#if defined(_MSC_VER) && defined(_MSVC_LANG)
+#define CXX_STD _MSVC_LANG
+#else
+#define CXX_STD __cplusplus
+#endif
+
+const char* info_language_dialect_default = "INFO" ":" "dialect_default["
+#if CXX_STD > 201703L
+  "20"
+#elif CXX_STD >= 201703L
+  "17"
+#elif CXX_STD >= 201402L
+  "14"
+#elif CXX_STD >= 201103L
+  "11"
+#else
+  "98"
+#endif
+"]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+  int require = 0;
+  require += info_compiler[argc];
+  require += info_platform[argc];
+#ifdef COMPILER_VERSION_MAJOR
+  require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+  require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+  require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+  require += info_simulate_version[argc];
+#endif
+  require += info_language_dialect_default[argc];
+  (void)argv;
+  return require;
+}
diff --git a/Modules/CMakeOBJCXXInformation.cmake b/Modules/CMakeOBJCXXInformation.cmake
new file mode 100644
index 0000000..3f55b01
--- /dev/null
+++ b/Modules/CMakeOBJCXXInformation.cmake
@@ -0,0 +1,273 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# This file sets the basic flags for the Objective-C++ language in CMake.
+# It also loads the available platform file for the system-compiler
+# if it exists.
+# It also loads a system - compiler - processor (or target hardware)
+# specific file, which is mainly useful for crosscompiling and embedded systems.
+
+include(CMakeLanguageInformation)
+
+# some compilers use different extensions (e.g. sdcc uses .rel)
+# so set the extension here first so it can be overridden by the compiler specific file
+set(CMAKE_OBJCXX_OUTPUT_EXTENSION .o)
+
+set(_INCLUDED_FILE 0)
+
+# Load compiler-specific information.
+if(CMAKE_OBJCXX_COMPILER_ID)
+  include(Compiler/${CMAKE_OBJCXX_COMPILER_ID}-OBJCXX OPTIONAL)
+endif()
+
+set(CMAKE_BASE_NAME)
+get_filename_component(CMAKE_BASE_NAME "${CMAKE_OBJCXX_COMPILER}" NAME_WE)
+# since the gnu compiler has several names force g++
+if(CMAKE_COMPILER_IS_GNUOBJCXX)
+  set(CMAKE_BASE_NAME g++)
+endif()
+
+
+# load a hardware specific file, mostly useful for embedded compilers
+if(CMAKE_SYSTEM_PROCESSOR)
+  if(CMAKE_OBJCXX_COMPILER_ID)
+    include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJCXX_COMPILER_ID}-OBJCXX-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+  endif()
+  if (NOT _INCLUDED_FILE)
+    include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+  endif ()
+endif()
+
+# load the system- and compiler specific files
+if(CMAKE_OBJCXX_COMPILER_ID)
+  include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJCXX_COMPILER_ID}-OBJCXX OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+endif()
+if (NOT _INCLUDED_FILE)
+  include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME} OPTIONAL
+          RESULT_VARIABLE _INCLUDED_FILE)
+endif ()
+
+# load any compiler-wrapper specific information
+if (CMAKE_OBJCXX_COMPILER_WRAPPER)
+  __cmake_include_compiler_wrapper(OBJCXX)
+endif ()
+
+# We specify the compiler information in the system file for some
+# platforms, but this language may not have been enabled when the file
+# was first included.  Include it again to get the language info.
+# Remove this when all compiler info is removed from system files.
+if (NOT _INCLUDED_FILE)
+  include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL)
+endif ()
+
+if(CMAKE_OBJCXX_SIZEOF_DATA_PTR)
+  foreach(f ${CMAKE_OBJCXX_ABI_FILES})
+    include(${f})
+  endforeach()
+  unset(CMAKE_OBJCXX_ABI_FILES)
+endif()
+
+# This should be included before the _INIT variables are
+# used to initialize the cache.  Since the rule variables
+# have if blocks on them, users can still define them here.
+# But, it should still be after the platform file so changes can
+# be made to those values.
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE)
+  # Save the full path of the file so try_compile can use it.
+  include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override)
+  set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}")
+endif()
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJCXX)
+  # Save the full path of the file so try_compile can use it.
+  include(${CMAKE_USER_MAKE_RULES_OVERRIDE_OBJCXX} RESULT_VARIABLE _override)
+  set(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJCXX "${_override}")
+endif()
+
+
+# Create a set of shared library variable specific to Objective-C++
+# For 90% of the systems, these are the same flags as the Objective-C versions
+# so if these are not set just copy the flags from the Objective-C version
+if(NOT CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS)
+  set(CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS})
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILE_OPTIONS_PIC)
+  set(CMAKE_OBJCXX_COMPILE_OPTIONS_PIC ${CMAKE_OBJC_COMPILE_OPTIONS_PIC})
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILE_OPTIONS_PIE)
+  set(CMAKE_OBJCXX_COMPILE_OPTIONS_PIE ${CMAKE_OBJC_COMPILE_OPTIONS_PIE})
+endif()
+if(NOT CMAKE_OBJCXX_LINK_OPTIONS_PIE)
+  set(CMAKE_OBJCXX_LINK_OPTIONS_PIE ${CMAKE_OBJC_LINK_OPTIONS_PIE})
+endif()
+if(NOT CMAKE_OBJCXX_LINK_OPTIONS_NO_PIE)
+  set(CMAKE_OBJCXX_LINK_OPTIONS_NO_PIE ${CMAKE_OBJC_LINK_OPTIONS_NO_PIE})
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILE_OPTIONS_DLL)
+  set(CMAKE_OBJCXX_COMPILE_OPTIONS_DLL ${CMAKE_OBJC_COMPILE_OPTIONS_DLL})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS)
+  set(CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_OBJC_FLAGS})
+endif()
+
+if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_OBJCXX_FLAGS)
+  set(CMAKE_SHARED_LIBRARY_LINK_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_LINK_OBJC_FLAGS})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG)
+  set(CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG_SEP)
+  set(CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG_SEP})
+endif()
+
+if(NOT CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJCXX_FLAG)
+  set(CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJC_FLAG})
+endif()
+
+if(NOT DEFINED CMAKE_EXE_EXPORTS_OBJCXX_FLAG)
+  set(CMAKE_EXE_EXPORTS_OBJCXX_FLAG ${CMAKE_EXE_EXPORTS_OBJC_FLAG})
+endif()
+
+if(NOT DEFINED CMAKE_SHARED_LIBRARY_SONAME_OBJCXX_FLAG)
+  set(CMAKE_SHARED_LIBRARY_SONAME_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_SONAME_OBJC_FLAG})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG)
+  set(CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG_SEP)
+  set(CMAKE_EXECUTABLE_RUNTIME_OBJCXX_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJCXX_FLAG_SEP})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RPATH_LINK_OBJCXX_FLAG)
+  set(CMAKE_EXECUTABLE_RPATH_LINK_OBJCXX_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJCXX_FLAG})
+endif()
+
+if(NOT DEFINED CMAKE_SHARED_LIBRARY_LINK_OBJCXX_WITH_RUNTIME_PATH)
+  set(CMAKE_SHARED_LIBRARY_LINK_OBJCXX_WITH_RUNTIME_PATH ${CMAKE_SHARED_LIBRARY_LINK_OBJC_WITH_RUNTIME_PATH})
+endif()
+
+if(NOT CMAKE_INCLUDE_FLAG_OBJCXX)
+  set(CMAKE_INCLUDE_FLAG_OBJCXX ${CMAKE_INCLUDE_FLAG_C})
+endif()
+
+# for most systems a module is the same as a shared library
+# so unless the variable CMAKE_MODULE_EXISTS is set just
+# copy the values from the LIBRARY variables
+if(NOT CMAKE_MODULE_EXISTS)
+  set(CMAKE_SHARED_MODULE_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS})
+  set(CMAKE_SHARED_MODULE_CREATE_OBJCXX_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS})
+endif()
+
+# repeat for modules
+if(NOT CMAKE_SHARED_MODULE_CREATE_OBJCXX_FLAGS)
+  set(CMAKE_SHARED_MODULE_CREATE_OBJCXX_FLAGS ${CMAKE_SHARED_MODULE_CREATE_OBJC_FLAGS})
+endif()
+
+if(NOT CMAKE_SHARED_MODULE_OBJCXX_FLAGS)
+  set(CMAKE_SHARED_MODULE_OBJCXX_FLAGS ${CMAKE_SHARED_MODULE_OBJC_FLAGS})
+endif()
+
+# Initialize OBJCXX link type selection flags from OBJC versions.
+foreach(type SHARED_LIBRARY SHARED_MODULE EXE)
+  if(NOT CMAKE_${type}_LINK_STATIC_OBJCXX_FLAGS)
+    set(CMAKE_${type}_LINK_STATIC_OBJCXX_FLAGS
+      ${CMAKE_${type}_LINK_STATIC_OBJC_FLAGS})
+  endif()
+  if(NOT CMAKE_${type}_LINK_DYNAMIC_OBJCXX_FLAGS)
+    set(CMAKE_${type}_LINK_DYNAMIC_OBJCXX_FLAGS
+      ${CMAKE_${type}_LINK_DYNAMIC_OBJC_FLAGS})
+  endif()
+endforeach()
+
+# add the flags to the cache based
+# on the initial values computed in the platform/*.cmake files
+# use _INIT variables so that this only happens the first time
+# and you can set these flags in the cmake cache
+set(CMAKE_OBJCXX_FLAGS_INIT "$ENV{OBJCXXFLAGS} ${CMAKE_OBJCXX_FLAGS_INIT}")
+
+cmake_initialize_per_config_variable(CMAKE_OBJCXX_FLAGS "Flags used by the Objective-C++ compiler")
+
+if(CMAKE_OBJCXX_STANDARD_LIBRARIES_INIT)
+  set(CMAKE_OBJCXX_STANDARD_LIBRARIES "${CMAKE_OBJCXX_STANDARD_LIBRARIES_INIT}"
+    CACHE STRING "Libraries linked by default with all Objective-C++ applications.")
+  mark_as_advanced(CMAKE_OBJCXX_STANDARD_LIBRARIES)
+endif()
+
+include(CMakeCommonLanguageInclude)
+
+# now define the following rules:
+# CMAKE_OBJCXX_CREATE_SHARED_LIBRARY
+# CMAKE_OBJCXX_CREATE_SHARED_MODULE
+# CMAKE_OBJCXX_COMPILE_OBJECT
+# CMAKE_OBJCXX_LINK_EXECUTABLE
+
+# variables supplied by the generator at use time
+# <TARGET>
+# <TARGET_BASE> the target without the suffix
+# <OBJECTS>
+# <OBJECT>
+# <LINK_LIBRARIES>
+# <FLAGS>
+# <LINK_FLAGS>
+
+# Objective-C++ compiler information
+# <CMAKE_OBJCXX_COMPILER>
+# <CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS>
+# <CMAKE_OBJCXX_SHARED_MODULE_CREATE_FLAGS>
+# <CMAKE_OBJCXX_LINK_FLAGS>
+
+# Static library tools
+# <CMAKE_AR>
+# <CMAKE_RANLIB>
+
+
+# create a shared Objective-C++ library
+if(NOT CMAKE_OBJCXX_CREATE_SHARED_LIBRARY)
+  set(CMAKE_OBJCXX_CREATE_SHARED_LIBRARY
+      "<CMAKE_OBJCXX_COMPILER> <CMAKE_SHARED_LIBRARY_OBJCXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
+endif()
+
+# create an Objective-C++ shared module copy the shared library rule by default
+if(NOT CMAKE_OBJCXX_CREATE_SHARED_MODULE)
+  set(CMAKE_OBJCXX_CREATE_SHARED_MODULE ${CMAKE_OBJCXX_CREATE_SHARED_LIBRARY})
+endif()
+
+
+# Create a static archive incrementally for large object file counts.
+# If CMAKE_OBJCXX_CREATE_STATIC_LIBRARY is set it will override these.
+if(NOT DEFINED CMAKE_OBJCXX_ARCHIVE_CREATE)
+  set(CMAKE_OBJCXX_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_OBJCXX_ARCHIVE_APPEND)
+  set(CMAKE_OBJCXX_ARCHIVE_APPEND "<CMAKE_AR> q  <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_OBJCXX_ARCHIVE_FINISH)
+  set(CMAKE_OBJCXX_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
+endif()
+
+# compile an Objective-C++ file into an object file
+if(NOT CMAKE_OBJCXX_COMPILE_OBJECT)
+  set(CMAKE_OBJCXX_COMPILE_OBJECT
+    "<CMAKE_OBJCXX_COMPILER>  <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
+endif()
+
+if(NOT CMAKE_OBJCXX_LINK_EXECUTABLE)
+  set(CMAKE_OBJCXX_LINK_EXECUTABLE
+    "<CMAKE_OBJCXX_COMPILER>  <FLAGS> <CMAKE_OBJCXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET> <LINK_LIBRARIES>")
+endif()
+
+mark_as_advanced(
+CMAKE_VERBOSE_MAKEFILE
+)
+
+set(CMAKE_OBJCXX_INFORMATION_LOADED 1)
diff --git a/Modules/CMakeTestOBJCXXCompiler.cmake b/Modules/CMakeTestOBJCXXCompiler.cmake
new file mode 100644
index 0000000..bcce2f1
--- /dev/null
+++ b/Modules/CMakeTestOBJCXXCompiler.cmake
@@ -0,0 +1,93 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+if(CMAKE_OBJCXX_COMPILER_FORCED)
+  # The compiler configuration was forced by the user.
+  # Assume the user has configured all compiler information.
+  set(CMAKE_OBJCXX_COMPILER_WORKS TRUE)
+  return()
+endif()
+
+include(CMakeTestCompilerCommon)
+
+# work around enforced code signing and / or missing exectuable target type
+set(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
+if(_CMAKE_FEATURE_DETECTION_TARGET_TYPE)
+  set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_CMAKE_FEATURE_DETECTION_TARGET_TYPE})
+endif()
+
+# Remove any cached result from an older CMake version.
+# We now store this in CMakeOBJCXXCompiler.cmake.
+unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE)
+
+# This file is used by EnableLanguage in cmGlobalGenerator to
+# determine that the selected Objective-C++ compiler can actually compile
+# and link the most basic of programs.   If not, a fatal error
+# is set and cmake stops processing commands and will not generate
+# any makefiles or projects.
+if(NOT CMAKE_OBJCXX_COMPILER_WORKS)
+  PrintTestCompilerStatus("OBJCXX" "")
+  __TestCompiler_setTryCompileTargetType()
+  file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm
+    "#ifndef __cplusplus\n"
+    "# error \"The CMAKE_OBJCXX_COMPILER is set to a C compiler\"\n"
+    "#endif\n"
+    "#ifndef __OBJC__\n"
+    "# error \"The CMAKE_OBJCXX_COMPILER is not an Objective-C++ compiler\"\n"
+    "#endif\n"
+    "int main(){return 0;}\n")
+  try_compile(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_BINARY_DIR}
+    ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCXXCompiler.mm
+    OUTPUT_VARIABLE __CMAKE_OBJCXX_COMPILER_OUTPUT)
+  # Move result from cache to normal variable.
+  set(CMAKE_OBJCXX_COMPILER_WORKS ${CMAKE_OBJCXX_COMPILER_WORKS})
+  unset(CMAKE_OBJCXX_COMPILER_WORKS CACHE)
+  set(OBJCXX_TEST_WAS_RUN 1)
+  __TestCompiler_restoreTryCompileTargetType()
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILER_WORKS)
+  PrintTestCompilerStatus("OBJCXX" " -- broken")
+  file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+    "Determining if the Objective-C++ compiler works failed with "
+    "the following output:\n${__CMAKE_OBJCXX_COMPILER_OUTPUT}\n\n")
+  string(REPLACE "\n" "\n  " _output "${__CMAKE_OBJCXX_COMPILER_OUTPUT}")
+  message(FATAL_ERROR "The Objective-C++ compiler\n  \"${CMAKE_OBJCXX_COMPILER}\"\n"
+    "is not able to compile a simple test program.\nIt fails "
+    "with the following output:\n  ${_output}\n\n"
+    "CMake will not be able to correctly generate this project.")
+else()
+  if(OBJCXX_TEST_WAS_RUN)
+    PrintTestCompilerStatus("OBJCXX" " -- works")
+    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+      "Determining if the Objective-C++ compiler works passed with "
+      "the following output:\n${__CMAKE_OBJCXX_COMPILER_OUTPUT}\n\n")
+  endif()
+
+  # Try to identify the ABI and configure it into CMakeOBJCXXCompiler.cmake
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
+  CMAKE_DETERMINE_COMPILER_ABI(OBJCXX ${CMAKE_ROOT}/Modules/CMakeOBJCXXCompilerABI.mm)
+  # Try to identify the compiler features
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
+  CMAKE_DETERMINE_COMPILE_FEATURES(OBJCXX)
+
+  # Re-configure to save learned information.
+  configure_file(
+    ${CMAKE_ROOT}/Modules/CMakeOBJCXXCompiler.cmake.in
+    ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCXXCompiler.cmake
+    @ONLY
+    )
+  include(${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCXXCompiler.cmake)
+
+  if(CMAKE_OBJCXX_SIZEOF_DATA_PTR)
+    foreach(f ${CMAKE_OBJCXX_ABI_FILES})
+      include(${f})
+    endforeach()
+    unset(CMAKE_OBJCXX_ABI_FILES)
+  endif()
+endif()
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE})
+unset(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE)
+unset(__CMAKE_OBJCXX_COMPILER_OUTPUT)
diff --git a/Modules/CheckOBJCXXCompilerFlag.cmake b/Modules/CheckOBJCXXCompilerFlag.cmake
new file mode 100644
index 0000000..c32741b
--- /dev/null
+++ b/Modules/CheckOBJCXXCompilerFlag.cmake
@@ -0,0 +1,64 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCXXCompilerFlag
+-----------------------
+
+Check whether the Objective-C++ compiler supports a given flag.
+
+.. command:: check_objcxx_compiler_flag
+
+  .. code-block:: cmake
+
+    check_objcxx_compiler_flag(<flag> <var>)
+
+  Check that the ``<flag>`` is accepted by the compiler without
+  a diagnostic.  Stores the result in an internal cache entry
+  named ``<var>``.
+
+This command temporarily sets the ``CMAKE_REQUIRED_DEFINITIONS`` variable
+and calls the ``check_objcxx_source_compiles`` macro from the
+:module:`CheckOBJCXXSourceCompiles` module.  See documentation of that
+module for a listing of variables that can otherwise modify the build.
+
+A positive result from this check indicates only that the compiler did not
+issue a diagnostic message when given the flag.  Whether the flag has any
+effect or even a specific one is beyond the scope of this module.
+
+.. note::
+  Since the :command:`try_compile` command forwards flags from variables
+  like :variable:`CMAKE_OBJCXX_FLAGS <CMAKE_<LANG>_FLAGS>`, unknown flags
+  in such variables may cause a false negative for this check.
+#]=======================================================================]
+
+include_guard(GLOBAL)
+include(CheckOBJCXXSourceCompiles)
+include(CMakeCheckCompilerFlagCommonPatterns)
+
+macro (CHECK_OBJCXX_COMPILER_FLAG _FLAG _RESULT)
+  set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
+  set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
+
+  # Normalize locale during test compilation.
+  set(_CheckOBJCXXCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
+  foreach(v ${_CheckOBJCXXCompilerFlag_LOCALE_VARS})
+    set(_CheckOBJCXXCompilerFlag_SAVED_${v} "$ENV{${v}}")
+    set(ENV{${v}} OBJCXX)
+  endforeach()
+  CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckOBJCXXCompilerFlag_COMMON_PATTERNS)
+  CHECK_OBJCXX_SOURCE_COMPILES("#ifndef __OBJC__\n#  error \"Not an Objective-C++ compiler\"\n#endif\nint main(void) { return 0; }" ${_RESULT}
+    # Some compilers do not fail with a bad flag
+    FAIL_REGEX "command line option .* is valid for .* but not for Objective-C\\\\+\\\\+" # GNU
+    FAIL_REGEX "argument unused during compilation: .*" # Clang
+    ${_CheckOBJCXXCompilerFlag_COMMON_PATTERNS}
+    )
+  foreach(v ${_CheckOBJCXXCompilerFlag_LOCALE_VARS})
+    set(ENV{${v}} ${_CheckOBJCXXCompilerFlag_SAVED_${v}})
+    unset(_CheckOBJCXXCompilerFlag_SAVED_${v})
+  endforeach()
+  unset(_CheckOBJCXXCompilerFlag_LOCALE_VARS)
+  unset(_CheckOBJCXXCompilerFlag_COMMON_PATTERNS)
+
+  set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
+endmacro ()
diff --git a/Modules/CheckOBJCXXSourceCompiles.cmake b/Modules/CheckOBJCXXSourceCompiles.cmake
new file mode 100644
index 0000000..4c0fdd0
--- /dev/null
+++ b/Modules/CheckOBJCXXSourceCompiles.cmake
@@ -0,0 +1,146 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCXXSourceCompiles
+-------------------------
+
+Check if given Objective-C++ source compiles and links into an executable.
+
+.. command:: check_objcxx_source_compiles
+
+  .. code-block:: cmake
+
+    check_objcxx_source_compiles(<code> <resultVar>
+                                 [FAIL_REGEX <regex1> [<regex2>...]])
+
+  Check that the source supplied in ``<code>`` can be compiled as a Objective-C++ source
+  file and linked as an executable (so it must contain at least a ``main()``
+  function). The result will be stored in the internal cache variable specified
+  by ``<resultVar>``, with a boolean true value for success and boolean false
+  for failure. If ``FAIL_REGEX`` is provided, then failure is determined by
+  checking if anything in the output matches any of the specified regular
+  expressions.
+
+  The underlying check is performed by the :command:`try_compile` command. The
+  compile and link commands can be influenced by setting any of the following
+  variables prior to calling ``check_objcxx_source_compiles()``:
+
+  ``CMAKE_REQUIRED_FLAGS``
+    Additional flags to pass to the compiler. Note that the contents of
+    :variable:`CMAKE_OBJCXX_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
+    configuration-specific variable are automatically added to the compiler
+    command before the contents of ``CMAKE_REQUIRED_FLAGS``.
+
+  ``CMAKE_REQUIRED_DEFINITIONS``
+    A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
+    ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
+    ``<resultVar>`` will also be added automatically.
+
+  ``CMAKE_REQUIRED_INCLUDES``
+    A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
+    the compiler. These will be the only header search paths used by
+    ``try_compile()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
+    directory property will be ignored.
+
+  ``CMAKE_REQUIRED_LINK_OPTIONS``
+    A :ref:`;-list <CMake Language Lists>` of options to add to the link
+    command (see :command:`try_compile` for further details).
+
+  ``CMAKE_REQUIRED_LIBRARIES``
+    A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
+    command. These can be the name of system libraries or they can be
+    :ref:`Imported Targets <Imported Targets>` (see :command:`try_compile` for
+    further details).
+
+  ``CMAKE_REQUIRED_QUIET``
+    If this variable evaluates to a boolean true value, all status messages
+    associated with the check will be suppressed.
+
+  The check is only performed once, with the result cached in the variable
+  named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
+  value rather than performing the check again, even if the ``<code>`` changes.
+  In order to force the check to be re-evaluated, the variable named by
+  ``<resultVar>`` must be manually removed from the cache.
+
+#]=======================================================================]
+
+include_guard(GLOBAL)
+
+macro(CHECK_OBJCXX_SOURCE_COMPILES SOURCE VAR)
+  if(NOT DEFINED "${VAR}")
+    set(_FAIL_REGEX)
+    set(_key)
+    foreach(arg ${ARGN})
+      if("${arg}" MATCHES "^(FAIL_REGEX)$")
+        set(_key "${arg}")
+      elseif(_key)
+        list(APPEND _${_key} "${arg}")
+      else()
+        message(FATAL_ERROR "Unknown argument:\n  ${arg}\n")
+      endif()
+    endforeach()
+
+    set(MACRO_CHECK_FUNCTION_DEFINITIONS
+      "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+    if(CMAKE_REQUIRED_LINK_OPTIONS)
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS
+        LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
+    else()
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS)
+    endif()
+    if(CMAKE_REQUIRED_LIBRARIES)
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES
+        LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+    else()
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES)
+    endif()
+    if(CMAKE_REQUIRED_INCLUDES)
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES
+        "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+    else()
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES)
+    endif()
+    file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm"
+      "${SOURCE}\n")
+
+    if(NOT CMAKE_REQUIRED_QUIET)
+      message(STATUS "Performing Test ${VAR}")
+    endif()
+    try_compile(${VAR}
+      ${CMAKE_BINARY_DIR}
+      ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm
+      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+      ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS}
+      ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES}
+      CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
+      "${CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES}"
+      OUTPUT_VARIABLE OUTPUT)
+
+    foreach(_regex ${_FAIL_REGEX})
+      if("${OUTPUT}" MATCHES "${_regex}")
+        set(${VAR} 0)
+      endif()
+    endforeach()
+
+    if(${VAR})
+      set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+      if(NOT CMAKE_REQUIRED_QUIET)
+        message(STATUS "Performing Test ${VAR} - Success")
+      endif()
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+        "Performing Objective-C++ SOURCE FILE Test ${VAR} succeeded with the following output:\n"
+        "${OUTPUT}\n"
+        "Source file was:\n${SOURCE}\n")
+    else()
+      if(NOT CMAKE_REQUIRED_QUIET)
+        message(STATUS "Performing Test ${VAR} - Failed")
+      endif()
+      set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+        "Performing Objective-C++ SOURCE FILE Test ${VAR} failed with the following output:\n"
+        "${OUTPUT}\n"
+        "Source file was:\n${SOURCE}\n")
+    endif()
+  endif()
+endmacro()
diff --git a/Modules/CheckOBJCXXSourceRuns.cmake b/Modules/CheckOBJCXXSourceRuns.cmake
new file mode 100644
index 0000000..a3d5923
--- /dev/null
+++ b/Modules/CheckOBJCXXSourceRuns.cmake
@@ -0,0 +1,145 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCXXSourceRuns
+---------------------
+
+Check if given Objective-C++ source compiles and links into an executable and can
+subsequently be run.
+
+.. command:: check_objcxx_source_runs
+
+  .. code-block:: cmake
+
+    check_objcxx_source_runs(<code> <resultVar>)
+
+  Check that the source supplied in ``<code>`` can be compiled as a Objective-C++ source
+  file, linked as an executable and then run. The ``<code>`` must contain at
+  least a ``main()`` function. If the ``<code>`` could be built and run
+  successfully, the internal cache variable specified by ``<resultVar>`` will
+  be set to 1, otherwise it will be set to an value that evaluates to boolean
+  false (e.g. an empty string or an error message).
+
+  The underlying check is performed by the :command:`try_run` command. The
+  compile and link commands can be influenced by setting any of the following
+  variables prior to calling ``check_objcxx_source_runs()``:
+
+  ``CMAKE_REQUIRED_FLAGS``
+    Additional flags to pass to the compiler. Note that the contents of
+    :variable:`CMAKE_OBJCXX_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
+    configuration-specific variable are automatically added to the compiler
+    command before the contents of ``CMAKE_REQUIRED_FLAGS``.
+
+  ``CMAKE_REQUIRED_DEFINITIONS``
+    A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
+    ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
+    ``<resultVar>`` will also be added automatically.
+
+  ``CMAKE_REQUIRED_INCLUDES``
+    A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
+    the compiler. These will be the only header search paths used by
+    ``try_run()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
+    directory property will be ignored.
+
+  ``CMAKE_REQUIRED_LINK_OPTIONS``
+    A :ref:`;-list <CMake Language Lists>` of options to add to the link
+    command (see :command:`try_run` for further details).
+
+  ``CMAKE_REQUIRED_LIBRARIES``
+    A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
+    command. These can be the name of system libraries or they can be
+    :ref:`Imported Targets <Imported Targets>` (see :command:`try_run` for
+    further details).
+
+  ``CMAKE_REQUIRED_QUIET``
+    If this variable evaluates to a boolean true value, all status messages
+    associated with the check will be suppressed.
+
+  The check is only performed once, with the result cached in the variable
+  named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
+  value rather than performing the check again, even if the ``<code>`` changes.
+  In order to force the check to be re-evaluated, the variable named by
+  ``<resultVar>`` must be manually removed from the cache.
+
+#]=======================================================================]
+
+include_guard(GLOBAL)
+
+macro(CHECK_OBJCXX_SOURCE_RUNS SOURCE VAR)
+  if(NOT DEFINED "${VAR}")
+    set(MACRO_CHECK_FUNCTION_DEFINITIONS
+      "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+    if(CMAKE_REQUIRED_LINK_OPTIONS)
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS
+        LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
+    else()
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS)
+    endif()
+    if(CMAKE_REQUIRED_LIBRARIES)
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES
+        LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+    else()
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES)
+    endif()
+    if(CMAKE_REQUIRED_INCLUDES)
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES
+        "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+    else()
+      set(CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES)
+    endif()
+    file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm"
+      "${SOURCE}\n")
+
+    if(NOT CMAKE_REQUIRED_QUIET)
+      message(STATUS "Performing Test ${VAR}")
+    endif()
+    try_run(${VAR}_EXITCODE ${VAR}_COMPILED
+      ${CMAKE_BINARY_DIR}
+      ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.mm
+      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+      ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LINK_OPTIONS}
+      ${CHECK_OBJCXX_SOURCE_COMPILES_ADD_LIBRARIES}
+      CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
+      -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
+      "${CHECK_OBJCXX_SOURCE_COMPILES_ADD_INCLUDES}"
+      COMPILE_OUTPUT_VARIABLE OUTPUT
+      RUN_OUTPUT_VARIABLE RUN_OUTPUT)
+
+    # if it did not compile make the return value fail code of 1
+    if(NOT ${VAR}_COMPILED)
+      set(${VAR}_EXITCODE 1)
+    endif()
+    # if the return value was 0 then it worked
+    if("${${VAR}_EXITCODE}" EQUAL 0)
+      set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+      if(NOT CMAKE_REQUIRED_QUIET)
+        message(STATUS "Performing Test ${VAR} - Success")
+      endif()
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+        "Performing Objective-C++ SOURCE FILE Test ${VAR} succeeded with the following output:\n"
+        "${OUTPUT}\n"
+        "...and run output:\n"
+        "${RUN_OUTPUT}\n"
+        "Return value: ${${VAR}}\n"
+        "Source file was:\n${SOURCE}\n")
+    else()
+      if(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES  "FAILED_TO_RUN")
+        set(${VAR} "${${VAR}_EXITCODE}")
+      else()
+        set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+      endif()
+
+      if(NOT CMAKE_REQUIRED_QUIET)
+        message(STATUS "Performing Test ${VAR} - Failed")
+      endif()
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+        "Performing Objective-C++ SOURCE FILE Test ${VAR} failed with the following output:\n"
+        "${OUTPUT}\n"
+        "...and run output:\n"
+        "${RUN_OUTPUT}\n"
+        "Return value: ${${VAR}_EXITCODE}\n"
+        "Source file was:\n${SOURCE}\n")
+    endif()
+  endif()
+endmacro()
diff --git a/Modules/Compiler/AppleClang-OBJCXX.cmake b/Modules/Compiler/AppleClang-OBJCXX.cmake
new file mode 100644
index 0000000..7c6f763
--- /dev/null
+++ b/Modules/Compiler/AppleClang-OBJCXX.cmake
@@ -0,0 +1,37 @@
+include(Compiler/Clang-OBJCXX)
+
+if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.0)
+  set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "-std=c++98")
+  set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
+  set(CMAKE_OBJCXX98_STANDARD__HAS_FULL_SUPPORT ON)
+
+  set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "-std=c++11")
+  set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
+endif()
+
+if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1)
+  set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++14")
+  set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14")
+  set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON)
+elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 5.1)
+  # AppleClang 5.0 knows this flag, but does not set a __cplusplus macro greater than 201103L
+  set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++1y")
+  set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++1y")
+  set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 6.1)
+  set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++1z")
+  set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
+endif()
+
+if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 8.0)
+    set(CMAKE_OBJCXX11_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 10.0)
+  set(CMAKE_OBJCXX20_STANDARD_COMPILE_OPTION "-std=c++2a")
+  set(CMAKE_OBJCXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a")
+endif()
+
+__compiler_check_default_language_standard(OBJCXX 4.0 98)
diff --git a/Modules/Compiler/Clang-OBJCXX.cmake b/Modules/Compiler/Clang-OBJCXX.cmake
new file mode 100644
index 0000000..b01ce64
--- /dev/null
+++ b/Modules/Compiler/Clang-OBJCXX.cmake
@@ -0,0 +1,70 @@
+include(Compiler/Clang)
+__compiler_clang(OBJCXX)
+
+if("x${CMAKE_OBJCXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
+  if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 2.1)
+    set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "-std=c++98")
+    set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
+  endif()
+
+  if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.1)
+    set(CMAKE_OBJCXX98_STANDARD__HAS_FULL_SUPPORT ON)
+    set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "-std=c++11")
+    set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
+    set(CMAKE_OBJCXX11_STANDARD__HAS_FULL_SUPPORT ON)
+  elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 2.1)
+    set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "-std=c++0x")
+    set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x")
+  endif()
+
+  if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.5)
+    set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++14")
+    set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++14")
+    set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON)
+  elseif(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.4)
+    set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std=c++1y")
+    set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std=gnu++1y")
+    set(CMAKE_OBJCXX14_STANDARD__HAS_FULL_SUPPORT ON)
+  endif()
+
+  set(_clang_version_std17 5.0)
+
+  if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}")
+    set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++17")
+    set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++17")
+  elseif (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 3.5)
+    set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std=c++1z")
+    set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std=gnu++1z")
+  endif()
+
+  if (NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS "${_clang_version_std17}")
+    set(CMAKE_OBJCXX20_STANDARD_COMPILE_OPTION "-std=c++2a")
+    set(CMAKE_OBJCXX20_EXTENSION_COMPILE_OPTION "-std=gnu++2a")
+  endif()
+
+  unset(_clang_version_std17)
+
+  __compiler_check_default_language_standard(OBJCXX 2.1 98)
+elseif(CMAKE_OBJCXX_COMPILER_VERSION VERSION_GREATER_EQUAL 3.9
+    AND CMAKE_OBJCXX_SIMULATE_VERSION VERSION_GREATER_EQUAL 19.0)
+  # This version of clang-cl and the MSVC version it simulates have
+  # support for -std: flags.
+  set(CMAKE_OBJCXX98_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_OBJCXX98_EXTENSION_COMPILE_OPTION "")
+  set(CMAKE_OBJCXX98_STANDARD__HAS_FULL_SUPPORT ON)
+  set(CMAKE_OBJCXX11_STANDARD_COMPILE_OPTION "")
+  set(CMAKE_OBJCXX11_EXTENSION_COMPILE_OPTION "")
+  set(CMAKE_OBJCXX14_STANDARD_COMPILE_OPTION "-std:c++14")
+  set(CMAKE_OBJCXX14_EXTENSION_COMPILE_OPTION "-std:c++14")
+  if (CMAKE_OBJCXX_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0)
+    set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std:c++17")
+    set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std:c++17")
+    set(CMAKE_OBJCXX20_STANDARD_COMPILE_OPTION "-std:c++latest")
+    set(CMAKE_OBJCXX20_EXTENSION_COMPILE_OPTION "-std:c++latest")
+  else()
+    set(CMAKE_OBJCXX17_STANDARD_COMPILE_OPTION "-std:c++latest")
+    set(CMAKE_OBJCXX17_EXTENSION_COMPILE_OPTION "-std:c++latest")
+  endif()
+
+  __compiler_check_default_language_standard(OBJCXX 3.9 14)
+endif()
diff --git a/Modules/Compiler/GNU-OBJCXX.cmake b/Modules/Compiler/GNU-OBJCXX.cmake
new file mode 100644
index 0000000..66a547e
--- /dev/null
+++ b/Modules/Compiler/GNU-OBJCXX.cmake
@@ -0,0 +1,10 @@
+include(Compiler/GNU)
+__compiler_gnu(OBJC)
+
+if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2)
+  set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
+endif()
+
+if(NOT CMAKE_OBJCXX_LINK_FLAGS)
+  set(CMAKE_OBCXX_LINK_FLAGS "-lstdc++")
+endif()
diff --git a/Modules/Platform/Apple-AppleClang-OBJCXX.cmake b/Modules/Platform/Apple-AppleClang-OBJCXX.cmake
new file mode 100644
index 0000000..ed172f1
--- /dev/null
+++ b/Modules/Platform/Apple-AppleClang-OBJCXX.cmake
@@ -0,0 +1,6 @@
+include(Platform/Apple-Clang-OBJCXX)
+if(NOT CMAKE_OBJCXX_COMPILER_VERSION VERSION_LESS 4.2)
+  set(CMAKE_OBJCXX_SYSTEM_FRAMEWORK_SEARCH_FLAG "-iframework ")
+else()
+  unset(CMAKE_OBJCXX_SYSTEM_FRAMEWORK_SEARCH_FLAG)
+endif()
diff --git a/Modules/Platform/Apple-Clang-OBJCXX.cmake b/Modules/Platform/Apple-Clang-OBJCXX.cmake
new file mode 100644
index 0000000..28fc352
--- /dev/null
+++ b/Modules/Platform/Apple-Clang-OBJCXX.cmake
@@ -0,0 +1,2 @@
+include(Platform/Apple-Clang)
+__apple_compiler_clang(OBJCXX)
diff --git a/Modules/Platform/Apple-GNU-OBJCXX.cmake b/Modules/Platform/Apple-GNU-OBJCXX.cmake
new file mode 100644
index 0000000..919e11d
--- /dev/null
+++ b/Modules/Platform/Apple-GNU-OBJCXX.cmake
@@ -0,0 +1,4 @@
+include(Platform/Apple-GNU)
+__apple_compiler_gnu(OBJCXX)
+cmake_gnu_set_sysroot_flag(OBJCXX)
+cmake_gnu_set_osx_deployment_target_flag(OBJCXX)
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index dcda7c5..d0bb359 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -120,14 +120,17 @@ set(CMAKE_CXX_CREATE_MACOSX_FRAMEWORK
       "<CMAKE_CXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
 
 set(CMAKE_OBJC_CREATE_MACOSX_FRAMEWORK
-  "<CMAKE_OBJC_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS> <LINK_FLAGS> -o <TARGET> -dynamiclib -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>"
-)
+      "<CMAKE_OBJC_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
+
+set(CMAKE_OBJCXX_CREATE_MACOSX_FRAMEWORK
+      "<CMAKE_OBJCXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJCXX_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
 
 # Set default framework search path flag for languages known to use a
 # preprocessor that may find headers in frameworks.
 set(CMAKE_C_FRAMEWORK_SEARCH_FLAG -F)
 set(CMAKE_CXX_FRAMEWORK_SEARCH_FLAG -F)
 set(CMAKE_OBJC_FRAMEWORK_SEARCH_FLAG -F)
+set(CMAKE_OBJCXX_FRAMEWORK_SEARCH_FLAG -F)
 set(CMAKE_Fortran_FRAMEWORK_SEARCH_FLAG -F)
 
 # default to searching for frameworks first
@@ -227,7 +230,7 @@ unset(_apps_paths)
 include(Platform/UnixPaths)
 if(_CMAKE_OSX_SYSROOT_PATH AND EXISTS ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
   list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${_CMAKE_OSX_SYSROOT_PATH}/usr)
-  foreach(lang C CXX OBJC)
+  foreach(lang C CXX OBJC OBJCXX)
     list(APPEND _CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES_INIT ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
   endforeach()
 endif()
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index 641cbaf..5a35007 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -707,7 +707,8 @@ struct CompilerIdNode : public cmGeneratorExpressionNode
 };
 
 static const CompilerIdNode cCompilerIdNode("C"), cxxCompilerIdNode("CXX"),
-  cudaCompilerIdNode("CUDA"), fortranCompilerIdNode("Fortran");
+  cudaCompilerIdNode("CUDA"), objcCompilerIdNode("OBJC"),
+  objcxxCompilerIdNode("OBJCXX"), fortranCompilerIdNode("Fortran");
 
 struct CompilerVersionNode : public cmGeneratorExpressionNode
 {
@@ -771,6 +772,7 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode
 
 static const CompilerVersionNode cCompilerVersionNode("C"),
   cxxCompilerVersionNode("CXX"), cudaCompilerVersionNode("CUDA"),
+  objcCompilerVersionNode("OBJC"), objcxxCompilerVersionNode("OBJCXX"),
   fortranCompilerVersionNode("Fortran");
 
 struct PlatformIdNode : public cmGeneratorExpressionNode
@@ -2243,6 +2245,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
     { "NOT", &notNode },
     { "C_COMPILER_ID", &cCompilerIdNode },
     { "CXX_COMPILER_ID", &cxxCompilerIdNode },
+    { "OBJC_COMPILER_ID", &objcCompilerIdNode },
+    { "OBJCXX_COMPILER_ID", &objcxxCompilerIdNode },
     { "CUDA_COMPILER_ID", &cudaCompilerIdNode },
     { "Fortran_COMPILER_ID", &fortranCompilerIdNode },
     { "VERSION_GREATER", &versionGreaterNode },
@@ -2253,6 +2257,8 @@ const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
     { "C_COMPILER_VERSION", &cCompilerVersionNode },
     { "CXX_COMPILER_VERSION", &cxxCompilerVersionNode },
     { "CUDA_COMPILER_VERSION", &cudaCompilerVersionNode },
+    { "OBJC_COMPILER_VERSION", &objcCompilerVersionNode },
+    { "OBJCXX_COMPILER_VERSION", &objcxxCompilerVersionNode },
     { "Fortran_COMPILER_VERSION", &fortranCompilerVersionNode },
     { "PLATFORM_ID", &platformIdNode },
     { "COMPILE_FEATURES", &compileFeaturesNode },
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index 2e17e59..789fc0e 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -2365,6 +2365,42 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH
       )
       list(APPEND TEST_BUILD_DIRS "${CMAKE_BINARY_DIR}/Tests/Objective-C/objc-file-extension-test")
 
+      add_test(Objective-CXX.simple-build-test ${CMAKE_CTEST_COMMAND}
+        --build-and-test
+        "${CMake_SOURCE_DIR}/Tests/Objective-C++/simple-build-test"
+        "${CMake_BINARY_DIR}/Tests/Objective-C++/simple-build-test"
+        --build-two-config
+        ${build_generator_args}
+        --build-project simple-build-test
+        --build-options ${build_options}
+        --test-command simple-build-test
+      )
+      list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C++/simple-build-test")
+
+      add_test(Objective-CXX.cxx-file-extension-test ${CMAKE_CTEST_COMMAND}
+        --build-and-test
+        "${CMake_SOURCE_DIR}/Tests/Objective-C++/cxx-file-extension-test"
+        "${CMake_BINARY_DIR}/Tests/Objective-C++/cxx-file-extension-test"
+        --build-two-config
+        ${build_generator_args}
+        --build-project cxx-file-extension-test
+        --build-options ${build_options}
+        --test-command cxx-file-extension-test
+      )
+      list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C++/cxx-file-extension-test")
+
+      add_test(Objective-CXX.objcxx-file-extension-test ${CMAKE_CTEST_COMMAND}
+        --build-and-test
+        "${CMake_SOURCE_DIR}/Tests/Objective-C++/objcxx-file-extension-test"
+        "${CMake_BINARY_DIR}/Tests/Objective-C++/objcxx-file-extension-test"
+        --build-two-config
+        ${build_generator_args}
+        --build-project objcxx-file-extension-test
+        --build-options ${build_options}
+        --test-command objcxx-file-extension-test
+      )
+      list(APPEND TEST_BUILD_DIRS "${CMAKE_BINARY_DIR}/Tests/Objective-C++/objcxx-file-extension-test")
+
     endif ()
   endif ()
 
diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt
index 1a25469..03babd2 100644
--- a/Tests/CMakeOnly/CMakeLists.txt
+++ b/Tests/CMakeOnly/CMakeLists.txt
@@ -36,6 +36,11 @@ if(CMAKE_OBJC_COMPILER)
   add_CMakeOnly_test(CheckOBJCCompilerFlag)
 endif()
 
+if(CMAKE_OBJCXX_COMPILER)
+  add_CMakeOnly_test(CompilerIdOBJCXX)
+  add_CMakeOnly_test(CheckOBJCXXCompilerFlag)
+endif()
+
 if(CMAKE_Fortran_COMPILER)
   add_CMakeOnly_test(CompilerIdFortran)
 endif()
diff --git a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
index e9bdf6a..90aa921 100644
--- a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
@@ -5,16 +5,17 @@ include(CheckLanguage)
 set(langs )
 set(expect_C 1)
 set(expect_CXX 1)
+
 if(APPLE)
   set(expect_OBJC 1)
+  set(expect_OBJCXX 1)
 endif()
 unset(expect_Fortran)
 set(expect_NoSuchLanguage 0)
 
 set(LANGUAGES C CXX Fortran CUDA NoSuchLanguage)
-
 if(APPLE)
-  list(APPEND LANGUAGES OBJC)
+  list(APPEND LANGUAGES OBJC OBJCXX)
 endif()
 
 foreach(lang ${LANGUAGES})
diff --git a/Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt
new file mode 100644
index 0000000..f83b738
--- /dev/null
+++ b/Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 2.8.12)
+
+project(CheckOBJCXXCompilerFlag)
+
+include(CheckOBJCXXCompilerFlag)
+
+if(CMAKE_COMPILER_IS_GNUOBJCXX)
+  set(COMPILER_FLAG -fobjc-direct-dispatch)
+else()
+  set(COMPILER_FLAG -fobjc-gc)
+endif()
+
+CHECK_OBJCXX_COMPILER_FLAGS(${COMPILER_FLAG} HAS_COMPILER_FLAG)
+
+if(NOT HAS_COMPILER_FLAG)
+  message(SEND_ERROR "Test fail: HAS_COMPILER_FLAG: ${COMPILER_FLAG}")
+endif()
diff --git a/Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt b/Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt
new file mode 100644
index 0000000..8f41db0
--- /dev/null
+++ b/Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(CompilerIdOBJCXX OBJCXX)
+
+foreach(v
+    CMAKE_OBJCXX_COMPILER
+    CMAKE_OBJCXX_COMPILER_ID
+    CMAKE_OBJCXX_COMPILER_VERSION
+    )
+  if(${v})
+    message(STATUS "${v}=[${${v}}]")
+  else()
+    message(SEND_ERROR "${v} not set!")
+  endif()
+endforeach()
diff --git a/Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt b/Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt
new file mode 100644
index 0000000..0b33875
--- /dev/null
+++ b/Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(cxx-file-extension-test CXX)
+
+add_executable(cxx-file-extension-test main.mm)
diff --git a/Tests/Objective-C++/cxx-file-extension-test/main.mm b/Tests/Objective-C++/cxx-file-extension-test/main.mm
new file mode 100644
index 0000000..1c159a9
--- /dev/null
+++ b/Tests/Objective-C++/cxx-file-extension-test/main.mm
@@ -0,0 +1,8 @@
+#ifndef __OBJC__
+#  error "Compiler cannot compile Objective-C"
+#endif
+
+int main()
+{
+  return 0;
+}
diff --git a/Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt b/Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt
new file mode 100644
index 0000000..eda7bba
--- /dev/null
+++ b/Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(objcxx-file-extension-test OBJCXX CXX)
+
+add_executable(objcxx-file-extension-test main.mm)
+target_link_libraries(objcxx-file-extension-test "-framework Foundation")
diff --git a/Tests/Objective-C++/objcxx-file-extension-test/main.mm b/Tests/Objective-C++/objcxx-file-extension-test/main.mm
new file mode 100644
index 0000000..d4aa1bb
--- /dev/null
+++ b/Tests/Objective-C++/objcxx-file-extension-test/main.mm
@@ -0,0 +1,14 @@
+#ifndef __OBJC__
+#  error "Compiler is not an Objective-C compiler."
+#endif
+
+#import <Foundation/Foundation.h>
+#include <iostream>
+
+int main()
+{
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+  std::cout << "Hello World" << std::endl;
+  [pool release];
+  return 0;
+}
diff --git a/Tests/Objective-C++/simple-build-test/CMakeLists.txt b/Tests/Objective-C++/simple-build-test/CMakeLists.txt
new file mode 100644
index 0000000..cf27683
--- /dev/null
+++ b/Tests/Objective-C++/simple-build-test/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.15)
+
+set(CMAKE_MACOSX_RPATH OFF)
+
+project(simple-build-test OBJCXX)
+
+add_library(foo SHARED foo.mm)
+target_link_libraries(foo "-framework Foundation")
+
+add_executable(simple-build-test main.mm)
+target_link_libraries(simple-build-test "-framework Foundation" foo)
diff --git a/Tests/Objective-C++/simple-build-test/foo.h b/Tests/Objective-C++/simple-build-test/foo.h
new file mode 100644
index 0000000..b3fb084
--- /dev/null
+++ b/Tests/Objective-C++/simple-build-test/foo.h
@@ -0,0 +1,9 @@
+#import <Foundation/Foundation.h>
+
+ at interface Foo : NSObject {
+  NSNumber* age;
+}
+
+ at property (nonatomic, retain) NSNumber* age;
+
+ at end
diff --git a/Tests/Objective-C++/simple-build-test/foo.mm b/Tests/Objective-C++/simple-build-test/foo.mm
new file mode 100644
index 0000000..2d452a8
--- /dev/null
+++ b/Tests/Objective-C++/simple-build-test/foo.mm
@@ -0,0 +1,7 @@
+#import "foo.h"
+
+ at implementation Foo
+
+ at synthesize age;
+
+ at end
diff --git a/Tests/Objective-C++/simple-build-test/main.mm b/Tests/Objective-C++/simple-build-test/main.mm
new file mode 100644
index 0000000..7c85551
--- /dev/null
+++ b/Tests/Objective-C++/simple-build-test/main.mm
@@ -0,0 +1,14 @@
+#import <Foundation/Foundation.h>
+#import "foo.h"
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+  Foo *theFoo = [[Foo alloc] init];
+  theFoo.age = [NSNumber numberWithInt:argc];
+  NSLog(@"%d\n",[theFoo.age intValue]);
+  std::cout << [theFoo.age intValue] << std::endl;
+  [pool release];
+  return 0;
+}
diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt
index 8fd8090..498e556 100644
--- a/Tests/TryCompile/CMakeLists.txt
+++ b/Tests/TryCompile/CMakeLists.txt
@@ -1,5 +1,5 @@
 cmake_minimum_required (VERSION 2.6)
-project(TryCompile OBJC C CXX)
+project(TryCompile)
 
 macro(TEST_ASSERT value msg)
   if (NOT ${value})
@@ -315,31 +315,57 @@ endif()
 
 #########################################################################
 #
-# Test that the CHECK_OBJCC_SOURCE_COMPILES, CHECK_OBJC_SOURCE_RUNS
-# macros work.
+# Test that the CHECK_OBJCC_SOURCE_COMPILES, CHECK_OBJCXX_SOURCE_COMPILES
+# CHECK_OBJC_SOURCE_RUNS and CHECK_OBJCXX_SOURCE_RUNS macros work
 
-include(CheckOBJCSourceCompiles)
-include(CheckOBJCSourceRuns)
+if (APPLE)
+    enable_language(OBJC)
+    enable_language(OBJCXX)
 
-CHECK_OBJC_SOURCE_COMPILES("I don't build in Objective-C" OBJC_BUILD_SHOULD_FAIL)
-CHECK_OBJC_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJC_BUILD_SHOULD_WORK)
+    include(CheckOBJCSourceCompiles)
+    include(CheckOBJCXXSourceCompiles)
+    include(CheckOBJCSourceRuns)
+    include(CheckOBJCXXSourceRuns)
 
-TEST_FAIL(OBJC_BUILD_SHOULD_FAIL "CHECK_OBJC_SOURCE_COMPILES() succeeded, but should have failed")
-TEST_ASSERT(SIMPLE_OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
+    CHECK_OBJC_SOURCE_COMPILES("I don't build in Objective-C" OBJC_BUILD_SHOULD_FAIL)
+    CHECK_OBJC_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJC_BUILD_SHOULD_WORK)
 
-set(CMAKE_REQUIRED_LIBRARIES "-framework Foundation")
+    TEST_FAIL(OBJC_BUILD_SHOULD_FAIL "CHECK_OBJC_SOURCE_COMPILES() succeeded, but should have failed")
+    TEST_ASSERT(SIMPLE_OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
 
-CHECK_OBJC_SOURCE_COMPILES("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_BUILD_SHOULD_WORK)
-CHECK_OBJC_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJC_RUN_SHOULD_FAIL)
-CHECK_OBJC_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJC_RUN_SHOULD_WORK)
-CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 2;\n}\n" OBJC_RUN_SHOULD_FAIL)
-CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_RUN_SHOULD_WORK)
+    set(CMAKE_REQUIRED_LIBRARIES "-framework Foundation")
 
-TEST_ASSERT(OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
-TEST_FAIL(SIMPLE_OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURC_RUNS() succeeds, but should have failed")
-TEST_ASSERT(SIMPLE_OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
-TEST_FAIL(OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURCE_RUNS() succeeds, but should have failed")
-TEST_ASSERT(OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
+    CHECK_OBJC_SOURCE_COMPILES("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_BUILD_SHOULD_WORK)
+    CHECK_OBJC_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJC_RUN_SHOULD_FAIL)
+    CHECK_OBJC_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJC_RUN_SHOULD_WORK)
+    CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 2;\n}\n" OBJC_RUN_SHOULD_FAIL)
+    CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_RUN_SHOULD_WORK)
+
+    TEST_ASSERT(OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
+    TEST_FAIL(SIMPLE_OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURC_RUNS() succeeds, but should have failed")
+    TEST_ASSERT(SIMPLE_OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
+    TEST_FAIL(OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURCE_RUNS() succeeds, but should have failed")
+    TEST_ASSERT(OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
+
+
+    CHECK_OBJCXX_SOURCE_COMPILES("I don't build in Objective-C++" OBJCXX_BUILD_SHOULD_FAIL)
+    CHECK_OBJCXX_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJCXX_BUILD_SHOULD_WORK)
+
+    TEST_FAIL(OBJCXX_BUILD_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_COMPILES() succeeded, but should have failed")
+    TEST_ASSERT(SIMPLE_OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded")
+
+    CHECK_OBJCXX_SOURCE_COMPILES("#import <Foundation/Foundation.h>\n#include <iostream>\nint main()\n{\nNSObject *foo;\nstd::cout << \"Hello\" << std::endl;\nreturn 0;\n}\n" OBJCXX_BUILD_SHOULD_WORK)
+    CHECK_OBJCXX_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJCXX_RUN_SHOULD_FAIL)
+    CHECK_OBJCXX_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJCXX_RUN_SHOULD_WORK)
+    CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 2;\n}\n" OBJCXX_RUN_SHOULD_FAIL)
+    CHECK_OBJCXX_SOURCE_RUNS("#import <Foundation/Foundation.h>\n#include <vector>\nint main()\n{\nNSObject *foo;\nstd::vector<int> bar;\nreturn 0;\n}\n" OBJCXX_RUN_SHOULD_WORK)
+
+    TEST_ASSERT(OBJCXX_BUILD_SHOULD_WORK "CHECK_OBJCXX_SOURCE_COMPILES() failed, but should have succeeded")
+    TEST_FAIL(SIMPLE_OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURC_RUNS() succeeds, but should have failed")
+    TEST_ASSERT(SIMPLE_OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded")
+    TEST_FAIL(OBJCXX_RUN_SHOULD_FAIL "CHECK_OBJCXX_SOURCE_RUNS() succeeds, but should have failed")
+    TEST_ASSERT(OBJCXX_RUN_SHOULD_WORK "CHECK_OBJCXX_SOURCE_RUNS() failed, but should have succeeded")
+endif()
 
 #######################################################################
 #

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=80f120a85fb0992e3f06ad69ebdad881bea9af8c
commit 80f120a85fb0992e3f06ad69ebdad881bea9af8c
Author:     Steve Wilson <stevew at wolfram.com>
AuthorDate: Fri Sep 13 18:11:15 2019 +0100
Commit:     Cristian Adam <cristian.adam at gmail.com>
CommitDate: Sat Sep 28 15:56:46 2019 +0200

    Languages: Add support for Objective-C
    
    Add entries in Modules and Modules/Platform to support
    Objective-C compiler determination and identification.
    Add Modules to check Objective-C compiler flags, source
    compilations, program checks, etc...
    
    Use OBJC as the designator of the language, eg:
    
    project(foo OBJC)
    
    Add various tests for Objective-C language features.  Add
    tests to preserve C++ handling of .m and .mm files when
    OBJC is not a configured language.
    
    Co-Authored-By: Cristian Adam <cristian.adam at gmail.com>

diff --git a/Help/command/enable_language.rst b/Help/command/enable_language.rst
index fb49b44..44beb54 100644
--- a/Help/command/enable_language.rst
+++ b/Help/command/enable_language.rst
@@ -1,7 +1,7 @@
 enable_language
 ---------------
 
-Enable a language (CXX/C/Fortran/etc)
+Enable a language (CXX/C/OBJC/Fortran/etc)
 
 .. code-block:: cmake
 
@@ -10,7 +10,7 @@ Enable a language (CXX/C/Fortran/etc)
 Enables support for the named language in CMake.  This is
 the same as the :command:`project` command but does not create any of the extra
 variables that are created by the project command.  Example languages
-are ``CXX``, ``C``, ``CUDA``, ``Fortran``, and ``ASM``.
+are ``CXX``, ``C``, ``CUDA``, ``OBJC``, ``Fortran``, and ``ASM``.
 
 If enabling ``ASM``, enable it last so that CMake can check whether
 compilers for other languages like ``C`` work for assembly too.
diff --git a/Help/command/project.rst b/Help/command/project.rst
index baf18be..2bbb3f4 100644
--- a/Help/command/project.rst
+++ b/Help/command/project.rst
@@ -87,7 +87,8 @@ The options are:
   Can also be specified without ``LANGUAGES`` keyword per the first, short signature.
 
   Selects which programming languages are needed to build the project.
-  Supported languages include ``C``, ``CXX`` (i.e.  C++), ``CUDA``, ``Fortran``, and ``ASM``.
+  Supported languages include ``C``, ``CXX`` (i.e.  C++), ``CUDA``, ``OBJC`` (i.e. Objective-C),
+  ``Fortran``, and ``ASM``.
   By default ``C`` and ``CXX`` are enabled if no language options are given.
   Specify language ``NONE``, or use the ``LANGUAGES`` keyword and list no languages,
   to skip enabling any languages.
diff --git a/Help/manual/cmake-generator-expressions.7.rst b/Help/manual/cmake-generator-expressions.7.rst
index c0449fb..8890433 100644
--- a/Help/manual/cmake-generator-expressions.7.rst
+++ b/Help/manual/cmake-generator-expressions.7.rst
@@ -130,6 +130,11 @@ Variable Queries
   ``1`` if the CMake's compiler id of the CUDA compiler matches any one
   of the entries in ``compiler_ids``, otherwise ``0``.
   See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
+``$<OBJC_COMPILER_ID:compiler_ids>``
+  where ``compiler_ids`` is a comma-separated list.
+  ``1`` if the CMake's compiler id of the Objective-C compiler matches any one
+  of the entries in ``compiler_ids``, otherwise ``0``.
+  See also the :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
 ``$<Fortran_COMPILER_ID:compiler_ids>``
   where ``compiler_ids`` is a comma-separated list.
   ``1`` if the CMake's compiler id of the Fortran compiler matches any one
@@ -413,6 +418,9 @@ Variable Queries
 ``$<CUDA_COMPILER_VERSION>``
   The version of the CUDA compiler used.
   See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
+``$<OBJC_COMPILER_VERSION>``
+  The version of the OBJC compiler used.
+  See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
 ``$<Fortran_COMPILER_VERSION>``
   The version of the Fortran compiler used.
   See also the :variable:`CMAKE_<LANG>_COMPILER_VERSION` variable.
diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst
index fc4bfdc..78881e6 100644
--- a/Help/manual/cmake-modules.7.rst
+++ b/Help/manual/cmake-modules.7.rst
@@ -36,6 +36,9 @@ These modules are loaded using the :command:`include` command.
    /module/CheckIncludeFiles
    /module/CheckLanguage
    /module/CheckLibraryExists
+   /module/CheckOBJCCompilerFlag
+   /module/CheckOBJCSourceCompiles
+   /module/CheckOBJCSourceRuns
    /module/CheckPIESupported
    /module/CheckPrototypeDefinition
    /module/CheckStructHasMember
diff --git a/Help/module/CheckOBJCCompilerFlag.rst b/Help/module/CheckOBJCCompilerFlag.rst
new file mode 100644
index 0000000..e4bd6fd
--- /dev/null
+++ b/Help/module/CheckOBJCCompilerFlag.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCCompilerFlag.cmake
diff --git a/Help/module/CheckOBJCSourceCompiles.rst b/Help/module/CheckOBJCSourceCompiles.rst
new file mode 100644
index 0000000..d4a1484
--- /dev/null
+++ b/Help/module/CheckOBJCSourceCompiles.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCSourceCompiles.cmake
diff --git a/Help/module/CheckOBJCSourceRuns.rst b/Help/module/CheckOBJCSourceRuns.rst
new file mode 100644
index 0000000..c72f0db
--- /dev/null
+++ b/Help/module/CheckOBJCSourceRuns.rst
@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/CheckOBJCSourceRuns.cmake
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index e7f0e70..6936cd4 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -42,8 +42,17 @@ if(CMAKE_COMPILER_IS_MINGW)
   set(MINGW 1)
 endif()
 set(CMAKE_CXX_COMPILER_ID_RUN 1)
+set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP)
 set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC)
-set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;mm;CPP)
+
+foreach (lang OBJC)
+  if (CMAKE_${lang}_COMPILER_ID_RUN)
+    foreach(extension IN LISTS CMAKE_${lang}_SOURCE_FILE_EXTENSIONS)
+      list(REMOVE_ITEM CMAKE_CXX_SOURCE_FILE_EXTENSIONS ${extension})
+    endforeach()
+  endif()
+endforeach()
+
 set(CMAKE_CXX_LINKER_PREFERENCE 30)
 set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
 
diff --git a/Modules/CMakeDetermineOBJCCompiler.cmake b/Modules/CMakeDetermineOBJCCompiler.cmake
new file mode 100644
index 0000000..ad13eab
--- /dev/null
+++ b/Modules/CMakeDetermineOBJCCompiler.cmake
@@ -0,0 +1,189 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# determine the compiler to use for Objective-C programs
+# NOTE, a generator may set CMAKE_OBJC_COMPILER before
+# loading this file to force a compiler.
+# use environment variable OBJC first if defined by user, next use
+# the cmake variable CMAKE_GENERATOR_OBJC which can be defined by a generator
+# as a default compiler
+#
+# Sets the following variables:
+#   CMAKE_OBJC_COMPILER
+#   CMAKE_AR
+#   CMAKE_RANLIB
+#   CMAKE_COMPILER_IS_GNUOBJC
+#   CMAKE_COMPILER_IS_CLANGOBJC
+#
+# If not already set before, it also sets
+#   _CMAKE_TOOLCHAIN_PREFIX
+
+include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
+
+# Load system-specific compiler preferences for this language.
+include(Platform/${CMAKE_SYSTEM_NAME}-Determine-OBJC OPTIONAL)
+include(Platform/${CMAKE_SYSTEM_NAME}-OBJC OPTIONAL)
+if(NOT CMAKE_OBJC_COMPILER_NAMES)
+  set(CMAKE_OBJC_COMPILER_NAMES clang)
+endif()
+
+if("${CMAKE_GENERATOR}" MATCHES "Xcode")
+  set(CMAKE_OBJC_COMPILER_XCODE_TYPE sourcecode.c.objc)
+else()
+  if(NOT CMAKE_OBJC_COMPILER)
+    set(CMAKE_OBJC_COMPILER_INIT NOTFOUND)
+
+    # prefer the environment variable OBJC
+    if($ENV{OBJC} MATCHES ".+")
+      get_filename_component(CMAKE_OBJC_COMPILER_INIT $ENV{OBJC} PROGRAM PROGRAM_ARGS CMAKE_OBJC_FLAGS_ENV_INIT)
+      if(CMAKE_OBJC_FLAGS_ENV_INIT)
+        set(CMAKE_OBJC_COMPILER_ARG1 "${CMAKE_OBJC_FLAGS_ENV_INIT}" CACHE STRING "First argument to Objective-C compiler")
+      endif()
+      if(NOT EXISTS ${CMAKE_OBJC_COMPILER_INIT})
+        message(FATAL_ERROR "Could not find compiler set in environment variable OBJC:\n$ENV{OBJC}.")
+      endif()
+    endif()
+
+    # next try prefer the compiler specified by the generator
+    if(CMAKE_GENERATOR_OBJC)
+      if(NOT CMAKE_OBJC_COMPILER_INIT)
+        set(CMAKE_OBJC_COMPILER_INIT ${CMAKE_GENERATOR_OBJC})
+      endif()
+    endif()
+
+    # finally list compilers to try
+    if(NOT CMAKE_OBJC_COMPILER_INIT)
+      set(CMAKE_OBJC_COMPILER_LIST ${_CMAKE_TOOLCHAIN_PREFIX}cc ${_CMAKE_TOOLCHAIN_PREFIX}gcc clang)
+    endif()
+
+    _cmake_find_compiler(OBJC)
+
+  else()
+    # we only get here if CMAKE_OBJC_COMPILER was specified using -D or a pre-made CMakeCache.txt
+    # (e.g. via ctest) or set in CMAKE_TOOLCHAIN_FILE
+    # if CMAKE_OBJC_COMPILER is a list of length 2, use the first item as
+    # CMAKE_OBJC_COMPILER and the 2nd one as CMAKE_OBJC_COMPILER_ARG1
+
+    list(LENGTH CMAKE_OBJC_COMPILER _CMAKE_OBJC_COMPILER_LIST_LENGTH)
+    if("${_CMAKE_OBJC_COMPILER_LIST_LENGTH}" EQUAL 2)
+      list(GET CMAKE_OBJC_COMPILER 1 CMAKE_OBJC_COMPILER_ARG1)
+      list(GET CMAKE_OBJC_COMPILER 0 CMAKE_OBJC_COMPILER)
+    endif()
+
+    # if a compiler was specified by the user but without path,
+    # now try to find it with the full path
+    # if it is found, force it into the cache,
+    # if not, don't overwrite the setting (which was given by the user) with "NOTFOUND"
+    # if the C compiler already had a path, reuse it for searching the CXX compiler
+    get_filename_component(_CMAKE_USER_OBJC_COMPILER_PATH "${CMAKE_OBJC_COMPILER}" PATH)
+    if(NOT _CMAKE_USER_OBJC_COMPILER_PATH)
+      find_program(CMAKE_OBJC_COMPILER_WITH_PATH NAMES ${CMAKE_OBJC_COMPILER})
+      if(CMAKE_OBJC_COMPILER_WITH_PATH)
+        set(CMAKE_OBJC_COMPILER ${CMAKE_OBJC_COMPILER_WITH_PATH} CACHE STRING "Objective-C compiler" FORCE)
+      endif()
+      unset(CMAKE_OBJC_COMPILER_WITH_PATH CACHE)
+    endif()
+  endif()
+  mark_as_advanced(CMAKE_OBJC_COMPILER)
+
+  # Each entry in this list is a set of extra flags to try
+  # adding to the compile line to see if it helps produce
+  # a valid identification file.
+  set(CMAKE_OBJC_COMPILER_ID_TEST_FLAGS_FIRST)
+  set(CMAKE_OBJC_COMPILER_ID_TEST_FLAGS
+    # Try compiling to an object file only.
+    "-c"
+
+    )
+endif()
+
+# Build a small source file to identify the compiler.
+if(NOT CMAKE_OBJC_COMPILER_ID_RUN)
+  set(CMAKE_OBJC_COMPILER_ID_RUN 1)
+
+  # Try to identify the compiler.
+  set(CMAKE_OBJC_COMPILER_ID)
+  file(READ ${CMAKE_ROOT}/Modules/CMakePlatformId.h.in
+    CMAKE_OBJC_COMPILER_ID_PLATFORM_CONTENT)
+
+  # Match the link line from xcodebuild output of the form
+  #  Ld ...
+  #      ...
+  #      /path/to/cc ...CompilerIdOBJC/...
+  # to extract the compiler front-end for the language.
+  set(CMAKE_OBJC_COMPILER_ID_TOOL_MATCH_REGEX "\nLd[^\n]*(\n[ \t]+[^\n]*)*\n[ \t]+([^ \t\r\n]+)[^\r\n]*-o[^\r\n]*CompilerIdOBJC/(\\./)?(CompilerIdOBJC.(framework|xctest)/)?CompilerIdOBJC[ \t\n\\\"]")
+  set(CMAKE_OBJC_COMPILER_ID_TOOL_MATCH_INDEX 2)
+
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerId.cmake)
+  CMAKE_DETERMINE_COMPILER_ID(OBJC OBJCCFLAGS CMakeOBJCCompilerId.m)
+
+  # Set old compiler and platform id variables.
+  if(CMAKE_OBJC_COMPILER_ID STREQUAL "GNU")
+    set(CMAKE_COMPILER_IS_GNUOBJC 1)
+  endif()
+  if(CMAKE_OBJC_COMPILER_ID STREQUAL "Clang")
+    set(CMAKE_COMPILER_IS_CLANGOBJC 1)
+  endif()
+endif()
+
+if (NOT _CMAKE_TOOLCHAIN_LOCATION)
+  get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_OBJC_COMPILER}" PATH)
+endif ()
+
+# If we have a gcc cross compiler, they have usually some prefix, like
+# e.g. powerpc-linux-gcc, arm-elf-gcc or i586-mingw32msvc-gcc, optionally
+# with a 3-component version number at the end (e.g. arm-eabi-gcc-4.5.2).
+# The other tools of the toolchain usually have the same prefix
+# NAME_WE cannot be used since then this test will fail for names like
+# "arm-unknown-nto-qnx6.3.0-gcc.exe", where BASENAME would be
+# "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
+if (CMAKE_CROSSCOMPILING  AND NOT _CMAKE_TOOLCHAIN_PREFIX)
+
+  if(CMAKE_OBJC_COMPILER_ID MATCHES "GNU|Clang|QCC")
+    get_filename_component(COMPILER_BASENAME "${CMAKE_OBJC_COMPILER}" NAME)
+    if (COMPILER_BASENAME MATCHES "^(.+-)(clang|g?cc)(-[0-9]+(\\.[0-9]+)*)?(-[^.]+)?(\\.exe)?$")
+      set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+      set(_CMAKE_COMPILER_SUFFIX ${CMAKE_MATCH_5})
+    elseif(CMAKE_OBJC_COMPILER_ID MATCHES "Clang")
+      if(CMAKE_OBJC_COMPILER_TARGET)
+        set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_OBJC_COMPILER_TARGET}-)
+      endif()
+    elseif(COMPILER_BASENAME MATCHES "qcc(\\.exe)?$")
+      if(CMAKE_OBJC_COMPILER_TARGET MATCHES "gcc_nto([a-z0-9]+_[0-9]+|[^_le]+)(le)?")
+        set(_CMAKE_TOOLCHAIN_PREFIX nto${CMAKE_MATCH_1}-)
+      endif()
+    endif ()
+
+    # if "llvm-" is part of the prefix, remove it, since llvm doesn't have its own binutils
+    # but uses the regular ar, objcopy, etc. (instead of llvm-objcopy etc.)
+    if ("${_CMAKE_TOOLCHAIN_PREFIX}" MATCHES "(.+-)?llvm-$")
+      set(_CMAKE_TOOLCHAIN_PREFIX ${CMAKE_MATCH_1})
+    endif ()
+  endif()
+
+endif ()
+
+set(_CMAKE_PROCESSING_LANGUAGE "OBJC")
+include(CMakeFindBinUtils)
+include(Compiler/${CMAKE_OBJC_COMPILER_ID}-FindBinUtils OPTIONAL)
+unset(_CMAKE_PROCESSING_LANGUAGE)
+
+if(CMAKE_OBJC_COMPILER_ARCHITECTURE_ID)
+  set(_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID
+    "set(CMAKE_OBJC_COMPILER_ARCHITECTURE_ID ${CMAKE_OBJC_COMPILER_ARCHITECTURE_ID})")
+else()
+  set(_SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID "")
+endif()
+
+if(CMAKE_OBJC_XCODE_ARCHS)
+  set(SET_CMAKE_XCODE_ARCHS
+    "set(CMAKE_XCODE_ARCHS \"${CMAKE_OBJC_XCODE_ARCHS}\")")
+endif()
+
+# configure variables set in this file for fast reload later on
+configure_file(${CMAKE_ROOT}/Modules/CMakeOBJCCompiler.cmake.in
+  ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake
+  @ONLY
+  )
+set(CMAKE_OBJC_COMPILER_ENV_VAR "OBJC")
diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in
new file mode 100644
index 0000000..1555517
--- /dev/null
+++ b/Modules/CMakeOBJCCompiler.cmake.in
@@ -0,0 +1,69 @@
+set(CMAKE_OBJC_COMPILER "@CMAKE_OBJC_COMPILER@")
+set(CMAKE_OBJC_COMPILER_ARG1 "@CMAKE_OBJC_COMPILER_ARG1@")
+set(CMAKE_OBJC_COMPILER_ID "@CMAKE_OBJC_COMPILER_ID@")
+set(CMAKE_OBJC_COMPILER_VERSION "@CMAKE_OBJC_COMPILER_VERSION@")
+set(CMAKE_OBJC_COMPILER_VERSION_INTERNAL "@CMAKE_OBJC_COMPILER_VERSION_INTERNAL@")
+set(CMAKE_OBJC_COMPILER_WRAPPER "@CMAKE_OBJC_COMPILER_WRAPPER@")
+set(CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT "@CMAKE_OBJC_STANDARD_COMPUTED_DEFAULT@")
+set(CMAKE_OBJC_COMPILE_FEATURES "@CMAKE_OBJC_COMPILE_FEATURES@")
+set(CMAKE_OBJC90_COMPILE_FEATURES "@CMAKE_OBJC90_COMPILE_FEATURES@")
+set(CMAKE_OBJC99_COMPILE_FEATURES "@CMAKE_OBJC99_COMPILE_FEATURES@")
+set(CMAKE_OBJC11_COMPILE_FEATURES "@CMAKE_OBJC11_COMPILE_FEATURES@")
+
+set(CMAKE_OBJC_PLATFORM_ID "@CMAKE_OBJC_PLATFORM_ID@")
+set(CMAKE_OBJC_SIMULATE_ID "@CMAKE_OBJC_SIMULATE_ID@")
+set(CMAKE_OBJC_COMPILER_FRONTEND_VARIANT "@CMAKE_OBJC_COMPILER_FRONTEND_VARIANT@")
+set(CMAKE_OBJC_SIMULATE_VERSION "@CMAKE_OBJC_SIMULATE_VERSION@")
+ at _SET_CMAKE_OBJC_COMPILER_ARCHITECTURE_ID@
+ at SET_CMAKE_XCODE_ARCHS@
+set(CMAKE_AR "@CMAKE_AR@")
+set(CMAKE_OBJC_COMPILER_AR "@CMAKE_OBJC_COMPILER_AR@")
+set(CMAKE_RANLIB "@CMAKE_RANLIB@")
+set(CMAKE_OBJC_COMPILER_RANLIB "@CMAKE_OBJC_COMPILER_RANLIB@")
+set(CMAKE_LINKER "@CMAKE_LINKER@")
+set(CMAKE_MT "@CMAKE_MT@")
+set(CMAKE_COMPILER_IS_GNUOBJC @CMAKE_COMPILER_IS_GNUOBJC@)
+set(CMAKE_OBJC_COMPILER_LOADED 1)
+set(CMAKE_OBJC_COMPILER_WORKS @CMAKE_OBJC_COMPILER_WORKS@)
+set(CMAKE_OBJC_ABI_COMPILED @CMAKE_OBJC_ABI_COMPILED@)
+
+set(CMAKE_OBJC_COMPILER_ENV_VAR "OBJC")
+
+set(CMAKE_OBJC_COMPILER_ID_RUN 1)
+set(CMAKE_OBJC_SOURCE_FILE_EXTENSIONS m)
+set(CMAKE_OBJC_IGNORE_EXTENSIONS h;H;o;O)
+set(CMAKE_OBJC_LINKER_PREFERENCE 5)
+
+foreach (lang C CXX OBJCXX)
+  foreach(extension IN LISTS CMAKE_OBJC_SOURCE_FILE_EXTENSIONS)
+    if (CMAKE_${lang}_COMPILER_ID_RUN)
+      list(REMOVE_ITEM CMAKE_${lang}_SOURCE_FILE_EXTENSIONS ${extension})
+    endif()
+  endforeach()
+endforeach()
+
+# Save compiler ABI information.
+set(CMAKE_OBJC_SIZEOF_DATA_PTR "@CMAKE_OBJC_SIZEOF_DATA_PTR@")
+set(CMAKE_OBJC_COMPILER_ABI "@CMAKE_OBJC_COMPILER_ABI@")
+set(CMAKE_OBJC_LIBRARY_ARCHITECTURE "@CMAKE_OBJC_LIBRARY_ARCHITECTURE@")
+
+if(CMAKE_OBJC_SIZEOF_DATA_PTR)
+  set(CMAKE_SIZEOF_VOID_P "${CMAKE_OBJC_SIZEOF_DATA_PTR}")
+endif()
+
+if(CMAKE_OBJC_COMPILER_ABI)
+  set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_OBJC_COMPILER_ABI}")
+endif()
+
+if(CMAKE_OBJC_LIBRARY_ARCHITECTURE)
+  set(CMAKE_LIBRARY_ARCHITECTURE "@CMAKE_OBJC_LIBRARY_ARCHITECTURE@")
+endif()
+
+ at CMAKE_OBJC_COMPILER_CUSTOM_CODE@
+ at CMAKE_OBJC_SYSROOT_FLAG_CODE@
+ at CMAKE_OBJC_OSX_DEPLOYMENT_TARGET_FLAG_CODE@
+
+set(CMAKE_OBJC_IMPLICIT_INCLUDE_DIRECTORIES "@CMAKE_OBJC_IMPLICIT_INCLUDE_DIRECTORIES@")
+set(CMAKE_OBJC_IMPLICIT_LINK_LIBRARIES "@CMAKE_OBJC_IMPLICIT_LINK_LIBRARIES@")
+set(CMAKE_OBJC_IMPLICIT_LINK_DIRECTORIES "@CMAKE_OBJC_IMPLICIT_LINK_DIRECTORIES@")
+set(CMAKE_OBJC_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_OBJC_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES@")
diff --git a/Modules/CMakeOBJCCompilerABI.m b/Modules/CMakeOBJCCompilerABI.m
new file mode 100644
index 0000000..8fa8511
--- /dev/null
+++ b/Modules/CMakeOBJCCompilerABI.m
@@ -0,0 +1,20 @@
+#ifdef __cplusplus
+# error "A C++ compiler has been selected for Objective-C."
+#endif
+
+/*--------------------------------------------------------------------------*/
+
+#include "CMakeCompilerABI.h"
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char *argv[])
+{
+  int require = 0;
+  require += info_sizeof_dptr[argc];
+#if defined(ABI_ID)
+  require += info_abi[argc];
+#endif
+  (void)argv;
+  return require;
+}
diff --git a/Modules/CMakeOBJCCompilerId.m.in b/Modules/CMakeOBJCCompilerId.m.in
new file mode 100644
index 0000000..2b8aa30
--- /dev/null
+++ b/Modules/CMakeOBJCCompilerId.m.in
@@ -0,0 +1,63 @@
+#ifdef __cplusplus
+# error "An Objective-C++ compiler has been selected for Objective-C."
+#endif
+
+ at CMAKE_OBJC_COMPILER_ID_CONTENT@
+
+/* Construct the string literal in pieces to prevent the source from
+   getting matched.  Store it in a pointer rather than an array
+   because some compilers will just produce instructions to fill the
+   array rather than assigning a pointer to a static array.  */
+char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+#ifdef SIMULATE_ID
+char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+#endif
+
+#ifdef __QNXNTO__
+char const* qnxnto = "INFO" ":" "qnxnto[]";
+#endif
+
+ at CMAKE_OBJC_COMPILER_ID_PLATFORM_CONTENT@
+ at CMAKE_OBJC_COMPILER_ID_ERROR_FOR_TEST@
+
+#if !defined(__STDC__)
+# if (defined(_MSC_VER) && !defined(__clang__)) \
+  || (defined(__ibmxl__) || defined(__IBMC__))
+#  define C_DIALECT "90"
+# else
+#  define C_DIALECT
+# endif
+#elif __STDC_VERSION__ >= 201000L
+# define C_DIALECT "11"
+#elif __STDC_VERSION__ >= 199901L
+# define C_DIALECT "99"
+#else
+# define C_DIALECT "90"
+#endif
+const char* info_language_dialect_default =
+  "INFO" ":" "dialect_default[" C_DIALECT "]";
+
+/*--------------------------------------------------------------------------*/
+
+int main(int argc, char* argv[])
+{
+  int require = 0;
+  require += info_compiler[argc];
+  require += info_platform[argc];
+  require += info_arch[argc];
+#ifdef COMPILER_VERSION_MAJOR
+  require += info_version[argc];
+#endif
+#ifdef COMPILER_VERSION_INTERNAL
+  require += info_version_internal[argc];
+#endif
+#ifdef SIMULATE_ID
+  require += info_simulate[argc];
+#endif
+#ifdef SIMULATE_VERSION_MAJOR
+  require += info_simulate_version[argc];
+#endif
+  require += info_language_dialect_default[argc];
+  (void)argv;
+  return require;
+}
diff --git a/Modules/CMakeOBJCInformation.cmake b/Modules/CMakeOBJCInformation.cmake
new file mode 100644
index 0000000..2baad4a
--- /dev/null
+++ b/Modules/CMakeOBJCInformation.cmake
@@ -0,0 +1,188 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+# This file sets the basic flags for the Objective-C language in CMake.
+# It also loads the available platform file for the system-compiler
+# if it exists.
+# It also loads a system - compiler - processor (or target hardware)
+# specific file, which is mainly useful for crosscompiling and embedded systems.
+
+include(CMakeLanguageInformation)
+
+# some compilers use different extensions (e.g. sdcc uses .rel)
+# so set the extension here first so it can be overridden by the compiler specific file
+set(CMAKE_OBJC_OUTPUT_EXTENSION .o)
+
+if(NOT CMAKE_INCLUDE_FLAG_OBJC)
+  set(CMAKE_INCLUDE_FLAG_OBJC ${CMAKE_INCLUDE_FLAG_C})
+endif()
+
+set(_INCLUDED_FILE 0)
+
+# Load compiler-specific information.
+if(CMAKE_OBJC_COMPILER_ID)
+  include(Compiler/${CMAKE_OBJC_COMPILER_ID}-OBJC OPTIONAL)
+endif()
+
+set(CMAKE_BASE_NAME)
+get_filename_component(CMAKE_BASE_NAME "${CMAKE_OBJC_COMPILER}" NAME_WE)
+if(CMAKE_COMPILER_IS_GNUOBJC)
+  set(CMAKE_BASE_NAME gcc)
+endif()
+
+
+# load a hardware specific file, mostly useful for embedded compilers
+if(CMAKE_SYSTEM_PROCESSOR)
+  if(CMAKE_OBJC_COMPILER_ID)
+    include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJC_COMPILER_ID}-OBJC-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+  endif()
+  if (NOT _INCLUDED_FILE)
+    include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}-${CMAKE_SYSTEM_PROCESSOR} OPTIONAL)
+  endif ()
+endif()
+
+
+# load the system- and compiler specific files
+if(CMAKE_OBJC_COMPILER_ID)
+  include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_OBJC_COMPILER_ID}-OBJC
+    OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+endif()
+if (NOT _INCLUDED_FILE)
+  include(Platform/${CMAKE_EFFECTIVE_SYSTEM_NAME}-${CMAKE_BASE_NAME}
+    OPTIONAL RESULT_VARIABLE _INCLUDED_FILE)
+endif ()
+
+# load any compiler-wrapper specific information
+if (CMAKE_OBJC_COMPILER_WRAPPER)
+  __cmake_include_compiler_wrapper(OBJC)
+endif ()
+
+# We specify the compiler information in the system file for some
+# platforms, but this language may not have been enabled when the file
+# was first included.  Include it again to get the language info.
+# Remove this when all compiler info is removed from system files.
+if (NOT _INCLUDED_FILE)
+  include(Platform/${CMAKE_SYSTEM_NAME} OPTIONAL)
+endif ()
+
+if(CMAKE_OBJC_SIZEOF_DATA_PTR)
+  foreach(f ${CMAKE_OBJC_ABI_FILES})
+    include(${f})
+  endforeach()
+  unset(CMAKE_OBJC_ABI_FILES)
+endif()
+
+# This should be included before the _INIT variables are
+# used to initialize the cache.  Since the rule variables
+# have if blocks on them, users can still define them here.
+# But, it should still be after the platform file so changes can
+# be made to those values.
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE)
+  # Save the full path of the file so try_compile can use it.
+  include(${CMAKE_USER_MAKE_RULES_OVERRIDE} RESULT_VARIABLE _override)
+  set(CMAKE_USER_MAKE_RULES_OVERRIDE "${_override}")
+endif()
+
+if(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC)
+  # Save the full path of the file so try_compile can use it.
+  include(${CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC} RESULT_VARIABLE _override)
+  set(CMAKE_USER_MAKE_RULES_OVERRIDE_OBJC "${_override}")
+endif()
+
+
+# for most systems a module is the same as a shared library
+# so unless the variable CMAKE_MODULE_EXISTS is set just
+# copy the values from the LIBRARY variables
+if(NOT CMAKE_MODULE_EXISTS)
+  set(CMAKE_SHARED_MODULE_OBJC_FLAGS ${CMAKE_SHARED_LIBRARY_OBJC_FLAGS})
+  set(CMAKE_SHARED_MODULE_CREATE_OBJC_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS})
+endif()
+
+set(CMAKE_OBJC_FLAGS_INIT "$ENV{OBJCFLAGS} ${CMAKE_OBJC_FLAGS_INIT}")
+
+cmake_initialize_per_config_variable(CMAKE_OBJC_FLAGS "Flags used by the Objective-C compiler")
+
+if(CMAKE_OBJC_STANDARD_LIBRARIES_INIT)
+  set(CMAKE_OBJC_STANDARD_LIBRARIES "${CMAKE_OBJC_STANDARD_LIBRARIES_INIT}"
+    CACHE STRING "Libraries linked by default with all Objective-C applications.")
+  mark_as_advanced(CMAKE_OBJC_STANDARD_LIBRARIES)
+endif()
+
+include(CMakeCommonLanguageInclude)
+
+# now define the following rule variables
+
+# CMAKE_OBJC_CREATE_SHARED_LIBRARY
+# CMAKE_OBJC_CREATE_SHARED_MODULE
+# CMAKE_OBJC_COMPILE_OBJECT
+# CMAKE_OBJC_LINK_EXECUTABLE
+
+# variables supplied by the generator at use time
+# <TARGET>
+# <TARGET_BASE> the target without the suffix
+# <OBJECTS>
+# <OBJECT>
+# <LINK_LIBRARIES>
+# <FLAGS>
+# <LINK_FLAGS>
+
+# Objective-C compiler information
+# <CMAKE_OBJC_COMPILER>
+# <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS>
+# <CMAKE_SHARED_MODULE_CREATE_OBJC_FLAGS>
+# <CMAKE_OBJC_LINK_FLAGS>
+
+# Static library tools
+# <CMAKE_AR>
+# <CMAKE_RANLIB>
+
+
+# create an Objective-C shared library
+if(NOT CMAKE_OBJC_CREATE_SHARED_LIBRARY)
+  set(CMAKE_OBJC_CREATE_SHARED_LIBRARY
+      "<CMAKE_OBJC_COMPILER> <CMAKE_SHARED_LIBRARY_OBJC_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
+endif()
+
+# create an Objective-C shared module just copy the shared library rule
+if(NOT CMAKE_OBJC_CREATE_SHARED_MODULE)
+  set(CMAKE_OBJC_CREATE_SHARED_MODULE ${CMAKE_OBJC_CREATE_SHARED_LIBRARY})
+endif()
+
+# Create an static archive incrementally for large object file counts.
+# If CMAKE_OBJC_CREATE_STATIC_LIBRARY is set it will override these.
+if(NOT DEFINED CMAKE_OBJC_ARCHIVE_CREATE)
+  set(CMAKE_OBJC_ARCHIVE_CREATE "<CMAKE_AR> qc <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_OBJC_ARCHIVE_APPEND)
+  set(CMAKE_OBJC_ARCHIVE_APPEND "<CMAKE_AR> q  <TARGET> <LINK_FLAGS> <OBJECTS>")
+endif()
+if(NOT DEFINED CMAKE_OBJC_ARCHIVE_FINISH)
+  set(CMAKE_OBJC_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
+endif()
+
+# compile an Objective-C file into an object file
+if(NOT CMAKE_OBJC_COMPILE_OBJECT)
+  set(CMAKE_OBJC_COMPILE_OBJECT
+    "<CMAKE_OBJC_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT>   -c <SOURCE>")
+endif()
+
+if(NOT CMAKE_OBJC_LINK_EXECUTABLE)
+  set(CMAKE_OBJC_LINK_EXECUTABLE
+    "<CMAKE_OBJC_COMPILER> <FLAGS> <CMAKE_OBJC_LINK_FLAGS> <LINK_FLAGS> <OBJECTS>  -o <TARGET> <LINK_LIBRARIES>")
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG)
+  set(CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG_SEP)
+  set(CMAKE_EXECUTABLE_RUNTIME_OBJC_FLAG_SEP ${CMAKE_SHARED_LIBRARY_RUNTIME_OBJC_FLAG_SEP})
+endif()
+
+if(NOT CMAKE_EXECUTABLE_RPATH_LINK_OBJC_FLAG)
+  set(CMAKE_EXECUTABLE_RPATH_LINK_OBJC_FLAG ${CMAKE_SHARED_LIBRARY_RPATH_LINK_OBJC_FLAG})
+endif()
+
+set(CMAKE_OBJC_INFORMATION_LOADED 1)
diff --git a/Modules/CMakeTestOBJCCompiler.cmake b/Modules/CMakeTestOBJCCompiler.cmake
new file mode 100644
index 0000000..0030683
--- /dev/null
+++ b/Modules/CMakeTestOBJCCompiler.cmake
@@ -0,0 +1,94 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+
+if(CMAKE_OBJC_COMPILER_FORCED)
+  # The compiler configuration was forced by the user.
+  # Assume the user has configured all compiler information.
+  set(CMAKE_OBJC_COMPILER_WORKS TRUE)
+  return()
+endif()
+
+include(CMakeTestCompilerCommon)
+
+# work around enforced code signing and / or missing exectuable target type
+set(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE ${CMAKE_TRY_COMPILE_TARGET_TYPE})
+if(_CMAKE_FEATURE_DETECTION_TARGET_TYPE)
+  set(CMAKE_TRY_COMPILE_TARGET_TYPE ${_CMAKE_FEATURE_DETECTION_TARGET_TYPE})
+endif()
+
+# Remove any cached result from an older CMake version.
+# We now store this in CMakeCCompiler.cmake.
+unset(CMAKE_OBJC_COMPILER_WORKS CACHE)
+
+# This file is used by EnableLanguage in cmGlobalGenerator to
+# determine that that selected Objective-C compiler can actually compile
+# and link the most basic of programs.   If not, a fatal error
+# is set and cmake stops processing commands and will not generate
+# any makefiles or projects.
+if(NOT CMAKE_OBJC_COMPILER_WORKS)
+  PrintTestCompilerStatus("OBJC" "")
+  __TestCompiler_setTryCompileTargetType()
+  file(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m
+    "#ifdef __cplusplus\n"
+    "# error \"The CMAKE_OBJC_COMPILER is set to a C++ compiler\"\n"
+    "#endif\n"
+    "#ifndef __OBJC__\n"
+    "# error \"The CMAKE_OBJC_COMPILER is not an Objective-C compiler\"\n"
+    "#endif\n"
+    "int main(int argc, char* argv[])\n"
+    "{ (void)argv; return argc-1;}\n")
+  try_compile(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_BINARY_DIR}
+    ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testOBJCCompiler.m
+    OUTPUT_VARIABLE __CMAKE_OBJC_COMPILER_OUTPUT)
+  # Move result from cache to normal variable.
+  set(CMAKE_OBJC_COMPILER_WORKS ${CMAKE_OBJC_COMPILER_WORKS})
+  unset(CMAKE_OBJC_COMPILER_WORKS CACHE)
+  set(OBJC_TEST_WAS_RUN 1)
+  __TestCompiler_restoreTryCompileTargetType()
+endif()
+
+if(NOT CMAKE_OBJC_COMPILER_WORKS)
+  PrintTestCompilerStatus("OBJC" " -- broken")
+  file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+    "Determining if the Objective-C compiler works failed with "
+    "the following output:\n${__CMAKE_OBJC_COMPILER_OUTPUT}\n\n")
+  string(REPLACE "\n" "\n  " _output "${__CMAKE_OBJC_COMPILER_OUTPUT}")
+  message(FATAL_ERROR "The Objective-C compiler\n  \"${CMAKE_OBJC_COMPILER}\"\n"
+    "is not able to compile a simple test program.\nIt fails "
+    "with the following output:\n  ${_output}\n\n"
+    "CMake will not be able to correctly generate this project.")
+else()
+  if(OBJC_TEST_WAS_RUN)
+    PrintTestCompilerStatus("OBJC" " -- works")
+    file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+      "Determining if the Objective-C compiler works passed with "
+      "the following output:\n${__CMAKE_OBJC_COMPILER_OUTPUT}\n\n")
+  endif()
+
+  # Try to identify the ABI and configure it into CMakeOBJCCompiler.cmake
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
+  CMAKE_DETERMINE_COMPILER_ABI(OBJC ${CMAKE_ROOT}/Modules/CMakeOBJCCompilerABI.m)
+  # Try to identify the compiler features
+  include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
+  CMAKE_DETERMINE_COMPILE_FEATURES(OBJC)
+
+  # Re-configure to save learned information.
+  configure_file(
+    ${CMAKE_ROOT}/Modules/CMakeOBJCCompiler.cmake.in
+    ${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake
+    @ONLY
+    )
+  include(${CMAKE_PLATFORM_INFO_DIR}/CMakeOBJCCompiler.cmake)
+
+  if(CMAKE_OBJC_SIZEOF_DATA_PTR)
+    foreach(f ${CMAKE_OBJC_ABI_FILES})
+      include(${f})
+    endforeach()
+    unset(CMAKE_OBJC_ABI_FILES)
+  endif()
+endif()
+
+set(CMAKE_TRY_COMPILE_TARGET_TYPE ${__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE})
+unset(__CMAKE_SAVED_TRY_COMPILE_TARGET_TYPE)
+unset(__CMAKE_OBJC_COMPILER_OUTPUT)
diff --git a/Modules/CheckOBJCCompilerFlag.cmake b/Modules/CheckOBJCCompilerFlag.cmake
new file mode 100644
index 0000000..1d975da
--- /dev/null
+++ b/Modules/CheckOBJCCompilerFlag.cmake
@@ -0,0 +1,64 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCCompilerFlag
+---------------------
+
+Check whether the Objective-C compiler supports a given flag.
+
+.. command:: check_objc_compiler_flag
+
+  .. code-block:: cmake
+
+    check_objc_compiler_flag(<flag> <var>)
+
+  Check that the ``<flag>`` is accepted by the compiler without
+  a diagnostic.  Stores the result in an internal cache entry
+  named ``<var>``.
+
+This command temporarily sets the ``CMAKE_REQUIRED_DEFINITIONS`` variable
+and calls the ``check_objc_source_compiles`` macro from the
+:module:`CheckOBJCSourceCompiles` module.  See documentation of that
+module for a listing of variables that can otherwise modify the build.
+
+A positive result from this check indicates only that the compiler did not
+issue a diagnostic message when given the flag.  Whether the flag has any
+effect or even a specific one is beyond the scope of this module.
+
+.. note::
+  Since the :command:`try_compile` command forwards flags from variables
+  like :variable:`CMAKE_OBJC_FLAGS <CMAKE_<LANG>_FLAGS>`, unknown flags
+  in such variables may cause a false negative for this check.
+#]=======================================================================]
+
+include_guard(GLOBAL)
+include(CheckOBJCSourceCompiles)
+include(CMakeCheckCompilerFlagCommonPatterns)
+
+macro (CHECK_OBJC_COMPILER_FLAG _FLAG _RESULT)
+  set(SAFE_CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS}")
+  set(CMAKE_REQUIRED_DEFINITIONS "${_FLAG}")
+
+   # Normalize locale during test compilation.
+  set(_CheckOBJCCompilerFlag_LOCALE_VARS LC_ALL LC_MESSAGES LANG)
+  foreach(v ${_CheckOBJCCompilerFlag_LOCALE_VARS})
+    set(_CheckOBJCCompilerFlag_SAVED_${v} "$ENV{${v}}")
+    set(ENV{${v}} OBJC)
+  endforeach()
+  CHECK_COMPILER_FLAG_COMMON_PATTERNS(_CheckOBJCCompilerFlag_COMMON_PATTERNS)
+  CHECK_OBJC_SOURCE_COMPILES("#ifndef __OBJC__\n#  error \"Not an Objective-C compiler\"\n#endif\nint main(void) { return 0; }" ${_RESULT}
+    # Some compilers do not fail with a bad flag
+    FAIL_REGEX "command line option .* is valid for .* but not for Objective-C" # GNU
+    FAIL_REGEX "argument unused during compilation: .*" # Clang
+    ${_CheckOBJCCompilerFlag_COMMON_PATTERNS}
+    )
+  foreach(v ${_CheckOBJCCompilerFlag_LOCALE_VARS})
+    set(ENV{${v}} ${_CheckOBJCCompilerFlag_SAVED_${v}})
+    unset(_CheckOBJCCompilerFlag_SAVED_${v})
+  endforeach()
+  unset(_CheckOBJCCompilerFlag_LOCALE_VARS)
+  unset(_CheckOBJCCompilerFlag_COMMON_PATTERNS)
+
+  set (CMAKE_REQUIRED_DEFINITIONS "${SAFE_CMAKE_REQUIRED_DEFINITIONS}")
+endmacro ()
diff --git a/Modules/CheckOBJCSourceCompiles.cmake b/Modules/CheckOBJCSourceCompiles.cmake
new file mode 100644
index 0000000..a4676ad
--- /dev/null
+++ b/Modules/CheckOBJCSourceCompiles.cmake
@@ -0,0 +1,145 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCSourceCompiles
+-----------------------
+
+Check if given Objective-C source compiles and links into an executable.
+
+.. command:: check_objc_source_compiles
+
+  .. code-block:: cmake
+
+    check_objc_source_compiles(<code> <resultVar>
+                               [FAIL_REGEX <regex1> [<regex2>...]])
+
+  Check that the source supplied in ``<code>`` can be compiled as a Objectie-C source
+  file and linked as an executable (so it must contain at least a ``main()``
+  function). The result will be stored in the internal cache variable specified
+  by ``<resultVar>``, with a boolean true value for success and boolean false
+  for failure. If ``FAIL_REGEX`` is provided, then failure is determined by
+  checking if anything in the output matches any of the specified regular
+  expressions.
+
+  The underlying check is performed by the :command:`try_compile` command. The
+  compile and link commands can be influenced by setting any of the following
+  variables prior to calling ``check_objc_source_compiles()``:
+
+  ``CMAKE_REQUIRED_FLAGS``
+    Additional flags to pass to the compiler. Note that the contents of
+    :variable:`CMAKE_OBJC_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
+    configuration-specific variable are automatically added to the compiler
+    command before the contents of ``CMAKE_REQUIRED_FLAGS``.
+
+  ``CMAKE_REQUIRED_DEFINITIONS``
+    A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
+    ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
+    ``<resultVar>`` will also be added automatically.
+
+  ``CMAKE_REQUIRED_INCLUDES``
+    A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
+    the compiler. These will be the only header search paths used by
+    ``try_compile()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
+    directory property will be ignored.
+
+  ``CMAKE_REQUIRED_LINK_OPTIONS``
+    A :ref:`;-list <CMake Language Lists>` of options to add to the link
+    command (see :command:`try_compile` for further details).
+
+  ``CMAKE_REQUIRED_LIBRARIES``
+    A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
+    command. These can be the name of system libraries or they can be
+    :ref:`Imported Targets <Imported Targets>` (see :command:`try_compile` for
+    further details).
+
+  ``CMAKE_REQUIRED_QUIET``
+    If this variable evaluates to a boolean true value, all status messages
+    associated with the check will be suppressed.
+
+  The check is only performed once, with the result cached in the variable
+  named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
+  value rather than performing the check again, even if the ``<code>`` changes.
+  In order to force the check to be re-evaluated, the variable named by
+  ``<resultVar>`` must be manually removed from the cache.
+
+#]=======================================================================]
+
+include_guard(GLOBAL)
+
+macro(CHECK_OBJC_SOURCE_COMPILES SOURCE VAR)
+  if(NOT DEFINED "${VAR}")
+    set(_FAIL_REGEX)
+    set(_key)
+    foreach(arg ${ARGN})
+      if("${arg}" MATCHES "^(FAIL_REGEX)$")
+        set(_key "${arg}")
+      elseif(_key)
+        list(APPEND _${_key} "${arg}")
+      else()
+        message(FATAL_ERROR "Unknown argument:\n  ${arg}\n")
+      endif()
+    endforeach()
+    set(MACRO_CHECK_FUNCTION_DEFINITIONS
+      "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+    if(CMAKE_REQUIRED_LINK_OPTIONS)
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS
+        LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
+    else()
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS)
+    endif()
+    if(CMAKE_REQUIRED_LIBRARIES)
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES
+        LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+    else()
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES)
+    endif()
+    if(CMAKE_REQUIRED_INCLUDES)
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES
+        "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+    else()
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES)
+    endif()
+    file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m"
+      "${SOURCE}\n")
+
+    if(NOT CMAKE_REQUIRED_QUIET)
+      message(STATUS "Performing Test ${VAR}")
+    endif()
+    try_compile(${VAR}
+      ${CMAKE_BINARY_DIR}
+      ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m
+      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+      ${CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS}
+      ${CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES}
+      CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
+      "${CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES}"
+      OUTPUT_VARIABLE OUTPUT)
+
+    foreach(_regex ${_FAIL_REGEX})
+      if("${OUTPUT}" MATCHES "${_regex}")
+        set(${VAR} 0)
+      endif()
+    endforeach()
+
+    if(${VAR})
+      set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+      if(NOT CMAKE_REQUIRED_QUIET)
+        message(STATUS "Performing Test ${VAR} - Success")
+      endif()
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+        "Performing Objective-C SOURCE FILE Test ${VAR} succeeded with the following output:\n"
+        "${OUTPUT}\n"
+        "Source file was:\n${SOURCE}\n")
+    else()
+      if(NOT CMAKE_REQUIRED_QUIET)
+        message(STATUS "Performing Test ${VAR} - Failed")
+      endif()
+      set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+        "Performing Objective-C SOURCE FILE Test ${VAR} failed with the following output:\n"
+        "${OUTPUT}\n"
+        "Source file was:\n${SOURCE}\n")
+    endif()
+  endif()
+endmacro()
diff --git a/Modules/CheckOBJCSourceRuns.cmake b/Modules/CheckOBJCSourceRuns.cmake
new file mode 100644
index 0000000..00a1ebd
--- /dev/null
+++ b/Modules/CheckOBJCSourceRuns.cmake
@@ -0,0 +1,145 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+CheckOBJCSourceRuns
+-------------------
+
+Check if given Objective-C source compiles and links into an executable and can
+subsequently be run.
+
+.. command:: check_objc_source_runs
+
+  .. code-block:: cmake
+
+    check_objc_source_runs(<code> <resultVar>)
+
+  Check that the source supplied in ``<code>`` can be compiled as a Objective-C source
+  file, linked as an executable and then run. The ``<code>`` must contain at
+  least a ``main()`` function. If the ``<code>`` could be built and run
+  successfully, the internal cache variable specified by ``<resultVar>`` will
+  be set to 1, otherwise it will be set to an value that evaluates to boolean
+  false (e.g. an empty string or an error message).
+
+  The underlying check is performed by the :command:`try_run` command. The
+  compile and link commands can be influenced by setting any of the following
+  variables prior to calling ``check_objc_source_runs()``:
+
+  ``CMAKE_REQUIRED_FLAGS``
+    Additional flags to pass to the compiler. Note that the contents of
+    :variable:`CMAKE_OBJC_FLAGS <CMAKE_<LANG>_FLAGS>` and its associated
+    configuration-specific variable are automatically added to the compiler
+    command before the contents of ``CMAKE_REQUIRED_FLAGS``.
+
+  ``CMAKE_REQUIRED_DEFINITIONS``
+    A :ref:`;-list <CMake Language Lists>` of compiler definitions of the form
+    ``-DFOO`` or ``-DFOO=bar``. A definition for the name specified by
+    ``<resultVar>`` will also be added automatically.
+
+  ``CMAKE_REQUIRED_INCLUDES``
+    A :ref:`;-list <CMake Language Lists>` of header search paths to pass to
+    the compiler. These will be the only header search paths used by
+    ``try_run()``, i.e. the contents of the :prop_dir:`INCLUDE_DIRECTORIES`
+    directory property will be ignored.
+
+  ``CMAKE_REQUIRED_LINK_OPTIONS``
+    A :ref:`;-list <CMake Language Lists>` of options to add to the link
+    command (see :command:`try_run` for further details).
+
+  ``CMAKE_REQUIRED_LIBRARIES``
+    A :ref:`;-list <CMake Language Lists>` of libraries to add to the link
+    command. These can be the name of system libraries or they can be
+    :ref:`Imported Targets <Imported Targets>` (see :command:`try_run` for
+    further details).
+
+  ``CMAKE_REQUIRED_QUIET``
+    If this variable evaluates to a boolean true value, all status messages
+    associated with the check will be suppressed.
+
+  The check is only performed once, with the result cached in the variable
+  named by ``<resultVar>``. Every subsequent CMake run will re-use this cached
+  value rather than performing the check again, even if the ``<code>`` changes.
+  In order to force the check to be re-evaluated, the variable named by
+  ``<resultVar>`` must be manually removed from the cache.
+
+#]=======================================================================]
+
+include_guard(GLOBAL)
+
+macro(CHECK_OBJC_SOURCE_RUNS SOURCE VAR)
+  if(NOT DEFINED "${VAR}")
+    set(MACRO_CHECK_FUNCTION_DEFINITIONS
+      "-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
+    if(CMAKE_REQUIRED_LINK_OPTIONS)
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS
+        LINK_OPTIONS ${CMAKE_REQUIRED_LINK_OPTIONS})
+    else()
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS)
+    endif()
+    if(CMAKE_REQUIRED_LIBRARIES)
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES
+        LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
+    else()
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES)
+    endif()
+    if(CMAKE_REQUIRED_INCLUDES)
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES
+        "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
+    else()
+      set(CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES)
+    endif()
+    file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m"
+      "${SOURCE}\n")
+
+    if(NOT CMAKE_REQUIRED_QUIET)
+      message(STATUS "Performing Test ${VAR}")
+    endif()
+    try_run(${VAR}_EXITCODE ${VAR}_COMPILED
+      ${CMAKE_BINARY_DIR}
+      ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.m
+      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
+      ${CHECK_OBJC_SOURCE_COMPILES_ADD_LINK_OPTIONS}
+      ${CHECK_OBJC_SOURCE_COMPILES_ADD_LIBRARIES}
+      CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
+      -DCMAKE_SKIP_RPATH:BOOL=${CMAKE_SKIP_RPATH}
+      "${CHECK_OBJC_SOURCE_COMPILES_ADD_INCLUDES}"
+      COMPILE_OUTPUT_VARIABLE OUTPUT
+      RUN_OUTPUT_VARIABLE RUN_OUTPUT)
+    # if it did not compile make the return value fail code of 1
+    if(NOT ${VAR}_COMPILED)
+      set(${VAR}_EXITCODE 1)
+    endif()
+    # if the return value was 0 then it worked
+    if("${${VAR}_EXITCODE}" EQUAL 0)
+      set(${VAR} 1 CACHE INTERNAL "Test ${VAR}")
+      if(NOT CMAKE_REQUIRED_QUIET)
+        message(STATUS "Performing Test ${VAR} - Success")
+      endif()
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+        "Performing Objective-C SOURCE FILE Test ${VAR} succeeded with the following compile output:\n"
+        "${OUTPUT}\n"
+        "...and run output:\n"
+        "${RUN_OUTPUT}\n"
+        "Return value: ${${VAR}}\n"
+        "Source file was:\n${SOURCE}\n")
+    else()
+      if(CMAKE_CROSSCOMPILING AND "${${VAR}_EXITCODE}" MATCHES  "FAILED_TO_RUN")
+        set(${VAR} "${${VAR}_EXITCODE}")
+      else()
+        set(${VAR} "" CACHE INTERNAL "Test ${VAR}")
+      endif()
+
+      if(NOT CMAKE_REQUIRED_QUIET)
+        message(STATUS "Performing Test ${VAR} - Failed")
+      endif()
+      file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+        "Performing Objective-C SOURCE FILE Test ${VAR} failed with the following compile output:\n"
+        "${OUTPUT}\n"
+        "...and run output:\n"
+        "${RUN_OUTPUT}\n"
+        "Return value: ${${VAR}_EXITCODE}\n"
+        "Source file was:\n${SOURCE}\n")
+
+    endif()
+  endif()
+endmacro()
diff --git a/Modules/Compiler/AppleClang-OBJC.cmake b/Modules/Compiler/AppleClang-OBJC.cmake
new file mode 100644
index 0000000..d1f3706
--- /dev/null
+++ b/Modules/Compiler/AppleClang-OBJC.cmake
@@ -0,0 +1,17 @@
+include(Compiler/Clang-OBJC)
+
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.0)
+  set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
+  set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
+  set(CMAKE_OBJC90_STANDARD__HAS_FULL_SUPPORT ON)
+
+  set(CMAKE_OBJC99_STANDARD_COMPILE_OPTION "-std=c99")
+  set(CMAKE_OBJC99_EXTENSION_COMPILE_OPTION "-std=gnu99")
+  set(CMAKE_OBJC99_STANDARD__HAS_FULL_SUPPORT ON)
+
+  set(CMAKE_OBJC11_STANDARD_COMPILE_OPTION "-std=c11")
+  set(CMAKE_OBJC11_EXTENSION_COMPILE_OPTION "-std=gnu11")
+  set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+__compiler_check_default_language_standard(OBJC 4.0 99)
diff --git a/Modules/Compiler/Clang-OBJC.cmake b/Modules/Compiler/Clang-OBJC.cmake
new file mode 100644
index 0000000..c61c497
--- /dev/null
+++ b/Modules/Compiler/Clang-OBJC.cmake
@@ -0,0 +1,18 @@
+include(Compiler/Clang)
+__compiler_clang(OBJC)
+
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 3.4)
+  set(CMAKE_OBJC90_STANDARD_COMPILE_OPTION "-std=c90")
+  set(CMAKE_OBJC90_EXTENSION_COMPILE_OPTION "-std=gnu90")
+  set(CMAKE_OBJC90_STANDARD__HAS_FULL_SUPPORT ON)
+
+  set(CMAKE_OBJC99_STANDARD_COMPILE_OPTION "-std=c99")
+  set(CMAKE_OBJC99_EXTENSION_COMPILE_OPTION "-std=gnu99")
+  set(CMAKE_OBJC99_STANDARD__HAS_FULL_SUPPORT ON)
+
+  set(CMAKE_OBJC11_STANDARD_COMPILE_OPTION "-std=c11")
+  set(CMAKE_OBJC11_EXTENSION_COMPILE_OPTION "-std=gnu11")
+  set(CMAKE_OBJC11_STANDARD__HAS_FULL_SUPPORT ON)
+endif()
+
+__compiler_check_default_language_standard(OBJC 3.4 99 3.6 11)
diff --git a/Modules/Compiler/GNU-OBJC.cmake b/Modules/Compiler/GNU-OBJC.cmake
new file mode 100644
index 0000000..5fba801
--- /dev/null
+++ b/Modules/Compiler/GNU-OBJC.cmake
@@ -0,0 +1,6 @@
+include(Compiler/GNU)
+__compiler_gnu(OBJC)
+
+if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.2)
+  set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
+endif()
diff --git a/Modules/Platform/Apple-AppleClang-OBJC.cmake b/Modules/Platform/Apple-AppleClang-OBJC.cmake
new file mode 100644
index 0000000..b78edb1
--- /dev/null
+++ b/Modules/Platform/Apple-AppleClang-OBJC.cmake
@@ -0,0 +1,6 @@
+include(Platform/Apple-Clang-OBJC)
+if(NOT CMAKE_OBJC_COMPILER_VERSION VERSION_LESS 4.2)
+  set(CMAKE_OBJC_SYSTEM_FRAMEWORK_SEARCH_FLAG "-iframework ")
+else()
+  unset(CMAKE_OBJC_SYSTEM_FRAMEWORK_SEARCH_FLAG)
+endif()
diff --git a/Modules/Platform/Apple-Clang-OBJC.cmake b/Modules/Platform/Apple-Clang-OBJC.cmake
new file mode 100644
index 0000000..63cd846
--- /dev/null
+++ b/Modules/Platform/Apple-Clang-OBJC.cmake
@@ -0,0 +1,2 @@
+include(Platform/Apple-Clang)
+__apple_compiler_clang(OBJC)
diff --git a/Modules/Platform/Apple-GNU-OBJC.cmake b/Modules/Platform/Apple-GNU-OBJC.cmake
new file mode 100644
index 0000000..aa8b33f
--- /dev/null
+++ b/Modules/Platform/Apple-GNU-OBJC.cmake
@@ -0,0 +1,4 @@
+include(Platform/Apple-GNU)
+__apple_compiler_gnu(OBJC)
+cmake_gnu_set_sysroot_flag(OBJC)
+cmake_gnu_set_osx_deployment_target_flag(OBJC)
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index 7e02814..dcda7c5 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -119,10 +119,15 @@ set(CMAKE_C_CREATE_MACOSX_FRAMEWORK
 set(CMAKE_CXX_CREATE_MACOSX_FRAMEWORK
       "<CMAKE_CXX_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
 
+set(CMAKE_OBJC_CREATE_MACOSX_FRAMEWORK
+  "<CMAKE_OBJC_COMPILER> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_OBJC_FLAGS> <LINK_FLAGS> -o <TARGET> -dynamiclib -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>"
+)
+
 # Set default framework search path flag for languages known to use a
 # preprocessor that may find headers in frameworks.
 set(CMAKE_C_FRAMEWORK_SEARCH_FLAG -F)
 set(CMAKE_CXX_FRAMEWORK_SEARCH_FLAG -F)
+set(CMAKE_OBJC_FRAMEWORK_SEARCH_FLAG -F)
 set(CMAKE_Fortran_FRAMEWORK_SEARCH_FLAG -F)
 
 # default to searching for frameworks first
@@ -222,7 +227,7 @@ unset(_apps_paths)
 include(Platform/UnixPaths)
 if(_CMAKE_OSX_SYSROOT_PATH AND EXISTS ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
   list(APPEND CMAKE_SYSTEM_PREFIX_PATH ${_CMAKE_OSX_SYSROOT_PATH}/usr)
-  foreach(lang C CXX)
+  foreach(lang C CXX OBJC)
     list(APPEND _CMAKE_${lang}_IMPLICIT_INCLUDE_DIRECTORIES_INIT ${_CMAKE_OSX_SYSROOT_PATH}/usr/include)
   endforeach()
 endif()
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 93e074d..3583dc9 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1654,7 +1654,7 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags,
     const char* deploymentTargetFlag =
       this->Makefile->GetDefinition(deploymentTargetFlagVar);
     if (!archs.empty() && !lang.empty() &&
-        (lang[0] == 'C' || lang[0] == 'F')) {
+        (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) {
       for (std::string const& arch : archs) {
         flags += " -arch ";
         flags += arch;
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index c284603..2e17e59 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -2328,6 +2328,43 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH
       list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/CFBundleTest")
 
       ADD_TEST_MACRO(ObjC++ ObjC++)
+
+      add_test(Objective-C.simple-build-test ${CMAKE_CTEST_COMMAND}
+        --build-and-test
+        "${CMake_SOURCE_DIR}/Tests/Objective-C/simple-build-test"
+        "${CMake_BINARY_DIR}/Tests/Objective-C/simple-build-test"
+        --build-two-config
+        ${build_generator_args}
+        --build-project simple-build-test
+        --build-options ${build_options}
+        --test-command simple-build-test
+      )
+      list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C/simple-build-test")
+
+      add_test(Objective-C.c-file-extension-test ${CMAKE_CTEST_COMMAND}
+        --build-and-test
+        "${CMake_SOURCE_DIR}/Tests/Objective-C/c-file-extension-test"
+        "${CMake_BINARY_DIR}/Tests/Objective-C/c-file-extension-test"
+        --build-two-config
+        ${build_generator_args}
+        --build-project c-file-extension-test
+        --build-options ${build_options}
+        --test-command c-file-extension-test
+      )
+      list(APPEND TEST_BUILD_DIRS "${CMake_BINARY_DIR}/Tests/Objective-C/c-file-extension-test")
+
+      add_test(Objective-C.objc-file-extension-test ${CMAKE_CTEST_COMMAND}
+        --build-and-test
+        "${CMake_SOURCE_DIR}/Tests/Objective-C/objc-file-extension-test"
+        "${CMake_BINARY_DIR}/Tests/Objective-C/objc-file-extension-test"
+        --build-two-config
+        ${build_generator_args}
+        --build-project objc-file-extension-test
+        --build-options ${build_options}
+        --test-command objc-file-extension-test
+      )
+      list(APPEND TEST_BUILD_DIRS "${CMAKE_BINARY_DIR}/Tests/Objective-C/objc-file-extension-test")
+
     endif ()
   endif ()
 
diff --git a/Tests/CMakeOnly/CMakeLists.txt b/Tests/CMakeOnly/CMakeLists.txt
index 19f3f79..1a25469 100644
--- a/Tests/CMakeOnly/CMakeLists.txt
+++ b/Tests/CMakeOnly/CMakeLists.txt
@@ -30,6 +30,12 @@ add_CMakeOnly_test(CheckStructHasMember)
 
 add_CMakeOnly_test(CompilerIdC)
 add_CMakeOnly_test(CompilerIdCXX)
+
+if(CMAKE_OBJC_COMPILER)
+  add_CMakeOnly_test(CompilerIdOBJC)
+  add_CMakeOnly_test(CheckOBJCCompilerFlag)
+endif()
+
 if(CMAKE_Fortran_COMPILER)
   add_CMakeOnly_test(CompilerIdFortran)
 endif()
diff --git a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
index ca4becb..e9bdf6a 100644
--- a/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
+++ b/Tests/CMakeOnly/CheckLanguage/CMakeLists.txt
@@ -5,10 +5,19 @@ include(CheckLanguage)
 set(langs )
 set(expect_C 1)
 set(expect_CXX 1)
+if(APPLE)
+  set(expect_OBJC 1)
+endif()
 unset(expect_Fortran)
 set(expect_NoSuchLanguage 0)
 
-foreach(lang C CXX Fortran CUDA NoSuchLanguage)
+set(LANGUAGES C CXX Fortran CUDA NoSuchLanguage)
+
+if(APPLE)
+  list(APPEND LANGUAGES OBJC)
+endif()
+
+foreach(lang ${LANGUAGES})
   check_language(${lang})
   if(NOT DEFINED CMAKE_${lang}_COMPILER)
     message(FATAL_ERROR "check_language(${lang}) did not set result")
diff --git a/Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt b/Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt
new file mode 100644
index 0000000..a9a96ee
--- /dev/null
+++ b/Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt
@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 2.8.12)
+
+project(CheckOBJCCompilerFlag)
+
+include(CheckOBJCCompilerFlag)
+
+if(CMAKE_COMPILER_IS_GNUOBJC)
+  set(COMPILER_FLAG -fobjc-direct-dispatch)
+else()
+  set(COMPILER_FLAG -fobjc-gc)
+endif()
+
+CHECK_OBJC_COMPILER_FLAGS(${COMPILER_FLAG} HAS_COMPILER_FLAG)
+
+if(NOT HAS_COMPILER_FLAG)
+  message(SEND_ERROR "Test fail: HAS_COMPILER_FLAG: ${COMPILER_FLAG}")
+endif
diff --git a/Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt b/Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt
new file mode 100644
index 0000000..8f13787
--- /dev/null
+++ b/Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 2.8.12)
+project(CompilerIdOBJC OBJC)
+
+foreach(v
+    CMAKE_OBJC_COMPILER
+    CMAKE_OBJC_COMPILER_ID
+    CMAKE_OBJC_COMPILER_VERSION
+    )
+  if(${v})
+    message(STATUS "${v}=[${${v}}]")
+  else()
+    message(SEND_ERROR "${v} not set!")
+  endif()
+endforeach()
diff --git a/Tests/Objective-C/c-file-extension-test/CMakeLists.txt b/Tests/Objective-C/c-file-extension-test/CMakeLists.txt
new file mode 100644
index 0000000..e091448
--- /dev/null
+++ b/Tests/Objective-C/c-file-extension-test/CMakeLists.txt
@@ -0,0 +1,5 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(c-file-extension-test C)
+
+add_executable(c-file-extension-test main.m)
diff --git a/Tests/Objective-C/c-file-extension-test/main.m b/Tests/Objective-C/c-file-extension-test/main.m
new file mode 100644
index 0000000..1c159a9
--- /dev/null
+++ b/Tests/Objective-C/c-file-extension-test/main.m
@@ -0,0 +1,8 @@
+#ifndef __OBJC__
+#  error "Compiler cannot compile Objective-C"
+#endif
+
+int main()
+{
+  return 0;
+}
diff --git a/Tests/Objective-C/objc-file-extension-test/CMakeLists.txt b/Tests/Objective-C/objc-file-extension-test/CMakeLists.txt
new file mode 100644
index 0000000..27e88be
--- /dev/null
+++ b/Tests/Objective-C/objc-file-extension-test/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 3.15)
+
+project(objc-file-extension-test OBJC CXX)
+
+add_executable(objc-file-extension-test main.m)
+target_link_libraries(objc-file-extension-test "-framework Foundation")
diff --git a/Tests/Objective-C/objc-file-extension-test/main.m b/Tests/Objective-C/objc-file-extension-test/main.m
new file mode 100644
index 0000000..2ec3917
--- /dev/null
+++ b/Tests/Objective-C/objc-file-extension-test/main.m
@@ -0,0 +1,12 @@
+#ifndef __OBJC__
+#  error "Compiler is not an Objective-C compiler."
+#endif
+
+#import <Foundation/Foundation.h>
+
+int main()
+{
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+  [pool release];
+  return 0;
+}
diff --git a/Tests/Objective-C/simple-build-test/CMakeLists.txt b/Tests/Objective-C/simple-build-test/CMakeLists.txt
new file mode 100644
index 0000000..5ab46ac
--- /dev/null
+++ b/Tests/Objective-C/simple-build-test/CMakeLists.txt
@@ -0,0 +1,11 @@
+cmake_minimum_required(VERSION 3.15)
+
+set(CMAKE_MACOSX_RPATH OFF)
+
+project(simple-build-test OBJC)
+
+add_library(foo SHARED foo.m)
+target_link_libraries(foo "-framework Foundation")
+
+add_executable(simple-build-test main.m)
+target_link_libraries(simple-build-test "-framework Foundation" foo)
diff --git a/Tests/Objective-C/simple-build-test/foo.h b/Tests/Objective-C/simple-build-test/foo.h
new file mode 100644
index 0000000..b3fb084
--- /dev/null
+++ b/Tests/Objective-C/simple-build-test/foo.h
@@ -0,0 +1,9 @@
+#import <Foundation/Foundation.h>
+
+ at interface Foo : NSObject {
+  NSNumber* age;
+}
+
+ at property (nonatomic, retain) NSNumber* age;
+
+ at end
diff --git a/Tests/Objective-C/simple-build-test/foo.m b/Tests/Objective-C/simple-build-test/foo.m
new file mode 100644
index 0000000..2d452a8
--- /dev/null
+++ b/Tests/Objective-C/simple-build-test/foo.m
@@ -0,0 +1,7 @@
+#import "foo.h"
+
+ at implementation Foo
+
+ at synthesize age;
+
+ at end
diff --git a/Tests/Objective-C/simple-build-test/main.m b/Tests/Objective-C/simple-build-test/main.m
new file mode 100644
index 0000000..970d554
--- /dev/null
+++ b/Tests/Objective-C/simple-build-test/main.m
@@ -0,0 +1,12 @@
+#import <Foundation/Foundation.h>
+#import "foo.h"
+
+int main(int argc, char **argv)
+{
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+  Foo *theFoo = [[Foo alloc] init];
+  theFoo.age = [NSNumber numberWithInt:argc];
+  NSLog(@"%d\n",[theFoo.age intValue]);
+  [pool release];
+  return 0;
+}
diff --git a/Tests/TryCompile/CMakeLists.txt b/Tests/TryCompile/CMakeLists.txt
index 54e96a2..8fd8090 100644
--- a/Tests/TryCompile/CMakeLists.txt
+++ b/Tests/TryCompile/CMakeLists.txt
@@ -1,5 +1,5 @@
 cmake_minimum_required (VERSION 2.6)
-project(TryCompile)
+project(TryCompile OBJC C CXX)
 
 macro(TEST_ASSERT value msg)
   if (NOT ${value})
@@ -313,6 +313,34 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
   TEST_ASSERT(C_STRICT_PROTOTYPES "CHECK_C_COMPILER_FLAG failed -Werror -Wstrict-prototypes")
 endif()
 
+#########################################################################
+#
+# Test that the CHECK_OBJCC_SOURCE_COMPILES, CHECK_OBJC_SOURCE_RUNS
+# macros work.
+
+include(CheckOBJCSourceCompiles)
+include(CheckOBJCSourceRuns)
+
+CHECK_OBJC_SOURCE_COMPILES("I don't build in Objective-C" OBJC_BUILD_SHOULD_FAIL)
+CHECK_OBJC_SOURCE_COMPILES("int main() { return 0; }" SIMPLE_OBJC_BUILD_SHOULD_WORK)
+
+TEST_FAIL(OBJC_BUILD_SHOULD_FAIL "CHECK_OBJC_SOURCE_COMPILES() succeeded, but should have failed")
+TEST_ASSERT(SIMPLE_OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
+
+set(CMAKE_REQUIRED_LIBRARIES "-framework Foundation")
+
+CHECK_OBJC_SOURCE_COMPILES("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_BUILD_SHOULD_WORK)
+CHECK_OBJC_SOURCE_RUNS("int main() { return 2; }" SIMPLE_OBJC_RUN_SHOULD_FAIL)
+CHECK_OBJC_SOURCE_RUNS("int main() { return 0; }" SIMPLE_OBJC_RUN_SHOULD_WORK)
+CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 2;\n}\n" OBJC_RUN_SHOULD_FAIL)
+CHECK_OBJC_SOURCE_RUNS("#import <Foundation/Foundation.h>\nint main()\n{\nNSObject *foo;\nreturn 0;\n}\n" OBJC_RUN_SHOULD_WORK)
+
+TEST_ASSERT(OBJC_BUILD_SHOULD_WORK "CHECK_OBJC_SOURCE_COMPILES() failed, but should have succeeded")
+TEST_FAIL(SIMPLE_OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURC_RUNS() succeeds, but should have failed")
+TEST_ASSERT(SIMPLE_OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
+TEST_FAIL(OBJC_RUN_SHOULD_FAIL "CHECK_OBJC_SOURCE_RUNS() succeeds, but should have failed")
+TEST_ASSERT(OBJC_RUN_SHOULD_WORK "CHECK_OBJC_SOURCE_RUNS() failed, but should have succeeded")
+
 #######################################################################
 #
 # also test that the check_prototype_definition macro works

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=156b56480a786db4d967bde5eb6d5edee56a27d0
commit 156b56480a786db4d967bde5eb6d5edee56a27d0
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Fri Sep 27 13:06:56 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Fri Sep 27 14:15:00 2019 -0400

    Makefiles: Revert "Make build root targets ... recursive"
    
    Revert the main logic change from commit 827da1119e (Makefiles: Make
    build root targets "all", "clean" and "preinstall" recursive,
    2019-05-17, v3.15.0-rc1~96^2~2) for the "all" and "preinstall" targets.
    
    The commit cleaned up the Makefile generator to use the same logic for
    the "all" target in the top-level directory as for subdirectories.  It
    exposed a long-existing bug that caused the "all" target in a
    subdirectory to include the "all" targets from sub-subdirectories even
    if they are marked `EXCLUDE_FROM_ALL`.  The `Tests/SubDir` test should
    fail but the problem is currently covered up by another bug introduced
    by commit dc6888573d (Pass EXCLUDE_FROM_ALL from directory to targets,
    2019-01-15, v3.14.0-rc1~83^2) that causes the "all" targets in
    `EXCLUDE_FROM_ALL` subdirectories to be empty.
    
    Revert the top-level "all" and "preinstall" targets to the old approach
    to prepare to fix the latter bug without exposing the long-existing bug
    at the top-level.  Leave the "clean" target in the new approach because
    it does not honor `EXCLUDE_FROM_ALL` anyway.
    
    Issue: #19753

diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index aa584ad..c636334 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -232,6 +232,14 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
     depends.push_back(this->EmptyRuleHackDepends);
   }
 
+  // Write and empty all:
+  lg->WriteMakeRule(makefileStream, "The main recursive all target", "all",
+                    depends, no_commands, true);
+
+  // Write an empty preinstall:
+  lg->WriteMakeRule(makefileStream, "The main recursive preinstall target",
+                    "preinstall", depends, no_commands, true);
+
   // Write out the "special" stuff
   lg->WriteSpecialTargetsTop(makefileStream);
 
@@ -473,8 +481,13 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
     ruleFileStream << "\n\n";
   }
 
-  // Write directory-level rules for "all".
-  this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
+  if (!lg->IsRootMakefile()) {
+    // Write directory-level rules for "all".
+    this->WriteDirectoryRule2(ruleFileStream, lg, "all", true, false);
+
+    // Write directory-level rules for "preinstall".
+    this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
+  }
 
   // Write directory-level rules for "clean".
   {
@@ -482,9 +495,6 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
     lg->AppendDirectoryCleanCommand(cmds);
     this->WriteDirectoryRule2(ruleFileStream, lg, "clean", false, false, cmds);
   }
-
-  // Write directory-level rules for "preinstall".
-  this->WriteDirectoryRule2(ruleFileStream, lg, "preinstall", true, true);
 }
 
 std::vector<cmGlobalGenerator::GeneratedMakeCommand>
@@ -707,6 +717,15 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
       lg->WriteMakeRule(ruleFileStream, "All Build rule for target.",
                         localName, depends, commands, true);
 
+      // add the all/all dependency
+      if (!this->IsExcluded(gtarget)) {
+        depends.clear();
+        depends.push_back(localName);
+        commands.clear();
+        lg->WriteMakeRule(ruleFileStream, "Include target in all.", "all",
+                          depends, commands, true);
+      }
+
       // Write the rule.
       commands.clear();
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=60473cc660cc37c922b0ff93112deeb34d51f2ca
commit 60473cc660cc37c922b0ff93112deeb34d51f2ca
Author:     Marc Chevrier <marc.chevrier at gmail.com>
AuthorDate: Fri Sep 27 12:20:15 2019 +0200
Commit:     Marc Chevrier <marc.chevrier at gmail.com>
CommitDate: Fri Sep 27 16:04:54 2019 +0200

    FPHSA: add capability to specify message explaining reason of failure
    
    Fixes: #19660

diff --git a/Help/release/dev/FPHSA-reason-failure-message.rst b/Help/release/dev/FPHSA-reason-failure-message.rst
new file mode 100644
index 0000000..419c3ba
--- /dev/null
+++ b/Help/release/dev/FPHSA-reason-failure-message.rst
@@ -0,0 +1,5 @@
+FPHSA-reason-failure-message
+----------------------------
+
+* Modules :module:`FindPackageHandleStandardArgs` gains the capability to
+  specify a message giving the reason for the failure.
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index a2999fc..d824ee8 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -27,6 +27,7 @@ valid filepaths.
       [VERSION_VAR <version-var>]
       [HANDLE_COMPONENTS]
       [CONFIG_MODE]
+      [REASON_FAILURE_MESSAGE <reason-failure-message>]
       [FAIL_MESSAGE <custom-failure-message>]
       )
 
@@ -81,6 +82,10 @@ valid filepaths.
     will automatically check whether the package configuration file
     was found.
 
+  ``REASON_FAILURE_MESSAGE <reason-failure-message>``
+    Specify a custom message of the reason for the failure which will be
+    appended to the default generated message.
+
   ``FAIL_MESSAGE <custom-failure-message>``
     Specify a custom failure message instead of using the default
     generated message.  Not recommended.
@@ -133,11 +138,15 @@ include(${CMAKE_CURRENT_LIST_DIR}/FindPackageMessage.cmake)
 
 # internal helper macro
 macro(_FPHSA_FAILURE_MESSAGE _msg)
+  set (__msg "${_msg}")
+  if (FPHSA_REASON_FAILURE_MESSAGE)
+    string(APPEND __msg "\n    Reason given by package: ${FPHSA_REASON_FAILURE_MESSAGE}\n")
+  endif()
   if (${_NAME}_FIND_REQUIRED)
-    message(FATAL_ERROR "${_msg}")
+    message(FATAL_ERROR "${__msg}")
   else ()
     if (NOT ${_NAME}_FIND_QUIETLY)
-      message(STATUS "${_msg}")
+      message(STATUS "${__msg}")
     endif ()
   endif ()
 endmacro()
@@ -158,12 +167,18 @@ macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
       foreach(currentConfigIndex RANGE ${configsCount})
         list(GET ${_NAME}_CONSIDERED_CONFIGS ${currentConfigIndex} filename)
         list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
-        string(APPEND configsText "    ${filename} (version ${version})\n")
+        string(APPEND configsText "\n    ${filename} (version ${version})")
       endforeach()
       if (${_NAME}_NOT_FOUND_MESSAGE)
-        string(APPEND configsText "    Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
+        if (FPHSA_REASON_FAILURE_MESSAGE)
+          string(PREPEND FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}\n    ")
+        else()
+          set(FPHSA_REASON_FAILURE_MESSAGE "${${_NAME}_NOT_FOUND_MESSAGE}")
+        endif()
+      else()
+        string(APPEND configsText "\n")
       endif()
-      _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
+      _FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:${configsText}")
 
     else()
       # Simple case: No Config-file was found at all:
@@ -177,7 +192,7 @@ function(FIND_PACKAGE_HANDLE_STANDARD_ARGS _NAME _FIRST_ARG)
 
 # Set up the arguments for `cmake_parse_arguments`.
   set(options  CONFIG_MODE  HANDLE_COMPONENTS)
-  set(oneValueArgs  FAIL_MESSAGE  VERSION_VAR  FOUND_VAR)
+  set(oneValueArgs  FAIL_MESSAGE  REASON_FAILURE_MESSAGE VERSION_VAR  FOUND_VAR)
   set(multiValueArgs REQUIRED_VARS)
 
 # Check whether we are in 'simple' or 'extended' mode:
diff --git a/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake b/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake
new file mode 100644
index 0000000..e25db1a
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake
@@ -0,0 +1 @@
+# pseudo config module
diff --git a/Tests/RunCMake/FPHSA/CustomMessageConfigVersion.cmake b/Tests/RunCMake/FPHSA/CustomMessageConfigVersion.cmake
new file mode 100644
index 0000000..b7c9e18
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/CustomMessageConfigVersion.cmake
@@ -0,0 +1,4 @@
+# pseudo find_module
+
+set (PACKAGE_VERSION 2)
+set (PACKAGE_VERSION_UNSUITABLE TRUE)
diff --git a/Tests/RunCMake/FPHSA/FindCustomMessage.cmake b/Tests/RunCMake/FPHSA/FindCustomMessage.cmake
new file mode 100644
index 0000000..4d67db8
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/FindCustomMessage.cmake
@@ -0,0 +1,17 @@
+# pseudo find_module
+
+if (REASON_FAILURE_MESSAGE)
+  list (PREPEND REASON_FAILURE_MESSAGE "REASON_FAILURE_MESSAGE")
+endif()
+
+include(FindPackageHandleStandardArgs)
+
+if (CONFIG_MODE)
+  find_package (CustomMessage QUIET CONFIG HINTS "${CMAKE_MODULE_PATH}")
+  find_package_handle_standard_args(CustomMessage CONFIG_MODE
+                                                  ${REASON_FAILURE_MESSAGE})
+else()
+  find_package_handle_standard_args(CustomMessage REQUIRED_VARS FOOBAR
+                                                  VERSION_VAR CustomMessage_VERSION
+                                                  ${REASON_FAILURE_MESSAGE})
+endif()
diff --git a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
index dd73cd4..f3e6c3e 100644
--- a/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
+++ b/Tests/RunCMake/FPHSA/RunCMakeTest.cmake
@@ -39,3 +39,10 @@ unset(RunCMake_DEFAULT_stderr)
 # check if searching for a version 0 works
 list(APPEND RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DPseudo_VERSION=0")
 run_cmake(exact_0_matching)
+
+# check custom error message
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DCustomMessage_VERSION=1.2.3.4")
+run_cmake(custom_message_1)
+set(RunCMake_TEST_OPTIONS "-DCMAKE_MODULE_PATH=${CMAKE_CURRENT_LIST_DIR}" "-DCONFIG_MODE=TRUE")
+run_cmake(custom_message_2)
+run_cmake(custom_message_3)
diff --git a/Tests/RunCMake/FPHSA/custom_message_1-result.txt b/Tests/RunCMake/FPHSA/custom_message_1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/FPHSA/custom_message_1-stderr.txt b/Tests/RunCMake/FPHSA/custom_message_1-stderr.txt
new file mode 100644
index 0000000..992fe39
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_1-stderr.txt
@@ -0,0 +1,7 @@
+^CMake Error at .+/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\):
+  Could NOT find CustomMessage \(missing: FOOBAR\) \(found suitable version
+  "1\.2\.3\.4", minimum required is "1\.2"\)
+
+      Reason given by package: Reason Failure
+
+Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/FPHSA/custom_message_1.cmake b/Tests/RunCMake/FPHSA/custom_message_1.cmake
new file mode 100644
index 0000000..330de50
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_1.cmake
@@ -0,0 +1,4 @@
+
+set (REASON_FAILURE_MESSAGE "Reason Failure")
+
+find_package(CustomMessage 1.2 REQUIRED)
diff --git a/Tests/RunCMake/FPHSA/custom_message_2-result.txt b/Tests/RunCMake/FPHSA/custom_message_2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/FPHSA/custom_message_2-stderr.txt b/Tests/RunCMake/FPHSA/custom_message_2-stderr.txt
new file mode 100644
index 0000000..4940752
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_2-stderr.txt
@@ -0,0 +1,8 @@
+^CMake Error at .+/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\):
+  Could NOT find CustomMessage \(Required is at least version "1\.2"\), checked
+  the following files:
+
+      .+/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake \(version 2\)
+      Reason given by package: Not Found Message
+
+Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/FPHSA/custom_message_2.cmake b/Tests/RunCMake/FPHSA/custom_message_2.cmake
new file mode 100644
index 0000000..a3f2d96
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_2.cmake
@@ -0,0 +1,5 @@
+
+unset (REASON_FAILURE_MESSAGE)
+set (CustomMessage_NOT_FOUND_MESSAGE "Not Found Message")
+
+find_package(CustomMessage 1.2 REQUIRED)
diff --git a/Tests/RunCMake/FPHSA/custom_message_3-result.txt b/Tests/RunCMake/FPHSA/custom_message_3-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/FPHSA/custom_message_3-stderr.txt b/Tests/RunCMake/FPHSA/custom_message_3-stderr.txt
new file mode 100644
index 0000000..dc55843
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_3-stderr.txt
@@ -0,0 +1,9 @@
+^CMake Error at .+/Modules/FindPackageHandleStandardArgs.cmake:[0-9]+ \(message\):
+  Could NOT find CustomMessage \(Required is at least version "1\.2"\), checked
+  the following files:
+
+      .+/Tests/RunCMake/FPHSA/CustomMessageConfig.cmake \(version 2\)
+      Reason given by package: Not Found Message
+      Reason Failure
+
+Call Stack \(most recent call first\):
diff --git a/Tests/RunCMake/FPHSA/custom_message_3.cmake b/Tests/RunCMake/FPHSA/custom_message_3.cmake
new file mode 100644
index 0000000..203e012
--- /dev/null
+++ b/Tests/RunCMake/FPHSA/custom_message_3.cmake
@@ -0,0 +1,5 @@
+
+set (REASON_FAILURE_MESSAGE "Reason Failure")
+set (CustomMessage_NOT_FOUND_MESSAGE "Not Found Message")
+
+find_package(CustomMessage 1.2 REQUIRED)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7d6e08b438a187e89735ae6aad749a14137f34be
commit 7d6e08b438a187e89735ae6aad749a14137f34be
Author:     Tushar Maheshwari <tushar27192 at gmail.com>
AuthorDate: Sun Sep 22 07:24:57 2019 +0530
Commit:     Tushar Maheshwari <tushar27192 at gmail.com>
CommitDate: Fri Sep 27 17:18:16 2019 +0530

    cmCursesMainForm: change Entries to object vector
    
    - Add move constructor and move assignment operator for
    `cmCursesCacheEntryComposite`.
    - Transfer ownership of Entries objects to std::vector.

diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h
index 1ed60c8..a711363 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.h
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h
@@ -25,6 +25,10 @@ public:
   cmCursesCacheEntryComposite& operator=(cmCursesCacheEntryComposite const&) =
     delete;
 
+  cmCursesCacheEntryComposite(cmCursesCacheEntryComposite&&) = default;
+  cmCursesCacheEntryComposite& operator=(cmCursesCacheEntryComposite&&) =
+    default;
+
   const char* GetValue();
 
   friend class cmCursesMainForm;
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 15ccc91..219771b 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -67,11 +67,10 @@ cmCursesMainForm::~cmCursesMainForm()
 // See if a cache entry is in the list of entries in the ui.
 bool cmCursesMainForm::LookForCacheEntry(const std::string& key)
 {
-  return std::any_of(
-    this->Entries.begin(), this->Entries.end(),
-    [&key](std::unique_ptr<cmCursesCacheEntryComposite> const& entry) {
-      return key == entry->Key;
-    });
+  return std::any_of(this->Entries.begin(), this->Entries.end(),
+                     [&key](cmCursesCacheEntryComposite const& entry) {
+                       return key == entry.Key;
+                     });
 }
 
 // Create new cmCursesCacheEntryComposite entries from the cache
@@ -79,7 +78,7 @@ void cmCursesMainForm::InitializeUI()
 {
   // Create a vector of cmCursesCacheEntryComposite's
   // which contain labels, entries and new entry markers
-  std::vector<std::unique_ptr<cmCursesCacheEntryComposite>> newEntries;
+  std::vector<cmCursesCacheEntryComposite> newEntries;
   std::vector<std::string> cacheKeys =
     this->CMakeInstance->GetState()->GetCacheEntryKeys();
   newEntries.reserve(cacheKeys.size());
@@ -101,9 +100,8 @@ void cmCursesMainForm::InitializeUI()
   if (count == 0) {
     // If cache is empty, display a label saying so and a
     // dummy entry widget (does not respond to input)
-    std::unique_ptr<cmCursesCacheEntryComposite> comp =
-      cm::make_unique<cmCursesCacheEntryComposite>("EMPTY CACHE", 30, 30);
-    comp->Entry = cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
+    cmCursesCacheEntryComposite comp("EMPTY CACHE", 30, 30);
+    comp.Entry = cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
     newEntries.emplace_back(std::move(comp));
   } else {
     // Create the composites.
@@ -118,8 +116,8 @@ void cmCursesMainForm::InitializeUI()
       }
 
       if (!this->LookForCacheEntry(key)) {
-        newEntries.emplace_back(cm::make_unique<cmCursesCacheEntryComposite>(
-          key, this->CMakeInstance->GetState(), true, 30, entrywidth));
+        newEntries.emplace_back(key, this->CMakeInstance->GetState(), true, 30,
+                                entrywidth);
         this->OkToGenerate = false;
       }
     }
@@ -134,8 +132,8 @@ void cmCursesMainForm::InitializeUI()
       }
 
       if (this->LookForCacheEntry(key)) {
-        newEntries.emplace_back(cm::make_unique<cmCursesCacheEntryComposite>(
-          key, this->CMakeInstance->GetState(), false, 30, entrywidth));
+        newEntries.emplace_back(key, this->CMakeInstance->GetState(), false,
+                                30, entrywidth);
       }
     }
   }
@@ -161,12 +159,12 @@ void cmCursesMainForm::RePost()
   } else {
     // If normal mode, count only non-advanced entries
     this->NumberOfVisibleEntries = 0;
-    for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
+    for (cmCursesCacheEntryComposite& entry : this->Entries) {
       const char* existingValue =
-        this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
+        this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
       bool advanced =
         this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
-          entry->GetValue(), "ADVANCED");
+          entry.GetValue(), "ADVANCED");
       if (!existingValue || (!this->AdvancedMode && advanced)) {
         continue;
       }
@@ -182,22 +180,22 @@ void cmCursesMainForm::RePost()
   this->Fields.reserve(3 * this->NumberOfVisibleEntries + 1);
 
   // Assign fields
-  for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
+  for (cmCursesCacheEntryComposite& entry : this->Entries) {
     const char* existingValue =
-      this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
+      this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
     bool advanced =
       this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
-        entry->GetValue(), "ADVANCED");
+        entry.GetValue(), "ADVANCED");
     if (!existingValue || (!this->AdvancedMode && advanced)) {
       continue;
     }
-    this->Fields.push_back(entry->Label->Field);
-    this->Fields.push_back(entry->IsNewLabel->Field);
-    this->Fields.push_back(entry->Entry->Field);
+    this->Fields.push_back(entry.Label->Field);
+    this->Fields.push_back(entry.IsNewLabel->Field);
+    this->Fields.push_back(entry.Entry->Field);
   }
   // if no cache entries there should still be one dummy field
   if (this->Fields.empty()) {
-    const auto& front = *this->Entries.front();
+    const auto& front = this->Entries.front();
     this->Fields.push_back(front.Label->Field);
     this->Fields.push_back(front.IsNewLabel->Field);
     this->Fields.push_back(front.Entry->Field);
@@ -241,12 +239,12 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
   } else {
     // If normal, display only non-advanced entries
     this->NumberOfVisibleEntries = 0;
-    for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
+    for (cmCursesCacheEntryComposite& entry : this->Entries) {
       const char* existingValue =
-        this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
+        this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
       bool advanced =
         this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
-          entry->GetValue(), "ADVANCED");
+          entry.GetValue(), "ADVANCED");
       if (!existingValue || (!this->AdvancedMode && advanced)) {
         continue;
       }
@@ -259,12 +257,12 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
   if (height > 0) {
     bool isNewPage;
     int i = 0;
-    for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
+    for (cmCursesCacheEntryComposite& entry : this->Entries) {
       const char* existingValue =
-        this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
+        this->CMakeInstance->GetState()->GetCacheEntryValue(entry.GetValue());
       bool advanced =
         this->CMakeInstance->GetState()->GetCacheEntryPropertyAsBool(
-          entry->GetValue(), "ADVANCED");
+          entry.GetValue(), "ADVANCED");
       if (!existingValue || (!this->AdvancedMode && advanced)) {
         continue;
       }
@@ -275,10 +273,10 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
       if (isNewPage) {
         this->NumberOfPages++;
       }
-      entry->Label->Move(left, top + row - 1, isNewPage);
-      entry->IsNewLabel->Move(left + 32, top + row - 1, false);
-      entry->Entry->Move(left + 33, top + row - 1, false);
-      entry->Entry->SetPage(this->NumberOfPages);
+      entry.Label->Move(left, top + row - 1, isNewPage);
+      entry.IsNewLabel->Move(left + 32, top + row - 1, false);
+      entry.Entry->Move(left + 33, top + row - 1, false);
+      entry.Entry->SetPage(this->NumberOfPages);
       i++;
     }
   }
@@ -630,12 +628,12 @@ void cmCursesMainForm::RemoveEntry(const char* value)
     return;
   }
 
-  auto removeIt = std::find_if(
-    this->Entries.begin(), this->Entries.end(),
-    [value](std::unique_ptr<cmCursesCacheEntryComposite>& entry) -> bool {
-      const char* val = entry->GetValue();
-      return val != nullptr && !strcmp(value, val);
-    });
+  auto removeIt =
+    std::find_if(this->Entries.begin(), this->Entries.end(),
+                 [value](cmCursesCacheEntryComposite& entry) -> bool {
+                   const char* val = entry.GetValue();
+                   return val != nullptr && !strcmp(value, val);
+                 });
 
   if (removeIt != this->Entries.end()) {
     this->CMakeInstance->UnwatchUnusedCli(value);
@@ -646,13 +644,13 @@ void cmCursesMainForm::RemoveEntry(const char* value)
 // copy from the list box to the cache manager
 void cmCursesMainForm::FillCacheManagerFromUI()
 {
-  for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
-    const std::string& cacheKey = entry->Key;
+  for (cmCursesCacheEntryComposite& entry : this->Entries) {
+    const std::string& cacheKey = entry.Key;
     const char* existingValue =
       this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey);
     if (existingValue) {
       std::string oldValue = existingValue;
-      std::string newValue = entry->Entry->GetValue();
+      std::string newValue = entry.Entry->GetValue();
       std::string fixedOldValue;
       std::string fixedNewValue;
       cmStateEnums::CacheEntryType t =
@@ -943,12 +941,12 @@ void cmCursesMainForm::HandleInput()
             // make the next or prev. current field after deletion
             auto nextEntryIt = std::find_if(
               this->Entries.begin(), this->Entries.end(),
-              [&nextVal](std::unique_ptr<cmCursesCacheEntryComposite>& entry) {
-                return nextVal == entry->Key;
+              [&nextVal](cmCursesCacheEntryComposite const& entry) {
+                return nextVal == entry.Key;
               });
 
             if (nextEntryIt != this->Entries.end()) {
-              set_current_field(this->Form, (*nextEntryIt)->Entry->Field);
+              set_current_field(this->Form, nextEntryIt->Entry->Field);
             }
           }
         }
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index 9a83c30..48d1791 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include "cmCursesCacheEntryComposite.h"
 #include "cmCursesForm.h"
 #include "cmCursesStandardIncludes.h"
 #include "cmStateTypes.h"
@@ -14,7 +15,6 @@
 #include <string>
 #include <vector>
 
-class cmCursesCacheEntryComposite;
 class cmake;
 
 /** \class cmCursesMainForm
@@ -123,7 +123,7 @@ protected:
   void JumpToCacheEntry(const char* str);
 
   // Copies of cache entries stored in the user interface
-  std::vector<std::unique_ptr<cmCursesCacheEntryComposite>> Entries;
+  std::vector<cmCursesCacheEntryComposite> Entries;
   // Errors produced during last run of cmake
   std::vector<std::string> Errors;
   // Command line arguments to be passed to cmake each time

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0833486d62e8ed3ae9f0219f9924c4e78d74f781
commit 0833486d62e8ed3ae9f0219f9924c4e78d74f781
Author:     Tushar Maheshwari <tushar27192 at gmail.com>
AuthorDate: Sat Sep 21 19:47:23 2019 +0530
Commit:     Tushar Maheshwari <tushar27192 at gmail.com>
CommitDate: Fri Sep 27 17:18:16 2019 +0530

    cmCursesStringWidget: remove manual delete
    
    - Relpace `char*` operations with `std::string`

diff --git a/Source/CursesDialog/cmCursesStringWidget.cxx b/Source/CursesDialog/cmCursesStringWidget.cxx
index 3fc1858..d3a05e8 100644
--- a/Source/CursesDialog/cmCursesStringWidget.cxx
+++ b/Source/CursesDialog/cmCursesStringWidget.cxx
@@ -9,7 +9,6 @@
 #include "cmStateTypes.h"
 
 #include <cstdio>
-#include <cstring>
 
 inline int ctrl(int z)
 {
@@ -35,13 +34,13 @@ void cmCursesStringWidget::OnTab(cmCursesMainForm* /*unused*/,
 
 void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW* /*unused*/)
 {
-  FORM* form = fm->GetForm();
   if (this->InEdit) {
     cmCursesForm::LogMessage("String widget leaving edit.");
     this->InEdit = false;
     fm->PrintKeys();
-    delete[] this->OriginalString;
+    this->OriginalString.clear();
     // trick to force forms to update the field buffer
+    FORM* form = fm->GetForm();
     form_driver(form, REQ_NEXT_FIELD);
     form_driver(form, REQ_PREV_FIELD);
     this->Done = true;
@@ -49,9 +48,7 @@ void cmCursesStringWidget::OnReturn(cmCursesMainForm* fm, WINDOW* /*unused*/)
     cmCursesForm::LogMessage("String widget entering edit.");
     this->InEdit = true;
     fm->PrintKeys();
-    char* buf = field_buffer(this->Field, 0);
-    this->OriginalString = new char[strlen(buf) + 1];
-    strcpy(this->OriginalString, buf);
+    this->OriginalString = field_buffer(this->Field, 0);
   }
 }
 
@@ -75,7 +72,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
     return false;
   }
 
-  this->OriginalString = nullptr;
+  this->OriginalString.clear();
   this->Done = false;
 
   char debugMessage[128];
@@ -113,7 +110,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
                key == ctrl('p') || key == KEY_NPAGE || key == ctrl('d') ||
                key == KEY_PPAGE || key == ctrl('u')) {
       this->InEdit = false;
-      delete[] this->OriginalString;
+      this->OriginalString.clear();
       // trick to force forms to update the field buffer
       form_driver(form, REQ_NEXT_FIELD);
       form_driver(form, REQ_PREV_FIELD);
@@ -125,7 +122,7 @@ bool cmCursesStringWidget::HandleInput(int& key, cmCursesMainForm* fm,
         this->InEdit = false;
         fm->PrintKeys();
         this->SetString(this->OriginalString);
-        delete[] this->OriginalString;
+        this->OriginalString.clear();
         touchwin(w);
         wrefresh(w);
         return true;
@@ -188,23 +185,18 @@ bool cmCursesStringWidget::PrintKeys()
   }
   if (this->InEdit) {
     char fmt_s[] = "%s";
-    char firstLine[512];
     // Clean the toolbar
-    memset(firstLine, ' ', sizeof(firstLine));
-    firstLine[511] = '\0';
     curses_move(y - 4, 0);
-    printw(fmt_s, firstLine);
-    curses_move(y - 3, 0);
-    printw(fmt_s, firstLine);
-    curses_move(y - 2, 0);
-    printw(fmt_s, firstLine);
-    curses_move(y - 1, 0);
-    printw(fmt_s, firstLine);
-
+    clrtoeol();
     curses_move(y - 3, 0);
     printw(fmt_s, "Editing option, press [enter] to confirm");
+    clrtoeol();
     curses_move(y - 2, 0);
     printw(fmt_s, "                press [esc] to cancel");
+    clrtoeol();
+    curses_move(y - 1, 0);
+    clrtoeol();
+
     return true;
   }
   return false;
diff --git a/Source/CursesDialog/cmCursesStringWidget.h b/Source/CursesDialog/cmCursesStringWidget.h
index 021515b..a41f0e8 100644
--- a/Source/CursesDialog/cmCursesStringWidget.h
+++ b/Source/CursesDialog/cmCursesStringWidget.h
@@ -23,9 +23,6 @@ class cmCursesStringWidget : public cmCursesWidget
 public:
   cmCursesStringWidget(int width, int height, int left, int top);
 
-  cmCursesStringWidget(cmCursesStringWidget const&) = delete;
-  cmCursesStringWidget& operator=(cmCursesStringWidget const&) = delete;
-
   /**
    * Handle user input. Called by the container of this widget
    * when this widget has focus. Returns true if the input was
@@ -65,7 +62,7 @@ public:
 protected:
   // true if the widget is in edit mode
   bool InEdit;
-  char* OriginalString;
+  std::string OriginalString;
   bool Done;
 };
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cf01d3d2bd649ab1157641b3212a360b06db747f
commit cf01d3d2bd649ab1157641b3212a360b06db747f
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Thu Sep 26 14:47:53 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Sep 26 14:58:26 2019 -0400

    Tests: Clarify target names in RunCMake.add_subdirectory ExcludeFromAll
    
    Rename the `baz` target to `subinc` to clarify that its role is to be
    included even though it is in an otherwise excluded subdirectory.

diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
index cc31428..16f39d9 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
@@ -9,5 +9,5 @@ file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.c
 set(main_exe \"$<TARGET_FILE:main>\")
 set(foo_lib \"$<TARGET_FILE:foo>\")
 set(bar_lib \"$<TARGET_FILE:bar>\")
-set(baz_lib \"$<TARGET_FILE:baz>\")
+set(subinc_lib \"$<TARGET_FILE:subinc>\")
 ")
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
index 99add23..9d7922f 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
@@ -1,8 +1,7 @@
 add_library(bar STATIC bar.cpp)
 
 add_library(foo STATIC foo.cpp)
-
-add_library(baz STATIC foo.cpp)
-set_target_properties(baz PROPERTIES EXCLUDE_FROM_ALL OFF)
-
 target_include_directories(foo PUBLIC .)
+
+add_library(subinc STATIC subinc.cpp)
+set_target_properties(subinc PROPERTIES EXCLUDE_FROM_ALL OFF)
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
index 2a0179e..56a8abd 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
@@ -6,7 +6,7 @@ if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
 
   foreach(file
       "${foo_lib}"
-      "${baz_lib}"
+      "${subinc_lib}"
       "${main_exe}"
       )
     if(NOT EXISTS "${file}")
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/subinc.cpp b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/subinc.cpp
new file mode 100644
index 0000000..e9faacd
--- /dev/null
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/subinc.cpp
@@ -0,0 +1,4 @@
+int subinc()
+{
+  return 0;
+}

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=21442d72a44c2bd732f2ff19ed89ce488854d25d
commit 21442d72a44c2bd732f2ff19ed89ce488854d25d
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Sep 24 12:39:33 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Sep 26 14:57:40 2019 -0400

    Tests: Revise RunCMake.add_subdirectory ExcludeFromAll to avoid globbing
    
    Also simplify the clean step.

diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
index f686005..cc31428 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll.cmake
@@ -4,3 +4,10 @@ add_subdirectory(ExcludeFromAll EXCLUDE_FROM_ALL)
 
 add_executable(main main.cpp)
 target_link_libraries(main PRIVATE foo)
+
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake CONTENT "
+set(main_exe \"$<TARGET_FILE:main>\")
+set(foo_lib \"$<TARGET_FILE:foo>\")
+set(bar_lib \"$<TARGET_FILE:bar>\")
+set(baz_lib \"$<TARGET_FILE:baz>\")
+")
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
index 9e6462b..99add23 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/CMakeLists.txt
@@ -5,16 +5,4 @@ add_library(foo STATIC foo.cpp)
 add_library(baz STATIC foo.cpp)
 set_target_properties(baz PROPERTIES EXCLUDE_FROM_ALL OFF)
 
-file(GENERATE
-  OUTPUT "${CMAKE_BINARY_DIR}/main.txt"
-  CONTENT "$<TARGET_FILE_NAME:main>")
-
-file(GENERATE
-  OUTPUT "${CMAKE_BINARY_DIR}/bar.txt"
-  CONTENT "$<TARGET_FILE_NAME:bar>")
-
-file(GENERATE
-  OUTPUT "${CMAKE_BINARY_DIR}/baz.txt"
-  CONTENT "$<TARGET_FILE_NAME:baz>")
-
 target_include_directories(foo PUBLIC .)
diff --git a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
index 14ec482..2a0179e 100644
--- a/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
+++ b/Tests/RunCMake/add_subdirectory/ExcludeFromAll/check.cmake
@@ -1,44 +1,31 @@
-# Use globbing to check if exes / libs were built because determining
-# exactly where these files will live inside a CMake -P script is
-# pretty challenging.
-
-file(READ "${RunCMake_TEST_BINARY_DIR}/main.txt" main_exe)
-file(READ "${RunCMake_TEST_BINARY_DIR}/bar.txt" bar_lib)
-file(READ "${RunCMake_TEST_BINARY_DIR}/baz.txt" baz_lib)
-
-set(found_main FALSE)
-file(GLOB_RECURSE files
-  LIST_DIRECTORIES FALSE
-  RELATIVE "${RunCMake_TEST_BINARY_DIR}"
-  "${RunCMake_TEST_BINARY_DIR}/*")
-foreach (file IN LISTS files)
-  if (file MATCHES "${main_exe}")
-    set(found_main TRUE)
+if(EXISTS ${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
+  include(${RunCMake_TEST_BINARY_DIR}/check-debug.cmake)
+  if(RunCMake_TEST_FAILED)
+    return()
   endif()
-endforeach()
-if (NOT found_main)
-  set(RunCMake_TEST_FAILED "'main' missing from ${RunCMake_TEST_BINARY_DIR}")
-endif()
 
-set(found_bar FALSE)
-set(found_baz FALSE)
-file(GLOB_RECURSE files
-  LIST_DIRECTORIES FALSE
-  RELATIVE "${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll"
-  "${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll/*")
-foreach (file IN LISTS files)
-  if (file MATCHES "${bar_lib}")
-    set(found_bar TRUE)
-  endif()
-  if (file MATCHES "${baz_lib}")
-    set(found_baz TRUE)
-  endif()
-endforeach()
-if (found_bar)
-  set(RunCMake_TEST_FAILED
-    "'bar' was not excluded from ${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll")
-endif()
-if (NOT found_baz)
-  set(RunCMake_TEST_FAILED
-    "'baz' missing from ${RunCMake_TEST_BINARY_DIR}/ExcludeFromAll")
+  foreach(file
+      "${foo_lib}"
+      "${baz_lib}"
+      "${main_exe}"
+      )
+    if(NOT EXISTS "${file}")
+      set(RunCMake_TEST_FAILED
+        "Artifact should exist but is missing:\n  ${file}")
+      return()
+    endif()
+  endforeach()
+  foreach(file
+      "${bar_lib}"
+      )
+    if(EXISTS "${file}")
+      set(RunCMake_TEST_FAILED
+        "Artifact should be missing but exists:\n  ${file}")
+      return()
+    endif()
+  endforeach()
+else()
+  set(RunCMake_TEST_FAILED "
+ '${RunCMake_TEST_BINARY_DIR}/check-debug.cmake' missing
+")
 endif()
diff --git a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
index 781e483..e9ba92f 100644
--- a/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
+++ b/Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake
@@ -27,14 +27,14 @@ run_cmake_install(CMP0082-OLD -DCMP0082_VALUE=OLD)
 run_cmake_install(CMP0082-NEW -DCMP0082_VALUE=NEW)
 
 set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ExcludeFromAll-build)
-set(RunCMake_TEST_NO_CLEAN 1)
-
-file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
-file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
-
+if(NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+  set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+endif()
 run_cmake(ExcludeFromAll)
+set(RunCMake_TEST_NO_CLEAN 1)
 set(RunCMake-check-file ExcludeFromAll/check.cmake)
-run_cmake_command(ExcludeFromAll-build ${CMAKE_COMMAND} --build .)
-
-unset(RunCMake_TEST_BINARY_DIR)
+run_cmake_command(ExcludeFromAll-build ${CMAKE_COMMAND} --build . --config Debug)
+unset(RunCMake-check-file)
 unset(RunCMake_TEST_NO_CLEAN)
+unset(RunCMake_TEST_OPTIONS)
+unset(RunCMake_TEST_BINARY_DIR)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=bc71b253cb372cc6c0ae50406a11b81fe4259559
commit bc71b253cb372cc6c0ae50406a11b81fe4259559
Author:     Tushar Maheshwari <tushar27192 at gmail.com>
AuthorDate: Sat Sep 14 17:27:00 2019 +0530
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Sep 26 11:10:22 2019 -0400

    cmCursesCacheEntryComposite: default destructor

diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
index 8b160a4..561784c 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
@@ -14,7 +14,10 @@
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
+#include <cm/memory>
+
 #include <cassert>
+#include <utility>
 #include <vector>
 
 cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
@@ -23,9 +26,11 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
   , LabelWidth(labelwidth)
   , EntryWidth(entrywidth)
 {
-  this->Label = new cmCursesLabelWidget(this->LabelWidth, 1, 1, 1, key);
-  this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
-  this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
+  this->Label =
+    cm::make_unique<cmCursesLabelWidget>(this->LabelWidth, 1, 1, 1, key);
+  this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, " ");
+  this->Entry =
+    cm::make_unique<cmCursesStringWidget>(this->EntryWidth, 1, 1, 1);
 }
 
 cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
@@ -35,47 +40,51 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
   , LabelWidth(labelwidth)
   , EntryWidth(entrywidth)
 {
-  this->Label = new cmCursesLabelWidget(this->LabelWidth, 1, 1, 1, key);
+  this->Label =
+    cm::make_unique<cmCursesLabelWidget>(this->LabelWidth, 1, 1, 1, key);
   if (isNew) {
-    this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, "*");
+    this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, "*");
   } else {
-    this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
+    this->IsNewLabel = cm::make_unique<cmCursesLabelWidget>(1, 1, 1, 1, " ");
   }
 
-  this->Entry = nullptr;
   const char* value = state->GetCacheEntryValue(key);
   assert(value);
   switch (state->GetCacheEntryType(key)) {
-    case cmStateEnums::BOOL:
-      this->Entry = new cmCursesBoolWidget(this->EntryWidth, 1, 1, 1);
-      if (cmIsOn(value)) {
-        static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(true);
-      } else {
-        static_cast<cmCursesBoolWidget*>(this->Entry)->SetValueAsBool(false);
-      }
+    case cmStateEnums::BOOL: {
+      auto bw = cm::make_unique<cmCursesBoolWidget>(this->EntryWidth, 1, 1, 1);
+      bw->SetValueAsBool(cmIsOn(value));
+      this->Entry = std::move(bw);
       break;
-    case cmStateEnums::PATH:
-      this->Entry = new cmCursesPathWidget(this->EntryWidth, 1, 1, 1);
-      static_cast<cmCursesPathWidget*>(this->Entry)->SetString(value);
+    }
+    case cmStateEnums::PATH: {
+      auto pw = cm::make_unique<cmCursesPathWidget>(this->EntryWidth, 1, 1, 1);
+      pw->SetString(value);
+      this->Entry = std::move(pw);
       break;
-    case cmStateEnums::FILEPATH:
-      this->Entry = new cmCursesFilePathWidget(this->EntryWidth, 1, 1, 1);
-      static_cast<cmCursesFilePathWidget*>(this->Entry)->SetString(value);
+    }
+    case cmStateEnums::FILEPATH: {
+      auto fpw =
+        cm::make_unique<cmCursesFilePathWidget>(this->EntryWidth, 1, 1, 1);
+      fpw->SetString(value);
+      this->Entry = std::move(fpw);
       break;
+    }
     case cmStateEnums::STRING: {
       const char* stringsProp = state->GetCacheEntryProperty(key, "STRINGS");
       if (stringsProp) {
-        cmCursesOptionsWidget* ow =
-          new cmCursesOptionsWidget(this->EntryWidth, 1, 1, 1);
-        this->Entry = ow;
-        std::vector<std::string> options = cmExpandedList(stringsProp);
-        for (auto const& opt : options) {
+        auto ow =
+          cm::make_unique<cmCursesOptionsWidget>(this->EntryWidth, 1, 1, 1);
+        for (std::string const& opt : cmExpandedList(stringsProp)) {
           ow->AddOption(opt);
         }
         ow->SetOption(value);
+        this->Entry = std::move(ow);
       } else {
-        this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
-        static_cast<cmCursesStringWidget*>(this->Entry)->SetString(value);
+        auto sw =
+          cm::make_unique<cmCursesStringWidget>(this->EntryWidth, 1, 1, 1);
+        sw->SetString(value);
+        this->Entry = std::move(sw);
       }
       break;
     }
@@ -88,12 +97,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
   }
 }
 
-cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite()
-{
-  delete this->Label;
-  delete this->IsNewLabel;
-  delete this->Entry;
-}
+cmCursesCacheEntryComposite::~cmCursesCacheEntryComposite() = default;
 
 const char* cmCursesCacheEntryComposite::GetValue()
 {
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h
index b18f076..1ed60c8 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.h
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h
@@ -5,6 +5,7 @@
 
 #include "cmConfigure.h" // IWYU pragma: keep
 
+#include <memory>
 #include <string>
 
 class cmCursesLabelWidget;
@@ -29,9 +30,9 @@ public:
   friend class cmCursesMainForm;
 
 protected:
-  cmCursesLabelWidget* Label;
-  cmCursesLabelWidget* IsNewLabel;
-  cmCursesWidget* Entry;
+  std::unique_ptr<cmCursesLabelWidget> Label;
+  std::unique_ptr<cmCursesLabelWidget> IsNewLabel;
+  std::unique_ptr<cmCursesWidget> Entry;
   std::string Key;
   int LabelWidth;
   int EntryWidth;
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index e754196..15ccc91 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -103,7 +103,7 @@ void cmCursesMainForm::InitializeUI()
     // dummy entry widget (does not respond to input)
     std::unique_ptr<cmCursesCacheEntryComposite> comp =
       cm::make_unique<cmCursesCacheEntryComposite>("EMPTY CACHE", 30, 30);
-    comp->Entry = new cmCursesDummyWidget(1, 1, 1, 1);
+    comp->Entry = cm::make_unique<cmCursesDummyWidget>(1, 1, 1, 1);
     newEntries.emplace_back(std::move(comp));
   } else {
     // Create the composites.

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=36875ff419240a5a60b1b13ff190a5824a8363a5
commit 36875ff419240a5a60b1b13ff190a5824a8363a5
Author:     Tushar Maheshwari <tushar27192 at gmail.com>
AuthorDate: Sun Sep 8 11:22:38 2019 +0530
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Thu Sep 26 11:10:20 2019 -0400

    cmCursesMainForm: cleanup manual allocation

diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
index 47fe84c..8b160a4 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.cxx
@@ -13,7 +13,6 @@
 #include "cmStateTypes.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
-#include "cmake.h"
 
 #include <cassert>
 #include <vector>
@@ -26,12 +25,11 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
 {
   this->Label = new cmCursesLabelWidget(this->LabelWidth, 1, 1, 1, key);
   this->IsNewLabel = new cmCursesLabelWidget(1, 1, 1, 1, " ");
-  this->Entry = nullptr;
   this->Entry = new cmCursesStringWidget(this->EntryWidth, 1, 1, 1);
 }
 
 cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
-  const std::string& key, cmake* cm, bool isNew, int labelwidth,
+  const std::string& key, cmState* state, bool isNew, int labelwidth,
   int entrywidth)
   : Key(key)
   , LabelWidth(labelwidth)
@@ -45,9 +43,9 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
   }
 
   this->Entry = nullptr;
-  const char* value = cm->GetState()->GetCacheEntryValue(key);
+  const char* value = state->GetCacheEntryValue(key);
   assert(value);
-  switch (cm->GetState()->GetCacheEntryType(key)) {
+  switch (state->GetCacheEntryType(key)) {
     case cmStateEnums::BOOL:
       this->Entry = new cmCursesBoolWidget(this->EntryWidth, 1, 1, 1);
       if (cmIsOn(value)) {
@@ -65,8 +63,7 @@ cmCursesCacheEntryComposite::cmCursesCacheEntryComposite(
       static_cast<cmCursesFilePathWidget*>(this->Entry)->SetString(value);
       break;
     case cmStateEnums::STRING: {
-      const char* stringsProp =
-        cm->GetState()->GetCacheEntryProperty(key, "STRINGS");
+      const char* stringsProp = state->GetCacheEntryProperty(key, "STRINGS");
       if (stringsProp) {
         cmCursesOptionsWidget* ow =
           new cmCursesOptionsWidget(this->EntryWidth, 1, 1, 1);
diff --git a/Source/CursesDialog/cmCursesCacheEntryComposite.h b/Source/CursesDialog/cmCursesCacheEntryComposite.h
index 0a69d3a..b18f076 100644
--- a/Source/CursesDialog/cmCursesCacheEntryComposite.h
+++ b/Source/CursesDialog/cmCursesCacheEntryComposite.h
@@ -9,15 +9,15 @@
 
 class cmCursesLabelWidget;
 class cmCursesWidget;
-class cmake;
+class cmState;
 
 class cmCursesCacheEntryComposite
 {
 public:
   cmCursesCacheEntryComposite(const std::string& key, int labelwidth,
                               int entrywidth);
-  cmCursesCacheEntryComposite(const std::string& key, cmake* cm, bool isNew,
-                              int labelwidth, int entrywidth);
+  cmCursesCacheEntryComposite(const std::string& key, cmState* state,
+                              bool isNew, int labelwidth, int entrywidth);
   ~cmCursesCacheEntryComposite();
 
   cmCursesCacheEntryComposite(cmCursesCacheEntryComposite const&) = delete;
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 5f8a19e..e754196 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -2,7 +2,6 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCursesMainForm.h"
 
-#include "cmAlgorithms.h"
 #include "cmCursesCacheEntryComposite.h"
 #include "cmCursesDummyWidget.h"
 #include "cmCursesForm.h"
@@ -18,6 +17,8 @@
 #include "cmVersion.h"
 #include "cmake.h"
 
+#include <cm/memory>
+
 #include <algorithm>
 #include <cstdio>
 #include <cstring>
@@ -34,8 +35,6 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
   , InitialWidth(initWidth)
 {
   this->NumberOfPages = 0;
-  this->Fields = nullptr;
-  this->Entries = nullptr;
   this->AdvancedMode = false;
   this->NumberOfVisibleEntries = 0;
   this->OkToGenerate = false;
@@ -43,7 +42,8 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
     "Welcome to ccmake, curses based user interface for CMake.");
   this->HelpMessage.emplace_back();
   this->HelpMessage.emplace_back(s_ConstHelpMessage);
-  this->CMakeInstance = new cmake(cmake::RoleProject, cmState::Project);
+  this->CMakeInstance =
+    cm::make_unique<cmake>(cmake::RoleProject, cmState::Project);
   this->CMakeInstance->SetCMakeEditCommand(
     cmSystemTools::GetCMakeCursesCommand());
 
@@ -52,8 +52,6 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
     cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake");
   this->Args[0] = whereCMake;
   this->CMakeInstance->SetArgs(this->Args);
-  this->SearchString = "";
-  this->OldSearchString = "";
   this->SearchMode = false;
 }
 
@@ -64,27 +62,16 @@ cmCursesMainForm::~cmCursesMainForm()
     free_form(this->Form);
     this->Form = nullptr;
   }
-  delete[] this->Fields;
-
-  // Clean-up composites
-  if (this->Entries) {
-    cmDeleteAll(*this->Entries);
-  }
-  delete this->Entries;
-  if (this->CMakeInstance) {
-    delete this->CMakeInstance;
-    this->CMakeInstance = nullptr;
-  }
 }
 
 // See if a cache entry is in the list of entries in the ui.
 bool cmCursesMainForm::LookForCacheEntry(const std::string& key)
 {
-  return this->Entries &&
-    std::any_of(this->Entries->begin(), this->Entries->end(),
-                [&key](cmCursesCacheEntryComposite* entry) {
-                  return key == entry->Key;
-                });
+  return std::any_of(
+    this->Entries.begin(), this->Entries.end(),
+    [&key](std::unique_ptr<cmCursesCacheEntryComposite> const& entry) {
+      return key == entry->Key;
+    });
 }
 
 // Create new cmCursesCacheEntryComposite entries from the cache
@@ -92,11 +79,10 @@ void cmCursesMainForm::InitializeUI()
 {
   // Create a vector of cmCursesCacheEntryComposite's
   // which contain labels, entries and new entry markers
-  std::vector<cmCursesCacheEntryComposite*>* newEntries =
-    new std::vector<cmCursesCacheEntryComposite*>;
+  std::vector<std::unique_ptr<cmCursesCacheEntryComposite>> newEntries;
   std::vector<std::string> cacheKeys =
     this->CMakeInstance->GetState()->GetCacheEntryKeys();
-  newEntries->reserve(cacheKeys.size());
+  newEntries.reserve(cacheKeys.size());
 
   // Count non-internal and non-static entries
   int count = 0;
@@ -112,13 +98,13 @@ void cmCursesMainForm::InitializeUI()
 
   int entrywidth = this->InitialWidth - 35;
 
-  cmCursesCacheEntryComposite* comp;
   if (count == 0) {
     // If cache is empty, display a label saying so and a
     // dummy entry widget (does not respond to input)
-    comp = new cmCursesCacheEntryComposite("EMPTY CACHE", 30, 30);
+    std::unique_ptr<cmCursesCacheEntryComposite> comp =
+      cm::make_unique<cmCursesCacheEntryComposite>("EMPTY CACHE", 30, 30);
     comp->Entry = new cmCursesDummyWidget(1, 1, 1, 1);
-    newEntries->push_back(comp);
+    newEntries.emplace_back(std::move(comp));
   } else {
     // Create the composites.
 
@@ -132,8 +118,8 @@ void cmCursesMainForm::InitializeUI()
       }
 
       if (!this->LookForCacheEntry(key)) {
-        newEntries->push_back(new cmCursesCacheEntryComposite(
-          key, this->CMakeInstance, true, 30, entrywidth));
+        newEntries.emplace_back(cm::make_unique<cmCursesCacheEntryComposite>(
+          key, this->CMakeInstance->GetState(), true, 30, entrywidth));
         this->OkToGenerate = false;
       }
     }
@@ -148,18 +134,14 @@ void cmCursesMainForm::InitializeUI()
       }
 
       if (this->LookForCacheEntry(key)) {
-        newEntries->push_back(new cmCursesCacheEntryComposite(
-          key, this->CMakeInstance, false, 30, entrywidth));
+        newEntries.emplace_back(cm::make_unique<cmCursesCacheEntryComposite>(
+          key, this->CMakeInstance->GetState(), false, 30, entrywidth));
       }
     }
   }
 
-  // Clean old entries
-  if (this->Entries) {
-    cmDeleteAll(*this->Entries);
-  }
-  delete this->Entries;
-  this->Entries = newEntries;
+  // Replace old entries
+  this->Entries = std::move(newEntries);
 
   // Compute fields from composites
   this->RePost();
@@ -173,13 +155,13 @@ void cmCursesMainForm::RePost()
     free_form(this->Form);
     this->Form = nullptr;
   }
-  delete[] this->Fields;
+  this->Fields.clear();
   if (this->AdvancedMode) {
-    this->NumberOfVisibleEntries = this->Entries->size();
+    this->NumberOfVisibleEntries = this->Entries.size();
   } else {
     // If normal mode, count only non-advanced entries
     this->NumberOfVisibleEntries = 0;
-    for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+    for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
       const char* existingValue =
         this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
       bool advanced =
@@ -197,15 +179,10 @@ void cmCursesMainForm::RePost()
   }
   // Assign the fields: 3 for each entry: label, new entry marker
   // ('*' or ' ') and entry widget
-  this->Fields = new FIELD*[3 * this->NumberOfVisibleEntries + 1];
-  size_t cc;
-  for (cc = 0; cc < 3 * this->NumberOfVisibleEntries + 1; cc++) {
-    this->Fields[cc] = nullptr;
-  }
+  this->Fields.reserve(3 * this->NumberOfVisibleEntries + 1);
 
   // Assign fields
-  int j = 0;
-  for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+  for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
     const char* existingValue =
       this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
     bool advanced =
@@ -214,21 +191,20 @@ void cmCursesMainForm::RePost()
     if (!existingValue || (!this->AdvancedMode && advanced)) {
       continue;
     }
-    this->Fields[3 * j] = entry->Label->Field;
-    this->Fields[3 * j + 1] = entry->IsNewLabel->Field;
-    this->Fields[3 * j + 2] = entry->Entry->Field;
-    j++;
+    this->Fields.push_back(entry->Label->Field);
+    this->Fields.push_back(entry->IsNewLabel->Field);
+    this->Fields.push_back(entry->Entry->Field);
   }
   // if no cache entries there should still be one dummy field
-  if (j == 0) {
-    const auto& front = *this->Entries->front();
-    this->Fields[0] = front.Label->Field;
-    this->Fields[1] = front.IsNewLabel->Field;
-    this->Fields[2] = front.Entry->Field;
+  if (this->Fields.empty()) {
+    const auto& front = *this->Entries.front();
+    this->Fields.push_back(front.Label->Field);
+    this->Fields.push_back(front.IsNewLabel->Field);
+    this->Fields.push_back(front.Entry->Field);
     this->NumberOfVisibleEntries = 1;
   }
   // Has to be null terminated.
-  this->Fields[3 * this->NumberOfVisibleEntries] = nullptr;
+  this->Fields.push_back(nullptr);
 }
 
 void cmCursesMainForm::Render(int left, int top, int width, int height)
@@ -261,11 +237,11 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
   height -= 7;
 
   if (this->AdvancedMode) {
-    this->NumberOfVisibleEntries = this->Entries->size();
+    this->NumberOfVisibleEntries = this->Entries.size();
   } else {
     // If normal, display only non-advanced entries
     this->NumberOfVisibleEntries = 0;
-    for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+    for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
       const char* existingValue =
         this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
       bool advanced =
@@ -283,7 +259,7 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
   if (height > 0) {
     bool isNewPage;
     int i = 0;
-    for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+    for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
       const char* existingValue =
         this->CMakeInstance->GetState()->GetCacheEntryValue(entry->GetValue());
       bool advanced =
@@ -308,7 +284,7 @@ void cmCursesMainForm::Render(int left, int top, int width, int height)
   }
 
   // Post the form
-  this->Form = new_form(this->Fields);
+  this->Form = new_form(this->Fields.data());
   post_form(this->Form);
   // Update toolbar
   this->UpdateStatusBar();
@@ -654,23 +630,23 @@ void cmCursesMainForm::RemoveEntry(const char* value)
     return;
   }
 
-  auto removeIt =
-    std::find_if(this->Entries->begin(), this->Entries->end(),
-                 [value](cmCursesCacheEntryComposite* entry) -> bool {
-                   const char* val = entry->GetValue();
-                   return val != nullptr && !strcmp(value, val);
-                 });
+  auto removeIt = std::find_if(
+    this->Entries.begin(), this->Entries.end(),
+    [value](std::unique_ptr<cmCursesCacheEntryComposite>& entry) -> bool {
+      const char* val = entry->GetValue();
+      return val != nullptr && !strcmp(value, val);
+    });
 
-  if (removeIt != this->Entries->end()) {
+  if (removeIt != this->Entries.end()) {
     this->CMakeInstance->UnwatchUnusedCli(value);
-    this->Entries->erase(removeIt);
+    this->Entries.erase(removeIt);
   }
 }
 
 // copy from the list box to the cache manager
 void cmCursesMainForm::FillCacheManagerFromUI()
 {
-  for (cmCursesCacheEntryComposite* entry : *this->Entries) {
+  for (std::unique_ptr<cmCursesCacheEntryComposite>& entry : this->Entries) {
     const std::string& cacheKey = entry->Key;
     const char* existingValue =
       this->CMakeInstance->GetState()->GetCacheEntryValue(cacheKey);
@@ -762,7 +738,7 @@ void cmCursesMainForm::HandleInput()
           this->JumpToCacheEntry(this->SearchString.c_str());
           this->OldSearchString = this->SearchString;
         }
-        this->SearchString = "";
+        this->SearchString.clear();
       }
       /*
       else if ( key == KEY_ESCAPE )
@@ -778,7 +754,7 @@ void cmCursesMainForm::HandleInput()
         }
       } else if (key == ctrl('h') || key == KEY_BACKSPACE || key == KEY_DC) {
         if (!this->SearchString.empty()) {
-          this->SearchString.resize(this->SearchString.size() - 1);
+          this->SearchString.pop_back();
         }
       }
     } else if (currentWidget && !this->SearchMode) {
@@ -867,17 +843,9 @@ void cmCursesMainForm::HandleInput()
             curField, "HELPSTRING");
         }
         if (helpString) {
-          char* message = new char
-            [strlen(curField) + strlen(helpString) +
-             strlen(
-               "Current option is: \n Help string for this option is: \n") +
-             10];
-          sprintf(
-            message,
-            "Current option is: %s\nHelp string for this option is: %s\n",
-            curField, helpString);
-          this->HelpMessage[1] = message;
-          delete[] message;
+          this->HelpMessage[1] =
+            cmStrCat("Current option is: ", curField, '\n',
+                     "Help string for this option is: ", helpString, '\n');
         } else {
           this->HelpMessage[1] = "";
         }
@@ -973,13 +941,13 @@ void cmCursesMainForm::HandleInput()
 
           if (nextCur) {
             // make the next or prev. current field after deletion
-            auto nextEntryIt =
-              std::find_if(this->Entries->begin(), this->Entries->end(),
-                           [&nextVal](cmCursesCacheEntryComposite* entry) {
-                             return nextVal == entry->Key;
-                           });
+            auto nextEntryIt = std::find_if(
+              this->Entries.begin(), this->Entries.end(),
+              [&nextVal](std::unique_ptr<cmCursesCacheEntryComposite>& entry) {
+                return nextVal == entry->Key;
+              });
 
-            if (nextEntryIt != this->Entries->end()) {
+            if (nextEntryIt != this->Entries.end()) {
               set_current_field(this->Form, (*nextEntryIt)->Entry->Field);
             }
           }
diff --git a/Source/CursesDialog/cmCursesMainForm.h b/Source/CursesDialog/cmCursesMainForm.h
index f3194ab..9a83c30 100644
--- a/Source/CursesDialog/cmCursesMainForm.h
+++ b/Source/CursesDialog/cmCursesMainForm.h
@@ -10,6 +10,7 @@
 #include "cmStateTypes.h"
 
 #include <cstddef>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -122,7 +123,7 @@ protected:
   void JumpToCacheEntry(const char* str);
 
   // Copies of cache entries stored in the user interface
-  std::vector<cmCursesCacheEntryComposite*>* Entries;
+  std::vector<std::unique_ptr<cmCursesCacheEntryComposite>> Entries;
   // Errors produced during last run of cmake
   std::vector<std::string> Errors;
   // Command line arguments to be passed to cmake each time
@@ -136,11 +137,7 @@ protected:
   static const char* s_ConstHelpMessage;
 
   // Fields displayed. Includes labels, new entry markers, entries
-  FIELD** Fields;
-  // Where is source of current project
-  std::string WhereSource;
-  // Where is cmake executable
-  std::string WhereCMake;
+  std::vector<FIELD*> Fields;
   // Number of entries shown (depends on mode -normal or advanced-)
   size_t NumberOfVisibleEntries;
   bool AdvancedMode;
@@ -150,7 +147,7 @@ protected:
   int NumberOfPages;
 
   int InitialWidth;
-  cmake* CMakeInstance;
+  std::unique_ptr<cmake> CMakeInstance;
 
   std::string SearchString;
   std::string OldSearchString;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=2b1607114985e56a7847eb6081d5656f73c230d0
commit 2b1607114985e56a7847eb6081d5656f73c230d0
Author:     Tushar Maheshwari <tushar27192 at gmail.com>
AuthorDate: Thu Sep 26 08:36:24 2019 +0530
Commit:     Tushar Maheshwari <tushar27192 at gmail.com>
CommitDate: Thu Sep 26 13:50:58 2019 +0530

    CursesDialog: modernize CMake usage

diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 8ed7b2f..fe048cb 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -1142,7 +1142,7 @@ target_link_libraries(cpack CPackLib)
 
 # Curses GUI
 if(BUILD_CursesDialog)
-  include(${CMake_SOURCE_DIR}/Source/CursesDialog/CMakeLists.txt)
+  add_subdirectory(CursesDialog)
 endif()
 
 # Qt GUI
diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt
index 270b07e..7009717 100644
--- a/Source/CursesDialog/CMakeLists.txt
+++ b/Source/CursesDialog/CMakeLists.txt
@@ -1,26 +1,22 @@
 # Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
 # file Copyright.txt or https://cmake.org/licensing for details.
 
-set( CURSES_SRCS
-              CursesDialog/cmCursesOptionsWidget.cxx
-              CursesDialog/cmCursesBoolWidget.cxx
-              CursesDialog/cmCursesCacheEntryComposite.cxx
-              CursesDialog/cmCursesDummyWidget.cxx
-              CursesDialog/cmCursesFilePathWidget.cxx
-              CursesDialog/cmCursesForm.cxx
-              CursesDialog/cmCursesLabelWidget.cxx
-              CursesDialog/cmCursesLongMessageForm.cxx
-              CursesDialog/cmCursesMainForm.cxx
-              CursesDialog/cmCursesPathWidget.cxx
-              CursesDialog/cmCursesStringWidget.cxx
-              CursesDialog/cmCursesWidget.cxx
-              CursesDialog/ccmake.cxx
-   )
-
-include_directories(${CURSES_INCLUDE_PATH})
-
-
-add_executable(ccmake ${CURSES_SRCS} )
+add_executable(ccmake
+  ccmake.cxx
+  cmCursesBoolWidget.cxx
+  cmCursesCacheEntryComposite.cxx
+  cmCursesDummyWidget.cxx
+  cmCursesFilePathWidget.cxx
+  cmCursesForm.cxx
+  cmCursesLabelWidget.cxx
+  cmCursesLongMessageForm.cxx
+  cmCursesMainForm.cxx
+  cmCursesOptionsWidget.cxx
+  cmCursesPathWidget.cxx
+  cmCursesStringWidget.cxx
+  cmCursesWidget.cxx
+  )
+target_include_directories(ccmake PRIVATE ${CURSES_INCLUDE_PATH})
 target_link_libraries(ccmake CMakeLib)
 if(CMAKE_USE_SYSTEM_FORM)
   find_path(CURSES_FORM_INCLUDE_DIR NAMES form.h HINTS ${CURSES_INCLUDE_PATH} ${CURSES_INCLUDE_PATH}/ncurses)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0cfbd85e7b0d61affda6450b1cc081860b5543a6
commit 0cfbd85e7b0d61affda6450b1cc081860b5543a6
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Tue Sep 24 13:07:14 2019 -0400
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Tue Sep 24 14:10:34 2019 -0400

    Tests: Teach RunCMake to support a custom working directory

diff --git a/Tests/RunCMake/RunCMake.cmake b/Tests/RunCMake/RunCMake.cmake
index ce71677..644da60 100644
--- a/Tests/RunCMake/RunCMake.cmake
+++ b/Tests/RunCMake/RunCMake.cmake
@@ -82,9 +82,12 @@ function(run_cmake test)
     set(maybe_input_file "")
   endif()
   if(RunCMake_TEST_COMMAND)
+    if(NOT RunCMake_TEST_COMMAND_WORKING_DIRECTORY)
+      set(RunCMake_TEST_COMMAND_WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+    endif()
     execute_process(
       COMMAND ${RunCMake_TEST_COMMAND}
-      WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}"
+      WORKING_DIRECTORY "${RunCMake_TEST_COMMAND_WORKING_DIRECTORY}"
       OUTPUT_VARIABLE actual_stdout
       ERROR_VARIABLE ${actual_stderr_var}
       RESULT_VARIABLE actual_result

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

Summary of changes:
 Help/command/enable_language.rst                   |   5 +-
 Help/command/project.rst                           |   3 +-
 Help/manual/cmake-generator-expressions.7.rst      |  28 +
 Help/manual/cmake-modules.7.rst                    |   6 +
 Help/module/CheckOBJCCompilerFlag.rst              |   1 +
 Help/module/CheckOBJCSourceCompiles.rst            |   1 +
 Help/module/CheckOBJCSourceRuns.rst                |   1 +
 Help/module/CheckOBJCXXCompilerFlag.rst            |   1 +
 Help/module/CheckOBJCXXSourceCompiles.rst          |   1 +
 Help/module/CheckOBJCXXSourceRuns.rst              |   1 +
 Help/prop_dir/EXCLUDE_FROM_ALL.rst                 |  20 +-
 Help/prop_tgt/EXCLUDE_FROM_ALL.rst                 |  16 +-
 Help/release/3.14.rst                              |   8 +
 Help/release/3.15.rst                              |   9 +
 Help/release/dev/FPHSA-reason-failure-message.rst  |   5 +
 Help/release/dev/objective-c-cxx.rst               |   9 +
 Modules/CMakeCXXCompiler.cmake.in                  |  11 +-
 Modules/CMakeDetermineOBJCCompiler.cmake           | 189 +++++
 Modules/CMakeDetermineOBJCXXCompiler.cmake         | 197 +++++
 Modules/CMakeOBJCCompiler.cmake.in                 |  69 ++
 Modules/CMakeOBJCCompilerABI.m                     |  20 +
 Modules/CMakeOBJCCompilerId.m.in                   |  63 ++
 Modules/CMakeOBJCInformation.cmake                 | 188 +++++
 Modules/CMakeOBJCXXCompiler.cmake.in               |  79 ++
 Modules/CMakeOBJCXXCompilerABI.mm                  |  20 +
 Modules/CMakeOBJCXXCompilerId.mm.in                |  68 ++
 Modules/CMakeOBJCXXInformation.cmake               | 273 +++++++
 Modules/CMakeTestOBJCCompiler.cmake                |  94 +++
 Modules/CMakeTestOBJCXXCompiler.cmake              |  93 +++
 Modules/CheckOBJCCompilerFlag.cmake                |  64 ++
 Modules/CheckOBJCSourceCompiles.cmake              | 145 ++++
 Modules/CheckOBJCSourceRuns.cmake                  | 145 ++++
 Modules/CheckOBJCXXCompilerFlag.cmake              |  64 ++
 Modules/CheckOBJCXXSourceCompiles.cmake            | 146 ++++
 Modules/CheckOBJCXXSourceRuns.cmake                | 145 ++++
 Modules/Compiler/AppleClang-OBJC.cmake             |  17 +
 Modules/Compiler/AppleClang-OBJCXX.cmake           |  37 +
 Modules/Compiler/Clang-OBJC.cmake                  |  18 +
 Modules/Compiler/Clang-OBJCXX.cmake                |  70 ++
 Modules/Compiler/GNU-OBJC.cmake                    |   6 +
 Modules/Compiler/GNU-OBJCXX.cmake                  |  10 +
 Modules/FindPackageHandleStandardArgs.cmake        |  27 +-
 Modules/Platform/Apple-AppleClang-OBJC.cmake       |   6 +
 Modules/Platform/Apple-AppleClang-OBJCXX.cmake     |   6 +
 Modules/Platform/Apple-Clang-OBJC.cmake            |   2 +
 Modules/Platform/Apple-Clang-OBJCXX.cmake          |   2 +
 Modules/Platform/Apple-GNU-OBJC.cmake              |   4 +
 Modules/Platform/Apple-GNU-OBJCXX.cmake            |   4 +
 Modules/Platform/Darwin.cmake                      |  10 +-
 Source/CMakeLists.txt                              |   2 +-
 Source/CursesDialog/CMakeLists.txt                 |  36 +-
 .../CursesDialog/cmCursesCacheEntryComposite.cxx   |  81 +-
 Source/CursesDialog/cmCursesCacheEntryComposite.h  |  17 +-
 Source/CursesDialog/cmCursesMainForm.cxx           | 174 ++---
 Source/CursesDialog/cmCursesMainForm.h             |  13 +-
 Source/CursesDialog/cmCursesStringWidget.cxx       |  32 +-
 Source/CursesDialog/cmCursesStringWidget.h         |   5 +-
 Source/cmGeneratorExpressionNode.cxx               |   8 +-
 Source/cmGlobalGenerator.cxx                       |  14 +-
 Source/cmGlobalGenerator.h                         |   2 +-
 Source/cmGlobalNinjaGenerator.h                    |   4 +-
 Source/cmGlobalUnixMakefileGenerator3.cxx          |  31 +-
 Source/cmGlobalVisualStudioGenerator.cxx           |   2 +-
 Source/cmGlobalXCodeGenerator.cxx                  |   2 +-
 Source/cmLocalGenerator.cxx                        |  12 +-
 Source/cmLocalNinjaGenerator.cxx                   |   4 +-
 Source/cmMakefile.cxx                              | 158 ++--
 Source/cmMakefile.h                                |  14 +-
 Source/cmQtAutoGenerator.cxx                       | 266 ++++---
 Source/cmQtAutoGenerator.h                         |  96 ++-
 Source/cmQtAutoMocUic.cxx                          | 856 +++++++++++++++++----
 Source/cmQtAutoMocUic.h                            | 551 +------------
 Source/cmQtAutoRcc.cxx                             | 129 +++-
 Source/cmQtAutoRcc.h                               |  72 +-
 Source/cmTarget.cxx                                |   8 +
 Source/cmcmd.cxx                                   |  21 +-
 Tests/CMakeLists.txt                               |  73 ++
 Tests/CMakeOnly/CMakeLists.txt                     |  11 +
 Tests/CMakeOnly/CheckLanguage/CMakeLists.txt       |  12 +-
 .../CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt |  17 +
 .../CheckOBJCXXCompilerFlag/CMakeLists.txt         |  17 +
 Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt      |  14 +
 Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt    |  14 +
 .../cxx-file-extension-test/CMakeLists.txt         |   5 +
 .../Objective-C++/cxx-file-extension-test/main.mm  |   8 +
 .../objcxx-file-extension-test/CMakeLists.txt      |   6 +
 .../objcxx-file-extension-test/main.mm             |  14 +
 .../Objective-C++/simple-build-test/CMakeLists.txt |  11 +
 Tests/Objective-C++/simple-build-test/foo.h        |   9 +
 Tests/Objective-C++/simple-build-test/foo.mm       |   7 +
 Tests/Objective-C++/simple-build-test/main.mm      |  14 +
 .../c-file-extension-test/CMakeLists.txt           |   5 +
 Tests/Objective-C/c-file-extension-test/main.m     |   8 +
 .../objc-file-extension-test/CMakeLists.txt        |   6 +
 Tests/Objective-C/objc-file-extension-test/main.m  |  12 +
 Tests/Objective-C/simple-build-test/CMakeLists.txt |  11 +
 Tests/Objective-C/simple-build-test/foo.h          |   9 +
 Tests/Objective-C/simple-build-test/foo.m          |   7 +
 Tests/Objective-C/simple-build-test/main.m         |  12 +
 Tests/RunCMake/FPHSA/CustomMessageConfig.cmake     |   1 +
 .../FPHSA/CustomMessageConfigVersion.cmake         |   4 +
 Tests/RunCMake/FPHSA/FindCustomMessage.cmake       |  17 +
 Tests/RunCMake/FPHSA/RunCMakeTest.cmake            |   7 +
 .../custom_message_1-result.txt}                   |   0
 Tests/RunCMake/FPHSA/custom_message_1-stderr.txt   |   7 +
 Tests/RunCMake/FPHSA/custom_message_1.cmake        |   4 +
 .../custom_message_2-result.txt}                   |   0
 Tests/RunCMake/FPHSA/custom_message_2-stderr.txt   |   8 +
 Tests/RunCMake/FPHSA/custom_message_2.cmake        |   5 +
 .../custom_message_3-result.txt}                   |   0
 Tests/RunCMake/FPHSA/custom_message_3-stderr.txt   |   9 +
 Tests/RunCMake/FPHSA/custom_message_3.cmake        |   5 +
 Tests/RunCMake/RunCMake.cmake                      |   5 +-
 .../ExcludeFromAll-build-sub-stderr.txt}           |   0
 .../RunCMake/add_subdirectory/ExcludeFromAll.cmake |   8 +
 .../add_subdirectory/ExcludeFromAll/CMakeLists.txt |  23 +-
 .../ExcludeFromAll/check-sub.cmake                 |  32 +
 .../add_subdirectory/ExcludeFromAll/check.cmake    |  73 +-
 .../add_subdirectory/ExcludeFromAll/subinc.cpp     |   4 +
 .../add_subdirectory/ExcludeFromAll/zot.cpp        |   4 +
 Tests/RunCMake/add_subdirectory/RunCMakeTest.cmake |  36 +-
 Tests/TryCompile/CMakeLists.txt                    |  54 ++
 122 files changed, 4252 insertions(+), 1373 deletions(-)
 create mode 100644 Help/module/CheckOBJCCompilerFlag.rst
 create mode 100644 Help/module/CheckOBJCSourceCompiles.rst
 create mode 100644 Help/module/CheckOBJCSourceRuns.rst
 create mode 100644 Help/module/CheckOBJCXXCompilerFlag.rst
 create mode 100644 Help/module/CheckOBJCXXSourceCompiles.rst
 create mode 100644 Help/module/CheckOBJCXXSourceRuns.rst
 create mode 100644 Help/release/dev/FPHSA-reason-failure-message.rst
 create mode 100644 Help/release/dev/objective-c-cxx.rst
 create mode 100644 Modules/CMakeDetermineOBJCCompiler.cmake
 create mode 100644 Modules/CMakeDetermineOBJCXXCompiler.cmake
 create mode 100644 Modules/CMakeOBJCCompiler.cmake.in
 create mode 100644 Modules/CMakeOBJCCompilerABI.m
 create mode 100644 Modules/CMakeOBJCCompilerId.m.in
 create mode 100644 Modules/CMakeOBJCInformation.cmake
 create mode 100644 Modules/CMakeOBJCXXCompiler.cmake.in
 create mode 100644 Modules/CMakeOBJCXXCompilerABI.mm
 create mode 100644 Modules/CMakeOBJCXXCompilerId.mm.in
 create mode 100644 Modules/CMakeOBJCXXInformation.cmake
 create mode 100644 Modules/CMakeTestOBJCCompiler.cmake
 create mode 100644 Modules/CMakeTestOBJCXXCompiler.cmake
 create mode 100644 Modules/CheckOBJCCompilerFlag.cmake
 create mode 100644 Modules/CheckOBJCSourceCompiles.cmake
 create mode 100644 Modules/CheckOBJCSourceRuns.cmake
 create mode 100644 Modules/CheckOBJCXXCompilerFlag.cmake
 create mode 100644 Modules/CheckOBJCXXSourceCompiles.cmake
 create mode 100644 Modules/CheckOBJCXXSourceRuns.cmake
 create mode 100644 Modules/Compiler/AppleClang-OBJC.cmake
 create mode 100644 Modules/Compiler/AppleClang-OBJCXX.cmake
 create mode 100644 Modules/Compiler/Clang-OBJC.cmake
 create mode 100644 Modules/Compiler/Clang-OBJCXX.cmake
 create mode 100644 Modules/Compiler/GNU-OBJC.cmake
 create mode 100644 Modules/Compiler/GNU-OBJCXX.cmake
 create mode 100644 Modules/Platform/Apple-AppleClang-OBJC.cmake
 create mode 100644 Modules/Platform/Apple-AppleClang-OBJCXX.cmake
 create mode 100644 Modules/Platform/Apple-Clang-OBJC.cmake
 create mode 100644 Modules/Platform/Apple-Clang-OBJCXX.cmake
 create mode 100644 Modules/Platform/Apple-GNU-OBJC.cmake
 create mode 100644 Modules/Platform/Apple-GNU-OBJCXX.cmake
 create mode 100644 Tests/CMakeOnly/CheckOBJCCompilerFlag/CMakeLists.txt
 create mode 100644 Tests/CMakeOnly/CheckOBJCXXCompilerFlag/CMakeLists.txt
 create mode 100644 Tests/CMakeOnly/CompilerIdOBJC/CMakeLists.txt
 create mode 100644 Tests/CMakeOnly/CompilerIdOBJCXX/CMakeLists.txt
 create mode 100644 Tests/Objective-C++/cxx-file-extension-test/CMakeLists.txt
 create mode 100644 Tests/Objective-C++/cxx-file-extension-test/main.mm
 create mode 100644 Tests/Objective-C++/objcxx-file-extension-test/CMakeLists.txt
 create mode 100644 Tests/Objective-C++/objcxx-file-extension-test/main.mm
 create mode 100644 Tests/Objective-C++/simple-build-test/CMakeLists.txt
 create mode 100644 Tests/Objective-C++/simple-build-test/foo.h
 create mode 100644 Tests/Objective-C++/simple-build-test/foo.mm
 create mode 100644 Tests/Objective-C++/simple-build-test/main.mm
 create mode 100644 Tests/Objective-C/c-file-extension-test/CMakeLists.txt
 create mode 100644 Tests/Objective-C/c-file-extension-test/main.m
 create mode 100644 Tests/Objective-C/objc-file-extension-test/CMakeLists.txt
 create mode 100644 Tests/Objective-C/objc-file-extension-test/main.m
 create mode 100644 Tests/Objective-C/simple-build-test/CMakeLists.txt
 create mode 100644 Tests/Objective-C/simple-build-test/foo.h
 create mode 100644 Tests/Objective-C/simple-build-test/foo.m
 create mode 100644 Tests/Objective-C/simple-build-test/main.m
 create mode 100644 Tests/RunCMake/FPHSA/CustomMessageConfig.cmake
 create mode 100644 Tests/RunCMake/FPHSA/CustomMessageConfigVersion.cmake
 create mode 100644 Tests/RunCMake/FPHSA/FindCustomMessage.cmake
 copy Tests/RunCMake/{while/MissingArgument-result.txt => FPHSA/custom_message_1-result.txt} (100%)
 create mode 100644 Tests/RunCMake/FPHSA/custom_message_1-stderr.txt
 create mode 100644 Tests/RunCMake/FPHSA/custom_message_1.cmake
 copy Tests/RunCMake/{while/MissingArgument-result.txt => FPHSA/custom_message_2-result.txt} (100%)
 create mode 100644 Tests/RunCMake/FPHSA/custom_message_2-stderr.txt
 create mode 100644 Tests/RunCMake/FPHSA/custom_message_2.cmake
 copy Tests/RunCMake/{while/MissingArgument-result.txt => FPHSA/custom_message_3-result.txt} (100%)
 create mode 100644 Tests/RunCMake/FPHSA/custom_message_3-stderr.txt
 create mode 100644 Tests/RunCMake/FPHSA/custom_message_3.cmake
 copy Tests/RunCMake/{target_link_options/LINK_OPTIONS-shared-result.txt => add_subdirectory/ExcludeFromAll-build-sub-stderr.txt} (100%)
 create mode 100644 Tests/RunCMake/add_subdirectory/ExcludeFromAll/check-sub.cmake
 create mode 100644 Tests/RunCMake/add_subdirectory/ExcludeFromAll/subinc.cpp
 create mode 100644 Tests/RunCMake/add_subdirectory/ExcludeFromAll/zot.cpp


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list