Просмотр исходного кода

Merge topic 'fileapi'

b9c6f08276 Help: Add release note for fileapi feature
4b6b2a571c fileapi: extend codemodel v2 with directory details
eb8c7676a4 fileapi: extend codemodel v2 with a project model
42f0125ceb fileapi: Add test for cmakeFiles v1
6615408193 fileapi: add cmakeFiles v1
3f6ee75a66 fileapi: Add test for cache v2
7489e95b8e fileapi: add cache v2
ea0a060168 fileapi: Add test for codemodel v2
...

Acked-by: Kitware Robot <[email protected]>
Merge-request: !2706
Brad King 7 лет назад
Родитель
Сommit
dc90cd6877
100 измененных файлов с 10168 добавлено и 4 удалено
  1. 1 1
      CMakeLists.txt
  2. 1 0
      Help/index.rst
  3. 1111 0
      Help/manual/cmake-file-api.7.rst
  4. 5 0
      Help/release/dev/fileapi.rst
  5. 8 0
      Source/CMakeLists.txt
  6. 800 0
      Source/cmFileAPI.cxx
  7. 204 0
      Source/cmFileAPI.h
  8. 113 0
      Source/cmFileAPICMakeFiles.cxx
  9. 15 0
      Source/cmFileAPICMakeFiles.h
  10. 105 0
      Source/cmFileAPICache.cxx
  11. 15 0
      Source/cmFileAPICache.h
  12. 1247 0
      Source/cmFileAPICodemodel.cxx
  13. 15 0
      Source/cmFileAPICodemodel.h
  14. 9 0
      Source/cmGlobalGenerator.cxx
  15. 6 0
      Source/cmGlobalGenerator.h
  16. 9 0
      Source/cmGlobalVisualStudio7Generator.cxx
  17. 4 0
      Source/cmGlobalVisualStudio7Generator.h
  18. 6 0
      Source/cmStateSnapshot.cxx
  19. 1 0
      Source/cmStateSnapshot.h
  20. 3 3
      Source/cmTimestamp.h
  21. 10 0
      Source/cmake.cxx
  22. 3 0
      Source/cmake.h
  23. 4 0
      Tests/RunCMake/CMakeLists.txt
  24. 3 0
      Tests/RunCMake/FileAPI/CMakeLists.txt
  25. 68 0
      Tests/RunCMake/FileAPI/ClientStateful-check.cmake
  26. 258 0
      Tests/RunCMake/FileAPI/ClientStateful-check.py
  27. 73 0
      Tests/RunCMake/FileAPI/ClientStateful-prep.cmake
  28. 0 0
      Tests/RunCMake/FileAPI/ClientStateful.cmake
  29. 15 0
      Tests/RunCMake/FileAPI/ClientStateless-check.cmake
  30. 26 0
      Tests/RunCMake/FileAPI/ClientStateless-check.py
  31. 5 0
      Tests/RunCMake/FileAPI/ClientStateless-prep.cmake
  32. 0 0
      Tests/RunCMake/FileAPI/ClientStateless.cmake
  33. 20 0
      Tests/RunCMake/FileAPI/DuplicateStateless-check.cmake
  34. 31 0
      Tests/RunCMake/FileAPI/DuplicateStateless-check.py
  35. 10 0
      Tests/RunCMake/FileAPI/DuplicateStateless-prep.cmake
  36. 0 0
      Tests/RunCMake/FileAPI/DuplicateStateless.cmake
  37. 8 0
      Tests/RunCMake/FileAPI/Empty-check.cmake
  38. 15 0
      Tests/RunCMake/FileAPI/Empty-check.py
  39. 1 0
      Tests/RunCMake/FileAPI/Empty-prep.cmake
  40. 0 0
      Tests/RunCMake/FileAPI/Empty.cmake
  41. 9 0
      Tests/RunCMake/FileAPI/EmptyClient-check.cmake
  42. 20 0
      Tests/RunCMake/FileAPI/EmptyClient-check.py
  43. 2 0
      Tests/RunCMake/FileAPI/EmptyClient-prep.cmake
  44. 0 0
      Tests/RunCMake/FileAPI/EmptyClient.cmake
  45. 16 0
      Tests/RunCMake/FileAPI/MixedStateless-check.cmake
  46. 27 0
      Tests/RunCMake/FileAPI/MixedStateless-check.py
  47. 6 0
      Tests/RunCMake/FileAPI/MixedStateless-prep.cmake
  48. 0 0
      Tests/RunCMake/FileAPI/MixedStateless.cmake
  49. 1 0
      Tests/RunCMake/FileAPI/Nothing-check.cmake
  50. 1 0
      Tests/RunCMake/FileAPI/Nothing-prep.cmake
  51. 0 0
      Tests/RunCMake/FileAPI/Nothing.cmake
  52. 58 0
      Tests/RunCMake/FileAPI/RunCMakeTest.cmake
  53. 15 0
      Tests/RunCMake/FileAPI/SharedStateless-check.cmake
  54. 22 0
      Tests/RunCMake/FileAPI/SharedStateless-check.py
  55. 6 0
      Tests/RunCMake/FileAPI/SharedStateless-prep.cmake
  56. 0 0
      Tests/RunCMake/FileAPI/SharedStateless.cmake
  57. 4 0
      Tests/RunCMake/FileAPI/Stale-check.cmake
  58. 1 0
      Tests/RunCMake/FileAPI/Stale-prep.cmake
  59. 0 0
      Tests/RunCMake/FileAPI/Stale.cmake
  60. 10 0
      Tests/RunCMake/FileAPI/alias/CMakeLists.txt
  61. 11 0
      Tests/RunCMake/FileAPI/cache-v2-ClientStateful-check.cmake
  62. 4 0
      Tests/RunCMake/FileAPI/cache-v2-ClientStateful-prep.cmake
  63. 11 0
      Tests/RunCMake/FileAPI/cache-v2-ClientStateless-check.cmake
  64. 2 0
      Tests/RunCMake/FileAPI/cache-v2-ClientStateless-prep.cmake
  65. 10 0
      Tests/RunCMake/FileAPI/cache-v2-SharedStateless-check.cmake
  66. 2 0
      Tests/RunCMake/FileAPI/cache-v2-SharedStateless-prep.cmake
  67. 134 0
      Tests/RunCMake/FileAPI/cache-v2-check.py
  68. 14 0
      Tests/RunCMake/FileAPI/cache-v2.cmake
  69. 163 0
      Tests/RunCMake/FileAPI/check_index.py
  70. 11 0
      Tests/RunCMake/FileAPI/cmakeFiles-v1-ClientStateful-check.cmake
  71. 4 0
      Tests/RunCMake/FileAPI/cmakeFiles-v1-ClientStateful-prep.cmake
  72. 11 0
      Tests/RunCMake/FileAPI/cmakeFiles-v1-ClientStateless-check.cmake
  73. 2 0
      Tests/RunCMake/FileAPI/cmakeFiles-v1-ClientStateless-prep.cmake
  74. 10 0
      Tests/RunCMake/FileAPI/cmakeFiles-v1-SharedStateless-check.cmake
  75. 2 0
      Tests/RunCMake/FileAPI/cmakeFiles-v1-SharedStateless-prep.cmake
  76. 94 0
      Tests/RunCMake/FileAPI/cmakeFiles-v1-check.py
  77. 8 0
      Tests/RunCMake/FileAPI/cmakeFiles-v1.cmake
  78. 12 0
      Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake
  79. 4 0
      Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-prep.cmake
  80. 12 0
      Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake
  81. 2 0
      Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-prep.cmake
  82. 11 0
      Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake
  83. 2 0
      Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-prep.cmake
  84. 5085 0
      Tests/RunCMake/FileAPI/codemodel-v2-check.py
  85. 35 0
      Tests/RunCMake/FileAPI/codemodel-v2.cmake
  86. 5 0
      Tests/RunCMake/FileAPI/custom/CMakeLists.txt
  87. 15 0
      Tests/RunCMake/FileAPI/cxx/CMakeLists.txt
  88. 1 0
      Tests/RunCMake/FileAPI/dir/CMakeLists.txt
  89. 0 0
      Tests/RunCMake/FileAPI/dir/dir/CMakeLists.txt
  90. 0 0
      Tests/RunCMake/FileAPI/dir/dirtest.cmake
  91. 0 0
      Tests/RunCMake/FileAPI/empty.c
  92. 0 0
      Tests/RunCMake/FileAPI/empty.cxx
  93. 24 0
      Tests/RunCMake/FileAPI/imported/CMakeLists.txt
  94. 9 0
      Tests/RunCMake/FileAPI/include_test.cmake
  95. 13 0
      Tests/RunCMake/FileAPI/object/CMakeLists.txt
  96. 0 0
      Tests/RunCMake/FileAPIDummyFile.cmake
  97. 12 0
      Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt
  98. 0 0
      Tests/RunCMake/FileAPIExternalSource/empty.c
  99. 5 0
      Tests/RunCMake/RunCMake.cmake
  100. 2 0
      Utilities/IWYU/mapping.imp

+ 1 - 1
CMakeLists.txt

@@ -538,7 +538,7 @@ macro (CMAKE_BUILD_UTILITIES)
   #---------------------------------------------------------------------
   # Build jsoncpp library.
   if(CMAKE_USE_SYSTEM_JSONCPP)
-    find_package(JsonCpp)
+    find_package(JsonCpp 1.4.1)
     if(NOT JsonCpp_FOUND)
       message(FATAL_ERROR
         "CMAKE_USE_SYSTEM_JSONCPP is ON but a JsonCpp is not found!")

+ 1 - 0
Help/index.rst

@@ -30,6 +30,7 @@ Reference Manuals
    /manual/cmake-compile-features.7
    /manual/cmake-developer.7
    /manual/cmake-env-variables.7
+   /manual/cmake-file-api.7
    /manual/cmake-generator-expressions.7
    /manual/cmake-generators.7
    /manual/cmake-language.7

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

@@ -0,0 +1,1111 @@
+.. cmake-manual-description: CMake File-Based API
+
+cmake-file-api(7)
+*****************
+
+.. only:: html
+
+   .. contents::
+
+Introduction
+============
+
+CMake provides a file-based API that clients may use to get semantic
+information about the buildsystems CMake generates.  Clients may use
+the API by writing query files to a specific location in a build tree
+to request zero or more `Object Kinds`_.  When CMake generates the
+buildsystem in that build tree it will read the query files and write
+reply files for the client to read.
+
+The file-based API uses a ``<build>/.cmake/api/`` directory at the top
+of a build tree.  The API is versioned to support changes to the layout
+of files within the API directory.  API file layout versioning is
+orthogonal to the versioning of `Object Kinds`_ used in replies.
+This version of CMake supports only one API version, `API v1`_.
+
+API v1
+======
+
+API v1 is housed in the ``<build>/.cmake/api/v1/`` directory.
+It has the following subdirectories:
+
+``query/``
+  Holds query files written by clients.
+  These may be `v1 Shared Stateless Query Files`_,
+  `v1 Client Stateless Query Files`_, or `v1 Client Stateful Query Files`_.
+
+``reply/``
+  Holds reply files written by CMake whenever it runs to generate a build
+  system.  These are indexed by a `v1 Reply Index File`_ file that may
+  reference additional `v1 Reply Files`_.  CMake owns all reply files.
+  Clients must never remove them.
+
+  Clients may look for and read a reply index file at any time.
+  Clients may optionally create the ``reply/`` directory at any time
+  and monitor it for the appearance of a new reply index file.
+
+v1 Shared Stateless Query Files
+-------------------------------
+
+Shared stateless query files allow clients to share requests for
+major versions of the `Object Kinds`_ and get all requested versions
+recognized by the CMake that runs.
+
+Clients may create shared requests by creating empty files in the
+``v1/query/`` directory.  The form is::
+
+  <build>/.cmake/api/v1/query/<kind>-v<major>
+
+where ``<kind>`` is one of the `Object Kinds`_, ``-v`` is literal,
+and ``<major>`` is the major version number.
+
+Files of this form are stateless shared queries not owned by any specific
+client.  Once created they should not be removed without external client
+coordination or human intervention.
+
+v1 Client Stateless Query Files
+-------------------------------
+
+Client stateless query files allow clients to create owned requests for
+major versions of the `Object Kinds`_ and get all requested versions
+recognized by the CMake that runs.
+
+Clients may create owned requests by creating empty files in
+client-specific query subdirectories.  The form is::
+
+  <build>/.cmake/api/v1/query/client-<client>/<kind>-v<major>
+
+where ``client-`` is literal, ``<client>`` is a string uniquely
+identifying the client, ``<kind>`` is one of the `Object Kinds`_,
+``-v`` is literal, and ``<major>`` is the major version number.
+Each client must choose a unique ``<client>`` identifier via its
+own means.
+
+Files of this form are stateless queries owned by the client ``<client>``.
+The owning client may remove them at any time.
+
+v1 Client Stateful Query Files
+------------------------------
+
+Stateful query files allow clients to request a list of versions of
+each of the `Object Kinds`_ and get only the most recent version
+recognized by the CMake that runs.
+
+Clients may create owned stateful queries by creating ``query.json``
+files in client-specific query subdirectories.  The form is::
+
+  <build>/.cmake/api/v1/query/client-<client>/query.json
+
+where ``client-`` is literal, ``<client>`` is a string uniquely
+identifying the client, and ``query.json`` is literal.  Each client
+must choose a unique ``<client>`` identifier via its own means.
+
+``query.json`` files are stateful queries owned by the client ``<client>``.
+The owning client may update or remove them at any time.  When a
+given client installation is updated it may then update the stateful
+query it writes to build trees to request newer object versions.
+This can be used to avoid asking CMake to generate multiple object
+versions unnecessarily.
+
+A ``query.json`` file must contain a JSON object:
+
+.. code-block:: json
+
+  {
+    "requests": [
+      { "kind": "<kind>" , "version": 1 },
+      { "kind": "<kind>" , "version": { "major": 1, "minor": 2 } },
+      { "kind": "<kind>" , "version": [2, 1] },
+      { "kind": "<kind>" , "version": [2, { "major": 1, "minor": 2 }] },
+      { "kind": "<kind>" , "version": 1, "client": {} },
+      { "kind": "..." }
+    ],
+    "client": {}
+  }
+
+The members are:
+
+``requests``
+  A JSON array containing zero or more requests.  Each request is
+  a JSON object with members:
+
+  ``kind``
+    Specifies one of the `Object Kinds`_ to be included in the reply.
+
+  ``version``
+    Indicates the version(s) of the object kind that the client
+    understands.  Versions have major and minor components following
+    semantic version conventions.  The value must be
+
+    * a JSON integer specifying a (non-negative) major version number, or
+    * a JSON object containing ``major`` and (optionally) ``minor``
+      members specifying non-negative integer version components, or
+    * a JSON array whose elements are each one of the above.
+
+  ``client``
+    Optional member reserved for use by the client.  This value is
+    preserved in the reply written for the client in the
+    `v1 Reply Index File`_ but is otherwise ignored.  Clients may use
+    this to pass custom information with a request through to its reply.
+
+  For each requested object kind CMake will choose the *first* version
+  that it recognizes for that kind among those listed in the request.
+  The response will use the selected *major* version with the highest
+  *minor* version known to the running CMake for that major version.
+  Therefore clients should list all supported major versions in
+  preferred order along with the minimal minor version required
+  for each major version.
+
+``client``
+  Optional member reserved for use by the client.  This value is
+  preserved in the reply written for the client in the
+  `v1 Reply Index File`_ but is otherwise ignored.  Clients may use
+  this to pass custom information with a query through to its reply.
+
+Other ``query.json`` top-level members are reserved for future use.
+If present they are ignored for forward compatibility.
+
+v1 Reply Index File
+-------------------
+
+CMake writes an ``index-*.json`` file to the ``v1/reply/`` directory
+whenever it runs to generate a build system.  Clients must read the
+reply index file first and may read other `v1 Reply Files`_ only by
+following references.  The form of the reply index file name is::
+
+  <build>/.cmake/api/v1/reply/index-<unspecified>.json
+
+where ``index-`` is literal and ``<unspecified>`` is an unspecified
+name selected by CMake.  Whenever a new index file is generated it
+is given a new name and any old one is deleted.  During the short
+time between these steps there may be multiple index files present;
+the one with the largest name in lexicographic order is the current
+index file.
+
+The reply index file contains a JSON object:
+
+.. code-block:: json
+
+  {
+    "cmake": {
+      "version": {
+        "major": 3, "minor": 14, "patch": 0, "suffix": "",
+        "string": "3.14.0", "isDirty": false
+      },
+      "paths": {
+        "cmake": "/prefix/bin/cmake",
+        "ctest": "/prefix/bin/ctest",
+        "cpack": "/prefix/bin/cpack",
+        "root": "/prefix/share/cmake-3.14"
+      },
+      "generator": {
+        "name": "Unix Makefiles"
+      }
+    },
+    "objects": [
+      { "kind": "<kind>",
+        "version": { "major": 1, "minor": 0 },
+        "jsonFile": "<file>" },
+      { "...": "..." }
+    ],
+    "reply": {
+      "<kind>-v<major>": { "kind": "<kind>",
+                           "version": { "major": 1, "minor": 0 },
+                           "jsonFile": "<file>" },
+      "<unknown>": { "error": "unknown query file" },
+      "...": {},
+      "client-<client>": {
+        "<kind>-v<major>": { "kind": "<kind>",
+                             "version": { "major": 1, "minor": 0 },
+                             "jsonFile": "<file>" },
+        "<unknown>": { "error": "unknown query file" },
+        "...": {},
+        "query.json": {
+          "requests": [ {}, {}, {} ],
+          "responses": [
+            { "kind": "<kind>",
+              "version": { "major": 1, "minor": 0 },
+              "jsonFile": "<file>" },
+            { "error": "unknown query file" },
+            { "...": {} }
+          ],
+          "client": {}
+        }
+      }
+    }
+  }
+
+The members are:
+
+``cmake``
+  A JSON object containing information about the instance of CMake that
+  generated the reply.  It contains members:
+
+  ``version``
+    A JSON object specifying the version of CMake with members:
+
+    ``major``, ``minor``, ``patch``
+      Integer values specifying the major, minor, and patch version components.
+    ``suffix``
+      A string specifying the version suffix, if any, e.g. ``g0abc3``.
+    ``string``
+      A string specifying the full version in the format
+      ``<major>.<minor>.<patch>[-<suffix>]``.
+    ``isDirty``
+      A boolean indicating whether the version was built from a version
+      controlled source tree with local modifications.
+
+  ``paths``
+    A JSON object specifying paths to things that come with CMake.
+    It has members for ``cmake``, ``ctest``, and ``cpack`` whose values
+    are JSON strings specifying the absolute path to each tool,
+    represented with forward slashes.  It also has a ``root`` member for
+    the absolute path to the directory containing CMake resources like the
+    ``Modules/`` directory (see :variable:`CMAKE_ROOT`).
+
+  ``generator``
+    A JSON object describing the CMake generator used for the build.
+    It has members:
+
+    ``name``
+      A string specifying the name of the generator.
+    ``platform``
+      If the generator supports :variable:`CMAKE_GENERATOR_PLATFORM`,
+      this is a string specifying the generator platform name.
+
+``objects``
+  A JSON array listing all versions of all `Object Kinds`_ generated
+  as part of the reply.  Each array entry is a
+  `v1 Reply File Reference`_.
+
+``reply``
+  A JSON object mirroring the content of the ``query/`` directory
+  that CMake loaded to produce the reply.  The members are of the form
+
+  ``<kind>-v<major>``
+    A member of this form appears for each of the
+    `v1 Shared Stateless Query Files`_ that CMake recognized as a
+    request for object kind ``<kind>`` with major version ``<major>``.
+    The value is a `v1 Reply File Reference`_ to the corresponding
+    reply file for that object kind and version.
+
+  ``<unknown>``
+    A member of this form appears for each of the
+    `v1 Shared Stateless Query Files`_ that CMake did not recognize.
+    The value is a JSON object with a single ``error`` member
+    containing a string with an error message indicating that the
+    query file is unknown.
+
+  ``client-<client>``
+    A member of this form appears for each client-owned directory
+    holding `v1 Client Stateless Query Files`_.
+    The value is a JSON object mirroring the content of the
+    ``query/client-<client>/`` directory.  The members are of the form:
+
+    ``<kind>-v<major>``
+      A member of this form appears for each of the
+      `v1 Client Stateless Query Files`_ that CMake recognized as a
+      request for object kind ``<kind>`` with major version ``<major>``.
+      The value is a `v1 Reply File Reference`_ to the corresponding
+      reply file for that object kind and version.
+
+    ``<unknown>``
+      A member of this form appears for each of the
+      `v1 Client Stateless Query Files`_ that CMake did not recognize.
+      The value is a JSON object with a single ``error`` member
+      containing a string with an error message indicating that the
+      query file is unknown.
+
+    ``query.json``
+      This member appears for clients using
+      `v1 Client Stateful Query Files`_.
+      If the ``query.json`` file failed to read or parse as a JSON object,
+      this member is a JSON object with a single ``error`` member
+      containing a string with an error message.  Otherwise, this member
+      is a JSON object mirroring the content of the ``query.json`` file.
+      The members are:
+
+      ``client``
+        A copy of the ``query.json`` file ``client`` member, if it exists.
+
+      ``requests``
+        A copy of the ``query.json`` file ``requests`` member, if it exists.
+
+      ``responses``
+        If the ``query.json`` file ``requests`` member is missing or invalid,
+        this member is a JSON object with a single ``error`` member
+        containing a string with an error message.  Otherwise, this member
+        contains a JSON array with a response for each entry of the
+        ``requests`` array, in the same order.  Each response is
+
+        * a JSON object with a single ``error`` member containing a string
+          with an error message, or
+        * a `v1 Reply File Reference`_ to the corresponding reply file for
+          the requested object kind and selected version.
+
+After reading the reply index file, clients may read the other
+`v1 Reply Files`_ it references.
+
+v1 Reply File Reference
+^^^^^^^^^^^^^^^^^^^^^^^
+
+The reply index file represents each reference to another reply file
+using a JSON object with members:
+
+``kind``
+  A string specifying one of the `Object Kinds`_.
+``version``
+  A JSON object with members ``major`` and ``minor`` specifying
+  integer version components of the object kind.
+``jsonFile``
+  A JSON string specifying a path relative to the reply index file
+  to another JSON file containing the object.
+
+v1 Reply Files
+--------------
+
+Reply files containing specific `Object Kinds`_ are written by CMake.
+The names of these files are unspecified and must not be interpreted
+by clients.  Clients must first read the `v1 Reply Index File`_ and
+and follow references to the names of the desired response objects.
+
+Reply files (including the index file) will never be replaced by
+files of the same name but different content.  This allows a client
+to read the files concurrently with a running CMake that may generate
+a new reply.  However, after generating a new reply CMake will attempt
+to remove reply files from previous runs that it did not just write.
+If a client attempts to read a reply file referenced by the index but
+finds the file missing, that means a concurrent CMake has generated
+a new reply.  The client may simply start again by reading the new
+reply index file.
+
+Object Kinds
+============
+
+The CMake file-based API reports semantic information about the build
+system using the following kinds of JSON objects.  Each kind of object
+is versioned independently using semantic versioning with major and
+minor components.  Every kind of object has the form:
+
+.. code-block:: json
+
+  {
+    "kind": "<kind>",
+    "version": { "major": 1, "minor": 0 },
+    "...": {}
+  }
+
+The ``kind`` member is a string specifying the object kind name.
+The ``version`` member is a JSON object with ``major`` and ``minor``
+members specifying integer components of the object kind's version.
+Additional top-level members are specific to each object kind.
+
+Object Kind "codemodel"
+-----------------------
+
+The ``codemodel`` object kind describes the build system structure as
+modeled by CMake.
+
+There is only one ``codemodel`` object major version, version 2.
+Version 1 does not exist to avoid confusion with that from
+:manual:`cmake-server(7)` mode.
+
+"codemodel" version 2
+^^^^^^^^^^^^^^^^^^^^^
+
+``codemodel`` object version 2 is a JSON object:
+
+.. code-block:: json
+
+  {
+    "kind": "codemodel",
+    "version": { "major": 2, "minor": 0 },
+    "paths": {
+      "source": "/path/to/top-level-source-dir",
+      "build": "/path/to/top-level-build-dir"
+    },
+    "configurations": [
+      {
+        "name": "Debug",
+        "directories": [
+          {
+            "source": ".",
+            "build": ".",
+            "childIndexes": [ 1 ],
+            "projectIndex": 0,
+            "targetIndexes": [ 0 ],
+            "hasInstallRule": true,
+            "minimumCMakeVersion": {
+              "string": "3.14"
+            }
+          },
+          {
+            "source": "sub",
+            "build": "sub",
+            "parentIndex": 0,
+            "projectIndex": 0,
+            "targetIndexes": [ 1 ],
+            "minimumCMakeVersion": {
+              "string": "3.14"
+            }
+          }
+        ],
+        "projects": [
+          {
+            "name": "MyProject",
+            "directoryIndexes": [ 0, 1 ],
+            "targetIndexes": [ 0, 1 ]
+          }
+        ],
+        "targets": [
+          {
+            "name": "MyExecutable",
+            "directoryIndex": 0,
+            "projectIndex": 0,
+            "jsonFile": "<file>"
+          },
+          {
+            "name": "MyLibrary",
+            "directoryIndex": 1,
+            "projectIndex": 0,
+            "jsonFile": "<file>"
+          }
+        ]
+      }
+    ]
+  }
+
+The members specific to ``codemodel`` objects are:
+
+``paths``
+  A JSON object containing members:
+
+  ``source``
+    A string specifying the absolute path to the top-level source directory,
+    represented with forward slashes.
+
+  ``build``
+    A string specifying the absolute path to the top-level build directory,
+    represented with forward slashes.
+
+``configurations``
+  A JSON array of entries corresponding to available build configurations.
+  On single-configuration generators there is one entry for the value
+  of the :variable:`CMAKE_BUILD_TYPE` variable.  For multi-configuration
+  generators there is an entry for each configuration listed in the
+  :variable:`CMAKE_CONFIGURATION_TYPES` variable.
+  Each entry is a JSON object containing members:
+
+  ``name``
+    A string specifying the name of the configuration, e.g. ``Debug``.
+
+  ``directories``
+    A JSON array of entries each corresponding to a build system directory
+    whose source directory contains a ``CMakeLists.txt`` file.  The first
+    entry corresponds to the top-level directory.  Each entry is a
+    JSON object containing members:
+
+    ``source``
+      A string specifying the path to the source directory, represented
+      with forward slashes.  If the directory is inside the top-level
+      source directory then the path is specified relative to that
+      directory (with ``.`` for the top-level source directory itself).
+      Otherwise the path is absolute.
+
+    ``build``
+      A string specifying the path to the build directory, represented
+      with forward slashes.  If the directory is inside the top-level
+      build directory then the path is specified relative to that
+      directory (with ``.`` for the top-level build directory itself).
+      Otherwise the path is absolute.
+
+    ``parentIndex``
+      Optional member that is present when the directory is not top-level.
+      The value is an unsigned integer 0-based index of another entry in
+      the main ``directories`` array that corresponds to the parent
+      directory that added this directory as a subdirectory.
+
+    ``childIndexes``
+      Optional member that is present when the directory has subdirectories.
+      The value is a JSON array of entries corresponding to child directories
+      created by the :command:`add_subdirectory` or :command:`subdirs`
+      command.  Each entry is an unsigned integer 0-based index of another
+      entry in the main ``directories`` array.
+
+    ``projectIndex``
+      An unsigned integer 0-based index into the main ``projects`` array
+      indicating the build system project to which the this directory belongs.
+
+    ``targetIndexes``
+      Optional member that is present when the directory itself has targets,
+      excluding those belonging to subdirectories.  The value is a JSON
+      array of entries corresponding to the targets.  Each entry is an
+      unsigned integer 0-based index into the main ``targets`` array.
+
+    ``minimumCMakeVersion``
+      Optional member present when a minimum required version of CMake is
+      known for the directory.  This is the ``<min>`` version given to the
+      most local call to the :command:`cmake_minimum_required(VERSION)`
+      command in the directory itself or one of its ancestors.
+      The value is a JSON object with one member:
+
+      ``string``
+        A string specifying the minimum required version in the format::
+
+          <major>.<minor>[.<patch>[.<tweak>]][<suffix>]
+
+        Each component is an unsigned integer and the suffix may be an
+        arbitrary string.
+
+    ``hasInstallRule``
+      Optional member that is present with boolean value ``true`` when
+      the directory or one of its subdirectories contains any
+      :command:`install` rules, i.e. whether a ``make install``
+      or equivalent rule is available.
+
+  ``projects``
+    A JSON array of entries corresponding to the top-level project
+    and sub-projects defined in the build system.  Each (sub-)project
+    corresponds to a source directory whose ``CMakeLists.txt`` file
+    calls the :command:`project` command with a project name different
+    from its parent directory.  The first entry corresponds to the
+    top-level project.
+
+    Each entry is a JSON object containing members:
+
+    ``name``
+      A string specifying the name given to the :command:`project` command.
+
+    ``parentIndex``
+      Optional member that is present when the project is not top-level.
+      The value is an unsigned integer 0-based index of another entry in
+      the main ``projects`` array that corresponds to the parent project
+      that added this project as a sub-project.
+
+    ``childIndexes``
+      Optional member that is present when the project has sub-projects.
+      The value is a JSON array of entries corresponding to the sub-projects.
+      Each entry is an unsigned integer 0-based index of another
+      entry in the main ``projects`` array.
+
+    ``directoryIndexes``
+      A JSON array of entries corresponding to build system directories
+      that are part of the project.  The first entry corresponds to the
+      top-level directory of the project.  Each entry is an unsigned
+      integer 0-based index into the main ``directories`` array.
+
+    ``targetIndexes``
+      Optional member that is present when the project itself has targets,
+      excluding those belonging to sub-projects.  The value is a JSON
+      array of entries corresponding to the targets.  Each entry is an
+      unsigned integer 0-based index into the main ``targets`` array.
+
+  ``targets``
+    A JSON array of entries corresponding to the build system targets.
+    Such targets are created by calls to :command:`add_executable`,
+    :command:`add_library`, and :command:`add_custom_target`, excluding
+    imported targets and interface libraries (which do not generate any
+    build rules).  Each entry is a JSON object containing members:
+
+    ``name``
+      A string specifying the target name.
+
+    ``id``
+      A string uniquely identifying the target.  This matches the ``id``
+      field in the file referenced by ``jsonFile``.
+
+    ``directoryIndex``
+      An unsigned integer 0-based index into the main ``directories`` array
+      indicating the build system directory in which the target is defined.
+
+    ``projectIndex``
+      An unsigned integer 0-based index into the main ``projects`` array
+      indicating the build system project in which the target is defined.
+
+    ``jsonFile``
+      A JSON string specifying a path relative to the codemodel file
+      to another JSON file containing a
+      `"codemodel" version 2 "target" object`_.
+
+"codemodel" version 2 "target" object
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A codemodel "target" object is referenced by a `"codemodel" version 2`_
+object's ``targets`` array.  Each "target" object is a JSON object
+with members:
+
+``name``
+  A string specifying the logical name of the target.
+
+``id``
+  A string uniquely identifying the target.  The format is unspecified
+  and should not be interpreted by clients.
+
+``type``
+  A string specifying the type of the target.  The value is one of
+  ``EXECUTABLE``, ``STATIC_LIBRARY``, ``SHARED_LIBRARY``,
+  ``MODULE_LIBRARY``, ``OBJECT_LIBRARY``, or ``UTILITY``.
+
+``backtrace``
+  Optional member that is present when a CMake language backtrace to
+  the command in the source code that created the target is available.
+  The value is an unsigned integer 0-based index into the
+  ``backtraceGraph`` member's ``nodes`` array.
+
+``folder``
+  Optional member that is present when the :prop_tgt:`FOLDER` target
+  property is set.  The value is a JSON object with one member:
+
+  ``name``
+    A string specifying the name of the target folder.
+
+``paths``
+  A JSON object containing members:
+
+  ``source``
+    A string specifying the path to the target's source directory,
+    represented with forward slashes.  If the directory is inside the
+    top-level source directory then the path is specified relative to
+    that directory (with ``.`` for the top-level source directory itself).
+    Otherwise the path is absolute.
+
+  ``build``
+    A string specifying the path to the target's build directory,
+    represented with forward slashes.  If the directory is inside the
+    top-level build directory then the path is specified relative to
+    that directory (with ``.`` for the top-level build directory itself).
+    Otherwise the path is absolute.
+
+``nameOnDisk``
+  Optional member that is present for executable and library targets
+  that are linked or archived into a single primary artifact.
+  The value is a string specifying the file name of that artifact on disk.
+
+``artifacts``
+  Optional member that is present for executable and library targets
+  that produce artifacts on disk meant for consumption by dependents.
+  The value is a JSON array of entries corresponding to the artifacts.
+  Each entry is a JSON object containing one member:
+
+  ``path``
+    A string specifying the path to the file on disk, represented with
+    forward slashes.  If the file is inside the top-level build directory
+    then the path is specified relative to that directory.
+    Otherwise the path is absolute.
+
+``isGeneratorProvided``
+  Optional member that is present with boolean value ``true`` if the
+  target is provided by CMake's build system generator rather than by
+  a command in the source code.
+
+``install``
+  Optional member that is present when the target has an :command:`install`
+  rule.  The value is a JSON object with members:
+
+  ``prefix``
+    A JSON object specifying the installation prefix.  It has one member:
+
+    ``path``
+      A string specifying the value of :variable:`CMAKE_INSTALL_PREFIX`.
+
+  ``destinations``
+    A JSON array of entries specifying an install destination path.
+    Each entry is a JSON object with members:
+
+    ``path``
+      A string specifying the install destination path.  The path may
+      be absolute or relative to the install prefix.
+
+    ``backtrace``
+      Optional member that is present when a CMake language backtrace to
+      the :command:`install` command invocation that specified this
+      destination is available.  The value is an unsigned integer 0-based
+      index into the ``backtraceGraph`` member's ``nodes`` array.
+
+``link``
+  Optional member that is present for executables and shared library
+  targets that link into a runtime binary.  The value is a JSON object
+  with members describing the link step:
+
+  ``language``
+    A string specifying the language (e.g. ``C``, ``CXX``, ``Fortran``)
+    of the toolchain is used to invoke the linker.
+
+  ``commandFragments``
+    Optional member that is present when fragments of the link command
+    line invocation are available.  The value is a JSON array of entries
+    specifying ordered fragments.  Each entry is a JSON object with members:
+
+    ``fragment``
+      A string specifying a fragment of the link command line invocation.
+      The value is encoded in the build system's native shell format.
+
+    ``role``
+      A string specifying the role of the fragment's content:
+
+      * ``flags``: link flags.
+      * ``libraries``: link library file paths or flags.
+      * ``libraryPath``: library search path flags.
+      * ``frameworkPath``: macOS framework search path flags.
+
+  ``lto``
+    Optional member that is present with boolean value ``true``
+    when link-time optimization (a.k.a. interprocedural optimization
+    or link-time code generation) is enabled.
+
+  ``sysroot``
+    Optional member that is present when the :variable:`CMAKE_SYSROOT_LINK`
+    or :variable:`CMAKE_SYSROOT` variable is defined.  The value is a
+    JSON object with one member:
+
+    ``path``
+      A string specifying the absolute path to the sysroot, represented
+      with forward slashes.
+
+``archive``
+  Optional member that is present for static library targets.  The value
+  is a JSON object with members describing the archive step:
+
+  ``commandFragments``
+    Optional member that is present when fragments of the archiver command
+    line invocation are available.  The value is a JSON array of entries
+    specifying the fragments.  Each entry is a JSON object with members:
+
+    ``fragment``
+      A string specifying a fragment of the archiver command line invocation.
+      The value is encoded in the build system's native shell format.
+
+    ``role``
+      A string specifying the role of the fragment's content:
+
+      * ``flags``: archiver flags.
+
+  ``lto``
+    Optional member that is present with boolean value ``true``
+    when link-time optimization (a.k.a. interprocedural optimization
+    or link-time code generation) is enabled.
+
+``dependencies``
+  Optional member that is present when the target depends on other targets.
+  The value is a JSON array of entries corresponding to the dependencies.
+  Each entry is a JSON object with members:
+
+  ``id``
+    A string uniquely identifying the target on which this target depends.
+    This matches the main ``id`` member of the other target.
+
+  ``backtrace``
+    Optional member that is present when a CMake language backtrace to
+    the :command:`add_dependencies`, :command:`target_link_libraries`,
+    or other command invocation that created this dependency is
+    available.  The value is an unsigned integer 0-based index into
+    the ``backtraceGraph`` member's ``nodes`` array.
+
+``sources``
+  A JSON array of entries corresponding to the target's source files.
+  Each entry is a JSON object with members:
+
+  ``path``
+    A string specifying the path to the source file on disk, represented
+    with forward slashes.  If the file is inside the top-level source
+    directory then the path is specified relative to that directory.
+    Otherwise the path is absolute.
+
+  ``compileGroupIndex``
+    Optional member that is present when the source is compiled.
+    The value is an unsigned integer 0-based index into the
+    ``compileGroups`` array.
+
+  ``sourceGroupIndex``
+    Optional member that is present when the source is part of a source
+    group either via the :command:`source_group` command or by default.
+    The value is an unsigned integer 0-based index into the
+    ``sourceGroups`` array.
+
+  ``isGenerated``
+    Optional member that is present with boolean value ``true`` if
+    the source is :prop_sf:`GENERATED`.
+
+  ``backtrace``
+    Optional member that is present when a CMake language backtrace to
+    the :command:`target_sources`, :command:`add_executable`,
+    :command:`add_library`, :command:`add_custom_target`, or other
+    command invocation that added this source to the target is
+    available.  The value is an unsigned integer 0-based index into
+    the ``backtraceGraph`` member's ``nodes`` array.
+
+``sourceGroups``
+  Optional member that is present when sources are grouped together by
+  the :command:`source_group` command or by default.  The value is a
+  JSON array of entries corresponding to the groups.  Each entry is
+  a JSON object with members:
+
+  ``name``
+    A string specifying the name of the source group.
+
+  ``sourceIndexes``
+    A JSON array listing the sources belonging to the group.
+    Each entry is an unsigned integer 0-based index into the
+    main ``sources`` array for the target.
+
+``compileGroups``
+  Optional member that is present when the target has sources that compile.
+  The value is a JSON array of entries corresponding to groups of sources
+  that all compile with the same settings.  Each entry is a JSON object
+  with members:
+
+  ``sourceIndexes``
+    A JSON array listing the sources belonging to the group.
+    Each entry is an unsigned integer 0-based index into the
+    main ``sources`` array for the target.
+
+  ``language``
+    A string specifying the language (e.g. ``C``, ``CXX``, ``Fortran``)
+    of the toolchain is used to compile the source file.
+
+  ``compileCommandFragments``
+    Optional member that is present when fragments of the compiler command
+    line invocation are available.  The value is a JSON array of entries
+    specifying ordered fragments.  Each entry is a JSON object with
+    one member:
+
+    ``fragment``
+      A string specifying a fragment of the compile command line invocation.
+      The value is encoded in the build system's native shell format.
+
+  ``includes``
+    Optional member that is present when there are include directories.
+    The value is a JSON array with an entry for each directory.  Each
+    entry is a JSON object with members:
+
+    ``path``
+      A string specifying the path to the include directory,
+      represented with forward slashes.
+
+    ``isSystem``
+      Optional member that is present with boolean value ``true`` if
+      the include directory is marked as a system include directory.
+
+    ``backtrace``
+      Optional member that is present when a CMake language backtrace to
+      the :command:`target_include_directories` or other command invocation
+      that added this include directory 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
+    entry is a JSON object with members:
+
+    ``define``
+      A string specifying the preprocessor definition in the format
+      ``<name>[=<value>]``, e.g. ``DEF`` or ``DEF=1``.
+
+    ``backtrace``
+      Optional member that is present when a CMake language backtrace to
+      the :command:`target_compile_definitions` or other command invocation
+      that added this preprocessor definition is available.  The value is
+      an unsigned integer 0-based index into the ``backtraceGraph``
+      member's ``nodes`` array.
+
+  ``sysroot``
+    Optional member that is present when the
+    :variable:`CMAKE_SYSROOT_COMPILE` or :variable:`CMAKE_SYSROOT`
+    variable is defined.  The value is a JSON object with one member:
+
+    ``path``
+      A string specifying the absolute path to the sysroot, represented
+      with forward slashes.
+
+``backtraceGraph``
+  A JSON object describing the graph of backtraces whose nodes are
+  referenced from ``backtrace`` members elsewhere.  The members are:
+
+  ``nodes``
+    A JSON array listing nodes in the backtrace graph.  Each entry
+    is a JSON object with members:
+
+    ``file``
+      An unsigned integer 0-based index into the backtrace ``files`` array.
+
+    ``line``
+      An optional member present when the node represents a line within
+      the file.  The value is an unsigned integer 1-based line number.
+
+    ``command``
+      An optional member present when the node represents a command
+      invocation within the file.  The value is an unsigned integer
+      0-based index into the backtrace ``commands`` array.
+
+    ``parent``
+      An optional member present when the node is not the bottom of
+      the call stack.  The value is an unsigned integer 0-based index
+      of another entry in the backtrace ``nodes`` array.
+
+  ``commands``
+    A JSON array listing command names referenced by backtrace nodes.
+    Each entry is a string specifying a command name.
+
+  ``files``
+    A JSON array listing CMake language files referenced by backtrace nodes.
+    Each entry is a string specifying the path to a file, represented
+    with forward slashes.  If the file is inside the top-level source
+    directory then the path is specified relative to that directory.
+    Otherwise the path is absolute.
+
+Object Kind "cache"
+-------------------
+
+The ``cache`` object kind lists cache entries.  These are the
+:ref:`CMake Language Variables` stored in the persistent cache
+(``CMakeCache.txt``) for the build tree.
+
+There is only one ``cache`` object major version, version 2.
+Version 1 does not exist to avoid confusion with that from
+:manual:`cmake-server(7)` mode.
+
+"cache" version 2
+^^^^^^^^^^^^^^^^^
+
+``cache`` object version 2 is a JSON object:
+
+.. code-block:: json
+
+  {
+    "kind": "cache",
+    "version": { "major": 2, "minor": 0 },
+    "entries": [
+      {
+        "name": "BUILD_SHARED_LIBS",
+        "value": "ON",
+        "type": "BOOL",
+        "properties": [
+          {
+            "name": "HELPSTRING",
+            "value": "Build shared libraries"
+          }
+        ]
+      },
+      {
+        "name": "CMAKE_GENERATOR",
+        "value": "Unix Makefiles",
+        "type": "INTERNAL",
+        "properties": [
+          {
+            "name": "HELPSTRING",
+            "value": "Name of generator."
+          }
+        ]
+      }
+    ]
+  }
+
+The members specific to ``cache`` objects are:
+
+``entries``
+  A JSON array whose entries are each a JSON object specifying a
+  cache entry.  The members of each entry are:
+
+  ``name``
+    A string specifying the name of the entry.
+
+  ``value``
+    A string specifying the value of the entry.
+
+  ``type``
+    A string specifying the type of the entry used by
+    :manual:`cmake-gui(1)` to choose a widget for editing.
+
+  ``properties``
+    A JSON array of entries specifying associated
+    :ref:`cache entry properties <Cache Entry Properties>`.
+    Each entry is a JSON object containing members:
+
+    ``name``
+      A string specifying the name of the cache entry property.
+
+    ``value``
+      A string specifying the value of the cache entry property.
+
+Object Kind "cmakeFiles"
+------------------------
+
+The ``cmakeFiles`` object kind lists files used by CMake while
+configuring and generating the build system.  These include the
+``CMakeLists.txt`` files as well as included ``.cmake`` files.
+
+There is only one ``cmakeFiles`` object major version, version 1.
+
+"cmakeFiles" version 1
+^^^^^^^^^^^^^^^^^^^^^^
+
+``cmakeFiles`` object version 1 is a JSON object:
+
+.. code-block:: json
+
+  {
+    "kind": "cmakeFiles",
+    "version": { "major": 1, "minor": 0 },
+    "paths": {
+      "build": "/path/to/top-level-build-dir",
+      "source": "/path/to/top-level-source-dir"
+    },
+    "inputs": [
+      {
+        "path": "CMakeLists.txt"
+      },
+      {
+        "isGenerated": true,
+        "path": "/path/to/top-level-build-dir/.../CMakeSystem.cmake"
+      },
+      {
+        "isExternal": true,
+        "path": "/path/to/external/third-party/module.cmake"
+      },
+      {
+        "isCMake": true,
+        "isExternal": true,
+        "path": "/path/to/cmake/Modules/CMakeGenericSystem.cmake"
+      }
+    ]
+  }
+
+The members specific to ``cmakeFiles`` objects are:
+
+``paths``
+  A JSON object containing members:
+
+  ``source``
+    A string specifying the absolute path to the top-level source directory,
+    represented with forward slashes.
+
+  ``build``
+    A string specifying the absolute path to the top-level build directory,
+    represented with forward slashes.
+
+``inputs``
+  A JSON array whose entries are each a JSON object specifying an input
+  file used by CMake when configuring and generating the build system.
+  The members of each entry are:
+
+  ``path``
+    A string specifying the path to an input file to CMake, represented
+    with forward slashes.  If the file is inside the top-level source
+    directory then the path is specified relative to that directory.
+    Otherwise the path is absolute.
+
+  ``isGenerated``
+    Optional member that is present with boolean value ``true``
+    if the path specifies a file that is under the top-level
+    build directory and the build is out-of-source.
+    This member is not available on in-source builds.
+
+  ``isExternal``
+    Optional member that is present with boolean value ``true``
+    if the path specifies a file that is not under the top-level
+    source or build directories.
+
+  ``isCMake``
+    Optional member that is present with boolean value ``true``
+    if the path specifies a file in the CMake installation.

