fileapi: Add cross-compiling emulator to codemodel-v2

Fixes: #25408
This commit is contained in:
Ralf Habacker 2023-11-11 15:35:21 +01:00 committed by Brad King
parent 2d0b7798db
commit 80a64c9ce5
15 changed files with 369 additions and 6 deletions

View File

@ -431,7 +431,7 @@ Version 1 does not exist to avoid confusion with that from
{
"kind": "codemodel",
"version": { "major": 2, "minor": 6 },
"version": { "major": 2, "minor": 7 },
"paths": {
"source": "/path/to/top-level-source-dir",
"build": "/path/to/top-level-build-dir"
@ -998,6 +998,32 @@ with members:
destination is available. The value is an unsigned integer 0-based
index into the ``backtraceGraph`` member's ``nodes`` array.
``launchers``
Optional member that is present on executable targets that have
at least one launcher specified by the project. The value is a
JSON array of entries corresponding to the specified launchers.
Each entry is a JSON object with members:
``command``
A string specifying the path to the launcher 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.
``arguments``
Optional member that is present when the launcher command has
arguments preceding the executable to be launched. The value
is a JSON array of strings representing the arguments.
``type``
A string specifying the type of launcher. The value is one of
the following:
``emulator``
An emulator for the target platform when cross-compiling.
See the :prop_tgt:`CROSSCOMPILING_EMULATOR` target property.
This field was added in codemodel version 2.7.
``link``
Optional member that is present for executables and shared library
targets that link into a runtime binary. The value is a JSON object

View File

@ -0,0 +1,7 @@
fileapi-exe-launcher
--------------------
* The :manual:`cmake-file-api(7)` "codemodel" version 2 ``version`` field has
been updated to 2.7.
* The :manual:`cmake-file-api(7)` "codemodel" version 2 "target" object gained
a new "launchers" field.

View File

@ -727,7 +727,7 @@ std::string cmFileAPI::NoSupportedVersion(
// The "codemodel" object kind.
// Update Help/manual/cmake-file-api.7.rst when updating this constant.
static unsigned int const CodeModelV2Minor = 6;
static unsigned int const CodeModelV2Minor = 7;
void cmFileAPI::BuildClientRequestCodeModel(
ClientRequest& r, std::vector<RequestVersion> const& versions)

View File

@ -41,10 +41,12 @@
#include "cmInstallSubdirectoryGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmLinkLineComputer.h" // IWYU pragma: keep
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmRange.h"
#include "cmSourceFile.h"
#include "cmSourceGroup.h"
#include "cmState.h"
@ -503,6 +505,8 @@ class Target
Json::Value DumpDependencies();
Json::Value DumpDependency(cmTargetDepend const& td);
Json::Value DumpFolder();
Json::Value DumpLauncher(const char* name, const char* type);
Json::Value DumpLaunchers();
public:
Target(cmGeneratorTarget* gt, std::string const& config);
@ -1223,6 +1227,13 @@ Json::Value Target::Dump()
target["archive"] = this->DumpArchive();
}
if (type == cmStateEnums::EXECUTABLE) {
Json::Value launchers = this->DumpLaunchers();
if (!launchers.empty()) {
target["launchers"] = std::move(launchers);
}
}
Json::Value dependencies = this->DumpDependencies();
if (!dependencies.empty()) {
target["dependencies"] = dependencies;
@ -2075,6 +2086,41 @@ Json::Value Target::DumpFolder()
}
return folder;
}
Json::Value Target::DumpLauncher(const char* name, const char* type)
{
cmValue property = this->GT->GetProperty(name);
Json::Value launcher;
if (property) {
cmList commandWithArgs{ *property };
std::string command(commandWithArgs[0]);
cmSystemTools::ConvertToUnixSlashes(command);
launcher = Json::objectValue;
launcher["command"] = RelativeIfUnder(this->TopSource, command);
launcher["type"] = type;
Json::Value args;
for (std::string const& arg : cmMakeRange(commandWithArgs).advance(1)) {
args.append(arg);
}
launcher["arguments"] = args;
}
return launcher;
}
Json::Value Target::DumpLaunchers()
{
Json::Value launchers;
bool allow =
this->GT->Makefile->GetDefinition("CMAKE_CROSSCOMPILING").IsOn();
Json::Value launcher;
if (allow) {
launcher = DumpLauncher("CROSSCOMPILING_EMULATOR", "emulator");
if (!launcher.empty()) {
launchers.append(launcher);
}
}
return launchers;
}
}
Json::Value cmFileAPICodemodelDump(cmFileAPI& fileAPI, unsigned long version)

