Преглед изворни кода

fileapi: Add a "directory" object to codemodel-v2

This object will contain more detailed directory-level information.

Co-Authored-by: Kyle Edwards <[email protected]>
Brad King пре 4 година
родитељ
комит
a12d7f70b1

+ 35 - 2
Help/manual/cmake-file-api.7.rst

@@ -443,7 +443,8 @@ Version 1 does not exist to avoid confusion with that from
             "hasInstallRule": true,
             "minimumCMakeVersion": {
               "string": "3.14"
-            }
+            },
+            "jsonFile": "<file>"
           },
           {
             "source": "sub",
@@ -453,7 +454,8 @@ Version 1 does not exist to avoid confusion with that from
             "targetIndexes": [ 1 ],
             "minimumCMakeVersion": {
               "string": "3.14"
-            }
+            },
+            "jsonFile": "<file>"
           }
         ],
         "projects": [
@@ -569,6 +571,13 @@ The members specific to ``codemodel`` objects are:
       :command:`install` rules, i.e. whether a ``make install``
       or equivalent rule is available.
 
+    ``jsonFile``
+      A JSON string specifying a path relative to the codemodel file
+      to another JSON file containing a
+      `"codemodel" version 2 "directory" object`_.
+
+      This field was added in codemodel version 2.3.
+
   ``projects``
     A JSON array of entries corresponding to the top-level project
     and sub-projects defined in the build system.  Each (sub-)project
@@ -633,6 +642,30 @@ The members specific to ``codemodel`` objects are:
       to another JSON file containing a
       `"codemodel" version 2 "target" object`_.
 
+"codemodel" version 2 "directory" object
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A codemodel "directory" object is referenced by a `"codemodel" version 2`_
+object's ``directories`` array.  Each "directory" object is a JSON object
+with members:
+
+``paths``
+  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.
+
 "codemodel" version 2 "target" object
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 

+ 8 - 0
Help/release/dev/fileapi-codemodel-directory.rst

@@ -0,0 +1,8 @@
+fileapi-codemodel-directory
+---------------------------
+
+* The :manual:`cmake-file-api(7)` "codemodel" version 2 ``version`` field has
+  component been updated to 2.3.
+
+* The :manual:`cmake-file-api(7)` "codemodel" version 2 gained a
+  new "directory" object containing directory-level information.

+ 1 - 1
Source/cmFileAPI.cxx

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

+ 71 - 1
Source/cmFileAPICodemodel.cxx

@@ -273,6 +273,7 @@ class CodemodelConfig
 
   Json::Value DumpDirectories();
   Json::Value DumpDirectory(Directory& d);
+  Json::Value DumpDirectoryObject(Directory& d);
 
   Json::Value DumpProjects();
   Json::Value DumpProject(Project& p);
@@ -372,6 +373,20 @@ struct hash<CompileData>
 } // namespace std
 
 namespace {
+class DirectoryObject
+{
+  cmLocalGenerator const* LG = nullptr;
+  std::string const& Config;
+  std::string TopSource;
+  std::string TopBuild;
+
+  Json::Value DumpPaths();
+
+public:
+  DirectoryObject(cmLocalGenerator const* lg, std::string const& config);
+  Json::Value Dump();
+};
+
 class Target
 {
   cmGeneratorTarget* GT;
@@ -684,7 +699,7 @@ Json::Value CodemodelConfig::DumpDirectories()
 
 Json::Value CodemodelConfig::DumpDirectory(Directory& d)
 {
-  Json::Value directory = Json::objectValue;
+  Json::Value directory = this->DumpDirectoryObject(d);
 
   std::string sourceDir = d.Snapshot.GetDirectory().GetCurrentSource();
   directory["source"] = RelativeIfUnder(this->TopSource, sourceDir);
@@ -724,6 +739,31 @@ Json::Value CodemodelConfig::DumpDirectory(Directory& d)
   return directory;
 }
 
+Json::Value CodemodelConfig::DumpDirectoryObject(Directory& d)
+{
+  std::string prefix = "directory";
+  std::string sourceDirRel = RelativeIfUnder(
+    this->TopSource, d.Snapshot.GetDirectory().GetCurrentSource());
+  std::string buildDirRel = RelativeIfUnder(
+    this->TopBuild, d.Snapshot.GetDirectory().GetCurrentBinary());
+  if (!cmSystemTools::FileIsFullPath(buildDirRel)) {
+    prefix = cmStrCat(prefix, '-', buildDirRel);
+  } else if (!cmSystemTools::FileIsFullPath(sourceDirRel)) {
+    prefix = cmStrCat(prefix, '-', sourceDirRel);
+  }
+  for (char& c : prefix) {
+    if (c == '/' || c == '\\') {
+      c = '.';
+    }
+  }
+  if (!this->Config.empty()) {
+    prefix += "-" + this->Config;
+  }
+
+  DirectoryObject dir(d.LocalGenerator, this->Config);
+  return this->FileAPI.MaybeJsonFile(dir.Dump(), prefix);
+}
+
 Json::Value CodemodelConfig::DumpProjects()
 {
   Json::Value projects = Json::arrayValue;
@@ -767,6 +807,36 @@ Json::Value CodemodelConfig::DumpMinimumCMakeVersion(cmStateSnapshot s)
   return minimumCMakeVersion;
 }
 
+DirectoryObject::DirectoryObject(cmLocalGenerator const* lg,
+                                 std::string const& config)
+  : LG(lg)
+  , Config(config)
+  , TopSource(lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeDirectory())
+  , TopBuild(
+      lg->GetGlobalGenerator()->GetCMakeInstance()->GetHomeOutputDirectory())
+{
+}
+
+Json::Value DirectoryObject::Dump()
+{
+  Json::Value directoryObject = Json::objectValue;
+  directoryObject["paths"] = this->DumpPaths();
+  return directoryObject;
+}
+
+Json::Value DirectoryObject::DumpPaths()
+{
+  Json::Value paths = Json::objectValue;
+
+  std::string const& sourceDir = this->LG->GetCurrentSourceDirectory();
+  paths["source"] = RelativeIfUnder(this->TopSource, sourceDir);
+
+  std::string const& buildDir = this->LG->GetCurrentBinaryDirectory();
+  paths["build"] = RelativeIfUnder(this->TopBuild, buildDir);
+
+  return paths;
+}
+
 Target::Target(cmGeneratorTarget* gt, std::string const& config)
   : GT(gt)
   , Config(config)

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

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

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

@@ -4,6 +4,7 @@ set(expect
   query/client-foo/query.json
   reply
   reply/codemodel-v2-[0-9a-f]+\\.json
+  .*
   reply/index-[0-9.T-]+\\.json
   .*
   )

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

@@ -4,6 +4,7 @@ set(expect
   query/client-foo/codemodel-v2
   reply
   reply/codemodel-v2-[0-9a-f]+\\.json
+  .*
   reply/index-[0-9.T-]+\\.json
   .*
   )

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

@@ -3,6 +3,7 @@ set(expect
   query/codemodel-v2
   reply
   reply/codemodel-v2-[0-9a-f]+\\.json
+  .*
   reply/index-[0-9.T-]+\\.json
   .*
   )

+ 20 - 2
Tests/RunCMake/FileAPI/codemodel-v2-check.py

@@ -12,7 +12,7 @@ def read_codemodel_json_data(filename):
 def check_objects(o, g):
     assert is_list(o)
     assert len(o) == 1
-    check_index_object(o[0], "codemodel", 2, 2, check_object_codemodel(g))
+    check_index_object(o[0], "codemodel", 2, 3, check_object_codemodel(g))
 
 def check_backtrace(t, b, backtrace):
     btg = t["backtraceGraph"]
@@ -55,7 +55,7 @@ def check_backtraces(t, actual, expected):
 def check_directory(c):
     def _check(actual, expected):
         assert is_dict(actual)
-        expected_keys = ["build", "source", "projectIndex"]
+        expected_keys = ["build", "jsonFile", "source", "projectIndex"]
         assert matches(actual["build"], expected["build"])
 
         assert is_int(actual["projectIndex"])
@@ -92,6 +92,17 @@ def check_directory(c):
 
         assert sorted(actual.keys()) == sorted(expected_keys)
 
+        assert is_string(actual["jsonFile"])
+        filepath = os.path.join(reply_dir, actual["jsonFile"])
+        with open(filepath) as f:
+            d = json.load(f)
+
+        assert is_dict(d)
+        assert sorted(d.keys()) == ["paths"]
+
+        assert is_string(d["paths"]["source"], actual["source"])
+        assert is_string(d["paths"]["build"], actual["build"])
+
     return _check
 
 def check_backtrace_graph(btg):
@@ -704,6 +715,13 @@ def gen_check_targets(c, g, inSource):
     if sys.platform not in ("win32", "cygwin", "msys"):
         for e in expected:
             e["artifacts"] = filter_list(lambda a: not a["_dllExtra"], e["artifacts"])
+            if e["install"] is not None:
+                e["install"]["destinations"] = filter_list(lambda d: "_dllExtra" not in d or not d["_dllExtra"], e["install"]["destinations"])
+
+    else:
+        for e in expected:
+            if e["install"] is not None:
+                e["install"]["destinations"] = filter_list(lambda d: "_namelink" not in d or not d["_namelink"], e["install"]["destinations"])
 
     if "aix" not in sys.platform:
         for e in expected:

+ 1 - 1
Tests/RunCMake/FileAPI/codemodel-v2-data/directories/external.json

@@ -10,5 +10,5 @@
     ],
     "projectName": "External",
     "minimumCMakeVersion": "3.12",
-    "hasInstallRule": null
+    "hasInstallRule": true
 }

