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..c7ac402da 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..37a8e38a8 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,13 @@ 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()) { - 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_ID], component.generator); + const RteGenerator* rteGenerator = get_or_null(context->generators, component.generator); + if(rteGenerator && !rteGenerator->IsExternal()) { + 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 +399,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 +413,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 +421,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 +470,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 +521,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 +596,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);