Forráskód Böngészése

Merge topic 'fileApiAddPrecompileHeadersBacktrace'

9f6d40ee23 fileapi: Extend codemodel targets with PRECOMPILE_HEADERS
b698764a31 Tests: Add a PCH example to RunCMake.FileAPI codemodel-v2
b3812c0e54 Tests: Fix indentation in RunCMake.FileAPI cxx_exe.json
9c48804b69 PCH: Fix source group of per-architecture PCH headers

Acked-by: Kitware Robot <[email protected]>
Merge-request: !4684
Brad King 5 éve
szülő
commit
15b9b41d72

+ 16 - 0
Help/manual/cmake-file-api.7.rst

@@ -899,6 +899,22 @@ with members:
       an unsigned integer 0-based index into the ``backtraceGraph``
       member's ``nodes`` array.
 
+  ``precompileHeaders``
+    Optional member that is present when :command:`target_precompile_headers`
+    or other command invocations set :prop_tgt:`PRECOMPILE_HEADERS` on the
+    target.  The value is a JSON array with an entry for each header.  Each
+    entry is a JSON object with members:
+
+    ``header``
+      Full path to the precompile header file.
+
+    ``backtrace``
+      Optional member that is present when a CMake language backtrace to
+      the :command:`target_precompile_headers` or other command invocation
+      that added this precompiled header is available.  The value is an
+      unsigned integer 0-based index into the ``backtraceGraph`` member's
+      ``nodes`` array.
+
   ``defines``
     Optional member that is present when there are preprocessor definitions.
     The value is a JSON array with an entry for each definition.  Each

+ 1 - 1
Source/cmFileAPI.cxx

@@ -665,7 +665,7 @@ std::string cmFileAPI::NoSupportedVersion(
 
 // The "codemodel" object kind.
 
-static unsigned int const CodeModelV2Minor = 0;
+static unsigned int const CodeModelV2Minor = 1;
 
 void cmFileAPI::BuildClientRequestCodeModel(
   ClientRequest& r, std::vector<RequestVersion> const& versions)

+ 30 - 0
Source/cmFileAPICodemodel.cxx

@@ -278,12 +278,14 @@ struct CompileData
   std::string Sysroot;
   std::vector<JBT<std::string>> Flags;
   std::vector<JBT<std::string>> Defines;
+  std::vector<JBT<std::string>> PrecompileHeaders;
   std::vector<IncludeEntry> Includes;
 
   friend bool operator==(CompileData const& l, CompileData const& r)
   {
     return (l.Language == r.Language && l.Sysroot == r.Sysroot &&
             l.Flags == r.Flags && l.Defines == r.Defines &&
+            l.PrecompileHeaders == r.PrecompileHeaders &&
             l.Includes == r.Includes);
   }
 };
@@ -313,6 +315,10 @@ struct hash<CompileData>
       result = result ^ hash<std::string>()(i.Value) ^
         hash<Json::ArrayIndex>()(i.Backtrace.Index);
     }
+    for (auto const& i : in.PrecompileHeaders) {
+      result = result ^ hash<std::string>()(i.Value) ^
+        hash<Json::ArrayIndex>()(i.Backtrace.Index);
+    }
     return result;
   }
 };
@@ -369,6 +375,7 @@ class Target
   Json::Value DumpPaths();
   Json::Value DumpCompileData(CompileData const& cd);
   Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
+  Json::Value DumpPrecompileHeader(JBT<std::string> const& header);
   Json::Value DumpDefine(JBT<std::string> const& def);
   Json::Value DumpSources();
   Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
@@ -825,6 +832,11 @@ void Target::ProcessLanguage(std::string const& lang)
       this->ToJBT(i),
       this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
   }
+  std::vector<BT<std::string>> precompileHeaders =
+    this->GT->GetPrecompileHeaders(this->Config, lang);
+  for (BT<std::string> const& pch : precompileHeaders) {
+    cd.PrecompileHeaders.emplace_back(this->ToJBT(pch));
+  }
 }
 
 Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si)