View File

@ -1 +1 @@
^{"debugger":(true|false),"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":6}]},{"kind":"configureLog","version":\[{"major":1,"minor":0}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"tls":(true|false),"version":{.*}}$
^{"debugger":(true|false),"fileApi":{"requests":\[{"kind":"codemodel","version":\[{"major":2,"minor":7}]},{"kind":"configureLog","version":\[{"major":1,"minor":0}]},{"kind":"cache","version":\[{"major":2,"minor":0}]},{"kind":"cmakeFiles","version":\[{"major":1,"minor":0}]},{"kind":"toolchains","version":\[{"major":1,"minor":0}]}]},"generators":\[.*\],"serverMode":false,"tls":(true|false),"version":{.*}}$

View File

@ -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, 6, check_object_codemodel(g))
check_index_object(o[0], "codemodel", 2, 7, check_object_codemodel(g))
def check_backtrace(t, b, backtrace):
btg = t["backtraceGraph"]
@ -405,6 +405,27 @@ def check_target(c):
missing_exception=lambda e: "Install path: %s" % e["path"],
extra_exception=lambda a: "Install path: %s" % a["path"])
if "launchers" in expected:
if expected["launchers"] is not None:
expected_keys.append("launchers")
def check_launcher(actual, expected):
assert is_dict(actual)
launcher_keys = ["arguments", "command", "type"]
assert sorted(actual.keys()) == sorted(launcher_keys)
assert matches(actual["command"], expected["command"])
assert matches(actual["type"], expected["type"])
if expected["arguments"] is not None:
check_list_match(lambda a, e: matches(a, e),
actual["arguments"], expected["arguments"],
missing_exception=lambda e: "argument: %s" % e,
extra_exception=lambda a: "argument: %s" % actual["arguments"])
check_list_match(lambda a, e: matches(a["type"], e["type"]),
obj["launchers"], expected["launchers"],
check=check_launcher,
check_exception=lambda a, e: "launchers: %s" % a,
missing_exception=lambda e: "launchers: %s" % e,
extra_exception=lambda a: "launchers: %s" % a)
if expected["link"] is not None:
expected_keys.append("link")
assert is_dict(obj["link"])
@ -709,6 +730,7 @@ def gen_check_directories(c, g):
read_codemodel_json_data("directories/alias.json"),
read_codemodel_json_data("directories/custom.json"),
read_codemodel_json_data("directories/cxx.json"),
read_codemodel_json_data("directories/cxx.cross.json"),
read_codemodel_json_data("directories/imported.json"),
read_codemodel_json_data("directories/interface.json"),
read_codemodel_json_data("directories/object.json"),
@ -782,6 +804,8 @@ def gen_check_targets(c, g, inSource):
read_codemodel_json_data("targets/zero_check_cxx.json"),
read_codemodel_json_data("targets/cxx_lib.json"),
read_codemodel_json_data("targets/cxx_exe.json"),
read_codemodel_json_data("targets/cxx_exe_cross_emulator.json"),
read_codemodel_json_data("targets/cxx_exe_cross_emulator_args.json"),
read_codemodel_json_data("targets/cxx_standard_compile_feature_exe.json"),
read_codemodel_json_data("targets/cxx_standard_exe.json"),
read_codemodel_json_data("targets/cxx_shared_lib.json"),

View File

