From eb8c7676a4723a44245e47630f12d4868e8e182c Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 13 Nov 2018 07:00:33 -0500 Subject: fileapi: extend codemodel v2 with a project model Offer clients a `project()`-centric view of the build system. This is similar to the directory-centric view but consolidates subdirectories that do not call `project()` with a new project name. Issue: #18398 Co-Author: Kyle Edwards --- Help/manual/cmake-file-api.7.rst | 56 ++++++ Source/cmFileAPICodemodel.cxx | 86 +++++++++ Tests/RunCMake/FileAPI/codemodel-v2-check.py | 261 ++++++++++++++++++++++++++- Tests/RunCMake/FileAPI/codemodel-v2.cmake | 1 + 4 files changed, 401 insertions(+), 3 deletions(-) diff --git a/Help/manual/cmake-file-api.7.rst b/Help/manual/cmake-file-api.7.rst index 0dbdfd7..f35e351 100644 --- a/Help/manual/cmake-file-api.7.rst +++ b/Help/manual/cmake-file-api.7.rst @@ -432,24 +432,35 @@ Version 1 does not exist to avoid confusion with that from "source": ".", "build": ".", "childIndexes": [ 1 ], + "projectIndex": 0, "targetIndexes": [ 0 ] }, { "source": "sub", "build": "sub", "parentIndex": 0, + "projectIndex": 0, "targetIndexes": [ 1 ] } ], + "projects": [ + { + "name": "MyProject", + "directoryIndexes": [ 0, 1 ], + "targetIndexes": [ 0, 1 ] + } + ], "targets": [ { "name": "MyExecutable", "directoryIndex": 0, + "projectIndex": 0, "jsonFile": "" }, { "name": "MyLibrary", "directoryIndex": 1, + "projectIndex": 0, "jsonFile": "" } ] @@ -514,12 +525,53 @@ The members specific to ``codemodel`` objects are: 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. + ``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`, @@ -538,6 +590,10 @@ The members specific to ``codemodel`` objects are: 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 diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 3d4a7cf..d432c1e 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -63,22 +63,42 @@ class CodemodelConfig { cmStateSnapshot Snapshot; Json::Value TargetIndexes = Json::arrayValue; + Json::ArrayIndex ProjectIndex; }; std::map DirectoryMap; std::vector Directories; + struct Project + { + cmStateSnapshot Snapshot; + static const Json::ArrayIndex NoParentIndex = + static_cast(-1); + Json::ArrayIndex ParentIndex = NoParentIndex; + Json::Value ChildIndexes = Json::arrayValue; + Json::Value DirectoryIndexes = Json::arrayValue; + Json::Value TargetIndexes = Json::arrayValue; + }; + std::map + ProjectMap; + std::vector 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); + public: CodemodelConfig(cmFileAPI& fileAPI, unsigned long version, std::string const& config); @@ -358,6 +378,7 @@ Json::Value CodemodelConfig::Dump() this->ProcessDirectories(); configuration["targets"] = this->DumpTargets(); configuration["directories"] = this->DumpDirectories(); + configuration["projects"] = this->DumpProjects(); return configuration; } @@ -376,6 +397,9 @@ void CodemodelConfig::ProcessDirectories() Directory& d = this->Directories[directoryIndex]; d.Snapshot = lg->GetStateSnapshot().GetBuildsystemDirectory(); this->DirectoryMap[d.Snapshot] = directoryIndex; + + d.ProjectIndex = this->AddProject(d.Snapshot); + this->Projects[d.ProjectIndex].DirectoryIndexes.append(directoryIndex); } } @@ -392,6 +416,29 @@ Json::ArrayIndex CodemodelConfig::GetDirectoryIndex(cmStateSnapshot s) 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(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; @@ -437,6 +484,11 @@ Json::Value CodemodelConfig::DumpTarget(cmGeneratorTarget* gt, 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; } @@ -473,6 +525,8 @@ Json::Value CodemodelConfig::DumpDirectory(Directory& d) directory["childIndexes"] = std::move(childIndexes); } + directory["projectIndex"] = d.ProjectIndex; + if (!d.TargetIndexes.empty()) { directory["targetIndexes"] = std::move(d.TargetIndexes); } @@ -480,6 +534,38 @@ Json::Value CodemodelConfig::DumpDirectory(Directory& d) 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; +} + Target::Target(cmGeneratorTarget* gt, std::string const& config) : GT(gt) , Config(config) diff --git a/Tests/RunCMake/FileAPI/codemodel-v2-check.py b/Tests/RunCMake/FileAPI/codemodel-v2-check.py index e82bddd..8111c79 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2-check.py +++ b/Tests/RunCMake/FileAPI/codemodel-v2-check.py @@ -39,9 +39,12 @@ def check_backtrace(t, b, backtrace): def check_directory(c): def _check(actual, expected): assert is_dict(actual) - expected_keys = ["build", "source"] + 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"]) @@ -102,11 +105,13 @@ def check_target_backtrace_graph(t): def check_target(c): def _check(actual, expected): assert is_dict(actual) - assert sorted(actual.keys()) == ["directoryIndex", "id", "jsonFile", "name"] + 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: @@ -383,6 +388,39 @@ def check_target(c): 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 = [ { @@ -396,6 +434,7 @@ def gen_check_directories(c, g): "^imported$", "^object$", "^.*/Tests/RunCMake/FileAPIExternalSource$", + "^dir$", ], "targetIds": [ "^ALL_BUILD::@6890427a1f51a3e7e1df$", @@ -408,6 +447,7 @@ def gen_check_directories(c, g): "^c_static_lib::@6890427a1f51a3e7e1df$", "^interface_exe::@6890427a1f51a3e7e1df$", ], + "projectName": "codemodel-v2", }, { "source": "^alias$", @@ -420,6 +460,7 @@ def gen_check_directories(c, g): "^c_alias_exe::@53632cba2752272bb008$", "^cxx_alias_exe::@53632cba2752272bb008$", ], + "projectName": "Alias", }, { "source": "^custom$", @@ -432,6 +473,7 @@ def gen_check_directories(c, g): "^custom_exe::@c11385ffed57b860da63$", "^custom_tgt::@c11385ffed57b860da63$", ], + "projectName": "Custom", }, { "source": "^cxx$", @@ -448,6 +490,7 @@ def gen_check_directories(c, g): "^cxx_static_exe::@a56b12a3f5c0529fb296$", "^cxx_static_lib::@a56b12a3f5c0529fb296$", ], + "projectName": "Cxx", }, { "source": "^imported$", @@ -463,6 +506,7 @@ def gen_check_directories(c, g): "^link_imported_shared_exe::@ba7eb709d0b48779c6c8$", "^link_imported_static_exe::@ba7eb709d0b48779c6c8$", ], + "projectName": "Imported", }, { "source": "^object$", @@ -477,6 +521,27 @@ def gen_check_directories(c, g): "^cxx_object_exe::@5ed5358f70faf8d8af7a$", "^cxx_object_lib::@5ed5358f70faf8d8af7a$", ], + "projectName": "Object", + }, + { + "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", }, { "source": "^.*/Tests/RunCMake/FileAPIExternalSource$", @@ -488,6 +553,7 @@ def gen_check_directories(c, g): "^ZERO_CHECK::@[0-9a-f]+$", "^generated_exe::@[0-9a-f]+$", ], + "projectName": "External", }, ] @@ -520,6 +586,7 @@ def gen_check_targets(c, g, inSource): "name": "ALL_BUILD", "id": "^ALL_BUILD::@6890427a1f51a3e7e1df$", "directorySource": "^\\.$", + "projectName": "codemodel-v2", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -698,6 +765,7 @@ def gen_check_targets(c, g, inSource): "name": "ZERO_CHECK", "id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$", "directorySource": "^\\.$", + "projectName": "codemodel-v2", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -767,6 +835,7 @@ def gen_check_targets(c, g, inSource): "name": "interface_exe", "id": "^interface_exe::@6890427a1f51a3e7e1df$", "directorySource": "^\\.$", + "projectName": "codemodel-v2", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -911,6 +980,7 @@ def gen_check_targets(c, g, inSource): "name": "c_lib", "id": "^c_lib::@6890427a1f51a3e7e1df$", "directorySource": "^\\.$", + "projectName": "codemodel-v2", "type": "STATIC_LIBRARY", "isGeneratorProvided": None, "sources": [ @@ -1017,6 +1087,7 @@ def gen_check_targets(c, g, inSource): "name": "c_exe", "id": "^c_exe::@6890427a1f51a3e7e1df$", "directorySource": "^\\.$", + "projectName": "codemodel-v2", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -1157,6 +1228,7 @@ def gen_check_targets(c, g, inSource): "name": "c_shared_lib", "id": "^c_shared_lib::@6890427a1f51a3e7e1df$", "directorySource": "^\\.$", + "projectName": "codemodel-v2", "type": "SHARED_LIBRARY", "isGeneratorProvided": None, "sources": [ @@ -1277,6 +1349,7 @@ def gen_check_targets(c, g, inSource): "name": "c_shared_exe", "id": "^c_shared_exe::@6890427a1f51a3e7e1df$", "directorySource": "^\\.$", + "projectName": "codemodel-v2", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -1417,6 +1490,7 @@ def gen_check_targets(c, g, inSource): "name": "c_static_lib", "id": "^c_static_lib::@6890427a1f51a3e7e1df$", "directorySource": "^\\.$", + "projectName": "codemodel-v2", "type": "STATIC_LIBRARY", "isGeneratorProvided": None, "sources": [ @@ -1523,6 +1597,7 @@ def gen_check_targets(c, g, inSource): "name": "c_static_exe", "id": "^c_static_exe::@6890427a1f51a3e7e1df$", "directorySource": "^\\.$", + "projectName": "codemodel-v2", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -1663,6 +1738,7 @@ def gen_check_targets(c, g, inSource): "name": "ALL_BUILD", "id": "^ALL_BUILD::@a56b12a3f5c0529fb296$", "directorySource": "^cxx$", + "projectName": "Cxx", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -1761,6 +1837,7 @@ def gen_check_targets(c, g, inSource): "name": "ZERO_CHECK", "id": "^ZERO_CHECK::@a56b12a3f5c0529fb296$", "directorySource": "^cxx$", + "projectName": "Cxx", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -1830,6 +1907,7 @@ def gen_check_targets(c, g, inSource): "name": "cxx_lib", "id": "^cxx_lib::@a56b12a3f5c0529fb296$", "directorySource": "^cxx$", + "projectName": "Cxx", "type": "STATIC_LIBRARY", "isGeneratorProvided": None, "sources": [ @@ -1912,6 +1990,7 @@ def gen_check_targets(c, g, inSource): "name": "cxx_exe", "id": "^cxx_exe::@a56b12a3f5c0529fb296$", "directorySource": "^cxx$", + "projectName": "Cxx", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -2016,6 +2095,7 @@ def gen_check_targets(c, g, inSource): "name": "cxx_shared_lib", "id": "^cxx_shared_lib::@a56b12a3f5c0529fb296$", "directorySource": "^cxx$", + "projectName": "Cxx", "type": "SHARED_LIBRARY", "isGeneratorProvided": None, "sources": [ @@ -2112,6 +2192,7 @@ def gen_check_targets(c, g, inSource): "name": "cxx_shared_exe", "id": "^cxx_shared_exe::@a56b12a3f5c0529fb296$", "directorySource": "^cxx$", + "projectName": "Cxx", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -2216,6 +2297,7 @@ def gen_check_targets(c, g, inSource): "name": "cxx_static_lib", "id": "^cxx_static_lib::@a56b12a3f5c0529fb296$", "directorySource": "^cxx$", + "projectName": "Cxx", "type": "STATIC_LIBRARY", "isGeneratorProvided": None, "sources": [ @@ -2298,6 +2380,7 @@ def gen_check_targets(c, g, inSource): "name": "cxx_static_exe", "id": "^cxx_static_exe::@a56b12a3f5c0529fb296$", "directorySource": "^cxx$", + "projectName": "Cxx", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -2402,6 +2485,7 @@ def gen_check_targets(c, g, inSource): "name": "ALL_BUILD", "id": "^ALL_BUILD::@53632cba2752272bb008$", "directorySource": "^alias$", + "projectName": "Alias", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -2484,6 +2568,7 @@ def gen_check_targets(c, g, inSource): "name": "ZERO_CHECK", "id": "^ZERO_CHECK::@53632cba2752272bb008$", "directorySource": "^alias$", + "projectName": "Alias", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -2553,6 +2638,7 @@ def gen_check_targets(c, g, inSource): "name": "c_alias_exe", "id": "^c_alias_exe::@53632cba2752272bb008$", "directorySource": "^alias$", + "projectName": "Alias", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -2657,6 +2743,7 @@ def gen_check_targets(c, g, inSource): "name": "cxx_alias_exe", "id": "^cxx_alias_exe::@53632cba2752272bb008$", "directorySource": "^alias$", + "projectName": "Alias", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -2761,6 +2848,7 @@ def gen_check_targets(c, g, inSource): "name": "ALL_BUILD", "id": "^ALL_BUILD::@5ed5358f70faf8d8af7a$", "directorySource": "^object$", + "projectName": "Object", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -2851,6 +2939,7 @@ def gen_check_targets(c, g, inSource): "name": "ZERO_CHECK", "id": "^ZERO_CHECK::@5ed5358f70faf8d8af7a$", "directorySource": "^object$", + "projectName": "Object", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -2920,6 +3009,7 @@ def gen_check_targets(c, g, inSource): "name": "c_object_lib", "id": "^c_object_lib::@5ed5358f70faf8d8af7a$", "directorySource": "^object$", + "projectName": "Object", "type": "OBJECT_LIBRARY", "isGeneratorProvided": None, "sources": [ @@ -3000,6 +3090,7 @@ def gen_check_targets(c, g, inSource): "name": "c_object_exe", "id": "^c_object_exe::@5ed5358f70faf8d8af7a$", "directorySource": "^object$", + "projectName": "Object", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -3141,6 +3232,7 @@ def gen_check_targets(c, g, inSource): "name": "cxx_object_lib", "id": "^cxx_object_lib::@5ed5358f70faf8d8af7a$", "directorySource": "^object$", + "projectName": "Object", "type": "OBJECT_LIBRARY", "isGeneratorProvided": None, "sources": [ @@ -3221,6 +3313,7 @@ def gen_check_targets(c, g, inSource): "name": "cxx_object_exe", "id": "^cxx_object_exe::@5ed5358f70faf8d8af7a$", "directorySource": "^object$", + "projectName": "Object", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -3362,6 +3455,7 @@ def gen_check_targets(c, g, inSource): "name": "ALL_BUILD", "id": "^ALL_BUILD::@ba7eb709d0b48779c6c8$", "directorySource": "^imported$", + "projectName": "Imported", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -3456,6 +3550,7 @@ def gen_check_targets(c, g, inSource): "name": "ZERO_CHECK", "id": "^ZERO_CHECK::@ba7eb709d0b48779c6c8$", "directorySource": "^imported$", + "projectName": "Imported", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -3525,6 +3620,7 @@ def gen_check_targets(c, g, inSource): "name": "link_imported_exe", "id": "^link_imported_exe::@ba7eb709d0b48779c6c8$", "directorySource": "^imported$", + "projectName": "Imported", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -3612,6 +3708,7 @@ def gen_check_targets(c, g, inSource): "name": "link_imported_shared_exe", "id": "^link_imported_shared_exe::@ba7eb709d0b48779c6c8$", "directorySource": "^imported$", + "projectName": "Imported", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -3699,6 +3796,7 @@ def gen_check_targets(c, g, inSource): "name": "link_imported_static_exe", "id": "^link_imported_static_exe::@ba7eb709d0b48779c6c8$", "directorySource": "^imported$", + "projectName": "Imported", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -3786,6 +3884,7 @@ def gen_check_targets(c, g, inSource): "name": "link_imported_object_exe", "id": "^link_imported_object_exe::@ba7eb709d0b48779c6c8$", "directorySource": "^imported$", + "projectName": "Imported", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -3873,6 +3972,7 @@ def gen_check_targets(c, g, inSource): "name": "link_imported_interface_exe", "id": "^link_imported_interface_exe::@ba7eb709d0b48779c6c8$", "directorySource": "^imported$", + "projectName": "Imported", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -3960,6 +4060,7 @@ def gen_check_targets(c, g, inSource): "name": "ALL_BUILD", "id": "^ALL_BUILD::@c11385ffed57b860da63$", "directorySource": "^custom$", + "projectName": "Custom", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -4038,6 +4139,7 @@ def gen_check_targets(c, g, inSource): "name": "ZERO_CHECK", "id": "^ZERO_CHECK::@c11385ffed57b860da63$", "directorySource": "^custom$", + "projectName": "Custom", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -4107,6 +4209,7 @@ def gen_check_targets(c, g, inSource): "name": "custom_tgt", "id": "^custom_tgt::@c11385ffed57b860da63$", "directorySource": "^custom$", + "projectName": "Custom", "type": "UTILITY", "isGeneratorProvided": None, "sources": [ @@ -4193,6 +4296,7 @@ def gen_check_targets(c, g, inSource): "name": "custom_exe", "id": "^custom_exe::@c11385ffed57b860da63$", "directorySource": "^custom$", + "projectName": "Custom", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -4297,6 +4401,7 @@ def gen_check_targets(c, g, inSource): "name": "ALL_BUILD", "id": "^ALL_BUILD::@[0-9a-f]+$", "directorySource": "^.*/Tests/RunCMake/FileAPIExternalSource$", + "projectName": "External", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -4375,6 +4480,7 @@ def gen_check_targets(c, g, inSource): "name": "ZERO_CHECK", "id": "^ZERO_CHECK::@[0-9a-f]+$", "directorySource": "^.*/Tests/RunCMake/FileAPIExternalSource$", + "projectName": "External", "type": "UTILITY", "isGeneratorProvided": True, "sources": [ @@ -4444,6 +4550,7 @@ def gen_check_targets(c, g, inSource): "name": "generated_exe", "id": "^generated_exe::@[0-9a-f]+$", "directorySource": "^.*/Tests/RunCMake/FileAPIExternalSource$", + "projectName": "External", "type": "EXECUTABLE", "isGeneratorProvided": None, "sources": [ @@ -4772,11 +4879,159 @@ def check_targets(c, g, inSource): 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", "targets"] + 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): diff --git a/Tests/RunCMake/FileAPI/codemodel-v2.cmake b/Tests/RunCMake/FileAPI/codemodel-v2.cmake index dca1dd1..72073d5 100644 --- a/Tests/RunCMake/FileAPI/codemodel-v2.cmake +++ b/Tests/RunCMake/FileAPI/codemodel-v2.cmake @@ -20,6 +20,7 @@ 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) -- cgit v0.12