@@ -980,6 +992,9 @@ CompileData Target::MergeCompileData(CompileData const& fd)
   // All compile groups share the sysroot of the target.
   cd.Sysroot = td.Sysroot;
 
+  // All compile groups share the precompile headers of the target.
+  cd.PrecompileHeaders = td.PrecompileHeaders;
+
   // Use target-wide flags followed by source-specific flags.
   cd.Flags.reserve(td.Flags.size() + fd.Flags.size());
   cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end());
@@ -1130,6 +1145,13 @@ Json::Value Target::DumpCompileData(CompileData const& cd)
     }
     result["defines"] = std::move(defines);
   }
+  if (!cd.PrecompileHeaders.empty()) {
+    Json::Value precompileHeaders = Json::arrayValue;
+    for (JBT<std::string> const& pch : cd.PrecompileHeaders) {
+      precompileHeaders.append(this->DumpPrecompileHeader(pch));
+    }
+    result["precompileHeaders"] = std::move(precompileHeaders);
+  }
 
   return result;
 }
@@ -1145,6 +1167,14 @@ Json::Value Target::DumpInclude(CompileData::IncludeEntry const& inc)
   return include;
 }
 
+Json::Value Target::DumpPrecompileHeader(JBT<std::string> const& header)
+{
+  Json::Value precompileHeader = Json::objectValue;
+  precompileHeader["header"] = header.Value;
+  this->AddBacktrace(precompileHeader, header.Backtrace);
+  return precompileHeader;
+}
+
 Json::Value Target::DumpDefine(JBT<std::string> const& def)
 {
   Json::Value define = Json::objectValue;

+ 1 - 1
Source/cmSourceFile.h

@@ -159,7 +159,7 @@ private:
   "\\.(C|F|M|c|c\\+\\+|cc|cpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|"                 \
   "rc|def|r|odl|idl|hpj|bat)$"
 
-#define CM_PCH_REGEX "cmake_pch\\.(h|hxx)$"
+#define CM_PCH_REGEX "cmake_pch(_[^.]+)?\\.(h|hxx)$"
 
 #define CM_RESOURCE_REGEX "\\.(pdf|plist|png|jpeg|jpg|storyboard|xcassets)$"
 

+ 2 - 1
Tests/RunCMake/CMakeLists.txt

@@ -203,7 +203,8 @@ endif()
 add_RunCMake_test(ExternalData)
 add_RunCMake_test(FeatureSummary)
 add_RunCMake_test(FPHSA)
-add_RunCMake_test(FileAPI -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE})
+add_RunCMake_test(FileAPI -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}
+                          -DCMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID})
 add_RunCMake_test(FindBoost)
 add_RunCMake_test(FindLua)
 add_RunCMake_test(FindOpenGL)

+ 1 - 1
Tests/RunCMake/CommandLine/E_capabilities-stdout.txt

@@ -1 +1 @@
-^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":0}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":true,"version":{.*}}$
+^{"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":1}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":true,"version":{.*}}$

+ 1 - 1
Tests/RunCMake/FileAPI/RunCMakeTest.cmake

@@ -23,7 +23,7 @@ function(check_python case)
   endif()
   file(GLOB index ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/reply/index-*.json)
   execute_process(
-    COMMAND ${PYTHON_EXECUTABLE} "${RunCMake_SOURCE_DIR}/${case}-check.py" "${index}"
+    COMMAND ${PYTHON_EXECUTABLE} "${RunCMake_SOURCE_DIR}/${case}-check.py" "${index}" "${CMAKE_CXX_COMPILER_ID}"
     RESULT_VARIABLE result
     OUTPUT_VARIABLE output
     ERROR_VARIABLE output

+ 33 - 1
Tests/RunCMake/FileAPI/codemodel-v2-check.py

@@ -12,7 +12,7 @@ def read_codemodel_json_data(filename):
 def check_objects(o, g):
     assert is_list(o)
     assert len(o) == 1
-    check_index_object(o[0], "codemodel", 2, 0, check_object_codemodel(g))
+    check_index_object(o[0], "codemodel", 2, 1, check_object_codemodel(g))
 
 def check_backtrace(t, b, backtrace):
     btg = t["backtraceGraph"]
@@ -404,6 +404,23 @@ def check_target(c):
                                      missing_exception=lambda e: "Include path: %s" % e["path"],
                                      extra_exception=lambda a: "Include path: %s" % a["path"])
 
