From ebcd874fadd75603d9c7efad7387d1486b896fc7 Mon Sep 17 00:00:00 2001 From: Evgueni Driouk Date: Fri, 2 Feb 2024 15:08:40 +0100 Subject: [PATCH 1/3] Support for external generators in RTE Model (#780) * Support for external generators in RTE Model read .generator.yml files make some common code accessible from different tools remove duplicated methods read generators.yml in RTE Model move ExecCommand to CrossPlatformUtils move constants to RteConstants move some utility methods to CollectionUtils rename RteFsUtils::CreateFile to RteFsUtils::CreateTextFile due to clash with Windows API --- .../include/CrossPlatformUtils.h | 7 + libs/crossplatform/src/CrossPlatformUtils.cpp | 24 ++ libs/crossplatform/test/src/UnitTests.cpp | 15 ++ libs/rtefsutils/include/RteFsUtils.h | 12 +- libs/rtefsutils/src/RteFsUtils.cpp | 28 ++- libs/rtefsutils/test/src/RteFsUtilsTest.cpp | 107 ++++---- libs/rtemodel/include/RteCallback.h | 4 +- libs/rtemodel/include/RteGenerator.h | 42 +++- libs/rtemodel/include/RteItem.h | 7 + libs/rtemodel/include/RteKernel.h | 38 ++- libs/rtemodel/src/RteCallback.cpp | 8 + libs/rtemodel/src/RteComponent.cpp | 2 +- libs/rtemodel/src/RteGenerator.cpp | 37 +-- libs/rtemodel/src/RteItem.cpp | 12 + libs/rtemodel/src/RteItemBuilder.cpp | 2 - libs/rtemodel/src/RteKernel.cpp | 55 +++++ libs/rtemodel/src/RteProject.cpp | 2 +- libs/rtemodel/test/src/RteModelTest.cpp | 2 +- libs/rteutils/CMakeLists.txt | 2 +- libs/rteutils/include/CollectionUtils.h | 110 +++++++++ libs/rteutils/include/RteConstants.h | 111 +++++++++ libs/rteutils/include/RteUtils.h | 39 ++- libs/rteutils/src/CollectionUtils.cpp | 39 +++ libs/rteutils/src/RteConstants.cpp | 60 +++++ libs/rteutils/src/RteUtils.cpp | 18 +- libs/rteutils/test/src/RteUtilsTest.cpp | 37 ++- libs/xmltree/include/XmlItem.h | 6 +- libs/xmltree/include/XmlTreeItem.h | 11 +- libs/xmltree/test/src/XmlTreeTest.cpp | 14 ++ libs/ymltree/test/YmlTreeTest.cpp | 4 +- tools/buildmgr/cbuild/include/CbuildUtils.h | 15 -- tools/buildmgr/cbuild/src/CbuildModel.cpp | 18 +- tools/buildmgr/cbuild/src/CbuildUtils.cpp | 26 -- .../cbuildgen/src/BuildSystemGenerator.cpp | 4 +- .../src/CBuildGenTestFixture.cpp | 8 +- .../src/CBuildGenTestFixture.h | 2 +- .../test/integrationtests/src/DebPkgTests.cpp | 8 +- .../src/BuildSystemGeneratorTests.cpp | 4 +- .../test/unittests/src/CbuildModelTests.cpp | 22 +- .../test/unittests/src/UtilsTests.cpp | 17 -- tools/packchk/src/PackChk.cpp | 2 +- .../test/integtests/src/PackChkIntegTests.cpp | 10 +- .../test/unittests/src/TestCheckFiles.cpp | 6 +- tools/packgen/include/PackGen.h | 8 - tools/packgen/src/PackGen.cpp | 34 +-- tools/projmgr/include/ProjMgrExtGenerator.h | 11 +- tools/projmgr/include/ProjMgrUtils.h | 202 +--------------- tools/projmgr/include/ProjMgrWorker.h | 1 - tools/projmgr/src/ProjMgr.cpp | 16 +- tools/projmgr/src/ProjMgrExtGenerator.cpp | 40 +-- tools/projmgr/src/ProjMgrGenerator.cpp | 10 +- tools/projmgr/src/ProjMgrUtils.cpp | 140 +---------- tools/projmgr/src/ProjMgrWorker.cpp | 228 +++++++++--------- tools/projmgr/src/ProjMgrYamlEmitter.cpp | 45 ++-- tools/projmgr/src/ProjMgrYamlParser.cpp | 2 +- .../test/src/ProjMgrGeneratorUnitTests.cpp | 2 +- tools/projmgr/test/src/ProjMgrTestEnv.cpp | 27 ++- tools/projmgr/test/src/ProjMgrTestEnv.h | 3 +- tools/projmgr/test/src/ProjMgrUnitTests.cpp | 25 +- .../test/src/ProjMgrUtilsUnitTests.cpp | 53 ---- .../test/src/ProjMgrWorkerUnitTests.cpp | 45 ++-- 61 files changed, 995 insertions(+), 894 deletions(-) create mode 100644 libs/rteutils/src/CollectionUtils.cpp create mode 100644 libs/rteutils/src/RteConstants.cpp diff --git a/libs/crossplatform/include/CrossPlatformUtils.h b/libs/crossplatform/include/CrossPlatformUtils.h index 866a822e4..5384e3dd1 100644 --- a/libs/crossplatform/include/CrossPlatformUtils.h +++ b/libs/crossplatform/include/CrossPlatformUtils.h @@ -84,6 +84,13 @@ class CrossPlatformUtils */ static bool CanExecute(const std::string& file); + /** + * @brief execute shell command + * @param cmd string shell command to be executed + * @return command execution result + */ + static const std::pair ExecCommand(const std::string& cmd); + enum class REG_STATUS { ENABLED, DISABLED, diff --git a/libs/crossplatform/src/CrossPlatformUtils.cpp b/libs/crossplatform/src/CrossPlatformUtils.cpp index 8d397515f..11f303658 100644 --- a/libs/crossplatform/src/CrossPlatformUtils.cpp +++ b/libs/crossplatform/src/CrossPlatformUtils.cpp @@ -4,9 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ #include "CrossPlatformUtils.h" +#include "CrossPlatform.h" #include "constants.h" #include +#include +#include std::string CrossPlatformUtils::GetEnv(const std::string& name) { @@ -64,4 +67,25 @@ const std::string& CrossPlatformUtils::GetHostType() return os_name; } + +const std::pair CrossPlatformUtils::ExecCommand(const std::string& cmd) +{ + std::array buffer; + std::string result; + int ret_code = -1; + std::function close = _pclose; + std::function open = _popen; + + auto deleter = [&close, &ret_code](FILE* cmd) { ret_code = close(cmd); }; + { + const std::unique_ptr pipe(open(cmd.c_str(), "r"), deleter); + if (pipe) { + while (fgets(buffer.data(), static_cast(buffer.size()), pipe.get()) != nullptr) { + result += buffer.data(); + } + } + } + return std::make_pair(result, ret_code); +} + // end of CrossplatformUtils.cpp diff --git a/libs/crossplatform/test/src/UnitTests.cpp b/libs/crossplatform/test/src/UnitTests.cpp index c219e132d..5fbca3a0c 100644 --- a/libs/crossplatform/test/src/UnitTests.cpp +++ b/libs/crossplatform/test/src/UnitTests.cpp @@ -107,4 +107,19 @@ TEST(CrossPlatformUnitTests, GetLongPathRegStatus) { EXPECT_EQ(CrossPlatformUtils::REG_STATUS::NOT_SUPPORTED, status); } } + +TEST(CrossPlatformUnitTests, ExecCommand) { + auto result = CrossPlatformUtils::ExecCommand("invalid command"); + EXPECT_EQ(false, (0 == result.second) ? true : false) << result.first; + + string testdir = "mkdir_test_dir"; + error_code ec; + if (filesystem::exists(testdir)) { + filesystem::remove(testdir); + } + result = CrossPlatformUtils::ExecCommand("mkdir " + testdir); + EXPECT_TRUE(filesystem::exists(testdir)); + EXPECT_EQ(true, (0 == result.second) ? true : false) << result.first; +} + // end of UnitTests.cpp diff --git a/libs/rtefsutils/include/RteFsUtils.h b/libs/rtefsutils/include/RteFsUtils.h index 347d43317..8be471498 100644 --- a/libs/rtefsutils/include/RteFsUtils.h +++ b/libs/rtefsutils/include/RteFsUtils.h @@ -8,7 +8,7 @@ */ /******************************************************************************/ /* - * Copyright (c) 2020-2021 Arm Limited. All rights reserved. + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. * * SPDX-License-Identifier: Apache-2.0 */ @@ -66,7 +66,7 @@ class RteFsUtils * @param content string to be stored in the created file * @return true if file is created */ - static bool CreateFile(const std::string& file, const std::string& content); + static bool CreateTextFile(const std::string& file, const std::string& content); /** * @brief copy string to file in binary mode. Previous content of file is destroyed. * @param fileName name of file @@ -377,6 +377,14 @@ class RteFsUtils * @return absolute file name if found, empty string otherwise */ static std::string FindFileInEtc(const std::string& fileName, const std::string& baseDir); + + /** + * @brief get file category according to file extension + * @param filename with extension + * @return string category + */ + static const std::string& FileCategoryFromExtension(const std::string& file); + }; #endif // RteFsUtils_H diff --git a/libs/rtefsutils/src/RteFsUtils.cpp b/libs/rtefsutils/src/RteFsUtils.cpp index fa7146ae9..3e4dcd5c9 100644 --- a/libs/rtefsutils/src/RteFsUtils.cpp +++ b/libs/rtefsutils/src/RteFsUtils.cpp @@ -203,7 +203,7 @@ string RteFsUtils::BackupFile(const string& fileName, bool bDeleteExisting) { return RteUtils::ERROR_STRING; } -bool RteFsUtils::CreateFile(const string& file, const string& content) { +bool RteFsUtils::CreateTextFile(const string& file, const string& content) { // Create file and directories error_code ec; fs::create_directories(fs::path(file).parent_path(), ec); @@ -233,7 +233,7 @@ bool RteFsUtils::CopyBufferToFile(const string& fileName, const string& buffer, } } - return CreateFile(fileName, buffer); + return CreateTextFile(fileName, buffer); } bool RteFsUtils::CopyMergeFile(const string& src, const string& dst, int nInstance, bool backup) { @@ -729,7 +729,8 @@ void RteFsUtils::GetMatchingFiles(list& files, const string& extension, const fs::path& p = entry.path(); string filename = p.filename().generic_string(); if (fs::is_regular_file(p)) { - if (p.extension() == extension) { + auto pos = filename.rfind(extension); + if (pos != string::npos && pos == (filename.size() - extension.size())) { files.push_back(p.generic_string()); // insert full absolute path bFound = true; } @@ -840,4 +841,25 @@ std::string RteFsUtils::FindFileInEtc(const std::string& fileName, const std::st return FindFile(fileName, baseDir, relSearchOrder); } +const string& RteFsUtils::FileCategoryFromExtension(const string& file) { + static const string& OTHER = "other"; + static const map> CATEGORIES = { + {"sourceC", {".c", ".C"}}, + {"sourceCpp", {".cpp", ".c++", ".C++", ".cxx", ".cc", ".CC"}}, + {"sourceAsm", {".asm", ".s", ".S"}}, + {"header", {".h", ".hpp"}}, + {"library", {".a", ".lib"}}, + {"object", {".o"}}, + {"linkerScript", {".sct", ".scf", ".ld", ".icf", ".src"}}, + {"doc", {".txt", ".md", ".pdf", ".htm", ".html"}}, + }; + fs::path ext((fs::path(file)).extension()); + for (const auto& category : CATEGORIES) { + if (find(category.second.begin(), category.second.end(), ext) != category.second.end()) { + return category.first; + } + } + return OTHER; +} + // End of RteFsUtils.cpp diff --git a/libs/rtefsutils/test/src/RteFsUtilsTest.cpp b/libs/rtefsutils/test/src/RteFsUtilsTest.cpp index 06f4e095f..26ae5f939 100644 --- a/libs/rtefsutils/test/src/RteFsUtilsTest.cpp +++ b/libs/rtefsutils/test/src/RteFsUtilsTest.cpp @@ -83,7 +83,7 @@ void RteFsUtilsTest::CreateInputFiles(const string& dir) { // Create dummy test files for (auto fileName : sortedFileSet) { string filePath = dir + "/" + fileName; - RteFsUtils::CreateFile(filePath, fileName); + RteFsUtils::CreateTextFile(filePath, fileName); } } @@ -111,7 +111,7 @@ TEST_F(RteFsUtilsTest, BackupFile) { string ret; error_code ec; - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); // Test filename with regular separators and multiple backup ret = RteUtils::SlashesToOsSlashes(RteFsUtils::BackupFile(filenameRegular)); @@ -161,7 +161,7 @@ TEST_F(RteFsUtilsTest, BackupFile) { TEST_F(RteFsUtilsTest, CmpFileMem) { bool ret; - RteFsUtils::CreateFile(filenameRegular, bufferFoo); + RteFsUtils::CreateTextFile(filenameRegular, bufferFoo); // Test filename with regular separators ret = RteFsUtils::CmpFileMem(filenameRegular, bufferFoo); @@ -231,7 +231,7 @@ TEST_F(RteFsUtilsTest, CopyBufferToFile) { RteFsUtils::RemoveFile(filenameRegular); // Test existent file with same content - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::CopyBufferToFile(filenameRegular, bufferFoo, false); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), true); @@ -239,7 +239,7 @@ TEST_F(RteFsUtilsTest, CopyBufferToFile) { RteFsUtils::RemoveFile(filenameRegular); // Test existent file with different content and backup argument - RteFsUtils::CreateFile(filenameRegular, bufferFoo); + RteFsUtils::CreateTextFile(filenameRegular, bufferFoo); ret = RteFsUtils::CopyBufferToFile(filenameRegular, bufferBar, true); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), true); @@ -254,7 +254,7 @@ TEST_F(RteFsUtilsTest, CopyCheckFile) { bool ret; error_code ec; - RteFsUtils::CreateFile(filenameRegular, bufferFoo); + RteFsUtils::CreateTextFile(filenameRegular, bufferFoo); // Test filename with regular separators ret = RteFsUtils::CopyCheckFile(filenameRegular, filenameRegularCopy, false); @@ -305,7 +305,7 @@ TEST_F(RteFsUtilsTest, ExpandFile) { bool ret; string buffer; - RteFsUtils::CreateFile(filenameRegular, "%Instance%"); + RteFsUtils::CreateTextFile(filenameRegular, "%Instance%"); // Test filename with regular separators ret = RteFsUtils::ExpandFile(filenameRegular, 1, buffer); @@ -337,7 +337,7 @@ TEST_F(RteFsUtilsTest, CopyMergeFile) { bool ret; error_code ec; - RteFsUtils::CreateFile(filenameRegular, "%Instance%"); + RteFsUtils::CreateTextFile(filenameRegular, "%Instance%"); // Test filename with regular separators ret = RteFsUtils::CopyMergeFile(filenameRegular, filenameRegularCopy, 1, false); @@ -391,8 +391,8 @@ TEST_F(RteFsUtilsTest, CopyTree) { // use CountFilesInFolder if additionall test EXPECT_EQ(RteFsUtils::CountFilesInFolder(dirnameBase), 0); - RteFsUtils::CreateFile(filenameRegular, "foo"); - RteFsUtils::CreateFile(filenameRegularCopy, "bar"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegularCopy, "bar"); EXPECT_EQ(RteFsUtils::CountFilesInFolder(dirnameBase), 2); @@ -470,19 +470,19 @@ TEST_F(RteFsUtilsTest, DeleteFileAutoRetry) { error_code ec; // Test filename with regular separators - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteFileAutoRetry(filenameRegular); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), false); // Test filename with backslashes separators - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteFileAutoRetry(filenameBackslash); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), false); // Test filename with mixed separators - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteFileAutoRetry(filenameMixed); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), false); @@ -496,13 +496,13 @@ TEST_F(RteFsUtilsTest, DeleteFileAutoRetry) { EXPECT_EQ(ret, true); // Test delay argument equal to zero - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteFileAutoRetry(filenameRegular, 5U, 0U); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), false); // Test retry argument equal to zero - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteFileAutoRetry(filenameRegular, 0U, 1U); EXPECT_EQ(ret, false); RteFsUtils::RemoveFile(filenameRegular); @@ -513,37 +513,37 @@ TEST_F(RteFsUtilsTest, DeleteTree) { error_code ec; // Test dirname with regular separators - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteTree(dirnameSubdir); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(dirnameSubdir), false); // Test dirname with backslashes separators - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteTree(dirnameSubdirBackslash); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(dirnameSubdir), false); // Test dirname with mixed separators - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteTree(dirnameSubdirMixed); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(dirnameSubdir), false); // Test dirname with regular separators and trailing - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteTree(dirnameSubdirWithTrailing); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(dirnameSubdir), false); // Test dirname with backslashes separators and trailing - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteTree(dirnameBackslashWithTrailing); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(dirnameSubdir), false); // Test dirname with mixed separators and trailing - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteTree(dirnameMixedWithTrailing); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(dirnameSubdir), false); @@ -557,7 +557,7 @@ TEST_F(RteFsUtilsTest, DeleteTree) { EXPECT_EQ(ret, true); // Test source not a directory - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::DeleteTree(filenameRegular); EXPECT_EQ(ret, false); RteFsUtils::RemoveFile(filenameRegular); @@ -568,7 +568,7 @@ TEST_F(RteFsUtilsTest, MoveExistingFile) { error_code ec; // Test filename with regular separators - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::MoveExistingFile(filenameRegular, filenameRegularCopy); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), false); @@ -576,7 +576,7 @@ TEST_F(RteFsUtilsTest, MoveExistingFile) { RteFsUtils::RemoveFile(filenameRegularCopy); // Test filename with backslashes separators - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::MoveExistingFile(filenameBackslash, filenameBackslashCopy); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), false); @@ -584,7 +584,7 @@ TEST_F(RteFsUtilsTest, MoveExistingFile) { RteFsUtils::RemoveFile(filenameRegularCopy); // Test filename with mixed separators - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::MoveExistingFile(filenameMixed, filenameMixedCopy); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), false); @@ -605,7 +605,7 @@ TEST_F(RteFsUtilsTest, MoveExistingFile) { TEST_F(RteFsUtilsTest, MoveFileExAutoRetry) { bool ret; // Test filename with default retry and delay arguments - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::MoveFileExAutoRetry(filenameRegular, filenameRegularCopy); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), false); @@ -613,7 +613,7 @@ TEST_F(RteFsUtilsTest, MoveFileExAutoRetry) { RteFsUtils::RemoveFile(filenameRegularCopy); // Test filename with delay argument equal to 0 - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::MoveFileExAutoRetry(filenameRegular, filenameRegularCopy, 5U, 0U); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), false); @@ -621,7 +621,7 @@ TEST_F(RteFsUtilsTest, MoveFileExAutoRetry) { RteFsUtils::RemoveFile(filenameRegularCopy); // Test filename with retry argument equal to 0 - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::MoveFileExAutoRetry(filenameRegular, filenameRegularCopy, 0U, 1U); EXPECT_EQ(ret, false); RteFsUtils::RemoveFile(filenameRegular); @@ -642,7 +642,7 @@ TEST_F(RteFsUtilsTest, CopyFileExAutoRetry) { EXPECT_FALSE(RteFsUtils::Exists(filenameRegularCopy)); // Test filename with default retry and delay arguments - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::CopyFileExAutoRetry(filenameRegular, filenameRegularCopy); EXPECT_EQ(ret, true); EXPECT_EQ(RteFsUtils::Exists(filenameRegular), true); @@ -706,7 +706,7 @@ TEST_F(RteFsUtilsTest, RemoveDirectoryAutoRetry) { EXPECT_EQ(ret, true); // Test path is not a directory - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); ret = RteFsUtils::RemoveDirectoryAutoRetry(filenameRegular); EXPECT_EQ(ret, false); RteFsUtils::RemoveFile(filenameRegular); @@ -729,7 +729,7 @@ TEST_F(RteFsUtilsTest, SetFileReadOnly) { error_code ec; constexpr fs::perms write_mask = fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write; - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); const fs::perms initial_perm = fs::status(filenameRegular, ec).permissions(); // Test filename with regular separators @@ -775,7 +775,7 @@ TEST_F(RteFsUtilsTest, SetTreeReadOnly) { constexpr fs::perms write_mask = fs::perms::owner_write | fs::perms::group_write | fs::perms::others_write; const string validationDir = dirnameSubdir + "/foo/bar"; - RteFsUtils::CreateFile(validationDir + "/baz.txt", "foo"); + RteFsUtils::CreateTextFile(validationDir + "/baz.txt", "foo"); const fs::perms initial_perm = fs::status(validationDir, ec).permissions(); // Set parent directory read-only for the reminder of the test @@ -829,7 +829,7 @@ TEST_F(RteFsUtilsTest, MakePathCanonical) { const string dirnameCanonical = fs::current_path(ec).append(dirnameSubdir).generic_string(); // create file and with parent directories for reliability of the tests - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); // Test filename with regular separators, file exists ret = RteFsUtils::MakePathCanonical(filenameRegular); @@ -885,7 +885,7 @@ TEST_F(RteFsUtilsTest, GetCurrentFolder) { const string expectedDir = fs::current_path(ec).append(dirnameSubdir).generic_string() + "/"; string curDir = RteFsUtils::GetCurrentFolder(); - RteFsUtils::CreateFile(filenameRegular, ""); + RteFsUtils::CreateTextFile(filenameRegular, ""); fs::current_path(dirnameSubdir, ec); currDir = RteFsUtils::GetCurrentFolder(); EXPECT_EQ(expectedDir, currDir); @@ -1064,6 +1064,10 @@ TEST_F(RteFsUtilsTest, GetMatchingFiles) { RteFsUtils::GetMatchingFiles(files, ".h", dirnameDir, 3, false); EXPECT_EQ(files.size(), 3); + files.clear(); + RteFsUtils::GetMatchingFiles(files, ".bar.h", dirnameDir, 3, true); + EXPECT_EQ(files.size(), 4); + RteFsUtils::RemoveDir(dirnameDir); } @@ -1083,15 +1087,15 @@ TEST_F(RteFsUtilsTest, GetFilesSorted) { TEST_F(RteFsUtilsTest, CreateExtendedName) { - RteFsUtils::CreateFile(filenameRegular, bufferFoo); + RteFsUtils::CreateTextFile(filenameRegular, bufferFoo); string backup = RteFsUtils::CreateExtendedName(filenameRegular, "backup"); EXPECT_EQ(backup, filenameRegular + "_backup_0"); - RteFsUtils::CreateFile(backup, "0"); + RteFsUtils::CreateTextFile(backup, "0"); backup = RteFsUtils::CreateExtendedName(filenameRegular, "backup"); EXPECT_EQ(backup, filenameRegular + "_backup_1"); - RteFsUtils::CreateFile(backup, "1"); + RteFsUtils::CreateTextFile(backup, "1"); backup = RteFsUtils::CreateExtendedName(filenameRegular, "backup"); EXPECT_EQ(backup, filenameRegular + "_backup_2"); @@ -1104,7 +1108,7 @@ TEST_F(RteFsUtilsTest, AbsolutePath) { error_code ec; const string absFilePath = fs::current_path(ec).append(filenameRegular).generic_string(); - RteFsUtils::CreateFile(filenameRegular, "foo"); + RteFsUtils::CreateTextFile(filenameRegular, "foo"); // Test empty path path = RteFsUtils::AbsolutePath(""); @@ -1123,7 +1127,7 @@ TEST_F(RteFsUtilsTest, FindFileRegEx) { const string& testdir = dirnameBase + "/FindFileRegEx"; const string& fileName = testdir + "/test.cdefault.yml"; RteFsUtils::CreateDirectories(testdir); - RteFsUtils::CreateFile(fileName, ""); + RteFsUtils::CreateTextFile(fileName, ""); string discoveredFile; vector searchPaths = { testdir }; EXPECT_EQ(true, RteFsUtils::FindFileRegEx(searchPaths, ".*\\.cdefault\\.yml", discoveredFile)); @@ -1136,8 +1140,8 @@ TEST_F(RteFsUtilsTest, FindFileRegEx_MultipleMatches) { const string& fileName1 = testdir + "/test1.cdefault.yml"; const string& fileName2 = testdir + "/test2.cdefault.yml"; RteFsUtils::CreateDirectories(testdir); - RteFsUtils::CreateFile(fileName1, ""); - RteFsUtils::CreateFile(fileName2, ""); + RteFsUtils::CreateTextFile(fileName1, ""); + RteFsUtils::CreateTextFile(fileName2, ""); string finding; vector searchPaths = { testdir }; EXPECT_EQ(false, RteFsUtils::FindFileRegEx(searchPaths, ".*\\.cdefault\\.yml", finding)); @@ -1153,6 +1157,24 @@ TEST_F(RteFsUtilsTest, FindFileRegEx_NoMatch) { RteFsUtils::RemoveDir(testdir); } +TEST_F(RteFsUtilsTest, FileCategoryFromExtension) { + map> testDataVec = { + {"sourceC", {"sourceFile.c", "sourceFile.C"}}, + {"sourceCpp", {"sourceFile.cpp", "sourceFile.c++", "sourceFile.C++", "sourceFile.cxx", "sourceFile.cc", "sourceFile.CC"}}, + {"sourceAsm", {"sourceFile.asm", "sourceFile.s", "sourceFile.S"}}, + {"header", {"headerFile.h", "headerFile.hpp"}}, + {"library", {"libraryFile.a", "libraryFile.lib"}}, + {"object", {"objectFile.o"}}, + {"linkerScript", {"linkerFile.sct", "linkerFile.scf", "linkerFile.ld", "linkerFile.icf"}}, + {"doc", {"documentFile.txt", "documentFile.md", "documentFile.pdf", "documentFile.htm", "documentFile.html"}}, + }; + for (const auto& [expected, files] : testDataVec) { + for (const auto& file : files) { + EXPECT_EQ(RteFsUtils::FileCategoryFromExtension(file), expected); + } + } +} + TEST_F(RteFsUtilsTest, GetAbsPathFromLocalUrl) { #ifdef _WIN32 // Absolute dummy path @@ -1186,4 +1208,7 @@ TEST_F(RteFsUtilsTest, GetAbsPathFromLocalUrl) { const string& testUrlOmittedHost = "file:" + absoluteFilename; EXPECT_EQ(absoluteFilename, RteFsUtils::GetAbsPathFromLocalUrl(testUrlOmittedHost)); #endif + } + +// end of RteFsUtilsTest.cpp diff --git a/libs/rtemodel/include/RteCallback.h b/libs/rtemodel/include/RteCallback.h index 7940fca5c..0076126f3 100644 --- a/libs/rtemodel/include/RteCallback.h +++ b/libs/rtemodel/include/RteCallback.h @@ -181,11 +181,11 @@ class RteCallback : public XMLTreeCallback }; /** - * @brief obtains globally defined generator + * @brief obtains globally defined external generator * @param id generator id * @return pointer to RteGenerator if found, nullptr otherwise */ - virtual RteGenerator* GetGenerator(const std::string& id) const { return nullptr; } + virtual RteGenerator* GetExternalGenerator(const std::string& id) const; /** * @brief get global RteCallback object diff --git a/libs/rtemodel/include/RteGenerator.h b/libs/rtemodel/include/RteGenerator.h index 35993e964..8fc6f3291 100644 --- a/libs/rtemodel/include/RteGenerator.h +++ b/libs/rtemodel/include/RteGenerator.h @@ -36,7 +36,7 @@ class RteGenerator : public RteItem * @brief constructor * @param parent pointer to RteItem parent */ - RteGenerator(RteItem* parent); + RteGenerator(RteItem* parent, bool bExternal = false); /** * @brief virtual destructor @@ -44,25 +44,30 @@ class RteGenerator : public RteItem ~RteGenerator() override; /** - * @brief get generator commands for all host types without expansion - * @return map with host type ("win", "linux", "mac", "other", or "all") as key and generator command as value + * @brief get generator "run" attribute + * @return generator run command */ - std::map GetCommands() const; + const std::string& GetRunAttribute() const { return GetAttribute("run"); } + + /** + * @brief get generator "path" attribute + * @return generator path + */ + const std::string& GetPathAttribute() const { return GetAttribute("path"); } /** * @brief get generator command without expansion * @param hostType host type to match, empty to match current host * @return generator command for specified host type */ - const std::string GetCommand(const std::string& hostType = EMPTY_STRING ) const; + virtual const std::string GetCommand(const std::string& hostType = EMPTY_STRING ) const; /** * @brief get expanded generator executable command - * @param target pointer to RteTarget * @param hostType host type to match, empty to match current host * @return generator command for specified host type */ - std::string GetExecutable(RteTarget* target, const std::string& hostType = EMPTY_STRING) const; + virtual std::string GetExecutable(const std::string& hostType = EMPTY_STRING) const; /** * @brief get item containing command line arguments @@ -124,25 +129,29 @@ class RteGenerator : public RteItem * @brief get generator working directory * @return working directory value */ - const std::string& GetWorkingDir() const { return GetItemValue("workingDir"); } + const std::string& GetWorkingDir() const; + + /** + * @brief return value of attribute "download-url" + * @return value of attribute "download-url" + */ + const std::string& GetURL() const override { return GetAttribute("download-url"); } /** * @brief get all arguments as vector for the given host type - * @param target pointer to RteTarget * @param hostType host type, empty to match current host * @param dryRun include dry-run arguments * @return vector of arguments consisting of switch and value in pairs */ - std::vector > GetExpandedArguments(RteTarget* target, const std::string& hostType = EMPTY_STRING, bool dryRun = false) const; + std::vector > GetExpandedArguments(const std::string& hostType = EMPTY_STRING, bool dryRun = false) const; /** * @brief get full command line with arguments and expanded key sequences for specified target - * @param target pointer to RteTarget * @param hostType host type, empty to match current host * @param dryRun include dry-run arguments * @return expanded command line with arguments, properly quoted */ - std::string GetExpandedCommandLine(RteTarget* target, const std::string& hostType = EMPTY_STRING, bool dryRun = false) const; + std::string GetExpandedCommandLine(const std::string& hostType = EMPTY_STRING, bool dryRun = false) const; /** * @brief get absolute path to gpdsc file for specified target @@ -217,6 +226,13 @@ class RteGenerator : public RteItem */ bool IsDryRunCapable(const std::string& hostType = EMPTY_STRING) const; + /** + * @brief check if the generator is external + * @return true if the generator is external, default returns false + */ + bool IsExternal() const { return m_bExternal; } + + protected: /** * @brief construct generator ID @@ -227,9 +243,9 @@ class RteGenerator : public RteItem private: RteItem* m_pDeviceAttributes; RteFileContainer* m_files; + bool m_bExternal; }; - /** * @brief class to support element in *.pdsc files */ diff --git a/libs/rtemodel/include/RteItem.h b/libs/rtemodel/include/RteItem.h index 958fad6cd..9fc2ee753 100644 --- a/libs/rtemodel/include/RteItem.h +++ b/libs/rtemodel/include/RteItem.h @@ -960,6 +960,13 @@ class RteRootItem : public RteItem m_rootFileName = rootFileName; } + /** + * @brief create a new instance of type RteItem + * @param tag name of tag + * @return pointer to instance of type RteItem + */ + RteItem* CreateItem(const std::string& tag) override; + protected: std::string m_rootFileName; // absolute filename of this item's file }; diff --git a/libs/rtemodel/include/RteKernel.h b/libs/rtemodel/include/RteKernel.h index b7404922b..f5d424101 100644 --- a/libs/rtemodel/include/RteKernel.h +++ b/libs/rtemodel/include/RteKernel.h @@ -44,6 +44,12 @@ class RteKernel */ virtual ~RteKernel(); + /** + * @brief initialize kernel + * @return true if successful + */ + virtual bool Init(); + /** * @brief getter for CMSIS pack root folder * @return CMSIS pack root folder @@ -82,6 +88,29 @@ class RteKernel */ void SetRteCallback(RteCallback* callback); + /** + * @brief get collection of externals generators + * @return map of id to RteGenerator pointer + */ + const std::map& GetExternalGenerators() const { return m_externalGenerators; } + + /** + * @brief get global external generator for given ID + * @param id generator ID string + * @return pointer to RteGenerator if found, nullptr otherwise + */ + RteGenerator* GetExternalGenerator(const std::string& id) const; + + /** + * @brief loads external generators + */ + void LoadExternalGenerators(); + + /** + * @brief clear and deletes external generators + */ + void ClearExternalGenerators(); + /** * @brief getter for global CMSIS RTE model * @return pointer to RteGlobalModel object @@ -290,7 +319,6 @@ class RteKernel void SetToolInfo(const XmlItem& attr) { m_toolInfo = attr; } protected: - bool GetUrlFromIndex(const std::string& indexFile, const std::string& name, const std::string& vendor, const std::string& version, std::string& indexedUrl, std::string& indexedVersion) const; bool GetLocalPacksUrls(const std::string& rtePath, std::list& urls) const; XMLTreeElement* ParseLocalRepositoryIdx(const std::string& rtePath) const; @@ -309,18 +337,24 @@ class RteKernel */ virtual YmlTree* CreateYmlTree(IXmlItemBuilder* itemBuilder) const; -protected: /** * @brief get this pointer to use in const methods * @return this */ RteKernel* GetThisKernel() const { return const_cast(this); } + +// data +protected: + RteGlobalModel* m_globalModel; bool m_bOwnModel; RteCallback* m_rteCallback; XmlItem m_toolInfo; std::string m_cmsisPackRoot; std::string m_cmsisToolboxDir; + std::map m_externalGeneratorFiles; + std::map m_externalGenerators; + }; #endif // RteKernel_H diff --git a/libs/rtemodel/src/RteCallback.cpp b/libs/rtemodel/src/RteCallback.cpp index b8600b900..5284b5e0d 100644 --- a/libs/rtemodel/src/RteCallback.cpp +++ b/libs/rtemodel/src/RteCallback.cpp @@ -50,6 +50,14 @@ long RteCallback::ShowMessageBox(const string& title, const string& message, uns return defaultVal; } +RteGenerator* RteCallback::GetExternalGenerator(const std::string& id) const +{ + if(GetRteKernel()) { + return GetRteKernel()->GetExternalGenerator(id); + } + return nullptr; +} + RteCallback* RteCallback::GetGlobal() { if(theGlobalCallback) { diff --git a/libs/rtemodel/src/RteComponent.cpp b/libs/rtemodel/src/RteComponent.cpp index 53c68b9f3..fdcafb03c 100644 --- a/libs/rtemodel/src/RteComponent.cpp +++ b/libs/rtemodel/src/RteComponent.cpp @@ -317,7 +317,7 @@ RteGenerator* RteComponent::GetGenerator() const generator = pack->GetGenerator(generatorName); } if (!generator && GetCallback()) { - generator = GetCallback()->GetGenerator(generatorName); + generator = GetCallback()->GetExternalGenerator(generatorName); } } return generator; diff --git a/libs/rtemodel/src/RteGenerator.cpp b/libs/rtemodel/src/RteGenerator.cpp index 7459c26d8..328d755d2 100644 --- a/libs/rtemodel/src/RteGenerator.cpp +++ b/libs/rtemodel/src/RteGenerator.cpp @@ -25,10 +25,11 @@ using namespace std; -RteGenerator::RteGenerator(RteItem* parent) : +RteGenerator::RteGenerator(RteItem* parent, bool bExternal) : RteItem(parent), m_pDeviceAttributes(nullptr), - m_files(nullptr) + m_files(nullptr), + m_bExternal(bExternal) { RteGenerator::Clear(); } @@ -74,6 +75,14 @@ const string& RteGenerator::GetGpdsc() const return EMPTY_STRING; } +const std::string& RteGenerator::GetWorkingDir() const +{ + if(IsExternal()) { + return GetPathAttribute(); + } + return GetItemValue("workingDir"); +} + RteItem* RteGenerator::GetArgumentsItem(const string& type) const { if (type.empty() || type == "exe") { @@ -89,7 +98,11 @@ RteItem* RteGenerator::GetArgumentsItem(const string& type) const return args; } -const string RteGenerator::GetCommand(const std::string& hostType) const { +const string RteGenerator::GetCommand(const std::string& hostType) const +{ + if(IsExternal()) { + return GetRunAttribute(); + } RteItem* exe = GetItemByTag("exe"); if (exe != NULL) { @@ -119,7 +132,7 @@ const string RteGenerator::GetCommand(const std::string& hostType) const { return GetItemValue("command"); } -string RteGenerator::GetExecutable(RteTarget* target, const std::string& hostType) const +string RteGenerator::GetExecutable(const std::string& hostType) const { string cmd = GetCommand(hostType); if (cmd.empty()) @@ -129,18 +142,15 @@ string RteGenerator::GetExecutable(RteTarget* target, const std::string& hostTyp return EMPTY_STRING; // return empty string here , GetExpandedWebLine() will return URL then cmd = ExpandString(cmd); - fs::path path(cmd); - if (target && path.is_relative()) { - RtePackage* p = GetPackage(); - if (p) - cmd = p->GetAbsolutePackagePath() + cmd; + if (RteFsUtils::IsRelative(cmd)) { + cmd = GetAbsolutePackagePath() + cmd; } return cmd; } -vector > RteGenerator::GetExpandedArguments(RteTarget* target, const string& hostType, bool dryRun) const +vector > RteGenerator::GetExpandedArguments(const string& hostType, bool dryRun) const { vector > args; RteItem* argsItem = GetArgumentsItem("exe"); @@ -156,10 +166,10 @@ vector > RteGenerator::GetExpandedArguments(RteTarget* targ return args; } -string RteGenerator::GetExpandedCommandLine(RteTarget* target, const string& hostType, bool dryRun) const +string RteGenerator::GetExpandedCommandLine(const string& hostType, bool dryRun) const { - const vector > args = GetExpandedArguments(target, hostType, dryRun); - string fullCmd = RteUtils::AddQuotesIfSpace(GetExecutable(target, hostType)); + const vector > args = GetExpandedArguments(hostType, dryRun); + string fullCmd = RteUtils::AddQuotesIfSpace(GetExecutable(hostType)); for (size_t i = 0; i < args.size(); i++) { fullCmd += ' ' + RteUtils::AddQuotesIfSpace(args[i].first + args[i].second); } @@ -282,7 +292,6 @@ RteGeneratorContainer::RteGeneratorContainer(RteItem* parent) : { } - RteGenerator* RteGeneratorContainer::GetGenerator(const string& id) const { return dynamic_cast(GetItem(id)); diff --git a/libs/rtemodel/src/RteItem.cpp b/libs/rtemodel/src/RteItem.cpp index 57bd517ee..d5966135f 100644 --- a/libs/rtemodel/src/RteItem.cpp +++ b/libs/rtemodel/src/RteItem.cpp @@ -18,6 +18,7 @@ #include "RtePackage.h" #include "RteProject.h" #include "RteModel.h" +#include "RteGenerator.h" #include "RteConstants.h" #include "RteFsUtils.h" @@ -1022,4 +1023,15 @@ void RteItem::SortChildren(CompareRteItemType cmp) m_children.sort(cmp); } + +RteItem* RteRootItem::CreateItem(const std::string& tag) +{ + // for YAML files create corresponding items depending on the root itself + if(GetTag() == "generator") { + return new RteGenerator(this, true); + } + return RteItem::CreateItem(tag); +} + + // End of RteItem.cpp diff --git a/libs/rtemodel/src/RteItemBuilder.cpp b/libs/rtemodel/src/RteItemBuilder.cpp index ba52a8da6..5ed21f831 100644 --- a/libs/rtemodel/src/RteItemBuilder.cpp +++ b/libs/rtemodel/src/RteItemBuilder.cpp @@ -39,8 +39,6 @@ RteItem* RteItemBuilder::CreateRootItem(const string& tag) } else if (tag == "cprj") { m_cprjFile = new CprjFile(m_rootParent); pRoot = m_cprjFile; - } else if (m_rootParent) { - pRoot = m_rootParent; } else { pRoot = new RteRootItem(m_rootParent); } diff --git a/libs/rtemodel/src/RteKernel.cpp b/libs/rtemodel/src/RteKernel.cpp index f1430eefc..7ee86ca7c 100644 --- a/libs/rtemodel/src/RteKernel.cpp +++ b/libs/rtemodel/src/RteKernel.cpp @@ -23,6 +23,8 @@ #include "XmlFormatter.h" #include "YmlFormatter.h" +#include "CollectionUtils.h" + using namespace std; static string schemaFile = "CPRJ.xsd"; @@ -62,6 +64,13 @@ RteKernel::~RteKernel() if (m_bOwnModel) { delete m_globalModel; } + ClearExternalGenerators(); +} + +bool RteKernel::Init() +{ + LoadExternalGenerators(); + return true; } bool RteKernel::SetCmsisPackRoot(const string& cmsisPackRoot) @@ -83,6 +92,11 @@ void RteKernel::SetRteCallback(RteCallback* callback) GetGlobalModel()->SetCallback(m_rteCallback); } +RteGenerator* RteKernel::GetExternalGenerator(const std::string& id) const +{ + return get_or_null(m_externalGenerators, id); +} + RteProject* RteKernel::GetProject(int nPjNum) const { return GetGlobalModel()->GetProject(nPjNum); @@ -233,6 +247,42 @@ bool RteKernel::InitializeCprj(RteCprjProject* cprjProject, const string& toolch return true; } +void RteKernel::LoadExternalGenerators() +{ + ClearExternalGenerators(); + string etcDir = GetCmsisToolboxDir() + "/etc"; + list files; + RteFsUtils::GetMatchingFiles(files, ".generator.yml", etcDir, 1, true); + RteGlobalModel* globalModel = GetGlobalModel(); + RteItemBuilder rteBuilder(globalModel); + unique_ptr ymlTree = CreateUniqueYmlTree(&rteBuilder); + for(auto& f : files) { + if(contains_key(m_externalGeneratorFiles, f)) { + continue; + } + bool result = ymlTree->ParseFile(f); + RteItem* rootItem = rteBuilder.GetRoot(); + if(result && rootItem) { + m_externalGeneratorFiles[f] = rootItem; + for(auto item : rootItem->GetChildren()) { + RteGenerator* g = dynamic_cast(item); + if(g) { + m_externalGenerators[g->GetID()] = g; + } + } + } + rteBuilder.Clear(false); + } +} + +void RteKernel::ClearExternalGenerators() +{ + m_externalGenerators.clear(); + for(auto [_, g] : m_externalGeneratorFiles) { + delete g; + } + m_externalGeneratorFiles.clear(); +} RtePackage* RteKernel::LoadPack(const string& pdscFile, PackageState packState) const { @@ -556,6 +606,7 @@ unique_ptr RteKernel::CreateUniqueXmlTree(IXmlItemBuilder* itemBuilder) { unique_ptr xmlTree(CreateXmlTree(itemBuilder)); if (xmlTree.get() != nullptr) { + xmlTree->SetCallback(GetRteCallback()); xmlTree->Init(); } return xmlTree; @@ -564,6 +615,10 @@ unique_ptr RteKernel::CreateUniqueXmlTree(IXmlItemBuilder* itemBuilder) unique_ptr RteKernel::CreateUniqueYmlTree(IXmlItemBuilder* itemBuilder) const { unique_ptr ymlTree(CreateYmlTree(itemBuilder)); + if (ymlTree.get() != nullptr) { + ymlTree->SetCallback(GetRteCallback()); + ymlTree->Init(); + } return ymlTree; } diff --git a/libs/rtemodel/src/RteProject.cpp b/libs/rtemodel/src/RteProject.cpp index f45a59121..4dbd11b34 100644 --- a/libs/rtemodel/src/RteProject.cpp +++ b/libs/rtemodel/src/RteProject.cpp @@ -1172,7 +1172,7 @@ RteGpdscInfo* RteProject::AddGpdscInfo(RteComponent* c, RteTarget* target) return NULL; RteGenerator* gen = c->GetGenerator(); - if (!gen) + if (!gen || gen->IsExternal()) // TODO : remove external check when implemented return NULL; // nothing to insert diff --git a/libs/rtemodel/test/src/RteModelTest.cpp b/libs/rtemodel/test/src/RteModelTest.cpp index 97203f67b..e483437e6 100644 --- a/libs/rtemodel/test/src/RteModelTest.cpp +++ b/libs/rtemodel/test/src/RteModelTest.cpp @@ -37,7 +37,7 @@ class ExtGenRteCallback : public RteCallback ~ExtGenRteCallback() override{ delete m_pExtGenerator; } - RteGenerator* GetGenerator(const std::string& id) const override { + RteGenerator* GetExternalGenerator(const std::string& id) const override { if (m_pExtGenerator->GetID() == "RteTestExternalGenerator") { return m_pExtGenerator; } diff --git a/libs/rteutils/CMakeLists.txt b/libs/rteutils/CMakeLists.txt index 7dc0a021f..e2db5f0eb 100644 --- a/libs/rteutils/CMakeLists.txt +++ b/libs/rteutils/CMakeLists.txt @@ -2,7 +2,7 @@ project(RteUtils VERSION 1.0.0) add_subdirectory("test") -SET(SOURCE_FILES AlnumCmp.cpp DeviceVendor.cpp RteError.cpp RteUtils.cpp VersionCmp.cpp WildCards.cpp) +SET(SOURCE_FILES AlnumCmp.cpp CollectionUtils.cpp DeviceVendor.cpp RteConstants.cpp RteError.cpp RteUtils.cpp VersionCmp.cpp WildCards.cpp) SET(HEADER_FILES AlnumCmp.h CollectionUtils.h DeviceVendor.h RteConstants.h RteError.h RteUtils.h ISchemaChecker.h VersionCmp.h WildCards.h) list(TRANSFORM SOURCE_FILES PREPEND src/) diff --git a/libs/rteutils/include/CollectionUtils.h b/libs/rteutils/include/CollectionUtils.h index bd5e22a58..30156c3b0 100644 --- a/libs/rteutils/include/CollectionUtils.h +++ b/libs/rteutils/include/CollectionUtils.h @@ -7,7 +7,13 @@ #ifndef COLLECTION_UTILS_H #define COLLECTION_UTILS_H +#include +#include #include +#include +#include +#include + /** * @brief Returns value stored in a map for a given key or default value if no entry is found * @tparam M template parameter representing a map @@ -49,4 +55,108 @@ bool contains_key(const M& m, const typename M::key_type& k) { return m.find(k) != m.end(); } +/** + * @brief string pair + */ +typedef std::pair StrPair; + +/** + * @brief string pair + */ +typedef std::pair StrIntPair; + +/** + * @brief string vector +*/ +typedef std::vector StrVec; + +/** + * @brief string set +*/ +typedef std::set StrSet; + +/** + * @brief vector of string pair +*/ +typedef std::vector StrPairVec; + +/** + * @brief vector of string pair pointer +*/ +typedef std::vector StrPairPtrVec; + +/** + * @brief map of vector of string pair +*/ +typedef std::map StrPairVecMap; + +/** + * @brief map of string vector +*/ +typedef std::map StrVecMap; + +/** + * @brief map of int +*/ +typedef std::map IntMap; + +/** + * @brief map of bool +*/ +typedef std::map BoolMap; + +/** + * @brief map of string +*/ +typedef std::map StrMap; + +class CollectionUtils +{ +private: + CollectionUtils() {}; // private constructor to forbid instantiation of a utility class + +public: + /** + * @brief add a string value into a vector if it does not already exist in the vector + * @param vec the vector to add the value into + * @param value the string value to add + */ + static void PushBackUniquely(std::vector& vec, const std::string& value); + + /** + * @brief add a string value into a list if it does not already exist in the list + * @param lst the list to add the value into + * @param value the value to add + */ + static void PushBackUniquely(std::list& lst, const std::string& value); + + /** + * @brief add a value pair into a vector if it does not already exist in the vector + * @param vec the vector to add the value into + * @param value the value pair to add + */ + static void PushBackUniquely(StrPairVec& vec, const StrPair& value); + + /** + * @brief merge two string vector maps + * @param map1 first string vector map + * @param map2 second string vector map + * @return StrVecMap merged map + */ + static StrVecMap MergeStrVecMap(const StrVecMap& map1, const StrVecMap& map2); + + /** + * @brief remove duplicate elements from vector without changing the order of elements + * @param input vector to be processed + */ + template + static void RemoveVectorDuplicates(std::vector& elemVec) { + auto end = elemVec.end(); + for (auto itr = elemVec.begin(); itr != end; ++itr) { + end = std::remove(itr + 1, end, *itr); + } + elemVec.erase(end, elemVec.end()); + } +}; + #endif // COLLECTION_UTILS_H diff --git a/libs/rteutils/include/RteConstants.h b/libs/rteutils/include/RteConstants.h index cee5bff21..dda9ff783 100644 --- a/libs/rteutils/include/RteConstants.h +++ b/libs/rteutils/include/RteConstants.h @@ -17,6 +17,7 @@ #include #include #include +#include "CollectionUtils.h" class RteConstants { @@ -83,6 +84,116 @@ class RteConstants static constexpr const char* PREFIX_PACK_VERSION = "@"; static constexpr const char PREFIX_PACK_VERSION_CHAR = '@'; + /** + * @brief output types + */ + static constexpr const char* OUTPUT_TYPE_BIN = "bin"; + static constexpr const char* OUTPUT_TYPE_ELF = "elf"; + static constexpr const char* OUTPUT_TYPE_HEX = "hex"; + static constexpr const char* OUTPUT_TYPE_LIB = "lib"; + static constexpr const char* OUTPUT_TYPE_CMSE = "cmse-lib"; + + /** + * @brief access sequences + */ + static constexpr const char* AS_SOLUTION = "Solution"; + static constexpr const char* AS_PROJECT = "Project"; + static constexpr const char* AS_COMPILER = "Compiler"; + static constexpr const char* AS_BUILD_TYPE = "BuildType"; + static constexpr const char* AS_TARGET_TYPE = "TargetType"; + static constexpr const char* AS_DNAME = "Dname"; + static constexpr const char* AS_PNAME = "Pname"; + static constexpr const char* AS_BNAME = "Bname"; + + static constexpr const char* AS_SOLUTION_DIR = "SolutionDir"; + static constexpr const char* AS_PROJECT_DIR = "ProjectDir"; + static constexpr const char* AS_OUT_DIR = "OutDir"; + static constexpr const char* AS_BIN = OUTPUT_TYPE_BIN; + static constexpr const char* AS_ELF = OUTPUT_TYPE_ELF; + static constexpr const char* AS_HEX = OUTPUT_TYPE_HEX; + static constexpr const char* AS_LIB = OUTPUT_TYPE_LIB; + static constexpr const char* AS_CMSE = OUTPUT_TYPE_CMSE; + + /** + * @brief default and toolchain specific output affixes + */ + static constexpr const char* DEFAULT_ELF_SUFFIX = ".elf"; + static constexpr const char* DEFAULT_LIB_PREFIX = ""; + static constexpr const char* DEFAULT_LIB_SUFFIX = ".a"; + + static constexpr const char* AC6_ELF_SUFFIX = ".axf"; + static constexpr const char* GCC_ELF_SUFFIX = ".elf"; + static constexpr const char* IAR_ELF_SUFFIX = ".out"; + static constexpr const char* AC6_LIB_PREFIX = ""; + static constexpr const char* GCC_LIB_PREFIX = "lib"; + static constexpr const char* IAR_LIB_PREFIX = ""; + static constexpr const char* AC6_LIB_SUFFIX = ".lib"; + static constexpr const char* GCC_LIB_SUFFIX = ".a"; + static constexpr const char* IAR_LIB_SUFFIX = ".a"; + + /** + * @brief device attributes maps + */ + static constexpr const char* YAML_FPU = "fpu"; + static constexpr const char* YAML_DSP = "dsp"; + static constexpr const char* YAML_MVE = "mve"; + static constexpr const char* YAML_ENDIAN = "endian"; + static constexpr const char* YAML_TRUSTZONE = "trustzone"; + static constexpr const char* YAML_BRANCH_PROTECTION = "branch-protection"; + + static constexpr const char* YAML_ON = "on"; + static constexpr const char* YAML_OFF = "off"; + static constexpr const char* YAML_FPU_DP = "dp"; + static constexpr const char* YAML_FPU_SP = "sp"; + static constexpr const char* YAML_MVE_FP = "fp"; + static constexpr const char* YAML_MVE_INT = "int"; + static constexpr const char* YAML_ENDIAN_BIG = "big"; + static constexpr const char* YAML_ENDIAN_LITTLE = "little"; + static constexpr const char* YAML_BP_BTI = "bti"; + static constexpr const char* YAML_BP_BTI_SIGNRET = "bti-signret"; + static constexpr const char* YAML_TZ_SECURE = "secure"; + static constexpr const char* YAML_TZ_NON_SECURE = "non-secure"; + + static constexpr const char* RTE_DFPU = "Dfpu"; + static constexpr const char* RTE_DDSP = "Ddsp"; + static constexpr const char* RTE_DMVE = "Dmve"; + static constexpr const char* RTE_DENDIAN = "Dendian"; + static constexpr const char* RTE_DSECURE = "Dsecure"; + static constexpr const char* RTE_DTZ = "Dtz"; + static constexpr const char* RTE_DBRANCHPROT = "DbranchProt"; + static constexpr const char* RTE_DPACBTI = "Dpacbti"; + + static constexpr const char* RTE_DP_FPU = "DP_FPU"; + static constexpr const char* RTE_SP_FPU = "SP_FPU"; + static constexpr const char* RTE_NO_FPU = "NO_FPU"; + static constexpr const char* RTE_DSP = "DSP"; + static constexpr const char* RTE_NO_DSP = "NO_DSP"; + static constexpr const char* RTE_MVE = "MVE"; + static constexpr const char* RTE_FP_MVE = "FP_FVE"; + static constexpr const char* RTE_NO_MVE = "NO_MVE"; + static constexpr const char* RTE_ENDIAN_BIG = "Big-endian"; + static constexpr const char* RTE_ENDIAN_LITTLE = "Little-endian"; + static constexpr const char* RTE_ENDIAN_CONFIGURABLE = "Configurable"; + static constexpr const char* RTE_SECURE = "Secure"; + static constexpr const char* RTE_NON_SECURE = "Non-secure"; + static constexpr const char* RTE_TZ_DISABLED = "TZ-disabled"; + static constexpr const char* RTE_NO_TZ = "NO_TZ"; + static constexpr const char* RTE_BTI = "BTI"; + static constexpr const char* RTE_BTI_SIGNRET = "BTI_SIGNRET"; + static constexpr const char* RTE_NO_BRANCHPROT = "NO_BRANCHPROT"; + static constexpr const char* RTE_NO_PACBTI = "NO_PACBTI"; + + static const StrMap DeviceAttributesKeys; + static const StrPairVecMap DeviceAttributesValues; + + /** + * @brief get equivalent device attribute + * @param key device attribute rte key + * @param value device attribute value (rte or yaml) + * @return rte or yaml equivalent device value + */ + static const std::string& GetDeviceAttribute(const std::string& key, const std::string& value); + }; #endif // RteConstants_H diff --git a/libs/rteutils/include/RteUtils.h b/libs/rteutils/include/RteUtils.h index 9f53fc949..20845ca93 100644 --- a/libs/rteutils/include/RteUtils.h +++ b/libs/rteutils/include/RteUtils.h @@ -20,14 +20,6 @@ #include "VersionCmp.h" #include "WildCards.h" -#include -#include -#include -#include -#include -#include - - class RteUtils { private: @@ -37,7 +29,7 @@ class RteUtils /** * @brief determine prefix of a string * @param s string containing the prefix - * @param delimiter delimiter after the prefix + * @param delimiter char delimiter after the prefix * @param withDelimiter true if returned string should contain delimiter, otherwise false * @return return prefix of a string with or without delimiter */ @@ -45,7 +37,7 @@ class RteUtils /** * @brief determine suffix of a string * @param s string containing the suffix - * @param delimiter delimiter ahead of the suffix + * @param delimiter char delimiter before suffix * @param withDelimiter true if returned string should contain delimiter, otherwise false * @return return suffix of a string with or without delimiter */ @@ -53,21 +45,21 @@ class RteUtils /** * @brief determine suffix as integer * @param s string containing the suffix - * @param delimiter delimiter ahead of the suffix + * @param delimiter char delimiter before suffix * @return return suffix as integer */ static int GetSuffixAsInt(const std::string& s, char delimiter = ':'); /** * @brief determine string after a delimiter * @param s string containing delimiter - * @param delimiter delimiter to look for + * @param delimiter string delimiter to look for * @return return string after delimiter */ static std::string RemovePrefixByString(const std::string& s, const char* delimiter = ":"); /** * @brief determine string ahead of a delimiter * @param s string containing delimiter - * @param delimiter delimiter to look for + * @param delimiter string delimiter to look for * @return return string ahead of delimiter */ static std::string RemoveSuffixByString(const std::string& s, const char* delimiter = ":"); @@ -136,6 +128,14 @@ class RteUtils */ static std::string& ReplaceAll(std::string& str, const std::string& toReplace, const std::string& with); + /** + * @brief expand string by replacing $keyword$ with corresponding values + * @param source string to expand + * @param variables string to string map with keyword values + * @return expanded string + */ + static std::string ExpandString(const std::string& src, const StrMap& variables); + /** * @brief replace blank(s) with underscore(s) * @param s string to be manipulated @@ -346,18 +346,7 @@ class RteUtils * @return XML specification of attributes */ static std::string ToXmlString(const std::map& attributes); - /** - * @brief remove duplicate elements from vector without changing the order of elements - * @param input vector to be processed - */ - template - static void RemoveVectorDuplicates(std::vector& elemVec) { - auto end = elemVec.end(); - for (auto itr = elemVec.begin(); itr != end; ++itr) { - end = std::remove(itr + 1, end, *itr); - } - elemVec.erase(end, elemVec.end()); - } + static const std::string EMPTY_STRING; static const std::string DASH_STRING; diff --git a/libs/rteutils/src/CollectionUtils.cpp b/libs/rteutils/src/CollectionUtils.cpp new file mode 100644 index 000000000..1b5d104a5 --- /dev/null +++ b/libs/rteutils/src/CollectionUtils.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "CollectionUtils.h" +#include + +using namespace std; + +void CollectionUtils::PushBackUniquely(vector& vec, const string& value) { + if (find(vec.cbegin(), vec.cend(), value) == vec.cend()) { + vec.push_back(value); + } +} + +void CollectionUtils::PushBackUniquely(list& list, const string& value) { + if (find(list.cbegin(), list.cend(), value) == list.cend()) { + list.push_back(value); + } +} + +void CollectionUtils::PushBackUniquely(StrPairVec& vec, const StrPair& value) { + for (const auto& item : vec) { + if ((value.first == item.first) && (value.second == item.second)) { + return; + } + } + vec.push_back(value); +} + +StrVecMap CollectionUtils::MergeStrVecMap(const StrVecMap& map1, const StrVecMap& map2) { + StrVecMap mergedMap(map1); + mergedMap.insert(map2.begin(), map2.end()); + return mergedMap; +} + +// end of CollectionUtils.cpp diff --git a/libs/rteutils/src/RteConstants.cpp b/libs/rteutils/src/RteConstants.cpp new file mode 100644 index 000000000..3efbbb0f9 --- /dev/null +++ b/libs/rteutils/src/RteConstants.cpp @@ -0,0 +1,60 @@ +/******************************************************************************/ +/* RTE - CMSIS Run-Time Environment */ +/******************************************************************************/ +/** @file RteConstants.cpp + * @brief CMSIS RTE Data Model +*/ +/******************************************************************************/ +/* + * Copyright (c) 2020-2024 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ +/******************************************************************************/ + +#include "RteConstants.h" +#include "RteUtils.h" + +using namespace std; + +const StrMap RteConstants::DeviceAttributesKeys = { + { RTE_DFPU , YAML_FPU }, + { RTE_DDSP , YAML_DSP }, + { RTE_DMVE , YAML_MVE }, + { RTE_DENDIAN , YAML_ENDIAN }, + { RTE_DSECURE , YAML_TRUSTZONE }, + { RTE_DBRANCHPROT, YAML_BRANCH_PROTECTION }, +}; + +const StrPairVecMap RteConstants::DeviceAttributesValues = { + { RTE_DFPU , {{ RTE_DP_FPU , YAML_FPU_DP }, + { RTE_SP_FPU , YAML_FPU_SP }, + { RTE_NO_FPU , YAML_OFF }}}, + { RTE_DDSP , {{ RTE_DSP , YAML_ON }, + { RTE_NO_DSP , YAML_OFF }}}, + { RTE_DMVE , {{ RTE_FP_MVE , YAML_MVE_FP }, + { RTE_MVE , YAML_MVE_INT }, + { RTE_NO_MVE , YAML_OFF }}}, + { RTE_DENDIAN , {{ RTE_ENDIAN_BIG , YAML_ENDIAN_BIG }, + { RTE_ENDIAN_LITTLE, YAML_ENDIAN_LITTLE }}}, + { RTE_DSECURE , {{ RTE_SECURE , YAML_TZ_SECURE }, + { RTE_NON_SECURE , YAML_TZ_NON_SECURE }, + { RTE_TZ_DISABLED , YAML_OFF }}}, + { RTE_DBRANCHPROT, {{ RTE_BTI , YAML_BP_BTI }, + { RTE_BTI_SIGNRET , YAML_BP_BTI_SIGNRET }, + { RTE_NO_BRANCHPROT, YAML_OFF }}}, +}; + +const string& RteConstants::GetDeviceAttribute(const string& key, const string& value) { + const auto& values = DeviceAttributesValues.at(key); + for (const auto& [rte, yaml] : values) { + if (value == rte) { + return yaml; + } else if (value == yaml) { + return rte; + } + } + return RteUtils::EMPTY_STRING; +} + +// end of RteConstants.cpp diff --git a/libs/rteutils/src/RteUtils.cpp b/libs/rteutils/src/RteUtils.cpp index b8b82dcc6..781b8f3d7 100644 --- a/libs/rteutils/src/RteUtils.cpp +++ b/libs/rteutils/src/RteUtils.cpp @@ -17,6 +17,7 @@ #include #include +#include using namespace std; @@ -154,6 +155,19 @@ std::string& RteUtils::ReplaceAll(std::string& str, const string& toReplace, con return str; } +string RteUtils::ExpandString(const string& src, const StrMap& variables) { + string ret = src; + if (regex_match(ret, regex(".*\\$.*\\$.*"))) { + for (const auto& [varName, replacement] : variables) { + const string var = "$" + varName + "$"; + size_t index = 0; + while ((index = ret.find(var)) != string::npos) { + ret.replace(index, var.length(), replacement); + } + } + } + return ret; +} string RteUtils::SpacesToUnderscore(const string& s) { @@ -238,9 +252,6 @@ string RteUtils::EnsureLf(const std::string& s) return ReplaceAll(tmp, RteUtils::CR_STRING, RteUtils::LF_STRING); } - - - string RteUtils::ExpandInstancePlaceholders(const string& s, int count) { static string INSTANCE = "%Instance%"; @@ -262,7 +273,6 @@ string RteUtils::ExpandInstancePlaceholders(const string& s, int count) return result; } - string RteUtils::ExtractFileName(const string& fileName) { string::size_type pos = fileName.find_last_of("\\/"); diff --git a/libs/rteutils/test/src/RteUtilsTest.cpp b/libs/rteutils/test/src/RteUtilsTest.cpp index a763dc297..08700ad43 100644 --- a/libs/rteutils/test/src/RteUtilsTest.cpp +++ b/libs/rteutils/test/src/RteUtilsTest.cpp @@ -27,6 +27,21 @@ TEST(RteUtilsTest, StringToFrom) { EXPECT_EQ(RteUtils::LongToString(32,16), "0x20"); } +TEST(RteUtilsTest, StringToInt) { + map testDataVec = { + { "0", 0 }, + { " ", 0 }, + { "", 0 }, + { "alphanum012345", 0 }, + { "000", 0 }, + { "123", 123 }, + { "+456", 456 }, + }; + for (const auto& [input, expected] : testDataVec) { + EXPECT_EQ(RteUtils::StringToInt(input, 0), expected); + } +} + TEST(RteUtilsTest, Trim) { EXPECT_EQ(RteUtils::Trim("").empty(), true); EXPECT_EQ(RteUtils::Trim(" \t\n\r").empty(), true); @@ -333,22 +348,22 @@ TEST(RteUtilsTest, RemoveVectorDuplicates) { vector testInput = { 1,2,3,2,4,5,3,6 }; vector expected = { 1,2,3,4,5,6 }; - RteUtils::RemoveVectorDuplicates(testInput); + CollectionUtils::RemoveVectorDuplicates(testInput); EXPECT_EQ(testInput, expected); testInput = { 1,1,3,3,1,2,2 }; expected = { 1,3,2 }; - RteUtils::RemoveVectorDuplicates(testInput); + CollectionUtils::RemoveVectorDuplicates(testInput); EXPECT_EQ(testInput, expected); testInput = { 1,1,1,1,1,1,1,1,1 }; expected = { 1 }; - RteUtils::RemoveVectorDuplicates(testInput); + CollectionUtils::RemoveVectorDuplicates(testInput); EXPECT_EQ(testInput, expected); testInput = { }; expected = { }; - RteUtils::RemoveVectorDuplicates(testInput); + CollectionUtils::RemoveVectorDuplicates(testInput); EXPECT_EQ(testInput, expected); } @@ -438,4 +453,18 @@ TEST(RteUtils, CollectionUtils) EXPECT_EQ(*get_or_default(strToPtr, "four", sDefault), 'd'); } +TEST(RteUtils, ExpandString) { + StrMap variables = { + {"Foo", "./foo"}, + {"Bar", "./bar"}, + {"Foo Bar", "./foo-bar"}, + }; + EXPECT_EQ(RteUtils::ExpandString("path1: $Foo/bar", variables), "path1: $Foo/bar"); + EXPECT_EQ(RteUtils::ExpandString("path1: $Foo$/bar", variables), "path1: ./foo/bar"); + EXPECT_EQ(RteUtils::ExpandString("path2: $Bar$/foo", variables), "path2: ./bar/foo"); + EXPECT_EQ(RteUtils::ExpandString("$Foo$ $Bar$", variables), "./foo ./bar"); + EXPECT_EQ(RteUtils::ExpandString("$Foo Bar$", variables), "./foo-bar"); + EXPECT_EQ(RteUtils::ExpandString("$Foo$ $Foo$ $Foo$", variables), "./foo ./foo ./foo"); +} + // end of RteUtilsTest.cpp diff --git a/libs/xmltree/include/XmlItem.h b/libs/xmltree/include/XmlItem.h index e58599f5f..7a4c719e0 100644 --- a/libs/xmltree/include/XmlItem.h +++ b/libs/xmltree/include/XmlItem.h @@ -469,14 +469,14 @@ class XmlItem * @param rootFileName absolute file name string */ virtual void SetRootFileName(const std::string& rootFileName) { - // default does nothing + AddAttribute(".", rootFileName, false); // default adds "." attribute } /** * @brief get absolute filename associated with the root item this instance belongs to - * @return file name string, empty if no file is associated (default) + * @return file name string, empty if no file is associated */ - virtual const std::string& GetRootFileName() const { return EMPTY_STRING; } + virtual const std::string& GetRootFileName() const { return GetAttribute("."); } /** * @brief return absolute path of the file this item is read from or associated with diff --git a/libs/xmltree/include/XmlTreeItem.h b/libs/xmltree/include/XmlTreeItem.h index 2eb3f723b..664c4e59b 100644 --- a/libs/xmltree/include/XmlTreeItem.h +++ b/libs/xmltree/include/XmlTreeItem.h @@ -366,9 +366,14 @@ class XmlTreeItem : public XmlItem */ const std::string& GetRootFileName() const override { - TITEM* root = GetRoot(); - if (root && root != this) // to protect recursion - return root->GetRootFileName(); + const std::string& rootFileName = XmlItem::GetRootFileName(); + if(!rootFileName.empty()) { + return rootFileName; + } + TITEM* parent = GetParent(); + if(parent) { + return parent->GetRootFileName(); + } return EMPTY_STRING; } diff --git a/libs/xmltree/test/src/XmlTreeTest.cpp b/libs/xmltree/test/src/XmlTreeTest.cpp index cc4ad8ce3..8308cc638 100644 --- a/libs/xmltree/test/src/XmlTreeTest.cpp +++ b/libs/xmltree/test/src/XmlTreeTest.cpp @@ -71,5 +71,19 @@ TEST(XmlTreeTest, GetAttribute) { EXPECT_FALSE(e.HasValue(val)); } EXPECT_FALSE(e.EraseAttributes("attr*")); + + EXPECT_TRUE(e.GetRootFileName().empty()); + e.SetRootFileName("e/foo.bar"); + EXPECT_EQ(e.GetRootFileName(), "e/foo.bar"); + EXPECT_EQ(e.GetRootFilePath(true), "e/"); + EXPECT_EQ(e.GetRootFilePath(false), "e"); + + XMLTreeElement* e1 = new XMLTreeElement(e); + XMLTreeElement* e2 = new XMLTreeElement(e1); + EXPECT_EQ(e1->GetRootFileName(), "e/foo.bar"); + EXPECT_EQ(e2->GetRootFileName(), "e/foo.bar"); + e1->SetRootFileName("e1/foo.bar"); + EXPECT_EQ(e1->GetRootFileName(), "e1/foo.bar"); + EXPECT_EQ(e2->GetRootFileName(), "e1/foo.bar"); } // end of XmlTreeTest.cpp diff --git a/libs/ymltree/test/YmlTreeTest.cpp b/libs/ymltree/test/YmlTreeTest.cpp index 310b0e69e..f5a610c85 100644 --- a/libs/ymltree/test/YmlTreeTest.cpp +++ b/libs/ymltree/test/YmlTreeTest.cpp @@ -217,13 +217,13 @@ TEST_F(YmlTreeTestF, ReadFileDefault) { EXPECT_TRUE(success); EXPECT_TRUE(tree.GetRoot()); XMLTreeElement* root = tree.GetRoot() ? tree.GetRoot()->GetFirstChild() : nullptr; - EXPECT_TRUE(root); + ASSERT_TRUE(root); + EXPECT_EQ(root->GetRootFileName(), ymlIn); XmlFormatter xmlFormatter; string xmlContent = xmlFormatter.FormatElement(root); tree.Clear(); - } // end of YmlTreeTest.cpp diff --git a/tools/buildmgr/cbuild/include/CbuildUtils.h b/tools/buildmgr/cbuild/include/CbuildUtils.h index a5a75e1f2..39b78badb 100644 --- a/tools/buildmgr/cbuild/include/CbuildUtils.h +++ b/tools/buildmgr/cbuild/include/CbuildUtils.h @@ -41,7 +41,6 @@ struct CbuildPackItem class CbuildUtils { public: - typedef std::pair Result; CbuildUtils(); ~CbuildUtils(); @@ -119,13 +118,6 @@ class CbuildUtils { */ static const std::string StrPathConv(const std::string& path); - /** - * @brief execute shell command - * @param cmd string shell command to be executed - * @return command execution result - */ - static const Result ExecCommand(const std::string& cmd); - /** * @brief convert path to absolute if it's unambiguously recognized as relative * accept toolchain flag as input (e.g. key=./relative/path) @@ -135,13 +127,6 @@ class CbuildUtils { */ static const std::string StrPathAbsolute(const std::string& path, const std::string& base); - /** - * @brief Add a value into a vector if it does not already exist in the vector - * @param vec The vector to add the value into - * @param value the value to add - */ - static void PushBackUniquely(std::vector& vec, const std::string& value); - /** * @brief generate json packlist file * @param packList vector with missing packs diff --git a/tools/buildmgr/cbuild/src/CbuildModel.cpp b/tools/buildmgr/cbuild/src/CbuildModel.cpp index e61a3c614..5862dc9ea 100644 --- a/tools/buildmgr/cbuild/src/CbuildModel.cpp +++ b/tools/buildmgr/cbuild/src/CbuildModel.cpp @@ -1478,17 +1478,17 @@ bool CbuildModel::EvalAccessSequence() { // remove duplicates for (auto& itemList : fieldList) { for (auto& [_, item] : *itemList) { - RteUtils::RemoveVectorDuplicates(item); + CollectionUtils::RemoveVectorDuplicates(item); } } - RteUtils::RemoveVectorDuplicates(m_targetDefines); - RteUtils::RemoveVectorDuplicates(m_targetIncludePaths); - RteUtils::RemoveVectorDuplicates(m_targetCFlags); - RteUtils::RemoveVectorDuplicates(m_targetCxxFlags); - RteUtils::RemoveVectorDuplicates(m_targetAsFlags); - RteUtils::RemoveVectorDuplicates(m_targetLdFlags); - RteUtils::RemoveVectorDuplicates(m_targetLdCFlags); - RteUtils::RemoveVectorDuplicates(m_targetLdCxxFlags); + CollectionUtils::RemoveVectorDuplicates(m_targetDefines); + CollectionUtils::RemoveVectorDuplicates(m_targetIncludePaths); + CollectionUtils::RemoveVectorDuplicates(m_targetCFlags); + CollectionUtils::RemoveVectorDuplicates(m_targetCxxFlags); + CollectionUtils::RemoveVectorDuplicates(m_targetAsFlags); + CollectionUtils::RemoveVectorDuplicates(m_targetLdFlags); + CollectionUtils::RemoveVectorDuplicates(m_targetLdCFlags); + CollectionUtils::RemoveVectorDuplicates(m_targetLdCxxFlags); return true; } diff --git a/tools/buildmgr/cbuild/src/CbuildUtils.cpp b/tools/buildmgr/cbuild/src/CbuildUtils.cpp index a2b251405..bb88a9826 100644 --- a/tools/buildmgr/cbuild/src/CbuildUtils.cpp +++ b/tools/buildmgr/cbuild/src/CbuildUtils.cpp @@ -185,32 +185,6 @@ const string CbuildUtils::StrPathAbsolute(const string& flagText, const string& return result.replace(offset, string::npos, "\"" + path + "\""); } - -const CbuildUtils::Result CbuildUtils::ExecCommand(const string& cmd) { - array buffer; - string result; - int ret_code = -1; - std::function close = _pclose; - std::function open = _popen; - - auto deleter = [&close, &ret_code](FILE* cmd) { ret_code = close(cmd); }; - { - const unique_ptr pipe(open(cmd.c_str(), "r"), deleter); - if (pipe) { - while (fgets(buffer.data(), static_cast(buffer.size()), pipe.get()) != nullptr) { - result += buffer.data(); - } - } - } - return make_pair(result, ret_code); -} - -void CbuildUtils::PushBackUniquely(std::vector& vec, const std::string& value) { - if (find(vec.cbegin(), vec.cend(), value) == vec.cend()) { - vec.push_back(value); - } -} - string CbuildUtils::GenerateJsonPackList(const std::vector& packList) { string json; if (!packList.empty()) { diff --git a/tools/buildmgr/cbuildgen/src/BuildSystemGenerator.cpp b/tools/buildmgr/cbuildgen/src/BuildSystemGenerator.cpp index e7cc254ab..330fefae7 100644 --- a/tools/buildmgr/cbuildgen/src/BuildSystemGenerator.cpp +++ b/tools/buildmgr/cbuildgen/src/BuildSystemGenerator.cpp @@ -396,14 +396,14 @@ bool BuildSystemGenerator::GenAuditFile(void) { void BuildSystemGenerator::MergeVecStr(const std::vector& src, std::vector& dest) { for (const auto& item : src) { - CbuildUtils::PushBackUniquely(dest, item); + CollectionUtils::PushBackUniquely(dest, item); } } void BuildSystemGenerator::MergeVecStrNorm(const std::vector& src, std::vector& dest) { for (const auto& item : src) { - CbuildUtils::PushBackUniquely(dest, StrNorm(item)); + CollectionUtils::PushBackUniquely(dest, StrNorm(item)); } } diff --git a/tools/buildmgr/test/integrationtests/src/CBuildGenTestFixture.cpp b/tools/buildmgr/test/integrationtests/src/CBuildGenTestFixture.cpp index a01317796..ebd6188fc 100644 --- a/tools/buildmgr/test/integrationtests/src/CBuildGenTestFixture.cpp +++ b/tools/buildmgr/test/integrationtests/src/CBuildGenTestFixture.cpp @@ -83,7 +83,7 @@ void CBuildGenTestFixture::RunCBuildGen(const TestParam& param, string projpath, '/' + param.targetArg + ".cprj\" " + param.command + (param.options.empty() ? "" : " ") + param.options + "\""; } - const auto& ret_val = CbuildUtils::ExecCommand(cmd.c_str()); + const auto& ret_val = CrossPlatformUtils::ExecCommand(cmd.c_str()); stdoutStr = ret_val.first; ASSERT_EQ(param.expect, (ret_val.second == 0) ? true : false); } @@ -209,17 +209,17 @@ void CBuildGenTestFixture::CheckDescriptionFiles(const string& filename1, const } -void CBuildGenTestFixture::GetDirectoryItems(const string& inPath, set &Result, const string& ignoreDir) { +void CBuildGenTestFixture::GetDirectoryItems(const string& inPath, set &result, const string& ignoreDir) { string itemPath; for (auto& item : fs::directory_iterator(inPath)) { if (fs::is_directory(fs::status(item))) { if (item.path().filename().compare(ignoreDir) == 0) { continue; } - GetDirectoryItems(item.path().generic_string(), Result, ignoreDir); + GetDirectoryItems(item.path().generic_string(), result, ignoreDir); } itemPath = item.path().generic_string(); - Result.insert(itemPath.substr(inPath.length() + 1, itemPath.length())); + result.insert(itemPath.substr(inPath.length() + 1, itemPath.length())); } } diff --git a/tools/buildmgr/test/integrationtests/src/CBuildGenTestFixture.h b/tools/buildmgr/test/integrationtests/src/CBuildGenTestFixture.h index cc82db4be..a3ca7fd46 100644 --- a/tools/buildmgr/test/integrationtests/src/CBuildGenTestFixture.h +++ b/tools/buildmgr/test/integrationtests/src/CBuildGenTestFixture.h @@ -22,7 +22,7 @@ class CBuildGenTestFixture : public ::testing::Test { void CheckCMakeIntermediateDir (const TestParam& param, const std::string& intdir); void CheckCPInstallFile (const TestParam& param, bool json=false); - void GetDirectoryItems (const std::string& inPath, std::set &Result, const std::string& ignoreDir); + void GetDirectoryItems (const std::string& inPath, std::set &result, const std::string& ignoreDir); std::string stdoutStr; }; diff --git a/tools/buildmgr/test/integrationtests/src/DebPkgTests.cpp b/tools/buildmgr/test/integrationtests/src/DebPkgTests.cpp index fd2b2c2de..3496e3f9b 100644 --- a/tools/buildmgr/test/integrationtests/src/DebPkgTests.cpp +++ b/tools/buildmgr/test/integrationtests/src/DebPkgTests.cpp @@ -33,14 +33,14 @@ void DebPkgTests::SetUp() { string DebPkgTests::FindPackage(const string& path) { string cmd = "find " + path + " -name *.deb"; - string pkgfile = CbuildUtils::ExecCommand(cmd.c_str()).first; + string pkgfile = CrossPlatformUtils::ExecCommand(cmd.c_str()).first; pkgfile.erase(pkgfile.find_last_not_of(" \f\n\r\t\v") + 1); return pkgfile; } void DebPkgTests::ExtractPackage(const string& pkg, const string& extPath) { string cmd = "dpkg-deb -xv " + pkg + " " + extPath; - auto res = CbuildUtils::ExecCommand(cmd.c_str()); + auto res = CrossPlatformUtils::ExecCommand(cmd.c_str()); ASSERT_FALSE(res.first.empty()); ASSERT_EQ(res.second, 0); @@ -93,13 +93,13 @@ TEST_F(DebPkgTests, CheckMetadata) { cmd = "find " + debpkgpath + " -name *.deb"; - auto result = CbuildUtils::ExecCommand(cmd.c_str()); + auto result = CrossPlatformUtils::ExecCommand(cmd.c_str()); ASSERT_FALSE(result.first.empty()); ASSERT_EQ(result.second, 0); string pkgfile = result.first; cmd = "dpkg-deb --info " + pkgfile; - auto res = CbuildUtils::ExecCommand(cmd.c_str()); + auto res = CrossPlatformUtils::ExecCommand(cmd.c_str()); ASSERT_FALSE(res.first.empty()); ASSERT_EQ(res.second, 0); diff --git a/tools/buildmgr/test/unittests/src/BuildSystemGeneratorTests.cpp b/tools/buildmgr/test/unittests/src/BuildSystemGeneratorTests.cpp index ac0ab779d..34e3cf483 100644 --- a/tools/buildmgr/test/unittests/src/BuildSystemGeneratorTests.cpp +++ b/tools/buildmgr/test/unittests/src/BuildSystemGeneratorTests.cpp @@ -54,7 +54,7 @@ void BuildSystemGeneratorTests::CreateBuildArtifacts(const string& outPath, RteFsUtils::CreateDirectories(outPath); for (const auto& fileName : testBuildArtifactNames) { string filePath = outPath + "/" + fileName; - ASSERT_TRUE(RteFsUtils::CreateFile(filePath, RteUtils::EMPTY_STRING)) << + ASSERT_TRUE(RteFsUtils::CreateTextFile(filePath, RteUtils::EMPTY_STRING)) << "unable to create file '" + filePath + "'"; } } @@ -186,7 +186,7 @@ TEST_F(BuildSystemGeneratorTests, GenAuditFile_With_Existing_Audit_File) { }; CreateBuildArtifacts(testout_folder, testBuildArtifactNames); - RteFsUtils::CreateFile(file, RteUtils::EMPTY_STRING); + RteFsUtils::CreateTextFile(file, RteUtils::EMPTY_STRING); EXPECT_TRUE(GenAuditFile()); EXPECT_TRUE(fs::exists(file, ec)); diff --git a/tools/buildmgr/test/unittests/src/CbuildModelTests.cpp b/tools/buildmgr/test/unittests/src/CbuildModelTests.cpp index 8f21ff035..739e150c2 100644 --- a/tools/buildmgr/test/unittests/src/CbuildModelTests.cpp +++ b/tools/buildmgr/test/unittests/src/CbuildModelTests.cpp @@ -50,9 +50,9 @@ TEST_F(CbuildModelTests, GetCompatibleToolchain_Select_Latest) { // Select latest compatible toolchain ASSERT_TRUE(RteFsUtils::CreateDirectories(toolchainDir)); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/AC6.6.6.4.cmake", "")); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/AC6.6.16.0.cmake", "")); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/GCC.6.19.0.cmake", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/AC6.6.6.4.cmake", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/AC6.6.16.0.cmake", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/GCC.6.19.0.cmake", "")); EXPECT_TRUE(GetCompatibleToolchain(name, versionRange, toolchainDir, envVars)); EXPECT_EQ(m_toolchainConfigVersion, expectedToolchainVersion); EXPECT_EQ(m_toolchainConfig, expectedToolchainConfig); @@ -79,8 +79,8 @@ TEST_F(CbuildModelTests, GetCompatibleToolchain_Invalid_Files) { // No .cmake file found ASSERT_TRUE(RteFsUtils::CreateDirectories(toolchainDir)); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/test.info", "")); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/AC6.info", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/test.info", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/AC6.info", "")); EXPECT_FALSE(GetCompatibleToolchain(name, versionRange, toolchainDir, envVars)); EXPECT_EQ(m_toolchainConfigVersion, RteUtils::EMPTY_STRING); EXPECT_EQ(m_toolchainConfig, RteUtils::EMPTY_STRING); @@ -97,9 +97,9 @@ TEST_F(CbuildModelTests, GetCompatibleToolchain_Select_Latest_recursively) { // Select latest compatible toolchain ASSERT_TRUE(RteFsUtils::CreateDirectories(toolchainDir+"/Test")); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/Test/AC6.6.6.4.cmake", "")); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/Test/AC6.6.16.0.cmake", "")); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/Test/GCC.6.19.0.cmake", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/Test/AC6.6.6.4.cmake", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/Test/AC6.6.16.0.cmake", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/Test/GCC.6.19.0.cmake", "")); EXPECT_TRUE(GetCompatibleToolchain(name, versionRange, toolchainDir, envVars)); EXPECT_EQ(m_toolchainConfigVersion, expectedToolchainVersion); EXPECT_EQ(m_toolchainConfig, expectedToolchainConfig); @@ -124,9 +124,9 @@ TEST_F(CbuildModelTests, GetCompatibleToolchain_Registered) { // Select latest compatible toolchain ASSERT_TRUE(RteFsUtils::CreateDirectories(toolchainDir + "/Test")); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/Test/AC6.6.6.4.cmake", "")); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/Test/AC6.6.16.0.cmake", "")); - ASSERT_TRUE(RteFsUtils::CreateFile(toolchainDir + "/Test/GCC.6.19.0.cmake", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/Test/AC6.6.6.4.cmake", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/Test/AC6.6.16.0.cmake", "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(toolchainDir + "/Test/GCC.6.19.0.cmake", "")); EXPECT_TRUE(GetCompatibleToolchain(name, versionRange, toolchainDir, envVars)); EXPECT_EQ(m_toolchainConfigVersion, expectedToolchainVersion); EXPECT_EQ(m_toolchainConfig, expectedToolchainConfig); diff --git a/tools/buildmgr/test/unittests/src/UtilsTests.cpp b/tools/buildmgr/test/unittests/src/UtilsTests.cpp index 65b10d03c..68df74452 100644 --- a/tools/buildmgr/test/unittests/src/UtilsTests.cpp +++ b/tools/buildmgr/test/unittests/src/UtilsTests.cpp @@ -165,23 +165,6 @@ TEST_F(CbuildUtilsTests, StrPathAbsolute) { // Restore CWD fs::current_path(cwd, ec); } - -TEST_F(CbuildUtilsTests, ExecCommand) { - auto result = CbuildUtils::ExecCommand("invalid command"); - EXPECT_EQ(false, (0 == result.second) ? true : false) << result.first; - - string testdir = "mkdir_test_dir"; - fs::current_path(testout_folder); - if (fs::exists(testdir)) RemoveDir(testdir); - - result = CbuildUtils::ExecCommand("mkdir " + testdir); - EXPECT_TRUE(fs::exists(testdir)); - EXPECT_EQ(true, (0 == result.second) ? true : false) << result.first; - - fs::current_path(CBuildUnitTestEnv::workingDir); - RemoveDir(testdir); -} - TEST_F(CbuildUtilsTests, EscapeQuotes) { string result = CbuildUtils::EscapeQuotes("-DFILE=\"config.h\""); EXPECT_EQ(result, "-DFILE=\\\"config.h\\\""); diff --git a/tools/packchk/src/PackChk.cpp b/tools/packchk/src/PackChk.cpp index f034d015d..617123160 100644 --- a/tools/packchk/src/PackChk.cpp +++ b/tools/packchk/src/PackChk.cpp @@ -75,7 +75,7 @@ bool PackChk::CreatePacknameFile(const string& filename, RtePackage* pKg) string absPath = RteFsUtils::AbsolutePath(filename).generic_string(); string content = pdscRef + "." + pkgVendor + "." + pkgVersion + PKG_FEXT; - if(!RteFsUtils::CreateFile(absPath, content)) { + if(!RteFsUtils::CreateTextFile(absPath, content)) { LogMsg("M205", PATH(absPath)); return false; } diff --git a/tools/packchk/test/integtests/src/PackChkIntegTests.cpp b/tools/packchk/test/integtests/src/PackChkIntegTests.cpp index 6bb753c2c..28fe0a730 100644 --- a/tools/packchk/test/integtests/src/PackChkIntegTests.cpp +++ b/tools/packchk/test/integtests/src/PackChkIntegTests.cpp @@ -295,11 +295,11 @@ TEST_F(PackChkIntegTests, AddRefPacks) { refPack3 = outDir + refPack3; refPack4 = outDir + refPack4; - ASSERT_TRUE(RteFsUtils::CreateFile(refPackTest, contentBegin + refNameTest + contentEnd)); - ASSERT_TRUE(RteFsUtils::CreateFile(refPack1, contentBegin + refName1 + contentEnd)); - ASSERT_TRUE(RteFsUtils::CreateFile(refPack2, contentBegin + refName2 + contentEnd)); - ASSERT_TRUE(RteFsUtils::CreateFile(refPack3, contentBegin + refName3 + contentEnd)); - ASSERT_TRUE(RteFsUtils::CreateFile(refPack4, contentBegin + refName4 + contentEnd)); + ASSERT_TRUE(RteFsUtils::CreateTextFile(refPackTest, contentBegin + refNameTest + contentEnd)); + ASSERT_TRUE(RteFsUtils::CreateTextFile(refPack1, contentBegin + refName1 + contentEnd)); + ASSERT_TRUE(RteFsUtils::CreateTextFile(refPack2, contentBegin + refName2 + contentEnd)); + ASSERT_TRUE(RteFsUtils::CreateTextFile(refPack3, contentBegin + refName3 + contentEnd)); + ASSERT_TRUE(RteFsUtils::CreateTextFile(refPack4, contentBegin + refName4 + contentEnd)); ASSERT_TRUE(RteFsUtils::Exists(refPackTest)); ASSERT_TRUE(RteFsUtils::Exists(refPack1)); diff --git a/tools/packchk/test/unittests/src/TestCheckFiles.cpp b/tools/packchk/test/unittests/src/TestCheckFiles.cpp index c6910604c..8d6001c0d 100644 --- a/tools/packchk/test/unittests/src/TestCheckFiles.cpp +++ b/tools/packchk/test/unittests/src/TestCheckFiles.cpp @@ -118,7 +118,7 @@ TEST_F(TestCheckFiles, CheckFileExtension_IncludeNoSlash) { TEST_F(TestCheckFiles, CheckFileExtension_IncludeNotADir) { // GIVEN an existing header file const string checkFile = "CheckFileExtension/TheIncludeDir/header.h"; - ASSERT_TRUE(RteFsUtils::CreateFile(string(BUILD_FOLDER)+checkFile, "")); + ASSERT_TRUE(RteFsUtils::CreateTextFile(string(BUILD_FOLDER)+checkFile, "")); // ... AND an item refering to this file as category include RteItem item(NULL); @@ -157,10 +157,10 @@ TEST_F(TestCheckFiles, CheckCaseSense) RteFsUtils::RemoveDir(testDataFolder); } ASSERT_TRUE(RteFsUtils::CreateDirectories(testApiFolder)); - ASSERT_TRUE(RteFsUtils::CreateFile( + ASSERT_TRUE(RteFsUtils::CreateTextFile( testApiFolder + "/Exclusive.h", RteUtils::EMPTY_STRING)); ASSERT_TRUE(RteFsUtils::CreateDirectories(testDataFolder + "/.test1")); - ASSERT_TRUE(RteFsUtils::CreateFile( + ASSERT_TRUE(RteFsUtils::CreateTextFile( testDataFolder + "/.test1/NonExclusive.h", RteUtils::EMPTY_STRING)); checkFiles.SetPackagePath(testDataFolder); diff --git a/tools/packgen/include/PackGen.h b/tools/packgen/include/PackGen.h index 1be72a186..2e6fbc030 100644 --- a/tools/packgen/include/PackGen.h +++ b/tools/packgen/include/PackGen.h @@ -195,7 +195,6 @@ YAML::Emitter& operator << (YAML::Emitter& out, const queryRequests& req); class PackGen { public: - typedef std::pair Result; /** * @brief class constructor @@ -256,13 +255,6 @@ class PackGen { */ bool CompressPack(void); - /** - * @brief execute external command in the underlying shell - * @param cmd command to be executed - * @return command execution result - */ - static const Result ExecCommand(const std::string& cmd); - protected: std::string m_manifest; std::string m_repoRoot; diff --git a/tools/packgen/src/PackGen.cpp b/tools/packgen/src/PackGen.cpp index 2bef76e05..1efcb1c61 100644 --- a/tools/packgen/src/PackGen.cpp +++ b/tools/packgen/src/PackGen.cpp @@ -9,6 +9,7 @@ #include "RteFsUtils.h" #include "XmlFormatter.h" +#include "CrossPlatformUtils.h" #include "CrossPlatform.h" #include @@ -33,7 +34,7 @@ PackGen::~PackGen(void) { } int PackGen::RunPackGen(int argc, char **argv) { - PackGen::Result result; + StrIntPair result; PackGen generator; error_code ec; @@ -110,7 +111,7 @@ int PackGen::RunPackGen(int argc, char **argv) { if (!generator.m_noComponents || generator.m_verbose) { // Check CMake - result = generator.ExecCommand("cmake --version"); + result = CrossPlatformUtils::ExecCommand("cmake --version"); if (result.second) { cerr << "packgen error: CMake was not found" << endl; return 1; @@ -958,7 +959,7 @@ void PackGen::CreatePackComponentsAndConditions(XMLTreeElement* rootElement, pac } bool PackGen::CheckPack(void) { - PackGen::Result result; + StrIntPair result; error_code ec; const auto& workingDir = fs::current_path(ec); @@ -985,7 +986,7 @@ bool PackGen::CheckPack(void) { } // packchk - result = ExecCommand("packchk \"" + pack.vendor + "." + pack.name + ".pdsc\"" + pdscList); + result = CrossPlatformUtils::ExecCommand("packchk \"" + pack.vendor + "." + pack.name + ".pdsc\"" + pdscList); if (result.second) { cerr << "packgen error: packchk failed" << endl << result.first << endl; return false; @@ -1001,7 +1002,7 @@ bool PackGen::CheckPack(void) { } bool PackGen::CompressPack(void) { - PackGen::Result result; + StrIntPair result; error_code ec; const auto& workingDir = fs::current_path(ec); @@ -1012,7 +1013,7 @@ bool PackGen::CompressPack(void) { fs::current_path(pack.outputDir, ec); // 7zip - result = ExecCommand("7z a \"" + pack.vendor + "." + pack.name + "." + pack.version + ".pack\" -tzip"); + result = CrossPlatformUtils::ExecCommand("7z a \"" + pack.vendor + "." + pack.name + "." + pack.version + ".pack\" -tzip"); if (result.second) { cerr << "packgen error: 7zip failed\n" << result.first << endl; return false; @@ -1067,7 +1068,7 @@ bool PackGen::CreateQuery() { // Run CMake const string cmd = build.options + " -S \"" + fs::path(m_manifest).parent_path().generic_string() + "\" -B \"" + buildRoot + "\""; - PackGen::Result result = ExecCommand(cmd); + auto result = CrossPlatformUtils::ExecCommand(cmd); if (result.second) { cerr << "packgen error: CMake failed\n" << result.first << endl; return false; @@ -1077,25 +1078,6 @@ bool PackGen::CreateQuery() { return true; } -const PackGen::Result PackGen::ExecCommand(const string& cmd) { - array buffer; - string result; - int ret_code = -1; - std::function close = _pclose; - std::function open = _popen; - - auto deleter = [&close, &ret_code](FILE* cmd) { ret_code = close(cmd); }; - { - const unique_ptr pipe(open(cmd.c_str(), "r"), deleter); - if (pipe) { - while (fgets(buffer.data(), static_cast(buffer.size()), pipe.get()) != nullptr) { - result += buffer.data(); - } - } - } - return make_pair(result, ret_code); -} - bool PackGen::CopyItem(const string& src, const string& dst, list& ext) { //Copy file or directory recursively filtering extensions error_code ec; diff --git a/tools/projmgr/include/ProjMgrExtGenerator.h b/tools/projmgr/include/ProjMgrExtGenerator.h index 96cd02784..5a353ef7e 100644 --- a/tools/projmgr/include/ProjMgrExtGenerator.h +++ b/tools/projmgr/include/ProjMgrExtGenerator.h @@ -48,7 +48,7 @@ class ProjMgrExtGenerator { /** * @brief class destructor */ - ~ProjMgrExtGenerator(void); + ~ProjMgrExtGenerator(); /** * @brief set check schema @@ -56,12 +56,6 @@ class ProjMgrExtGenerator { */ void SetCheckSchema(bool checkSchema); - /** - * @brief retrieve globally registered generators - * @return true if successful - */ - bool RetrieveGlobalGenerators(void); - /** * @brief verify if generator is global * @param generatorId generator identifier @@ -122,11 +116,8 @@ class ProjMgrExtGenerator { protected: ProjMgrParser* m_parser = nullptr; - StrVec m_globalGeneratorFiles; - std::map m_globalGenerators; GeneratorContextVecMap m_usedGenerators; bool m_checkSchema; - std::string m_compilerRoot; }; #endif // PROJMGREXTGENERATOR_H diff --git a/tools/projmgr/include/ProjMgrUtils.h b/tools/projmgr/include/ProjMgrUtils.h index 21189ddd7..32e4b1373 100644 --- a/tools/projmgr/include/ProjMgrUtils.h +++ b/tools/projmgr/include/ProjMgrUtils.h @@ -81,56 +81,6 @@ typedef std::vector ConnectionsCollectionVec; */ typedef std::map ConnectionsCollectionMap; -/** - * @brief string pair - */ -typedef std::pair StrPair; - -/** - * @brief string vector -*/ -typedef std::vector StrVec; - -/** - * @brief string set -*/ -typedef std::set StrSet; - -/** - * @brief vector of string pair -*/ -typedef std::vector StrPairVec; - -/** - * @brief vector of string pair pointer -*/ -typedef std::vector StrPairPtrVec; - -/** - * @brief map of vector of string pair -*/ -typedef std::map StrPairVecMap; - -/** - * @brief map of string vector -*/ -typedef std::map StrVecMap; - -/** - * @brief map of int -*/ -typedef std::map IntMap; - -/** - * @brief map of bool -*/ -typedef std::map BoolMap; - -/** - * @brief map of string -*/ -typedef std::map StrMap; - /** * @brief project manager utility class */ @@ -144,110 +94,6 @@ class ProjMgrUtils { public: - typedef std::pair Result; - - /** - * @brief output types - */ - static constexpr const char* OUTPUT_TYPE_BIN = "bin"; - static constexpr const char* OUTPUT_TYPE_ELF = "elf"; - static constexpr const char* OUTPUT_TYPE_HEX = "hex"; - static constexpr const char* OUTPUT_TYPE_LIB = "lib"; - static constexpr const char* OUTPUT_TYPE_CMSE = "cmse-lib"; - - /** - * @brief access sequences - */ - static constexpr const char* AS_SOLUTION = "Solution"; - static constexpr const char* AS_PROJECT = "Project"; - static constexpr const char* AS_COMPILER = "Compiler"; - static constexpr const char* AS_BUILD_TYPE = "BuildType"; - static constexpr const char* AS_TARGET_TYPE = "TargetType"; - static constexpr const char* AS_DNAME = "Dname"; - static constexpr const char* AS_PNAME = "Pname"; - static constexpr const char* AS_BNAME = "Bname"; - - static constexpr const char* AS_SOLUTION_DIR = "SolutionDir"; - static constexpr const char* AS_PROJECT_DIR = "ProjectDir"; - static constexpr const char* AS_OUT_DIR = "OutDir"; - static constexpr const char* AS_BIN = OUTPUT_TYPE_BIN; - static constexpr const char* AS_ELF = OUTPUT_TYPE_ELF; - static constexpr const char* AS_HEX = OUTPUT_TYPE_HEX; - static constexpr const char* AS_LIB = OUTPUT_TYPE_LIB; - static constexpr const char* AS_CMSE = OUTPUT_TYPE_CMSE; - - /** - * @brief default and toolchain specific output affixes - */ - static constexpr const char* DEFAULT_ELF_SUFFIX = ".elf"; - static constexpr const char* DEFAULT_LIB_PREFIX = ""; - static constexpr const char* DEFAULT_LIB_SUFFIX = ".a"; - - static constexpr const char* AC6_ELF_SUFFIX = ".axf"; - static constexpr const char* GCC_ELF_SUFFIX = ".elf"; - static constexpr const char* IAR_ELF_SUFFIX = ".out"; - static constexpr const char* AC6_LIB_PREFIX = ""; - static constexpr const char* GCC_LIB_PREFIX = "lib"; - static constexpr const char* IAR_LIB_PREFIX = ""; - static constexpr const char* AC6_LIB_SUFFIX = ".lib"; - static constexpr const char* GCC_LIB_SUFFIX = ".a"; - static constexpr const char* IAR_LIB_SUFFIX = ".a"; - - /** - * @brief device attributes maps - */ - static constexpr const char* YAML_FPU = "fpu"; - static constexpr const char* YAML_DSP = "dsp"; - static constexpr const char* YAML_MVE = "mve"; - static constexpr const char* YAML_ENDIAN = "endian"; - static constexpr const char* YAML_TRUSTZONE = "trustzone"; - static constexpr const char* YAML_BRANCH_PROTECTION = "branch-protection"; - - static constexpr const char* YAML_ON = "on"; - static constexpr const char* YAML_OFF = "off"; - static constexpr const char* YAML_FPU_DP = "dp"; - static constexpr const char* YAML_FPU_SP = "sp"; - static constexpr const char* YAML_MVE_FP = "fp"; - static constexpr const char* YAML_MVE_INT = "int"; - static constexpr const char* YAML_ENDIAN_BIG = "big"; - static constexpr const char* YAML_ENDIAN_LITTLE = "little"; - static constexpr const char* YAML_BP_BTI = "bti"; - static constexpr const char* YAML_BP_BTI_SIGNRET = "bti-signret"; - static constexpr const char* YAML_TZ_SECURE = "secure"; - static constexpr const char* YAML_TZ_NON_SECURE = "non-secure"; - - static constexpr const char* RTE_DFPU = "Dfpu"; - static constexpr const char* RTE_DDSP = "Ddsp"; - static constexpr const char* RTE_DMVE = "Dmve"; - static constexpr const char* RTE_DENDIAN = "Dendian"; - static constexpr const char* RTE_DSECURE = "Dsecure"; - static constexpr const char* RTE_DTZ = "Dtz"; - static constexpr const char* RTE_DBRANCHPROT = "DbranchProt"; - static constexpr const char* RTE_DPACBTI = "Dpacbti"; - - static constexpr const char* RTE_DP_FPU = "DP_FPU"; - static constexpr const char* RTE_SP_FPU = "SP_FPU"; - static constexpr const char* RTE_NO_FPU = "NO_FPU"; - static constexpr const char* RTE_DSP = "DSP"; - static constexpr const char* RTE_NO_DSP = "NO_DSP"; - static constexpr const char* RTE_MVE = "MVE"; - static constexpr const char* RTE_FP_MVE = "FP_FVE"; - static constexpr const char* RTE_NO_MVE = "NO_MVE"; - static constexpr const char* RTE_ENDIAN_BIG = "Big-endian"; - static constexpr const char* RTE_ENDIAN_LITTLE = "Little-endian"; - static constexpr const char* RTE_ENDIAN_CONFIGURABLE = "Configurable"; - static constexpr const char* RTE_SECURE = "Secure"; - static constexpr const char* RTE_NON_SECURE = "Non-secure"; - static constexpr const char* RTE_TZ_DISABLED = "TZ-disabled"; - static constexpr const char* RTE_NO_TZ = "NO_TZ"; - static constexpr const char* RTE_BTI = "BTI"; - static constexpr const char* RTE_BTI_SIGNRET = "BTI_SIGNRET"; - static constexpr const char* RTE_NO_BRANCHPROT = "NO_BRANCHPROT"; - static constexpr const char* RTE_NO_PACBTI = "NO_PACBTI"; - - static const StrMap DeviceAttributesKeys; - static const StrPairVecMap DeviceAttributesValues; - /** * @brief read gpdsc file * @param path to gpdsc file @@ -257,45 +103,7 @@ class ProjMgrUtils { */ static RtePackage* ReadGpdscFile(const std::string& gpdsc, bool& valid); - /** - * @brief execute shell command - * @param cmd string shell command to be executed - * @return command execution result - */ - static const Result ExecCommand(const std::string& cmd); - - /** - * @brief get file category according to file extension - * @param filename with extension - * @return string category - */ - static const std::string GetCategory(const std::string& file); - - /** - * @brief add a value into a vector/list if it does not already exist in the vector/list - * @param vec/list the vector/list to add the value into - * @param value the value to add - */ - static void PushBackUniquely(std::vector& vec, const std::string& value); - static void PushBackUniquely(std::list& lst, const std::string& value); - static void PushBackUniquely(StrPairVec& vec, const StrPair& value); - - /** - * @brief merge two string vector maps - * @param map1 first string vector map - * @param map2 second string vector map - * @return StrVecMap merged map - */ - static StrVecMap MergeStrVecMap(const StrVecMap& map1, const StrVecMap& map2); - - /** - * @brief convert string to int, return 0 if it's empty or not convertible - * @param string - * @return int - */ - static int StringToInt(const std::string& value); - - /** + /** * @brief expand compiler id the format @[>=] into name, minimum and maximum versions * @param compiler id * @param name reference to compiler name @@ -361,14 +169,6 @@ class ProjMgrUtils { const std::vector& allAvailableContexts, const std::vector& contextFilters); - /** - * @brief get equivalent device attribute - * @param key device attribute rte key - * @param value device attribute value (rte or yaml) - * @return rte or yaml equivalent device value - */ - static const std::string& GetDeviceAttribute(const std::string& key, const std::string& value); - /** * @brief convert a pack ID to a pack info * @param packId the pack id (YML format) diff --git a/tools/projmgr/include/ProjMgrWorker.h b/tools/projmgr/include/ProjMgrWorker.h index 2ebe340e5..0fcbbccf3 100644 --- a/tools/projmgr/include/ProjMgrWorker.h +++ b/tools/projmgr/include/ProjMgrWorker.h @@ -745,7 +745,6 @@ class ProjMgrWorker { std::vector& combinations); void PushBackUniquely(ConnectionsCollectionVec& vec, const ConnectionsCollection& value); void PushBackUniquely(std::vector& vec, const ToolchainItem& value); - std::string ExpandString(const std::string& src, const StrMap& variables); void GetRegisteredToolchains(void); bool GetLatestToolchain(ToolchainItem& toolchain); bool GetToolchainConfig(const std::string& name, const std::string& version, std::string& configPath, std::string& selectedConfigVersion); diff --git a/tools/projmgr/src/ProjMgr.cpp b/tools/projmgr/src/ProjMgr.cpp index 7212eecd1..a297c7dbe 100644 --- a/tools/projmgr/src/ProjMgr.cpp +++ b/tools/projmgr/src/ProjMgr.cpp @@ -299,8 +299,11 @@ int ProjMgr::RunProjMgr(int argc, char** argv, char** envp) { } } manager.m_worker.SetEnvironmentVariables(envVars); - - res = manager.ProcessCommands(); + if(manager.m_worker.InitializeModel()) { + res = manager.ProcessCommands(); + } else { + res = 1; + } return res; } @@ -466,11 +469,6 @@ bool ProjMgr::PopulateContexts(void) { // Retrieve all context types m_worker.RetrieveAllContextTypes(); - // Retrieve global generators - if (!m_extGenerator.RetrieveGlobalGenerators()) { - return false; - } - return true; } @@ -489,10 +487,6 @@ bool ProjMgr::RunConfigure(bool printConfig) { map* contexts = nullptr; m_worker.GetContexts(contexts); - // Initialize model - if (!m_worker.InitializeModel()) { - return false; - } vector allContexts; vector orderedContexts; m_worker.GetYmlOrderedContexts(orderedContexts); diff --git a/tools/projmgr/src/ProjMgrExtGenerator.cpp b/tools/projmgr/src/ProjMgrExtGenerator.cpp index 9a986c560..3c7a677ea 100644 --- a/tools/projmgr/src/ProjMgrExtGenerator.cpp +++ b/tools/projmgr/src/ProjMgrExtGenerator.cpp @@ -7,6 +7,7 @@ #include "ProjMgrExtGenerator.h" #include "ProjMgrLogger.h" #include "ProjMgrYamlEmitter.h" +#include "ProjMgrKernel.h" #include "RteFsUtils.h" @@ -17,7 +18,7 @@ ProjMgrExtGenerator::ProjMgrExtGenerator(ProjMgrParser* parser) : m_checkSchema(false) { } -ProjMgrExtGenerator::~ProjMgrExtGenerator(void) { +ProjMgrExtGenerator::~ProjMgrExtGenerator() { // Reserved } @@ -25,34 +26,8 @@ void ProjMgrExtGenerator::SetCheckSchema(bool checkSchema) { m_checkSchema = checkSchema; } -bool ProjMgrExtGenerator::RetrieveGlobalGenerators(void) { - if (m_globalGeneratorFiles.empty()) { - // get global generator files - ProjMgrUtils::GetCompilerRoot(m_compilerRoot); - StrVec toolchainConfigFiles; - error_code ec; - for (auto const& entry : fs::recursive_directory_iterator(m_compilerRoot, ec)) { - if (entry.path().filename().string().find(".generator.yml") == string::npos) { - continue; - } - m_globalGeneratorFiles.push_back(entry.path().generic_string()); - } - // parse global generator files - for (auto const& generatorFile : m_globalGeneratorFiles) { - if (!m_parser->ParseGlobalGenerator(generatorFile, m_checkSchema)) { - return false; - } - } - m_globalGenerators = m_parser->GetGlobalGenerators(); - } - return true; -} - bool ProjMgrExtGenerator::IsGlobalGenerator(const string& generatorId) { - if (m_globalGenerators.find(generatorId) == m_globalGenerators.end()) { - return false; - } - return true; + return ProjMgrKernel::Get()->GetExternalGenerator(generatorId) != nullptr; } bool ProjMgrExtGenerator::CheckGeneratorId(const string& generatorId, const string& componentId) { @@ -65,15 +40,18 @@ bool ProjMgrExtGenerator::CheckGeneratorId(const string& generatorId, const stri } const string& ProjMgrExtGenerator::GetGlobalGenDir(const string& generatorId) { - return(m_globalGenerators[generatorId].path); + RteGenerator* g = ProjMgrKernel::Get()->GetExternalGenerator(generatorId); + return g ? g->GetPathAttribute() : RteUtils::EMPTY_STRING; } const string& ProjMgrExtGenerator::GetGlobalGenRunCmd(const string& generatorId) { - return(m_globalGenerators[generatorId].run); + RteGenerator* g = ProjMgrKernel::Get()->GetExternalGenerator(generatorId); + return g ? g->GetRunAttribute() : RteUtils::EMPTY_STRING; } const string& ProjMgrExtGenerator::GetGlobalDescription(const string& generatorId) { - return(m_globalGenerators[generatorId].description); + RteGenerator* g = ProjMgrKernel::Get()->GetExternalGenerator(generatorId); + return g ? g->GetDescription() : RteUtils::EMPTY_STRING; } void ProjMgrExtGenerator::AddUsedGenerator(const string& generatorId, const string& genDir, const string& contextId) { diff --git a/tools/projmgr/src/ProjMgrGenerator.cpp b/tools/projmgr/src/ProjMgrGenerator.cpp index 734d89d89..aedeb8e8b 100644 --- a/tools/projmgr/src/ProjMgrGenerator.cpp +++ b/tools/projmgr/src/ProjMgrGenerator.cpp @@ -183,11 +183,11 @@ void ProjMgrGenerator::GenerateCprjTarget(XMLTreeElement* element, const Context targetOutputElement->AddAttribute("rtedir", context.directories.rte); const auto& types = context.outputTypes; const vector> outputTypes = { - { types.bin.on, types.bin.filename, ProjMgrUtils::OUTPUT_TYPE_BIN }, - { types.elf.on, types.elf.filename, ProjMgrUtils::OUTPUT_TYPE_ELF }, - { types.hex.on, types.hex.filename, ProjMgrUtils::OUTPUT_TYPE_HEX }, - { types.lib.on, types.lib.filename, ProjMgrUtils::OUTPUT_TYPE_LIB }, - { types.cmse.on, types.cmse.filename, ProjMgrUtils::OUTPUT_TYPE_CMSE }, + { types.bin.on, types.bin.filename, RteConstants::OUTPUT_TYPE_BIN }, + { types.elf.on, types.elf.filename, RteConstants::OUTPUT_TYPE_ELF }, + { types.hex.on, types.hex.filename, RteConstants::OUTPUT_TYPE_HEX }, + { types.lib.on, types.lib.filename, RteConstants::OUTPUT_TYPE_LIB }, + { types.cmse.on, types.cmse.filename, RteConstants::OUTPUT_TYPE_CMSE }, }; for (const auto& [on, file, type] : outputTypes) { if (on) { diff --git a/tools/projmgr/src/ProjMgrUtils.cpp b/tools/projmgr/src/ProjMgrUtils.cpp index a0471b702..0d9cc6d95 100644 --- a/tools/projmgr/src/ProjMgrUtils.cpp +++ b/tools/projmgr/src/ProjMgrUtils.cpp @@ -13,51 +13,10 @@ #include "CrossPlatform.h" #include "CrossPlatformUtils.h" -#include -#include #include using namespace std; -const StrMap ProjMgrUtils::DeviceAttributesKeys = { - { RTE_DFPU , YAML_FPU }, - { RTE_DDSP , YAML_DSP }, - { RTE_DMVE , YAML_MVE }, - { RTE_DENDIAN , YAML_ENDIAN }, - { RTE_DSECURE , YAML_TRUSTZONE }, - { RTE_DBRANCHPROT, YAML_BRANCH_PROTECTION }, -}; - -const StrPairVecMap ProjMgrUtils::DeviceAttributesValues = { - { RTE_DFPU , {{ RTE_DP_FPU , YAML_FPU_DP }, - { RTE_SP_FPU , YAML_FPU_SP }, - { RTE_NO_FPU , YAML_OFF }}}, - { RTE_DDSP , {{ RTE_DSP , YAML_ON }, - { RTE_NO_DSP , YAML_OFF }}}, - { RTE_DMVE , {{ RTE_FP_MVE , YAML_MVE_FP }, - { RTE_MVE , YAML_MVE_INT }, - { RTE_NO_MVE , YAML_OFF }}}, - { RTE_DENDIAN , {{ RTE_ENDIAN_BIG , YAML_ENDIAN_BIG }, - { RTE_ENDIAN_LITTLE, YAML_ENDIAN_LITTLE }}}, - { RTE_DSECURE , {{ RTE_SECURE , YAML_TZ_SECURE }, - { RTE_NON_SECURE , YAML_TZ_NON_SECURE }, - { RTE_TZ_DISABLED , YAML_OFF }}}, - { RTE_DBRANCHPROT, {{ RTE_BTI , YAML_BP_BTI }, - { RTE_BTI_SIGNRET , YAML_BP_BTI_SIGNRET }, - { RTE_NO_BRANCHPROT, YAML_OFF }}}, -}; - -const string& ProjMgrUtils::GetDeviceAttribute(const string& key, const string& value) { - const auto& values = DeviceAttributesValues.at(key); - for (const auto& [rte, yaml] : values) { - if (value == rte) { - return yaml; - } else if (value == yaml) { - return rte; - } - } - return RteUtils::EMPTY_STRING; -} RtePackage* ProjMgrUtils::ReadGpdscFile(const string& gpdsc, bool& valid) { fs::path path(gpdsc); @@ -85,85 +44,6 @@ RtePackage* ProjMgrUtils::ReadGpdscFile(const string& gpdsc, bool& valid) { return nullptr; } -const ProjMgrUtils::Result ProjMgrUtils::ExecCommand(const string& cmd) { - array buffer; - string result; - int ret_code = -1; - std::function close = _pclose; - std::function open = _popen; - - auto deleter = [&close, &ret_code](FILE* cmd) { ret_code = close(cmd); }; - { - const unique_ptr pipe(open(cmd.c_str(), "r"), deleter); - if (pipe) { - while (fgets(buffer.data(), static_cast(buffer.size()), pipe.get()) != nullptr) { - result += buffer.data(); - } - } - } - return make_pair(result, ret_code); -} - -const string ProjMgrUtils::GetCategory(const string& file) { - static const map> CATEGORIES = { - {"sourceC", {".c", ".C"}}, - {"sourceCpp", {".cpp", ".c++", ".C++", ".cxx", ".cc", ".CC"}}, - {"sourceAsm", {".asm", ".s", ".S"}}, - {"header", {".h", ".hpp"}}, - {"library", {".a", ".lib"}}, - {"object", {".o"}}, - {"linkerScript", {".sct", ".scf", ".ld", ".icf", ".src"}}, - {"doc", {".txt", ".md", ".pdf", ".htm", ".html"}}, - }; - fs::path ext((fs::path(file)).extension()); - for (const auto& category : CATEGORIES) { - if (find(category.second.begin(), category.second.end(), ext) != category.second.end()) { - return category.first; - } - } - return "other"; -} - -void ProjMgrUtils::PushBackUniquely(vector& vec, const string& value) { - if (find(vec.cbegin(), vec.cend(), value) == vec.cend()) { - vec.push_back(value); - } -} - -void ProjMgrUtils::PushBackUniquely(list& list, const string& value) { - if (find(list.cbegin(), list.cend(), value) == list.cend()) { - list.push_back(value); - } -} - -void ProjMgrUtils::PushBackUniquely(StrPairVec& vec, const StrPair& value) { - for (const auto& item : vec) { - if ((value.first == item.first) && (value.second == item.second)) { - return; - } - } - vec.push_back(value); -} - -StrVecMap ProjMgrUtils::MergeStrVecMap(const StrVecMap& map1, const StrVecMap& map2) { - StrVecMap mergedMap(map1); - mergedMap.insert(map2.begin(), map2.end()); - return mergedMap; -} - -int ProjMgrUtils::StringToInt(const string& value) { - int intValue = 0; - smatch sm; - if (regex_match(value, sm, regex("^[\\+]?([0-9]+)$"))) { - try { - intValue = stoi(sm[1]); - } - catch (exception&) {}; - } - return intValue; -} - - void ProjMgrUtils::ExpandCompilerId(const string& compiler, string& name, string& minVer, string& maxVer) { name = RteUtils::GetPrefix(compiler, '@'); string version = RteUtils::GetSuffix(compiler, '@'); @@ -269,15 +149,15 @@ bool ProjMgrUtils::ParseContextEntry(const string& contextEntry, ContextName& co } void ProjMgrUtils::SetOutputType(const string typeString, OutputTypes& type) { - if (typeString == OUTPUT_TYPE_BIN) { + if (typeString == RteConstants::OUTPUT_TYPE_BIN) { type.bin.on = true; - } else if (typeString == OUTPUT_TYPE_ELF) { + } else if (typeString == RteConstants::OUTPUT_TYPE_ELF) { type.elf.on = true; - } else if (typeString == OUTPUT_TYPE_HEX) { + } else if (typeString == RteConstants::OUTPUT_TYPE_HEX) { type.hex.on = true; - } else if (typeString == OUTPUT_TYPE_LIB) { + } else if (typeString == RteConstants::OUTPUT_TYPE_LIB) { type.lib.on = true; - } else if (typeString == OUTPUT_TYPE_CMSE) { + } else if (typeString == RteConstants::OUTPUT_TYPE_CMSE) { type.cmse.on = true; } } @@ -292,12 +172,12 @@ ProjMgrUtils::Error ProjMgrUtils::GetSelectedContexts(vector& selectedCo if (contextFilters.empty()) { if (allContexts.empty()) { // default context - ProjMgrUtils::PushBackUniquely(selectedContexts, ""); + CollectionUtils::PushBackUniquely(selectedContexts, ""); } else { // select all contexts for (const auto& context : allContexts) { - ProjMgrUtils::PushBackUniquely(selectedContexts, context); + CollectionUtils::PushBackUniquely(selectedContexts, context); } } } @@ -311,7 +191,7 @@ ProjMgrUtils::Error ProjMgrUtils::GetSelectedContexts(vector& selectedCo // append element to the output list for_each(filteredContexts.begin(), filteredContexts.end(), [&](const string& context) { - ProjMgrUtils::PushBackUniquely(selectedContexts, context); + CollectionUtils::PushBackUniquely(selectedContexts, context); }); } } @@ -336,7 +216,7 @@ vector ProjMgrUtils::GetFilteredContexts( for (const auto& context : allContexts) { // add context to output list if exact match if (context == contextFilter) { - ProjMgrUtils::PushBackUniquely(selectedContexts, context); + CollectionUtils::PushBackUniquely(selectedContexts, context); continue; } @@ -348,7 +228,7 @@ vector ProjMgrUtils::GetFilteredContexts( contextPattern += "+" + (inputContext.target != RteUtils::EMPTY_STRING ? inputContext.target : "*"); const string fullContextItem = contextItem.project + "." + contextItem.build + "+" + contextItem.target; if (WildCards::Match(fullContextItem, contextPattern)) { - ProjMgrUtils::PushBackUniquely(selectedContexts, context); + CollectionUtils::PushBackUniquely(selectedContexts, context); } } } diff --git a/tools/projmgr/src/ProjMgrWorker.cpp b/tools/projmgr/src/ProjMgrWorker.cpp index 522405ac0..50668d744 100644 --- a/tools/projmgr/src/ProjMgrWorker.cpp +++ b/tools/projmgr/src/ProjMgrWorker.cpp @@ -18,23 +18,23 @@ using namespace std; static const regex accessSequencesRegEx = regex(string("^(") + - ProjMgrUtils::AS_SOLUTION_DIR + "|" + - ProjMgrUtils::AS_PROJECT_DIR + "|" + - ProjMgrUtils::AS_OUT_DIR + "|" + - ProjMgrUtils::AS_BIN + "|" + - ProjMgrUtils::AS_ELF + "|" + - ProjMgrUtils::AS_HEX + "|" + - ProjMgrUtils::AS_LIB + "|" + - ProjMgrUtils::AS_CMSE + ")" + + RteConstants::AS_SOLUTION_DIR + "|" + + RteConstants::AS_PROJECT_DIR + "|" + + RteConstants::AS_OUT_DIR + "|" + + RteConstants::AS_BIN + "|" + + RteConstants::AS_ELF + "|" + + RteConstants::AS_HEX + "|" + + RteConstants::AS_LIB + "|" + + RteConstants::AS_CMSE + ")" + "\\((.*)\\)$" ); static const map> affixesMap = { - { "" , {ProjMgrUtils::DEFAULT_ELF_SUFFIX, ProjMgrUtils::DEFAULT_LIB_PREFIX, ProjMgrUtils::DEFAULT_LIB_SUFFIX }}, - { "AC6", {ProjMgrUtils::AC6_ELF_SUFFIX , ProjMgrUtils::AC6_LIB_PREFIX , ProjMgrUtils::AC6_LIB_SUFFIX }}, - { "GCC", {ProjMgrUtils::GCC_ELF_SUFFIX , ProjMgrUtils::GCC_LIB_PREFIX , ProjMgrUtils::GCC_LIB_SUFFIX }}, - { "CLANG", {ProjMgrUtils::GCC_ELF_SUFFIX , ProjMgrUtils::GCC_LIB_PREFIX , ProjMgrUtils::GCC_LIB_SUFFIX }}, - { "IAR", {ProjMgrUtils::IAR_ELF_SUFFIX , ProjMgrUtils::IAR_LIB_PREFIX , ProjMgrUtils::IAR_LIB_SUFFIX }}, + { "" , {RteConstants::DEFAULT_ELF_SUFFIX, RteConstants::DEFAULT_LIB_PREFIX, RteConstants::DEFAULT_LIB_SUFFIX }}, + { "AC6", {RteConstants::AC6_ELF_SUFFIX , RteConstants::AC6_LIB_PREFIX , RteConstants::AC6_LIB_SUFFIX }}, + { "GCC", {RteConstants::GCC_ELF_SUFFIX , RteConstants::GCC_LIB_PREFIX , RteConstants::GCC_LIB_SUFFIX }}, + { "CLANG", {RteConstants::GCC_ELF_SUFFIX , RteConstants::GCC_LIB_PREFIX , RteConstants::GCC_LIB_SUFFIX }}, + { "IAR", {RteConstants::IAR_ELF_SUFFIX , RteConstants::IAR_LIB_PREFIX , RteConstants::IAR_LIB_SUFFIX }}, }; ProjMgrWorker::ProjMgrWorker(ProjMgrParser* parser, ProjMgrExtGenerator* extGenerator) : @@ -129,12 +129,12 @@ void ProjMgrWorker::AddContext(ContextDesc& descriptor, const TypePair& type, Co context.directories.cprj = RteFsUtils::MakePathCanonical(RteFsUtils::AbsolutePath(context.directories.cprj).generic_string()); // context variables - context.variables[ProjMgrUtils::AS_SOLUTION] = context.csolution->name; - context.variables[ProjMgrUtils::AS_PROJECT] = context.cproject->name; - context.variables[ProjMgrUtils::AS_BUILD_TYPE] = context.type.build; - context.variables[ProjMgrUtils::AS_TARGET_TYPE] = context.type.target; + context.variables[RteConstants::AS_SOLUTION] = context.csolution->name; + context.variables[RteConstants::AS_PROJECT] = context.cproject->name; + context.variables[RteConstants::AS_BUILD_TYPE] = context.type.build; + context.variables[RteConstants::AS_TARGET_TYPE] = context.type.target; - ProjMgrUtils::PushBackUniquely(m_ymlOrderedContexts, context.name); + CollectionUtils::PushBackUniquely(m_ymlOrderedContexts, context.name); m_contexts[context.name] = context; } } @@ -161,7 +161,7 @@ bool ProjMgrWorker::ParseContextLayers(ContextItem& context) { } if (CheckContextFilters(clayer.typeFilter, context)) { error_code ec; - string const& clayerRef = ExpandString(clayer.layer, context.variables); + string const& clayerRef = RteUtils::ExpandString(clayer.layer, context.variables); string const& clayerFile = fs::canonical(fs::path(context.cproject->directory).append(clayerRef), ec).generic_string(); if (clayerFile.empty()) { if (regex_match(clayer.layer, regex(".*\\$.*\\$.*"))) { @@ -316,6 +316,9 @@ string ProjMgrWorker::GetPackRoot() { } bool ProjMgrWorker::InitializeModel() { + if(m_kernel) { + return true; // already initialized; + } m_packRoot = GetPackRoot(); m_kernel = ProjMgrKernel::Get(); if (!m_kernel) { @@ -329,7 +332,7 @@ bool ProjMgrWorker::InitializeModel() { } m_kernel->SetCmsisPackRoot(m_packRoot); m_model->SetCallback(m_kernel->GetCallback()); - return true; + return m_kernel->Init(); } bool ProjMgrWorker::LoadAllRelevantPacks() { @@ -350,14 +353,14 @@ bool ProjMgrWorker::LoadAllRelevantPacks() { for(const auto& [pdscFile, pathVer] : contextItem.pdscFiles) { const string& path = pathVer.first; if(!path.empty()) { - ProjMgrUtils::PushBackUniquely(pdscFiles, pdscFile); + CollectionUtils::PushBackUniquely(pdscFiles, pdscFile); } } // then all others for(const auto& [pdscFile, pathVer] : contextItem.pdscFiles) { const string& path = pathVer.first; if(path.empty()) { - ProjMgrUtils::PushBackUniquely(pdscFiles, pdscFile); + CollectionUtils::PushBackUniquely(pdscFiles, pdscFile); } } } @@ -585,7 +588,7 @@ bool ProjMgrWorker::CollectLayersFromPacks(ContextItem& context, StrVecMap& clay if (!RteFsUtils::Exists(clayerFile)) { return false; } - ProjMgrUtils::PushBackUniquely(clayers[clayerItem->GetTypeString()], clayerFile); + CollectionUtils::PushBackUniquely(clayers[clayerItem->GetTypeString()], clayerFile); } return true; } @@ -606,7 +609,7 @@ bool ProjMgrWorker::CollectLayersFromSearchPath(const string& clayerSearchPath, return false; } ClayerItem* clayer = &m_parser->GetGenericClayers()[clayerFile]; - ProjMgrUtils::PushBackUniquely(clayers[clayer->type], clayerFile); + CollectionUtils::PushBackUniquely(clayers[clayer->type], clayerFile); } } } @@ -617,7 +620,7 @@ bool ProjMgrWorker::CollectLayersFromSearchPath(const string& clayerSearchPath, void ProjMgrWorker::GetRequiredLayerTypes(ContextItem& context, LayersDiscovering& discover) { for (const auto& clayer : context.cproject->clayers) { if (clayer.type.empty() || !CheckContextFilters(clayer.typeFilter, context) || - (ExpandString(clayer.layer, context.variables) != clayer.layer)) { + (RteUtils::ExpandString(clayer.layer, context.variables) != clayer.layer)) { continue; } discover.requiredLayerTypes.push_back(clayer.type); @@ -667,14 +670,14 @@ bool ProjMgrWorker::ProcessCandidateLayers(ContextItem& context, LayersDiscoveri bool ProjMgrWorker::GetCandidateLayers(LayersDiscovering& discover) { // clayers matching required types - StrVecMap genericClayers = ProjMgrUtils::MergeStrVecMap(discover.genericClayersFromSearchPath, discover.genericClayersFromPacks); + StrVecMap genericClayers = CollectionUtils::MergeStrVecMap(discover.genericClayersFromSearchPath, discover.genericClayersFromPacks); for (const auto& requiredType : discover.requiredLayerTypes) { if (genericClayers.find(requiredType) != genericClayers.end()) { for (const auto& clayer : genericClayers.at(requiredType)) { discover.candidateClayers[requiredType].push_back(clayer); } } else { - ProjMgrUtils::PushBackUniquely(discover.missedRequiredTypes, requiredType); + CollectionUtils::PushBackUniquely(discover.missedRequiredTypes, requiredType); } } // parse matched type layers @@ -781,7 +784,7 @@ bool ProjMgrWorker::ProcessLayerCombinations(ContextItem& context, LayersDiscove for (const auto& [type, _] : discover.candidateClayers) { for (const auto& collection : combination) { if (collection.type == type) { - ProjMgrUtils::PushBackUniquely(context.compatibleLayers[type], collection.filename); + CollectionUtils::PushBackUniquely(context.compatibleLayers[type], collection.filename); } } } @@ -1038,7 +1041,7 @@ ConnectionsValidationResult ProjMgrWorker::ValidateConnections(ConnectionsCollec const auto& value = provided->second; if ((providedValues.find(key) != providedValues.end())) { // connection is provided multiple times - ProjMgrUtils::PushBackUniquely(conflicts, key); + CollectionUtils::PushBackUniquely(conflicts, key); continue; } // new entry @@ -1052,7 +1055,7 @@ ConnectionsValidationResult ProjMgrWorker::ValidateConnections(ConnectionsCollec const auto& value = (*it)->second; if (value.find_first_of('+') == 0) { // move entry to the consumedAddedValues map - consumedAddedValues[id] += ProjMgrUtils::StringToInt(value); + consumedAddedValues[id] += RteUtils::StringToInt(value, 0); it = connections.consumes.erase(it); } else { it++; @@ -1063,7 +1066,7 @@ ConnectionsValidationResult ProjMgrWorker::ValidateConnections(ConnectionsCollec StrPairVec overflows; for (const auto& [consumedKey, consumedValue] : consumedAddedValues) { const int providedValue = providedValues.find(consumedKey) == providedValues.end() ? 0 : - ProjMgrUtils::StringToInt(providedValues.at(consumedKey)); + RteUtils::StringToInt(providedValues.at(consumedKey), 0); if (consumedValue > providedValue) { overflows.push_back({ consumedKey, to_string(consumedValue) + " > " + to_string(providedValue) }); } @@ -1253,16 +1256,16 @@ bool ProjMgrWorker::ProcessDevice(ContextItem& context) { // Set or update target attributes const StrMap attrMap = { - { attr.fpu, ProjMgrUtils::RTE_DFPU }, - { attr.dsp, ProjMgrUtils::RTE_DDSP }, - { attr.mve, ProjMgrUtils::RTE_DMVE }, - { attr.endian, ProjMgrUtils::RTE_DENDIAN }, - { attr.trustzone, ProjMgrUtils::RTE_DSECURE }, - { attr.branchProtection, ProjMgrUtils::RTE_DBRANCHPROT }, + { attr.fpu, RteConstants::RTE_DFPU }, + { attr.dsp, RteConstants::RTE_DDSP }, + { attr.mve, RteConstants::RTE_DMVE }, + { attr.endian, RteConstants::RTE_DENDIAN }, + { attr.trustzone, RteConstants::RTE_DSECURE }, + { attr.branchProtection, RteConstants::RTE_DBRANCHPROT }, }; for (const auto& [yamlValue, rteKey] : attrMap) { if (!yamlValue.empty()) { - const auto& rteValue = ProjMgrUtils::GetDeviceAttribute(rteKey, yamlValue); + const auto& rteValue = RteConstants::GetDeviceAttribute(rteKey, yamlValue); if (!rteValue.empty()) { context.targetAttributes[rteKey] = rteValue; } @@ -1274,8 +1277,8 @@ bool ProjMgrWorker::ProcessDevice(ContextItem& context) { context.packages.insert({ context.devicePack->GetID(), context.devicePack }); } GetDeviceItem(context.device, context.deviceItem); - context.variables[ProjMgrUtils::AS_DNAME] = context.deviceItem.name; - context.variables[ProjMgrUtils::AS_PNAME] = context.deviceItem.pname; + context.variables[RteConstants::AS_DNAME] = context.deviceItem.name; + context.variables[RteConstants::AS_PNAME] = context.deviceItem.pname; return true; } @@ -1298,30 +1301,30 @@ bool ProjMgrWorker::ProcessBoardPrecedence(StringCollection& item) { void ProjMgrWorker::CheckDeviceAttributes(const string& device, const ProcessorItem& userSelection, const StrMap& targetAttributes) { // check endian compatibility if (!userSelection.endian.empty()) { - if (targetAttributes.find(ProjMgrUtils::RTE_DENDIAN) != targetAttributes.end()) { - const auto& endian = targetAttributes.at(ProjMgrUtils::RTE_DENDIAN); - if ((endian != ProjMgrUtils::RTE_ENDIAN_CONFIGURABLE) && - (endian != ProjMgrUtils::GetDeviceAttribute(ProjMgrUtils::RTE_DENDIAN, userSelection.endian))) { - ProjMgrLogger::Warn("device '" + device + "' does not support '" + ProjMgrUtils::YAML_ENDIAN + ": " + userSelection.endian + "'"); + if (targetAttributes.find(RteConstants::RTE_DENDIAN) != targetAttributes.end()) { + const auto& endian = targetAttributes.at(RteConstants::RTE_DENDIAN); + if ((endian != RteConstants::RTE_ENDIAN_CONFIGURABLE) && + (endian != RteConstants::GetDeviceAttribute(RteConstants::RTE_DENDIAN, userSelection.endian))) { + ProjMgrLogger::Warn("device '" + device + "' does not support '" + RteConstants::YAML_ENDIAN + ": " + userSelection.endian + "'"); } } } // check dp vs sp fpu - if ((userSelection.fpu == ProjMgrUtils::YAML_FPU_DP) && - (targetAttributes.find(ProjMgrUtils::RTE_DFPU) != targetAttributes.end()) && - (targetAttributes.at(ProjMgrUtils::RTE_DFPU) == ProjMgrUtils::RTE_SP_FPU)) { - ProjMgrLogger::Warn("device '" + device + "' does not support '" + ProjMgrUtils::YAML_FPU + ": " + userSelection.fpu + "'"); + if ((userSelection.fpu == RteConstants::YAML_FPU_DP) && + (targetAttributes.find(RteConstants::RTE_DFPU) != targetAttributes.end()) && + (targetAttributes.at(RteConstants::RTE_DFPU) == RteConstants::RTE_SP_FPU)) { + ProjMgrLogger::Warn("device '" + device + "' does not support '" + RteConstants::YAML_FPU + ": " + userSelection.fpu + "'"); } // check disabled capabilities const vector> attrMapCompatibility = { - { ProjMgrUtils::YAML_FPU , userSelection.fpu, ProjMgrUtils::RTE_DFPU, ProjMgrUtils::RTE_NO_FPU }, - { ProjMgrUtils::YAML_DSP , userSelection.dsp, ProjMgrUtils::RTE_DDSP, ProjMgrUtils::RTE_NO_DSP }, - { ProjMgrUtils::YAML_MVE , userSelection.mve, ProjMgrUtils::RTE_DMVE, ProjMgrUtils::RTE_NO_MVE }, - { ProjMgrUtils::YAML_TRUSTZONE , userSelection.trustzone, ProjMgrUtils::RTE_DTZ, ProjMgrUtils::RTE_NO_TZ }, - { ProjMgrUtils::YAML_BRANCH_PROTECTION, userSelection.branchProtection, ProjMgrUtils::RTE_DPACBTI, ProjMgrUtils::RTE_NO_PACBTI }, + { RteConstants::YAML_FPU , userSelection.fpu, RteConstants::RTE_DFPU, RteConstants::RTE_NO_FPU }, + { RteConstants::YAML_DSP , userSelection.dsp, RteConstants::RTE_DDSP, RteConstants::RTE_NO_DSP }, + { RteConstants::YAML_MVE , userSelection.mve, RteConstants::RTE_DMVE, RteConstants::RTE_NO_MVE }, + { RteConstants::YAML_TRUSTZONE , userSelection.trustzone, RteConstants::RTE_DTZ, RteConstants::RTE_NO_TZ }, + { RteConstants::YAML_BRANCH_PROTECTION, userSelection.branchProtection, RteConstants::RTE_DPACBTI, RteConstants::RTE_NO_PACBTI }, }; for (const auto& [yamlKey, yamlValue, rteKey, rteValue] : attrMapCompatibility) { - if (!yamlValue.empty() && (yamlValue != ProjMgrUtils::YAML_OFF)) { + if (!yamlValue.empty() && (yamlValue != RteConstants::YAML_OFF)) { if ((targetAttributes.find(rteKey) == targetAttributes.end()) || (targetAttributes.at(rteKey) == rteValue)) { ProjMgrLogger::Warn("device '" + device + "' does not support '" + yamlKey + ": " + yamlValue + "'"); @@ -1622,9 +1625,9 @@ bool ProjMgrWorker::ProcessComponents(ContextItem& context) { } // Get generator + string generatorId = matchedComponent->GetGeneratorName(); RteGenerator* generator = matchedComponent->GetGenerator(); - string generatorId = generator ? generator->GetID() : ""; - if (generator) { + if (generator && !generator->IsExternal()) { context.generators.insert({ generatorId, generator }); string genDir; if (!GetGeneratorDir(generator, context, layer, genDir)) { @@ -1635,20 +1638,18 @@ bool ProjMgrWorker::ProcessComponents(ContextItem& context) { context.gpdscs.insert({ gpdsc, {componentId, generatorId, genDir} }); } else { // Get external generator id - const string extGenId = matchedComponent->GetGeneratorName(); - if (!extGenId.empty()) { + if (!generatorId.empty()) { // check if required global generator is registered - if (!m_extGenerator->CheckGeneratorId(extGenId, componentId)) { + if (!m_extGenerator->CheckGeneratorId(generatorId, componentId)) { return false; } string genDir; - if (!GetExtGeneratorDir(extGenId, context, layer, genDir)) { + if (!GetExtGeneratorDir(generatorId, context, layer, genDir)) { return false; } // keep track of used generators - m_extGenerator->AddUsedGenerator(extGenId, genDir, context.name); - context.extGenDir[extGenId] = genDir; - generatorId = extGenId; + m_extGenerator->AddUsedGenerator(generatorId, genDir, context.name); + context.extGenDir[generatorId] = genDir; } } @@ -2265,10 +2266,10 @@ bool ProjMgrWorker::ProcessPrecedences(ContextItem& context, bool rerun) { // set context variables (static access sequences) DeviceItem deviceItem; GetDeviceItem(context.device, deviceItem); - context.variables[ProjMgrUtils::AS_DNAME] = deviceItem.name; - context.variables[ProjMgrUtils::AS_PNAME] = deviceItem.pname; - context.variables[ProjMgrUtils::AS_BNAME] = context.board; - context.variables[ProjMgrUtils::AS_COMPILER] = context.toolchain.name; + context.variables[RteConstants::AS_DNAME] = deviceItem.name; + context.variables[RteConstants::AS_PNAME] = deviceItem.pname; + context.variables[RteConstants::AS_BNAME] = context.board; + context.variables[RteConstants::AS_COMPILER] = context.toolchain.name; // Add cdefault misc into csolution if (context.cdefault) { @@ -2748,29 +2749,29 @@ void ProjMgrWorker::ExpandAccessSequence(const ContextItem & context, const Cont const string relOutDir = RteFsUtils::RelativePath(refContextOutDir, context.directories.cprj, withHeadingDot); string regExStr = "\\$"; string replacement; - if (sequence == ProjMgrUtils::AS_SOLUTION_DIR) { - regExStr += ProjMgrUtils::AS_SOLUTION_DIR; + if (sequence == RteConstants::AS_SOLUTION_DIR) { + regExStr += RteConstants::AS_SOLUTION_DIR; replacement = RteFsUtils::RelativePath(refContext.csolution->directory, context.directories.cprj, withHeadingDot); - } else if (sequence == ProjMgrUtils::AS_PROJECT_DIR) { - regExStr += ProjMgrUtils::AS_PROJECT_DIR; + } else if (sequence == RteConstants::AS_PROJECT_DIR) { + regExStr += RteConstants::AS_PROJECT_DIR; replacement = RteFsUtils::RelativePath(refContext.cproject->directory, context.directories.cprj, withHeadingDot); - } else if (sequence == ProjMgrUtils::AS_OUT_DIR) { - regExStr += ProjMgrUtils::AS_OUT_DIR; + } else if (sequence == RteConstants::AS_OUT_DIR) { + regExStr += RteConstants::AS_OUT_DIR; replacement = relOutDir; - } else if (sequence == ProjMgrUtils::AS_ELF) { - regExStr += ProjMgrUtils::AS_ELF; + } else if (sequence == RteConstants::AS_ELF) { + regExStr += RteConstants::AS_ELF; replacement = refContext.outputTypes.elf.on ? relOutDir + "/" + refContext.outputTypes.elf.filename : ""; - } else if (sequence == ProjMgrUtils::AS_BIN) { - regExStr += ProjMgrUtils::AS_BIN; + } else if (sequence == RteConstants::AS_BIN) { + regExStr += RteConstants::AS_BIN; replacement = refContext.outputTypes.bin.on ? relOutDir + "/" + refContext.outputTypes.bin.filename : ""; - } else if (sequence == ProjMgrUtils::AS_HEX) { - regExStr += ProjMgrUtils::AS_HEX; + } else if (sequence == RteConstants::AS_HEX) { + regExStr += RteConstants::AS_HEX; replacement = refContext.outputTypes.hex.on ? relOutDir + "/" + refContext.outputTypes.hex.filename : ""; - } else if (sequence == ProjMgrUtils::AS_LIB) { - regExStr += ProjMgrUtils::AS_LIB; + } else if (sequence == RteConstants::AS_LIB) { + regExStr += RteConstants::AS_LIB; replacement = refContext.outputTypes.lib.on ? relOutDir + "/" + refContext.outputTypes.lib.filename : ""; - } else if (sequence == ProjMgrUtils::AS_CMSE) { - regExStr += ProjMgrUtils::AS_CMSE; + } else if (sequence == RteConstants::AS_CMSE) { + regExStr += RteConstants::AS_CMSE; replacement = refContext.outputTypes.cmse.on ? relOutDir + "/" + refContext.outputTypes.cmse.filename : ""; } regex regEx = regex(regExStr + "\\(.*\\)\\$"); @@ -2781,7 +2782,7 @@ bool ProjMgrWorker::ProcessSequenceRelative(ContextItem& context, string& item, size_t offset = 0; bool pathReplace = false; // expand variables (static access sequences) - const string input = item = ExpandString(item, context.variables); + const string input = item = RteUtils::ExpandString(item, context.variables); // expand dynamic access sequences while (offset != string::npos) { string sequence; @@ -2816,7 +2817,7 @@ bool ProjMgrWorker::ProcessSequenceRelative(ContextItem& context, string& item, ExpandAccessSequence(context, refContext, sequenceName, item, withHeadingDot); // store dependency information if (refContext.name != context.name) { - ProjMgrUtils::PushBackUniquely(context.dependsOn, refContext.name); + CollectionUtils::PushBackUniquely(context.dependsOn, refContext.name); } } else { // full or partial context name cannot be resolved to a valid context @@ -2909,7 +2910,7 @@ bool ProjMgrWorker::AddFile(const FileNode& src, vector& dst, ContextI // Set file category if (srcNode.category.empty()) { - srcNode.category = ProjMgrUtils::GetCategory(srcNode.file); + srcNode.category = RteFsUtils::FileCategoryFromExtension(srcNode.file); } dst.push_back(srcNode); @@ -2984,7 +2985,7 @@ void ProjMgrWorker::CheckCompilerFilterSpelling(const string& compiler) { return; } } - ProjMgrUtils::PushBackUniquely(m_missingToolchains, compilerName); + CollectionUtils::PushBackUniquely(m_missingToolchains, compilerName); } bool ProjMgrWorker::CheckType(const TypeFilter& typeFilter, const vector& typeVec) { @@ -3049,24 +3050,24 @@ bool ProjMgrWorker::CheckContextFilters(const TypeFilter& typeFilter, const Cont void ProjMgrWorker::RetrieveAllContextTypes(void) { const auto& csolution = m_parser->GetCsolution(); for (const auto& [buildType, item] : csolution.buildTypes) { - ProjMgrUtils::PushBackUniquely(m_types.allBuildTypes, buildType); + CollectionUtils::PushBackUniquely(m_types.allBuildTypes, buildType); for (const auto& mappedContext : item.contextMap) { if (!mappedContext.build.empty()) { - ProjMgrUtils::PushBackUniquely(m_types.allBuildTypes, mappedContext.build); + CollectionUtils::PushBackUniquely(m_types.allBuildTypes, mappedContext.build); } if (!mappedContext.target.empty()) { - ProjMgrUtils::PushBackUniquely(m_types.allTargetTypes, mappedContext.target); + CollectionUtils::PushBackUniquely(m_types.allTargetTypes, mappedContext.target); } } } for (const auto& [targetType, item] : csolution.targetTypes) { - ProjMgrUtils::PushBackUniquely(m_types.allTargetTypes, targetType); + CollectionUtils::PushBackUniquely(m_types.allTargetTypes, targetType); for (const auto& mappedContext : item.build.contextMap) { if (!mappedContext.build.empty()) { - ProjMgrUtils::PushBackUniquely(m_types.allBuildTypes, mappedContext.build); + CollectionUtils::PushBackUniquely(m_types.allBuildTypes, mappedContext.build); } if (!mappedContext.target.empty()) { - ProjMgrUtils::PushBackUniquely(m_types.allTargetTypes, mappedContext.target); + CollectionUtils::PushBackUniquely(m_types.allTargetTypes, mappedContext.target); } } } @@ -3162,7 +3163,7 @@ void ProjMgrWorker::ApplyFilter(const vector& origin, const set& } } if (match) { - ProjMgrUtils::PushBackUniquely(result, item); + CollectionUtils::PushBackUniquely(result, item); } } } @@ -3230,14 +3231,14 @@ bool ProjMgrWorker::ListPacks(vector&packs, bool bListMissingPacksOnly, for(const auto& [pdscFile, pathVer] : context.pdscFiles) { const string& path = pathVer.first; if(!path.empty()) { - ProjMgrUtils::PushBackUniquely(pdscFiles, pdscFile); + CollectionUtils::PushBackUniquely(pdscFiles, pdscFile); } } // then all others for(const auto& [pdscFile, pathVer] : context.pdscFiles) { const string& path = pathVer.first; if(path.empty()) { - ProjMgrUtils::PushBackUniquely(pdscFiles, pdscFile); + CollectionUtils::PushBackUniquely(pdscFiles, pdscFile); } } } @@ -3604,7 +3605,7 @@ bool ProjMgrWorker::ListLayers(vector& layers, const string& clayerSearc for (const auto& validSet : validSets) { layerEntry += "\n set: " + validSet; } - ProjMgrUtils::PushBackUniquely(layers, layerEntry); + CollectionUtils::PushBackUniquely(layers, layerEntry); } return true; } @@ -3791,7 +3792,7 @@ bool ProjMgrWorker::ExecuteGenerator(std::string& generatorId) { //const string generatorCommand = m_kernel->GetCmsisPackRoot() + "/" + generator->GetPackagePath() + generator->GetCommand(); // check if generator executable has execute permissions - const string generatorExe = generator->GetExecutable(context.rteActiveTarget); + const string generatorExe = generator->GetExecutable(); if (generatorExe.empty()) { ProjMgrLogger::Error("generator executable '" + generatorId + "' was not found"); return false; @@ -3809,13 +3810,13 @@ bool ProjMgrWorker::ExecuteGenerator(std::string& generatorId) { ProjMgrLogger::Error("generator '" + generatorId + "' is not dry-run capable"); return false; } - const string generatorCommand = generator->GetExpandedCommandLine(context.rteActiveTarget, RteUtils::EMPTY_STRING, m_dryRun); + const string generatorCommand = generator->GetExpandedCommandLine(RteUtils::EMPTY_STRING, m_dryRun); error_code ec; const auto& workingDir = fs::current_path(ec); RteFsUtils::CreateDirectories(generatorDestination); fs::current_path(generatorDestination, ec); - ProjMgrUtils::Result result = ProjMgrUtils::ExecCommand(generatorCommand); + StrIntPair result = CrossPlatformUtils::ExecCommand(generatorCommand); fs::current_path(workingDir, ec); ProjMgrLogger::Info("generator '" + generatorId + "' for context '" + selectedContext + "' reported:\n" + result.first); @@ -3915,20 +3916,6 @@ bool ProjMgrWorker::IsContextSelected(const string& context) { return false; } -string ProjMgrWorker::ExpandString(const string& src, const StrMap& variables) { - string ret = src; - if (regex_match(ret, regex(".*\\$.*\\$.*"))) { - for (const auto& [varName, replacement] : variables) { - const string var = "$" + varName + "$"; - size_t index = 0; - while ((index = ret.find(var)) != string::npos) { - ret.replace(index, var.length(), replacement); - } - } - } - return ret; -} - bool ProjMgrWorker::ListToolchains(vector& toolchains) { bool allSupported = true; for (const auto& selectedContext : m_selectedContexts) { @@ -4139,7 +4126,7 @@ StrSet ProjMgrWorker::GetValidSets(ContextItem& context, const string& clayer) { bool ProjMgrWorker::ProcessOutputFilenames(ContextItem& context) { // get base name and output types from project and project setups context.outputTypes = {}; - context.cproject->output.baseName = ExpandString(context.cproject->output.baseName, context.variables); + context.cproject->output.baseName = RteUtils::ExpandString(context.cproject->output.baseName, context.variables); string baseName; StringCollection baseNameCollection = { &baseName, @@ -4152,7 +4139,7 @@ bool ProjMgrWorker::ProcessOutputFilenames(ContextItem& context) { } for (auto& setup : context.cproject->setups) { if (CheckContextFilters(setup.type, context) && CheckCompiler(setup.forCompiler, context.compiler)) { - setup.output.baseName = ExpandString(setup.output.baseName, context.variables); + setup.output.baseName = RteUtils::ExpandString(setup.output.baseName, context.variables); baseNameCollection.elements.push_back(&setup.output.baseName); for (const auto& type : setup.output.type) { ProjMgrUtils::SetOutputType(type, context.outputTypes); @@ -4307,7 +4294,7 @@ bool ProjMgrWorker::ListConfigFiles(vector& configFiles) { configEntry += " (update@" + updateVersion + ")"; } } - ProjMgrUtils::PushBackUniquely(configFiles, configEntry); + CollectionUtils::PushBackUniquely(configFiles, configEntry); } } } @@ -4405,13 +4392,14 @@ bool ProjMgrWorker::ExecuteExtGenerator(std::string& generatorId) { } // Execute generator command + string binDir = ProjMgrKernel::Get()->GetCmsisToolboxDir() + "/bin"; string runCmd = m_extGenerator->GetGlobalGenRunCmd(generatorId); - RteFsUtils::NormalizePath(runCmd, m_compilerRoot); + RteFsUtils::NormalizePath(runCmd, binDir); runCmd += " " + fs::path(cbuildgenOutput).append(m_parser->GetCsolution().name + ".cbuild-gen-idx.yml").generic_string(); error_code ec; const auto& workingDir = fs::current_path(ec); fs::current_path(genDir, ec); - ProjMgrUtils::Result result = ProjMgrUtils::ExecCommand(runCmd); + StrIntPair result = CrossPlatformUtils::ExecCommand(runCmd); fs::current_path(workingDir, ec); ProjMgrLogger::Info("generator '" + generatorId + "' for context '" + selectedContextId + "' reported:\n" + result.first); if (result.second) { diff --git a/tools/projmgr/src/ProjMgrYamlEmitter.cpp b/tools/projmgr/src/ProjMgrYamlEmitter.cpp index 027085a61..33f17f8ea 100644 --- a/tools/projmgr/src/ProjMgrYamlEmitter.cpp +++ b/tools/projmgr/src/ProjMgrYamlEmitter.cpp @@ -131,7 +131,7 @@ ProjMgrYamlCbuildPack::ProjMgrYamlCbuildPack(YAML::Node node, const vector defines; if (context->rteActiveTarget != nullptr) { for (const auto& define : context->rteActiveTarget->GetDefines()) { - ProjMgrUtils::PushBackUniquely(defines, define); + CollectionUtils::PushBackUniquely(defines, define); } } SetDefineNode(contextNode[YAML_DEFINE], defines); @@ -317,7 +317,7 @@ void ProjMgrYamlCbuild::SetContextNode(YAML::Node contextNode, const ContextItem }) { for (auto include : targetIncludes) { RteFsUtils::NormalizePath(include, context->cproject->directory); - ProjMgrUtils::PushBackUniquely(includes, FormatPath(include, context->directories.cbuild)); + CollectionUtils::PushBackUniquely(includes, FormatPath(include, context->directories.cbuild)); } } } @@ -348,14 +348,14 @@ void ProjMgrYamlCbuild::SetComponentsNode(YAML::Node node, const ContextItem* co SetControlsNode(componentNode, context, componentItem->build); SetComponentFilesNode(componentNode[YAML_FILES], context, componentId); if (!component.generator.empty()) { - if (context->generators.find(component.generator) != context->generators.end()) { + SetNodeValue(componentNode[YAML_GENERATOR][YAML_ID], component.generator); + const RteGenerator* rteGenerator = get_or_null(context->generators, component.generator); + if(rteGenerator && !rteGenerator->IsExternal()) { const RteGenerator* rteGenerator = context->generators.at(component.generator); - SetNodeValue(componentNode[YAML_GENERATOR][YAML_ID], component.generator); - SetNodeValue(componentNode[YAML_GENERATOR][YAML_FROM_PACK], RtePackage::GetPackageIDfromAttributes(*rteGenerator->GetPackage())); + SetNodeValue(componentNode[YAML_GENERATOR][YAML_FROM_PACK], rteGenerator->GetPackageID()); SetGeneratorFiles(componentNode[YAML_GENERATOR], context, componentId); - } else if (context->extGenDir.find(component.generator) != context->extGenDir.end()) { - SetNodeValue(componentNode[YAML_GENERATOR][YAML_ID], component.generator); - SetNodeValue(componentNode[YAML_GENERATOR][YAML_PATH], + } else if (contains_key(context->extGenDir, component.generator)) { + SetNodeValue(componentNode[YAML_GENERATOR][YAML_PATH], FormatPath(fs::path(context->extGenDir.at(component.generator)).append(context->cproject->name + ".cgen.yml").generic_string(), context->directories.cbuild)); } else { @@ -400,6 +400,9 @@ void ProjMgrYamlCbuild::SetGeneratorFiles(YAML::Node node, const ContextItem* co void ProjMgrYamlCbuild::SetGeneratorsNode(YAML::Node node, const ContextItem* context) { for (const auto& [generatorId, generator] : context->generators) { + if(generator->IsExternal()) { + continue; + } YAML::Node genNode; SetNodeValue(genNode[YAML_GENERATOR], generatorId); @@ -411,7 +414,7 @@ void ProjMgrYamlCbuild::SetGeneratorsNode(YAML::Node node, const ContextItem* co break; } } - SetNodeValue(genNode[YAML_FROM_PACK], RtePackage::GetPackageIDfromAttributes(*generator->GetPackage())); + SetNodeValue(genNode[YAML_FROM_PACK], generator->GetPackageID()); SetNodeValue(genNode[YAML_PATH], FormatPath(workingDir, context->directories.cbuild)); SetNodeValue(genNode[YAML_GPDSC], FormatPath(gpdscFile, context->directories.cbuild)); @@ -419,14 +422,14 @@ void ProjMgrYamlCbuild::SetGeneratorsNode(YAML::Node node, const ContextItem* co YAML::Node commandNode; // Executable file - const string exe = generator->GetExecutable(context->rteActiveTarget, host); + const string exe = generator->GetExecutable(host); if (exe.empty()) continue; commandNode[YAML_FILE] = FormatPath(exe, context->directories.cbuild); // Arguments YAML::Node argumentsNode; - const vector >& args = generator->GetExpandedArguments(context->rteActiveTarget, host); + const vector >& args = generator->GetExpandedArguments(host); for (auto [swtch, value] : args) { // If the argument is recognized as an absolute path, make sure to reformat // it to use CMSIS_PACK_ROOT or to be relative the working directory @@ -468,7 +471,7 @@ void ProjMgrYamlCbuild::SetFilesNode(YAML::Node node, const ContextItem* context for (const auto& file : files) { YAML::Node fileNode; SetNodeValue(fileNode[YAML_FILE], file.file); - SetNodeValue(fileNode[YAML_CATEGORY], ProjMgrUtils::GetCategory(file.file)); + SetNodeValue(fileNode[YAML_CATEGORY], RteFsUtils::FileCategoryFromExtension(file.file)); SetControlsNode(fileNode, context, file.build); node.push_back(fileNode); } @@ -519,11 +522,11 @@ void ProjMgrYamlCbuild::SetOutputDirsNode(YAML::Node node, const ContextItem* co void ProjMgrYamlCbuild::SetOutputNode(YAML::Node node, const ContextItem* context) { const auto& types = context->outputTypes; const vector> outputTypes = { - { types.bin.on, types.bin.filename, ProjMgrUtils::OUTPUT_TYPE_BIN }, - { types.elf.on, types.elf.filename, ProjMgrUtils::OUTPUT_TYPE_ELF }, - { types.hex.on, types.hex.filename, ProjMgrUtils::OUTPUT_TYPE_HEX }, - { types.lib.on, types.lib.filename, ProjMgrUtils::OUTPUT_TYPE_LIB }, - { types.cmse.on, types.cmse.filename, ProjMgrUtils::OUTPUT_TYPE_CMSE }, + { types.bin.on, types.bin.filename, RteConstants::OUTPUT_TYPE_BIN }, + { types.elf.on, types.elf.filename, RteConstants::OUTPUT_TYPE_ELF }, + { types.hex.on, types.hex.filename, RteConstants::OUTPUT_TYPE_HEX }, + { types.lib.on, types.lib.filename, RteConstants::OUTPUT_TYPE_LIB }, + { types.cmse.on, types.cmse.filename, RteConstants::OUTPUT_TYPE_CMSE }, }; for (const auto& [on, file, type] : outputTypes) { if (on) { @@ -594,10 +597,10 @@ void ProjMgrYamlCbuild::SetControlsNode(YAML::Node node, const ContextItem* cont } void ProjMgrYamlCbuild::SetProcessorNode(YAML::Node node, const map& targetAttributes) { - for (const auto& [rteKey, yamlKey]: ProjMgrUtils::DeviceAttributesKeys) { + for (const auto& [rteKey, yamlKey]: RteConstants::DeviceAttributesKeys) { if (targetAttributes.find(rteKey) != targetAttributes.end()) { const auto& rteValue = targetAttributes.at(rteKey); - const auto& yamlValue = ProjMgrUtils::GetDeviceAttribute(rteKey, rteValue); + const auto& yamlValue = RteConstants::GetDeviceAttribute(rteKey, rteValue); if (!yamlValue.empty()) { SetNodeValue(node[yamlKey], yamlValue); } diff --git a/tools/projmgr/src/ProjMgrYamlParser.cpp b/tools/projmgr/src/ProjMgrYamlParser.cpp index f64e5845d..82c10ca33 100644 --- a/tools/projmgr/src/ProjMgrYamlParser.cpp +++ b/tools/projmgr/src/ProjMgrYamlParser.cpp @@ -701,7 +701,7 @@ bool ProjMgrYamlParser::ParseContexts(const YAML::Node& parent, CsolutionItem& c descriptor.cproject = RteFsUtils::RelativePath(fs::canonical(fs::path(csolution.directory).append(descriptor.cproject), ec).generic_string(), csolution.directory); if (!descriptor.cproject.empty()) { csolution.contexts.push_back(descriptor); - ProjMgrUtils::PushBackUniquely(csolution.cprojects, descriptor.cproject); + CollectionUtils::PushBackUniquely(csolution.cprojects, descriptor.cproject); } } } diff --git a/tools/projmgr/test/src/ProjMgrGeneratorUnitTests.cpp b/tools/projmgr/test/src/ProjMgrGeneratorUnitTests.cpp index ca1a57142..fef9d3f8a 100644 --- a/tools/projmgr/test/src/ProjMgrGeneratorUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrGeneratorUnitTests.cpp @@ -99,7 +99,7 @@ TEST_F(ProjMgrGeneratorUnitTests, FailCreatingDirectories) { // Create a file with same name as parent directory where cbuild-gen.yml will be attempted to be created EXPECT_TRUE(RteFsUtils::CreateDirectories(folder)); - EXPECT_TRUE(RteFsUtils::CreateFile(folder + "/TypeA", "")); + EXPECT_TRUE(RteFsUtils::CreateTextFile(folder + "/TypeA", "")); EXPECT_EQ(1, ProjMgr::RunProjMgr(6, argv, 0)); diff --git a/tools/projmgr/test/src/ProjMgrTestEnv.cpp b/tools/projmgr/test/src/ProjMgrTestEnv.cpp index a4fcd8862..51eea1a34 100644 --- a/tools/projmgr/test/src/ProjMgrTestEnv.cpp +++ b/tools/projmgr/test/src/ProjMgrTestEnv.cpp @@ -21,6 +21,8 @@ string testcmsispack_folder; string testcmsiscompiler_folder; string schema_folder; string templates_folder; +string etc_folder; +string bin_folder; StdStreamRedirect::StdStreamRedirect() : m_outbuffer(""), m_cerrbuffer(""), @@ -56,6 +58,11 @@ void ProjMgrTestEnv::SetUp() { testoutput_folder = RteFsUtils::GetCurrentFolder() + "output"; testcmsispack_folder = string(CMAKE_SOURCE_DIR) + "test/packs"; testcmsiscompiler_folder = testinput_folder + "/TestToolchains"; + etc_folder = string(PROJMGRUNITTESTS_BIN_PATH) + "/../etc"; + RteFsUtils::NormalizePath(etc_folder); + bin_folder = string(PROJMGRUNITTESTS_BIN_PATH) + "/../bin"; + RteFsUtils::NormalizePath(bin_folder); + if (RteFsUtils::Exists(testoutput_folder)) { RteFsUtils::RemoveDir(testoutput_folder); } @@ -69,12 +76,11 @@ void ProjMgrTestEnv::SetUp() { ASSERT_FALSE(schema_folder.empty()); // copy schemas - std::string schemaDestDir = string(PROJMGRUNITTESTS_BIN_PATH) + "/../etc"; - if (RteFsUtils::Exists(schemaDestDir)) { - RteFsUtils::RemoveDir(schemaDestDir); + if (RteFsUtils::Exists(etc_folder)) { + RteFsUtils::RemoveDir(etc_folder); } - RteFsUtils::CreateDirectories(schemaDestDir); - fs::copy(fs::path(schema_folder), fs::path(schemaDestDir), fs::copy_options::recursive, ec); + RteFsUtils::CreateDirectories(etc_folder); + fs::copy(fs::path(schema_folder), fs::path(etc_folder), fs::copy_options::recursive, ec); //copy test input data if (RteFsUtils::Exists(testinput_folder)) { @@ -83,6 +89,11 @@ void ProjMgrTestEnv::SetUp() { RteFsUtils::CreateDirectories(testinput_folder); fs::copy(fs::path(testdata_folder), fs::path(testinput_folder), fs::copy_options::recursive, ec); + if (RteFsUtils::Exists(bin_folder)) { + RteFsUtils::RemoveDir(bin_folder); + } + RteFsUtils::CreateDirectories(bin_folder); + // copy local pack string srcPackPath, destPackPath; srcPackPath = testcmsispack_folder + "/ARM/RteTest_DFP/0.2.0"; @@ -114,9 +125,9 @@ void ProjMgrTestEnv::SetUp() { // create dummy cmsis compiler root RteFsUtils::CreateDirectories(testcmsiscompiler_folder); - RteFsUtils::CreateFile(testcmsiscompiler_folder + "/AC6.6.18.0.cmake", ""); - RteFsUtils::CreateFile(testcmsiscompiler_folder + "/GCC.11.2.1.cmake", ""); - RteFsUtils::CreateFile(testcmsiscompiler_folder + "/IAR.8.50.6.cmake", ""); + RteFsUtils::CreateTextFile(testcmsiscompiler_folder + "/AC6.6.18.0.cmake", ""); + RteFsUtils::CreateTextFile(testcmsiscompiler_folder + "/GCC.11.2.1.cmake", ""); + RteFsUtils::CreateTextFile(testcmsiscompiler_folder + "/IAR.8.50.6.cmake", ""); CrossPlatformUtils::SetEnv("CMSIS_COMPILER_ROOT", testcmsiscompiler_folder); // copy linker script template files diff --git a/tools/projmgr/test/src/ProjMgrTestEnv.h b/tools/projmgr/test/src/ProjMgrTestEnv.h index 7aad859d7..01370bf47 100644 --- a/tools/projmgr/test/src/ProjMgrTestEnv.h +++ b/tools/projmgr/test/src/ProjMgrTestEnv.h @@ -16,7 +16,8 @@ extern std::string testinput_folder; extern std::string testcmsispack_folder; extern std::string testcmsiscompiler_folder; extern std::string schema_folder; - +extern std::string etc_folder; +extern std::string bin_folder; /** * @brief direct console output to string */ diff --git a/tools/projmgr/test/src/ProjMgrUnitTests.cpp b/tools/projmgr/test/src/ProjMgrUnitTests.cpp index 9f9e8d5b9..7cfe549f5 100644 --- a/tools/projmgr/test/src/ProjMgrUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrUnitTests.cpp @@ -3318,7 +3318,7 @@ TEST_F(ProjMgrUnitTests, RunProjMgrSolution_GetCdefaultFile1) { const string& testdir = testoutput_folder + "/FindFileRegEx"; const string& fileName = testdir + "/cdefault.yml"; RteFsUtils::CreateDirectories(testdir); - RteFsUtils::CreateFile(fileName, ""); + RteFsUtils::CreateTextFile(fileName, ""); m_rootDir = testdir; m_cdefaultFile.clear(); EXPECT_TRUE(GetCdefaultFile()); @@ -3759,7 +3759,7 @@ TEST_F(ProjMgrUnitTests, RunProjMgr_WriteCprjFail) { argv[9] = (char*)"_export"; // Fail to write export cprj file - RteFsUtils::CreateFile(outputFolder + "/test2.Debug+CM0_export.cprj", ""); + RteFsUtils::CreateTextFile(outputFolder + "/test2.Debug+CM0_export.cprj", ""); RteFsUtils::SetTreeReadOnly(outputFolder); EXPECT_EQ(1, RunProjMgr(10, argv, 0)); @@ -3881,7 +3881,7 @@ error csolution: processing context 'outputFiles.TypeConflict\\+Target' failed\n TEST_F(ProjMgrUnitTests, SelectToolchains) { const string& AC6_6_6_5 = testinput_folder + "/TestToolchains/AC6.6.6.5.cmake"; - RteFsUtils::CreateFile(AC6_6_6_5, ""); + RteFsUtils::CreateTextFile(AC6_6_6_5, ""); char* envp[6]; string ac6_0 = "AC6_TOOLCHAIN_6_20_0=" + testinput_folder; string ac6_1 = "AC6_TOOLCHAIN_6_16_1=" + testinput_folder; @@ -4211,8 +4211,8 @@ TEST_F(ProjMgrUnitTests, RunProjMgr_UpdateRte) { const string& testdir = testoutput_folder + "/OutputDir"; RteFsUtils::RemoveDir(rteDir); RteFsUtils::RemoveDir(testdir); - RteFsUtils::CreateFile(configFile, "// config file"); - RteFsUtils::CreateFile(baseFile, "// config file@base"); + RteFsUtils::CreateTextFile(configFile, "// config file"); + RteFsUtils::CreateTextFile(baseFile, "// config file@base"); StdStreamRedirect streamRedirect; string csolutionFile = testinput_folder + "/TestSolution/test.csolution.yml"; @@ -4792,12 +4792,13 @@ TEST_F(ProjMgrUnitTests, RunProjMgrSolution_cbuildset_file) { } TEST_F(ProjMgrUnitTests, ExternalGenerator) { + const string& srcGlobalGenerator = testinput_folder + "/ExternalGenerator/global.generator.yml"; - const string& dstGlobalGenerator = testcmsiscompiler_folder + "/global.generator.yml"; + const string& dstGlobalGenerator = etc_folder + "/global.generator.yml"; RteFsUtils::CopyCheckFile(srcGlobalGenerator, dstGlobalGenerator, false); const string& srcBridgeTool = testinput_folder + "/ExternalGenerator/bridge.sh"; - const string& dstBridgeTool = testcmsiscompiler_folder + "/bridge.sh"; + const string& dstBridgeTool = bin_folder + "/bridge.sh"; RteFsUtils::CopyCheckFile(srcBridgeTool, dstBridgeTool, false); // list generators @@ -4896,7 +4897,7 @@ error csolution: generator 'RteTestExternalGenerator' required by component 'ARM TEST_F(ProjMgrUnitTests, ExternalGenerator_WrongGenDir) { const string& srcGlobalGenerator = testinput_folder + "/ExternalGenerator/wrong-gendir.generator.yml"; - const string& dstGlobalGenerator = testcmsiscompiler_folder + "/global.generator.yml"; + const string& dstGlobalGenerator = etc_folder + "/global.generator.yml"; RteFsUtils::CopyCheckFile(srcGlobalGenerator, dstGlobalGenerator, false); StdStreamRedirect streamRedirect; @@ -4922,7 +4923,7 @@ warning csolution: unknown access sequence: 'UnknownAccessSequence()'\n\ TEST_F(ProjMgrUnitTests, ExternalGenerator_NoGenDir) { const string& srcGlobalGenerator = testinput_folder + "/ExternalGenerator/no-gendir.generator.yml"; - const string& dstGlobalGenerator = testcmsiscompiler_folder + "/global.generator.yml"; + const string& dstGlobalGenerator = etc_folder + "/global.generator.yml"; RteFsUtils::CopyCheckFile(srcGlobalGenerator, dstGlobalGenerator, false); StdStreamRedirect streamRedirect; @@ -4967,7 +4968,7 @@ error csolution: a single context must be specified\n\ TEST_F(ProjMgrUnitTests, ExternalGenerator_WrongGeneratedData) { const string& srcGlobalGenerator = testinput_folder + "/ExternalGenerator/global.generator.yml"; - const string& dstGlobalGenerator = testcmsiscompiler_folder + "/global.generator.yml"; + const string& dstGlobalGenerator = etc_folder + "/global.generator.yml"; RteFsUtils::CopyCheckFile(srcGlobalGenerator, dstGlobalGenerator, false); StdStreamRedirect streamRedirect; @@ -5003,7 +5004,7 @@ TEST_F(ProjMgrUnitTests, ExternalGenerator_WrongGeneratedData) { TEST_F(ProjMgrUnitTests, ExternalGenerator_NoCgenFile) { const string& srcGlobalGenerator = testinput_folder + "/ExternalGenerator/global.generator.yml"; - const string& dstGlobalGenerator = testcmsiscompiler_folder + "/global.generator.yml"; + const string& dstGlobalGenerator = etc_folder + "/global.generator.yml"; RteFsUtils::CopyCheckFile(srcGlobalGenerator, dstGlobalGenerator, false); const string genDir = m_extGenerator.GetGlobalGenDir("RteTestExternalGenerator"); @@ -5027,7 +5028,7 @@ TEST_F(ProjMgrUnitTests, ExternalGenerator_NoCgenFile) { TEST_F(ProjMgrUnitTests, ExternalGeneratorListVerbose) { const string& srcGlobalGenerator = testinput_folder + "/ExternalGenerator/global.generator.yml"; - const string& dstGlobalGenerator = testcmsiscompiler_folder + "/global.generator.yml"; + const string& dstGlobalGenerator = etc_folder + "/global.generator.yml"; RteFsUtils::CopyCheckFile(srcGlobalGenerator, dstGlobalGenerator, false); StdStreamRedirect streamRedirect; diff --git a/tools/projmgr/test/src/ProjMgrUtilsUnitTests.cpp b/tools/projmgr/test/src/ProjMgrUtilsUnitTests.cpp index 1435faf28..030abc8b7 100644 --- a/tools/projmgr/test/src/ProjMgrUtilsUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrUtilsUnitTests.cpp @@ -72,59 +72,6 @@ TEST_F(ProjMgrUtilsUnitTests, ReadGpdscFileNoExists) { EXPECT_FALSE(validGpdsc); } -TEST_F(ProjMgrUtilsUnitTests, ExecCommand) { - auto result = ProjMgrUtils::ExecCommand("invalid command"); - EXPECT_EQ(false, (0 == result.second) ? true : false) << result.first; - - string testdir = "mkdir_test_dir"; - error_code ec; - const auto& workingDir = fs::current_path(ec); - fs::current_path(testoutput_folder, ec); - if (fs::exists(testdir)) { - RteFsUtils::RemoveDir(testdir); - } - result = ProjMgrUtils::ExecCommand("mkdir " + testdir); - EXPECT_TRUE(fs::exists(testdir)); - EXPECT_EQ(true, (0 == result.second) ? true : false) << result.first; - - fs::current_path(workingDir, ec); - RteFsUtils::RemoveDir(testdir); -} - -TEST_F(ProjMgrUtilsUnitTests, StrToInt) { - map testDataVec = { - { "0", 0 }, - { " ", 0 }, - { "", 0 }, - { "alphanum012345", 0 }, - { "000", 0 }, - { "123", 123 }, - { "+456", 456 }, - }; - for (const auto& [input, expected] : testDataVec) { - EXPECT_EQ(ProjMgrUtils::StringToInt(input), expected); - } -} - -TEST_F(ProjMgrUtilsUnitTests, GetCategory) { - map> testDataVec = { - {"sourceC", {"sourceFile.c", "sourceFile.C"}}, - {"sourceCpp", {"sourceFile.cpp", "sourceFile.c++", "sourceFile.C++", "sourceFile.cxx", "sourceFile.cc", "sourceFile.CC"}}, - {"sourceAsm", {"sourceFile.asm", "sourceFile.s", "sourceFile.S"}}, - {"header", {"headerFile.h", "headerFile.hpp"}}, - {"library", {"libraryFile.a", "libraryFile.lib"}}, - {"object", {"objectFile.o"}}, - {"linkerScript", {"linkerFile.sct", "linkerFile.scf", "linkerFile.ld", "linkerFile.icf"}}, - {"doc", {"documentFile.txt", "documentFile.md", "documentFile.pdf", "documentFile.htm", "documentFile.html"}}, - }; - for (const auto& [expected, files] : testDataVec) { - for (const auto& file : files) { - EXPECT_EQ(ProjMgrUtils::GetCategory(file), expected); - } - } -} - - TEST_F(ProjMgrUtilsUnitTests, CompilersIntersect) { string intersection; CompilersIntersect("AC6@6.16.0", "AC6", intersection); diff --git a/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp b/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp index dfcd209c7..929804041 100644 --- a/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrWorkerUnitTests.cpp @@ -33,7 +33,7 @@ void ProjMgrWorkerUnitTests::SetCsolutionPacks(CsolutionItem* csolution, std::ve } context.csolution = csolution; context.type.target = targetType; - ProjMgrUtils::PushBackUniquely(m_ymlOrderedContexts, targetType); + CollectionUtils::PushBackUniquely(m_ymlOrderedContexts, targetType); m_contexts.insert(std::pair(string(targetType), context)); } @@ -1105,21 +1105,6 @@ TEST_F(ProjMgrWorkerUnitTests, CollectLayersFromPacks) { EXPECT_FALSE(CollectLayersFromPacks(context, clayers)); } -TEST_F(ProjMgrWorkerUnitTests, ExpandString) { - ContextItem context; - context.variables = { - {"Foo", "./foo"}, - {"Bar", "./bar"}, - {"Foo Bar", "./foo-bar"}, - }; - - EXPECT_EQ(ExpandString("path1: $Foo$/bar", context.variables), "path1: ./foo/bar"); - EXPECT_EQ(ExpandString("path2: $Bar$/foo", context.variables), "path2: ./bar/foo"); - EXPECT_EQ(ExpandString("$Foo$ $Bar$", context.variables), "./foo ./bar"); - EXPECT_EQ(ExpandString("$Foo Bar$", context.variables), "./foo-bar"); - EXPECT_EQ(ExpandString("$Foo$ $Foo$ $Foo$", context.variables), "./foo ./foo ./foo"); -} - TEST_F(ProjMgrWorkerUnitTests, ListToolchains) { const string& cmsisPackRoot = CrossPlatformUtils::GetEnv("CMSIS_COMPILER_ROOT"); @@ -1280,7 +1265,7 @@ TEST_F(ProjMgrWorkerUnitTests, ProcessLinkerOptions) { linker.regions = linkerRegionsFile; cproject.linker.push_back(linker); context.compiler = "AC6"; - context.variables[ProjMgrUtils::AS_COMPILER] = context.compiler; + context.variables[RteConstants::AS_COMPILER] = context.compiler; string expectedLinkerScriptFile = "path/to/linkerScript_AC6.sct"; string expectedLinkerRegionsFile = "path/to/linkerRegions_AC6.h"; EXPECT_TRUE(ProcessLinkerOptions(context)); @@ -1566,22 +1551,22 @@ TEST_F(ProjMgrWorkerUnitTests, CheckDeviceAttributes) { StrMap targetAttributes; StdStreamRedirect streamRedirect; - userSelection.branchProtection = ProjMgrUtils::YAML_BP_BTI; - userSelection.dsp = ProjMgrUtils::YAML_ON; - userSelection.endian = ProjMgrUtils::YAML_ENDIAN_BIG; - userSelection.fpu = ProjMgrUtils::YAML_FPU_DP; - userSelection.mve = ProjMgrUtils::YAML_MVE_FP; - userSelection.trustzone = ProjMgrUtils::YAML_TZ_SECURE; - targetAttributes[ProjMgrUtils::RTE_DPACBTI] = ProjMgrUtils::RTE_NO_PACBTI; - targetAttributes[ProjMgrUtils::RTE_DDSP] = ProjMgrUtils::RTE_NO_DSP; - targetAttributes[ProjMgrUtils::RTE_DENDIAN] = ProjMgrUtils::RTE_ENDIAN_LITTLE; - targetAttributes[ProjMgrUtils::RTE_DFPU] = ProjMgrUtils::RTE_SP_FPU; - targetAttributes[ProjMgrUtils::RTE_DMVE] = ProjMgrUtils::RTE_NO_MVE; - targetAttributes[ProjMgrUtils::RTE_DTZ] = ProjMgrUtils::RTE_NO_TZ; + userSelection.branchProtection = RteConstants::YAML_BP_BTI; + userSelection.dsp = RteConstants::YAML_ON; + userSelection.endian = RteConstants::YAML_ENDIAN_BIG; + userSelection.fpu = RteConstants::YAML_FPU_DP; + userSelection.mve = RteConstants::YAML_MVE_FP; + userSelection.trustzone = RteConstants::YAML_TZ_SECURE; + targetAttributes[RteConstants::RTE_DPACBTI] = RteConstants::RTE_NO_PACBTI; + targetAttributes[RteConstants::RTE_DDSP] = RteConstants::RTE_NO_DSP; + targetAttributes[RteConstants::RTE_DENDIAN] = RteConstants::RTE_ENDIAN_LITTLE; + targetAttributes[RteConstants::RTE_DFPU] = RteConstants::RTE_SP_FPU; + targetAttributes[RteConstants::RTE_DMVE] = RteConstants::RTE_NO_MVE; + targetAttributes[RteConstants::RTE_DTZ] = RteConstants::RTE_NO_TZ; CheckDeviceAttributes(device, userSelection, targetAttributes); auto errStr = streamRedirect.GetErrorString(); - + EXPECT_TRUE(errStr.find("warning csolution: device 'TestDevice' does not support 'endian: big'") != string::npos); EXPECT_TRUE(errStr.find("warning csolution: device 'TestDevice' does not support 'fpu: dp'") != string::npos); EXPECT_TRUE(errStr.find("warning csolution: device 'TestDevice' does not support 'dsp: on'") != string::npos); From ee5c3959ef99988592d7a6ffade32b840cfb325a Mon Sep 17 00:00:00 2001 From: Evgueni Driouk Date: Fri, 2 Feb 2024 15:50:46 +0100 Subject: [PATCH 2/3] Update ProjMgrYamlEmitter.cpp --- tools/projmgr/src/ProjMgrYamlEmitter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/projmgr/src/ProjMgrYamlEmitter.cpp b/tools/projmgr/src/ProjMgrYamlEmitter.cpp index 33f17f8ea..37a8e38a8 100644 --- a/tools/projmgr/src/ProjMgrYamlEmitter.cpp +++ b/tools/projmgr/src/ProjMgrYamlEmitter.cpp @@ -351,7 +351,6 @@ void ProjMgrYamlCbuild::SetComponentsNode(YAML::Node node, const ContextItem* co SetNodeValue(componentNode[YAML_GENERATOR][YAML_ID], component.generator); const RteGenerator* rteGenerator = get_or_null(context->generators, component.generator); if(rteGenerator && !rteGenerator->IsExternal()) { - const RteGenerator* rteGenerator = context->generators.at(component.generator); SetNodeValue(componentNode[YAML_GENERATOR][YAML_FROM_PACK], rteGenerator->GetPackageID()); SetGeneratorFiles(componentNode[YAML_GENERATOR], context, componentId); } else if (contains_key(context->extGenDir, component.generator)) { From d326d3d36e850568321a6920649127e7041751af Mon Sep 17 00:00:00 2001 From: Evgueni Driouk Date: Fri, 2 Feb 2024 15:50:58 +0100 Subject: [PATCH 3/3] Update ProjMgrWorker.cpp --- tools/projmgr/src/ProjMgrWorker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/projmgr/src/ProjMgrWorker.cpp b/tools/projmgr/src/ProjMgrWorker.cpp index 50668d744..c7ac402da 100644 --- a/tools/projmgr/src/ProjMgrWorker.cpp +++ b/tools/projmgr/src/ProjMgrWorker.cpp @@ -317,7 +317,7 @@ string ProjMgrWorker::GetPackRoot() { bool ProjMgrWorker::InitializeModel() { if(m_kernel) { - return true; // already initialized; + return true; // already initialized } m_packRoot = GetPackRoot(); m_kernel = ProjMgrKernel::Get();