+ 5 - 0
Help/release/dev/fileapi.rst

@@ -0,0 +1,5 @@
+fileapi
+-------
+
+* A file-based api for clients to get semantic buildsystem information
+  has been added.  See the :manual:`cmake-file-api(7)` manual.

+ 8 - 0
Source/CMakeLists.txt

@@ -207,6 +207,14 @@ set(SRCS
   cmExtraKateGenerator.h
   cmExtraSublimeTextGenerator.cxx
   cmExtraSublimeTextGenerator.h
+  cmFileAPI.cxx
+  cmFileAPI.h
+  cmFileAPICache.cxx
+  cmFileAPICache.h
+  cmFileAPICodemodel.cxx
+  cmFileAPICodemodel.h
+  cmFileAPICMakeFiles.cxx
+  cmFileAPICMakeFiles.h
   cmFileLock.cxx
   cmFileLock.h
   cmFileLockPool.cxx

+ 800 - 0
Source/cmFileAPI.cxx

@@ -0,0 +1,800 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmFileAPI.h"
+
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmFileAPICMakeFiles.h"
+#include "cmFileAPICache.h"
+#include "cmFileAPICodemodel.h"
+#include "cmGlobalGenerator.h"
+#include "cmSystemTools.h"
+#include "cmTimestamp.h"
+#include "cmake.h"
+#include "cmsys/Directory.hxx"
+#include "cmsys/FStream.hxx"
+
+#include <algorithm>
+#include <cassert>
+#include <chrono>
+#include <ctime>
+#include <iomanip>
+#include <sstream>
+#include <utility>
+
+cmFileAPI::cmFileAPI(cmake* cm)
+  : CMakeInstance(cm)
+{
+  this->APIv1 =
+    this->CMakeInstance->GetHomeOutputDirectory() + "/.cmake/api/v1";
+
+  Json::CharReaderBuilder rbuilder;
+  rbuilder["collectComments"] = false;
+  rbuilder["failIfExtra"] = true;
+  rbuilder["rejectDupKeys"] = false;
+  rbuilder["strictRoot"] = true;
+  this->JsonReader =
+    std::unique_ptr<Json::CharReader>(rbuilder.newCharReader());
+
+  Json::StreamWriterBuilder wbuilder;
+  wbuilder["indentation"] = "\t";
+  this->JsonWriter =
+    std::unique_ptr<Json::StreamWriter>(wbuilder.newStreamWriter());
+}
+
+void cmFileAPI::ReadQueries()
+{
+  std::string const query_dir = this->APIv1 + "/query";
+  this->QueryExists = cmSystemTools::FileIsDirectory(query_dir);
+  if (!this->QueryExists) {
+    return;
+  }
+
+  // Load queries at the top level.
+  std::vector<std::string> queries = cmFileAPI::LoadDir(query_dir);
+
+  // Read the queries and save for later.
+  for (std::string& query : queries) {
+    if (cmHasLiteralPrefix(query, "client-")) {
+      this->ReadClient(query);
+    } else if (!cmFileAPI::ReadQuery(query, this->TopQuery.Known)) {
+      this->TopQuery.Unknown.push_back(std::move(query));
+    }
+  }
+}
+
+void cmFileAPI::WriteReplies()
+{
+  if (this->QueryExists) {
+    cmSystemTools::MakeDirectory(this->APIv1 + "/reply");
+    this->WriteJsonFile(this->BuildReplyIndex(), "index", ComputeSuffixTime);
+  }
+
+  this->RemoveOldReplyFiles();
+}
+
+std::vector<std::string> cmFileAPI::LoadDir(std::string const& dir)
+{
+  std::vector<std::string> files;
+  cmsys::Directory d;
+  d.Load(dir);
+  for (unsigned long i = 0; i < d.GetNumberOfFiles(); ++i) {
+    std::string f = d.GetFile(i);
+    if (f != "." && f != "..") {
+      files.push_back(std::move(f));
+    }
+  }
+  std::sort(files.begin(), files.end());
+  return files;
+}
+
+void cmFileAPI::RemoveOldReplyFiles()
+{
+  std::string const reply_dir = this->APIv1 + "/reply";
+  std::vector<std::string> files = this->LoadDir(reply_dir);
+  for (std::string const& f : files) {
+    if (this->ReplyFiles.find(f) == this->ReplyFiles.end()) {
+      std::string file = reply_dir + "/" + f;
+      cmSystemTools::RemoveFile(file);
+    }
+  }
+}
+
+bool cmFileAPI::ReadJsonFile(std::string const& file, Json::Value& value,
+                             std::string& error)
+{
+  std::vector<char> content;
+
+  cmsys::ifstream fin;
+  if (!cmSystemTools::FileIsDirectory(file)) {
+    fin.open(file.c_str(), std::ios::binary);
+  }
+  auto finEnd = fin.rdbuf()->pubseekoff(0, std::ios::end);
+  if (finEnd > 0) {
+    size_t finSize = finEnd;
+    try {
+      // Allocate a buffer to read the whole file.
+      content.resize(finSize);
+
+      // Now read the file from the beginning.
+      fin.seekg(0, std::ios::beg);
+      fin.read(content.data(), finSize);
+    } catch (...) {
+      fin.setstate(std::ios::failbit);
+    }
+  }
+  fin.close();
+  if (!fin) {
+    value = Json::Value();
+    error = "failed to read from file";
+    return false;
+  }
+
+  // Parse our buffer as json.
+  if (!this->JsonReader->parse(content.data(), content.data() + content.size(),
+                               &value, &error)) {
+    value = Json::Value();
+    return false;
+  }
+
+  return true;
+}
+
+std::string cmFileAPI::WriteJsonFile(
+  Json::Value const& value, std::string const& prefix,
+  std::string (*computeSuffix)(std::string const&))
+{
+  std::string fileName;
+
+  // Write the json file with a temporary name.
+  std::string const& tmpFile = this->APIv1 + "/tmp.json";
+  cmsys::ofstream ftmp(tmpFile.c_str());
+  this->JsonWriter->write(value, &ftmp);
+  ftmp << "\n";
+  ftmp.close();
+  if (!ftmp) {
+    cmSystemTools::RemoveFile(tmpFile);
+    return fileName;
+  }
+
+  // Compute the final name for the file.
+  fileName = prefix + "-" + computeSuffix(tmpFile) + ".json";
+
+  // Create the destination.
+  std::string file = this->APIv1 + "/reply";
+  cmSystemTools::MakeDirectory(file);
+  file += "/";
+  file += fileName;
+
+  // If the final name already exists then assume it has proper content.
+  // Otherwise, atomically place the reply file at its final name
+  if (cmSystemTools::FileExists(file, true) ||
+      !cmSystemTools::RenameFile(tmpFile.c_str(), file.c_str())) {
+    cmSystemTools::RemoveFile(tmpFile);
+  }
+
+  // Record this among files we have just written.
+  this->ReplyFiles.insert(fileName);
+
+  return fileName;
+}
+
+Json::Value cmFileAPI::MaybeJsonFile(Json::Value in, std::string const& prefix)
+{
+  Json::Value out;
+  if (in.isObject() || in.isArray()) {
+    out = Json::objectValue;
+    out["jsonFile"] = this->WriteJsonFile(in, prefix);
+  } else {
+    out = std::move(in);
+  }
+  return out;
+}
+
+std::string cmFileAPI::ComputeSuffixHash(std::string const& file)
+{
+  cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
+  std::string hash = hasher.HashFile(file);
+  hash.resize(20, '0');
+  return hash;
+}
+
+std::string cmFileAPI::ComputeSuffixTime(std::string const&)
+{
+  std::chrono::milliseconds ms =
+    std::chrono::duration_cast<std::chrono::milliseconds>(
+      std::chrono::system_clock::now().time_since_epoch());
+  std::chrono::seconds s =
+    std::chrono::duration_cast<std::chrono::seconds>(ms);
+
+  std::time_t ts = s.count();
+  std::size_t tms = ms.count() % 1000;
+
+  cmTimestamp cmts;
+  std::ostringstream ss;
+  ss << cmts.CreateTimestampFromTimeT(ts, "%Y-%m-%dT%H-%M-%S", true) << '-'
+     << std::setfill('0') << std::setw(4) << tms;
+  return ss.str();
+}
+
+bool cmFileAPI::ReadQuery(std::string const& query,
+                          std::vector<Object>& objects)
+{
+  // Parse the "<kind>-" syntax.
+  std::string::size_type sep_pos = query.find('-');
+  if (sep_pos == std::string::npos) {
+    return false;
+  }
+  std::string kindName = query.substr(0, sep_pos);
+  std::string verStr = query.substr(sep_pos + 1);
+  if (kindName == ObjectKindName(ObjectKind::CodeModel)) {
+    Object o;
+    o.Kind = ObjectKind::CodeModel;
+    if (verStr == "v2") {
+      o.Version = 2;
+    } else {
+      return false;
+    }
+    objects.push_back(o);
+    return true;
+  }
+  if (kindName == ObjectKindName(ObjectKind::Cache)) {
+    Object o;
+    o.Kind = ObjectKind::Cache;
+    if (verStr == "v2") {
+      o.Version = 2;
+    } else {
+      return false;
+    }
+    objects.push_back(o);
+    return true;
+  }
+  if (kindName == ObjectKindName(ObjectKind::CMakeFiles)) {
+    Object o;
+    o.Kind = ObjectKind::CMakeFiles;
+    if (verStr == "v1") {
+      o.Version = 1;
+    } else {
+      return false;
+    }
+    objects.push_back(o);
+    return true;
+  }
+  if (kindName == ObjectKindName(ObjectKind::InternalTest)) {
+    Object o;
+    o.Kind = ObjectKind::InternalTest;
+    if (verStr == "v1") {
+      o.Version = 1;
+    } else if (verStr == "v2") {
+      o.Version = 2;
+    } else {
+      return false;
+    }
+    objects.push_back(o);
+    return true;
+  }
+  return false;
+}
+
+void cmFileAPI::ReadClient(std::string const& client)
+{
+  // Load queries for the client.
+  std::string clientDir = this->APIv1 + "/query/" + client;
+  std::vector<std::string> queries = this->LoadDir(clientDir);
+
+  // Read the queries and save for later.
+  ClientQuery& clientQuery = this->ClientQueries[client];
+  for (std::string& query : queries) {
+    if (query == "query.json") {
+      clientQuery.HaveQueryJson = true;
+      this->ReadClientQuery(client, clientQuery.QueryJson);
+    } else if (!this->ReadQuery(query, clientQuery.DirQuery.Known)) {
+      clientQuery.DirQuery.Unknown.push_back(std::move(query));
+    }
+  }
+}
+
+void cmFileAPI::ReadClientQuery(std::string const& client, ClientQueryJson& q)
+{
+  // Read the query.json file.
+  std::string queryFile = this->APIv1 + "/query/" + client + "/query.json";
+  Json::Value query;
+  if (!this->ReadJsonFile(queryFile, query, q.Error)) {
+    return;
+  }
+  if (!query.isObject()) {
+    q.Error = "query root is not an object";
+    return;
+  }
+
+  Json::Value const& clientValue = query["client"];
+  if (!clientValue.isNull()) {
+    q.ClientValue = clientValue;
+  }
+  q.RequestsValue = std::move(query["requests"]);
+  q.Requests = this->BuildClientRequests(q.RequestsValue);
+}
+
+Json::Value cmFileAPI::BuildReplyIndex()
+{
+  Json::Value index(Json::objectValue);
+
+  // Report information about this version of CMake.
+  index["cmake"] = this->BuildCMake();
+
+  // Reply to all queries that we loaded.
+  Json::Value& reply = index["reply"] = this->BuildReply(this->TopQuery);
+  for (auto const& client : this->ClientQueries) {
+    std::string const& clientName = client.first;
+    ClientQuery const& clientQuery = client.second;
+    reply[clientName] = this->BuildClientReply(clientQuery);
+  }
+
+  // Move our index of generated objects into its field.
+  Json::Value& objects = index["objects"] = Json::arrayValue;
+  for (auto& entry : this->ReplyIndexObjects) {
+    objects.append(std::move(entry.second)); // NOLINT(*)
+  }
+
+  return index;
+}
+
+Json::Value cmFileAPI::BuildCMake()
+{
+  Json::Value cmake = Json::objectValue;
+  cmake["version"] = this->CMakeInstance->ReportVersionJson();
+  Json::Value& cmake_paths = cmake["paths"] = Json::objectValue;
+  cmake_paths["cmake"] = cmSystemTools::GetCMakeCommand();
+  cmake_paths["ctest"] = cmSystemTools::GetCTestCommand();
+  cmake_paths["cpack"] = cmSystemTools::GetCPackCommand();
+  cmake_paths["root"] = cmSystemTools::GetCMakeRoot();
+  cmake["generator"] = this->CMakeInstance->GetGlobalGenerator()->GetJson();
+  return cmake;
+}
+
+Json::Value cmFileAPI::BuildReply(Query const& q)
+{
+  Json::Value reply = Json::objectValue;
+  for (Object const& o : q.Known) {
+    std::string const& name = ObjectName(o);
+    reply[name] = this->AddReplyIndexObject(o);
+  }
+
+  for (std::string const& name : q.Unknown) {
+    reply[name] = cmFileAPI::BuildReplyError("unknown query file");
+  }
+  return reply;
+}
+
+Json::Value cmFileAPI::BuildReplyError(std::string const& error)
+{
+  Json::Value e = Json::objectValue;
+  e["error"] = error;
+  return e;
+}
+
+Json::Value const& cmFileAPI::AddReplyIndexObject(Object const& o)
+{
+  Json::Value& indexEntry = this->ReplyIndexObjects[o];
+  if (!indexEntry.isNull()) {
+    // The reply object has already been generated.
+    return indexEntry;
+  }
+
+  // Generate this reply object.
+  Json::Value const& object = this->BuildObject(o);
+  assert(object.isObject());
+
+  // Populate this index entry.
+  indexEntry = Json::objectValue;
+  indexEntry["kind"] = object["kind"];
+  indexEntry["version"] = object["version"];
+  indexEntry["jsonFile"] = this->WriteJsonFile(object, ObjectName(o));
+  return indexEntry;
+}
+
+const char* cmFileAPI::ObjectKindName(ObjectKind kind)
+{
+  // Keep in sync with ObjectKind enum.
+  static const char* objectKindNames[] = {
+    "codemodel",  //
+    "cache",      //
+    "cmakeFiles", //
+    "__test"      //
+  };
+  return objectKindNames[size_t(kind)];
+}
+
+std::string cmFileAPI::ObjectName(Object const& o)
+{
+  std::string name = ObjectKindName(o.Kind);
+  name += "-v";
+  name += std::to_string(o.Version);
+  return name;
+}
+
+Json::Value cmFileAPI::BuildObject(Object const& object)
+{
+  Json::Value value;
+
+  switch (object.Kind) {
+    case ObjectKind::CodeModel:
+      value = this->BuildCodeModel(object);
+      break;
+    case ObjectKind::Cache:
+      value = this->BuildCache(object);
+      break;
+    case ObjectKind::CMakeFiles:
+      value = this->BuildCMakeFiles(object);
+      break;
+    case ObjectKind::InternalTest:
+      value = this->BuildInternalTest(object);
+      break;
+  }
+
+  return value;
+}
+
+cmFileAPI::ClientRequests cmFileAPI::BuildClientRequests(
+  Json::Value const& requests)
+{
+  ClientRequests result;
+  if (requests.isNull()) {
+    result.Error = "'requests' member missing";
+    return result;
+  }
+  if (!requests.isArray()) {
+    result.Error = "'requests' member is not an array";
+    return result;
+  }
+
+  result.reserve(requests.size());
+  for (Json::Value const& request : requests) {
+    result.emplace_back(this->BuildClientRequest(request));
+  }
+
+  return result;
+}
+
+cmFileAPI::ClientRequest cmFileAPI::BuildClientRequest(
+  Json::Value const& request)
+{
+  ClientRequest r;
+
+  if (!request.isObject()) {
+    r.Error = "request is not an object";
+    return r;
+  }
+
+  Json::Value const& kind = request["kind"];
+  if (kind.isNull()) {
+    r.Error = "'kind' member missing";
+    return r;
+  }
+  if (!kind.isString()) {
+    r.Error = "'kind' member is not a string";
+    return r;
+  }
+  std::string const& kindName = kind.asString();
+
+  if (kindName == this->ObjectKindName(ObjectKind::CodeModel)) {
+    r.Kind = ObjectKind::CodeModel;
+  } else if (kindName == this->ObjectKindName(ObjectKind::Cache)) {
+    r.Kind = ObjectKind::Cache;
+  } else if (kindName == this->ObjectKindName(ObjectKind::CMakeFiles)) {
+    r.Kind = ObjectKind::CMakeFiles;
+  } else if (kindName == this->ObjectKindName(ObjectKind::InternalTest)) {
+    r.Kind = ObjectKind::InternalTest;
+  } else {
+    r.Error = "unknown request kind '" + kindName + "'";
+    return r;
+  }
+
+  Json::Value const& version = request["version"];
+  if (version.isNull()) {
+    r.Error = "'version' member missing";
+    return r;
+  }
+  std::vector<RequestVersion> versions;
+  if (!cmFileAPI::ReadRequestVersions(version, versions, r.Error)) {
+    return r;
+  }
+
+  switch (r.Kind) {
+    case ObjectKind::CodeModel:
+      this->BuildClientRequestCodeModel(r, versions);
+      break;
+    case ObjectKind::Cache:
+      this->BuildClientRequestCache(r, versions);
+      break;
+    case ObjectKind::CMakeFiles:
+      this->BuildClientRequestCMakeFiles(r, versions);
+      break;
+    case ObjectKind::InternalTest:
+      this->BuildClientRequestInternalTest(r, versions);
+      break;
+  }
+
+  return r;
+}
+
+Json::Value cmFileAPI::BuildClientReply(ClientQuery const& q)
+{
+  Json::Value reply = this->BuildReply(q.DirQuery);
+
+  if (!q.HaveQueryJson) {
+    return reply;
+  }
+
+  Json::Value& reply_query_json = reply["query.json"];
+  ClientQueryJson const& qj = q.QueryJson;
+
+  if (!qj.Error.empty()) {
+    reply_query_json = this->BuildReplyError(qj.Error);
+    return reply;
+  }
+
+  if (!qj.ClientValue.isNull()) {
+    reply_query_json["client"] = qj.ClientValue;
+  }
+
+  if (!qj.RequestsValue.isNull()) {
+    reply_query_json["requests"] = qj.RequestsValue;
+  }
+
+  reply_query_json["responses"] = this->BuildClientReplyResponses(qj.Requests);
+
+  return reply;
+}
+
+Json::Value cmFileAPI::BuildClientReplyResponses(
+  ClientRequests const& requests)
+{
+  Json::Value responses;
+
+  if (!requests.Error.empty()) {
+    responses = this->BuildReplyError(requests.Error);
+    return responses;
+  }
+
+  responses = Json::arrayValue;
+  for (ClientRequest const& request : requests) {
+    responses.append(this->BuildClientReplyResponse(request));
+  }
+
+  return responses;
+}
+
+Json::Value cmFileAPI::BuildClientReplyResponse(ClientRequest const& request)
+{
+  Json::Value response;
+  if (!request.Error.empty()) {
+    response = this->BuildReplyError(request.Error);
+    return response;
+  }
+  response = this->AddReplyIndexObject(request);
+  return response;
+}
+
+bool cmFileAPI::ReadRequestVersions(Json::Value const& version,
+                                    std::vector<RequestVersion>& versions,
+                                    std::string& error)
+{
+  if (version.isArray()) {
+    for (Json::Value const& v : version) {
+      if (!ReadRequestVersion(v, /*inArray=*/true, versions, error)) {
+        return false;
+      }
+    }
+  } else {
+    if (!ReadRequestVersion(version, /*inArray=*/false, versions, error)) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool cmFileAPI::ReadRequestVersion(Json::Value const& version, bool inArray,
+                                   std::vector<RequestVersion>& result,
+                                   std::string& error)
+{
+  if (version.isUInt()) {
+    RequestVersion v;
+    v.Major = version.asUInt();
+    result.push_back(v);
+    return true;
+  }
+
+  if (!version.isObject()) {
+    if (inArray) {
+      error = "'version' array entry is not a non-negative integer or object";
+    } else {
+      error =
+        "'version' member is not a non-negative integer, object, or array";
+    }
+    return false;
+  }
+
+  Json::Value const& major = version["major"];
+  if (major.isNull()) {
+    error = "'version' object 'major' member missing";
+    return false;
+  }
+  if (!major.isUInt()) {
+    error = "'version' object 'major' member is not a non-negative integer";
+    return false;
+  }
+
+  RequestVersion v;
+  v.Major = major.asUInt();
+
+  Json::Value const& minor = version["minor"];
+  if (minor.isUInt()) {
+    v.Minor = minor.asUInt();
+  } else if (!minor.isNull()) {
+    error = "'version' object 'minor' member is not a non-negative integer";
+    return false;
+  }
+
+  result.push_back(v);
+
+  return true;
+}
+
+std::string cmFileAPI::NoSupportedVersion(
+  std::vector<RequestVersion> const& versions)
+{
+  std::ostringstream msg;
+  msg << "no supported version specified";
+  if (!versions.empty()) {
+    msg << " among:";
+    for (RequestVersion const& v : versions) {
+      msg << " " << v.Major << "." << v.Minor;
+    }
+  }
+  return msg.str();
+}
+
+// The "codemodel" object kind.
+
+static unsigned int const CodeModelV2Minor = 0;
+
+void cmFileAPI::BuildClientRequestCodeModel(
+  ClientRequest& r, std::vector<RequestVersion> const& versions)
+{
+  // Select a known version from those requested.
+  for (RequestVersion const& v : versions) {
+    if ((v.Major == 2 && v.Minor <= CodeModelV2Minor)) {
+      r.Version = v.Major;
+      break;
+    }
+  }
+  if (!r.Version) {
+    r.Error = NoSupportedVersion(versions);
+  }
+}
+
+Json::Value cmFileAPI::BuildCodeModel(Object const& object)
+{
+  using namespace std::placeholders;
+  Json::Value codemodel = cmFileAPICodemodelDump(*this, object.Version);
+  codemodel["kind"] = this->ObjectKindName(object.Kind);
+
+  Json::Value& version = codemodel["version"] = Json::objectValue;
+  if (object.Version == 2) {
+    version["major"] = 2;
+    version["minor"] = CodeModelV2Minor;
+  } else {
+    return codemodel; // should be unreachable
+  }
+
+  return codemodel;
+}
+
+// The "cache" object kind.
+
+static unsigned int const CacheV2Minor = 0;
+
+void cmFileAPI::BuildClientRequestCache(
+  ClientRequest& r, std::vector<RequestVersion> const& versions)
+{
+  // Select a known version from those requested.
+  for (RequestVersion const& v : versions) {
+    if ((v.Major == 2 && v.Minor <= CacheV2Minor)) {
+      r.Version = v.Major;
+      break;
+    }
+  }
+  if (!r.Version) {
+    r.Error = NoSupportedVersion(versions);
+  }
+}
+
+Json::Value cmFileAPI::BuildCache(Object const& object)
+{
+  using namespace std::placeholders;
+  Json::Value cache = cmFileAPICacheDump(*this, object.Version);
+  cache["kind"] = this->ObjectKindName(object.Kind);
+
+  Json::Value& version = cache["version"] = Json::objectValue;
+  if (object.Version == 2) {
+    version["major"] = 2;
+    version["minor"] = CacheV2Minor;
+  } else {
+    return cache; // should be unreachable
+  }
+
+  return cache;
+}
+
+// The "cmakeFiles" object kind.
+
+static unsigned int const CMakeFilesV1Minor = 0;
+
+void cmFileAPI::BuildClientRequestCMakeFiles(
+  ClientRequest& r, std::vector<RequestVersion> const& versions)
+{
+  // Select a known version from those requested.
+  for (RequestVersion const& v : versions) {
+    if ((v.Major == 1 && v.Minor <= CMakeFilesV1Minor)) {
+      r.Version = v.Major;
+      break;
+    }
+  }
+  if (!r.Version) {
+    r.Error = NoSupportedVersion(versions);
+  }
+}
+
+Json::Value cmFileAPI::BuildCMakeFiles(Object const& object)
+{
+  using namespace std::placeholders;
+  Json::Value cmakeFiles = cmFileAPICMakeFilesDump(*this, object.Version);
+  cmakeFiles["kind"] = this->ObjectKindName(object.Kind);
+
+  Json::Value& version = cmakeFiles["version"] = Json::objectValue;
+  if (object.Version == 1) {
+    version["major"] = 1;
+    version["minor"] = CMakeFilesV1Minor;
+  } else {
+    return cmakeFiles; // should be unreachable
+  }
+
+  return cmakeFiles;
+}
+
+// The "__test" object kind is for internal testing of CMake.
+
+static unsigned int const InternalTestV1Minor = 3;
+static unsigned int const InternalTestV2Minor = 0;
+
+void cmFileAPI::BuildClientRequestInternalTest(
+  ClientRequest& r, std::vector<RequestVersion> const& versions)
+{
+  // Select a known version from those requested.
+  for (RequestVersion const& v : versions) {
+    if ((v.Major == 1 && v.Minor <= InternalTestV1Minor) || //
+        (v.Major == 2 && v.Minor <= InternalTestV2Minor)) {
+      r.Version = v.Major;
+      break;
+    }
+  }
+  if (!r.Version) {
+    r.Error = NoSupportedVersion(versions);
+  }
+}
+
+Json::Value cmFileAPI::BuildInternalTest(Object const& object)
+{
+  Json::Value test = Json::objectValue;
+  test["kind"] = this->ObjectKindName(object.Kind);
+  Json::Value& version = test["version"] = Json::objectValue;
+  if (object.Version == 2) {
+    version["major"] = 2;
+    version["minor"] = InternalTestV2Minor;
+  } else {
+    version["major"] = 1;
+    version["minor"] = InternalTestV1Minor;
+  }
+  return test;
+}

+ 204 - 0
Source/cmFileAPI.h

@@ -0,0 +1,204 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmFileAPI_h
+#define cmFileAPI_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_jsoncpp_reader.h"
+#include "cm_jsoncpp_value.h"
+#include "cm_jsoncpp_writer.h"
+
+#include <map>
+#include <memory> // IWYU pragma: keep
+#include <string>
+#include <unordered_set>
+#include <vector>
+
+class cmake;
+
+class cmFileAPI
+{
+public:
+  cmFileAPI(cmake* cm);
+
+  /** Read fileapi queries from disk.  */
+  void ReadQueries();
+
+  /** Write fileapi replies to disk.  */
+  void WriteReplies();
+
+  /** Get the "cmake" instance with which this was constructed.  */
+  cmake* GetCMakeInstance() const { return this->CMakeInstance; }
+
+  /** Convert a JSON object or array into an object with a single
+      "jsonFile" member specifying a file named with the given prefix
+      and holding the original object.  Other JSON types are unchanged.  */
+  Json::Value MaybeJsonFile(Json::Value in, std::string const& prefix);
+
+private:
+  cmake* CMakeInstance;
+
+  /** The api/v1 directory location.  */
+  std::string APIv1;
+
+  /** The set of files we have just written to the reply directory.  */
+  std::unordered_set<std::string> ReplyFiles;
+
+  static std::vector<std::string> LoadDir(std::string const& dir);
+  void RemoveOldReplyFiles();
+
+  // Keep in sync with ObjectKindName.
+  enum class ObjectKind
+  {
+    CodeModel,
+    Cache,
+    CMakeFiles,
+    InternalTest
+  };
+
+  /** Identify one object kind and major version.  */
+  struct Object
+  {
+    ObjectKind Kind;
+    unsigned long Version = 0;
+    friend bool operator<(Object const& l, Object const& r)
+    {
+      if (l.Kind != r.Kind) {
+        return l.Kind < r.Kind;
+      }
+      return l.Version < r.Version;
+    }
+  };
+
+  /** Represent content of a query directory.  */
+  struct Query
+  {
+    /** Known object kind-version pairs.  */
+    std::vector<Object> Known;
+    /** Unknown object kind names.  */
+    std::vector<std::string> Unknown;
+  };
+
+  /** Represent one request in a client 'query.json'.  */
+  struct ClientRequest : public Object
+  {
+    /** Empty if request is valid, else the error string.  */
+    std::string Error;
+  };
+
+  /** Represent the "requests" in a client 'query.json'.  */
+  struct ClientRequests : public std::vector<ClientRequest>
+  {
+    /** Empty if requests field is valid, else the error string.  */
+    std::string Error;
+  };
+
+  /** Represent the content of a client query.json file.  */
+  struct ClientQueryJson
+  {
+    /** The error string if parsing failed, else empty.  */
+    std::string Error;
+
+    /** The 'query.json' object "client" member if it exists, else null.  */
+    Json::Value ClientValue;
+
+    /** The 'query.json' object "requests" member if it exists, else null.  */
+    Json::Value RequestsValue;
+
+    /** Requests extracted from 'query.json'.  */
+    ClientRequests Requests;
+  };
+
+  /** Represent content of a client query directory.  */
+  struct ClientQuery
+  {
+    /** The content of the client query directory except 'query.json'.  */
+    Query DirQuery;
+
+    /** True if 'query.json' exists.  */
+    bool HaveQueryJson = false;
+
+    /** The 'query.json' content.  */
+    ClientQueryJson QueryJson;
+  };
+
+  /** Whether the top-level query directory exists at all.  */
+  bool QueryExists = false;
+
+  /** The content of the top-level query directory.  */
+  Query TopQuery;
+
+  /** The content of each "client-$client" query directory.  */
+  std::map<std::string, ClientQuery> ClientQueries;
+
+  /** Reply index object generated for object kind/version.
+      This populates the "objects" field of the reply index.  */
+  std::map<Object, Json::Value> ReplyIndexObjects;
+
+  std::unique_ptr<Json::CharReader> JsonReader;
+  std::unique_ptr<Json::StreamWriter> JsonWriter;
+
+  bool ReadJsonFile(std::string const& file, Json::Value& value,
+                    std::string& error);
+
+  std::string WriteJsonFile(
+    Json::Value const& value, std::string const& prefix,
+    std::string (*computeSuffix)(std::string const&) = ComputeSuffixHash);
+  static std::string ComputeSuffixHash(std::string const&);
+  static std::string ComputeSuffixTime(std::string const&);
+
+  static bool ReadQuery(std::string const& query,
+                        std::vector<Object>& objects);
+  void ReadClient(std::string const& client);
+  void ReadClientQuery(std::string const& client, ClientQueryJson& q);
+
+  Json::Value BuildReplyIndex();
+  Json::Value BuildCMake();
+  Json::Value BuildReply(Query const& q);
+  static Json::Value BuildReplyError(std::string const& error);
+  Json::Value const& AddReplyIndexObject(Object const& o);
+
+  static const char* ObjectKindName(ObjectKind kind);
+  static std::string ObjectName(Object const& o);
+
+  Json::Value BuildObject(Object const& object);
+
+  ClientRequests BuildClientRequests(Json::Value const& requests);
+  ClientRequest BuildClientRequest(Json::Value const& request);
+  Json::Value BuildClientReply(ClientQuery const& q);
+  Json::Value BuildClientReplyResponses(ClientRequests const& requests);
+  Json::Value BuildClientReplyResponse(ClientRequest const& request);
+
+  struct RequestVersion
+  {
+    unsigned int Major = 0;
+    unsigned int Minor = 0;
+  };
+  static bool ReadRequestVersions(Json::Value const& version,
+                                  std::vector<RequestVersion>& versions,
+                                  std::string& error);
+  static bool ReadRequestVersion(Json::Value const& version, bool inArray,
+                                 std::vector<RequestVersion>& result,
+                                 std::string& error);
+  static std::string NoSupportedVersion(
+    std::vector<RequestVersion> const& versions);
+
+  void BuildClientRequestCodeModel(
+    ClientRequest& r, std::vector<RequestVersion> const& versions);
+  Json::Value BuildCodeModel(Object const& object);
+
+  void BuildClientRequestCache(ClientRequest& r,
+                               std::vector<RequestVersion> const& versions);
+  Json::Value BuildCache(Object const& object);
+
+  void BuildClientRequestCMakeFiles(
+    ClientRequest& r, std::vector<RequestVersion> const& versions);
+  Json::Value BuildCMakeFiles(Object const& object);
+
+  void BuildClientRequestInternalTest(
+    ClientRequest& r, std::vector<RequestVersion> const& versions);
+  Json::Value BuildInternalTest(Object const& object);
+};
+
+#endif

+ 113 - 0
Source/cmFileAPICMakeFiles.cxx

@@ -0,0 +1,113 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmFileAPICMakeFiles.h"
+
+#include "cmFileAPI.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+#include "cm_jsoncpp_value.h"
+
+#include <string>
+
+namespace {
+
+class CMakeFiles
+{
+  cmFileAPI& FileAPI;
+  unsigned long Version;
+  std::string CMakeModules;
+  std::string const& TopSource;
+  std::string const& TopBuild;
+  bool OutOfSource;
+
+  Json::Value DumpPaths();
+  Json::Value DumpInputs();
+  Json::Value DumpInput(std::string const& file);
+
+public:
+  CMakeFiles(cmFileAPI& fileAPI, unsigned long version);
+  Json::Value Dump();
+};
+
+CMakeFiles::CMakeFiles(cmFileAPI& fileAPI, unsigned long version)
+  : FileAPI(fileAPI)
+  , Version(version)
+  , CMakeModules(cmSystemTools::GetCMakeRoot() + "/Modules")
+  , TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory())
+  , TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory())
+  , OutOfSource(TopBuild != TopSource)
+{
+  static_cast<void>(this->Version);
+}
+
+Json::Value CMakeFiles::Dump()
+{
+  Json::Value cmakeFiles = Json::objectValue;
+  cmakeFiles["paths"] = this->DumpPaths();
+  cmakeFiles["inputs"] = DumpInputs();
+  return cmakeFiles;
+}
+
+Json::Value CMakeFiles::DumpPaths()
+{
+  Json::Value paths = Json::objectValue;
+  paths["source"] = this->TopSource;
+  paths["build"] = this->TopBuild;
+  return paths;
+}
+
+Json::Value CMakeFiles::DumpInputs()
+{
+  Json::Value inputs = Json::arrayValue;
+
+  cmGlobalGenerator* gg =
+    this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
+  for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) {
+    cmMakefile const* mf = lg->GetMakefile();
+    for (std::string const& file : mf->GetListFiles()) {
+      inputs.append(this->DumpInput(file));
+    }
+  }
+
+  return inputs;
+}
+
+Json::Value CMakeFiles::DumpInput(std::string const& file)
+{
+  Json::Value input = Json::objectValue;
+
+  bool const isCMake = cmSystemTools::IsSubDirectory(file, this->CMakeModules);
+  if (isCMake) {
+    input["isCMake"] = true;
+  }
+
+  if (!cmSystemTools::IsSubDirectory(file, this->TopSource) &&
+      !cmSystemTools::IsSubDirectory(file, this->TopBuild)) {
+    input["isExternal"] = true;
+  }
+
+  if (this->OutOfSource &&
+      cmSystemTools::IsSubDirectory(file, this->TopBuild)) {
+    input["isGenerated"] = true;
+  }
+
+  std::string path = file;
+  if (!isCMake && cmSystemTools::IsSubDirectory(path, this->TopSource)) {
+    // Use a relative path within the source directory.
+    path = cmSystemTools::RelativePath(this->TopSource, path);
+  }
+  input["path"] = path;
+
+  return input;
+}
+}
+
+Json::Value cmFileAPICMakeFilesDump(cmFileAPI& fileAPI, unsigned long version)
+{
+  CMakeFiles cmakeFiles(fileAPI, version);
+  return cmakeFiles.Dump();
+}

