[Cmake-commits] CMake branch, master, updated. v3.15.3-1072-g01cce69

Kitware Robot kwrobot at kitware.com
Wed Sep 18 11:39:09 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  01cce69870ec7efbb8138f5345aa7ffed8b7ac12 (commit)
       via  a981a9a7451bbabdc5048f982dce4b3553fe9711 (commit)
       via  c9c1eb99fe011546b5d9390c7fbbeebfda491c65 (commit)
       via  729d997f1073c7a177da5b46b073a08b95adfa74 (commit)
      from  45b7d5284e11cb34885b756bee8dedeb94fc16cb (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=01cce69870ec7efbb8138f5345aa7ffed8b7ac12
commit 01cce69870ec7efbb8138f5345aa7ffed8b7ac12
Merge: a981a9a c9c1eb9
Author:     Kyle Edwards <kyle.edwards at kitware.com>
AuthorDate: Wed Sep 18 15:35:13 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Sep 18 11:36:03 2019 -0400

    Merge topic 'smart_ptr/cmCPackGeneratorFactory'
    
    c9c1eb99fe cmCPackGeneratorFactory: rule of zero
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Merge-request: !3826


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a981a9a7451bbabdc5048f982dce4b3553fe9711
commit a981a9a7451bbabdc5048f982dce4b3553fe9711
Merge: 45b7d52 729d997
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Wed Sep 18 15:33:23 2019 +0000
Commit:     Kitware Robot <kwrobot at kitware.com>
CommitDate: Wed Sep 18 11:34:00 2019 -0400

    Merge topic 'shared-pch'
    
    729d997f10 Precompile Headers: Add REUSE_FROM signature
    
    Acked-by: Kitware Robot <kwrobot at kitware.com>
    Acked-by: Rickard Englund <rickard at r-englund.com>
    Acked-by: Viktor Kirilov <vik.kirilov at gmail.com>
    Merge-request: !3762


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c9c1eb99fe011546b5d9390c7fbbeebfda491c65
commit c9c1eb99fe011546b5d9390c7fbbeebfda491c65
Author:     Tushar Maheshwari <tushar27192 at gmail.com>
AuthorDate: Sat Sep 7 14:15:08 2019 +0530
Commit:     Kyle Edwards <kyle.edwards at kitware.com>
CommitDate: Tue Sep 17 13:05:26 2019 -0400

    cmCPackGeneratorFactory: rule of zero

diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index a564eb1..79e344b 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -6,7 +6,6 @@
 #include <utility>
 
 #include "IFW/cmCPackIFWGenerator.h"
-#include "cmAlgorithms.h"
 #ifdef HAVE_FREEBSD_PKG
 #  include "cmCPackFreeBSDGenerator.h"
 #endif
@@ -138,33 +137,21 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
 #endif
 }
 
