Skip to content

Commit 2e8d330

Browse files
authored
[projmgr] Add RPC method DiscoverLayers
1 parent 4d190c6 commit 2e8d330

File tree

12 files changed

+468
-130
lines changed

12 files changed

+468
-130
lines changed

tools/projmgr/include/ProjMgr.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ class ProjMgr {
7070
*/
7171
bool LoadSolution(const std::string& csolution, const std::string& activeTargetSet);
7272

73+
/**
74+
* @brief setup contexts
75+
* @param path to <solution>.csolution.yml file
76+
* @param active target set in the format <target-type>[@<set>]
77+
* @return processing status
78+
*/
79+
bool SetupContexts(const std::string& csolution, const std::string& activeTargetSet);
80+
7381
/**
7482
* @brief convert solution and generate yml files
7583
* @param path to <solution>.csolution.yml file

tools/projmgr/include/ProjMgrWorker.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,42 @@ struct DebuggerType {
367367
CustomItem custom;
368368
};
369369

370+
/**
371+
* @brief settings type containing
372+
* connection set
373+
*/
374+
struct SettingsType {
375+
std::string set;
376+
};
377+
378+
/**
379+
* @brief layer variable type containing
380+
* variable name
381+
* clayer path
382+
* brief description
383+
* list of connection sets
384+
* directory path that contains the layer (from PDSC)
385+
* clayer path relative to directory path (from PDSC)
386+
* proposed destination directory for the layer (from PDSC)
387+
*/
388+
struct LayerVariable {
389+
std::string name;
390+
std::string clayer;
391+
std::string description;
392+
std::vector<SettingsType> settings;
393+
std::string path;
394+
std::string file;
395+
std::string copyTo;
396+
};
397+
398+
/**
399+
* @brief variables configuration type containing
400+
* list of layer variables
401+
*/
402+
struct VariablesConfiguration {
403+
std::vector<LayerVariable> variables;
404+
};
405+
370406
/**
371407
* @brief project context item containing
372408
* pointer to csolution,
@@ -431,6 +467,7 @@ struct DebuggerType {
431467
* image only flag
432468
* west options
433469
* west on flag
470+
* layer variables configurations
434471
*/
435472
struct ContextItem {
436473
CdefaultItem* cdefault = nullptr;
@@ -502,6 +539,7 @@ struct ContextItem {
502539
bool imageOnly = false;
503540
WestDesc west;
504541
bool westOn = false;
542+
std::vector<VariablesConfiguration> variablesConfigurations;
505543
};
506544

507545
/**
@@ -1051,6 +1089,18 @@ class ProjMgrWorker {
10511089
*/
10521090
bool IsLibOnly(const std::vector<ContextItem*>& contexts);
10531091

1092+
/**
1093+
* @brief get processed contexts
1094+
* @return reference to vector with context items
1095+
*/
1096+
const std::vector<ContextItem*>& GetProcessedContexts(void);
1097+
1098+
/**
1099+
* @brief elaborate possible variables configurations according to compatible layers
1100+
* @return true if there are configurations available
1101+
*/
1102+
bool ElaborateVariablesConfigurations();
1103+
10541104
/**
10551105
* @brief clear worker members for reloading a solution
10561106
* @return true if there is no error
@@ -1094,6 +1144,7 @@ class ProjMgrWorker {
10941144
std::map<std::string, ContextItem> m_contexts;
10951145
std::map<std::string, std::set<std::string>> m_contextErrMap;
10961146
std::vector<std::string> m_selectedContexts;
1147+
std::vector<ContextItem*> m_processedContexts;
10971148
std::string m_outputDir;
10981149
std::string m_packRoot;
10991150
std::string m_compilerRoot;

tools/projmgr/src/ProjMgr.cpp

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1104,22 +1104,11 @@ bool ProjMgr::RunListLayers(void) {
11041104
// Step4: Run only when --update-idx flag is used
11051105
// Update the cbuild-idx.yml file with layer information
11061106
if (m_updateIdx) {
1107-
map<string, ContextItem>* contexts = nullptr;
1108-
m_worker.GetContexts(contexts);
1109-
1110-
// Check if contexts were properly retrieved
1111-
if (contexts == nullptr) {
1112-
return false;
1113-
}
1114-
11151107
// Generate Cbuild index
1116-
m_processedContexts.clear();
1117-
for (auto& contextName : m_worker.GetSelectedContexts()) {
1118-
auto& contextItem = (*contexts)[contextName];
1119-
m_processedContexts.push_back(&contextItem);
1120-
}
1121-
if (!m_processedContexts.empty()) {
1122-
if (!m_emitter.GenerateCbuildIndex(m_processedContexts,
1108+
const auto& processedContexts = m_worker.GetProcessedContexts();
1109+
if (!processedContexts.empty()) {
1110+
m_worker.ElaborateVariablesConfigurations();
1111+
if (!m_emitter.GenerateCbuildIndex(processedContexts,
11231112
m_failedContext, map<string, ExecutesItem>())) {
11241113
return false;
11251114
}
@@ -1301,10 +1290,11 @@ void ProjMgr::InitSolution(const std::string& csolution, const std::string& acti
13011290
m_contextSet = true;
13021291
} else {
13031292
m_activeTargetSet = activeTargetSet;
1293+
m_contextSet = false;
13041294
}
13051295
}
13061296

1307-
bool ProjMgr::LoadSolution(const std::string& csolution, const std::string& activeTargetSet) {
1297+
bool ProjMgr::SetupContexts(const std::string& csolution, const std::string& activeTargetSet) {
13081298

13091299
InitSolution(csolution, activeTargetSet, false);
13101300

@@ -1314,6 +1304,14 @@ bool ProjMgr::LoadSolution(const std::string& csolution, const std::string& acti
13141304
if (!ParseAndValidateContexts()) {
13151305
return false;
13161306
}
1307+
return true;
1308+
}
1309+
1310+
bool ProjMgr::LoadSolution(const std::string& csolution, const std::string& activeTargetSet) {
1311+
1312+
if (!SetupContexts(csolution, activeTargetSet)) {
1313+
return false;
1314+
}
13171315
if (!ProcessContexts()) {
13181316
return false;
13191317
}

tools/projmgr/src/ProjMgrCbuildIdx.cpp

Lines changed: 23 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class ProjMgrCbuildIdx : public ProjMgrCbuildBase {
2222
const map<string, ExecutesItem>& executes);
2323
private:
2424
void SetExecutesNode(YAML::Node node, const map<string, ExecutesItem>& executes, const string& base, const string& ref);
25-
void SetVariablesNode(YAML::Node node, ProjMgrParser* parser, const ContextItem* context, const map<string, map<string, set<const ConnectItem*>>>& layerTypes);
25+
void SetVariablesNode(YAML::Node node, ProjMgrParser* parser, const ContextItem* context, const VariablesConfiguration& configuration);
2626
};
2727

2828
ProjMgrCbuildIdx::ProjMgrCbuildIdx(YAML::Node node,
@@ -64,37 +64,17 @@ ProjMgrCbuildIdx::ProjMgrCbuildIdx(YAML::Node node,
6464
}
6565

6666
// Collect layer connection info specific to each target
67-
if (context->validConnections.size() > 0) {
67+
if (!context->variablesConfigurations.empty()) {
6868
configTargets.push_back(context->type.target);
69-
map<int, map<string, map<string, set<const ConnectItem*>>>> configurations;
70-
int index = 0;
71-
for (const auto& combination : context->validConnections) {
72-
index++;
73-
for (const auto& item : combination) {
74-
if (item.type.empty())
75-
continue;
76-
for (const auto& [type, _] : context->compatibleLayers) {
77-
// add all required layer types, including discarded optionals
78-
configurations[index][type].insert({});
79-
}
80-
for (const auto& connect : item.connections) {
81-
configurations[index][item.type][item.filename].insert(connect);
82-
}
83-
}
84-
}
85-
86-
// Process connection info and generate nodes
87-
if (configurations.size() > 0) {
88-
YAML::Node targetTypeNode;
89-
SetNodeValue(targetTypeNode[YAML_TARGETTYPE], context->type.target);
90-
for (const auto& [index, types] : configurations) {
91-
YAML::Node configurationsNode;
92-
configurationsNode[YAML_CONFIGURATION] = YAML::Null;
93-
SetVariablesNode(configurationsNode[YAML_VARIABLES], parser, context, types);
94-
targetTypeNode[YAML_TARGET_CONFIGURATIONS].push_back(configurationsNode);
95-
}
96-
node[YAML_CONFIGURATIONS].push_back(targetTypeNode);
69+
YAML::Node targetTypeNode;
70+
SetNodeValue(targetTypeNode[YAML_TARGETTYPE], context->type.target);
71+
for (const auto& configuration : context->variablesConfigurations) {
72+
YAML::Node configurationsNode;
73+
configurationsNode[YAML_CONFIGURATION] = YAML::Null;
74+
SetVariablesNode(configurationsNode[YAML_VARIABLES], parser, context, configuration);
75+
targetTypeNode[YAML_TARGET_CONFIGURATIONS].push_back(configurationsNode);
9776
}
77+
node[YAML_CONFIGURATIONS].push_back(targetTypeNode);
9878
}
9979
}
10080

@@ -206,53 +186,22 @@ ProjMgrCbuildIdx::ProjMgrCbuildIdx(YAML::Node node,
206186
}
207187

208188
void ProjMgrCbuildIdx::SetVariablesNode(YAML::Node node, ProjMgrParser* parser, const ContextItem* context,
209-
const map<string, map<string, set<const ConnectItem*>>>& layerTypes) {
210-
for (const auto& [type, filenames] : layerTypes) {
211-
if (type.empty()) {
212-
continue;
213-
}
189+
const VariablesConfiguration& configuration) {
190+
for (const auto& variable : configuration.variables) {
214191
YAML::Node layerNode;
215-
string layerFile;
216-
const string layerId = context->layerVariables.find(type) != context->layerVariables.end() ?
217-
context->layerVariables.at(type) : type + "-Layer";
218-
if (filenames.empty()) {
219-
layerNode[layerId] = "";
192+
if (variable.clayer.empty()) {
193+
layerNode[variable.name] = "";
220194
}
221-
for (const auto& [filename, options] : filenames) {
222-
string packRoot = ProjMgrKernel::Get()->GetCmsisPackRoot();
223-
layerFile = filename;
224-
RteFsUtils::NormalizePath(layerFile);
225-
layerFile = RteFsUtils::MakePathCanonical(layerFile);
226-
// Replace with ${CMSIS_PACK_ROOT} or $SolutionDir()$ depending on the detected path
227-
size_t index = layerFile.find(packRoot);
228-
if (index != string::npos) {
229-
layerFile.replace(index, packRoot.length(), "${CMSIS_PACK_ROOT}");
230-
}
231-
else {
232-
string relPath = RteFsUtils::RelativePath(filename, context->csolution->directory);
233-
if (!relPath.empty()) {
234-
layerFile = "$" + string(RteConstants::AS_SOLUTION_DIR_BR) + "$/" + RteFsUtils::LexicallyNormal(relPath);
235-
}
236-
}
237-
SetNodeValue(layerNode[layerId], layerFile);
238-
if (parser->GetGenericClayers().find(filename) != parser->GetGenericClayers().end()) {
239-
const auto& clayer = parser->GetGenericClayers().at(filename);
240-
SetNodeValue(layerNode[YAML_DESCRIPTION], clayer.description);
241-
}
242-
for (const auto& connect : options) {
243-
if (!connect->set.empty()) {
244-
YAML::Node setNode;
245-
SetNodeValue(setNode[YAML_SET], connect->set + " (" + connect->connect + (connect->info.empty() ? "" : " - " + connect->info) + ")");
246-
layerNode[YAML_SETTINGS].push_back(setNode);
247-
}
248-
}
249-
if (context->packLayers.find(filename) != context->packLayers.end()) {
250-
const auto& clayer = context->packLayers.at(filename);
251-
SetNodeValue(layerNode[YAML_PATH], clayer->GetOriginalAbsolutePath(clayer->GetPathString()));
252-
SetNodeValue(layerNode[YAML_FILE], clayer->GetFileString());
253-
SetNodeValue(layerNode[YAML_COPY_TO], clayer->GetCopyToString());
254-
}
195+
SetNodeValue(layerNode[variable.name], variable.clayer);
196+
SetNodeValue(layerNode[YAML_DESCRIPTION], variable.description);
197+
for (const auto& setting : variable.settings) {
198+
YAML::Node setNode;
199+
SetNodeValue(setNode[YAML_SET], setting.set);
200+
layerNode[YAML_SETTINGS].push_back(setNode);
255201
}
202+
SetNodeValue(layerNode[YAML_PATH], variable.path);
203+
SetNodeValue(layerNode[YAML_FILE], variable.file);
204+
SetNodeValue(layerNode[YAML_COPY_TO], variable.copyTo);
256205
node.push_back(layerNode);
257206
}
258207
}

tools/projmgr/src/ProjMgrRpcServer.cpp

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class RpcHandler : public RpcMethods {
9797
RpcArgs::LogMessages GetLogMessages(void) override;
9898
RpcArgs::DraftProjectsInfo GetDraftProjects(const RpcArgs::DraftProjectsFilter& filter) override;
9999
RpcArgs::ConvertSolutionResult ConvertSolution(const string& solution, const string& activeTarget, const bool& updateRte) override;
100+
RpcArgs::DiscoverLayersInfo DiscoverLayers(const string& solution, const string& activeTarget) override;
100101

101102
protected:
102103
enum Exception
@@ -126,6 +127,7 @@ class RpcHandler : public RpcMethods {
126127
RteTarget* GetActiveTarget(const string& context) const;
127128
RteComponentAggregate* GetComponentAggregate(const string& context, const string& id) const;
128129
bool SelectVariantOrVersion(const string& context, const string& id, const string& value, bool bVariant);
130+
bool CheckSolutionArg(string& solution, optional<string>& message) const;
129131
};
130132

131133
bool ProjMgrRpcServer::Run(void) {
@@ -169,6 +171,19 @@ bool ProjMgrRpcServer::Run(void) {
169171
return true;
170172
}
171173

174+
bool RpcHandler::CheckSolutionArg(string& solution, optional<string>& message) const {
175+
if (!regex_match(solution, regex(".*\\.csolution\\.(yml|yaml)"))) {
176+
message = solution + " is not a *.csolution.yml file";
177+
return false;
178+
}
179+
solution = RteFsUtils::MakePathCanonical(solution);
180+
if (!RteFsUtils::Exists(solution)) {
181+
message = solution + " file does not exist";
182+
return false;
183+
}
184+
return true;
185+
}
186+
172187
const ContextItem& RpcHandler::GetContext(const string& context) const {
173188
if (!m_solutionLoaded) {
174189
throw JsonRpcException(SOLUTION_NOT_LOADED, "a valid solution must be loaded before proceeding");
@@ -690,9 +705,8 @@ RpcArgs::DraftProjectsInfo RpcHandler::GetDraftProjects(const RpcArgs::DraftProj
690705

691706
RpcArgs::ConvertSolutionResult RpcHandler::ConvertSolution(const string& solution, const string& activeTarget, const bool& updateRte) {
692707
RpcArgs::ConvertSolutionResult result = {{ false }};
693-
const auto csolutionFile = RteFsUtils::MakePathCanonical(solution);
694-
if (!regex_match(csolutionFile, regex(".*\\.csolution\\.(yml|yaml)"))) {
695-
result.message = solution + " is not a *.csolution.yml file";
708+
string csolutionFile = solution;
709+
if (!CheckSolutionArg(csolutionFile, result.message)) {
696710
return result;
697711
}
698712
if (!m_manager.RunConvert(csolutionFile, activeTarget, updateRte) || !ProjMgrLogger::Get().GetErrors().empty()) {
@@ -712,4 +726,67 @@ RpcArgs::ConvertSolutionResult RpcHandler::ConvertSolution(const string& solutio
712726
return result;
713727
}
714728

729+
RpcArgs::DiscoverLayersInfo RpcHandler::DiscoverLayers(const string& solution, const string& activeTarget) {
730+
RpcArgs::DiscoverLayersInfo result = {{ false }};
731+
string csolutionFile = solution;
732+
if (!CheckSolutionArg(csolutionFile, result.message)) {
733+
return result;
734+
}
735+
if (!m_manager.SetupContexts(csolutionFile, activeTarget)) {
736+
result.message = "Setup of solution contexts failed";
737+
return result;
738+
}
739+
m_worker.SetUpCommand(true);
740+
StrVec layers;
741+
StrSet fails;
742+
if (!m_worker.ListLayers(layers, "", fails) || !m_worker.ElaborateVariablesConfigurations()) {
743+
result.message = "No compatible software layer found. Review required connections of the project";
744+
return result;
745+
} else {
746+
// retrieve valid configurations
747+
vector<RpcArgs::VariablesConfiguration> vcVec;
748+
const auto& processedContexts = m_worker.GetProcessedContexts();
749+
for (const auto& context : processedContexts) {
750+
if (!context->variablesConfigurations.empty()) {
751+
for (const auto& configuration : context->variablesConfigurations) {
752+
RpcArgs::VariablesConfiguration vc;
753+
vector<RpcArgs::LayerVariable> lvVec;
754+
for (const auto& variable : configuration.variables) {
755+
RpcArgs::LayerVariable lv = { variable.name, variable.clayer };
756+
vector<RpcArgs::SettingsType> settings;
757+
for (const auto& s : variable.settings) {
758+
if (!s.set.empty()) {
759+
settings.push_back(RpcArgs::SettingsType{s.set});
760+
}
761+
}
762+
if (!settings.empty()) {
763+
lv.settings = settings;
764+
}
765+
if (!variable.path.empty()) {
766+
lv.path = variable.path;
767+
}
768+
if (!variable.file.empty()) {
769+
lv.file = variable.file;
770+
}
771+
if (!variable.copyTo.empty()) {
772+
lv.copyTo = variable.copyTo;
773+
}
774+
lvVec.push_back(lv);
775+
}
776+
vc.variables = lvVec;
777+
vcVec.push_back(vc);
778+
}
779+
// break after first project context with possible variable configurations
780+
// solutions with undefined layer variables over multiple projects are currently not supported
781+
break;
782+
}
783+
}
784+
if (!vcVec.empty()) {
785+
result.configurations = vcVec;
786+
}
787+
result.success = true;
788+
return result;
789+
}
790+
}
791+
715792
// end of ProkMgrRpcServer.cpp

0 commit comments

Comments
 (0)