+ 15 - 0
Source/cmFileAPICMakeFiles.h

@@ -0,0 +1,15 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmFileAPICMakeFiles_h
+#define cmFileAPICMakeFiles_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_jsoncpp_value.h"
+
+class cmFileAPI;
+
+extern Json::Value cmFileAPICMakeFilesDump(cmFileAPI& fileAPI,
+                                           unsigned long version);
+
+#endif

+ 105 - 0
Source/cmFileAPICache.cxx

@@ -0,0 +1,105 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmFileAPICache.h"
+
+#include "cmFileAPI.h"
+#include "cmState.h"
+#include "cmake.h"
+
+#include "cm_jsoncpp_value.h"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+namespace {
+
+class Cache
+{
+  cmFileAPI& FileAPI;
+  unsigned long Version;
+  cmState* State;
+
+  Json::Value DumpEntries();
+  Json::Value DumpEntry(std::string const& name);
+  Json::Value DumpEntryProperties(std::string const& name);
+  Json::Value DumpEntryProperty(std::string const& name,
+                                std::string const& prop);
+
+public:
+  Cache(cmFileAPI& fileAPI, unsigned long version);
+  Json::Value Dump();
+};
+
+Cache::Cache(cmFileAPI& fileAPI, unsigned long version)
+  : FileAPI(fileAPI)
+  , Version(version)
+  , State(this->FileAPI.GetCMakeInstance()->GetState())
+{
+  static_cast<void>(this->Version);
+}
+
+Json::Value Cache::Dump()
+{
+  Json::Value cache = Json::objectValue;
+  cache["entries"] = DumpEntries();
+  return cache;
+}
+
+Json::Value Cache::DumpEntries()
+{
+  Json::Value entries = Json::arrayValue;
+
+  std::vector<std::string> names = this->State->GetCacheEntryKeys();
+  std::sort(names.begin(), names.end());
+
+  for (std::string const& name : names) {
+    entries.append(this->DumpEntry(name));
+  }
+
+  return entries;
+}
+
+Json::Value Cache::DumpEntry(std::string const& name)
+{
+  Json::Value entry = Json::objectValue;
+  entry["name"] = name;
+  entry["type"] =
+    cmState::CacheEntryTypeToString(this->State->GetCacheEntryType(name));
+  entry["value"] = this->State->GetCacheEntryValue(name);
+
+  Json::Value properties = this->DumpEntryProperties(name);
+  if (!properties.empty()) {
+    entry["properties"] = std::move(properties);
+  }
+
+  return entry;
+}
+
+Json::Value Cache::DumpEntryProperties(std::string const& name)
+{
+  Json::Value properties = Json::arrayValue;
+  std::vector<std::string> props =
+    this->State->GetCacheEntryPropertyList(name);
+  std::sort(props.begin(), props.end());
+  for (std::string const& prop : props) {
+    properties.append(this->DumpEntryProperty(name, prop));
+  }
+  return properties;
+}
+
+Json::Value Cache::DumpEntryProperty(std::string const& name,
+                                     std::string const& prop)
+{
+  Json::Value property = Json::objectValue;
+  property["name"] = prop;
+  property["value"] = this->State->GetCacheEntryProperty(name, prop);
+  return property;
+}
+}
+
+Json::Value cmFileAPICacheDump(cmFileAPI& fileAPI, unsigned long version)
+{
+  Cache cache(fileAPI, version);
+  return cache.Dump();
+}

+ 15 - 0
Source/cmFileAPICache.h

@@ -0,0 +1,15 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmFileAPICache_h
+#define cmFileAPICache_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_jsoncpp_value.h"
+
+class cmFileAPI;
+
+extern Json::Value cmFileAPICacheDump(cmFileAPI& fileAPI,
+                                      unsigned long version);
+
+#endif

+ 1247 - 0
Source/cmFileAPICodemodel.cxx

