From 5f15bb179f3af1b8487256c87a6f38f31d76eddc Mon Sep 17 00:00:00 2001 From: grasci <86058054+grasci-arm@users.noreply.github.com> Date: Fri, 16 Aug 2024 09:33:48 +0100 Subject: [PATCH] cbuild setup delivering missing info when no compiler specified (#1002) (#1701) Addressing: https://github.com/Open-CMSIS-Pack/devtools/issues/1663 --- tools/projmgr/include/ProjMgrWorker.h | 8 ++ tools/projmgr/src/ProjMgr.cpp | 1 + tools/projmgr/src/ProjMgrWorker.cpp | 77 +++++++++++++------ .../data/TestLayers/no_compiler.cproject.yml | 26 +++++++ .../data/TestLayers/no_compiler.csolution.yml | 16 ++++ .../TestLayers/ref/no_compiler.cbuild-idx.yml | 30 ++++++++ tools/projmgr/test/src/ProjMgrUnitTests.cpp | 20 +++++ 7 files changed, 153 insertions(+), 25 deletions(-) create mode 100644 tools/projmgr/test/data/TestLayers/no_compiler.cproject.yml create mode 100644 tools/projmgr/test/data/TestLayers/no_compiler.csolution.yml create mode 100644 tools/projmgr/test/data/TestLayers/ref/no_compiler.cbuild-idx.yml diff --git a/tools/projmgr/include/ProjMgrWorker.h b/tools/projmgr/include/ProjMgrWorker.h index a0d168459..287385bb3 100644 --- a/tools/projmgr/include/ProjMgrWorker.h +++ b/tools/projmgr/include/ProjMgrWorker.h @@ -554,6 +554,12 @@ class ProjMgrWorker { */ void SetSelectedToolchain(const std::string& selectedToolchain); + /** + * @brief set flag when setup command is triggered + * @param boolean isSetup + */ + void SetUpCommand(bool isSetup); + /** * @brief execute generator of a given context * @param generator identifier @@ -712,6 +718,7 @@ class ProjMgrWorker { bool m_dryRun; bool m_relativePaths; bool m_cbuild2cmake; + bool m_isSetupCommand; std::set m_undefLayerVars; StrMap m_packMetadata; std::map m_executes; @@ -822,6 +829,7 @@ class ProjMgrWorker { void SetExecutesDependencies(const std::string& output, const std::string& dep, const std::string& outDir); bool ValidateComponentSources(ContextItem& context); void ProcessSelectableCompilers(); + StrVec CollectSelectableCompilers(); void ProcessTmpDir(std::string& tmpdir, const std::string& base); }; diff --git a/tools/projmgr/src/ProjMgr.cpp b/tools/projmgr/src/ProjMgr.cpp index 4f25fde9f..33dc2a1e1 100644 --- a/tools/projmgr/src/ProjMgr.cpp +++ b/tools/projmgr/src/ProjMgr.cpp @@ -203,6 +203,7 @@ int ProjMgr::ParseCommandLine(int argc, char** argv) { m_worker.SetDryRun(m_dryRun); m_ymlOrder = parseResult.count("yml-order"); m_updateIdx = parseResult.count("update-idx"); + m_worker.SetUpCommand(m_updateIdx); m_contextSet = parseResult.count("context-set"); m_relativePaths = parseResult.count("relative-paths"); m_worker.SetPrintRelativePaths(m_relativePaths); diff --git a/tools/projmgr/src/ProjMgrWorker.cpp b/tools/projmgr/src/ProjMgrWorker.cpp index 2664a4d0a..5232894be 100644 --- a/tools/projmgr/src/ProjMgrWorker.cpp +++ b/tools/projmgr/src/ProjMgrWorker.cpp @@ -294,6 +294,10 @@ const StrVec& ProjMgrWorker::GetSelectableCompilers(void) { return m_selectableCompilers; } +void ProjMgrWorker::SetUpCommand(bool isSetup) { + m_isSetupCommand = isSetup; +} + bool ProjMgrWorker::CollectRequiredPdscFiles(ContextItem& context, const std::string& packRoot) { if (!ProcessPackages(context, packRoot)) { @@ -1681,14 +1685,26 @@ bool ProjMgrWorker::AddPackRequirements(ContextItem& context, const vectorcompiler.empty()) { - // compiler was not specified + // Use the default compiler if available + if (context.cdefault && !context.cdefault->compiler.empty()) { + context.compiler = context.cdefault->compiler; + } + // Otherwise, select the first available compiler from selectableCompilers + else if (m_isSetupCommand && !context.csolution->selectableCompilers.empty()) { + m_selectableCompilers = CollectSelectableCompilers(); + if (m_selectableCompilers.size() > 0) { + context.compiler = m_selectableCompilers[0]; + } + else { + m_undefCompiler = true; + return false; + } + } + // No compiler was specified, mark as undefined and return failure + else { m_undefCompiler = true; return false; - } else { - context.compiler = context.cdefault->compiler; } } @@ -4946,27 +4962,38 @@ void ProjMgrWorker::ProcessSelectableCompilers() { if (m_undefCompiler) { // compiler was not specified // get selectable compilers specified in cdefault and csolution - StrVecMap compilersMap; - for (const auto& selectableCompilers : { m_parser->GetCdefault().selectableCompilers, m_parser->GetCsolution().selectableCompilers }) { - for (const auto& selectableCompiler : selectableCompilers) { - ToolchainItem item = GetToolchain(selectableCompiler); - CollectionUtils::PushBackUniquely(compilersMap[item.name], selectableCompiler); - } - } - // store intersection of required versions if compatible with registered one - for (const auto& [name, compilers] : compilersMap) { - string intersection; - for (const auto& compiler : compilers) { - ProjMgrUtils::CompilersIntersect(intersection, compiler, intersection); - } - if (!intersection.empty()) { - ToolchainItem item = GetToolchain(intersection); - if (GetLatestToolchain(item)) { - CollectionUtils::PushBackUniquely(m_selectableCompilers, intersection); - } - } - } + m_selectableCompilers = CollectSelectableCompilers(); + m_toolchainErrors.insert("compiler undefined, use '--toolchain' option or add 'compiler: ' to yml input" + string(m_selectableCompilers.size() > 0 ? ", selectable values can be found in cbuild-idx.yml" : "")); } } + +StrVec ProjMgrWorker::CollectSelectableCompilers() { + StrVec resCompilers; + StrVecMap compilersMap; + + const auto selectableCompilerLists = { m_parser->GetCdefault().selectableCompilers, m_parser->GetCsolution().selectableCompilers }; + for (const auto& selectableCompilers : selectableCompilerLists) { + for (const auto& selectableCompiler : selectableCompilers) { + ToolchainItem toolchain = GetToolchain(selectableCompiler); + CollectionUtils::PushBackUniquely(compilersMap[toolchain.name], selectableCompiler); + } + } + // store intersection of required versions if compatible with registered one + for (const auto& [name, compilers] : compilersMap) { + string intersection; + for (const auto& compiler : compilers) { + ProjMgrUtils::CompilersIntersect(intersection, compiler, intersection); + } + + // If a compatible version is found, add it to selectable compilers + if (!intersection.empty()) { + ToolchainItem toolchain = GetToolchain(intersection); + if (GetLatestToolchain(toolchain)) { + CollectionUtils::PushBackUniquely(resCompilers, intersection); + } + } + } + return resCompilers; +} diff --git a/tools/projmgr/test/data/TestLayers/no_compiler.cproject.yml b/tools/projmgr/test/data/TestLayers/no_compiler.cproject.yml new file mode 100644 index 000000000..c3b83e8ef --- /dev/null +++ b/tools/projmgr/test/data/TestLayers/no_compiler.cproject.yml @@ -0,0 +1,26 @@ +project: + layers: + - layer: select.clayer.yml + type: Select1 + + connections: + - connect: project X + set: set1.select1 + info: set 1 select 1 + consumes: + - connectA + - connectB + + - connect: project Y + set: set1.select2 + info: set 1 select 2 + consumes: + - connectB + - connectC + + - connect: project Z + set: set1.select2 + info: set 1 select 2 + consumes: + - connectC + - connectD diff --git a/tools/projmgr/test/data/TestLayers/no_compiler.csolution.yml b/tools/projmgr/test/data/TestLayers/no_compiler.csolution.yml new file mode 100644 index 000000000..55a704873 --- /dev/null +++ b/tools/projmgr/test/data/TestLayers/no_compiler.csolution.yml @@ -0,0 +1,16 @@ +solution: + select-compiler: + - compiler: AC6 + - compiler: GCC + - compiler: CLANG + + target-types: + - type: RteTest_ARMCM3 + device: RteTest_ARMCM3 + + projects: + - project: no_compiler.cproject.yml + + packs: + - pack: ARM::RteTest + - pack: ARM::RteTest_DFP diff --git a/tools/projmgr/test/data/TestLayers/ref/no_compiler.cbuild-idx.yml b/tools/projmgr/test/data/TestLayers/ref/no_compiler.cbuild-idx.yml new file mode 100644 index 000000000..51277b4ac --- /dev/null +++ b/tools/projmgr/test/data/TestLayers/ref/no_compiler.cbuild-idx.yml @@ -0,0 +1,30 @@ +build-idx: + generated-by: csolution version 0.0.0+g113301ee + csolution: no_compiler.csolution.yml + tmpdir: tmp + configurations: + - target-type: RteTest_ARMCM3 + target-configurations: + - configuration: + variables: + - Board-Layer: $SolutionDir()$/select.clayer.yml + settings: + - set: set1.select1 (provided connections A and B - set 1 select 1) + - configuration: + variables: + - Board-Layer: $SolutionDir()$/select.clayer.yml + settings: + - set: set1.select2 (provided connections B and C - set 1 select 2) + select-compiler: + - compiler: AC6 + - compiler: GCC + cprojects: + - cproject: no_compiler.cproject.yml + clayers: + - clayer: select.clayer.yml + cbuilds: + - cbuild: no_compiler+RteTest_ARMCM3.cbuild.yml + project: no_compiler + configuration: +RteTest_ARMCM3 + clayers: + - clayer: select.clayer.yml diff --git a/tools/projmgr/test/src/ProjMgrUnitTests.cpp b/tools/projmgr/test/src/ProjMgrUnitTests.cpp index b42bd09ba..61b37120c 100644 --- a/tools/projmgr/test/src/ProjMgrUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrUnitTests.cpp @@ -6203,3 +6203,23 @@ TEST_F(ProjMgrUnitTests, RunProjMgr_conflict_cbuild_set) { auto errStr = streamRedirect.GetErrorString(); EXPECT_NE(errStr.find("build-type is not unique in 'test1.Release+CM0' and 'test1.Debug+CM0'"), string::npos); } + +TEST_F(ProjMgrUnitTests, ListLayers_update_idx_with_no_compiler_selected) { + StdStreamRedirect streamRedirect; + char* argv[6]; + const string& csolution = testinput_folder + "/TestLayers/no_compiler.csolution.yml"; + string expectedOutStr = ".*no_compiler.cbuild-idx.yml - info csolution: file generated successfully\\n"; + + argv[1] = (char*)"list"; + argv[2] = (char*)"layers"; + argv[3] = (char*)"--solution"; + argv[4] = (char*)csolution.c_str(); + argv[5] = (char*)"--update-idx"; + + EXPECT_EQ(0, RunProjMgr(6, argv, m_envp)); + EXPECT_TRUE(regex_match(streamRedirect.GetOutString(), regex(expectedOutStr))); + + ProjMgrTestEnv::CompareFile(testinput_folder + "/TestLayers/ref/no_compiler.cbuild-idx.yml", + testinput_folder + "/TestLayers/no_compiler.cbuild-idx.yml"); + EXPECT_TRUE(ProjMgrYamlSchemaChecker().Validate(testinput_folder + "/TestLayers/no_compiler.cbuild-idx.yml")); +}