@ -0,0 +1,15 @@
{
"source": "^cxx/cross$",
"build": "^cxx/cross$",
"parentSource": "^cxx$",
"parentIndex": 2,
"childSources": null,
"targetIds": [
"^cxx_exe_cross_emulator::@ee4a268216d1f53c4e2e$",
"^cxx_exe_cross_emulator_args::@ee4a268216d1f53c4e2e$"
],
"projectName": "Cxx",
"minimumCMakeVersion": "3.13",
"hasInstallRule": null,
"installers": []
}

View File

@ -2,7 +2,9 @@
"source": "^cxx$",
"build": "^cxx$",
"parentSource": "^\\.$",
"childSources": null,
"childSources": [
"^cxx/cross$"
],
"targetIds": [
"^ALL_BUILD::@a56b12a3f5c0529fb296$",
"^ZERO_CHECK::@a56b12a3f5c0529fb296$",

View File

@ -3,13 +3,16 @@
"parentName": "codemodel-v2",
"childNames": null,
"directorySources": [
"^cxx$"
"^cxx$",
"^cxx/cross$"
],
"targetIds": [
"^ALL_BUILD::@a56b12a3f5c0529fb296$",
"^ZERO_CHECK::@a56b12a3f5c0529fb296$",
"^cxx_lib::@a56b12a3f5c0529fb296$",
"^cxx_exe::@a56b12a3f5c0529fb296$",
"^cxx_exe_cross_emulator::@ee4a268216d1f53c4e2e$",
"^cxx_exe_cross_emulator_args::@ee4a268216d1f53c4e2e$",
"^cxx_standard_compile_feature_exe::@a56b12a3f5c0529fb296$",
"^cxx_standard_exe::@a56b12a3f5c0529fb296$",
"^cxx_shared_lib::@a56b12a3f5c0529fb296$",

View File

@ -82,6 +82,14 @@
"id": "^cxx_exe::@a56b12a3f5c0529fb296$",
"backtrace": null
},
{
"id": "^cxx_exe_cross_emulator::@ee4a268216d1f53c4e2e$",
"backtrace": null
},
{
"id": "^cxx_exe_cross_emulator_args::@ee4a268216d1f53c4e2e$",
"backtrace": null
},
{
"id": "^cxx_standard_compile_feature_exe::@a56b12a3f5c0529fb296$",
"backtrace": null

View File

@ -122,6 +122,14 @@
"id": "^cxx_exe::@a56b12a3f5c0529fb296$",
"backtrace": null
},
{
"id": "^cxx_exe_cross_emulator::@ee4a268216d1f53c4e2e$",
"backtrace": null
},
{
"id": "^cxx_exe_cross_emulator_args::@ee4a268216d1f53c4e2e$",
"backtrace": null
},
{
"id": "^cxx_standard_compile_feature_exe::@a56b12a3f5c0529fb296$",
"backtrace": null

View File

@ -0,0 +1,106 @@
{
"name": "cxx_exe_cross_emulator",
"id": "^cxx_exe_cross_emulator::@ee4a268216d1f53c4e2e$",
"directorySource": "^cxx/cross$",
"projectName": "Cxx",
"type": "EXECUTABLE",
"isGeneratorProvided": null,
"fileSets": null,
"sources": [
{
"path": "^empty\\.cxx$",
"isGenerated": null,
"fileSetName": null,
"sourceGroupName": "Source Files",
"compileGroupLanguage": "CXX",
"backtrace": [
{
"file": "^cxx/cross/CMakeLists\\.txt$",
"line": 3,
"command": "add_executable",
"hasParent": true
},
{
"file": "^cxx/cross/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
]
}
],
"sourceGroups": [
{
"name": "Source Files",
"sourcePaths": [
"^empty\\.cxx$"
]
}
],
"compileGroups": [
{
"language": "CXX",
"sourcePaths": [
"^empty\\.cxx$"
],
"includes": null,
"frameworks": null,
"defines": null,
"compileCommandFragments": null
}
],
"backtrace": [
{
"file": "^cxx/cross/CMakeLists\\.txt$",
"line": 3,
"command": "add_executable",
"hasParent": true
},
{
"file": "^cxx/cross/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
],
"folder": null,
"nameOnDisk": "^cxx_exe_cross_emulator(\\.exe)?$",
"artifacts": [
{
"path": "^cxx/cross/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_exe_cross_emulator(\\.exe)?$",
"_dllExtra": false
},
{
"path": "^cxx/cross/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_exe_cross_emulator\\.pdb$",
"_dllExtra": true
}
],
"build": "^cxx/cross$",
"source": "^cxx/cross$",
"install": null,
"launchers" : [
{
"arguments" : null,
"command": "^no-such-emulator(\\.exe)?$",
"type" : "emulator"
}
],
"link": {
"language": "CXX",
"lto": null,
"commandFragments": [
{
"fragment" : ".*",
"role" : "flags",
"backtrace": null
}
]
},
"archive": null,
"dependencies": [
{
"id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
"backtrace": null
}
]
}

View File

@ -0,0 +1,109 @@
{
"name": "cxx_exe_cross_emulator_args",
"id": "^cxx_exe_cross_emulator_args::@ee4a268216d1f53c4e2e$",
"directorySource": "^cxx/cross$",
"projectName": "Cxx",
"type": "EXECUTABLE",
"isGeneratorProvided": null,
"fileSets": null,
"sources": [
{
"path": "^empty\\.cxx$",
"isGenerated": null,
"fileSetName": null,
"sourceGroupName": "Source Files",
"compileGroupLanguage": "CXX",
"backtrace": [
{
"file": "^cxx/cross/CMakeLists\\.txt$",
"line": 6,
"command": "add_executable",
"hasParent": true
},
{
"file": "^cxx/cross/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
]
}
],
"sourceGroups": [
{
"name": "Source Files",
"sourcePaths": [
"^empty\\.cxx$"
]
}
],
"compileGroups": [
{
"language": "CXX",
"sourcePaths": [
"^empty\\.cxx$"
],
"includes": null,
"frameworks": null,
"defines": null,
"compileCommandFragments": null
}
],
"backtrace": [
{
"file": "^cxx/cross/CMakeLists\\.txt$",
"line": 6,
"command": "add_executable",
"hasParent": true
},
{
"file": "^cxx/cross/CMakeLists\\.txt$",
"line": null,
"command": null,
"hasParent": false
}
],
"folder": null,
"nameOnDisk": "^cxx_exe_cross_emulator_args(\\.exe)?$",
"artifacts": [
{
"path": "^cxx/cross/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_exe_cross_emulator_args(\\.exe)?$",
"_dllExtra": false
},
{
"path": "^cxx/cross/((Debug|Release|RelWithDebInfo|MinSizeRel)/)?cxx_exe_cross_emulator_args\\.pdb$",
"_dllExtra": true
}
],
"build": "^cxx/cross$",
"source": "^cxx/cross$",
"install": null,
"launchers" : [
{
"arguments" : [
"arg1",
"arg2 with space"
],
"command": "^no-such-emulator(\\.exe)?$",
"type" : "emulator"
}
],
"link": {
"language": "CXX",
"lto": null,
"commandFragments": [
{
"fragment" : ".*",
"role" : "flags",
"backtrace": null
}
]
},
"archive": null,
"dependencies": [
{
"id": "^ZERO_CHECK::@6890427a1f51a3e7e1df$",
"backtrace": null
}
]
}

View File

@ -45,3 +45,5 @@ if(_rdeps)
FRAMEWORK DESTINATION fw
)
endif()
add_subdirectory(cross)

View File

@ -0,0 +1,7 @@
# Cross-compiling is normally global. Cover it without duplicating everything.
set(CMAKE_CROSSCOMPILING 1)
add_executable(cxx_exe_cross_emulator ../../empty.cxx)
set_property(TARGET cxx_exe_cross_emulator PROPERTY CROSSCOMPILING_EMULATOR no-such-emulator)
add_executable(cxx_exe_cross_emulator_args ../../empty.cxx)
set_property(TARGET cxx_exe_cross_emulator_args PROPERTY CROSSCOMPILING_EMULATOR "no-such-emulator;arg1;arg2 with space")