@@ -0,0 +1,1247 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#include "cmFileAPICodemodel.h"
+
+#include "cmCryptoHash.h"
+#include "cmFileAPI.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallGenerator.h"
+#include "cmInstallSubdirectoryGenerator.h"
+#include "cmInstallTargetGenerator.h"
+#include "cmLinkLineComputer.h"
+#include "cmListFileCache.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmSourceFile.h"
+#include "cmSourceGroup.h"
+#include "cmState.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTargetDepend.h"
+#include "cmake.h"
+
+#include "cm_jsoncpp_value.h"
+
+#include <algorithm>
+#include <cassert>
+#include <map>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+namespace {
+
+class Codemodel
+{
+  cmFileAPI& FileAPI;
+  unsigned long Version;
+
+  Json::Value DumpPaths();
+  Json::Value DumpConfigurations();
+  Json::Value DumpConfiguration(std::string const& config);
+
+public:
+  Codemodel(cmFileAPI& fileAPI, unsigned long version);
+  Json::Value Dump();
+};
+
+class CodemodelConfig
+{
+  cmFileAPI& FileAPI;
+  unsigned long Version;
+  std::string const& Config;
+  std::string TopSource;
+  std::string TopBuild;
+
+  struct Directory
+  {
+    cmStateSnapshot Snapshot;
+    cmLocalGenerator const* LocalGenerator = nullptr;
+    Json::Value TargetIndexes = Json::arrayValue;
+    Json::ArrayIndex ProjectIndex;
+    bool HasInstallRule = false;
+  };
+  std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
+    DirectoryMap;
+  std::vector<Directory> Directories;
+
+  struct Project
+  {
+    cmStateSnapshot Snapshot;
+    static const Json::ArrayIndex NoParentIndex =
+      static_cast<Json::ArrayIndex>(-1);
+    Json::ArrayIndex ParentIndex = NoParentIndex;
+    Json::Value ChildIndexes = Json::arrayValue;
+    Json::Value DirectoryIndexes = Json::arrayValue;
+    Json::Value TargetIndexes = Json::arrayValue;
+  };
+  std::map<cmStateSnapshot, Json::ArrayIndex, cmStateSnapshot::StrictWeakOrder>
+    ProjectMap;
+  std::vector<Project> Projects;
+
+  void ProcessDirectories();
+
+  Json::ArrayIndex GetDirectoryIndex(cmLocalGenerator const* lg);
+  Json::ArrayIndex GetDirectoryIndex(cmStateSnapshot s);
+
+  Json::ArrayIndex AddProject(cmStateSnapshot s);
+
+  Json::Value DumpTargets();
+  Json::Value DumpTarget(cmGeneratorTarget* gt, Json::ArrayIndex ti);
+
+  Json::Value DumpDirectories();
+  Json::Value DumpDirectory(Directory& d);
+
+  Json::Value DumpProjects();
+  Json::Value DumpProject(Project& p);
+
+  Json::Value DumpMinimumCMakeVersion(cmStateSnapshot s);
+
+public:
+  CodemodelConfig(cmFileAPI& fileAPI, unsigned long version,
+                  std::string const& config);
+  Json::Value Dump();
+};
+
+std::string RelativeIfUnder(std::string const& top, std::string const& in)
+{
+  std::string out;
+  if (in == top) {
+    out = ".";
+  } else if (cmSystemTools::IsSubDirectory(in, top)) {
+    out = in.substr(top.size() + 1);
+  } else {
+    out = in;
+  }
+  return out;
+}
+
+std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild)
+{
+  cmCryptoHash hasher(cmCryptoHash::AlgoSHA3_256);
+  std::string path = RelativeIfUnder(
+    topBuild, gt->GetLocalGenerator()->GetCurrentBinaryDirectory());
+  std::string hash = hasher.HashString(path);
+  hash.resize(20, '0');
+  return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash;
+}
+
+class BacktraceData
+{
+  std::string TopSource;
+  std::unordered_map<std::string, Json::ArrayIndex> CommandMap;
+  std::unordered_map<std::string, Json::ArrayIndex> FileMap;
+  std::unordered_map<cmListFileContext const*, Json::ArrayIndex> NodeMap;
+  Json::Value Commands = Json::arrayValue;
+  Json::Value Files = Json::arrayValue;
+  Json::Value Nodes = Json::arrayValue;
+
+  Json::ArrayIndex AddCommand(std::string const& command)
+  {
+    auto i = this->CommandMap.find(command);
+    if (i == this->CommandMap.end()) {
+      auto cmdIndex = static_cast<Json::ArrayIndex>(this->Commands.size());
+      i = this->CommandMap.emplace(command, cmdIndex).first;
+      this->Commands.append(command);
+    }
+    return i->second;
+  }
+
+  Json::ArrayIndex AddFile(std::string const& file)
+  {
+    auto i = this->FileMap.find(file);
+    if (i == this->FileMap.end()) {
+      auto fileIndex = static_cast<Json::ArrayIndex>(this->Files.size());
+      i = this->FileMap.emplace(file, fileIndex).first;
+      this->Files.append(RelativeIfUnder(this->TopSource, file));
+    }
+    return i->second;
+  }
+
+public:
+  BacktraceData(std::string const& topSource);
+  bool Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index);
+  Json::Value Dump();
+};
+
+BacktraceData::BacktraceData(std::string const& topSource)
+  : TopSource(topSource)
+{
+}
+
+bool BacktraceData::Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index)
+{
+  if (bt.Empty()) {
+    return false;
+  }
+  cmListFileContext const* top = &bt.Top();
+  auto found = this->NodeMap.find(top);
+  if (found != this->NodeMap.end()) {
+    index = found->second;
+    return true;
+  }
+  Json::Value entry = Json::objectValue;
+  entry["file"] = this->AddFile(top->FilePath);
+  if (top->Line) {
+    entry["line"] = static_cast<int>(top->Line);
+  }
+  if (!top->Name.empty()) {
+    entry["command"] = this->AddCommand(top->Name);
+  }
+  Json::ArrayIndex parent;
+  if (this->Add(bt.Pop(), parent)) {
+    entry["parent"] = parent;
+  }
+  index = this->NodeMap[top] = this->Nodes.size();
+  this->Nodes.append(std::move(entry)); // NOLINT(*)
+  return true;
+}
+
+Json::Value BacktraceData::Dump()
+{
+  Json::Value backtraceGraph;
+  this->CommandMap.clear();
+  this->FileMap.clear();
+  this->NodeMap.clear();
+  backtraceGraph["commands"] = std::move(this->Commands);
+  backtraceGraph["files"] = std::move(this->Files);
+  backtraceGraph["nodes"] = std::move(this->Nodes);
+  return backtraceGraph;
+}
+
+struct CompileData
+{
+  struct IncludeEntry
+  {
+    BT<std::string> Path;
+    bool IsSystem = false;
+    IncludeEntry(BT<std::string> path, bool isSystem)
+      : Path(std::move(path))
+      , IsSystem(isSystem)
+    {
+    }
+  };
+
+  void SetDefines(std::set<BT<std::string>> const& defines);
+
+  std::string Language;
+  std::string Sysroot;
+  std::vector<BT<std::string>> Flags;
+  std::vector<BT<std::string>> Defines;
+  std::vector<IncludeEntry> Includes;
+};
+
+void CompileData::SetDefines(std::set<BT<std::string>> const& defines)
+{
+  this->Defines.reserve(defines.size());
+  for (BT<std::string> const& d : defines) {
+    this->Defines.push_back(d);
+  }
+}
+
+class Target
+{
+  cmGeneratorTarget* GT;
+  std::string const& Config;
+  std::string TopSource;
+  std::string TopBuild;
+  std::vector<cmSourceGroup> SourceGroupsLocal;
+  BacktraceData Backtraces;
+
+  std::map<std::string, CompileData> CompileDataMap;
+
+  std::unordered_map<cmSourceFile const*, Json::ArrayIndex> SourceMap;
+  Json::Value Sources = Json::arrayValue;
+
+  struct SourceGroup
+  {
+    std::string Name;
+    Json::Value SourceIndexes = Json::arrayValue;
+  };
+  std::unordered_map<cmSourceGroup const*, Json::ArrayIndex> SourceGroupsMap;
+  std::vector<SourceGroup> SourceGroups;
+
+  struct CompileGroup
+  {
+    std::map<Json::Value, Json::ArrayIndex>::iterator Entry;
+    Json::Value SourceIndexes = Json::arrayValue;
+  };
+  std::map<Json::Value, Json::ArrayIndex> CompileGroupMap;
+  std::vector<CompileGroup> CompileGroups;
+
+  void ProcessLanguages();
+  void ProcessLanguage(std::string const& lang);
+
+  Json::ArrayIndex AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si);
+  CompileData BuildCompileData(cmSourceFile* sf);
+  Json::ArrayIndex AddSourceCompileGroup(cmSourceFile* sf,
+                                         Json::ArrayIndex si);
+  void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt);
+  Json::Value DumpPaths();
+  Json::Value DumpCompileData(CompileData cd);
+  Json::Value DumpInclude(CompileData::IncludeEntry const& inc);
+  Json::Value DumpDefine(BT<std::string> const& def);
+  Json::Value DumpSources();
+  Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
+                         Json::ArrayIndex si);
+  Json::Value DumpSourceGroups();
+  Json::Value DumpSourceGroup(SourceGroup& sg);
+  Json::Value DumpCompileGroups();
+  Json::Value DumpCompileGroup(CompileGroup& cg);
+  Json::Value DumpSysroot(std::string const& path);
+  Json::Value DumpInstall();
+  Json::Value DumpInstallPrefix();
+  Json::Value DumpInstallDestinations();
+  Json::Value DumpInstallDestination(cmInstallTargetGenerator* itGen);
+  Json::Value DumpArtifacts();
+  Json::Value DumpLink();
+  Json::Value DumpArchive();
+  Json::Value DumpLinkCommandFragments();
+  Json::Value DumpCommandFragments(std::vector<BT<std::string>> const& frags);
+  Json::Value DumpCommandFragment(BT<std::string> const& frag,
+                                  std::string const& role = std::string());
+  Json::Value DumpDependencies();
+  Json::Value DumpDependency(cmTargetDepend const& td);
+  Json::Value DumpFolder();
+
+public:
+  Target(cmGeneratorTarget* gt, std::string const& config);
+  Json::Value Dump();
+};
+
+Codemodel::Codemodel(cmFileAPI& fileAPI, unsigned long version)
+  : FileAPI(fileAPI)
+  , Version(version)
+{
+}
+
+Json::Value Codemodel::Dump()
+{
+  Json::Value codemodel = Json::objectValue;
+
+  codemodel["paths"] = this->DumpPaths();
+  codemodel["configurations"] = this->DumpConfigurations();
+
+  return codemodel;
+}
+
+Json::Value Codemodel::DumpPaths()
+{
+  Json::Value paths = Json::objectValue;
+  paths["source"] = this->FileAPI.GetCMakeInstance()->GetHomeDirectory();
+  paths["build"] = this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory();
+  return paths;
+}
+
+Json::Value Codemodel::DumpConfigurations()
+{
+  std::vector<std::string> configs;
+  cmGlobalGenerator* gg =
+    this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
+  auto makefiles = gg->GetMakefiles();
+  if (!makefiles.empty()) {
+    makefiles[0]->GetConfigurations(configs);
+    if (configs.empty()) {
+      configs.emplace_back();
+    }
+  }
+  Json::Value configurations = Json::arrayValue;
+  for (std::string const& config : configs) {
+    configurations.append(this->DumpConfiguration(config));
+  }
+  return configurations;
+}
+
+Json::Value Codemodel::DumpConfiguration(std::string const& config)
+{
+  CodemodelConfig configuration(this->FileAPI, this->Version, config);
+  return configuration.Dump();
+}
+
+CodemodelConfig::CodemodelConfig(cmFileAPI& fileAPI, unsigned long version,
+                                 std::string const& config)
+  : FileAPI(fileAPI)
+  , Version(version)
+  , Config(config)
+  , TopSource(this->FileAPI.GetCMakeInstance()->GetHomeDirectory())
+  , TopBuild(this->FileAPI.GetCMakeInstance()->GetHomeOutputDirectory())
+{
+  static_cast<void>(this->Version);
+}
+
+Json::Value CodemodelConfig::Dump()
+{
+  Json::Value configuration = Json::objectValue;
+  configuration["name"] = this->Config;
+  this->ProcessDirectories();
+  configuration["targets"] = this->DumpTargets();
+  configuration["directories"] = this->DumpDirectories();
+  configuration["projects"] = this->DumpProjects();
+  return configuration;
+}
+
+void CodemodelConfig::ProcessDirectories()
+{
+  cmGlobalGenerator* gg =
+    this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
+  std::vector<cmLocalGenerator*> const& localGens = gg->GetLocalGenerators();
+
+  // Add directories in forward order to process parents before children.
+  this->Directories.reserve(localGens.size());
+  for (cmLocalGenerator* lg : localGens) {
+    auto directoryIndex =
+      static_cast<Json::ArrayIndex>(this->Directories.size());
+    this->Directories.emplace_back();
+    Directory& d = this->Directories[directoryIndex];
+    d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory();
+    d.LocalGenerator = lg;
+    this->DirectoryMap[d.Snapshot] = directoryIndex;
+
+    d.ProjectIndex = this->AddProject(d.Snapshot);
+    this->Projects[d.ProjectIndex].DirectoryIndexes.append(directoryIndex);
+  }
+
+  // Update directories in reverse order to process children before parents.
+  for (auto di = this->Directories.rbegin(); di != this->Directories.rend();
+       ++di) {
+    Directory& d = *di;
+
+    // Accumulate the presence of install rules on the way up.
+    for (auto gen : d.LocalGenerator->GetMakefile()->GetInstallGenerators()) {
+      if (!dynamic_cast<cmInstallSubdirectoryGenerator*>(gen)) {
+        d.HasInstallRule = true;
+        break;
+      }
+    }
+    if (!d.HasInstallRule) {
+      for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) {
+        cmStateSnapshot childDir = child.GetBuildsystemDirectory();
+        Json::ArrayIndex const childIndex = this->GetDirectoryIndex(childDir);
+        if (this->Directories[childIndex].HasInstallRule) {
+          d.HasInstallRule = true;
+          break;
+        }
+      }
+    }
+  }
+}
+
+Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmLocalGenerator const* lg)
+{
+  return this->GetDirectoryIndex(
+    lg->GetStateSnapshot().GetBuildsystemDirectory());
+}
+
+Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmStateSnapshot s)
+{
+  auto i = this->DirectoryMap.find(s);
+  assert(i != this->DirectoryMap.end());
+  return i->second;
+}
+
+Json::ArrayIndex CodemodelConfig::AddProject(cmStateSnapshot s)
+{
+  cmStateSnapshot ps = s.GetBuildsystemDirectoryParent();
+  if (ps.IsValid() && ps.GetProjectName() == s.GetProjectName()) {
+    // This directory is part of its parent directory project.
+    Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps);
+    return this->Directories[parentDirIndex].ProjectIndex;
+  }
+
+  // This directory starts a new project.
+  auto projectIndex = static_cast<Json::ArrayIndex>(this->Projects.size());
+  this->Projects.emplace_back();
+  Project& p = this->Projects[projectIndex];
+  p.Snapshot = s;
+  this->ProjectMap[s] = projectIndex;
+  if (ps.IsValid()) {
+    Json::ArrayIndex const parentDirIndex = this->GetDirectoryIndex(ps);
+    p.ParentIndex = this->Directories[parentDirIndex].ProjectIndex;
+    this->Projects[p.ParentIndex].ChildIndexes.append(projectIndex);
+  }
+  return projectIndex;
+}
+
+Json::Value CodemodelConfig::DumpTargets()
+{
+  Json::Value targets = Json::arrayValue;
+
+  std::vector<cmGeneratorTarget*> targetList;
+  cmGlobalGenerator* gg =
+    this->FileAPI.GetCMakeInstance()->GetGlobalGenerator();
+  for (cmLocalGenerator const* lg : gg->GetLocalGenerators()) {
+    std::vector<cmGeneratorTarget*> const& list = lg->GetGeneratorTargets();
+    targetList.insert(targetList.end(), list.begin(), list.end());
+  }
+  std::sort(targetList.begin(), targetList.end(),
+            [](cmGeneratorTarget* l, cmGeneratorTarget* r) {
+              return l->GetName() < r->GetName();
+            });
+
+  for (cmGeneratorTarget* gt : targetList) {
+    if (gt->GetType() == cmStateEnums::GLOBAL_TARGET ||
+        gt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+      continue;
+    }
+
+    targets.append(this->DumpTarget(gt, targets.size()));
+  }
+
+  return targets;
+}
+
+Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt,
+                                        Json::ArrayIndex ti)
+{
+  Target t(gt, this->Config);
+  std::string prefix = "target-" + gt->GetName();
+  if (!this->Config.empty()) {
+    prefix += "-" + this->Config;
+  }
+  Json::Value target = this->FileAPI.MaybeJsonFile(t.Dump(), prefix);
+  target["name"] = gt->GetName();
+  target["id"] = TargetId(gt, this->TopBuild);
+
+  // Cross-reference directory containing target.
+  Json::ArrayIndex di = this->GetDirectoryIndex(gt->GetLocalGenerator());
+  target["directoryIndex"] = di;
+  this->Directories[di].TargetIndexes.append(ti);
+
+  // Cross-reference project containing target.
+  Json::ArrayIndex pi = this->Directories[di].ProjectIndex;
+  target["projectIndex"] = pi;
+  this->Projects[pi].TargetIndexes.append(ti);
+
+  return target;
+}
+
+Json::Value CodemodelConfig::DumpDirectories()
+{
+  Json::Value directories = Json::arrayValue;
+  for (Directory& d : this->Directories) {
+    directories.append(this->DumpDirectory(d));
+  }
+  return directories;
+}
+
+Json::Value CodemodelConfig::DumpDirectory(Directory& d)
+{
+  Json::Value directory = Json::objectValue;
+
+  std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource();
+  directory["source"] = RelativeIfUnder(this->TopSource, sourceDir);
+
+  std::string buildDir = d.Snapshot.GetDirectory().GetCurrentBinary();
+  directory["build"] = RelativeIfUnder(this->TopBuild, buildDir);
+
+  cmStateSnapshot parentDir = d.Snapshot.GetBuildsystemDirectoryParent();
+  if (parentDir.IsValid()) {
+    directory["parentIndex"] = this->GetDirectoryIndex(parentDir);
+  }
+
+  Json::Value childIndexes = Json::arrayValue;
+  for (cmStateSnapshot const& child : d.Snapshot.GetChildren()) {
+    childIndexes.append(
+      this->GetDirectoryIndex(child.GetBuildsystemDirectory()));
+  }
+  if (!childIndexes.empty()) {
+    directory["childIndexes"] = std::move(childIndexes);
+  }
+
+  directory["projectIndex"] = d.ProjectIndex;
+
+  if (!d.TargetIndexes.empty()) {
+    directory["targetIndexes"] = std::move(d.TargetIndexes);
+  }
+
+  Json::Value minimumCMakeVersion = this->DumpMinimumCMakeVersion(d.Snapshot);
+  if (!minimumCMakeVersion.isNull()) {
+    directory["minimumCMakeVersion"] = std::move(minimumCMakeVersion);
+  }
+
+  if (d.HasInstallRule) {
+    directory["hasInstallRule"] = true;
+  }
+
+  return directory;
+}
+
+Json::Value CodemodelConfig::DumpProjects()
+{
+  Json::Value projects = Json::arrayValue;
+  for (Project& p : this->Projects) {
+    projects.append(this->DumpProject(p));
+  }
+  return projects;
+}
+
+Json::Value CodemodelConfig::DumpProject(Project& p)
+{
+  Json::Value project = Json::objectValue;
+
+  project["name"] = p.Snapshot.GetProjectName();
+
+  if (p.ParentIndex != Project::NoParentIndex) {
+    project["parentIndex"] = p.ParentIndex;
+  }
+
+  if (!p.ChildIndexes.empty()) {
+    project["childIndexes"] = std::move(p.ChildIndexes);
+  }
+
+  project["directoryIndexes"] = std::move(p.DirectoryIndexes);
+
+  if (!p.TargetIndexes.empty()) {
+    project["targetIndexes"] = std::move(p.TargetIndexes);
+  }
+
+  return project;
+}
+
+Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s)
+{
+  Json::Value minimumCMakeVersion;
+  if (std::string const* def =
+        s.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION")) {
+    minimumCMakeVersion = Json::objectValue;
+    minimumCMakeVersion["string"] = *def;
+  }
+  return minimumCMakeVersion;
+}
+
+Target::Target(cmGeneratorTarget* gt, std::string const& config)
+  : GT(gt)
+  , Config(config)
+  , TopSource(gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory())
+  , TopBuild(
+      gt->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory())
+  , SourceGroupsLocal(this->GT->Makefile->GetSourceGroups())
+  , Backtraces(this->TopSource)
+{
+}
+
+Json::Value Target::Dump()
+{
+  Json::Value target = Json::objectValue;
+
+  cmStateEnums::TargetType const type = this->GT->GetType();
+
+  target["name"] = this->GT->GetName();
+  target["type"] = cmState::GetTargetTypeName(type);
+  target["id"] = TargetId(this->GT, this->TopBuild);
+  target["paths"] = this->DumpPaths();
+  if (this->GT->Target->GetIsGeneratorProvided()) {
+    target["isGeneratorProvided"] = true;
+  }
+
+  this->AddBacktrace(target, this->GT->GetBacktrace());
+
+  if (this->GT->Target->GetHaveInstallRule()) {
+    target["install"] = this->DumpInstall();
+  }
+
+  if (this->GT->HaveWellDefinedOutputFiles()) {
+    Json::Value artifacts = this->DumpArtifacts();
+    if (!artifacts.empty()) {
+      target["artifacts"] = std::move(artifacts);
+    }
+  }
+
+  if (type == cmStateEnums::EXECUTABLE ||
+      type == cmStateEnums::SHARED_LIBRARY ||
+      type == cmStateEnums::MODULE_LIBRARY) {
+    target["nameOnDisk"] = this->GT->GetFullName(this->Config);
+    target["link"] = this->DumpLink();
+  } else if (type == cmStateEnums::STATIC_LIBRARY) {
+    target["nameOnDisk"] = this->GT->GetFullName(this->Config);
+    target["archive"] = this->DumpArchive();
+  }
+
+  Json::Value dependencies = this->DumpDependencies();
+  if (!dependencies.empty()) {
+    target["dependencies"] = dependencies;
+  }
+
+  {
+    this->ProcessLanguages();
+
+    target["sources"] = this->DumpSources();
+
+    Json::Value folder = this->DumpFolder();
+    if (!folder.isNull()) {
+      target["folder"] = std::move(folder);
+    }
+
+    Json::Value sourceGroups = this->DumpSourceGroups();
+    if (!sourceGroups.empty()) {
+      target["sourceGroups"] = std::move(sourceGroups);
+    }
+
+    Json::Value compileGroups = this->DumpCompileGroups();
+    if (!compileGroups.empty()) {
+      target["compileGroups"] = std::move(compileGroups);
+    }
+  }
+
+  target["backtraceGraph"] = this->Backtraces.Dump();
+
+  return target;
+}
+
+void Target::ProcessLanguages()
+{
+  std::set<std::string> languages;
+  this->GT->GetLanguages(languages, this->Config);
+  for (std::string const& lang : languages) {
+    this->ProcessLanguage(lang);
+  }
+}
+
+void Target::ProcessLanguage(std::string const& lang)
+{
+  CompileData& cd = this->CompileDataMap[lang];
+  cd.Language = lang;
+  if (const char* sysrootCompile =
+        this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_COMPILE")) {
+    cd.Sysroot = sysrootCompile;
+  } else if (const char* sysroot =
+               this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
+    cd.Sysroot = sysroot;
+  }
+  cmLocalGenerator* lg = this->GT->GetLocalGenerator();
+  {
+    // FIXME: Add flags from end section of ExpandRuleVariable,
+    // which may need to be factored out.
+    std::string flags;
+    lg->GetTargetCompileFlags(this->GT, this->Config, lang, flags);
+    cd.Flags.emplace_back(std::move(flags), cmListFileBacktrace());
+  }
+  std::set<BT<std::string>> defines =
+    lg->GetTargetDefines(this->GT, this->Config, lang);
+  cd.SetDefines(defines);
+  std::vector<BT<std::string>> includePathList =
+    lg->GetIncludeDirectories(this->GT, lang, this->Config, true);
+  for (BT<std::string> const& i : includePathList) {
+    cd.Includes.emplace_back(
+      i, this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang));
+  }
+}
+
+Json::ArrayIndex Target::AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si)
+{
+  std::unordered_map<cmSourceGroup const*, Json::ArrayIndex>::iterator i =
+    this->SourceGroupsMap.find(sg);
+  if (i == this->SourceGroupsMap.end()) {
+    auto sgIndex = static_cast<Json::ArrayIndex>(this->SourceGroups.size());
+    i = this->SourceGroupsMap.emplace(sg, sgIndex).first;
+    SourceGroup g;
+    g.Name = sg->GetFullName();
+    this->SourceGroups.push_back(std::move(g));
+  }
+  this->SourceGroups[i->second].SourceIndexes.append(si);
+  return i->second;
+}
+
+CompileData Target::BuildCompileData(cmSourceFile* sf)
+{
+  CompileData fd;
+
+  fd.Language = sf->GetLanguage();
+  if (fd.Language.empty()) {
+    return fd;
+  }
+  CompileData const& cd = this->CompileDataMap.at(fd.Language);
+
+  fd.Sysroot = cd.Sysroot;
+
+  cmLocalGenerator* lg = this->GT->GetLocalGenerator();
+  cmGeneratorExpressionInterpreter genexInterpreter(lg, this->Config, this->GT,
+                                                    fd.Language);
+
+  fd.Flags = cd.Flags;
+  const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+  if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) {
+    std::string flags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS);
+    fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace());
+  }
+  const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+  if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) {
+    std::string flags;
+    lg->AppendCompileOptions(
+      flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
+    fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace());
+  }
+
+  // Add include directories from source file properties.
+  {
+    std::vector<std::string> includes;
+    const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+    if (const char* cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) {
+      const std::string& evaluatedIncludes =
+        genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES);
+      lg->AppendIncludeDirectories(includes, evaluatedIncludes, *sf);
+
+      for (std::string const& include : includes) {
+        bool const isSystemInclude = this->GT->IsSystemIncludeDirectory(
+          include, this->Config, fd.Language);
+        fd.Includes.emplace_back(include, isSystemInclude);
+      }
+    }
+  }
+  fd.Includes.insert(fd.Includes.end(), cd.Includes.begin(),
+                     cd.Includes.end());
+
+  const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
+  std::set<std::string> fileDefines;
+  if (const char* defs = sf->GetProperty(COMPILE_DEFINITIONS)) {
+    lg->AppendDefines(fileDefines,
+                      genexInterpreter.Evaluate(defs, COMPILE_DEFINITIONS));
+  }
+
+  const std::string defPropName =
+    "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(this->Config);
+  if (const char* config_defs = sf->GetProperty(defPropName)) {
+    lg->AppendDefines(
+      fileDefines,
+      genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS));
+  }
+
+  std::set<BT<std::string>> defines;
+  defines.insert(fileDefines.begin(), fileDefines.end());
+  defines.insert(cd.Defines.begin(), cd.Defines.end());
+
+  fd.SetDefines(defines);
+
+  return fd;
+}
+
+Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf,
+                                               Json::ArrayIndex si)
+{
+  Json::Value compileDataJson =
+    this->DumpCompileData(this->BuildCompileData(sf));
+  std::map<Json::Value, Json::ArrayIndex>::iterator i =
+    this->CompileGroupMap.find(compileDataJson);
+  if (i == this->CompileGroupMap.end()) {
+    Json::ArrayIndex cgIndex =
+      static_cast<Json::ArrayIndex>(this->CompileGroups.size());
+    i =
+      this->CompileGroupMap.emplace(std::move(compileDataJson), cgIndex).first;
+    CompileGroup g;
+    g.Entry = i;
+    this->CompileGroups.push_back(std::move(g));
+  }
+  this->CompileGroups[i->second].SourceIndexes.append(si);
+  return i->second;
+}
+
+void Target::AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt)
+{
+  Json::ArrayIndex backtrace;
+  if (this->Backtraces.Add(bt, backtrace)) {
+    object["backtrace"] = backtrace;
+  }
+}
+
+Json::Value Target::DumpPaths()
+{
+  Json::Value paths = Json::objectValue;
+  cmLocalGenerator* lg = this->GT->GetLocalGenerator();
+
+  std::string const& sourceDir = lg->GetCurrentSourceDirectory();
+  paths["source"] = RelativeIfUnder(this->TopSource, sourceDir);
+
+  std::string const& buildDir = lg->GetCurrentBinaryDirectory();
+  paths["build"] = RelativeIfUnder(this->TopBuild, buildDir);
+
+  return paths;
+}
+
+Json::Value Target::DumpSources()
+{
+  Json::Value sources = Json::arrayValue;
+  cmGeneratorTarget::KindedSources const& kinded =
+    this->GT->GetKindedSources(this->Config);
+  for (cmGeneratorTarget::SourceAndKind const& sk : kinded.Sources) {
+    sources.append(this->DumpSource(sk, sources.size()));
+  }
+  return sources;
+}
+
+Json::Value Target::DumpSource(cmGeneratorTarget::SourceAndKind const& sk,
+                               Json::ArrayIndex si)
+{
+  Json::Value source = Json::objectValue;
+
+  std::string const path = sk.Source.Value->GetFullPath();
+  source["path"] = RelativeIfUnder(this->TopSource, path);
+  if (sk.Source.Value->GetPropertyAsBool("GENERATED")) {
+    source["isGenerated"] = true;
+  }
+  this->AddBacktrace(source, sk.Source.Backtrace);
+
+  if (cmSourceGroup* sg =
+        this->GT->Makefile->FindSourceGroup(path, this->SourceGroupsLocal)) {
+    source["sourceGroupIndex"] = this->AddSourceGroup(sg, si);
+  }
+
+  switch (sk.Kind) {
+    case cmGeneratorTarget::SourceKindObjectSource: {
+      source["compileGroupIndex"] =
+        this->AddSourceCompileGroup(sk.Source.Value, si);
+    } break;
+    case cmGeneratorTarget::SourceKindAppManifest:
+    case cmGeneratorTarget::SourceKindCertificate:
+    case cmGeneratorTarget::SourceKindCustomCommand:
+    case cmGeneratorTarget::SourceKindExternalObject:
+    case cmGeneratorTarget::SourceKindExtra:
+    case cmGeneratorTarget::SourceKindHeader:
+    case cmGeneratorTarget::SourceKindIDL:
+    case cmGeneratorTarget::SourceKindManifest:
+    case cmGeneratorTarget::SourceKindModuleDefinition:
+    case cmGeneratorTarget::SourceKindResx:
+    case cmGeneratorTarget::SourceKindXaml:
+      break;
+  }
+
+  return source;
+}
+
+Json::Value Target::DumpCompileData(CompileData cd)
+{
+  Json::Value result = Json::objectValue;
+
+  if (!cd.Language.empty()) {
+    result["language"] = cd.Language;
+  }
+  if (!cd.Sysroot.empty()) {
+    result["sysroot"] = this->DumpSysroot(cd.Sysroot);
+  }
+  if (!cd.Flags.empty()) {
+    result["compileCommandFragments"] = this->DumpCommandFragments(cd.Flags);
+  }
+  if (!cd.Includes.empty()) {
+    Json::Value includes = Json::arrayValue;
+    for (auto const& i : cd.Includes) {
+      includes.append(this->DumpInclude(i));
+    }
+    result["includes"] = includes;
+  }
+  if (!cd.Defines.empty()) {
+    Json::Value defines = Json::arrayValue;
+    for (BT<std::string> const& d : cd.Defines) {
+      defines.append(this->DumpDefine(d));
+    }
+    result["defines"] = std::move(defines);
+  }
+
+  return result;
+}
+
+Json::Value Target::DumpInclude(CompileData::IncludeEntry const& inc)
+{
+  Json::Value include = Json::objectValue;
+  include["path"] = inc.Path.Value;
+  if (inc.IsSystem) {
+    include["isSystem"] = true;
+  }
+  this->AddBacktrace(include, inc.Path.Backtrace);
+  return include;
+}
+
+Json::Value Target::DumpDefine(BT<std::string> const& def)
+{
+  Json::Value define = Json::objectValue;
+  define["define"] = def.Value;
+  this->AddBacktrace(define, def.Backtrace);
+  return define;
+}
+
+Json::Value Target::DumpSourceGroups()
+{
+  Json::Value sourceGroups = Json::arrayValue;
+  for (auto& sg : this->SourceGroups) {
+    sourceGroups.append(this->DumpSourceGroup(sg));
+  }
+  return sourceGroups;
+}
+
+Json::Value Target::DumpSourceGroup(SourceGroup& sg)
+{
+  Json::Value group = Json::objectValue;
+  group["name"] = sg.Name;
+  group["sourceIndexes"] = std::move(sg.SourceIndexes);
+  return group;
+}
+
+Json::Value Target::DumpCompileGroups()
+{
+  Json::Value compileGroups = Json::arrayValue;
+  for (auto& cg : this->CompileGroups) {
+    compileGroups.append(this->DumpCompileGroup(cg));
+  }
+  return compileGroups;
+}
+
+Json::Value Target::DumpCompileGroup(CompileGroup& cg)
+{
+  Json::Value group = cg.Entry->first;
+  group["sourceIndexes"] = std::move(cg.SourceIndexes);
+  return group;
+}
+
+Json::Value Target::DumpSysroot(std::string const& path)
+{
+  Json::Value sysroot = Json::objectValue;
+  sysroot["path"] = path;
+  return sysroot;
+}
+
+Json::Value Target::DumpInstall()
+{
+  Json::Value install = Json::objectValue;
+  install["prefix"] = this->DumpInstallPrefix();
+  install["destinations"] = this->DumpInstallDestinations();
+  return install;
+}
+
+Json::Value Target::DumpInstallPrefix()
+{
+  Json::Value prefix = Json::objectValue;
+  std::string p =
+    this->GT->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+  cmSystemTools::ConvertToUnixSlashes(p);
+  prefix["path"] = p;
+  return prefix;
+}
+
+Json::Value Target::DumpInstallDestinations()
+{
+  Json::Value destinations = Json::arrayValue;
+  auto installGens = this->GT->Makefile->GetInstallGenerators();
+  for (auto iGen : installGens) {
+    auto itGen = dynamic_cast<cmInstallTargetGenerator*>(iGen);
+    if (itGen != nullptr && itGen->GetTarget() == this->GT) {
+      destinations.append(this->DumpInstallDestination(itGen));
+    }
+  }
+  return destinations;
+}
+
+Json::Value Target::DumpInstallDestination(cmInstallTargetGenerator* itGen)
+{
+  Json::Value destination = Json::objectValue;
+  destination["path"] = itGen->GetDestination(this->Config);
+  this->AddBacktrace(destination, itGen->GetBacktrace());
+  return destination;
+}
+
+Json::Value Target::DumpArtifacts()
+{
+  Json::Value artifacts = Json::arrayValue;
+
+  // Object libraries have only object files as artifacts.
+  if (this->GT->GetType() == cmStateEnums::OBJECT_LIBRARY) {
+    if (!this->GT->GetGlobalGenerator()->HasKnownObjectFileLocation(nullptr)) {
+      return artifacts;
+    }
+    std::vector<cmSourceFile const*> objectSources;
+    this->GT->GetObjectSources(objectSources, this->Config);
+    std::string const obj_dir = this->GT->GetObjectDirectory(this->Config);
+    for (cmSourceFile const* sf : objectSources) {
+      const std::string& obj = this->GT->GetObjectName(sf);
+      Json::Value artifact = Json::objectValue;
+      artifact["path"] = RelativeIfUnder(this->TopBuild, obj_dir + obj);
+      artifacts.append(std::move(artifact)); // NOLINT(*)
+    }
+    return artifacts;
+  }
+
+  // Other target types always have a "main" artifact.
+  {
+    Json::Value artifact = Json::objectValue;
+    artifact["path"] =
+      RelativeIfUnder(this->TopBuild,
+                      this->GT->GetFullPath(
+                        this->Config, cmStateEnums::RuntimeBinaryArtifact));
+    artifacts.append(std::move(artifact)); // NOLINT(*)
+  }
+
+  // Add Windows-specific artifacts produced by the linker.
+  if (this->GT->IsDLLPlatform() &&
+      this->GT->GetType() != cmStateEnums::STATIC_LIBRARY) {
+    if (this->GT->GetType() == cmStateEnums::SHARED_LIBRARY ||
+        this->GT->IsExecutableWithExports()) {
+      Json::Value artifact = Json::objectValue;
+      artifact["path"] =
+        RelativeIfUnder(this->TopBuild,
+                        this->GT->GetFullPath(
+                          this->Config, cmStateEnums::ImportLibraryArtifact));
+      artifacts.append(std::move(artifact)); // NOLINT(*)
+    }
+    cmGeneratorTarget::OutputInfo const* output =
+      this->GT->GetOutputInfo(this->Config);
+    if (output && !output->PdbDir.empty()) {
+      Json::Value artifact = Json::objectValue;
+      artifact["path"] = RelativeIfUnder(this->TopBuild,
+                                         output->PdbDir + '/' +
+                                           this->GT->GetPDBName(this->Config));
+      artifacts.append(std::move(artifact)); // NOLINT(*)
+    }
+  }
+  return artifacts;
+}
+
+Json::Value Target::DumpLink()
+{
+  Json::Value link = Json::objectValue;
+  std::string lang = this->GT->GetLinkerLanguage(this->Config);
+  link["language"] = lang;
+  {
+    Json::Value commandFragments = this->DumpLinkCommandFragments();
+    if (!commandFragments.empty()) {
+      link["commandFragments"] = std::move(commandFragments);
+    }
+  }
+  if (const char* sysrootLink =
+        this->GT->Makefile->GetDefinition("CMAKE_SYSROOT_LINK")) {
+    link["sysroot"] = this->DumpSysroot(sysrootLink);
+  } else if (const char* sysroot =
+               this->GT->Makefile->GetDefinition("CMAKE_SYSROOT")) {
+    link["sysroot"] = this->DumpSysroot(sysroot);
+  }
+  if (this->GT->IsIPOEnabled(lang, this->Config)) {
+    link["lto"] = true;
+  }
+  return link;
+}
+
+Json::Value Target::DumpArchive()
+{
+  Json::Value archive = Json::objectValue;
+  {
+    // The "link" fragments not relevant to static libraries are empty.
+    Json::Value commandFragments = this->DumpLinkCommandFragments();
+    if (!commandFragments.empty()) {
+      archive["commandFragments"] = std::move(commandFragments);
+    }
+  }
+  std::string lang = this->GT->GetLinkerLanguage(this->Config);
+  if (this->GT->IsIPOEnabled(lang, this->Config)) {
+    archive["lto"] = true;
+  }
+  return archive;
+}
+
+Json::Value Target::DumpLinkCommandFragments()
+{
+  Json::Value linkFragments = Json::arrayValue;
+
+  std::string linkLanguageFlags;
+  std::string linkFlags;
+  std::string frameworkPath;
+  std::string linkPath;
+  std::string linkLibs;
+  cmLocalGenerator* lg = this->GT->GetLocalGenerator();
+  cmLinkLineComputer linkLineComputer(lg,
+                                      lg->GetStateSnapshot().GetDirectory());
+  lg->GetTargetFlags(&linkLineComputer, this->Config, linkLibs,
+                     linkLanguageFlags, linkFlags, frameworkPath, linkPath,
+                     this->GT);
+  linkLanguageFlags = cmSystemTools::TrimWhitespace(linkLanguageFlags);
+  linkFlags = cmSystemTools::TrimWhitespace(linkFlags);
+  frameworkPath = cmSystemTools::TrimWhitespace(frameworkPath);
+  linkPath = cmSystemTools::TrimWhitespace(linkPath);
+  linkLibs = cmSystemTools::TrimWhitespace(linkLibs);
+
+  if (!linkLanguageFlags.empty()) {
+    linkFragments.append(
+      this->DumpCommandFragment(std::move(linkLanguageFlags), "flags"));
+  }
+
+  if (!linkFlags.empty()) {
+    linkFragments.append(
+      this->DumpCommandFragment(std::move(linkFlags), "flags"));
+  }
+
+  if (!frameworkPath.empty()) {
+    linkFragments.append(
+      this->DumpCommandFragment(std::move(frameworkPath), "frameworkPath"));
+  }
+
+  if (!linkPath.empty()) {
+    linkFragments.append(
+      this->DumpCommandFragment(std::move(linkPath), "libraryPath"));
+  }
+
+  if (!linkLibs.empty()) {
+    linkFragments.append(
+      this->DumpCommandFragment(std::move(linkLibs), "libraries"));
+  }
+
+  return linkFragments;
+}
+
+Json::Value Target::DumpCommandFragments(
+  std::vector<BT<std::string>> const& frags)
+{
+  Json::Value commandFragments = Json::arrayValue;
+  for (BT<std::string> const& f : frags) {
+    commandFragments.append(this->DumpCommandFragment(f));
+  }
+  return commandFragments;
+}
+
+Json::Value Target::DumpCommandFragment(BT<std::string> const& frag,
+                                        std::string const& role)
+{
+  Json::Value fragment = Json::objectValue;
+  fragment["fragment"] = frag.Value;
+  if (!role.empty()) {
+    fragment["role"] = role;
+  }
+  this->AddBacktrace(fragment, frag.Backtrace);
+  return fragment;
+}
+
+Json::Value Target::DumpDependencies()
+{
+  Json::Value dependencies = Json::arrayValue;
+  cmGlobalGenerator* gg = this->GT->GetGlobalGenerator();
+  for (cmTargetDepend const& td : gg->GetTargetDirectDepends(this->GT)) {
+    dependencies.append(this->DumpDependency(td));
+  }
+  return dependencies;
+}
+
+Json::Value Target::DumpDependency(cmTargetDepend const& td)
+{
+  Json::Value dependency = Json::objectValue;
+  dependency["id"] = TargetId(td, this->TopBuild);
+  this->AddBacktrace(dependency, td.GetBacktrace());
+  return dependency;
+}
+
+Json::Value Target::DumpFolder()
+{
+  Json::Value folder;
+  if (const char* f = this->GT->GetProperty("FOLDER")) {
+    folder = Json::objectValue;
+    folder["name"] = f;
+  }
+  return folder;
+}
+}
+
+Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI, unsigned long version)
+{
+  Codemodel codemodel(fileAPI, version);
+  return codemodel.Dump();
+}

