Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion libs/rtemodel/include/RteKernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,13 @@ class RteKernel
*/
void SetToolInfo(const XmlItem& attr) { m_toolInfo = attr; }

/**
* @brief read the latest available pack version and resolved PDSC file for each pack.
* @param Output map of pack ID to latest version and resolved PDSC file path
* @return true if at least one latest pack entry was found, otherwise false
*/
bool ReadPackLatestVerAndPath(std::map<std::string, std::pair<std::string, std::string>>& latestPacks) const;

protected:
/**
* @brief get local pdsc files, optionally filtered
Expand All @@ -330,9 +337,14 @@ class RteKernel
bool GetLocalPdscFiles(const XmlItem& attr, std::map<std::string, std::string, RtePackageComparator>& pdscMap) const;
/**
* @brief parses $CMSIS_PACK_ROOT/.Local/loacl_repository.pidx file
* @return pointer to "index" element if successful, nullptr otherwise
* @return pointer to "pindex" element if successful, nullptr otherwise
*/
XMLTreeElement* ParseLocalRepositoryIdx() const;
/**
* @brief parses $CMSIS_PACK_ROOT/.Web/index.pidx file
* @return pointer to "pindex" element if successful, nullptr otherwise
*/
XMLTreeElement* ParseWebRepositoryIdx() const;

/**
* @brief create an XMLTree object to parse XML files
Expand All @@ -354,6 +366,12 @@ class RteKernel
*/
RteKernel* GetThisKernel() const { return const_cast<RteKernel*>(this); }

/**
* @brief parses a repository index file
* @param absolute path to the repository index file
* @return pointer to "pindex" element if successful, nullptr otherwise
*/
XMLTreeElement* ParseRepositoryIdx(const std::string& indexPath) const;

