Skip to content

Commit

Permalink
[projmgr] Generate *.cbuild-set.yml listing selected contexts
Browse files Browse the repository at this point in the history
  • Loading branch information
grasci-arm authored Oct 9, 2023
1 parent 33b5949 commit c5728d5
Show file tree
Hide file tree
Showing 23 changed files with 436 additions and 11 deletions.
23 changes: 23 additions & 0 deletions tools/projmgr/include/ProjMgrParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,17 @@ struct ClayerItem {
GeneratorsItem generators;
};

/**
* @brief cbuildset item containing
* list of contexts,
* toochain used,
*/
struct CbuildSetItem {
std::string generatedBy;
std::vector<std::string> contexts;
std::string compiler;
};

/**
* @brief projmgr parser class for public interfacing
*/
Expand Down Expand Up @@ -448,6 +459,12 @@ class ProjMgrParser {
*/
bool ParseGenericClayer(const std::string& input, bool checkSchema);

/**
* @brief parse cbuild set file
* @param input path to *.cbuild-set.yml file
*/
bool ParseCbuildSet(const std::string& input);

/**
* @brief get cdefault
* @return cdefault item
Expand Down Expand Up @@ -478,9 +495,15 @@ class ProjMgrParser {
*/
std::map<std::string, ClayerItem>& GetGenericClayers(void);

/**
* @brief get cbuildset
* @return cbuildset item
*/
CbuildSetItem& GetCbuildSetItem(void);
protected:
CdefaultItem m_cdefault;
CsolutionItem m_csolution;
CbuildSetItem m_cbuildSet;
std::map<std::string, CprojectItem> m_cprojects;
std::map<std::string, ClayerItem> m_clayers;
std::map<std::string, ClayerItem> m_genericClayers;
Expand Down
9 changes: 8 additions & 1 deletion tools/projmgr/include/ProjMgrWorker.h
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,8 @@ class ProjMgrWorker {
*/
bool ParseContextSelection(
const std::vector<std::string>& contextSelection,
const std::string& contextReplace = RteUtils::EMPTY_STRING);
const std::string& contextReplace = RteUtils::EMPTY_STRING,
const bool checkCbuildSet = false);

/**
* @brief check if context is selected
Expand Down Expand Up @@ -605,6 +606,12 @@ class ProjMgrWorker {
*/
void PrintMissingFilters(void);

/**
* @brief get selected toolchain
* @return string selected toolchain
*/
std::string GetSelectedToochain(void);

protected:
ProjMgrParser* m_parser = nullptr;
ProjMgrKernel* m_kernel = nullptr;
Expand Down
7 changes: 7 additions & 0 deletions tools/projmgr/include/ProjMgrYamlEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ class ProjMgrYamlEmitter {
* @return true if executed successfully
*/
static bool GenerateCbuild(ContextItem* context, const RteGenerator* generator = nullptr);

/**
* @brief generate cbuild set file
* @param contexts vector with pointers to contexts
* @return true if executed successfully
*/
static bool GenerateCbuildSet(ProjMgrParser& parser, const std::vector<ContextItem*> contexts, const std::string& selectedCompiler);
};

#endif // PROJMGRYAMLEMITTER_H
9 changes: 9 additions & 0 deletions tools/projmgr/include/ProjMgrYamlParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ static constexpr const char* YAML_BUILDTYPES = "build-types";
static constexpr const char* YAML_CATEGORY = "category";
static constexpr const char* YAML_CBUILDS = "cbuilds";
static constexpr const char* YAML_CBUILD = "cbuild";
static constexpr const char* YAML_CBUILD_SET = "cbuild-set";
static constexpr const char* YAML_CDEFAULT = "cdefault";
static constexpr const char* YAML_CLAYERS = "clayers";
static constexpr const char* YAML_CLAYER = "clayer";
Expand Down Expand Up @@ -178,6 +179,13 @@ class ProjMgrYamlParser {
bool ParseClayer(const std::string& input, std::map<std::string,
ClayerItem>& clayers, bool checkSchema);

/**
* @brief parse cbuild-set
* @param input path to cbuild-set.yml file
* @param reference to store parsed cbuildset item
* @return true if executed successfully
*/
bool ParseCbuildSet(const std::string& input, CbuildSetItem& cbuildSet);
protected:
void ParseMisc(const YAML::Node& parent, std::vector<MiscItem>& misc);
void ParseDefine(const YAML::Node& parent, std::vector<std::string>& define);
Expand Down Expand Up @@ -211,6 +219,7 @@ class ProjMgrYamlParser {
bool ValidateCsolution(const std::string& input, const YAML::Node& root);
bool ValidateCproject(const std::string& input, const YAML::Node& root);
bool ValidateClayer(const std::string& input, const YAML::Node& root);
bool ValidateCbuildSet(const std::string& input, const YAML::Node& root);
bool ValidateKeys(const std::string& input, const YAML::Node& parent, const std::set<std::string>& keys);
bool ValidateSequence(const std::string& input, const YAML::Node& parent, const std::string& seqKey);
bool ValidateMapping(const std::string& input, const YAML::Node& parent, const std::string& seqKey);
Expand Down
3 changes: 2 additions & 1 deletion tools/projmgr/include/ProjMgrYamlSchemaChecker.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class ProjMgrYamlSchemaChecker {
SOLUTION,
PROJECT,
LAYER,
BUILD
BUILD,
BUILDSET
};
/**
* @brief class constructor
Expand Down
13 changes: 13 additions & 0 deletions tools/projmgr/schemas/cbuildset.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/schemas/projmgr/2.1.0/tools/projmgr/schemas/cbuild-set.schema.json",
"title": "CMSIS cbuild-set",
"description": "defines a selected set of build configuration",
"version": "2.1.0",
"properties": {
"cbuild-set": {
"$ref": "./common.schema.json#/definitions/BuildSetDescType"
}
},
"required": [ "cbuild-set" ]
}
10 changes: 10 additions & 0 deletions tools/projmgr/schemas/common.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,16 @@
"CreatedInfoType": {
"type": "string",
"pattern": "^.*@\\d+\\.\\d+\\.\\d+(-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"
},
"BuildSetDescType": {
"type": "object",
"properties": {
"generated-by": { "type": "string", "description": "Tool name along with version information used to generate this application" },
"contexts": { "$ref": "#/definitions/ArrayOfStrings", "description": "List of fully specified contexts" },
"compiler": { "type": "string", "description": "Selection of compiler used" }
},
"additionalProperties": false,
"required": ["generated-by", "contexts"]
}
}
}
13 changes: 12 additions & 1 deletion tools/projmgr/src/ProjMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,10 @@ bool ProjMgr::RunConfigure(bool printConfig) {
if (!PopulateContexts()) {
return false;
}

bool checkCbuildSet = ((m_context.size() > 0) || (!m_selectedToolchain.empty()) ? false : true);
// Parse context selection
if (!m_worker.ParseContextSelection(m_context, m_contextReplacement)) {
if (!m_worker.ParseContextSelection(m_context, m_contextReplacement, checkCbuildSet)) {
return false;
}
// Get context pointers
Expand Down Expand Up @@ -469,6 +471,7 @@ bool ProjMgr::RunConfigure(bool printConfig) {
m_processedContexts.push_back(&contextItem);
}
}
m_selectedToolchain = m_worker.GetSelectedToochain();
// Print warnings for missing filters
m_worker.PrintMissingFilters();
if (m_verbose) {
Expand All @@ -491,6 +494,13 @@ bool ProjMgr::RunConfigure(bool printConfig) {
}
}

// Generate cbuild-set file
if (!m_processedContexts.empty()) {
if (!m_emitter.GenerateCbuildSet(m_parser, m_processedContexts, m_selectedToolchain)) {
return false;
}
}

return !error;
}

Expand Down Expand Up @@ -526,6 +536,7 @@ bool ProjMgr::RunConvert(void) {
return false;
}
}

return !error;
}

Expand Down
9 changes: 9 additions & 0 deletions tools/projmgr/src/ProjMgrParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ bool ProjMgrParser::ParseGenericClayer(const string& input, bool checkSchema) {
return ProjMgrYamlParser().ParseClayer(input, m_genericClayers, checkSchema);
}

bool ProjMgrParser::ParseCbuildSet(const string& input) {
// Parse cbuild-set file
return ProjMgrYamlParser().ParseCbuildSet(input, m_cbuildSet);
}

CdefaultItem& ProjMgrParser::GetCdefault(void) {
return m_cdefault;
}
Expand All @@ -68,3 +73,7 @@ map<string, ClayerItem>& ProjMgrParser::GetClayers(void) {
map<string, ClayerItem>& ProjMgrParser::GetGenericClayers(void) {
return m_genericClayers;
}

CbuildSetItem& ProjMgrParser::GetCbuildSetItem(void) {
return m_cbuildSet;
}
30 changes: 24 additions & 6 deletions tools/projmgr/src/ProjMgrWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3511,15 +3511,29 @@ bool ProjMgrWorker::ProcessSequencesRelatives(ContextItem& context, BuildType& b
return true;
}

bool ProjMgrWorker::ParseContextSelection(const vector<string>& contextSelection, const string& contextReplace) {
bool ProjMgrWorker::ParseContextSelection(const vector<string>& contextSelection,
const string& contextReplace, const bool checkCbuildSet) {
vector<string> contexts;
ListContexts(contexts);
const auto& filterError = ProjMgrUtils::GetSelectedContexts(m_selectedContexts, contexts, contextSelection);
if (filterError) {
ProjMgrLogger::Error(filterError.m_errMsg);
return false;
}

auto csolutionItem = m_parser->GetCsolution();
string cbuildSetFile = csolutionItem.directory + "/" + csolutionItem.name + ".cbuild-set.yml";
if (checkCbuildSet && RteFsUtils::Exists(cbuildSetFile)) {
if (!m_parser->ParseCbuildSet(cbuildSetFile)) {
return false;
}
const auto& cbuildSetItem = m_parser->GetCbuildSetItem();
m_selectedContexts = cbuildSetItem.contexts;
m_selectedToolchain = cbuildSetItem.compiler;
}
else {
const auto& filterError = ProjMgrUtils::GetSelectedContexts(
m_selectedContexts, contexts, contextSelection);
if (filterError) {
ProjMgrLogger::Error(filterError.m_errMsg);
return false;
}
}
auto selectedContexts = m_selectedContexts;
if (contextReplace != RteUtils::EMPTY_STRING) {
const auto& replaceError = ProjMgrUtils::ReplaceContexts(m_selectedContexts, contexts, contextReplace);
Expand Down Expand Up @@ -3923,3 +3937,7 @@ bool ProjMgrWorker::ListConfigFiles(vector<string>& configFiles) {
}
return true;
}

std::string ProjMgrWorker::GetSelectedToochain(void) {
return m_selectedToolchain;
}
48 changes: 47 additions & 1 deletion tools/projmgr/src/ProjMgrYamlEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class ProjMgrYamlBase {
class ProjMgrYamlCbuild : public ProjMgrYamlBase {
private:
friend class ProjMgrYamlEmitter;
ProjMgrYamlCbuild(YAML::Node node, const vector<ContextItem*> processedContexts, const string& selectedCompiler);
ProjMgrYamlCbuild(YAML::Node node, const ContextItem* context, const RteGenerator* generator);
void SetContextNode(YAML::Node node, const ContextItem* context);
void SetComponentsNode(YAML::Node node, const ContextItem* context);
Expand Down Expand Up @@ -134,6 +135,22 @@ ProjMgrYamlCbuild::ProjMgrYamlCbuild(YAML::Node node, const ContextItem* context
}
}

ProjMgrYamlCbuild::ProjMgrYamlCbuild(YAML::Node node,
const vector<ContextItem*> processedContexts, const string& selectedCompiler)
{
vector<string> contexts;
for (const auto& context : processedContexts) {
if (context) {
contexts.push_back(context->name);
}
}
SetNodeValue(node[YAML_GENERATED_BY], ORIGINAL_FILENAME + string(" version ") + VERSION_STRING);
SetNodeValue(node[YAML_CONTEXTS], contexts);
if (!selectedCompiler.empty()) {
SetNodeValue(node[YAML_COMPILER], selectedCompiler);
}
}

void ProjMgrYamlCbuild::SetContextNode(YAML::Node contextNode, const ContextItem* context) {
SetNodeValue(contextNode[YAML_GENERATED_BY], ORIGINAL_FILENAME + string(" version ") + VERSION_STRING);

Expand Down Expand Up @@ -414,7 +431,6 @@ void ProjMgrYamlCbuild::SetLicenseInfoNode(YAML::Node node, const ContextItem* c
}
}


void ProjMgrYamlCbuild::SetControlsNode(YAML::Node node, const ContextItem* context, const BuildType& controls) {
SetNodeValue(node[YAML_OPTIMIZE], controls.optimize);
SetNodeValue(node[YAML_DEBUG], controls.debug);
Expand Down Expand Up @@ -621,3 +637,33 @@ bool ProjMgrYamlEmitter::GenerateCbuild(ContextItem* context, const RteGenerator

return cbuild.WriteFile(rootNode, filename);
}

bool ProjMgrYamlEmitter::GenerateCbuildSet(ProjMgrParser& parser,
const std::vector<ContextItem*> contexts, const string& selectedCompiler)
{
const string& filename = parser.GetCsolution().directory + "/" +
parser.GetCsolution().name + ".cbuild-set.yml";

YAML::Node rootNode;
ProjMgrYamlCbuild cbuild(rootNode[YAML_CBUILD_SET], contexts, selectedCompiler);

// Compare yaml contents
if (!cbuild.CompareFile(filename, rootNode)) {
ofstream fileStream(filename);
if (!fileStream) {
ProjMgrLogger::Error(filename, "file cannot be written");
return false;
}
YAML::Emitter emitter;
emitter << rootNode;
fileStream << emitter.c_str();
fileStream << endl;
fileStream << flush;
fileStream.close();
ProjMgrLogger::Info(filename, "file generated successfully");
}
else {
ProjMgrLogger::Info(filename, "file is already up-to-date");
}
return true;
}
45 changes: 45 additions & 0 deletions tools/projmgr/src/ProjMgrYamlParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,31 @@ bool ProjMgrYamlParser::ParseClayer(const string& input,
return true;
}

bool ProjMgrYamlParser::ParseCbuildSet(const string& input, CbuildSetItem& cbuildSet) {
// Validate file schema
if (!ProjMgrYamlSchemaChecker().Validate(
input, ProjMgrYamlSchemaChecker::FileType::BUILDSET)) {
return false;
}

try {
const YAML::Node& root = YAML::LoadFile(input);
if (!ValidateCbuildSet(input, root)) {
return false;
}

const YAML::Node& cbuildSetNode = root[YAML_CBUILD_SET];
ParseString(cbuildSetNode, YAML_GENERATED_BY, cbuildSet.generatedBy);
ParseVector(cbuildSetNode, YAML_CONTEXTS, cbuildSet.contexts);
ParseString(cbuildSetNode, YAML_COMPILER, cbuildSet.compiler);
}
catch (YAML::Exception& e) {
ProjMgrLogger::Error(input, e.mark.line + 1, e.mark.column + 1, e.msg);
return false;
}
return true;
}

// EnsurePortability checks the presence of backslash, case inconsistency and absolute path
// It clears the string 'value' when it is an absolute path
void ProjMgrYamlParser::EnsurePortability(const string& file, const YAML::Mark& mark, const string& key, string& value, bool checkExist) {
Expand Down Expand Up @@ -863,6 +888,12 @@ const set<string> layerKeys = {
YAML_GENERATORS,
};

const set<string> cbuildSetKeys = {
YAML_GENERATED_BY,
YAML_CONTEXTS,
YAML_COMPILER,
};

const set<string> targetTypeKeys = {
YAML_TYPE,
YAML_DEVICE,
Expand Down Expand Up @@ -1109,6 +1140,20 @@ bool ProjMgrYamlParser::ValidateClayer(const string& input, const YAML::Node& ro
return true;
}

bool ProjMgrYamlParser::ValidateCbuildSet(const string& input, const YAML::Node& root) {
const set<string> rootKeys = {
YAML_CBUILD_SET,
};
if (!ValidateKeys(input, root, rootKeys)) {
return false;
}
const YAML::Node& contextSetNode = root[YAML_CBUILD_SET];
if (!ValidateKeys(input, contextSetNode, cbuildSetKeys)) {
return false;
}
return true;
}

bool ProjMgrYamlParser::ValidateKeys(const string& input, const YAML::Node& parent, const set<string>& keys) {
bool valid = true;
for (const auto& item : parent) {
Expand Down
Loading

0 comments on commit c5728d5

Please sign in to comment.