+                if "precompileHeaders" in expected:
+                    expected_keys.append("precompileHeaders")
+
+                    def check_precompile_header(actual, expected):
+                        assert is_dict(actual)
+                        expected_keys = ["backtrace", "header"]
+                        check_backtrace(obj, actual["backtrace"], expected["backtrace"])
+
+                        assert sorted(actual.keys()) == sorted(expected_keys)
+
+                    check_list_match(lambda a, e: matches(a["header"], e["header"]),
+                                     actual["precompileHeaders"], expected["precompileHeaders"],
+                                     check=check_precompile_header,
+                                     check_exception=lambda a, e: "Precompile header: %s" % a["header"],
+                                     missing_exception=lambda e: "Precompile header: %s" % e["header"],
+                                     extra_exception=lambda a: "Precompile header: %s" % a["header"])
+
                 if expected["defines"] is not None:
                     expected_keys.append("defines")
 
@@ -561,6 +578,20 @@ def gen_check_targets(c, g, inSource):
         read_codemodel_json_data("targets/generated_exe.json"),
     ]
 
+    if cxx_compiler_id in ['Clang', 'AppleClang', 'GNU', 'Intel', 'MSVC', 'Embarcadero'] and g["name"] != "Xcode":
+        for e in expected:
+            if e["name"] == "cxx_exe":
+                if matches(g["name"], "^(Visual Studio |Ninja Multi-Config)"):
+                    precompile_header_data = read_codemodel_json_data("targets/cxx_exe_precompileheader_multigen.json")
+                else:
+                    if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""):
+                        precompile_header_data = read_codemodel_json_data("targets/cxx_exe_precompileheader_2arch.json")
+                    else:
+                        precompile_header_data = read_codemodel_json_data("targets/cxx_exe_precompileheader.json")
+                e["compileGroups"] = precompile_header_data["compileGroups"]
+                e["sources"] = precompile_header_data["sources"]
+                e["sourceGroups"] = precompile_header_data["sourceGroups"]
+
     if not os.path.exists(os.path.join(reply_dir, "..", "..", "..", "..", "ipo_enabled.txt")):
         for e in expected:
             try:
@@ -715,6 +746,7 @@ def check_object_codemodel(g):
             check_object_codemodel_configuration(c, g, inSource)
     return _check
 
+cxx_compiler_id = sys.argv[2]
 assert is_dict(index)
 assert sorted(index.keys()) == ["cmake", "objects", "reply"]
 check_objects(index["objects"], index["cmake"]["generator"])

+ 21 - 2
Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe.json

@@ -43,17 +43,36 @@
             ],
             "includes": null,
             "defines": null,