// data
protected:
Expand Down
55 changes: 53 additions & 2 deletions libs/rtemodel/src/RteKernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,9 +610,17 @@ bool RteKernel::GetLocalPdscFiles(const XmlItem& attr, std::map<std::string, std

XMLTreeElement* RteKernel::ParseLocalRepositoryIdx() const
{
// Parse local repository index file
const string indexPath = GetCmsisPackRoot() + "/.Local/local_repository.pidx";
return ParseRepositoryIdx(GetCmsisPackRoot() + "/.Local/local_repository.pidx");
}

XMLTreeElement* RteKernel::ParseWebRepositoryIdx() const
{
return ParseRepositoryIdx(GetCmsisPackRoot() + "/.Web/index.pidx");
}

XMLTreeElement* RteKernel::ParseRepositoryIdx(const string& indexPath) const
{
// Parse local repository index file
if (!RteFsUtils::Exists(indexPath)) {
return nullptr;
}
Expand All @@ -632,6 +640,49 @@ XMLTreeElement* RteKernel::ParseLocalRepositoryIdx() const
return pIndexChild;
}

bool RteKernel::ReadPackLatestVerAndPath(map<string, pair<string, string>>& latestPacks) const {
// read latest public pack versions from /.Web/index.pidx and the corresponding latest Web PDSC file paths
unique_ptr<XMLTreeElement> webPIndexChild(ParseWebRepositoryIdx());
if (webPIndexChild) {
for (auto& child : webPIndexChild->GetChildren()) {
if (!child || child->GetTag() != "pdsc") {
continue;
}
const string& vendor = child->GetAttribute("vendor");
const string& name = child->GetAttribute("name");
const string& version = child->GetAttribute("version");
if (vendor.empty() || name.empty() || version.empty()) {
continue;
}
const string packId = vendor + "::" + name;
const string pdscFile = GetCmsisPackRoot() + "/.Web/" + vendor + "." + name + ".pdsc";
latestPacks[packId] = { version, RteFsUtils::Exists(pdscFile) ? pdscFile : string() };
}
}
// read effective PDSC files (installed + local). Override the current entry if the local version is newer than the web version
XmlItem attributes;
map<string, string, RtePackageComparator> effectivePdscMap;
if (GetEffectivePdscFilesAsMap(effectivePdscMap, true)) {
for (const auto& [_, localPdscFile] : effectivePdscMap) {
RtePackage* pack = LoadPack(localPdscFile);
if (!pack) {
continue;
}
const string& vendor = pack->GetVendorString();
const string& name = pack->GetName();
const string& version = pack->GetVersionString();
if (vendor.empty() || name.empty() || version.empty()) {
continue;
}
const string packId = vendor + "::" + name;
auto it = latestPacks.find(packId);
if (it == latestPacks.end() || VersionCmp::Compare(it->second.first, version) < 0) {
latestPacks[packId] = { version, localPdscFile };
}
}
}
return !latestPacks.empty();
}

unique_ptr<XMLTree> RteKernel::CreateUniqueXmlTree(IXmlItemBuilder* itemBuilder, const std::string& ext) const
{
Expand Down
8 changes: 4 additions & 4 deletions libs/rtemodel/test/src/RteChkTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ using namespace std;

TEST(RteChkTest, Summary) {

const string summary = "Collecting pdsc files 8 files found\n\
const string summary = "Collecting pdsc files 9 files found\n\
Parsing XML passed\n\
\n\
Constructing Model passed\n\
Expand All @@ -25,10 +25,10 @@ Cleaning XML data\n\
Validating Model passed\n\
\n\
Summary:\n\
Packs: 8\n\
Packs: 9\n\
Generic: 4\n\
DFP: 3\n\
BSP: 1\n\
BSP: 2\n\
\n\
Components: 61\n\
From generic packs: 36\n\
Expand All @@ -50,7 +50,7 @@ completed\n";
rteChk.AddFileDir(RteModelTestConfig::CMSIS_PACK_ROOT);
int res = rteChk.RunCheckRte();
EXPECT_EQ(res, 0);
EXPECT_EQ(rteChk.GetPackCount(), 8);
EXPECT_EQ(rteChk.GetPackCount(), 9);
EXPECT_EQ(rteChk.GetComponentCount(), 61);
EXPECT_EQ(rteChk.GetDeviceCount(), 10);
EXPECT_EQ(rteChk.GetBoardCount(), 15);
Expand Down
2 changes: 1 addition & 1 deletion libs/rtemodel/test/src/RteModelTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ TEST(RteModelTest, LoadPacks) {

list<string> files;
rteKernel.GetEffectivePdscFiles(files, false);
EXPECT_EQ(files.size(), 11);
EXPECT_EQ(files.size(), 12);

RteModel* rteModel = rteKernel.GetGlobalModel();
ASSERT_NE(rteModel, nullptr);
Expand Down
51 changes: 51 additions & 0 deletions test/packs/ARM/RteTestBoard/0.0.1/ARM.RteTestBoard.pdsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>

<package schemaVersion="1.3" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="PACK.xsd">
<name>RteTestBoard</name>
<description>Testing packages listing</description>
<vendor>ARM</vendor>

<releases>
<release version="0.0.1" date="2026-04-24">
Pre-initial version 0.0.1 for testing CheckPackVerCmd
</release>
</releases>

<requirements>
<packages>
<package vendor="ARM" name="RteTest_DFP" version="0.1.1:0.2.0"/>
</packages>
</requirements>

<boards>
<board name="RteTest board listing" vendor="Keil" revision="Rev.C">
<description>uVision Simulator</description>
<mountedDevice deviceIndex="0" Dvendor="ARM:82" Dname="RteTest_ARMCM0"/>
<compatibleDevice deviceIndex="0" Dvendor="ARM:82" Dname="RteTest_ARMCM3"/>
<compatibleDevice deviceIndex="0" Dvendor="ARM:82" Dname="RteTest_ARMCM4_NOFP"/>
<compatibleDevice deviceIndex="0" Dvendor="ARM:82" Dname="RteTest_ARMCM4_FP"/>
<algorithm name="Board/Flash/BoargAlgo1.FLM" start="0x00000000" size="0x00040000" default="1"/>
<algorithm name="Board/Flash/BoargAlgo2.FLM" start="0x00000000" size="0x00020000" default="0"/>
<memory name="BoardFLASH" access="rx" start="0x30000000" size="0x00040000" startup="1" default="1"/>
<memory name="BoardRAM" access="rwx" start="0x40000000" size="0x00020000" uninit="1" default="1"/>
</board>
<board name="RteTest NoMCU board" vendor="Keil">
<description>No device board</description>
<mountedDevice Dvendor="NO_VENDOR:0" Dname="NO_MCU"/>
<memory name="BoardFLASH" access="rx" start="0x30000000" size="0x00040000" startup="1" default="1"/>
<memory name="BoardRAM" access="rwx" start="0x40000000" size="0x00020000" uninit="1" default="1"/>
</board>
<board name="RteTest CM4 board" vendor="Keil" revision="Rev.C">
<description>uVision Simulator</description>
<book category="overview" name="https://www.keil.arm.com/boards/" title="Development boards for application prototyping"/>
<book category="other" name="Documents/README.md" title="Guide" public="true"/>
<mountedDevice deviceIndex="0" Dvendor="ARM:82" Dname="RteTest_ARMCM4_FP"/>
<compatibleDevice deviceIndex="0" Dvendor="ARM:82" Dname="RteTest_ARMCM4_NOFP"/>
<algorithm name="Board/Flash/BoargAlgo1.FLM" start="0x00000000" size="0x00040000" default="1"/>
<algorithm name="Board/Flash/BoargAlgo2.FLM" start="0x00000000" size="0x00020000" default="0"/>
<memory name="BoardFLASH" access="rx" start="0x30000000" size="0x00040000" startup="1" default="1"/>
<memory name="BoardRAM" access="rwx" start="0x40000000" size="0x00020000" default="1"/>
</board>
</boards>

</package>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CortexM4Device.FLM : not real flash algorithm
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CortexM4SubFamily.FLM : not real flash algorithm
1 change: 1 addition & 0 deletions test/packs/ARM/RteTestBoard/0.0.1/Documents/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Board documentation
6 changes: 6 additions & 0 deletions test/packs/ARM/RteTestBoard/0.1.0/ARM.RteTestBoard.pdsc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
<release version="0.1.0" date="2022-03-11">
Initial version
</release>
<release version="0.0.2" date="2026-04-24">
Pre-initial version 0.0.2 for testing CheckPackVerCmd
</release>
<release version="0.0.1" date="2026-04-24">
Pre-initial version 0.0.1 for testing CheckPackVerCmd
</release>
</releases>

<requirements>
Expand Down
1 change: 1 addition & 0 deletions tools/projmgr/include/ProjMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ class ProjMgr {
std::vector<ContextItem*> m_allContexts;
std::set<std::string> m_failedContext;

bool RunCheckPackVerCmd();
bool RunConfigure();
bool RunCodeGenerator();
bool RunListPacks();
Expand Down
18 changes: 18 additions & 0 deletions tools/projmgr/include/ProjMgrWorker.h
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,24 @@ class ProjMgrWorker {
*/
bool CheckMissingFiles();

/**
* @brief check selected packs against latest versions
* @param vector of output lines describing pack update status
* @param optional filter
* @return true if check completed successfully
*/
bool CheckPackVerAndCollectRelNotes(std::vector<std::string>& results, const std::string& filter = RteUtils::EMPTY_STRING);

/**
* @brief read release notes for versions newer than the current version and up to the latest version
* @param resolved path to the latest PDSC file
* @param version currently used by the project
* @param latest available version resolved for the latest pack or the .pidx file
* @param output list of collected release note strings for versions to be filled
* @return true if at least one matching release note was found, otherwise false
*/
bool ReadPackReleaseNotes(const std::string& pdscFile, const std::string& currentVersion, const std::string& latestVersion, std::vector<std::string>& releaseNotes);

/**
* @brief collect unused packs for each selected context
*/
Expand Down
29 changes: 29 additions & 0 deletions tools/projmgr/src/ProjMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ static constexpr const char* USAGE = "\n\
Usage:\n\
csolution <command> [<name>.csolution.yml] [options]\n\n\
Commands:\n\
check Check existing project for potential pack updates\n\
convert Convert user input *.yml files to *.cbuild.yml files\n\
list boards Print list of available board names\n\
list configs Print list of configuration files\n\
Expand Down Expand Up @@ -179,6 +180,7 @@ int ProjMgr::ParseCommandLine(int argc, char** argv) {
{"update-rte", { false, {context, contextSet, activeTargetSet, debug, load, quiet, schemaCheck, toolchain, verbose, frozenPacks}}},
{"convert", { false, {context, contextSet, activeTargetSet, debug, exportSuffix, load, quiet, schemaCheck, noUpdateRte, output, outputAlt, toolchain, verbose, frozenPacks, cbuildgen}}},
{"run", { false, {context, contextSet, activeTargetSet, debug, generator, load, quiet, schemaCheck, verbose, dryRun}}},
{"check", { false, {context, contextSet, activeTargetSet, debug, load, quiet, schemaCheck, verbose}}},
{"list packs", { true, {context, contextSet, activeTargetSet, debug, filter, load, missing, locked, quiet, schemaCheck, toolchain, verbose}}},
{"list boards", { true, {context, contextSet, activeTargetSet, debug, filter, load, quiet, schemaCheck, toolchain, verbose}}},
{"list devices", { true, {context, contextSet, activeTargetSet, debug, filter, load, quiet, schemaCheck, toolchain, verbose}}},
Expand Down Expand Up @@ -397,6 +399,10 @@ int ProjMgr::ProcessCommands() {
if (!m_rpcServer.Run()) {
return ErrorCode::ERROR;
}
} else if (m_command == "check") {
if (!RunCheckPackVerCmd()) {
return ErrorCode::ERROR;
}
} else {
ProjMgrLogger::Get().Error("<command> was not found");
return ErrorCode::ERROR;
Expand Down Expand Up @@ -1034,6 +1040,29 @@ bool ProjMgr::RunCodeGenerator(void) {
return true;
}

bool ProjMgr::RunCheckPackVerCmd(void) {
if (m_csolutionFile.empty()) {
ProjMgrLogger::Get().Error("input csolution.yml was not specified");
return false;
}
// Check input options
if (!PopulateContexts()) {
return false;
}
// Parse all input files and create contexts
if (!ParseAndValidateContexts()) {
return false;
}

vector<string> outputs;
const bool result = m_worker.CheckPackVerAndCollectRelNotes(outputs, m_filter);

for (const auto& line : outputs) {
ProjMgrLogger::out() << line << std::endl;
}
return result;
}

bool ProjMgr::RunListToolchains(void) {
if (!m_csolutionFile.empty()) {
// Parse all input files and create contexts
Expand Down
Loading
Loading