Skip to content

Commit

Permalink
[projmgr] Add --toolchain command line option
Browse files Browse the repository at this point in the history
  • Loading branch information
grasci-arm authored Feb 23, 2023
1 parent 682e65d commit 9a84abb
Show file tree
Hide file tree
Showing 66 changed files with 476 additions and 78 deletions.
1 change: 1 addition & 0 deletions tools/projmgr/include/ProjMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class ProjMgr {
std::string m_loadPacksPolicy;
std::string m_clayerSearchPath;
std::string m_export;
std::string m_selectedToolchain;
bool m_checkSchema;
bool m_missingPacks;
bool m_updateRteFiles;
Expand Down
2 changes: 1 addition & 1 deletion tools/projmgr/include/ProjMgrGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ProjMgrGenerator {
void GenerateCprjCreated(XMLTreeElement* element);
void GenerateCprjInfo(XMLTreeElement* element, const std::string& description);
void GenerateCprjPackages(XMLTreeElement* element, const ContextItem& context, bool nonLocked = false);
void GenerateCprjCompilers(XMLTreeElement* element, const ToolchainItem& toolchain);
void GenerateCprjCompilers(XMLTreeElement* element, const ContextItem& context);
void GenerateCprjTarget(XMLTreeElement* element, const ContextItem& context);
void GenerateCprjComponents(XMLTreeElement* element, const ContextItem& context, bool nonLocked = false);
void GenerateCprjGroups(XMLTreeElement* element, const std::vector<GroupNode>& groups, const std::string& compiler);
Expand Down
25 changes: 25 additions & 0 deletions tools/projmgr/include/ProjMgrUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,31 @@ class ProjMgrUtils {
*/
static int StringToInt(const std::string& value);

/**
* @brief expand compiler id the format <name>@[>=]<version> into name, minimum and maximum versions
* @param compiler id
* @param name reference to compiler name
* @param minVer reference to compiler minimum version
* @param maxVer reference to compiler maximum version
*/
static void ExpandCompilerId(const std::string& compiler, std::string& name, std::string& minVer, std::string& maxVer);

/**
* @brief check if compilers are compatible in the format <name>@[>=]<version>
* @param first compiler id
* @param second compiler id
* @return true if compilers are compatible, false otherwise
*/
static bool AreCompilersCompatible(const std::string& first, const std::string& second);

/**
* @brief get compilers version range intersection in the format <name>@[>=]<version>
* @param first compiler id
* @param second compiler id
* @param intersection reference to intersection id
*/
static void CompilersIntersect(const std::string& first, const std::string& second, std::string& intersection);

protected:
static std::string ConstructID(const std::vector<std::pair<const char*, const std::string&>>& elements);
};
Expand Down
8 changes: 8 additions & 0 deletions tools/projmgr/include/ProjMgrWorker.h
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,12 @@ class ProjMgrWorker {
*/
void SetEnvironmentVariables(const StrVec& envVars);

/**
* @brief set selected toolchain
* @param reference to selected toolchain
*/
void SetSelectedToolchain(const std::string& selectedToolchain);

/**
* @brief execute generator of a given context
* @param generator identifier
Expand Down Expand Up @@ -503,6 +509,7 @@ class ProjMgrWorker {
std::string m_outputDir;
std::string m_packRoot;
std::string m_compilerRoot;
std::string m_selectedToolchain;
LoadPacksPolicy m_loadPacksPolicy;
bool m_checkSchema;
bool m_verbose;
Expand All @@ -520,6 +527,7 @@ class ProjMgrWorker {
bool SetTargetAttributes(ContextItem& context, std::map<std::string, std::string>& attributes);
bool ProcessPrecedences(ContextItem& context);
bool ProcessPrecedence(StringCollection& item);
bool ProcessCompilerPrecedence(StringCollection& item);
bool ProcessDevice(ContextItem& context);
bool ProcessDevicePrecedence(StringCollection& item);
bool ProcessBoardPrecedence(StringCollection& item);
Expand Down
28 changes: 18 additions & 10 deletions tools/projmgr/src/ProjMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Usage:\n\
-l, --load arg Set policy for packs loading [latest|all|required]\n\
-L, --clayer-path arg Set search path for external clayers\n\
-e, --export arg Set suffix for exporting <context><suffix>.cprj retaining only specified versions\n\
-t, --toolchain arg Selection of the toolchain used in the project optionally with version\n\
-n, --no-check-schema Skip schema check\n\
-U, --no-update-rte Skip creation of RTE directory and files\n\
-v, --verbose Enable verbose messages\n\
Expand Down Expand Up @@ -113,29 +114,30 @@ int ProjMgr::RunProjMgr(int argc, char **argv, char** envp) {
cxxopts::Option verbose("v,verbose", "Enable verbose messages", cxxopts::value<bool>()->default_value("false"));
cxxopts::Option debug("d,debug", "Enable debug messages", cxxopts::value<bool>()->default_value("false"));
cxxopts::Option exportSuffix("e,export", "Set suffix for exporting <context><suffix>.cprj retaining only specified versions", cxxopts::value<string>());
cxxopts::Option toolchain("t,toolchain","Selection of the toolchain used in the project optionally with version", cxxopts::value<string>());
cxxopts::Option ymlOrder("yml-order", "Preserve order as specified in input yml", cxxopts::value<bool>()->default_value("false"));

// command options dictionary
map<string, vector<cxxopts::Option>> optionsDict = {
{"convert", {solution, context, output, load, verbose, debug, exportSuffix, schemaCheck, noUpdateRte}},
{"convert", {solution, context, output, load, verbose, debug, exportSuffix, toolchain, schemaCheck, noUpdateRte}},
{"run", {solution, generator, context, load, verbose, debug, schemaCheck}},
{"list packs", {solution, context, filter, missing, load, verbose, debug, schemaCheck}},
{"list boards", {solution, context, filter, load, verbose, debug, schemaCheck}},
{"list devices", {solution, context, filter, load, verbose, debug, schemaCheck}},
{"list components", {solution, context, filter, load, verbose, debug, schemaCheck}},
{"list dependencies", {solution, context, filter, load, verbose, debug, schemaCheck}},
{"list packs", {solution, context, filter, missing, load, verbose, debug, toolchain, schemaCheck}},
{"list boards", {solution, context, filter, load, verbose, debug, toolchain, schemaCheck}},
{"list devices", {solution, context, filter, load, verbose, debug, toolchain, schemaCheck}},
{"list components", {solution, context, filter, load, verbose, debug, toolchain, schemaCheck}},
{"list dependencies", {solution, context, filter, load, verbose, debug, toolchain, schemaCheck}},
{"list contexts", {solution, filter, verbose, debug, schemaCheck, ymlOrder}},
{"list generators", {solution, context, load, verbose, debug, schemaCheck}},
{"list layers", {solution, context, load, verbose, debug, schemaCheck, clayerSearchPath}},
{"list toolchains", {solution, verbose, debug,}},
{"list generators", {solution, context, load, verbose, debug, toolchain, schemaCheck}},
{"list layers", {solution, context, load, verbose, debug, toolchain, schemaCheck, clayerSearchPath}},
{"list toolchains", {solution, context, verbose, debug, toolchain}},
};

try {
options.add_options("", {
{"positional", "", cxxopts::value<vector<string>>()},
solution, context, filter, generator,
load, clayerSearchPath, missing, schemaCheck, noUpdateRte, output,
help, version, verbose, debug, exportSuffix, ymlOrder
help, version, verbose, debug, exportSuffix, toolchain, ymlOrder
});
options.parse_positional({ "positional" });

Expand Down Expand Up @@ -202,6 +204,9 @@ int ProjMgr::RunProjMgr(int argc, char **argv, char** envp) {
if (parseResult.count("export")) {
manager.m_export = parseResult["export"].as<string>();
}
if (parseResult.count("toolchain")) {
manager.m_selectedToolchain = parseResult["toolchain"].as<string>();
}
if (parseResult.count("output")) {
manager.m_outputDir = parseResult["output"].as<string>();
manager.m_outputDir = fs::path(manager.m_outputDir).generic_string();
Expand Down Expand Up @@ -325,6 +330,9 @@ bool ProjMgr::PopulateContexts(void) {
return false;
}

// Set output directory
m_worker.SetSelectedToolchain(m_selectedToolchain);

// Set output directory
m_worker.SetOutputDir(m_outputDir);

Expand Down
18 changes: 12 additions & 6 deletions tools/projmgr/src/ProjMgrGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ bool ProjMgrGenerator::GenerateCprj(ContextItem& context, const string& filename

// Compilers
if (compilersElement) {
GenerateCprjCompilers(compilersElement, context.toolchain);
GenerateCprjCompilers(compilersElement, context);
}

// Target
Expand Down Expand Up @@ -141,13 +141,19 @@ void ProjMgrGenerator::GenerateCprjPackages(XMLTreeElement* element, const Conte
}
}

void ProjMgrGenerator::GenerateCprjCompilers(XMLTreeElement* element, const ToolchainItem& toolchain) {
void ProjMgrGenerator::GenerateCprjCompilers(XMLTreeElement* element, const ContextItem& context) {
XMLTreeElement* compilerElement = element->CreateElement("compiler");
if (compilerElement) {
compilerElement->AddAttribute("name", toolchain.name);
if (!toolchain.version.empty()) {
compilerElement->AddAttribute("version", toolchain.version);
compilerElement->AddAttribute("name", context.toolchain.name);
// set minimum version according to registered/supported toolchain
string versionRange = context.toolchain.version;
// set maximum version according to solution requirements
string name, minVer, maxVer;
ProjMgrUtils::ExpandCompilerId(context.compiler, name, minVer, maxVer);
if (!maxVer.empty()) {
versionRange += ":" + maxVer;
}
compilerElement->AddAttribute("version", versionRange);
}
}

Expand Down Expand Up @@ -292,7 +298,7 @@ void ProjMgrGenerator::GenerateCprjMisc(XMLTreeElement* element, const MiscItem&
XMLTreeElement* flagsElement = element->CreateElement(flags.first);
if (flagsElement) {
flagsElement->AddAttribute("add", GetStringFromVector(flags.second, " "));
flagsElement->AddAttribute("compiler", misc.compiler);
flagsElement->AddAttribute("compiler", RteUtils::GetPrefix(misc.compiler, '@'));
}
}
}
Expand Down
66 changes: 66 additions & 0 deletions tools/projmgr/src/ProjMgrUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,69 @@ int ProjMgrUtils::StringToInt(const string& value) {
}
return intValue;
}


void ProjMgrUtils::ExpandCompilerId(const string& compiler, string& name, string& minVer, string& maxVer) {
name = RteUtils::GetPrefix(compiler, '@');
string version = RteUtils::GetSuffix(compiler, '@');
if (version.empty()) {
// any version
minVer = "0.0.0";
} else {
if (version.find(">=") != string::npos) {
// minimum version
minVer = version.substr(2);
} else {
// fixed version
minVer = maxVer = version;
}
}
}

bool ProjMgrUtils::AreCompilersCompatible(const string& first, const string& second) {
if (!first.empty() && !second.empty()) {
string firstName, firstMin, firstMax, secondName, secondMin, secondMax;
ExpandCompilerId(first, firstName, firstMin, firstMax);
ExpandCompilerId(second, secondName, secondMin, secondMax);
if ((firstName != secondName) ||
(!firstMax.empty() && !secondMin.empty() && (VersionCmp::Compare(firstMax, secondMin) < 0)) ||
(!secondMax.empty() && !firstMin.empty() && (VersionCmp::Compare(secondMax, firstMin) < 0))) {
return false;
}
}
return true;
}

void ProjMgrUtils::CompilersIntersect(const string& first, const string& second, string& intersection) {
if ((first.empty() && second.empty()) ||
!AreCompilersCompatible(first, second)) {
return;
}
string firstName, firstMin, firstMax, secondName, secondMin, secondMax;
ExpandCompilerId(first, firstName, firstMin, firstMax);
ExpandCompilerId(second, secondName, secondMin, secondMax);
// get intersection
if (firstMax.empty()) {
firstMax = secondMax;
}
if (secondMax.empty()) {
secondMax = firstMax;
}
const string& intersectName = firstName.empty() ? secondName : firstName;
const string& intersectMin = VersionCmp::Compare(firstMin, secondMin) < 0 ? secondMin : firstMin;
const string& intersectMax = VersionCmp::Compare(firstMax, secondMax) > 0 ? secondMax : firstMax;
if (intersectMax.empty()) {
if (VersionCmp::Compare(intersectMin, "0.0.0") == 0) {
// any version
intersection = intersectName;
} else {
// minimum version
intersection = intersectName + "@>=" + intersectMin;
}
} else {
if (intersectMin == intersectMax) {
// fixed version
intersection = intersectName + "@" + intersectMin;
}
}
}
32 changes: 22 additions & 10 deletions tools/projmgr/src/ProjMgrWorker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ void ProjMgrWorker::SetOutputDir(const std::string& outputDir) {
m_outputDir = outputDir;
}

void ProjMgrWorker::SetSelectedToolchain(const std::string& selectedToolchain) {
m_selectedToolchain = selectedToolchain;
}

void ProjMgrWorker::SetCheckSchema(bool checkSchema) {
m_checkSchema = checkSchema;
}
Expand Down Expand Up @@ -1601,6 +1605,19 @@ bool ProjMgrWorker::ProcessPrecedence(StringCollection& item) {
return true;
}

bool ProjMgrWorker::ProcessCompilerPrecedence(StringCollection& item) {
for (const auto& element : item.elements) {
if (!element->empty()) {
if (!ProjMgrUtils::AreCompilersCompatible(*item.assign, *element)) {
ProjMgrLogger::Error("redefinition from '" + *item.assign + "' into '" + *element + "' is not allowed");
return false;
}
ProjMgrUtils::CompilersIntersect(*item.assign, *element, *item.assign);
}
}
return true;
}

void ProjMgrWorker::MergeStringVector(StringVectorCollection& item) {
for (const auto& element : item.pair) {
AddStringItemsUniquely(*item.assign, *element.add);
Expand Down Expand Up @@ -1663,12 +1680,13 @@ bool ProjMgrWorker::ProcessPrecedences(ContextItem& context) {
&context.controls.csolution.compiler,
&context.controls.target.compiler,
&context.controls.build.compiler,
&m_selectedToolchain,
},
};
for (const auto& [_, clayer] : context.clayers) {
compiler.elements.push_back(&clayer->target.build.compiler);
}
if (!ProcessPrecedence(compiler)) {
if (!ProcessCompilerPrecedence(compiler)) {
return false;
}
if (!ProcessToolchain(context)) {
Expand Down Expand Up @@ -1825,7 +1843,7 @@ bool ProjMgrWorker::ProcessPrecedences(ContextItem& context) {
miscVec.push_back(&clayer.misc);
}
context.controls.processed.misc.push_back({});
context.controls.processed.misc.front().compiler = context.toolchain.name;
context.controls.processed.misc.front().compiler = context.compiler;
AddMiscUniquely(context.controls.processed.misc.front(), miscVec);

// Defines
Expand Down Expand Up @@ -2135,11 +2153,8 @@ bool ProjMgrWorker::CheckCompiler(const vector<string>& forCompiler, const strin
if (forCompiler.empty()) {
return true;
}
const ToolchainItem& selectedToolchain = GetToolchain(selectedCompiler);
for (const auto& compiler : forCompiler) {
const ToolchainItem& toolchain = GetToolchain(compiler);
if (toolchain.name == selectedToolchain.name &&
(toolchain.version.empty() || toolchain.version == selectedToolchain.version)) {
if (ProjMgrUtils::AreCompilersCompatible(compiler, selectedCompiler)) {
return true;
}
}
Expand Down Expand Up @@ -2425,9 +2440,6 @@ bool ProjMgrWorker::ListComponents(vector<string>& components, const string& fil
if (!ProcessPrecedences(context)) {
return false;
}
if (!ProcessToolchain(context)) {
return false;
}
if (!ProcessDevice(context)) {
return false;
}
Expand Down Expand Up @@ -2686,7 +2698,7 @@ void ProjMgrWorker::AddMiscUniquely(MiscItem& dst, vector<vector<MiscItem>*>& ve

void ProjMgrWorker::AddMiscUniquely(MiscItem& dst, vector<MiscItem>& vec) {
for (auto& src : vec) {
if (src.compiler.empty() || (src.compiler == dst.compiler)) {
if (ProjMgrUtils::AreCompilersCompatible(src.compiler, dst.compiler)) {
// Copy individual flags
AddStringItemsUniquely(dst.as, src.as);
AddStringItemsUniquely(dst.c, src.c);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ layer:
- DEF_LAYER1
add-path:
- path/to/layer1
compiler: [email protected]
compiler: AC6@>=6.18.0
misc:
- C:
- --layer1-flag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ layer:
- DEF_LAYER1
add-path:
- path/to/layer1
compiler: [email protected]
compiler: AC6@>=6.18.0
misc:
- C:
- --layer1-flag
Expand Down
2 changes: 1 addition & 1 deletion tools/projmgr/test/data/TestLayers/testlayers.cproject.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

project:
device: RteTest_ARMCM0
compiler: [email protected]
compiler: AC6@>=6.18.0

layers:
- layer: ./Layer1/layer1.clayer.yml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

project:
device: RteTest_ARMCM0
compiler: [email protected]
compiler: AC6@>=6.18.0

layers:
- layer: ./Layer1/layer1.clayer_invalid_schema.yml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

project:
device: :cm0_core0
compiler: [email protected]
compiler: AC6@>=6.18.0

layers:
- layer: ./Layer2/layer2.clayer_package_with_pname.yml
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/cproject.schema.json

project:
compiler: [email protected]
compiler: AC6@>=6.18.0
device: :cm0_core0

layers:
Expand Down
Loading

0 comments on commit 9a84abb

Please sign in to comment.