+            "precompileHeaders": [
+              {
+                "header": ".*empty\\.h$",
+                "backtrace": [
+                  {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": 21,
+                    "command": "target_precompile_headers",
+                    "hasParent": true
+                  },
+                  {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": null,
+                    "command": null,
+                    "hasParent": false
+                  }
+                ]
+              }
+            ],
             "compileCommandFragments": [
                 {
                     "fragment" : "TargetCompileOptions",
-							"backtrace": [
+                    "backtrace": [
                         {
                             "file": "^cxx/CMakeLists\\.txt$",
                             "line": 17,
                             "command": "target_compile_options",
                             "hasParent": true
                         },
-								{
+                        {
                             "file" : "^cxx/CMakeLists\\.txt$",
                             "line": null,
                             "command": null,

+ 161 - 0
Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader.json

@@ -0,0 +1,161 @@
+{
+  "compileGroups": [
+    {
+      "language": "CXX",
+      "sourcePaths": [
+        ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$"
+      ],
+      "includes": null,
+      "defines": null,
+      "precompileHeaders": [
+        {
+          "header": ".*empty\\.h$",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 21,
+              "command": "target_precompile_headers",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ],
+      "compileCommandFragments": [
+        {
+          "fragment": "TargetCompileOptions",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 17,
+              "command": "target_compile_options",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "language": "CXX",
+      "sourcePaths": [
+        "^empty\\.cxx$"
+      ],
+      "includes": null,
+      "defines": null,
+      "precompileHeaders": [
+        {
+          "header": ".*empty\\.h$",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 21,
+              "command": "target_precompile_headers",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ],
+      "compileCommandFragments": [
+        {
+          "fragment": "TargetCompileOptions",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 17,
+              "command": "target_compile_options",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ]
+    }
+  ],
+  "sources": [
+    {
+      "path": ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Source Files",
+      "compileGroupLanguage": "CXX",
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": "^empty\\.cxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Source Files",
+      "compileGroupLanguage": "CXX",
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": 5,
+          "command": "add_executable",
+          "hasParent": true
+        },
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": ".*/cmake_pch(_[^.]+)?\\.hxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Precompile Header File",
+      "compileGroupLanguage": null,
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    }
+  ],
+  "sourceGroups": [
+    {
+      "name": "Source Files",
+      "sourcePaths": [
+        ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$",
+        "^empty\\.cxx$"
+      ]
+    },
+    {
+      "name": "Precompile Header File",
+      "sourcePaths": [
+        ".*/cmake_pch(_[^.]+)?\\.hxx$"
+      ]
+    }
+  ]
+}

+ 237 - 0
Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_2arch.json

@@ -0,0 +1,237 @@
+{
+  "compileGroups": [
+    {
+      "language": "CXX",
+      "sourcePaths": [
+        ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$"
+      ],
+      "includes": null,
+      "defines": null,
+      "precompileHeaders": [
+        {
+          "header": ".*empty\\.h$",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 21,
+              "command": "target_precompile_headers",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ],
+      "compileCommandFragments": [
+        {
+          "fragment": "TargetCompileOptions",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 17,
+              "command": "target_compile_options",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "language": "CXX",
+      "sourcePaths": [
+        ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$"
+      ],
+      "includes": null,
+      "defines": null,
+      "precompileHeaders": [
+        {
+          "header": ".*empty\\.h$",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 21,
+              "command": "target_precompile_headers",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ],
+      "compileCommandFragments": [
+        {
+          "fragment": "TargetCompileOptions",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 17,
+              "command": "target_compile_options",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "language": "CXX",
+      "sourcePaths": [
+        "^empty\\.cxx$"
+      ],
+      "includes": null,
+      "defines": null,
+      "precompileHeaders": [
+        {
+          "header": ".*empty\\.h$",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 21,
+              "command": "target_precompile_headers",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ],
+      "compileCommandFragments": [
+        {
+          "fragment": "TargetCompileOptions",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 17,
+              "command": "target_compile_options",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ]
+    }
+  ],
+  "sources": [
+    {
+      "path": ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Source Files",
+      "compileGroupLanguage": "CXX",
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Source Files",
+      "compileGroupLanguage": "CXX",
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": "^empty\\.cxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Source Files",
+      "compileGroupLanguage": "CXX",
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": 5,
+          "command": "add_executable",
+          "hasParent": true
+        },
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": ".*/cmake_pch(_[^.]+)?\\.hxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Precompile Header File",
+      "compileGroupLanguage": null,
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": ".*/cmake_pch(_[^.]+)?\\.hxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Precompile Header File",
+      "compileGroupLanguage": null,
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    }
+  ],
+  "sourceGroups": [
+    {
+      "name": "Source Files",
+      "sourcePaths": [
+        ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$",
+        ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$",
+        "^empty\\.cxx$"
+      ]
+    },
+    {
+      "name": "Precompile Header File",
+      "sourcePaths": [
+        ".*/cmake_pch(_[^.]+)?\\.hxx$",
+        ".*/cmake_pch(_[^.]+)?\\.hxx$"
+      ]
+    }
+  ]
+}

+ 206 - 0
Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_exe_precompileheader_multigen.json

@@ -0,0 +1,206 @@
+{
+  "compileGroups": [
+    {
+      "language": "CXX",
+      "sourcePaths": [
+        ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$"
+      ],
+      "includes": null,
+      "defines": null,
+      "precompileHeaders": [
+        {
+          "header": ".*empty\\.h$",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 21,
+              "command": "target_precompile_headers",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ],
+      "compileCommandFragments": [
+        {
+          "fragment": "TargetCompileOptions",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 17,
+              "command": "target_compile_options",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ]
+    },
+    {
+      "language": "CXX",
+      "sourcePaths": [
+        "^empty\\.cxx$"
+      ],
+      "includes": null,
+      "defines": null,
+      "precompileHeaders": [
+        {
+          "header": ".*empty\\.h$",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 21,
+              "command": "target_precompile_headers",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ],
+      "compileCommandFragments": [
+        {
+          "fragment": "TargetCompileOptions",
+          "backtrace": [
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": 17,
+              "command": "target_compile_options",
+              "hasParent": true
+            },
+            {
+              "file": "^cxx/CMakeLists\\.txt$",
+              "line": null,
+              "command": null,
+              "hasParent": false
+            }
+          ]
+        }
+      ]
+    }
+  ],
+  "sources": [
+    {
+      "path": ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Source Files",
+      "compileGroupLanguage": "CXX",
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": "^empty\\.cxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Source Files",
+      "compileGroupLanguage": "CXX",
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": 5,
+          "command": "add_executable",
+          "hasParent": true
+        },
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": ".*/Debug/cmake_pch(_[^.]+)?\\.hxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Precompile Header File",
+      "compileGroupLanguage": null,
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": ".*/Release/cmake_pch(_[^.]+)?\\.hxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Precompile Header File",
+      "compileGroupLanguage": null,
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": ".*/MinSizeRel/cmake_pch(_[^.]+)?\\.hxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Precompile Header File",
+      "compileGroupLanguage": null,
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    },
+    {
+      "path": ".*/RelWithDebInfo/cmake_pch(_[^.]+)?\\.hxx$",
+      "isGenerated": null,
+      "sourceGroupName": "Precompile Header File",
+      "compileGroupLanguage": null,
+      "backtrace": [
+        {
+          "file": "^cxx/CMakeLists\\.txt$",
+          "line": null,
+          "command": null,
+          "hasParent": false
+        }
+      ]
+    }
+  ],
+  "sourceGroups": [
+    {
+      "name": "Source Files",
+      "sourcePaths": [
+        ".*cmake_pch(_[^.]+)?(\\.hxx)?\\.cxx$",
+        "^empty\\.cxx$"
+      ]
+    },
+    {
+      "name": "Precompile Header File",
+      "sourcePaths": [
+        ".*/Debug/cmake_pch(_[^.]+)?\\.hxx$",
+        ".*/Release/cmake_pch(_[^.]+)?\\.hxx$",
+        ".*/MinSizeRel/cmake_pch(_[^.]+)?\\.hxx$",
+        ".*/RelWithDebInfo/cmake_pch(_[^.]+)?\\.hxx$"
+      ]
+    }
+  ]
+}

+ 2 - 0
Tests/RunCMake/FileAPI/cxx/CMakeLists.txt

@@ -17,3 +17,5 @@ target_link_libraries(cxx_static_exe PRIVATE cxx_static_lib)
 target_compile_options(cxx_exe PUBLIC TargetCompileOptions)
 target_link_options(cxx_exe PUBLIC TargetLinkOptions)
 target_link_directories(cxx_exe PUBLIC "${CMAKE_BINARY_DIR}/TargetLinkDir")
+
+target_precompile_headers(cxx_exe PUBLIC ../empty.h)

+ 0 - 0
Tests/RunCMake/FileAPI/empty.h