+ 15 - 0
Source/cmFileAPICodemodel.h

@@ -0,0 +1,15 @@
+/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+   file Copyright.txt or https://cmake.org/licensing for details.  */
+#ifndef cmFileAPICodemodel_h
+#define cmFileAPICodemodel_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_jsoncpp_value.h"
+
+class cmFileAPI;
+
+extern Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI,
+                                          unsigned long version);
+
+#endif

+ 9 - 0
Source/cmGlobalGenerator.cxx

@@ -112,6 +112,15 @@ cmGlobalGenerator::~cmGlobalGenerator()
   delete this->ExtraGenerator;
 }
 
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+Json::Value cmGlobalGenerator::GetJson() const
+{
+  Json::Value generator = Json::objectValue;
+  generator["name"] = this->GetName();
+  return generator;
+}
+#endif
+
 bool cmGlobalGenerator::SetGeneratorInstance(std::string const& i,
                                              cmMakefile* mf)
 {

+ 6 - 0
Source/cmGlobalGenerator.h

@@ -24,6 +24,7 @@
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #  include "cmFileLockPool.h"
+#  include "cm_jsoncpp_value.h"
 #endif
 
 #define CMAKE_DIRECTORY_ID_SEP "::@"
@@ -70,6 +71,11 @@ public:
     return codecvt::None;
   }
 
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  /** Get a JSON object describing the generator.  */
+  virtual Json::Value GetJson() const;
+#endif
+
   /** Tell the generator about the target system.  */
   virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; }
 

+ 9 - 0
Source/cmGlobalVisualStudio7Generator.cxx

@@ -254,6 +254,15 @@ cmLocalGenerator* cmGlobalVisualStudio7Generator::CreateLocalGenerator(
   return lg;
 }
 
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+Json::Value cmGlobalVisualStudio7Generator::GetJson() const
+{
+  Json::Value generator = this->cmGlobalVisualStudioGenerator::GetJson();
+  generator["platform"] = this->GetPlatformName();
+  return generator;
+}
+#endif
+
 std::string const& cmGlobalVisualStudio7Generator::GetPlatformName() const
 {
   if (!this->GeneratorPlatform.empty()) {

+ 4 - 0
Source/cmGlobalVisualStudio7Generator.h

@@ -28,6 +28,10 @@ public:
   ///! Create a local generator appropriate to this Global Generator
   cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
 
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  Json::Value GetJson() const override;
+#endif
+
   bool SetSystemName(std::string const& s, cmMakefile* mf) override;
 
   bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;

+ 6 - 0
Source/cmStateSnapshot.cxx

@@ -66,6 +66,12 @@ bool cmStateSnapshot::IsValid() const
     : false;
 }
 
+cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectory() const
+{
+  return cmStateSnapshot(this->State,
+                         this->Position->BuildSystemDirectory->DirectoryEnd);
+}
+
 cmStateSnapshot cmStateSnapshot::GetBuildsystemDirectoryParent() const
 {
   cmStateSnapshot snapshot;

+ 1 - 0
Source/cmStateSnapshot.h

@@ -37,6 +37,7 @@ public:
   std::vector<cmStateSnapshot> GetChildren();
 
   bool IsValid() const;
+  cmStateSnapshot GetBuildsystemDirectory() const;
   cmStateSnapshot GetBuildsystemDirectoryParent() const;
   cmStateSnapshot GetCallStackParent() const;
   cmStateSnapshot GetCallStackBottom() const;

+ 3 - 3
Source/cmTimestamp.h

@@ -23,12 +23,12 @@ public:
                                    const std::string& formatString,
                                    bool utcFlag);
 
-private:
-  time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const;
-
   std::string CreateTimestampFromTimeT(time_t timeT, std::string formatString,
                                        bool utcFlag) const;
 
+private:
+  time_t CreateUtcTimeTFromTm(struct tm& timeStruct) const;
+
   std::string AddTimestampComponent(char flag, struct tm& timeStruct,
                                     time_t timeT) const;
 };

+ 10 - 0
Source/cmake.cxx

@@ -30,6 +30,7 @@
 #if defined(CMAKE_BUILD_WITH_CMAKE)
 #  include "cm_jsoncpp_writer.h"
 
+#  include "cmFileAPI.h"
 #  include "cmGraphVizWriter.h"
 #  include "cmVariableWatch.h"
 #  include <unordered_map>
@@ -1443,6 +1444,11 @@ int cmake::ActualConfigure()
     this->TruncateOutputLog("CMakeError.log");
   }
 
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  this->FileAPI = cm::make_unique<cmFileAPI>(this);
+  this->FileAPI->ReadQueries();
+#endif
+
   // actually do the configure
   this->GlobalGenerator->Configure();
   // Before saving the cache
@@ -1682,6 +1688,10 @@ int cmake::Generate()
   // for the Visual Studio and Xcode generators.)
   this->SaveCache(this->GetHomeOutputDirectory());
 
+#if defined(CMAKE_BUILD_WITH_CMAKE)
+  this->FileAPI->WriteReplies();
+#endif
+
   return 0;
 }
 

+ 3 - 0
Source/cmake.h

@@ -6,6 +6,7 @@
 #include "cmConfigure.h" // IWYU pragma: keep
 
 #include <map>
+#include <memory> // IWYU pragma: keep
 #include <set>
 #include <string>
 #include <unordered_set>
@@ -21,6 +22,7 @@
 #endif
 
 class cmExternalMakefileProjectGeneratorFactory;
+class cmFileAPI;
 class cmFileTimeComparison;
 class cmGlobalGenerator;
 class cmGlobalGeneratorFactory;
@@ -528,6 +530,7 @@ private:
 
 #if defined(CMAKE_BUILD_WITH_CMAKE)
   cmVariableWatch* VariableWatch;
+  std::unique_ptr<cmFileAPI> FileAPI;
 #endif
 
   cmState* State;

+ 4 - 0
Tests/RunCMake/CMakeLists.txt

@@ -66,6 +66,9 @@ function(add_RunCMake_test_group test types)
   endforeach()
 endfunction()
 
+# Some tests use python for extra checks.
+find_package(PythonInterp QUIET)
+
 if(XCODE_VERSION AND "${XCODE_VERSION}" VERSION_LESS 6.1)
   set(Swift_ARGS -DXCODE_BELOW_6_1=1)
 endif()
@@ -155,6 +158,7 @@ add_RunCMake_test(DisallowedCommands)
 add_RunCMake_test(ExternalData)
 add_RunCMake_test(FeatureSummary)
 add_RunCMake_test(FPHSA)
+add_RunCMake_test(FileAPI -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE})
 add_RunCMake_test(FindBoost)
 add_RunCMake_test(FindLua)
 add_RunCMake_test(FindOpenGL)

+ 3 - 0
Tests/RunCMake/FileAPI/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.12)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)

+ 68 - 0
Tests/RunCMake/FileAPI/ClientStateful-check.cmake

@@ -0,0 +1,68 @@
+set(expect
+  query
+  query/client-client-member
+  query/client-client-member/query.json
+  query/client-empty-array
+  query/client-empty-array/query.json
+  query/client-empty-object
+  query/client-empty-object/query.json
+  query/client-json-bad-root
+  query/client-json-bad-root/query.json
+  query/client-json-empty
+  query/client-json-empty/query.json
+  query/client-json-extra
+  query/client-json-extra/query.json
+  query/client-not-file
+  query/client-not-file/query.json
+  query/client-request-array-negative-major-version
+  query/client-request-array-negative-major-version/query.json
+  query/client-request-array-negative-minor-version
+  query/client-request-array-negative-minor-version/query.json
+  query/client-request-array-negative-version
+  query/client-request-array-negative-version/query.json
+  query/client-request-array-no-major-version
+  query/client-request-array-no-major-version/query.json
+  query/client-request-array-no-supported-version
+  query/client-request-array-no-supported-version-among
+  query/client-request-array-no-supported-version-among/query.json
+  query/client-request-array-no-supported-version/query.json
+  query/client-request-array-version-1
+  query/client-request-array-version-1-1
+  query/client-request-array-version-1-1/query.json
+  query/client-request-array-version-1/query.json
+  query/client-request-array-version-2
+  query/client-request-array-version-2/query.json
+  query/client-request-negative-major-version
+  query/client-request-negative-major-version/query.json
+  query/client-request-negative-minor-version
+  query/client-request-negative-minor-version/query.json
+  query/client-request-negative-version
+  query/client-request-negative-version/query.json
+  query/client-request-no-major-version
+  query/client-request-no-major-version/query.json
+  query/client-request-no-version
+  query/client-request-no-version/query.json
+  query/client-request-version-1
+  query/client-request-version-1-1
+  query/client-request-version-1-1/query.json
+  query/client-request-version-1/query.json
+  query/client-request-version-2
+  query/client-request-version-2/query.json
+  query/client-requests-bad
+  query/client-requests-bad/query.json
+  query/client-requests-empty
+  query/client-requests-empty/query.json
+  query/client-requests-not-kinded
+  query/client-requests-not-kinded/query.json
+  query/client-requests-not-objects
+  query/client-requests-not-objects/query.json
+  query/client-requests-unknown
+  query/client-requests-unknown/query.json
+  reply
+  reply/__test-v1-[0-9a-f]+.json
+  reply/__test-v2-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(ClientStateful)

+ 258 - 0
Tests/RunCMake/FileAPI/ClientStateful-check.py

@@ -0,0 +1,258 @@
+from check_index import *
+
+def check_reply(q):
+    assert is_dict(q)
+    assert sorted(q.keys()) == [
+        "client-client-member",
+        "client-empty-array",
+        "client-empty-object",
+        "client-json-bad-root",
+        "client-json-empty",
+        "client-json-extra",
+        "client-not-file",
+        "client-request-array-negative-major-version",
+        "client-request-array-negative-minor-version",
+        "client-request-array-negative-version",
+        "client-request-array-no-major-version",
+        "client-request-array-no-supported-version",
+        "client-request-array-no-supported-version-among",
+        "client-request-array-version-1",
+        "client-request-array-version-1-1",
+        "client-request-array-version-2",
+        "client-request-negative-major-version",
+        "client-request-negative-minor-version",
+        "client-request-negative-version",
+        "client-request-no-major-version",
+        "client-request-no-version",
+        "client-request-version-1",
+        "client-request-version-1-1",
+        "client-request-version-2",
+        "client-requests-bad",
+        "client-requests-empty",
+        "client-requests-not-kinded",
+        "client-requests-not-objects",
+        "client-requests-unknown",
+    ]
+    expected = [
+        (check_query_client_member, "client-client-member"),
+        (check_query_empty_array, "client-empty-array"),
+        (check_query_empty_object, "client-empty-object"),
+        (check_query_json_bad_root, "client-json-bad-root"),
+        (check_query_json_empty, "client-json-empty"),
+        (check_query_json_extra, "client-json-extra"),
+        (check_query_not_file, "client-not-file"),
+        (check_query_requests_bad, "client-requests-bad"),
+        (check_query_requests_empty, "client-requests-empty"),
+        (check_query_requests_not_kinded, "client-requests-not-kinded"),
+        (check_query_requests_not_objects, "client-requests-not-objects"),
+        (check_query_requests_unknown, "client-requests-unknown"),
+    ]
+    for (f, k) in expected:
+        assert is_dict(q[k])
+        assert sorted(q[k].keys()) == ["query.json"]
+        f(q[k]["query.json"])
+    expected = [
+        (check_query_response_array_negative_major_version,     "client-request-array-negative-major-version"),
+        (check_query_response_array_negative_minor_version,     "client-request-array-negative-minor-version"),
+        (check_query_response_array_negative_version,           "client-request-array-negative-version"),
+        (check_query_response_array_no_major_version,           "client-request-array-no-major-version"),
+        (check_query_response_array_no_supported_version,       "client-request-array-no-supported-version"),
+        (check_query_response_array_no_supported_version_among, "client-request-array-no-supported-version-among"),
+        (check_query_response_array_version_1,                  "client-request-array-version-1"),
+        (check_query_response_array_version_1_1,                "client-request-array-version-1-1"),
+        (check_query_response_array_version_2,                  "client-request-array-version-2"),
+        (check_query_response_negative_major_version,           "client-request-negative-major-version"),
+        (check_query_response_negative_minor_version,           "client-request-negative-minor-version"),
+        (check_query_response_negative_version,                 "client-request-negative-version"),
+        (check_query_response_no_major_version,                 "client-request-no-major-version"),
+        (check_query_response_no_version,                       "client-request-no-version"),
+        (check_query_response_version_1,                        "client-request-version-1"),
+        (check_query_response_version_1_1,                      "client-request-version-1-1"),
+        (check_query_response_version_2,                        "client-request-version-2"),
+    ]
+    for (f, k) in expected:
+        assert is_dict(q[k])
+        assert sorted(q[k].keys()) == ["query.json"]
+        assert is_dict(q[k]["query.json"])
+        assert sorted(q[k]["query.json"].keys()) == ["requests", "responses"]
+        r = q[k]["query.json"]["requests"]
+        assert is_list(r)
+        assert len(r) == 1
+        assert is_dict(r[0])
+        assert r[0]["kind"] == "__test"
+        r = q[k]["query.json"]["responses"]
+        assert is_list(r)
+        assert len(r) == 1
+        assert is_dict(r[0])
+        f(r[0])
+
+def check_query_client_member(q):
+    assert is_dict(q)
+    assert sorted(q.keys()) == ["client", "responses"]
+    assert is_dict(q["client"])
+    assert sorted(q["client"].keys()) == []
+    check_error(q["responses"], "'requests' member missing")
+
+def check_query_empty_array(q):
+    check_error(q, "query root is not an object")
+
+def check_query_empty_object(q):
+    assert is_dict(q)
+    assert sorted(q.keys()) == ["responses"]
+    check_error(q["responses"], "'requests' member missing")
+
+def check_query_json_bad_root(q):
+    check_error_re(q, "A valid JSON document must be either an array or an object value")
+
+def check_query_json_empty(q):
+    check_error_re(q, "value, object or array expected")
+
+def check_query_json_extra(q):
+    check_error_re(q, "Extra non-whitespace after JSON value")
+
+def check_query_not_file(q):
+    check_error_re(q, "failed to read from file")
+
+def check_query_requests_bad(q):
+    assert is_dict(q)
+    assert sorted(q.keys()) == ["requests", "responses"]
+    r = q["requests"]
+    assert is_dict(r)
+    assert sorted(r.keys()) == []
+    check_error(q["responses"], "'requests' member is not an array")
+
+def check_query_requests_empty(q):
+    assert is_dict(q)
+    assert sorted(q.keys()) == ["requests", "responses"]
+    r = q["requests"]
+    assert is_list(r)
+    assert len(r) == 0
+    r = q["responses"]
+    assert is_list(r)
+    assert len(r) == 0
+
+def check_query_requests_not_kinded(q):
+    assert is_dict(q)
+    assert sorted(q.keys()) == ["requests", "responses"]
+    r = q["requests"]
+    assert is_list(r)
+    assert len(r) == 4
+    assert is_dict(r[0])
+    assert sorted(r[0].keys()) == []
+    assert is_dict(r[1])
+    assert sorted(r[1].keys()) == ["kind"]
+    assert is_dict(r[1]["kind"])
+    assert is_dict(r[2])
+    assert sorted(r[2].keys()) == ["kind"]
+    assert is_list(r[2]["kind"])
+    assert is_dict(r[3])
+    assert sorted(r[3].keys()) == ["kind"]
+    assert is_int(r[3]["kind"])
+    r = q["responses"]
+    assert is_list(r)
+    assert len(r) == 4
+    check_error(r[0], "'kind' member missing")
+    check_error(r[1], "'kind' member is not a string")
+    check_error(r[2], "'kind' member is not a string")
+    check_error(r[3], "'kind' member is not a string")
+
+def check_query_requests_not_objects(q):
+    assert is_dict(q)
+    assert sorted(q.keys()) == ["requests", "responses"]
+    r = q["requests"]
+    assert is_list(r)
+    assert len(r) == 3
+    assert is_int(r[0])
+    assert is_string(r[1])
+    assert is_list(r[2])
+    r = q["responses"]
+    assert is_list(r)
+    assert len(r) == 3
+    check_error(r[0], "request is not an object")
+    check_error(r[1], "request is not an object")
+    check_error(r[2], "request is not an object")
+
+def check_query_requests_unknown(q):
+    assert is_dict(q)
+    assert sorted(q.keys()) == ["requests", "responses"]
+    r = q["requests"]
+    assert is_list(r)
+    assert len(r) == 3
+    assert is_dict(r[0])
+    assert sorted(r[0].keys()) == ["kind"]
+    assert r[0]["kind"] == "unknownC"
+    assert is_dict(r[1])
+    assert sorted(r[1].keys()) == ["kind"]
+    assert r[1]["kind"] == "unknownB"
+    assert is_dict(r[2])
+    assert sorted(r[2].keys()) == ["kind"]
+    assert r[2]["kind"] == "unknownA"
+    r = q["responses"]
+    assert is_list(r)
+    assert len(r) == 3
+    check_error(r[0], "unknown request kind 'unknownC'")
+    check_error(r[1], "unknown request kind 'unknownB'")
+    check_error(r[2], "unknown request kind 'unknownA'")
+
+def check_query_response_array_negative_major_version(r):
+    check_error(r, "'version' object 'major' member is not a non-negative integer")
+
+def check_query_response_array_negative_minor_version(r):
+    check_error(r, "'version' object 'minor' member is not a non-negative integer")
+
+def check_query_response_array_negative_version(r):
+    check_error(r, "'version' array entry is not a non-negative integer or object")
+
+def check_query_response_array_no_major_version(r):
+    check_error(r, "'version' object 'major' member missing")
+
+def check_query_response_array_no_supported_version(r):
+    check_error(r, "no supported version specified")
+
+def check_query_response_array_no_supported_version_among(r):
+    check_error(r, "no supported version specified among: 4.0 3.0")
+
+def check_query_response_array_version_1(r):
+    check_index__test(r, 1, 3)
+
+def check_query_response_array_version_1_1(r):
+    check_index__test(r, 1, 3) # always uses latest minor version
+
+def check_query_response_array_version_2(r):
+    check_index__test(r, 2, 0)
+
+def check_query_response_negative_major_version(r):
+    check_error(r, "'version' object 'major' member is not a non-negative integer")
+
+def check_query_response_negative_minor_version(r):
+    check_error(r, "'version' object 'minor' member is not a non-negative integer")
+
+def check_query_response_negative_version(r):
+    check_error(r, "'version' member is not a non-negative integer, object, or array")
+
+def check_query_response_no_major_version(r):
+    check_error(r, "'version' object 'major' member missing")
+
+def check_query_response_no_version(r):
+    check_error(r, "'version' member missing")
+
+def check_query_response_version_1(r):
+    check_index__test(r, 1, 3)
+
+def check_query_response_version_1_1(r):
+    check_index__test(r, 1, 3) # always uses latest minor version
+
+def check_query_response_version_2(r):
+    check_index__test(r, 2, 0)
+
+def check_objects(o):
+    assert is_list(o)
+    assert len(o) == 2
+    check_index__test(o[0], 1, 3)
+    check_index__test(o[1], 2, 0)
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_cmake(index["cmake"])
+check_reply(index["reply"])
+check_objects(index["objects"])

+ 73 - 0
Tests/RunCMake/FileAPI/ClientStateful-prep.cmake

@@ -0,0 +1,73 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-client-member/query.json" [[{ "client": {} }]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-empty-array/query.json" "[]")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-empty-object/query.json" "{}")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-json-bad-root/query.json" [["invalid root"]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-json-empty/query.json" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-json-extra/query.json" "{}x")
+file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-not-file/query.json")
+
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-requests-bad/query.json" [[{ "requests": {} }]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-requests-empty/query.json" [[{ "requests": [] }]])
+
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-requests-not-objects/query.json" [[
+{ "requests": [ 0, "", [] ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-requests-not-kinded/query.json" [[
+{ "requests": [ {}, { "kind": {} }, { "kind": [] }, { "kind": 0 } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-requests-unknown/query.json" [[
+{ "requests": [ { "kind": "unknownC" }, { "kind": "unknownB" }, { "kind": "unknownA" } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-no-version/query.json" [[
+{ "requests": [ { "kind": "__test" } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-negative-version/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : -1 } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-no-major-version/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : {} } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-negative-major-version/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : { "major": -1 } } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-negative-minor-version/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : { "major": 0, "minor": -1 } } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-array-negative-version/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : [ 1, -1 ] } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-array-no-major-version/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : [ 1, {} ] } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-array-negative-major-version/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : [ 1, { "major": -1 } ] } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-array-negative-minor-version/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : [ 1, { "major": 0, "minor": -1 } ] } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-array-no-supported-version/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : [] } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-array-no-supported-version-among/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : [4, 3] } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-version-1/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : 1 } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-version-1-1/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : { "major": 1, "minor": 1 } } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-version-2/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : { "major": 2 } } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-array-version-1/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : [3, 1] } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-array-version-1-1/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : [3, { "major": 1, "minor": 1 }, 2 ] } ] }
+]])
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-request-array-version-2/query.json" [[
+{ "requests": [ { "kind": "__test", "version" : [3, { "major": 2 } ]  } ] }
+]])
+
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/reply/object-to-be-deleted.json" "")

+ 0 - 0
Tests/RunCMake/FileAPI/ClientStateful.cmake


+ 15 - 0
Tests/RunCMake/FileAPI/ClientStateless-check.cmake