-cmCPackGeneratorFactory::~cmCPackGeneratorFactory()
-{
-  cmDeleteAll(this->Generators);
-}
-
-cmCPackGenerator* cmCPackGeneratorFactory::NewGenerator(
+std::unique_ptr<cmCPackGenerator> cmCPackGeneratorFactory::NewGenerator(
   const std::string& name)
 {
-  cmCPackGenerator* gen = this->NewGeneratorInternal(name);
+  auto it = this->GeneratorCreators.find(name);
+  if (it == this->GeneratorCreators.end()) {
+    return nullptr;
+  }
+  std::unique_ptr<cmCPackGenerator> gen(it->second());
   if (!gen) {
     return nullptr;
   }
-  this->Generators.push_back(gen);
   gen->SetLogger(this->Logger);
   return gen;
 }
 
-cmCPackGenerator* cmCPackGeneratorFactory::NewGeneratorInternal(
-  const std::string& name)
-{
-  auto it = this->GeneratorCreators.find(name);
-  if (it == this->GeneratorCreators.end()) {
-    return nullptr;
-  }
-  return (it->second)();
-}
-
 void cmCPackGeneratorFactory::RegisterGenerator(
   const std::string& name, const char* generatorDescription,
   CreateGeneratorCall* createGenerator)
diff --git a/Source/CPack/cmCPackGeneratorFactory.h b/Source/CPack/cmCPackGeneratorFactory.h
index da2eb8d..62b7484 100644
--- a/Source/CPack/cmCPackGeneratorFactory.h
+++ b/Source/CPack/cmCPackGeneratorFactory.h
@@ -6,8 +6,8 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
+#include <memory>
 #include <string>
-#include <vector>
 
 class cmCPackGenerator;
 class cmCPackLog;
@@ -20,14 +20,9 @@ class cmCPackGeneratorFactory
 {
 public:
   cmCPackGeneratorFactory();
-  ~cmCPackGeneratorFactory();
-
-  cmCPackGeneratorFactory(const cmCPackGeneratorFactory&) = delete;
-  cmCPackGeneratorFactory& operator=(const cmCPackGeneratorFactory&) = delete;
 
   //! Get the generator
-  cmCPackGenerator* NewGenerator(const std::string& name);
-  void DeleteGenerator(cmCPackGenerator* gen);
+  std::unique_ptr<cmCPackGenerator> NewGenerator(const std::string& name);
 
   using CreateGeneratorCall = cmCPackGenerator*();
 
@@ -44,9 +39,6 @@ public:
   }
 
 private:
-  cmCPackGenerator* NewGeneratorInternal(const std::string& name);
-  std::vector<cmCPackGenerator*> Generators;
-
   using t_GeneratorCreatorsMap = std::map<std::string, CreateGeneratorCall*>;
   t_GeneratorCreatorsMap GeneratorCreators;
   DescriptionsMap GeneratorDescriptions;
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index ab44a42..ce41d40 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -25,6 +25,7 @@
 #include <cstddef>
 #include <iostream>
 #include <map>
+#include <memory>
 #include <sstream>
 #include <string>
 #include <utility>
@@ -237,7 +238,6 @@ int main(int argc, char const* const* argv)
 
   cmCPackGeneratorFactory generators;
   generators.SetLogger(&log);
-  cmCPackGenerator* cpackGenerator = nullptr;
 
   cmDocumentation doc;
   doc.addCPackStandardDocSections();
@@ -360,7 +360,8 @@ int main(int argc, char const* const* argv)
           parsed = 0;
         }
         if (parsed) {
-          cpackGenerator = generators.NewGenerator(gen);
+          std::unique_ptr<cmCPackGenerator> cpackGenerator =
+            generators.NewGenerator(gen);
           if (cpackGenerator) {
             cpackGenerator->SetTrace(trace);
             cpackGenerator->SetTraceExpand(traceExpand);

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=729d997f1073c7a177da5b46b073a08b95adfa74
commit 729d997f1073c7a177da5b46b073a08b95adfa74
Author:     Cristian Adam <cristian.adam at gmail.com>
AuthorDate: Fri Aug 30 16:21:19 2019 +0200
Commit:     Cristian Adam <cristian.adam at gmail.com>
CommitDate: Tue Sep 17 11:58:38 2019 +0200

    Precompile Headers: Add REUSE_FROM signature
    
    Add the ability to share precompiled headers artifacts between
    targets.
    
    Fixes: #19659

diff --git a/Help/command/target_precompile_headers.rst b/Help/command/target_precompile_headers.rst
index 3e28265..7d36b11 100644
--- a/Help/command/target_precompile_headers.rst
+++ b/Help/command/target_precompile_headers.rst
@@ -9,9 +9,23 @@ Add a list of header files to precompile.
     <INTERFACE|PUBLIC|PRIVATE> [header1...]
     [<INTERFACE|PUBLIC|PRIVATE> [header2...] ...])
 
+  target_precompile_headers(<target> REUSE_FROM <other_target>)
+
 Adds header files to :prop_tgt:`PRECOMPILE_HEADERS` or
 :prop_tgt:`INTERFACE_PRECOMPILE_HEADERS` target properties.
 
+The second signature will reuse an already precompiled header file artefact
+from another target. This is done by setting the
+:prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` to ``<other_target>`` value.
+The ``<other_target>`` will become a dependency of ``<target>``.
+
+.. note::
+
+  The second signature will require the same set of compiler options,
+  compiler flags, compiler definitions for both ``<target>``, and
+  ``<other_target>``. Compilers (e.g. GCC) will issue a warning if the
+  precompiled header file cannot be used (``-Winvalid-pch``).
+
 Precompiling header files can speed up compilation by creating a partially
 processed version of some header files, and then using that version during
 compilations rather than repeatedly parsing the original headers.
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index 19afb7d..0928abe 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -298,6 +298,7 @@ Properties on Targets
    /prop_tgt/PDB_OUTPUT_DIRECTORY
    /prop_tgt/POSITION_INDEPENDENT_CODE
    /prop_tgt/PRECOMPILE_HEADERS
+   /prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM
    /prop_tgt/PREFIX
    /prop_tgt/PRIVATE_HEADER
    /prop_tgt/PROJECT_LABEL
diff --git a/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst b/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst
new file mode 100644
index 0000000..d740303
--- /dev/null
+++ b/Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst
@@ -0,0 +1,7 @@
+PRECOMPILE_HEADERS_REUSE_FROM
+-----------------------------
+
+Target from which to reuse the precomipled headers build artifact.
+
+See the second signature of :command:`target_precompile_headers` command
+for more detailed information.
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index 6ddcaa3..34f5d03 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -333,10 +333,17 @@ macro(__windows_compiler_msvc lang)
   set(CMAKE_LINK_PCH ON)
   if(MSVC_VERSION GREATER_EQUAL 1910)
     # VS 2017 or greater
-    set(CMAKE_PCH_PROLOGUE "#pragma system_header")
+    if (NOT ${CMAKE_${lang}_COMPILER_ID} STREQUAL "Clang")
+        set(CMAKE_PCH_PROLOGUE "#pragma system_header")
+    else()
+        set(CMAKE_PCH_PROLOGUE "#pragma clang system_header")
+    endif()
+  endif()
+  if (NOT ${CMAKE_${lang}_COMPILER_ID} STREQUAL "Clang")
+    set(CMAKE_PCH_COPY_COMPILE_PDB ON)
   endif()
-  set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH /Yu<PCH_HEADER> /FI<PCH_HEADER>)
-  set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH /Yc<PCH_HEADER> /FI<PCH_HEADER>)
+  set(CMAKE_${lang}_COMPILE_OPTIONS_USE_PCH /Yu<PCH_HEADER> /Fp<PCH_FILE> /FI<PCH_HEADER>)
+  set(CMAKE_${lang}_COMPILE_OPTIONS_CREATE_PCH /Yc<PCH_HEADER> /Fp<PCH_FILE> /FI<PCH_HEADER>)
 
   if("x${CMAKE_${lang}_COMPILER_ID}" STREQUAL "xMSVC")
     set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 33286ad..19a096b 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -171,6 +171,7 @@ std::string cmCommonTargetGenerator::ComputeTargetCompilePDB() const
   if (this->GeneratorTarget->GetType() > cmStateEnums::OBJECT_LIBRARY) {
     return compilePdbPath;
   }
+
   compilePdbPath =
     this->GeneratorTarget->GetCompilePDBPath(this->GetConfigName());
   if (compilePdbPath.empty()) {
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 2ca5706..3a321c5 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -35,6 +35,7 @@
 #include "cmRange.h"
 #include "cmSourceFile.h"
 #include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
 #include "cmState.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
@@ -3371,57 +3372,67 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config,
     }
     std::string& filename = inserted.first->second;
 
+    const cmGeneratorTarget* generatorTarget = this;
+    const char* pchReuseFrom =
+      generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
+    if (pchReuseFrom) {
+      generatorTarget =
+        this->GetGlobalGenerator()->FindGeneratorTarget(pchReuseFrom);
+    }
+
     if (this->GetGlobalGenerator()->IsMultiConfig()) {
-      filename =
-        cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), "/");
+      filename = cmStrCat(
+        generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(), "/");
     } else {
       // For GCC we need to have the header file .h[xx]
       // next to the .h[xx].gch file
-      filename = this->ObjectDirectory;
+      filename = generatorTarget->ObjectDirectory;
     }
 
-    filename = cmStrCat(filename, "CMakeFiles/", this->GetName(),
+    filename = cmStrCat(filename, "CMakeFiles/", generatorTarget->GetName(),
                         ".dir/cmake_pch", ((language == "C") ? ".h" : ".hxx"));
 
     const std::string filename_tmp = cmStrCat(filename, ".tmp");
-    {
+    if (!pchReuseFrom) {
       auto pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE");
       auto pchEpilogue = this->Makefile->GetDefinition("CMAKE_PCH_EPILOGUE");
 
-      cmGeneratedFileStream file(
-        filename_tmp, false,
-        this->GetGlobalGenerator()->GetMakefileEncoding());
-      file << "/* generated by CMake */\n\n";
-      if (pchPrologue) {
-        file << pchPrologue << "\n";
-      }
-      if (this->GetGlobalGenerator()->IsXcode()) {
-        file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n";
-      }
-      if (language == "CXX") {
-        file << "#ifdef __cplusplus\n";
-      }
-      for (auto const& header_bt : headers) {
-        if (header_bt.Value.empty()) {
-          continue;
+      {
+        cmGeneratedFileStream file(
+          filename_tmp, false,
+          this->GetGlobalGenerator()->GetMakefileEncoding());
+        file << "/* generated by CMake */\n\n";
+        if (pchPrologue) {
+          file << pchPrologue << "\n";
         }
-        if (header_bt.Value[0] == '<' || header_bt.Value[0] == '"') {
-          file << "#include " << header_bt.Value << "\n";
-        } else {
-          file << "#include \"" << header_bt.Value << "\"\n";
+        if (this->GetGlobalGenerator()->IsXcode()) {
+          file << "#ifndef CMAKE_SKIP_PRECOMPILE_HEADERS\n";
+        }
+        if (language == "CXX") {
+          file << "#ifdef __cplusplus\n";
+        }
+        for (auto const& header_bt : headers) {
+          if (header_bt.Value.empty()) {
+            continue;
+          }
+          if (header_bt.Value[0] == '<' || header_bt.Value[0] == '\"') {
+            file << "#include " << header_bt.Value << "\n";
+          } else {
+            file << "#include \"" << header_bt.Value << "\"\n";
+          }
+        }
+        if (language == "CXX") {
+          file << "#endif // __cplusplus\n";
+        }
+        if (this->GetGlobalGenerator()->IsXcode()) {
+          file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n";
+        }
+        if (pchEpilogue) {
+          file << pchEpilogue << "\n";
         }
       }
-      if (language == "CXX") {
-        file << "#endif // __cplusplus\n";
-      }
-      if (this->GetGlobalGenerator()->IsXcode()) {
-        file << "#endif // CMAKE_SKIP_PRECOMPILE_HEADERS\n";
-      }
-      if (pchEpilogue) {
-        file << pchEpilogue << "\n";
-      }
+      cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
     }
-    cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
   }
   return inserted.first->second;
 }
@@ -3440,8 +3451,18 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config,
       return std::string();
     }
     std::string& filename = inserted.first->second;
-    filename = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
-                        "/CMakeFiles/", this->GetName(), ".dir/cmake_pch");
+
+    const cmGeneratorTarget* generatorTarget = this;
+    const char* pchReuseFrom =
+      generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
+    if (pchReuseFrom) {
+      generatorTarget =
+        this->GetGlobalGenerator()->FindGeneratorTarget(pchReuseFrom);
+    }
+
+    filename =
+      cmStrCat(generatorTarget->LocalGenerator->GetCurrentBinaryDirectory(),
+               "/CMakeFiles/", generatorTarget->GetName(), ".dir/cmake_pch");
 
     // For GCC the source extension will be tranformed into .h[xx].gch
     if (!this->Makefile->IsOn("CMAKE_LINK_PCH")) {
@@ -3449,12 +3470,40 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config,
     } else {
       filename += ((language == "C") ? ".c" : ".cxx");
     }
+
     const std::string filename_tmp = cmStrCat(filename, ".tmp");
-    {
-      cmGeneratedFileStream file(filename_tmp);
-      file << "/* generated by CMake */\n";
+    if (!pchReuseFrom) {
+      {
+        cmGeneratedFileStream file(filename_tmp);
+        file << "/* generated by CMake */\n";
+      }
+      cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
     }
-    cmSystemTools::MoveFileIfDifferent(filename_tmp, filename);
+  }
+  return inserted.first->second;
+}
+
+std::string cmGeneratorTarget::GetPchFileObject(const std::string& config,
+                                                const std::string& language)
+{
+  if (language != "C" && language != "CXX") {
+    return std::string();
+  }
+  const auto inserted =
+    this->PchObjectFiles.insert(std::make_pair(language + config, ""));
+  if (inserted.second) {
+    const std::string pchSource = this->GetPchSource(config, language);
+    if (pchSource.empty()) {
+      return std::string();
+    }
+    std::string& filename = inserted.first->second;
+
+    this->AddSource(pchSource, true);
+
+    auto pchSf = this->Makefile->GetOrCreateSource(
+      pchSource, false, cmSourceFileLocationKind::Known);
+
+    filename = cmStrCat(this->ObjectDirectory, this->GetObjectName(pchSf));
   }
   return inserted.first->second;
 }
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 4207d65..6c36c4b 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -462,6 +462,8 @@ public:
                            const std::string& language) const;
   std::string GetPchSource(const std::string& config,
                            const std::string& language) const;
+  std::string GetPchFileObject(const std::string& config,
+                               const std::string& language);
 
   bool IsSystemIncludeDirectory(const std::string& dir,
                                 const std::string& config,
@@ -880,6 +882,7 @@ private:
   mutable std::set<std::string> LinkImplicitNullProperties;
   mutable std::map<std::string, std::string> PchHeaders;
   mutable std::map<std::string, std::string> PchSources;
+  mutable std::map<std::string, std::string> PchObjectFiles;
 
   void ExpandLinkItems(std::string const& prop, std::string const& value,
                        std::string const& config,
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 5bbb83c..afcd69f 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -4,7 +4,9 @@
 
 #include "cmAlgorithms.h"
 #include "cmComputeLinkInformation.h"
+#include "cmCustomCommand.h"
 #include "cmCustomCommandGenerator.h"
+#include "cmCustomCommandLines.h"
 #include "cmGeneratedFileStream.h"
 #include "cmGeneratorExpression.h"
 #include "cmGeneratorExpressionEvaluationFile.h"
@@ -2255,23 +2257,124 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target,
     return;
   }
 
+  const char* pchReuseFrom =
+    target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM");
+
   auto pch_sf = this->Makefile->GetOrCreateSource(
     pchSource, false, cmSourceFileLocationKind::Known);
   std::string pchFile = pchHeader;
 
   if (!this->GetGlobalGenerator()->IsXcode()) {
+    if (!pchReuseFrom) {
+      target->AddSource(pchSource, true);
+    }
+
     // Exclude the pch files from linking
     if (this->Makefile->IsOn("CMAKE_LINK_PCH")) {
-      cmSystemTools::ReplaceString(pchFile, (lang == "C" ? ".h" : ".hxx"),
-                                   pchExtension);
-      pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str());
+
+      auto replaceExtension = [](const std::string& str,
+                                 const std::string& ext) -> std::string {
+        auto dot_pos = str.rfind('.');
+        std::string result;
+        if (dot_pos != std::string::npos) {
+          result = str.substr(0, dot_pos);
+        }
+        result += ext;
+        return result;
+      };
+
+      if (!pchReuseFrom) {
+        std::string pchSourceObj = target->GetPchFileObject(config, lang);
+
+        pchFile = replaceExtension(pchSourceObj, pchExtension);
+        pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str());
+      } else {
+        auto reuseTarget =
+          this->GlobalGenerator->FindGeneratorTarget(pchReuseFrom);
+
+        if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) {
+
+          const std::string pdb_prefix =
+            this->GetGlobalGenerator()->IsMultiConfig()
+            ? cmStrCat(this->GlobalGenerator->GetCMakeCFGIntDir(), "/")
+            : "";
+
+          const std::string target_compile_pdb_dir =
+            cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+                     "/", target->GetName(), ".dir/");
+
+          const std::string copy_script =
+            cmStrCat(target_compile_pdb_dir, "copy_idb_pdb.cmake");
+          cmGeneratedFileStream file(copy_script);
+
+          file << "# CMake generated file\n";
+          for (auto extension : { ".pdb", ".idb" }) {
+            const std::string from_file = cmStrCat(
+              reuseTarget->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+              "/", pchReuseFrom, ".dir/${PDB_PREFIX}", pchReuseFrom,
+              extension);
+
+            const std::string to_dir = cmStrCat(
+              target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/",
+              target->GetName(), ".dir/${PDB_PREFIX}");
+
+            file << "if (EXISTS \"" << from_file << "\")\n";
+            file << "  file(COPY \"" << from_file << "\""
+                 << " DESTINATION \"" << to_dir << "\")\n";
+            file << "endif()\n";
+          }
+
+          cmCustomCommandLines commandLines;
+          cmCustomCommandLine currentLine;
+          currentLine.push_back(cmSystemTools::GetCMakeCommand());
+          currentLine.push_back(cmStrCat("-DPDB_PREFIX=", pdb_prefix));
+          currentLine.push_back("-P");
+          currentLine.push_back(copy_script);
+          commandLines.push_back(std::move(currentLine));
+
+          const std::string no_main_dependency;
+          const std::vector<std::string> no_deps;
+          const char* no_message = "";
+          const char* no_current_dir = nullptr;
+          std::vector<std::string> no_byproducts;
+
+          std::vector<std::string> outputs;
+          outputs.push_back(cmStrCat(target_compile_pdb_dir, pdb_prefix,
+                                     pchReuseFrom, ".pdb"));
+
+          if (this->GetGlobalGenerator()->IsMultiConfig()) {
+            this->Makefile->AddCustomCommandToTarget(
+              target->GetName(), outputs, no_deps, commandLines,
+              cmTarget::PRE_BUILD, no_message, no_current_dir);
+          } else {
+            cmImplicitDependsList no_implicit_depends;
+            cmSourceFile* copy_rule = this->Makefile->AddCustomCommandToOutput(
+              outputs, no_byproducts, no_deps, no_main_dependency,
+              no_implicit_depends, commandLines, no_message, no_current_dir);
+
+            if (copy_rule) {
+              target->AddSource(copy_rule->ResolveFullPath());
+            }
+          }
+
+          target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
+                                      target_compile_pdb_dir.c_str());
+        }
+
+        std::string pchSourceObj = reuseTarget->GetPchFileObject(config, lang);
+
+        // Link to the pch object file
+        target->Target->SetProperty(
+          "LINK_FLAGS",
+          this->ConvertToOutputFormat(pchSourceObj, SHELL).c_str());
+
+        pchFile = replaceExtension(pchSourceObj, pchExtension);
+      }
     } else {
       pchFile += pchExtension;
       pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str());
     }
 
-    target->AddSource(pchSource, true);
-
     for (auto& str : { std::ref(useOptionList), std::ref(createOptionList) }) {
       cmSystemTools::ReplaceString(str, "<PCH_HEADER>", pchHeader);
       cmSystemTools::ReplaceString(str, "<PCH_FILE>", pchFile);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 6637e32..e65fb25 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1085,6 +1085,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
   MAKE_STATIC_PROP(COMPILE_FEATURES);
   MAKE_STATIC_PROP(COMPILE_OPTIONS);
   MAKE_STATIC_PROP(PRECOMPILE_HEADERS);
+  MAKE_STATIC_PROP(PRECOMPILE_HEADERS_REUSE_FROM);
   MAKE_STATIC_PROP(CUDA_PTX_COMPILATION);
   MAKE_STATIC_PROP(EXPORT_NAME);
   MAKE_STATIC_PROP(IMPORTED_GLOBAL);
@@ -1231,6 +1232,41 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
       << impl->Name << "\")\n";
     impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
     return;
+  } else if (prop == propPRECOMPILE_HEADERS_REUSE_FROM) {
+    if (this->GetProperty("PRECOMPILE_HEADERS")) {
+      std::ostringstream e;
+      e << "PRECOMPILE_HEADERS property is already set on target (\""
+        << impl->Name << "\")\n";
+      impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+      return;
+    }
+    auto reusedTarget =
+      impl->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
+        value);
+    if (!reusedTarget) {
+      const std::string e(
+        "PRECOMPILE_HEADERS_REUSE_FROM set with non existing target");
+      impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
+      return;
+    }
+
+    std::string reusedFrom = reusedTarget->GetSafeProperty(prop);
+    if (reusedFrom.empty()) {
+      reusedFrom = value;
+    }
+
+    impl->Properties.SetProperty(prop, reusedFrom.c_str());
+
+    reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom.c_str());
+    reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
+                              cmStrCat(reusedFrom, ".dir/").c_str());
+
+    for (auto p : { "COMPILE_PDB_NAME", "PRECOMPILE_HEADERS",
+                    "INTERFACE_PRECOMPILE_HEADERS" }) {
+      this->SetProperty(p, reusedTarget->GetProperty(p));
+    }
+
+    this->AddUtility(reusedFrom, impl->Makefile);
   } else {
     impl->Properties.SetProperty(prop, value);
   }
@@ -1308,6 +1344,14 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
       impl->LinkDirectoriesBacktraces.push_back(lfbt);
     }
   } else if (prop == "PRECOMPILE_HEADERS") {
+    if (this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) {
+      std::ostringstream e;
+      e << "PRECOMPILE_HEADERS_REUSE_FROM property is already set on target "
+           "(\""
+        << impl->Name << "\")\n";
+      impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str());
+      return;
+    }
     if (value && *value) {
       impl->PrecompileHeadersEntries.emplace_back(value);
       cmListFileBacktrace lfbt = impl->Makefile->GetBacktrace();
diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx
index 30cf1be..97f1bea 100644
--- a/Source/cmTargetPrecompileHeadersCommand.cxx
+++ b/Source/cmTargetPrecompileHeadersCommand.cxx
@@ -10,7 +10,7 @@
 bool cmTargetPrecompileHeadersCommand::InitialPass(
   std::vector<std::string> const& args, cmExecutionStatus&)
 {
-  return this->HandleArguments(args, "PRECOMPILE_HEADERS");
+  return this->HandleArguments(args, "PRECOMPILE_HEADERS", PROCESS_REUSE_FROM);
 }
 
 void cmTargetPrecompileHeadersCommand::HandleMissingTarget(
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 3aa845c..4bc3125 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -65,6 +65,19 @@ bool cmTargetPropCommandBase::HandleArguments(
     ++argIndex;
   }
 
+  if ((flags & PROCESS_REUSE_FROM) && args[argIndex] == "REUSE_FROM") {
+    if (args.size() != 3) {
+      this->SetError("called with incorrect number of arguments");
+      return false;
+    }
+    ++argIndex;
+
+    this->Target->SetProperty("PRECOMPILE_HEADERS_REUSE_FROM",
+                              args[argIndex].c_str());
+
+    ++argIndex;
+  }
+
   this->Property = prop;
 
   while (argIndex < args.size()) {
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index 943285d..b244417 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -17,9 +17,10 @@ class cmTargetPropCommandBase : public cmCommand
 public:
   enum ArgumentFlags
   {
-    NO_FLAGS = 0,
-    PROCESS_BEFORE = 1,
-    PROCESS_SYSTEM = 2
+    NO_FLAGS = 0x0,
+    PROCESS_BEFORE = 0x1,
+    PROCESS_SYSTEM = 0x2,
+    PROCESS_REUSE_FROM = 0x3
   };
 
   bool HandleArguments(std::vector<std::string> const& args,
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake
new file mode 100644
index 0000000..4502456
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake
@@ -0,0 +1,20 @@
+cmake_minimum_required(VERSION 3.15)
+project(PchReuseFrom C)
+
+add_library(empty empty.c)
+target_precompile_headers(empty PUBLIC
+  <stdio.h>
+  <string.h>
+)
+target_include_directories(empty PUBLIC include)
+
+add_library(foo foo.c)
+target_include_directories(foo PUBLIC include)
+target_precompile_headers(foo REUSE_FROM empty)
+
+add_executable(foobar foobar.c)
+target_link_libraries(foobar foo )
+set_target_properties(foobar PROPERTIES PRECOMPILE_HEADERS_REUSE_FROM foo)
+
+enable_testing()
+add_test(NAME foobar COMMAND foobar)
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir-build-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir-build-stderr.txt
new file mode 100644
index 0000000..8cdcfd9
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir-build-stderr.txt
@@ -0,0 +1,2 @@
+^(|Warning #670: precompiled header file [^
+]* was not generated in this directory)$
diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake
new file mode 100644
index 0000000..fff74dc
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake
@@ -0,0 +1,18 @@
+cmake_minimum_required(VERSION 3.15)
+project(PchReuseFromSubdir C)
+
+add_library(empty empty.c)
+target_precompile_headers(empty PUBLIC
+  <stdio.h>
+  <string.h>
+)
+target_include_directories(empty PUBLIC include)
+
+add_library(foo foo.c)
+target_include_directories(foo PUBLIC include)
+target_precompile_headers(foo REUSE_FROM empty)
+
+subdirs(subdir)
+
+enable_testing()
+add_test(NAME foobar COMMAND foobar)
diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
index fffcc47..bd3b1b8 100644
--- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
+++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake
@@ -16,3 +16,5 @@ run_cmake(DisabledPch)
 run_test(PchInterface)
 run_cmake(PchPrologueEpilogue)
 run_test(SkipPrecompileHeaders)
+run_test(PchReuseFrom)
+run_test(PchReuseFromSubdir)
diff --git a/Tests/RunCMake/PrecompileHeaders/empty.c b/Tests/RunCMake/PrecompileHeaders/empty.c
new file mode 100644
index 0000000..30ae1c4
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/empty.c
@@ -0,0 +1,3 @@
+void nothing()
+{
+}
diff --git a/Tests/RunCMake/PrecompileHeaders/include/foo.h b/Tests/RunCMake/PrecompileHeaders/include/foo.h
index 4a49474..fc0ae14 100644
--- a/Tests/RunCMake/PrecompileHeaders/include/foo.h
+++ b/Tests/RunCMake/PrecompileHeaders/include/foo.h
@@ -1,6 +1,6 @@
 #ifndef foo_h
 #define foo_h
 
-extern int foo();
+int foo(void);
 
 #endif
diff --git a/Tests/RunCMake/PrecompileHeaders/subdir/CMakeLists.txt b/Tests/RunCMake/PrecompileHeaders/subdir/CMakeLists.txt
new file mode 100644
index 0000000..fa926c4
--- /dev/null
+++ b/Tests/RunCMake/PrecompileHeaders/subdir/CMakeLists.txt
@@ -0,0 +1,3 @@
+add_executable(foobar ../foobar.c)
+target_link_libraries(foobar foo )
+set_target_properties(foobar PROPERTIES PRECOMPILE_HEADERS_REUSE_FROM foo)

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

Summary of changes:
 Help/command/target_precompile_headers.rst         |  14 +++
 Help/manual/cmake-properties.7.rst                 |   1 +
 Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst    |   7 ++
 Modules/Platform/Windows-MSVC.cmake                |  13 +-
 Source/CPack/cmCPackGeneratorFactory.cxx           |  25 +---
 Source/CPack/cmCPackGeneratorFactory.h             |  12 +-
 Source/CPack/cpack.cxx                             |   5 +-
 Source/cmCommonTargetGenerator.cxx                 |   1 +
 Source/cmGeneratorTarget.cxx                       | 131 ++++++++++++++-------
 Source/cmGeneratorTarget.h                         |   3 +
 Source/cmLocalGenerator.cxx                        | 113 +++++++++++++++++-
 Source/cmTarget.cxx                                |  44 +++++++
 Source/cmTargetPrecompileHeadersCommand.cxx        |   2 +-
 Source/cmTargetPropCommandBase.cxx                 |  13 ++
 Source/cmTargetPropCommandBase.h                   |   7 +-
 .../RunCMake/PrecompileHeaders/PchReuseFrom.cmake  |  20 ++++
 .../PchReuseFromSubdir-build-stderr.txt            |   2 +
 .../PrecompileHeaders/PchReuseFromSubdir.cmake     |  18 +++
 .../RunCMake/PrecompileHeaders/RunCMakeTest.cmake  |   2 +
 Tests/RunCMake/PrecompileHeaders/empty.c           |   3 +
 Tests/RunCMake/PrecompileHeaders/include/foo.h     |   2 +-
 .../PrecompileHeaders/subdir/CMakeLists.txt        |   3 +
 22 files changed, 356 insertions(+), 85 deletions(-)
 create mode 100644 Help/prop_tgt/PRECOMPILE_HEADERS_REUSE_FROM.rst
 create mode 100644 Tests/RunCMake/PrecompileHeaders/PchReuseFrom.cmake
 create mode 100644 Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir-build-stderr.txt
 create mode 100644 Tests/RunCMake/PrecompileHeaders/PchReuseFromSubdir.cmake
 create mode 100644 Tests/RunCMake/PrecompileHeaders/empty.c
 create mode 100644 Tests/RunCMake/PrecompileHeaders/subdir/CMakeLists.txt


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list