+ 97 - 4
Tests/RunCMake/FileAPI/codemodel-v2-data/targets/c_shared_lib.json

@@ -90,10 +90,10 @@
         }
     ],
     "folder": null,
-    "nameOnDisk": "^(lib|cyg)?c_shared_lib\\.(so|dylib|dll)$",
+    "nameOnDisk": "^(lib|cyg)?c_shared_lib(-1)?\\.(so|dylib|dll)$",
     "artifacts": [
         {
-            "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib\\.(so|dylib|dll)$",
+            "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib(-1)?\\.(so|dylib|dll)$",
             "_dllExtra": false
         },
         {
@@ -101,13 +101,106 @@
             "_dllExtra": true
         },
         {
-            "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib\\.pdb$",
+            "path": "^lib/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?(lib|cyg)?c_shared_lib(-1)?\\.pdb$",
             "_dllExtra": true
         }
     ],
     "build": "^\\.$",
     "source": "^\\.$",
-    "install": null,
+    "install": {
+        "prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$",
+        "destinations": [
+            {
+                "path": "lib",
+                "backtrace": [
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": 41,
+                        "command": "install",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": 3,
+                        "command": "include",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": false
+                    }
+                ]
+            },
+            {
+                "path": "lib",
+                "_dllExtra": true,
+                "backtrace": [
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": 41,
+                        "command": "install",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": 3,
+                        "command": "include",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": false
+                    }
+                ]
+            },
+            {
+                "path": "lib",
+                "_namelink": true,
+                "backtrace": [
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": 46,
+                        "command": "install",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": 3,
+                        "command": "include",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": false
+                    }
+                ]
+            }
+        ]
+    },
     "link": {
         "language": "C",
         "lto": true,

+ 94 - 1
Tests/RunCMake/FileAPI/codemodel-v2-data/targets/cxx_shared_lib.json

@@ -83,7 +83,100 @@
     ],
     "build": "^cxx$",
     "source": "^cxx$",