@@ -0,0 +1,15 @@
+set(expect
+  query
+  query/client-foo
+  query/client-foo/__test-v1
+  query/client-foo/__test-v2
+  query/client-foo/__test-v3
+  query/client-foo/unknown
+  reply
+  reply/__test-v1-[0-9a-f]+.json
+  reply/__test-v2-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(ClientStateless)

+ 26 - 0
Tests/RunCMake/FileAPI/ClientStateless-check.py

@@ -0,0 +1,26 @@
+from check_index import *
+
+def check_reply(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == ["client-foo"]
+    check_reply_client_foo(r["client-foo"])
+
+def check_reply_client_foo(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == ["__test-v1", "__test-v2", "__test-v3", "unknown"]
+    check_index__test(r["__test-v1"], 1, 3)
+    check_index__test(r["__test-v2"], 2, 0)
+    check_error(r["__test-v3"], "unknown query file")
+    check_error(r["unknown"], "unknown query file")
+
+def check_objects(o):
+    assert is_list(o)
+    assert len(o) == 2
+    check_index__test(o[0], 1, 3)
+    check_index__test(o[1], 2, 0)
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_cmake(index["cmake"])
+check_reply(index["reply"])
+check_objects(index["objects"])

+ 5 - 0
Tests/RunCMake/FileAPI/ClientStateless-prep.cmake

@@ -0,0 +1,5 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/__test-v1" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/__test-v2" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/__test-v3" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/unknown" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/reply/object-to-be-deleted.json" "")

+ 0 - 0
Tests/RunCMake/FileAPI/ClientStateless.cmake


+ 20 - 0
Tests/RunCMake/FileAPI/DuplicateStateless-check.cmake

@@ -0,0 +1,20 @@
+set(expect
+  query
+  query/__test-v1
+  query/__test-v2
+  query/__test-v3
+  query/client-foo
+  query/client-foo/__test-v1
+  query/client-foo/__test-v2
+  query/client-foo/__test-v3
+  query/client-foo/unknown
+  query/query.json
+  query/unknown
+  reply
+  reply/__test-v1-[0-9a-f]+.json
+  reply/__test-v2-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(DuplicateStateless)

+ 31 - 0
Tests/RunCMake/FileAPI/DuplicateStateless-check.py

@@ -0,0 +1,31 @@
+from check_index import *
+
+def check_reply(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == ["__test-v1", "__test-v2", "__test-v3", "client-foo", "query.json", "unknown"]
+    check_index__test(r["__test-v1"], 1, 3)
+    check_index__test(r["__test-v2"], 2, 0)
+    check_error(r["__test-v3"], "unknown query file")
+    check_reply_client_foo(r["client-foo"])
+    check_error(r["query.json"], "unknown query file")
+    check_error(r["unknown"], "unknown query file")
+
+def check_reply_client_foo(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == ["__test-v1", "__test-v2", "__test-v3", "unknown"]
+    check_index__test(r["__test-v1"], 1, 3)
+    check_index__test(r["__test-v2"], 2, 0)
+    check_error(r["__test-v3"], "unknown query file")
+    check_error(r["unknown"], "unknown query file")
+
+def check_objects(o):
+    assert is_list(o)
+    assert len(o) == 2
+    check_index__test(o[0], 1, 3)
+    check_index__test(o[1], 2, 0)
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_cmake(index["cmake"])
+check_reply(index["reply"])
+check_objects(index["objects"])

+ 10 - 0
Tests/RunCMake/FileAPI/DuplicateStateless-prep.cmake

@@ -0,0 +1,10 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/__test-v1" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/__test-v2" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/__test-v3" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/query.json" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/unknown" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/__test-v1" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/__test-v2" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/__test-v3" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/unknown" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/reply/object-to-be-deleted.json" "")

+ 0 - 0
Tests/RunCMake/FileAPI/DuplicateStateless.cmake


+ 8 - 0
Tests/RunCMake/FileAPI/Empty-check.cmake

@@ -0,0 +1,8 @@
+set(expect
+  query
+  reply
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(Empty)

+ 15 - 0
Tests/RunCMake/FileAPI/Empty-check.py

@@ -0,0 +1,15 @@
+from check_index import *
+
+def check_reply(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == []
+
+def check_objects(o):
+    assert is_list(o)
+    assert len(o) == 0
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_cmake(index["cmake"])
+check_reply(index["reply"])
+check_objects(index["objects"])

+ 1 - 0
Tests/RunCMake/FileAPI/Empty-prep.cmake

@@ -0,0 +1 @@
+file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query")

+ 0 - 0
Tests/RunCMake/FileAPI/Empty.cmake


+ 9 - 0
Tests/RunCMake/FileAPI/EmptyClient-check.cmake

@@ -0,0 +1,9 @@
+set(expect
+  query
+  query/client-foo
+  reply
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(EmptyClient)

+ 20 - 0
Tests/RunCMake/FileAPI/EmptyClient-check.py

@@ -0,0 +1,20 @@
+from check_index import *
+
+def check_reply(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == ["client-foo"]
+    check_reply_client_foo(r["client-foo"])
+
+def check_reply_client_foo(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == []
+
+def check_objects(o):
+    assert is_list(o)
+    assert len(o) == 0
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_cmake(index["cmake"])
+check_reply(index["reply"])
+check_objects(index["objects"])

+ 2 - 0
Tests/RunCMake/FileAPI/EmptyClient-prep.cmake

@@ -0,0 +1,2 @@
+file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/reply/object-to-be-deleted.json" "")

+ 0 - 0
Tests/RunCMake/FileAPI/EmptyClient.cmake


+ 16 - 0
Tests/RunCMake/FileAPI/MixedStateless-check.cmake

@@ -0,0 +1,16 @@
+set(expect
+  query
+  query/__test-v1
+  query/__test-v3
+  query/client-foo
+  query/client-foo/__test-v2
+  query/client-foo/unknown
+  query/query.json
+  reply
+  reply/__test-v1-[0-9a-f]+.json
+  reply/__test-v2-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(MixedStateless)

+ 27 - 0
Tests/RunCMake/FileAPI/MixedStateless-check.py

@@ -0,0 +1,27 @@
+from check_index import *
+
+def check_reply(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == ["__test-v1", "__test-v3", "client-foo", "query.json"]
+    check_index__test(r["__test-v1"], 1, 3)
+    check_error(r["__test-v3"], "unknown query file")
+    check_reply_client_foo(r["client-foo"])
+    check_error(r["query.json"], "unknown query file")
+
+def check_reply_client_foo(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == ["__test-v2", "unknown"]
+    check_index__test(r["__test-v2"], 2, 0)
+    check_error(r["unknown"], "unknown query file")
+
+def check_objects(o):
+    assert is_list(o)
+    assert len(o) == 2
+    check_index__test(o[0], 1, 3)
+    check_index__test(o[1], 2, 0)
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_cmake(index["cmake"])
+check_reply(index["reply"])
+check_objects(index["objects"])

+ 6 - 0
Tests/RunCMake/FileAPI/MixedStateless-prep.cmake

@@ -0,0 +1,6 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/__test-v1" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/__test-v2" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/__test-v3" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/query.json" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/unknown" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/reply/object-to-be-deleted.json" "")

+ 0 - 0
Tests/RunCMake/FileAPI/MixedStateless.cmake


+ 1 - 0
Tests/RunCMake/FileAPI/Nothing-check.cmake

@@ -0,0 +1 @@
+check_api("^$")

+ 1 - 0
Tests/RunCMake/FileAPI/Nothing-prep.cmake

@@ -0,0 +1 @@
+file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1")

+ 0 - 0
Tests/RunCMake/FileAPI/Nothing.cmake


+ 58 - 0
Tests/RunCMake/FileAPI/RunCMakeTest.cmake

@@ -0,0 +1,58 @@
+include(RunCMake)
+
+# Function called in *-check.cmake scripts to check api files.
+function(check_api expect)
+  file(GLOB_RECURSE actual
+    LIST_DIRECTORIES TRUE
+    RELATIVE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1
+    ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/*
+    )
+  if(NOT "${actual}" MATCHES "${expect}")
+    set(RunCMake_TEST_FAILED "API files:
+  ${actual}
+do not match what we expected:
+  ${expect}
+in directory:
+  ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1" PARENT_SCOPE)
+  endif()
+endfunction()
+
+function(check_python case)
+  if(RunCMake_TEST_FAILED OR NOT PYTHON_EXECUTABLE)
+    return()
+  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}"
+    RESULT_VARIABLE result
+    OUTPUT_VARIABLE output
+    ERROR_VARIABLE output
+    )
+  if(NOT result EQUAL 0)
+    string(REPLACE "\n" "\n  " output "  ${output}")
+    set(RunCMake_TEST_FAILED "Unexpected index:\n${output}" PARENT_SCOPE)
+  endif()
+endfunction()
+
+run_cmake(Nothing)
+run_cmake(Empty)
+run_cmake(EmptyClient)
+run_cmake(Stale)
+run_cmake(SharedStateless)
+run_cmake(ClientStateless)
+run_cmake(MixedStateless)
+run_cmake(DuplicateStateless)
+run_cmake(ClientStateful)
+
+function(run_object object)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${object}-build)
+  run_cmake(${object})
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(${object}-SharedStateless ${CMAKE_COMMAND} .)
+  run_cmake_command(${object}-ClientStateless ${CMAKE_COMMAND} .)
+  run_cmake_command(${object}-ClientStateful ${CMAKE_COMMAND} .)
+endfunction()
+
+run_object(codemodel-v2)
+run_object(cache-v2)
+run_object(cmakeFiles-v1)

+ 15 - 0
Tests/RunCMake/FileAPI/SharedStateless-check.cmake

@@ -0,0 +1,15 @@
+set(expect
+  query
+  query/__test-v1
+  query/__test-v2
+  query/__test-v3
+  query/query.json
+  query/unknown
+  reply
+  reply/__test-v1-[0-9a-f]+.json
+  reply/__test-v2-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(SharedStateless)

+ 22 - 0
Tests/RunCMake/FileAPI/SharedStateless-check.py

@@ -0,0 +1,22 @@
+from check_index import *
+
+def check_reply(r):
+    assert is_dict(r)
+    assert sorted(r.keys()) == ["__test-v1", "__test-v2", "__test-v3", "query.json", "unknown"]
+    check_index__test(r["__test-v1"], 1, 3)
+    check_index__test(r["__test-v2"], 2, 0)
+    check_error(r["__test-v3"], "unknown query file")
+    check_error(r["query.json"], "unknown query file")
+    check_error(r["unknown"], "unknown query file")
+
+def check_objects(o):
+    assert is_list(o)
+    assert len(o) == 2
+    check_index__test(o[0], 1, 3)
+    check_index__test(o[1], 2, 0)
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_cmake(index["cmake"])
+check_reply(index["reply"])
+check_objects(index["objects"])

+ 6 - 0
Tests/RunCMake/FileAPI/SharedStateless-prep.cmake

@@ -0,0 +1,6 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/__test-v1" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/__test-v2" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/__test-v3" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/query.json" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/unknown" "")
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/reply/object-to-be-deleted.json" "")

+ 0 - 0
Tests/RunCMake/FileAPI/SharedStateless.cmake


+ 4 - 0
Tests/RunCMake/FileAPI/Stale-check.cmake

@@ -0,0 +1,4 @@
+set(expect
+  reply
+  )
+check_api("^${expect}$")

+ 1 - 0
Tests/RunCMake/FileAPI/Stale-prep.cmake

@@ -0,0 +1 @@
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/reply/object-to-be-deleted.json" "")

+ 0 - 0
Tests/RunCMake/FileAPI/Stale.cmake


+ 10 - 0
Tests/RunCMake/FileAPI/alias/CMakeLists.txt

@@ -0,0 +1,10 @@
+project(Alias)
+enable_language(CXX)
+
+add_library(c_alias_lib ALIAS c_lib)
+add_executable(c_alias_exe ../empty.c)
+target_link_libraries(c_alias_exe PRIVATE c_alias_lib)
+
+add_library(cxx_alias_lib ALIAS cxx_lib)
+add_executable(cxx_alias_exe ../empty.cxx)
+target_link_libraries(cxx_alias_exe PRIVATE cxx_alias_lib)

+ 11 - 0
Tests/RunCMake/FileAPI/cache-v2-ClientStateful-check.cmake

@@ -0,0 +1,11 @@
+set(expect
+  query
+  query/client-foo
+  query/client-foo/query.json
+  reply
+  reply/cache-v2-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(cache-v2)

+ 4 - 0
Tests/RunCMake/FileAPI/cache-v2-ClientStateful-prep.cmake

@@ -0,0 +1,4 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/query.json" [[
+{ "requests": [ { "kind": "cache", "version" : 2 } ] }
+]])

+ 11 - 0
Tests/RunCMake/FileAPI/cache-v2-ClientStateless-check.cmake

@@ -0,0 +1,11 @@
+set(expect
+  query
+  query/client-foo
+  query/client-foo/cache-v2
+  reply
+  reply/cache-v2-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(cache-v2)

+ 2 - 0
Tests/RunCMake/FileAPI/cache-v2-ClientStateless-prep.cmake

@@ -0,0 +1,2 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/cache-v2" "")

+ 10 - 0
Tests/RunCMake/FileAPI/cache-v2-SharedStateless-check.cmake

@@ -0,0 +1,10 @@
+set(expect
+  query
+  query/cache-v2
+  reply
+  reply/cache-v2-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(cache-v2)

+ 2 - 0
Tests/RunCMake/FileAPI/cache-v2-SharedStateless-prep.cmake

@@ -0,0 +1,2 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/cache-v2" "")

+ 134 - 0
Tests/RunCMake/FileAPI/cache-v2-check.py

@@ -0,0 +1,134 @@
+from check_index import *
+
+def check_objects(o):
+    assert is_list(o)
+    assert len(o) == 1
+    check_index_object(o[0], "cache", 2, 0, check_object_cache)
+
+def check_cache_entry(actual, expected):
+    assert is_dict(actual)
+    assert sorted(actual.keys()) == ["name", "properties", "type", "value"]
+
+    assert is_string(actual["type"], expected["type"])
+    assert is_string(actual["value"], expected["value"])
+
+    def check_property(actual, expected):
+        assert is_dict(actual)
+        assert sorted(actual.keys()) == ["name", "value"]
+        assert is_string(actual["value"], expected["value"])
+
+    check_list_match(lambda a, e: is_string(a["name"], e["name"]), actual["properties"], expected["properties"], check=check_property)
+
+def check_object_cache(o):
+    assert sorted(o.keys()) == ["entries", "kind", "version"]
+    # The "kind" and "version" members are handled by check_index_object.
+    check_list_match(lambda a, e: is_string(a["name"], e["name"]), o["entries"], [
+        {
+            "name": "CM_OPTION_BOOL",
+            "type": "BOOL",
+            "value": "OFF",
+            "properties": [
+                {
+                    "name": "HELPSTRING",
+                    "value": "Testing option()",
+                },
+            ],
+        },
+        {
+            "name": "CM_SET_BOOL",
+            "type": "BOOL",
+            "value": "ON",
+            "properties": [
+                {
+                    "name": "HELPSTRING",
+                    "value": "Testing set(CACHE BOOL)",
+                },
+                {
+                    "name": "ADVANCED",
+                    "value": "1",
+                },
+            ],
+        },
+        {
+            "name": "CM_SET_FILEPATH",
+            "type": "FILEPATH",
+            "value": "dir1/dir2/empty.txt",
+            "properties": [
+                {
+                    "name": "HELPSTRING",
+                    "value": "Testing set(CACHE FILEPATH)",
+                },
+            ],
+        },
+        {
+            "name": "CM_SET_PATH",
+            "type": "PATH",
+            "value": "dir1/dir2",
+            "properties": [
+                {
+                    "name": "HELPSTRING",
+                    "value": "Testing set(CACHE PATH)",
+                },
+                {
+                    "name": "ADVANCED",
+                    "value": "ON",
+                },
+            ],
+        },
+        {
+            "name": "CM_SET_STRING",
+            "type": "STRING",
+            "value": "test",
+            "properties": [
+                {
+                    "name": "HELPSTRING",
+                    "value": "Testing set(CACHE STRING)",
+                },
+            ],
+        },
+        {
+            "name": "CM_SET_STRINGS",
+            "type": "STRING",
+            "value": "1",
+            "properties": [
+                {
+                    "name": "HELPSTRING",
+                    "value": "Testing set(CACHE STRING) with STRINGS",
+                },
+                {
+                    "name": "STRINGS",
+                    "value": "1;2;3;4",
+                },
+            ],
+        },
+        {
+            "name": "CM_SET_INTERNAL",
+            "type": "INTERNAL",
+            "value": "int2",
+            "properties": [
+                {
+                    "name": "HELPSTRING",
+                    "value": "Testing set(CACHE INTERNAL)",
+                },
+            ],
+        },
+        {
+            "name": "CM_SET_TYPE",
+            "type": "STRING",
+            "value": "1",
+            "properties": [
+                {
+                    "name": "HELPSTRING",
+                    "value": "Testing set(CACHE INTERNAL) with set_property(TYPE)",
+                },
+                {
+                    "name": "ADVANCED",
+                    "value": "0",
+                },
+            ],
+        },
+    ], check=check_cache_entry, allow_extra=True)
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_objects(index["objects"])

+ 14 - 0
Tests/RunCMake/FileAPI/cache-v2.cmake

@@ -0,0 +1,14 @@
+option(CM_OPTION_BOOL "Testing option()" "OFF")
+set(CM_SET_BOOL "ON" CACHE BOOL "Testing set(CACHE BOOL)")
+mark_as_advanced(CM_SET_BOOL)
+set(CM_SET_FILEPATH "dir1/dir2/empty.txt" CACHE FILEPATH "Testing set(CACHE FILEPATH)")
+set(CM_SET_PATH "dir1/dir2" CACHE PATH "Testing set(CACHE PATH)")
+set_property(CACHE CM_SET_PATH PROPERTY ADVANCED ON)
+set(CM_SET_STRING "test" CACHE STRING "Testing set(CACHE STRING)")
+set(CM_SET_STRINGS "1" CACHE STRING "Testing set(CACHE STRING) with STRINGS")
+set_property(CACHE CM_SET_STRINGS PROPERTY STRINGS "1;2;3;4")
+set(CM_SET_INTERNAL "int" CACHE INTERNAL "Testing set(CACHE INTERNAL)")
+set_property(CACHE CM_SET_INTERNAL PROPERTY VALUE "int2")
+set(CM_SET_TYPE "1" CACHE INTERNAL "Testing set(CACHE INTERNAL) with set_property(TYPE)")
+set_property(CACHE CM_SET_TYPE PROPERTY TYPE "STRING")
+set_property(CACHE CM_SET_TYPE PROPERTY ADVANCED "0")

+ 163 - 0
Tests/RunCMake/FileAPI/check_index.py

@@ -0,0 +1,163 @@
+import sys
+import os
+import json
+import re
+
+if sys.version_info[0] >= 3:
+    unicode = str
+
+def is_bool(x, val=None):
+    return isinstance(x, bool) and (val is None or x == val)
+
+def is_dict(x):
+    return isinstance(x, dict)
+
+def is_list(x):
+    return isinstance(x, list)
+
+def is_int(x, val=None):
+    return (isinstance(x, int) or isinstance(x, long)) and (val is None or x == val)
+
+def is_string(x, val=None):
+    return (isinstance(x, str) or isinstance(x, unicode)) and (val is None or x == val)
+
+def matches(s, pattern):
+    return is_string(s) and bool(re.search(pattern, s))
+
+def check_list_match(match, actual, expected, check=None, check_exception=None, missing_exception=None, extra_exception=None, allow_extra=False):
+    """
+    Handle the common pattern of making sure every actual item "matches" some
+    item in the expected list, and that neither list has extra items after
+    matching is completed.
+
+    @param match: Callback to check if an actual item matches an expected
+    item. Return True if the item matches, return False if the item doesn't
+    match.
+    @param actual: List of actual items to search.
+    @param expected: List of expected items to match.
+    @param check: Optional function to check that the actual item is valid by
+    comparing it to the expected item.
+    @param check_exception: Optional function that returns an argument to
+    append to any exception thrown by the check function.
+    @param missing_exception: Optional function that returns an argument to
+    append to the exception thrown when an item is not found.
+    @param extra_exception: Optional function that returns an argument to
+    append to the exception thrown when an extra item is found.
+    @param allow_extra: Optional parameter allowing there to be extra actual
+    items after all the expected items have been found.
+    """
+    assert is_list(actual)
+    _actual = actual[:]
+    for expected_item in expected:
+        found = False
+        for i, actual_item in enumerate(_actual):
+            if match(actual_item, expected_item):
+                if check:
+                    try:
+                        check(actual_item, expected_item)
+                    except BaseException as e:
+                        if check_exception:
+                            e.args += (check_exception(actual_item, expected_item),)
+                        raise
+                found = True
+                del _actual[i]
+                break
+        if missing_exception:
+            assert found, missing_exception(expected_item)
+        else:
+            assert found
+    if not allow_extra:
+        if extra_exception:
+            assert len(_actual) == 0, [extra_exception(a) for a in _actual]
+        else:
+            assert len(_actual) == 0
+
+def filter_list(f, l):
+    if l is not None:
+        l = list(filter(f, l))
+    if l == []:
+        l = None
+    return l
+
+def check_cmake(cmake):
+    assert is_dict(cmake)
+    assert sorted(cmake.keys()) == ["generator", "paths", "version"]
+    check_cmake_version(cmake["version"])
+    check_cmake_paths(cmake["paths"])
+    check_cmake_generator(cmake["generator"])
+
+def check_cmake_version(v):
+    assert is_dict(v)
+    assert sorted(v.keys()) == ["isDirty", "major", "minor", "patch", "string", "suffix"]
+    assert is_string(v["string"])
+    assert is_int(v["major"])
+    assert is_int(v["minor"])
+    assert is_int(v["patch"])
+    assert is_string(v["suffix"])
+    assert is_bool(v["isDirty"])
+
+def check_cmake_paths(v):
+    assert is_dict(v)
+    assert sorted(v.keys()) == ["cmake", "cpack", "ctest", "root"]
+    assert is_string(v["cmake"])
+    assert is_string(v["cpack"])
+    assert is_string(v["ctest"])
+    assert is_string(v["root"])
+
+def check_cmake_generator(g):
+    assert is_dict(g)
+    name = g.get("name", None)
+    assert is_string(name)
+    if name.startswith("Visual Studio"):
+        assert sorted(g.keys()) == ["name", "platform"]
+        assert is_string(g["platform"])
+    else:
+        assert sorted(g.keys()) == ["name"]
+
+def check_index_object(indexEntry, kind, major, minor, check):
+    assert is_dict(indexEntry)
+    assert sorted(indexEntry.keys()) == ["jsonFile", "kind", "version"]
+    assert is_string(indexEntry["kind"])
+    assert indexEntry["kind"] == kind
+    assert is_dict(indexEntry["version"])
+    assert sorted(indexEntry["version"].keys()) == ["major", "minor"]
+    assert indexEntry["version"]["major"] == major
+    assert indexEntry["version"]["minor"] == minor
+    assert is_string(indexEntry["jsonFile"])
+    filepath = os.path.join(reply_dir, indexEntry["jsonFile"])
+    with open(filepath) as f:
+        object = json.load(f)
+    assert is_dict(object)
+    assert "kind" in object
+    assert is_string(object["kind"])
+    assert object["kind"] == kind
+    assert "version" in object
+    assert is_dict(object["version"])
+    assert sorted(object["version"].keys()) == ["major", "minor"]
+    assert object["version"]["major"] == major
+    assert object["version"]["minor"] == minor
+    if check:
+        check(object)
+
+def check_index__test(indexEntry, major, minor):
+    def check(object):
+        assert sorted(object.keys()) == ["kind", "version"]
+    check_index_object(indexEntry, "__test", major, minor, check)
+
+def check_error(value, error):
+    assert is_dict(value)
+    assert sorted(value.keys()) == ["error"]
+    assert is_string(value["error"])
+    assert value["error"] == error
+
+def check_error_re(value, error):
+    assert is_dict(value)
+    assert sorted(value.keys()) == ["error"]
+    assert is_string(value["error"])
+    assert re.search(error, value["error"])
+
+reply_index = sys.argv[1]
+reply_dir = os.path.dirname(reply_index)
+
+with open(reply_index) as f:
+    index = json.load(f)

+ 11 - 0
Tests/RunCMake/FileAPI/cmakeFiles-v1-ClientStateful-check.cmake

@@ -0,0 +1,11 @@
+set(expect
+  query
+  query/client-foo
+  query/client-foo/query.json
+  reply
+  reply/cmakeFiles-v1-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(cmakeFiles-v1)

+ 4 - 0
Tests/RunCMake/FileAPI/cmakeFiles-v1-ClientStateful-prep.cmake

@@ -0,0 +1,4 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/query.json" [[
+{ "requests": [ { "kind": "cmakeFiles", "version" : 1 } ] }
+]])

+ 11 - 0
Tests/RunCMake/FileAPI/cmakeFiles-v1-ClientStateless-check.cmake

@@ -0,0 +1,11 @@
+set(expect
+  query
+  query/client-foo
+  query/client-foo/cmakeFiles-v1
+  reply
+  reply/cmakeFiles-v1-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(cmakeFiles-v1)

+ 2 - 0
Tests/RunCMake/FileAPI/cmakeFiles-v1-ClientStateless-prep.cmake

@@ -0,0 +1,2 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/cmakeFiles-v1" "")

+ 10 - 0
Tests/RunCMake/FileAPI/cmakeFiles-v1-SharedStateless-check.cmake

@@ -0,0 +1,10 @@
+set(expect
+  query
+  query/cmakeFiles-v1
+  reply
+  reply/cmakeFiles-v1-[0-9a-f]+.json
+  reply/index-[0-9.T-]+.json
+  )
+check_api("^${expect}$")
+
+check_python(cmakeFiles-v1)

+ 2 - 0
Tests/RunCMake/FileAPI/cmakeFiles-v1-SharedStateless-prep.cmake

@@ -0,0 +1,2 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/cmakeFiles-v1" "")

+ 94 - 0
Tests/RunCMake/FileAPI/cmakeFiles-v1-check.py

@@ -0,0 +1,94 @@
+from check_index import *
+
+def check_objects(o):
+    assert is_list(o)
+    assert len(o) == 1
+    check_index_object(o[0], "cmakeFiles", 1, 0, check_object_cmakeFiles)
+
+def check_input(actual, expected):
+    assert is_dict(actual)
+    expected_keys = ["path"]
+
+    if expected["isGenerated"] is not None:
+        expected_keys.append("isGenerated")
+        assert is_bool(actual["isGenerated"], expected["isGenerated"])
+
+    if expected["isExternal"] is not None:
+        expected_keys.append("isExternal")
+        assert is_bool(actual["isExternal"], expected["isExternal"])
+
+    if expected["isCMake"] is not None:
+        expected_keys.append("isCMake")
+        assert is_bool(actual["isCMake"], expected["isCMake"])
+
+    assert sorted(actual.keys()) == sorted(expected_keys)
+
+def check_object_cmakeFiles(o):
+    assert sorted(o.keys()) == ["inputs", "kind", "paths", "version"]
+    # The "kind" and "version" members are handled by check_index_object.
+    assert is_dict(o["paths"])
+    assert sorted(o["paths"].keys()) == ["build", "source"]
+    assert matches(o["paths"]["build"], "^.*/Tests/RunCMake/FileAPI/cmakeFiles-v1-build$")
+    assert matches(o["paths"]["source"], "^.*/Tests/RunCMake/FileAPI$")
+
+    expected = [
+        {
+            "path": "^CMakeLists\\.txt$",
+            "isGenerated": None,
+            "isExternal": None,
+            "isCMake": None,
+        },
+        {
+            "path": "^cmakeFiles-v1\\.cmake$",
+            "isGenerated": None,
+            "isExternal": None,
+            "isCMake": None,
+        },
+        {
+            "path": "^dir/CMakeLists\\.txt$",
+            "isGenerated": None,
+            "isExternal": None,
+            "isCMake": None,
+        },
+        {
+            "path": "^dir/dir/CMakeLists\\.txt$",
+            "isGenerated": None,
+            "isExternal": None,
+            "isCMake": None,
+        },
+        {
+            "path": "^dir/dirtest\\.cmake$",
+            "isGenerated": None,
+            "isExternal": None,
+            "isCMake": None,
+        },
+        {
+            "path": "^.*/Tests/RunCMake/FileAPIDummyFile\\.cmake$",
+            "isGenerated": None,
+            "isExternal": True,
+            "isCMake": None,
+        },
+        {
+            "path": "^.*/Tests/RunCMake/FileAPI/cmakeFiles-v1-build/generated\\.cmake",
+            "isGenerated": True,
+            "isExternal": None,
+            "isCMake": None,
+        },
+        {
+            "path": "^.*/Modules/CMakeParseArguments\\.cmake$",
+            "isGenerated": None,
+            "isExternal": True,
+            "isCMake": True,
+        },
+    ]
+
+    inSource = os.path.dirname(o["paths"]["build"]) == o["paths"]["source"]
+    if inSource:
+        for e in expected:
+            e["path"] = e["path"].replace("^.*/Tests/RunCMake/FileAPI/", "^", 1)
+
+    check_list_match(lambda a, e: matches(a["path"], e["path"]), o["inputs"], expected, check=check_input, allow_extra=True)
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_objects(index["objects"])

+ 8 - 0
Tests/RunCMake/FileAPI/cmakeFiles-v1.cmake

@@ -0,0 +1,8 @@
+include("${CMAKE_CURRENT_LIST_DIR}/dir/dirtest.cmake")
+include(CMakeParseArguments)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/generated.cmake" "")
+include("${CMAKE_CURRENT_BINARY_DIR}/generated.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/../FileAPIDummyFile.cmake")
+
+add_subdirectory(dir)

+ 12 - 0
Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-check.cmake

@@ -0,0 +1,12 @@
+set(expect
+  query
+  query/client-foo
+  query/client-foo/query.json
+  reply
+  reply/codemodel-v2-[0-9a-f]+\\.json
+  reply/index-[0-9.T-]+\\.json
+  .*
+  )
+check_api("^${expect}$")
+
+check_python(codemodel-v2)

+ 4 - 0
Tests/RunCMake/FileAPI/codemodel-v2-ClientStateful-prep.cmake

@@ -0,0 +1,4 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/query.json" [[
+{ "requests": [ { "kind": "codemodel", "version" : 2 } ] }
+]])

+ 12 - 0
Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-check.cmake

@@ -0,0 +1,12 @@
+set(expect
+  query
+  query/client-foo
+  query/client-foo/codemodel-v2
+  reply
+  reply/codemodel-v2-[0-9a-f]+\\.json
+  reply/index-[0-9.T-]+\\.json
+  .*
+  )
+check_api("^${expect}$")
+
+check_python(codemodel-v2)

+ 2 - 0
Tests/RunCMake/FileAPI/codemodel-v2-ClientStateless-prep.cmake

@@ -0,0 +1,2 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/client-foo/codemodel-v2" "")

+ 11 - 0
Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-check.cmake

@@ -0,0 +1,11 @@
+set(expect
+  query
+  query/codemodel-v2
+  reply
+  reply/codemodel-v2-[0-9a-f]+\\.json
+  reply/index-[0-9.T-]+\\.json
+  .*
+  )
+check_api("^${expect}$")
+
+check_python(codemodel-v2)

+ 2 - 0
Tests/RunCMake/FileAPI/codemodel-v2-SharedStateless-prep.cmake

@@ -0,0 +1,2 @@
+file(REMOVE_RECURSE ${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query)
+file(WRITE "${RunCMake_TEST_BINARY_DIR}/.cmake/api/v1/query/codemodel-v2" "")

+ 5085 - 0
Tests/RunCMake/FileAPI/codemodel-v2-check.py

@@ -0,0 +1,5085 @@
+from check_index import *
+
+import sys
+import os
+
+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))
+
+def check_backtrace(t, b, backtrace):
+    btg = t["backtraceGraph"]
+    for expected in backtrace:
+        assert is_int(b)
+        node = btg["nodes"][b]
+        expected_keys = ["file"]
+        assert matches(btg["files"][node["file"]], expected["file"])
+
+        if expected["line"] is not None:
+            expected_keys.append("line")
+            assert is_int(node["line"], expected["line"])
+
+        if expected["command"] is not None:
+            expected_keys.append("command")
+            assert is_int(node["command"])
+            assert is_string(btg["commands"][node["command"]], expected["command"])
+
+        if expected["hasParent"]:
+            expected_keys.append("parent")
+            assert is_int(node["parent"])
+            b = node["parent"]
+        else:
+            b = None
+
+        assert sorted(node.keys()) == sorted(expected_keys)
+
+    assert b is None
+
+def check_directory(c):
+    def _check(actual, expected):
+        assert is_dict(actual)
+        expected_keys = ["build", "source", "projectIndex"]
+        assert matches(actual["build"], expected["build"])
+
+        assert is_int(actual["projectIndex"])
+        assert is_string(c["projects"][actual["projectIndex"]]["name"], expected["projectName"])
+
+        if expected["parentSource"] is not None:
+            expected_keys.append("parentIndex")
+            assert is_int(actual["parentIndex"])
+            assert matches(c["directories"][actual["parentIndex"]]["source"], expected["parentSource"])
+
+        if expected["childSources"] is not None:
+            expected_keys.append("childIndexes")
+            check_list_match(lambda a, e: matches(c["directories"][a]["source"], e),
+                             actual["childIndexes"], expected["childSources"],
+                             missing_exception=lambda e: "Child source: %s" % e,
+                             extra_exception=lambda a: "Child source: %s" % a["source"])
+
+        if expected["targetIds"] is not None:
+            expected_keys.append("targetIndexes")
+            check_list_match(lambda a, e: matches(c["targets"][a]["id"], e),
+                             actual["targetIndexes"], expected["targetIds"],
+                             missing_exception=lambda e: "Target ID: %s" % e,
+                             extra_exception=lambda a: "Target ID: %s" % c["targets"][a]["id"])
+
+        if expected["minimumCMakeVersion"] is not None:
+            expected_keys.append("minimumCMakeVersion")
+            assert is_dict(actual["minimumCMakeVersion"])
+            assert sorted(actual["minimumCMakeVersion"].keys()) == ["string"]
+            assert is_string(actual["minimumCMakeVersion"]["string"], expected["minimumCMakeVersion"])
+
+        if expected["hasInstallRule"] is not None:
+            expected_keys.append("hasInstallRule")
+            assert is_bool(actual["hasInstallRule"], expected["hasInstallRule"])
+
+        assert sorted(actual.keys()) == sorted(expected_keys)
+
+    return _check
+
+def check_target_backtrace_graph(t):
+    btg = t["backtraceGraph"]
+    assert is_dict(btg)
+    assert sorted(btg.keys()) == ["commands", "files", "nodes"]
+    assert is_list(btg["commands"])
+
+    for c in btg["commands"]:
+        assert is_string(c)
+
+    for f in btg["files"]:
+        assert is_string(f)
+
+    for n in btg["nodes"]:
+        expected_keys = ["file"]
+        assert is_dict(n)
+        assert is_int(n["file"])
+        assert 0 <= n["file"] < len(btg["files"])
+
+        if "line" in n:
+            expected_keys.append("line")
+            assert is_int(n["line"])
+
+        if "command" in n:
+            expected_keys.append("command")
+            assert is_int(n["command"])
+            assert 0 <= n["command"] < len(btg["commands"])
+
+        if "parent" in n:
+            expected_keys.append("parent")
+            assert is_int(n["parent"])
+            assert 0 <= n["parent"] < len(btg["nodes"])
+
+        assert sorted(n.keys()) == sorted(expected_keys)
+
+def check_target(c):
+    def _check(actual, expected):
+        assert is_dict(actual)
+        assert sorted(actual.keys()) == ["directoryIndex", "id", "jsonFile", "name", "projectIndex"]
+        assert is_int(actual["directoryIndex"])
+        assert matches(c["directories"][actual["directoryIndex"]]["source"], expected["directorySource"])
+        assert is_string(actual["name"], expected["name"])
+        assert is_string(actual["jsonFile"])
+        assert is_int(actual["projectIndex"])
+        assert is_string(c["projects"][actual["projectIndex"]]["name"], expected["projectName"])
+
+        filepath = os.path.join(reply_dir, actual["jsonFile"])
+        with open(filepath) as f:
+            obj = json.load(f)
+
+        expected_keys = ["name", "id", "type", "backtraceGraph", "paths", "sources"]
+        assert is_dict(obj)
+        assert is_string(obj["name"], expected["name"])
+        assert matches(obj["id"], expected["id"])
+        assert is_string(obj["type"], expected["type"])
+        check_target_backtrace_graph(obj)
+
+        assert is_dict(obj["paths"])
+        assert sorted(obj["paths"].keys()) == ["build", "source"]
+        assert matches(obj["paths"]["build"], expected["build"])
+        assert matches(obj["paths"]["source"], expected["source"])
+
+        def check_source(actual, expected):
+            assert is_dict(actual)
+            expected_keys = ["path"]
+
+            if expected["compileGroupLanguage"] is not None:
+                expected_keys.append("compileGroupIndex")
+                assert is_string(obj["compileGroups"][actual["compileGroupIndex"]]["language"], expected["compileGroupLanguage"])
+
+            if expected["sourceGroupName"] is not None:
+                expected_keys.append("sourceGroupIndex")
+                assert is_string(obj["sourceGroups"][actual["sourceGroupIndex"]]["name"], expected["sourceGroupName"])
+
+            if expected["isGenerated"] is not None:
+                expected_keys.append("isGenerated")
+                assert is_bool(actual["isGenerated"], expected["isGenerated"])
+
+            if expected["backtrace"] is not None:
+                expected_keys.append("backtrace")
+                check_backtrace(obj, actual["backtrace"], expected["backtrace"])
+
+            assert sorted(actual.keys()) == sorted(expected_keys)
+
+        check_list_match(lambda a, e: matches(a["path"], e["path"]), obj["sources"],
+                         expected["sources"], check=check_source,
+                         check_exception=lambda a, e: "Source file: %s" % a["path"],
+                         missing_exception=lambda e: "Source file: %s" % e["path"],
+                         extra_exception=lambda a: "Source file: %s" % a["path"])
+
+        if expected["backtrace"] is not None:
+            expected_keys.append("backtrace")
+            check_backtrace(obj, obj["backtrace"], expected["backtrace"])
+
+        if expected["folder"] is not None:
+            expected_keys.append("folder")
+            assert is_dict(obj["folder"])
+            assert sorted(obj["folder"].keys()) == ["name"]
+            assert is_string(obj["folder"]["name"], expected["folder"])
+
+        if expected["nameOnDisk"] is not None:
+            expected_keys.append("nameOnDisk")
+            assert matches(obj["nameOnDisk"], expected["nameOnDisk"])
+
+        if expected["artifacts"] is not None:
+            expected_keys.append("artifacts")
+
+            def check_artifact(actual, expected):
+                assert is_dict(actual)
+                assert sorted(actual.keys()) == ["path"]
+
+            check_list_match(lambda a, e: matches(a["path"], e["path"]),
+                             obj["artifacts"], expected["artifacts"],
+                             check=check_artifact,
+                             check_exception=lambda a, e: "Artifact: %s" % a["path"],
+                             missing_exception=lambda e: "Artifact: %s" % e["path"],
+                             extra_exception=lambda a: "Artifact: %s" % a["path"])
+
+        if expected["isGeneratorProvided"] is not None:
+            expected_keys.append("isGeneratorProvided")
+            assert is_bool(obj["isGeneratorProvided"], expected["isGeneratorProvided"])
+
+        if expected["install"] is not None:
+            expected_keys.append("install")
+            assert is_dict(obj["install"])
+            assert sorted(obj["install"].keys()) == ["destinations", "prefix"]
+
+            assert is_dict(obj["install"]["prefix"])
+            assert sorted(obj["install"]["prefix"].keys()) == ["path"]
+            assert matches(obj["install"]["prefix"]["path"], expected["install"]["prefix"])
+
+            def check_install_destination(actual, expected):
+                assert is_dict(actual)
+                expected_keys = ["path"]
+
+                if expected["backtrace"] is not None:
+                    expected_keys.append("backtrace")
+                    check_backtrace(obj, actual["backtrace"], expected["backtrace"])
+
+                assert sorted(actual.keys()) == sorted(expected_keys)
+
+            check_list_match(lambda a, e: matches(a["path"], e["path"]),
+                             obj["install"]["destinations"], expected["install"]["destinations"],
+                             check=check_install_destination,
+                             check_exception=lambda a, e: "Install path: %s" % a["path"],
+                             missing_exception=lambda e: "Install path: %s" % e["path"],
+                             extra_exception=lambda a: "Install path: %s" % a["path"])
+
+        if expected["link"] is not None:
+            expected_keys.append("link")
+            assert is_dict(obj["link"])
+            link_keys = ["language"]
+
+            assert is_string(obj["link"]["language"], expected["link"]["language"])
+
+            # FIXME: Properly test commandFragments
+            if "commandFragments" in obj["link"]:
+                link_keys.append("commandFragments")
+                assert is_list(obj["link"]["commandFragments"])
+                for f in obj["link"]["commandFragments"]:
+                    assert is_dict(f)
+                    assert sorted(f.keys()) == ["fragment", "role"]
+                    assert is_string(f["fragment"])
+                    assert is_string(f["role"])
+                    assert f["role"] in ("flags", "libraries", "libraryPath", "frameworkPath")
+
+            if expected["link"]["lto"] is not None:
+                link_keys.append("lto")
+                assert is_bool(obj["link"]["lto"], expected["link"]["lto"])
+
+            # FIXME: Properly test sysroot
+            if "sysroot" in obj["link"]:
+                link_keys.append("sysroot")
+                assert is_string(obj["link"]["sysroot"])
+
+            assert sorted(obj["link"].keys()) == sorted(link_keys)
+
+        if expected["archive"] is not None:
+            expected_keys.append("archive")
+            assert is_dict(obj["archive"])
+            archive_keys = []
+
+            # FIXME: Properly test commandFragments
+            if "commandFragments" in obj["archive"]:
+                archive_keys.append("commandFragments")
+                assert is_list(obj["archive"]["commandFragments"])
+                for f in obj["archive"]["commandFragments"]:
+                    assert is_dict(f)
+                    assert sorted(f.keys()) == ["fragment", "role"]
+                    assert is_string(f["fragment"])
+                    assert is_string(f["role"])
+                    assert f["role"] in ("flags")
+
+            if expected["archive"]["lto"] is not None:
+                archive_keys.append("lto")
+                assert is_bool(obj["archive"]["lto"], expected["archive"]["lto"])
+
+            assert sorted(obj["archive"].keys()) == sorted(archive_keys)
+
+        if expected["dependencies"] is not None:
+            expected_keys.append("dependencies")
+
+            def check_dependency(actual, expected):
+                assert is_dict(actual)
+                expected_keys = ["id"]
+
+                if expected["backtrace"] is not None:
+                    expected_keys.append("backtrace")
+                    check_backtrace(obj, actual["backtrace"], expected["backtrace"])
+
+                assert sorted(actual.keys()) == sorted(expected_keys)
+
+            check_list_match(lambda a, e: matches(a["id"], e["id"]),
+                             obj["dependencies"], expected["dependencies"],
+                             check=check_dependency,
+                             check_exception=lambda a, e: "Dependency ID: %s" % a["id"],
+                             missing_exception=lambda e: "Dependency ID: %s" % e["id"],
+                             extra_exception=lambda a: "Dependency ID: %s" % a["id"])
+
+        if expected["sourceGroups"] is not None:
+            expected_keys.append("sourceGroups")
+
+            def check_source_group(actual, expected):
+                assert is_dict(actual)
+                assert sorted(actual.keys()) == ["name", "sourceIndexes"]
+
+                check_list_match(lambda a, e: matches(obj["sources"][a]["path"], e),
+                                 actual["sourceIndexes"], expected["sourcePaths"],
+                                 missing_exception=lambda e: "Source path: %s" % e,
+                                 extra_exception=lambda a: "Source path: %s" % obj["sources"][a]["path"])
+
+            check_list_match(lambda a, e: is_string(a["name"], e["name"]),
+                             obj["sourceGroups"], expected["sourceGroups"],
+                             check=check_source_group,
+                             check_exception=lambda a, e: "Source group: %s" % a["name"],
+                             missing_exception=lambda e: "Source group: %s" % e["name"],
+                             extra_exception=lambda a: "Source group: %s" % a["name"])
+
+        if expected["compileGroups"] is not None:
+            expected_keys.append("compileGroups")
+
+            def check_compile_group(actual, expected):
+                assert is_dict(actual)
+                expected_keys = ["sourceIndexes", "language"]
+
+                check_list_match(lambda a, e: matches(obj["sources"][a]["path"], e),
+                                 actual["sourceIndexes"], expected["sourcePaths"],
+                                 missing_exception=lambda e: "Source path: %s" % e,
+                                 extra_exception=lambda a: "Source path: %s" % obj["sources"][a]["path"])
+
+                # FIXME: Properly test compileCommandFragments
+                if "compileCommandFragments" in actual:
+                    expected_keys.append("compileCommandFragments")
+                    assert is_list(actual["compileCommandFragments"])
+                    for f in actual["compileCommandFragments"]:
+                        assert is_dict(f)
+                        assert sorted(f.keys()) == ["fragment"]
+                        assert is_string(f["fragment"])
+
+                if expected["includes"] is not None:
+                    expected_keys.append("includes")
+
+                    def check_include(actual, expected):
+                        assert is_dict(actual)
+                        expected_keys = ["path"]
+
+                        if expected["isSystem"] is not None:
+                            expected_keys.append("isSystem")
+                            assert is_bool(actual["isSystem"], expected["isSystem"])
+
+                        if expected["backtrace"] is not None:
+                            expected_keys.append("backtrace")
+                            check_backtrace(obj, actual["backtrace"], expected["backtrace"])
+
+                        assert sorted(actual.keys()) == sorted(expected_keys)
+
+                    check_list_match(lambda a, e: matches(a["path"], e["path"]),
+                                     actual["includes"], expected["includes"],
+                                     check=check_include,
+                                     check_exception=lambda a, e: "Include path: %s" % a["path"],
+                                     missing_exception=lambda e: "Include path: %s" % e["path"],
+                                     extra_exception=lambda a: "Include path: %s" % a["path"])
+
+                if expected["defines"] is not None:
+                    expected_keys.append("defines")
+
+                    def check_define(actual, expected):
+                        assert is_dict(actual)
+                        expected_keys = ["define"]
+
+                        if expected["backtrace"] is not None:
+                            expected_keys.append("backtrace")
+                            check_backtrace(obj, actual["backtrace"], expected["backtrace"])
+
+                        assert sorted(actual.keys()) == sorted(expected_keys)
+
+                    check_list_match(lambda a, e: is_string(a["define"], e["define"]),
+                                     actual["defines"], expected["defines"],
+                                     check=check_define,
+                                     check_exception=lambda a, e: "Define: %s" % a["define"],
+                                     missing_exception=lambda e: "Define: %s" % e["define"],
+                                     extra_exception=lambda a: "Define: %s" % a["define"])
+
+                # FIXME: Properly test sysroot
+                if "sysroot" in actual:
+                    expected_keys.append("sysroot")
+                    assert is_string(actual["sysroot"])
+
+                assert sorted(actual.keys()) == sorted(expected_keys)
+
+            check_list_match(lambda a, e: is_string(a["language"], e["language"]),
+                             obj["compileGroups"], expected["compileGroups"],
+                             check=check_compile_group,
+                             check_exception=lambda a, e: "Compile group: %s" % a["language"],
+                             missing_exception=lambda e: "Compile group: %s" % e["language"],
+                             extra_exception=lambda a: "Compile group: %s" % a["language"])
+
+        assert sorted(obj.keys()) == sorted(expected_keys)
+
+    return _check
+
+def check_project(c):
+    def _check(actual, expected):
+        assert is_dict(actual)
+        expected_keys = ["name", "directoryIndexes"]
+
+        check_list_match(lambda a, e: matches(c["directories"][a]["source"], e),
+                         actual["directoryIndexes"], expected["directorySources"],
+                         missing_exception=lambda e: "Directory source: %s" % e,
+                         extra_exception=lambda a: "Directory source: %s" % c["directories"][a]["source"])
+
+        if expected["parentName"] is not None:
+            expected_keys.append("parentIndex")
+            assert is_int(actual["parentIndex"])
+            assert is_string(c["projects"][actual["parentIndex"]]["name"], expected["parentName"])
+
+        if expected["childNames"] is not None:
+            expected_keys.append("childIndexes")
+            check_list_match(lambda a, e: is_string(c["projects"][a]["name"], e),
+                             actual["childIndexes"], expected["childNames"],
+                             missing_exception=lambda e: "Child name: %s" % e,
+                             extra_exception=lambda a: "Child name: %s" % c["projects"][a]["name"])
+
+        if expected["targetIds"] is not None:
+            expected_keys.append("targetIndexes")
+            check_list_match(lambda a, e: matches(c["targets"][a]["id"], e),
+                             actual["targetIndexes"], expected["targetIds"],
+                             missing_exception=lambda e: "Target ID: %s" % e,
+                             extra_exception=lambda a: "Target ID: %s" % c["targets"][a]["id"])
+
+        assert sorted(actual.keys()) == sorted(expected_keys)
+
+    return _check
+
+def gen_check_directories(c, g):
+    expected = [
+        {
+            "source": "^\\.$",
+            "build": "^\\.$",
+            "parentSource": None,
+            "childSources": [
+                "^alias$",
+                "^custom$",
+                "^cxx$",
+                "^imported$",
+                "^object$",
+                "^.*/Tests/RunCMake/FileAPIExternalSource$",
+                "^dir$",
+            ],
+            "targetIds": [
+                "^ALL_BUILD::@6890427a1f51a3e7e1df$",
+                "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                "^c_exe::@6890427a1f51a3e7e1df$",
+                "^c_lib::@6890427a1f51a3e7e1df$",
+                "^c_shared_exe::@6890427a1f51a3e7e1df$",
+                "^c_shared_lib::@6890427a1f51a3e7e1df$",
+                "^c_static_exe::@6890427a1f51a3e7e1df$",
+                "^c_static_lib::@6890427a1f51a3e7e1df$",
+                "^interface_exe::@6890427a1f51a3e7e1df$",
+            ],
+            "projectName": "codemodel-v2",
+            "minimumCMakeVersion": "3.12",
+            "hasInstallRule": True,
+        },
+        {
+            "source": "^alias$",
+            "build": "^alias$",
+            "parentSource": "^\\.$",
+            "childSources": None,
+            "targetIds": [
+                "^ALL_BUILD::@53632cba2752272bb008$",
+                "^ZERO_CHECK::@53632cba2752272bb008$",
+                "^c_alias_exe::@53632cba2752272bb008$",
+                "^cxx_alias_exe::@53632cba2752272bb008$",
+            ],
+            "projectName": "Alias",
+            "minimumCMakeVersion": "3.12",
+            "hasInstallRule": None,
+        },
+        {
+            "source": "^custom$",
+            "build": "^custom$",
+            "parentSource": "^\\.$",
+            "childSources": None,
+            "targetIds": [
+                "^ALL_BUILD::@c11385ffed57b860da63$",
+                "^ZERO_CHECK::@c11385ffed57b860da63$",
+                "^custom_exe::@c11385ffed57b860da63$",
+                "^custom_tgt::@c11385ffed57b860da63$",
+            ],
+            "projectName": "Custom",
+            "minimumCMakeVersion": "3.12",
+            "hasInstallRule": None,
+        },
+        {
+            "source": "^cxx$",
+            "build": "^cxx$",
+            "parentSource": "^\\.$",
+            "childSources": None,
+            "targetIds": [
+                "^ALL_BUILD::@a56b12a3f5c0529fb296$",
+                "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+                "^cxx_exe::@a56b12a3f5c0529fb296$",
+                "^cxx_lib::@a56b12a3f5c0529fb296$",
+                "^cxx_shared_exe::@a56b12a3f5c0529fb296$",
+                "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
+                "^cxx_static_exe::@a56b12a3f5c0529fb296$",
+                "^cxx_static_lib::@a56b12a3f5c0529fb296$",
+            ],
+            "projectName": "Cxx",
+            "minimumCMakeVersion": "3.12",
+            "hasInstallRule": None,
+        },
+        {
+            "source": "^imported$",
+            "build": "^imported$",
+            "parentSource": "^\\.$",
+            "childSources": None,
+            "targetIds": [
+                "^ALL_BUILD::@ba7eb709d0b48779c6c8$",
+                "^ZERO_CHECK::@ba7eb709d0b48779c6c8$",
+                "^link_imported_exe::@ba7eb709d0b48779c6c8$",
+                "^link_imported_interface_exe::@ba7eb709d0b48779c6c8$",
+                "^link_imported_object_exe::@ba7eb709d0b48779c6c8$",
+                "^link_imported_shared_exe::@ba7eb709d0b48779c6c8$",
+                "^link_imported_static_exe::@ba7eb709d0b48779c6c8$",
+            ],
+            "projectName": "Imported",
+            "minimumCMakeVersion": "3.12",
+            "hasInstallRule": None,
+        },
+        {
+            "source": "^object$",
+            "build": "^object$",
+            "parentSource": "^\\.$",
+            "childSources": None,
+            "targetIds": [
+                "^ALL_BUILD::@5ed5358f70faf8d8af7a$",
+                "^ZERO_CHECK::@5ed5358f70faf8d8af7a$",
+                "^c_object_exe::@5ed5358f70faf8d8af7a$",
+                "^c_object_lib::@5ed5358f70faf8d8af7a$",
+                "^cxx_object_exe::@5ed5358f70faf8d8af7a$",
+                "^cxx_object_lib::@5ed5358f70faf8d8af7a$",
+            ],
+            "projectName": "Object",
+            "minimumCMakeVersion": "3.13",
+            "hasInstallRule": True,
+        },
+        {
+            "source": "^dir$",
+            "build": "^dir$",
+            "parentSource": "^\\.$",
+            "childSources": [
+                "^dir/dir$",
+            ],
+            "targetIds": None,
+            "projectName": "codemodel-v2",
+            "minimumCMakeVersion": "3.12",
+            "hasInstallRule": None,
+        },
+        {
+            "source": "^dir/dir$",
+            "build": "^dir/dir$",
+            "parentSource": "^dir$",
+            "childSources": None,
+            "targetIds": None,
+            "projectName": "codemodel-v2",
+            "minimumCMakeVersion": "3.12",
+            "hasInstallRule": None,
+        },
+        {
+            "source": "^.*/Tests/RunCMake/FileAPIExternalSource$",
+            "build": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild$",
+            "parentSource": "^\\.$",
+            "childSources": None,
+            "targetIds": [
+                "^ALL_BUILD::@[0-9a-f]+$",
+                "^ZERO_CHECK::@[0-9a-f]+$",
+                "^generated_exe::@[0-9a-f]+$",
+            ],
+            "projectName": "External",
+            "minimumCMakeVersion": "3.12",
+            "hasInstallRule": None,
+        },
+    ]
+
+    if matches(g, "^Visual Studio "):
+        for e in expected:
+            if e["parentSource"] is not None:
+                e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^ZERO_CHECK"), e["targetIds"])
+
+    elif g == "Xcode":
+        if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""):
+            for e in expected:
+                e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(link_imported_object_exe)"), e["targetIds"])
+
+    else:
+        for e in expected:
+            e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(ALL_BUILD|ZERO_CHECK)"), e["targetIds"])
+
+    return expected
+
+def check_directories(c, g):
+    check_list_match(lambda a, e: matches(a["source"], e["source"]), c["directories"], gen_check_directories(c, g),
+                     check=check_directory(c),
+                     check_exception=lambda a, e: "Directory source: %s" % a["source"],
+                     missing_exception=lambda e: "Directory source: %s" % e["source"],
+                     extra_exception=lambda a: "Directory source: %s" % a["source"])
+
+def gen_check_targets(c, g, inSource):
+    expected = [
+        {
+            "name": "ALL_BUILD",
+            "id": "^ALL_BUILD::@6890427a1f51a3e7e1df$",
+            "directorySource": "^\\.$",
+            "projectName": "codemodel-v2",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/ALL_BUILD$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/ALL_BUILD\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/ALL_BUILD$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/ALL_BUILD\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^\\.$",
+            "source": "^\\.$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^interface_exe::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_lib::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_exe::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_shared_lib::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_shared_exe::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_static_lib::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_static_exe::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_alias_exe::@53632cba2752272bb008$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_alias_exe::@53632cba2752272bb008$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_exe::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_shared_exe::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_static_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_static_exe::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_object_lib::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_object_exe::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_object_lib::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_object_exe::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_shared_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_static_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_object_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_interface_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^custom_exe::@c11385ffed57b860da63$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^generated_exe::@[0-9a-f]+$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ZERO_CHECK",
+            "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+            "directorySource": "^\\.$",
+            "projectName": "codemodel-v2",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/ZERO_CHECK$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/ZERO_CHECK\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/ZERO_CHECK$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/ZERO_CHECK\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^\\.$",
+            "source": "^\\.$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": None,
+        },
+        {
+            "name": "interface_exe",
+            "id": "^interface_exe::@6890427a1f51a3e7e1df$",
+            "directorySource": "^\\.$",
+            "projectName": "codemodel-v2",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^include_test\\.cmake$",
+                            "line": 3,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^include_test\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": [
+                        {
+                            "define": "interface_exe_EXPORTS",
+                            "backtrace": None,
+                        },
+                    ],
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^include_test\\.cmake$",
+                    "line": 3,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^include_test\\.cmake$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": True,
+                },
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": 3,
+                    "command": "include",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": 3,
+                    "command": "include",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^my_interface_exe\\.myexe$",
+            "artifacts": [
+                {
+                    "path": "^bin/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?my_interface_exe\\.myexe$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?my_interface_exe\\.(dll\\.a|lib)$",
+                    "_dllExtra": True,
+                },
+                {
+                    "path": "^bin/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?my_interface_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^\\.$",
+            "source": "^\\.$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "c_lib",
+            "id": "^c_lib::@6890427a1f51a3e7e1df$",
+            "directorySource": "^\\.$",
+            "projectName": "codemodel-v2",
+            "type": "STATIC_LIBRARY",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 5,
+                            "command": "add_library",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": 5,
+                    "command": "add_library",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": 3,
+                    "command": "include",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^(lib)?c_lib\\.(a|lib)$",
+            "artifacts": [
+                {
+                    "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?c_lib\\.(a|lib)$",
+                    "_dllExtra": False,
+                },
+            ],
+            "build": "^\\.$",
+            "source": "^\\.$",
+            "install": None,
+            "link": None,
+            "archive": {
+                "lto": None,
+            },
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "c_exe",
+            "id": "^c_exe::@6890427a1f51a3e7e1df$",
+            "directorySource": "^\\.$",
+            "projectName": "codemodel-v2",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 6,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": 6,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": 3,
+                    "command": "include",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^c_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^\\.$",
+            "source": "^\\.$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^c_lib::@6890427a1f51a3e7e1df$",
+                    "backtrace": [
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 7,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "c_shared_lib",
+            "id": "^c_shared_lib::@6890427a1f51a3e7e1df$",
+            "directorySource": "^\\.$",
+            "projectName": "codemodel-v2",
+            "type": "SHARED_LIBRARY",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 9,
+                            "command": "add_library",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": [
+                        {
+                            "define": "c_shared_lib_EXPORTS",
+                            "backtrace": None,
+                        },
+                    ],
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": 9,
+                    "command": "add_library",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": 3,
+                    "command": "include",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^(lib|cyg)?c_shared_lib\\.(so|dylib|dll)$",
+            "artifacts": [
+                {
+                    "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib\\.(so|dylib|dll)$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?c_shared_lib\\.(dll\\.a|lib)$",
+                    "_dllExtra": True,
+                },
+                {
+                    "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^\\.$",
+            "source": "^\\.$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": True,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "c_shared_exe",
+            "id": "^c_shared_exe::@6890427a1f51a3e7e1df$",
+            "directorySource": "^\\.$",
+            "projectName": "codemodel-v2",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 10,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": 10,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": 3,
+                    "command": "include",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^c_shared_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_shared_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_shared_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^\\.$",
+            "source": "^\\.$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": True,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^c_shared_lib::@6890427a1f51a3e7e1df$",
+                    "backtrace": [
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 11,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "c_static_lib",
+            "id": "^c_static_lib::@6890427a1f51a3e7e1df$",
+            "directorySource": "^\\.$",
+            "projectName": "codemodel-v2",
+            "type": "STATIC_LIBRARY",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 13,
+                            "command": "add_library",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": 13,
+                    "command": "add_library",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": 3,
+                    "command": "include",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^(lib)?c_static_lib\\.(a|lib)$",
+            "artifacts": [
+                {
+                    "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?c_static_lib\\.(a|lib)$",
+                    "_dllExtra": False,
+                },
+            ],
+            "build": "^\\.$",
+            "source": "^\\.$",
+            "install": None,
+            "link": None,
+            "archive": {
+                "lto": True,
+            },
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "c_static_exe",
+            "id": "^c_static_exe::@6890427a1f51a3e7e1df$",
+            "directorySource": "^\\.$",
+            "projectName": "codemodel-v2",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 14,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": 14,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^codemodel-v2\\.cmake$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": 3,
+                    "command": "include",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^c_static_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_static_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_static_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^\\.$",
+            "source": "^\\.$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^c_static_lib::@6890427a1f51a3e7e1df$",
+                    "backtrace": [
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": 15,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^codemodel-v2\\.cmake$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "include",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ALL_BUILD",
+            "id": "^ALL_BUILD::@a56b12a3f5c0529fb296$",
+            "directorySource": "^cxx$",
+            "projectName": "Cxx",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/cxx/CMakeFiles/ALL_BUILD$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/cxx/CMakeFiles/ALL_BUILD\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/cxx/CMakeFiles/ALL_BUILD$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/cxx/CMakeFiles/ALL_BUILD\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^cxx$",
+            "source": "^cxx$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_exe::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_shared_exe::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_static_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_static_exe::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ZERO_CHECK",
+            "id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+            "directorySource": "^cxx$",
+            "projectName": "Cxx",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/cxx/CMakeFiles/ZERO_CHECK$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/cxx/CMakeFiles/ZERO_CHECK\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/cxx/CMakeFiles/ZERO_CHECK$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/cxx/CMakeFiles/ZERO_CHECK\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^cxx$",
+            "source": "^cxx$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": None,
+        },
+        {
+            "name": "cxx_lib",
+            "id": "^cxx_lib::@a56b12a3f5c0529fb296$",
+            "directorySource": "^cxx$",
+            "projectName": "Cxx",
+            "type": "STATIC_LIBRARY",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.cxx$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": 4,
+                            "command": "add_library",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": 4,
+                    "command": "add_library",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^(lib)?cxx_lib\\.(a|lib)$",
+            "artifacts": [
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?cxx_lib\\.(a|lib)$",
+                    "_dllExtra": False,
+                },
+            ],
+            "build": "^cxx$",
+            "source": "^cxx$",
+            "install": None,
+            "link": None,
+            "archive": {
+                "lto": None,
+            },
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "cxx_exe",
+            "id": "^cxx_exe::@a56b12a3f5c0529fb296$",
+            "directorySource": "^cxx$",
+            "projectName": "Cxx",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.cxx$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": 5,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": 5,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": "bin",
+            "nameOnDisk": "^cxx_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^cxx$",
+            "source": "^cxx$",
+            "install": None,
+            "link": {
+                "language": "CXX",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^cxx_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": 6,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "cxx_shared_lib",
+            "id": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
+            "directorySource": "^cxx$",
+            "projectName": "Cxx",
+            "type": "SHARED_LIBRARY",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.cxx$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": 9,
+                            "command": "add_library",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                    "includes": None,
+                    "defines": [
+                        {
+                            "define": "cxx_shared_lib_EXPORTS",
+                            "backtrace": None,
+                        },
+                    ],
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": 9,
+                    "command": "add_library",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^(lib|cyg)?cxx_shared_lib\\.(so|dylib|dll)$",
+            "artifacts": [
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?cxx_shared_lib\\.(so|dylib|dll)$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?cxx_shared_lib\\.(dll\\.a|lib)$",
+                    "_dllExtra": True,
+                },
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?cxx_shared_lib\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^cxx$",
+            "source": "^cxx$",
+            "install": None,
+            "link": {
+                "language": "CXX",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "cxx_shared_exe",
+            "id": "^cxx_shared_exe::@a56b12a3f5c0529fb296$",
+            "directorySource": "^cxx$",
+            "projectName": "Cxx",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.cxx$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": 10,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": 10,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^cxx_shared_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_shared_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_shared_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^cxx$",
+            "source": "^cxx$",
+            "install": None,
+            "link": {
+                "language": "CXX",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": 11,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "cxx_static_lib",
+            "id": "^cxx_static_lib::@a56b12a3f5c0529fb296$",
+            "directorySource": "^cxx$",
+            "projectName": "Cxx",
+            "type": "STATIC_LIBRARY",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.cxx$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": 13,
+                            "command": "add_library",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": 13,
+                    "command": "add_library",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^(lib)?cxx_static_lib\\.(a|lib)$",
+            "artifacts": [
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib)?cxx_static_lib\\.(a|lib)$",
+                    "_dllExtra": False,
+                },
+            ],
+            "build": "^cxx$",
+            "source": "^cxx$",
+            "install": None,
+            "link": None,
+            "archive": {
+                "lto": None,
+            },
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "cxx_static_exe",
+            "id": "^cxx_static_exe::@a56b12a3f5c0529fb296$",
+            "directorySource": "^cxx$",
+            "projectName": "Cxx",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.cxx$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": 14,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": 14,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^cxx/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^cxx_static_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_static_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^cxx/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_static_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^cxx$",
+            "source": "^cxx$",
+            "install": None,
+            "link": {
+                "language": "CXX",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^cxx_static_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": [
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": 15,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^cxx/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ALL_BUILD",
+            "id": "^ALL_BUILD::@53632cba2752272bb008$",
+            "directorySource": "^alias$",
+            "projectName": "Alias",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/alias/CMakeFiles/ALL_BUILD$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/alias/CMakeFiles/ALL_BUILD\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/alias/CMakeFiles/ALL_BUILD$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/alias/CMakeFiles/ALL_BUILD\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^alias/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^alias$",
+            "source": "^alias$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@53632cba2752272bb008$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_alias_exe::@53632cba2752272bb008$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_alias_exe::@53632cba2752272bb008$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ZERO_CHECK",
+            "id": "^ZERO_CHECK::@53632cba2752272bb008$",
+            "directorySource": "^alias$",
+            "projectName": "Alias",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/alias/CMakeFiles/ZERO_CHECK$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/alias/CMakeFiles/ZERO_CHECK\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/alias/CMakeFiles/ZERO_CHECK$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/alias/CMakeFiles/ZERO_CHECK\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^alias/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^alias$",
+            "source": "^alias$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": None,
+        },
+        {
+            "name": "c_alias_exe",
+            "id": "^c_alias_exe::@53632cba2752272bb008$",
+            "directorySource": "^alias$",
+            "projectName": "Alias",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": 5,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^alias/CMakeLists\\.txt$",
+                    "line": 5,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^alias/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^c_alias_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^alias/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_alias_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^alias/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_alias_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^alias$",
+            "source": "^alias$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^c_lib::@6890427a1f51a3e7e1df$",
+                    "backtrace": [
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": 6,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "id": "^ZERO_CHECK::@53632cba2752272bb008$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "cxx_alias_exe",
+            "id": "^cxx_alias_exe::@53632cba2752272bb008$",
+            "directorySource": "^alias$",
+            "projectName": "Alias",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.cxx$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": 9,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^alias/CMakeLists\\.txt$",
+                    "line": 9,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^alias/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^cxx_alias_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^alias/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_alias_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^alias/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_alias_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^alias$",
+            "source": "^alias$",
+            "install": None,
+            "link": {
+                "language": "CXX",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^cxx_lib::@a56b12a3f5c0529fb296$",
+                    "backtrace": [
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": 10,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^alias/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "id": "^ZERO_CHECK::@53632cba2752272bb008$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ALL_BUILD",
+            "id": "^ALL_BUILD::@5ed5358f70faf8d8af7a$",
+            "directorySource": "^object$",
+            "projectName": "Object",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/CMakeFiles/ALL_BUILD$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/CMakeFiles/ALL_BUILD\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/CMakeFiles/ALL_BUILD$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/CMakeFiles/ALL_BUILD\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^object$",
+            "source": "^object$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_object_lib::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^c_object_exe::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_object_lib::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^cxx_object_exe::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ZERO_CHECK",
+            "id": "^ZERO_CHECK::@5ed5358f70faf8d8af7a$",
+            "directorySource": "^object$",
+            "projectName": "Object",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/CMakeFiles/ZERO_CHECK$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/CMakeFiles/ZERO_CHECK\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/CMakeFiles/ZERO_CHECK$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/CMakeFiles/ZERO_CHECK\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^object$",
+            "source": "^object$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": None,
+        },
+        {
+            "name": "c_object_lib",
+            "id": "^c_object_lib::@5ed5358f70faf8d8af7a$",
+            "directorySource": "^object$",
+            "projectName": "Object",
+            "type": "OBJECT_LIBRARY",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": 5,
+                            "command": "add_library",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": 5,
+                    "command": "add_library",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": [
+                {
+                    "path": "^object/.*/empty(\\.c)?\\.o(bj)?$",
+                    "_dllExtra": False,
+                },
+            ],
+            "build": "^object$",
+            "source": "^object$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "c_object_exe",
+            "id": "^c_object_exe::@5ed5358f70faf8d8af7a$",
+            "directorySource": "^object$",
+            "projectName": "Object",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": 6,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/.*/empty(\\.c)?\\.o(bj)?$",
+                    "isGenerated": True,
+                    "sourceGroupName": "Object Libraries",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": 7,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+                {
+                    "name": "Object Libraries",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/.*/empty(\\.c)?\\.o(bj)?$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": 6,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^c_object_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^object/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_object_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^object/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?c_object_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^object$",
+            "source": "^object$",
+            "install": {
+                "prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$",
+                "destinations": [
+                    {
+                        "path": "bin",
+                        "backtrace": [
+                            {
+                                "file": "^object/CMakeLists\\.txt$",
+                                "line": 13,
+                                "command": "install",
+                                "hasParent": True,
+                            },
+                            {
+                                "file": "^object/CMakeLists\\.txt$",
+                                "line": None,
+                                "command": None,
+                                "hasParent": False,
+                            },
+                        ],
+                    },
+                ],
+            },
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^c_object_lib::@5ed5358f70faf8d8af7a$",
+                    # FIXME: Add a backtrace here when it becomes available.
+                    # You'll know when it's available, because this test will
+                    # fail.
+                    "backtrace": None,
+                },
+                {
+                    "id": "^ZERO_CHECK::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "cxx_object_lib",
+            "id": "^cxx_object_lib::@5ed5358f70faf8d8af7a$",
+            "directorySource": "^object$",
+            "projectName": "Object",
+            "type": "OBJECT_LIBRARY",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.cxx$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": 9,
+                            "command": "add_library",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": 9,
+                    "command": "add_library",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": [
+                {
+                    "path": "^object/.*/empty(\\.cxx)?\\.o(bj)?$",
+                    "_dllExtra": False,
+                },
+            ],
+            "build": "^object$",
+            "source": "^object$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "cxx_object_exe",
+            "id": "^cxx_object_exe::@5ed5358f70faf8d8af7a$",
+            "directorySource": "^object$",
+            "projectName": "Object",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.cxx$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": 10,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/.*/empty(\\.cxx)?\\.o(bj)?$",
+                    "isGenerated": True,
+                    "sourceGroupName": "Object Libraries",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": 11,
+                            "command": "target_link_libraries",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^object/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                },
+                {
+                    "name": "Object Libraries",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/object/.*/empty(\\.cxx)?\\.o(bj)?$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^empty\\.cxx$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": 10,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^object/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^cxx_object_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^object/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_object_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^object/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_object_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^object$",
+            "source": "^object$",
+            "install": {
+                "prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$",
+                "destinations": [
+                    {
+                        "path": "bin",
+                        "backtrace": [
+                            {
+                                "file": "^object/CMakeLists\\.txt$",
+                                "line": 13,
+                                "command": "install",
+                                "hasParent": True,
+                            },
+                            {
+                                "file": "^object/CMakeLists\\.txt$",
+                                "line": None,
+                                "command": None,
+                                "hasParent": False,
+                            },
+                        ],
+                    },
+                ],
+            },
+            "link": {
+                "language": "CXX",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^cxx_object_lib::@5ed5358f70faf8d8af7a$",
+                    # FIXME: Add a backtrace here when it becomes available.
+                    # You'll know when it's available, because this test will
+                    # fail.
+                    "backtrace": None,
+                },
+                {
+                    "id": "^ZERO_CHECK::@5ed5358f70faf8d8af7a$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ALL_BUILD",
+            "id": "^ALL_BUILD::@ba7eb709d0b48779c6c8$",
+            "directorySource": "^imported$",
+            "projectName": "Imported",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/imported/CMakeFiles/ALL_BUILD$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/imported/CMakeFiles/ALL_BUILD\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/imported/CMakeFiles/ALL_BUILD$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/imported/CMakeFiles/ALL_BUILD\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^imported$",
+            "source": "^imported$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_shared_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_static_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_object_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^link_imported_interface_exe::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ZERO_CHECK",
+            "id": "^ZERO_CHECK::@ba7eb709d0b48779c6c8$",
+            "directorySource": "^imported$",
+            "projectName": "Imported",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/imported/CMakeFiles/ZERO_CHECK$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/imported/CMakeFiles/ZERO_CHECK\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/imported/CMakeFiles/ZERO_CHECK$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/imported/CMakeFiles/ZERO_CHECK\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^imported$",
+            "source": "^imported$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": None,
+        },
+        {
+            "name": "link_imported_exe",
+            "id": "^link_imported_exe::@ba7eb709d0b48779c6c8$",
+            "directorySource": "^imported$",
+            "projectName": "Imported",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": 5,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": 5,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^link_imported_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^imported$",
+            "source": "^imported$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "link_imported_shared_exe",
+            "id": "^link_imported_shared_exe::@ba7eb709d0b48779c6c8$",
+            "directorySource": "^imported$",
+            "projectName": "Imported",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": 9,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": 9,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^link_imported_shared_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_shared_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_shared_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^imported$",
+            "source": "^imported$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "link_imported_static_exe",
+            "id": "^link_imported_static_exe::@ba7eb709d0b48779c6c8$",
+            "directorySource": "^imported$",
+            "projectName": "Imported",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": 13,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": 13,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^link_imported_static_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_static_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_static_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^imported$",
+            "source": "^imported$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "link_imported_object_exe",
+            "id": "^link_imported_object_exe::@ba7eb709d0b48779c6c8$",
+            "directorySource": "^imported$",
+            "projectName": "Imported",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": 18,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": 18,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^link_imported_object_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_object_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_object_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^imported$",
+            "source": "^imported$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "link_imported_interface_exe",
+            "id": "^link_imported_interface_exe::@ba7eb709d0b48779c6c8$",
+            "directorySource": "^imported$",
+            "projectName": "Imported",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": 23,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^imported/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": 23,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^imported/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^link_imported_interface_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_interface_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^imported/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?link_imported_interface_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^imported$",
+            "source": "^imported$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@ba7eb709d0b48779c6c8$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ALL_BUILD",
+            "id": "^ALL_BUILD::@c11385ffed57b860da63$",
+            "directorySource": "^custom$",
+            "projectName": "Custom",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/ALL_BUILD$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/ALL_BUILD\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/ALL_BUILD$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/ALL_BUILD\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^custom/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^custom$",
+            "source": "^custom$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@c11385ffed57b860da63$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^custom_exe::@c11385ffed57b860da63$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ZERO_CHECK",
+            "id": "^ZERO_CHECK::@c11385ffed57b860da63$",
+            "directorySource": "^custom$",
+            "projectName": "Custom",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/ZERO_CHECK$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/ZERO_CHECK\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/ZERO_CHECK$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/ZERO_CHECK\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^custom/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^custom$",
+            "source": "^custom$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": None,
+        },
+        {
+            "name": "custom_tgt",
+            "id": "^custom_tgt::@c11385ffed57b860da63$",
+            "directorySource": "^custom$",
+            "projectName": "Custom",
+            "type": "UTILITY",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/custom_tgt$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": 3,
+                            "command": "add_custom_target",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(custom/)?CMakeFiles/([0-9a-f]+/)?custom_tgt\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/custom/CMakeFiles/custom_tgt$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/(custom/)?CMakeFiles/([0-9a-f]+/)?custom_tgt\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^custom/CMakeLists\\.txt$",
+                    "line": 3,
+                    "command": "add_custom_target",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^custom/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^custom$",
+            "source": "^custom$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@c11385ffed57b860da63$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "custom_exe",
+            "id": "^custom_exe::@c11385ffed57b860da63$",
+            "directorySource": "^custom$",
+            "projectName": "Custom",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": 4,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^empty\\.c$",
+                    ],
+                    "includes": None,
+                    "defines": None,
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^custom/CMakeLists\\.txt$",
+                    "line": 4,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^custom/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^custom_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^custom/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?custom_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^custom/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?custom_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^custom$",
+            "source": "^custom$",
+            "install": None,
+            "link": {
+                "language": "C",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^custom_tgt::@c11385ffed57b860da63$",
+                    "backtrace": [
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": 5,
+                            "command": "add_dependencies",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^custom/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "id": "^ZERO_CHECK::@c11385ffed57b860da63$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ALL_BUILD",
+            "id": "^ALL_BUILD::@[0-9a-f]+$",
+            "directorySource": "^.*/Tests/RunCMake/FileAPIExternalSource$",
+            "projectName": "External",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/CMakeFiles/ALL_BUILD$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/CMakeFiles/ALL_BUILD\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/CMakeFiles/ALL_BUILD$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/CMakeFiles/ALL_BUILD\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild$",
+            "source": "^.*/Tests/RunCMake/FileAPIExternalSource$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@[0-9a-f]+$",
+                    "backtrace": None,
+                },
+                {
+                    "id": "^generated_exe::@[0-9a-f]+$",
+                    "backtrace": None,
+                },
+            ],
+        },
+        {
+            "name": "ZERO_CHECK",
+            "id": "^ZERO_CHECK::@[0-9a-f]+$",
+            "directorySource": "^.*/Tests/RunCMake/FileAPIExternalSource$",
+            "projectName": "External",
+            "type": "UTILITY",
+            "isGeneratorProvided": True,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/CMakeFiles/ZERO_CHECK$",
+                    "isGenerated": True,
+                    "sourceGroupName": "",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/CMakeFiles/ZERO_CHECK\\.rule$",
+                    "isGenerated": True,
+                    "sourceGroupName": "CMake Rules",
+                    "compileGroupLanguage": None,
+                    "backtrace": [
+                        {
+                            "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/CMakeFiles/ZERO_CHECK$",
+                    ],
+                },
+                {
+                    "name": "CMake Rules",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/CMakeFiles/ZERO_CHECK\\.rule$",
+                    ],
+                },
+            ],
+            "compileGroups": None,
+            "backtrace": [
+                {
+                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": None,
+            "artifacts": None,
+            "build": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild$",
+            "source": "^.*/Tests/RunCMake/FileAPIExternalSource$",
+            "install": None,
+            "link": None,
+            "archive": None,
+            "dependencies": None,
+        },
+        {
+            "name": "generated_exe",
+            "id": "^generated_exe::@[0-9a-f]+$",
+            "directorySource": "^.*/Tests/RunCMake/FileAPIExternalSource$",
+            "projectName": "External",
+            "type": "EXECUTABLE",
+            "isGeneratorProvided": None,
+            "sources": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPIExternalSource/empty\\.c$",
+                    "isGenerated": None,
+                    "sourceGroupName": "Source Files",
+                    "compileGroupLanguage": "C",
+                    "backtrace": [
+                        {
+                            "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                            "line": 5,
+                            "command": "add_executable",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/generated\\.cxx$",
+                    "isGenerated": True,
+                    "sourceGroupName": "Generated Source Files",
+                    "compileGroupLanguage": "CXX",
+                    "backtrace": [
+                        {
+                            "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                            "line": 6,
+                            "command": "target_sources",
+                            "hasParent": True,
+                        },
+                        {
+                            "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                            "line": None,
+                            "command": None,
+                            "hasParent": False,
+                        },
+                    ],
+                },
+            ],
+            "sourceGroups": [
+                {
+                    "name": "Source Files",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPIExternalSource/empty\\.c$",
+                    ],
+                },
+                {
+                    "name": "Generated Source Files",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/generated\\.cxx$",
+                    ],
+                },
+            ],
+            "compileGroups": [
+                {
+                    "language": "C",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPIExternalSource/empty\\.c$",
+                    ],
+                    "includes": [
+                        {
+                            "path": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild$",
+                            "isSystem": None,
+                            "backtrace": None,
+                        },
+                        {
+                            "path": "^.*/Tests/RunCMake/FileAPIExternalSource$",
+                            "isSystem": True,
+                            "backtrace": [
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": 11,
+                                    "command": "target_include_directories",
+                                    "hasParent": True,
+                                },
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": None,
+                                    "command": None,
+                                    "hasParent": False,
+                                },
+                            ],
+                        },
+                    ],
+                    "defines": [
+                        {
+                            "define": "EMPTY_C=1",
+                            "backtrace": None,
+                        },
+                        {
+                            "define": "SRC_DUMMY",
+                            "backtrace": None,
+                        },
+                        {
+                            "define": "GENERATED_EXE=1",
+                            "backtrace": [
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": 12,
+                                    "command": "target_compile_definitions",
+                                    "hasParent": True,
+                                },
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": None,
+                                    "command": None,
+                                    "hasParent": False,
+                                },
+                            ],
+                        },
+                        {
+                            "define": "TGT_DUMMY",
+                            "backtrace": [
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": 12,
+                                    "command": "target_compile_definitions",
+                                    "hasParent": True,
+                                },
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": None,
+                                    "command": None,
+                                    "hasParent": False,
+                                },
+                            ],
+                        },
+                    ],
+                },
+                {
+                    "language": "CXX",
+                    "sourcePaths": [
+                        "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/generated\\.cxx$",
+                    ],
+                    "includes": [
+                        {
+                            "path": "^.*/Tests/RunCMake/FileAPIExternalSource$",
+                            "isSystem": True,
+                            "backtrace": [
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": 11,
+                                    "command": "target_include_directories",
+                                    "hasParent": True,
+                                },
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": None,
+                                    "command": None,
+                                    "hasParent": False,
+                                },
+                            ],
+                        },
+                    ],
+                    "defines": [
+                        {
+                            "define": "GENERATED_EXE=1",
+                            "backtrace": [
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": 12,
+                                    "command": "target_compile_definitions",
+                                    "hasParent": True,
+                                },
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": None,
+                                    "command": None,
+                                    "hasParent": False,
+                                },
+                            ],
+                        },
+                        {
+                            "define": "TGT_DUMMY",
+                            "backtrace": [
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": 12,
+                                    "command": "target_compile_definitions",
+                                    "hasParent": True,
+                                },
+                                {
+                                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                                    "line": None,
+                                    "command": None,
+                                    "hasParent": False,
+                                },
+                            ],
+                        },
+                    ],
+                },
+            ],
+            "backtrace": [
+                {
+                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                    "line": 5,
+                    "command": "add_executable",
+                    "hasParent": True,
+                },
+                {
+                    "file": "^.*/Tests/RunCMake/FileAPIExternalSource/CMakeLists\\.txt$",
+                    "line": None,
+                    "command": None,
+                    "hasParent": False,
+                },
+            ],
+            "folder": None,
+            "nameOnDisk": "^generated_exe(\\.exe)?$",
+            "artifacts": [
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?generated_exe(\\.exe)?$",
+                    "_dllExtra": False,
+                },
+                {
+                    "path": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?generated_exe\\.pdb$",
+                    "_dllExtra": True,
+                },
+            ],
+            "build": "^.*/Tests/RunCMake/FileAPI/FileAPIExternalBuild$",
+            "source": "^.*/Tests/RunCMake/FileAPIExternalSource$",
+            "install": None,
+            "link": {
+                "language": "CXX",
+                "lto": None,
+            },
+            "archive": None,
+            "dependencies": [
+                {
+                    "id": "^ZERO_CHECK::@[0-9a-f]+$",
+                    "backtrace": None,
+                },
+            ],
+        },
+    ]
+
+    if not os.path.exists(os.path.join(reply_dir, "..", "..", "..", "..", "ipo_enabled.txt")):
+        for e in expected:
+            try:
+                e["link"]["lto"] = None
+            except TypeError:  # "link" is not a dict, no problem.
+                pass
+            try:
+                e["archive"]["lto"] = None
+            except TypeError:  # "archive" is not a dict, no problem.
+                pass
+
+    if inSource:
+        for e in expected:
+            if e["sources"] is not None:
+                for s in e["sources"]:
+                    s["path"] = s["path"].replace("^.*/Tests/RunCMake/FileAPI/", "^", 1)
+            if e["sourceGroups"] is not None:
+                for g in e["sourceGroups"]:
+                    g["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in g["sourcePaths"]]
+            if e["compileGroups"] is not None:
+                for g in e["compileGroups"]:
+                    g["sourcePaths"] = [p.replace("^.*/Tests/RunCMake/FileAPI/", "^", 1) for p in g["sourcePaths"]]
+
+    if matches(g, "^Visual Studio "):
+        expected = filter_list(lambda e: e["name"] not in ("ZERO_CHECK") or e["id"] == "^ZERO_CHECK::@6890427a1f51a3e7e1df$", expected)
+        for e in expected:
+            if e["type"] == "UTILITY":
+                if e["id"] == "^ZERO_CHECK::@6890427a1f51a3e7e1df$":
+                    e["sources"] = [
+                        {
+                            "path": "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/([0-9a-f]+/)?generate\\.stamp\\.rule$",
+                            "isGenerated": True,
+                            "sourceGroupName": "CMake Rules",
+                            "compileGroupLanguage": None,
+                            "backtrace": [
+                                {
+                                    "file": "^CMakeLists\\.txt$",
+                                    "line": None,
+                                    "command": None,
+                                    "hasParent": False,
+                                },
+                            ],
+                        },
+                    ]
+                    e["sourceGroups"] = [
+                        {
+                            "name": "CMake Rules",
+                            "sourcePaths": [
+                                "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build/CMakeFiles/([0-9a-f]+/)?generate\\.stamp\\.rule$",
+                            ],
+                        },
+                    ]
+                elif e["name"] in ("ALL_BUILD"):
+                    e["sources"] = []
+                    e["sourceGroups"] = None
+            if e["dependencies"] is not None:
+                for d in e["dependencies"]:
+                    if matches(d["id"], "^\\^ZERO_CHECK::@"):
+                        d["id"] = "^ZERO_CHECK::@6890427a1f51a3e7e1df$"
+
+    elif g == "Xcode":
+        if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""):
+            expected = filter_list(lambda e: e["name"] not in ("link_imported_object_exe"), expected)
+            for e in expected:
+                e["dependencies"] = filter_list(lambda d: not matches(d["id"], "^\\^link_imported_object_exe::@"), e["dependencies"])
+                if e["name"] in ("c_object_lib", "cxx_object_lib"):
+                    e["artifacts"] = None
+
+    else:
+        for e in expected:
+            e["dependencies"] = filter_list(lambda d: not matches(d["id"], "^\\^ZERO_CHECK::@"), e["dependencies"])
+
+        expected = filter_list(lambda t: t["name"] not in ("ALL_BUILD", "ZERO_CHECK"), expected)
+
+    if sys.platform not in ("win32", "cygwin", "msys"):
+        for e in expected:
+            e["artifacts"] = filter_list(lambda a: not a["_dllExtra"], e["artifacts"])
+
+    return expected
+
+def check_targets(c, g, inSource):
+    check_list_match(lambda a, e: matches(a["id"], e["id"]),
+                     c["targets"], gen_check_targets(c, g, inSource),
+                     check=check_target(c),
+                     check_exception=lambda a, e: "Target ID: %s" % a["id"],
+                     missing_exception=lambda e: "Target ID: %s" % e["id"],
+                     extra_exception=lambda a: "Target ID: %s" % a["id"])
+
+def gen_check_projects(c, g):
+    expected = [
+        {
+            "name": "codemodel-v2",
+            "parentName": None,
+            "childNames": [
+                "Alias",
+                "Custom",
+                "Cxx",
+                "Imported",
+                "Object",
+                "External",
+            ],
+            "directorySources": [
+                "^\\.$",
+                "^dir$",
+                "^dir/dir$",
+            ],
+            "targetIds": [
+                "^ALL_BUILD::@6890427a1f51a3e7e1df$",
+                "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
+                "^interface_exe::@6890427a1f51a3e7e1df$",
+                "^c_lib::@6890427a1f51a3e7e1df$",
+                "^c_exe::@6890427a1f51a3e7e1df$",
+                "^c_shared_lib::@6890427a1f51a3e7e1df$",
+                "^c_shared_exe::@6890427a1f51a3e7e1df$",
+                "^c_static_lib::@6890427a1f51a3e7e1df$",
+                "^c_static_exe::@6890427a1f51a3e7e1df$",
+            ],
+        },
+        {
+            "name": "Cxx",
+            "parentName": "codemodel-v2",
+            "childNames": None,
+            "directorySources": [
+                "^cxx$",
+            ],
+            "targetIds": [
+                "^ALL_BUILD::@a56b12a3f5c0529fb296$",
+                "^ZERO_CHECK::@a56b12a3f5c0529fb296$",
+                "^cxx_lib::@a56b12a3f5c0529fb296$",
+                "^cxx_exe::@a56b12a3f5c0529fb296$",
+                "^cxx_shared_lib::@a56b12a3f5c0529fb296$",
+                "^cxx_shared_exe::@a56b12a3f5c0529fb296$",
+                "^cxx_static_lib::@a56b12a3f5c0529fb296$",
+                "^cxx_static_exe::@a56b12a3f5c0529fb296$",
+            ],
+        },
+        {
+            "name": "Alias",
+            "parentName": "codemodel-v2",
+            "childNames": None,
+            "directorySources": [
+                "^alias$",
+            ],
+            "targetIds": [
+                "^ALL_BUILD::@53632cba2752272bb008$",
+                "^ZERO_CHECK::@53632cba2752272bb008$",
+                "^c_alias_exe::@53632cba2752272bb008$",
+                "^cxx_alias_exe::@53632cba2752272bb008$",
+            ],
+        },
+        {
+            "name": "Object",
+            "parentName": "codemodel-v2",
+            "childNames": None,
+            "directorySources": [
+                "^object$",
+            ],
+            "targetIds": [
+                "^ALL_BUILD::@5ed5358f70faf8d8af7a$",
+                "^ZERO_CHECK::@5ed5358f70faf8d8af7a$",
+                "^c_object_lib::@5ed5358f70faf8d8af7a$",
+                "^c_object_exe::@5ed5358f70faf8d8af7a$",
+                "^cxx_object_lib::@5ed5358f70faf8d8af7a$",
+                "^cxx_object_exe::@5ed5358f70faf8d8af7a$",
+            ],
+        },
+        {
+            "name": "Imported",
+            "parentName": "codemodel-v2",
+            "childNames": None,
+            "directorySources": [
+                "^imported$",
+            ],
+            "targetIds": [
+                "^ALL_BUILD::@ba7eb709d0b48779c6c8$",
+                "^ZERO_CHECK::@ba7eb709d0b48779c6c8$",
+                "^link_imported_exe::@ba7eb709d0b48779c6c8$",
+                "^link_imported_shared_exe::@ba7eb709d0b48779c6c8$",
+                "^link_imported_static_exe::@ba7eb709d0b48779c6c8$",
+                "^link_imported_object_exe::@ba7eb709d0b48779c6c8$",
+                "^link_imported_interface_exe::@ba7eb709d0b48779c6c8$",
+            ],
+        },
+        {
+            "name": "Custom",
+            "parentName": "codemodel-v2",
+            "childNames": None,
+            "directorySources": [
+                "^custom$",
+            ],
+            "targetIds": [
+                "^ALL_BUILD::@c11385ffed57b860da63$",
+                "^ZERO_CHECK::@c11385ffed57b860da63$",
+                "^custom_tgt::@c11385ffed57b860da63$",
+                "^custom_exe::@c11385ffed57b860da63$",
+            ],
+        },
+        {
+            "name": "External",
+            "parentName": "codemodel-v2",
+            "childNames": None,
+            "directorySources": [
+                "^.*/Tests/RunCMake/FileAPIExternalSource$",
+            ],
+            "targetIds": [
+                "^ALL_BUILD::@[0-9a-f]+$",
+                "^ZERO_CHECK::@[0-9a-f]+$",
+                "^generated_exe::@[0-9a-f]+$",
+            ],
+        },
+    ]
+
+    if matches(g, "^Visual Studio "):
+        for e in expected:
+            if e["parentName"] is not None:
+                e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^ZERO_CHECK"), e["targetIds"])
+
+    elif g == "Xcode":
+        if ';' in os.environ.get("CMAKE_OSX_ARCHITECTURES", ""):
+            for e in expected:
+                e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(link_imported_object_exe)"), e["targetIds"])
+
+    else:
+        for e in expected:
+            e["targetIds"] = filter_list(lambda t: not matches(t, "^\\^(ALL_BUILD|ZERO_CHECK)"), e["targetIds"])
+
+    return expected
+
+def check_projects(c, g):
+    check_list_match(lambda a, e: is_string(a["name"], e["name"]), c["projects"], gen_check_projects(c, g),
+                     check=check_project(c),
+                     check_exception=lambda a, e: "Project name: %s" % a["name"],
+                     missing_exception=lambda e: "Project name: %s" % e["name"],
+                     extra_exception=lambda a: "Project name: %s" % a["name"])
+
+def check_object_codemodel_configuration(c, g, inSource):
+    assert sorted(c.keys()) == ["directories", "name", "projects", "targets"]
+    assert is_string(c["name"])
+    check_directories(c, g)
+    check_targets(c, g, inSource)
+    check_projects(c, g)
+
+def check_object_codemodel(g):
+    def _check(o):
+        assert sorted(o.keys()) == ["configurations", "kind", "paths", "version"]
+        # The "kind" and "version" members are handled by check_index_object.
+        assert is_dict(o["paths"])
+        assert sorted(o["paths"].keys()) == ["build", "source"]
+        assert matches(o["paths"]["build"], "^.*/Tests/RunCMake/FileAPI/codemodel-v2-build$")
+        assert matches(o["paths"]["source"], "^.*/Tests/RunCMake/FileAPI$")
+
+        inSource = os.path.dirname(o["paths"]["build"]) == o["paths"]["source"]
+
+        if matches(g, "^(Visual Studio |Xcode$)"):
+            assert sorted([c["name"] for c in o["configurations"]]) == ["Debug", "MinSizeRel", "RelWithDebInfo", "Release"]
+        else:
+            assert len(o["configurations"]) == 1
+            assert o["configurations"][0]["name"] in ("", "Debug", "Release", "RelWithDebInfo", "MinSizeRel")
+
+        for c in o["configurations"]:
+            check_object_codemodel_configuration(c, g, inSource)
+    return _check
+
+assert is_dict(index)
+assert sorted(index.keys()) == ["cmake", "objects", "reply"]
+check_objects(index["objects"], index["cmake"]["generator"]["name"])

+ 35 - 0
Tests/RunCMake/FileAPI/codemodel-v2.cmake

@@ -0,0 +1,35 @@
+enable_language(C)
+
+include("${CMAKE_CURRENT_LIST_DIR}/include_test.cmake")
+
+add_library(c_lib empty.c)
+add_executable(c_exe empty.c)
+target_link_libraries(c_exe PRIVATE c_lib)
+
+add_library(c_shared_lib SHARED empty.c)
+add_executable(c_shared_exe empty.c)
+target_link_libraries(c_shared_exe PRIVATE c_shared_lib)
+
+add_library(c_static_lib STATIC empty.c)
+add_executable(c_static_exe empty.c)
+target_link_libraries(c_static_exe PRIVATE c_static_lib)
+
+add_subdirectory(cxx)
+add_subdirectory(alias)
+add_subdirectory(object)
+add_subdirectory(imported)
+add_subdirectory(custom)
+add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/../FileAPIExternalSource" "${CMAKE_CURRENT_BINARY_DIR}/../FileAPIExternalBuild")
+add_subdirectory(dir)
+
+set_property(TARGET c_shared_lib PROPERTY LIBRARY_OUTPUT_DIRECTORY lib)
+set_property(TARGET c_shared_lib PROPERTY RUNTIME_OUTPUT_DIRECTORY lib)
+
+include(CheckIPOSupported)
+check_ipo_supported(RESULT _ipo LANGUAGES C)
+if(_ipo)
+  set_property(TARGET c_shared_lib PROPERTY INTERPROCEDURAL_OPTIMIZATION ON)
+  set_property(TARGET c_shared_exe PROPERTY INTERPROCEDURAL_OPTIMIZATION ON)
+  set_property(TARGET c_static_lib PROPERTY INTERPROCEDURAL_OPTIMIZATION ON)
+  file(WRITE "${CMAKE_BINARY_DIR}/ipo_enabled.txt" "")
+endif()