-    "install": null,
+    "install": {
+        "prefix": "^(/usr/local|[A-Za-z]:.*/codemodel-v2)$",
+        "destinations": [
+            {
+                "path": "lib",
+                "backtrace": [
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": 41,
+                        "command": "install",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": 3,
+                        "command": "include",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": false
+                    }
+                ]
+            },
+            {
+                "path": "lib",
+                "_dllExtra": true,
+                "backtrace": [
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": 41,
+                        "command": "install",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": 3,
+                        "command": "include",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": false
+                    }
+                ]
+            },
+            {
+                "path": "lib",
+                "_namelink": true,
+                "backtrace": [
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": 46,
+                        "command": "install",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^codemodel-v2\\.cmake$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": 3,
+                        "command": "include",
+                        "hasParent": true
+                    },
+                    {
+                        "file": "^CMakeLists\\.txt$",
+                        "line": null,
+                        "command": null,
+                        "hasParent": false
+                    }
+                ]
+            }
+        ]
+    },
     "link": {
         "language": "CXX",
         "lto": null,

+ 16 - 1
Tests/RunCMake/FileAPI/codemodel-v2.cmake

@@ -35,4 +35,19 @@ if(_ipo)
   file(WRITE "${CMAKE_BINARY_DIR}/ipo_enabled.txt" "")
 endif()
 
-install(TARGETS cxx_exe)
+install(TARGETS cxx_exe COMPONENT Tools EXPORT FooTargets)
+
+set_target_properties(c_shared_lib PROPERTIES VERSION 1.2.3 SOVERSION 1)
+install(TARGETS c_shared_lib cxx_shared_lib
+  ARCHIVE DESTINATION lib
+  RUNTIME DESTINATION lib
+  LIBRARY DESTINATION lib NAMELINK_SKIP
+  )
+install(TARGETS c_shared_lib cxx_shared_lib LIBRARY NAMELINK_ONLY)
+
+install(FILES empty.h TYPE INCLUDE RENAME empty-renamed.h OPTIONAL)
+install(FILES codemodel-v2.cmake empty.h DESTINATION include)
+install(DIRECTORY . dir cxx/ OPTIONAL DESTINATION dir1)
+install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/dir" "${CMAKE_CURRENT_SOURCE_DIR}/cxx/" DESTINATION dir2)
+install(EXPORT FooTargets DESTINATION lib/cmake/foo)
+install(SCRIPT InstallScript.cmake)

+ 1 - 1
Tests/RunCMake/FileAPI/cxx/CMakeLists.txt

@@ -16,7 +16,7 @@ target_link_libraries(cxx_static_exe PRIVATE cxx_static_lib)
 
 target_compile_options(cxx_exe PUBLIC TargetCompileOptions)
 target_link_options(cxx_exe PUBLIC TargetLinkOptions)
-target_link_directories(cxx_exe PUBLIC "${CMAKE_BINARY_DIR}/TargetLinkDir")
+target_link_directories(cxx_exe PUBLIC "$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/TargetLinkDir>")
 
 target_precompile_headers(cxx_exe PUBLIC ../empty.h)
 

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

@@ -11,3 +11,6 @@ set_property(SOURCE empty.c PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY
 target_include_directories(generated_exe SYSTEM PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
 target_compile_definitions(generated_exe PRIVATE GENERATED_EXE=1 -DTGT_DUMMY)
 set_source_files_properties(empty.c PROPERTIES COMPILE_OPTIONS SRC_COMPILE_OPTIONS_DUMMY)
+
+install(DIRECTORY . DESTINATION dir3)
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} EXCLUDE_FROM_ALL DESTINATION dir4)