+ 5 - 0
Tests/RunCMake/FileAPI/custom/CMakeLists.txt

@@ -0,0 +1,5 @@
+project(Custom)
+
+add_custom_target(custom_tgt COMMAND ${CMAKE_COMMAND} -E echo "Building custom_tgt")
+add_executable(custom_exe ../empty.c)
+add_dependencies(custom_exe custom_tgt)

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

@@ -0,0 +1,15 @@
+project(Cxx)
+enable_language(CXX)
+
+add_library(cxx_lib ../empty.cxx)
+add_executable(cxx_exe ../empty.cxx)
+target_link_libraries(cxx_exe PRIVATE cxx_lib)
+set_property(TARGET cxx_exe PROPERTY FOLDER bin)
+
+add_library(cxx_shared_lib SHARED ../empty.cxx)
+add_executable(cxx_shared_exe ../empty.cxx)
+target_link_libraries(cxx_shared_exe PRIVATE cxx_shared_lib)
+
+add_library(cxx_static_lib STATIC ../empty.cxx)
+add_executable(cxx_static_exe ../empty.cxx)
+target_link_libraries(cxx_static_exe PRIVATE cxx_static_lib)

+ 1 - 0
Tests/RunCMake/FileAPI/dir/CMakeLists.txt

@@ -0,0 +1 @@
+add_subdirectory(dir)

+ 0 - 0
Tests/RunCMake/FileAPI/dir/dir/CMakeLists.txt


+ 0 - 0
Tests/RunCMake/FileAPI/dir/dirtest.cmake


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


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


+ 24 - 0
Tests/RunCMake/FileAPI/imported/CMakeLists.txt

@@ -0,0 +1,24 @@
+project(Imported)
+
+add_library(imported_lib UNKNOWN IMPORTED)
+add_executable(imported_exe IMPORTED)
+add_executable(link_imported_exe ../empty.c)
+target_link_libraries(link_imported_exe PRIVATE imported_lib)
+
+add_library(imported_shared_lib SHARED IMPORTED)
+add_executable(link_imported_shared_exe ../empty.c)
+target_link_libraries(link_imported_shared_exe PRIVATE imported_shared_lib)
+
+add_library(imported_static_lib STATIC IMPORTED)
+add_executable(link_imported_static_exe ../empty.c)
+target_link_libraries(link_imported_static_exe PRIVATE imported_static_lib)
+
+if(NOT CMAKE_GENERATOR STREQUAL "Xcode" OR NOT CMAKE_OSX_ARCHITECTURES MATCHES "[;$]")
+  add_library(imported_object_lib OBJECT IMPORTED)
+  add_executable(link_imported_object_exe ../empty.c)
+  target_link_libraries(link_imported_object_exe PRIVATE imported_object_lib)
+endif()
+
+add_library(imported_interface_lib INTERFACE IMPORTED)
+add_executable(link_imported_interface_exe ../empty.c)
+target_link_libraries(link_imported_interface_exe PRIVATE imported_interface_lib)

+ 9 - 0
Tests/RunCMake/FileAPI/include_test.cmake

@@ -0,0 +1,9 @@
+add_library(interface_lib INTERFACE)
+target_compile_definitions(interface_lib INTERFACE COMPILED_WITH_INTERFACE_LIB)
+add_executable(interface_exe empty.c)
+target_link_libraries(interface_exe PRIVATE inteface_lib)
+set_property(TARGET interface_exe PROPERTY ENABLE_EXPORTS ON)
+set_property(TARGET interface_exe PROPERTY RUNTIME_OUTPUT_DIRECTORY bin)
+set_property(TARGET interface_exe PROPERTY ARCHIVE_OUTPUT_DIRECTORY lib)
+set_property(TARGET interface_exe PROPERTY OUTPUT_NAME my_interface_exe)
+set_property(TARGET interface_exe PROPERTY SUFFIX .myexe)

+ 13 - 0
Tests/RunCMake/FileAPI/object/CMakeLists.txt

@@ -0,0 +1,13 @@
+cmake_minimum_required(VERSION 3.13)
+project(Object)
+enable_language(CXX)
+
+add_library(c_object_lib OBJECT ../empty.c)
+add_executable(c_object_exe ../empty.c)
+target_link_libraries(c_object_exe PRIVATE c_object_lib)
+
+add_library(cxx_object_lib OBJECT ../empty.cxx)
+add_executable(cxx_object_exe ../empty.cxx)
+target_link_libraries(cxx_object_exe PRIVATE cxx_object_lib)
+
+install(TARGETS c_object_exe cxx_object_exe DESTINATION bin)

+ 0 - 0
Tests/RunCMake/FileAPIDummyFile.cmake


+ 12 - 0
Tests/RunCMake/FileAPIExternalSource/CMakeLists.txt

@@ -0,0 +1,12 @@
+project(External)
+enable_language(CXX)
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/generated.cxx" "")
+add_executable(generated_exe empty.c)
+target_sources(generated_exe PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/generated.cxx")
+source_group("Generated Source Files" FILES "${CMAKE_CURRENT_BINARY_DIR}/generated.cxx")
+set_property(SOURCE "${CMAKE_CURRENT_BINARY_DIR}/generated.cxx" PROPERTY GENERATED ON)
+set_property(SOURCE empty.c PROPERTY COMPILE_DEFINITIONS EMPTY_C=1 SRC_DUMMY)
+set_property(SOURCE empty.c PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}")
+target_include_directories(generated_exe SYSTEM PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
+target_compile_definitions(generated_exe PRIVATE GENERATED_EXE=1 -DTGT_DUMMY)

+ 0 - 0
Tests/RunCMake/FileAPIExternalSource/empty.c


+ 5 - 0
Tests/RunCMake/RunCMake.cmake

@@ -45,6 +45,11 @@ function(run_cmake test)
     file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
   endif()
   file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  if(RunCMake-prep-file AND EXISTS ${top_src}/${RunCMake-prep-file})
+    include(${top_src}/${RunCMake-prep-file})
+  else()
+    include(${top_src}/${test}-prep.cmake OPTIONAL)
+  endif()
   if(NOT DEFINED RunCMake_TEST_OPTIONS)
     set(RunCMake_TEST_OPTIONS "")
   endif()

+ 2 - 0
Utilities/IWYU/mapping.imp

@@ -123,6 +123,8 @@
   { symbol: [ "SIGINT", private, "\"cm_uv.h\"", public ] },
   { symbol: [ "ssize_t", private, "\"cm_uv.h\"", public ] },
 
+  { symbol: [ "Json::ArrayIndex", private, "\"cm_jsoncpp_value.h\"", public ] },
+
   { symbol: [ "std::ifstream", private, "\"cmsys/FStream.hxx\"", public ] },
   { symbol: [ "std::ofstream", private, "\"cmsys/FStream.hxx\"", public ] },
   { symbol: [ "cmsys::ifstream", private, "\"cmsys/FStream.hxx\"", public ] },

Некоторые файлы не были показаны из-за большого количества измененных файлов