From 8881935a38fa08fc0b7ca15e1f3a701e3d341375 Mon Sep 17 00:00:00 2001 From: Neko Box Coder Date: Sat, 3 May 2025 20:54:46 +0100 Subject: [PATCH 1/5] Updating CppOverride and tests --- External/CppOverride | 2 +- Src/Tests/BuildsManagerTest.cpp | 383 +++++++++--------- Src/Tests/IncludeManagerTest.cpp | 650 +++++++++++++++---------------- 3 files changed, 517 insertions(+), 518 deletions(-) diff --git a/External/CppOverride b/External/CppOverride index 4f467e3..0f4c252 160000 --- a/External/CppOverride +++ b/External/CppOverride @@ -1 +1 @@ -Subproject commit 4f467e39bb9c1b1ecee05708a7f85d60d7364ec7 +Subproject commit 0f4c252b0811ff58e1635b8e67c494aaef6a948e diff --git a/Src/Tests/BuildsManagerTest.cpp b/Src/Tests/BuildsManagerTest.cpp index cb2e631..ac89c88 100644 --- a/Src/Tests/BuildsManagerTest.cpp +++ b/Src/Tests/BuildsManagerTest.cpp @@ -74,27 +74,25 @@ int main(int argc, char** argv) ) { //Checking mappings file path - returnMappingsPathExistsResult = CppOverride::CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(mappingsFilePath, CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(returnMappingsPathExistsResult); + returnMappingsPathExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(mappingsFilePath, CO_ANY) + .Returns(true) + .Times(1) + .ReturnsResult(); //Open mappings file - returnIfstreamResult = CppOverride::CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) - .WhenCalledWith - (mappingsFilePath) - .Returns() - .Times(1) - .AssignResult(returnIfstreamResult); + returnIfstreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) + .WhenCalledWith(mappingsFilePath) + .Returns() + .Times(1) + .ReturnsResult(); //Checking if mappings file is opened - returnIsOpenResult = CppOverride::CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, is_open) - .Returns(true) - .Times(1) - .AssignResult(returnIsOpenResult); + returnIsOpenResult = CO_SETUP_OVERRIDE (OverrideInstance, is_open) + .Returns(true) + .Times(1) + .ReturnsResult(); //Return file content std::string mappingsContent; if(!customContent.empty()) @@ -105,11 +103,10 @@ int main(int argc, char** argv) mappingsContent += scriptsPaths.at(i) + "," + scriptsBuildsPaths.at(i) + "\n"; } - returnRdbufResult = CppOverride::CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) - .Returns(mappingsContent) - .Times(1) - .AssignResult(returnRdbufResult); + returnRdbufResult = CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) + .Returns(mappingsContent) + .Times(1) + .ReturnsResult(); }; ssTEST_INIT_TEST_GROUP(); @@ -131,11 +128,11 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( - std::shared_ptr result = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) - .Times(1) - .Returns(false) - .AssignResult(result); + std::shared_ptr result = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) + .Times(1) + .Returns(false) + .ReturnsResult(); ghc::filesystem::path outPath; ); ssTEST_OUTPUT_ASSERT(buildsManager->CreateBuildMapping(scriptsPaths.front()) == false); @@ -156,20 +153,20 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //Checking mappings file path - std::shared_ptr pathExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(mappingsFilePath, CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(pathExistsResult); + std::shared_ptr pathExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(mappingsFilePath, CO_ANY) + .Returns(true) + .Times(1) + .ReturnsResult(); //Open mappings file - std::shared_ptr ifstreamResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) - .WhenCalledWith(mappingsFilePath) - .Returns() - .Times(1) - .AssignResult(ifstreamResult); + std::shared_ptr ifstreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) + .WhenCalledWith(mappingsFilePath) + .Returns() + .Times(1) + .ReturnsResult(); ); ssTEST_OUTPUT_EXECUTION( buildsManager->Initialize(); ); ssTEST_OUTPUT_ASSERT("Checking mappings file path", pathExistsResult->LastStatusSucceed()); @@ -182,48 +179,48 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //Checking mappings file path - std::shared_ptr mappingsPathExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(mappingsFilePath, CO_ANY) - .Returns(false) - .Times(1) - .AssignResult(mappingsPathExistsResult); + std::shared_ptr mappingsPathExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(mappingsFilePath, CO_ANY) + .Returns(false) + .Times(1) + .ReturnsResult(); //Checking builds directory exist - std::shared_ptr buildsDirExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(buildsDirPath, CO_ANY) - .Returns(false) - .Times(1) - .AssignResult(buildsDirExistsResult); + std::shared_ptr buildsDirExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(buildsDirPath, CO_ANY) + .Returns(false) + .Times(1) + .ReturnsResult(); //Create builds directory - std::shared_ptr createBuildsDirResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) - .WhenCalledWith(buildsDirPath, CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(createBuildsDirResult); + std::shared_ptr createBuildsDirResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) + .WhenCalledWith(buildsDirPath, CO_ANY) + .Returns(true) + .Times(1) + .ReturnsResult(); //Creating mappings file - std::shared_ptr ofstreamResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_ofstream) - .WhenCalledWith(mappingsFilePath) - .Returns() - .Times(1) - .AssignResult(ofstreamResult); + std::shared_ptr ofstreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ofstream) + .WhenCalledWith(mappingsFilePath) + .Returns() + .Times(1) + .ReturnsResult(); //Checking if mappings file is created - std::shared_ptr ofstreamIsOpenResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, is_open) - .Returns(true) - .Times(1) - .AssignResult(ofstreamIsOpenResult); + std::shared_ptr ofstreamIsOpenResult = + CO_SETUP_OVERRIDE (OverrideInstance, is_open) + .Returns(true) + .Times(1) + .ReturnsResult(); //Closing mappings file - std::shared_ptr ofstreamCloseResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, close) - .Returns() - .Times(1) - .AssignResult(ofstreamCloseResult); + std::shared_ptr ofstreamCloseResult = + CO_SETUP_OVERRIDE (OverrideInstance, close) + .Returns() + .Times(1) + .ReturnsResult(); ); ssTEST_OUTPUT_ASSERT( "Initialize should succeed", buildsManager->Initialize(), true); ssTEST_OUTPUT_ASSERT( "Checking mappings file path", @@ -253,21 +250,35 @@ int main(int argc, char** argv) isOpenResult, rdbufResult, ""); //When mapped build path exists - std::shared_ptr mappedBuildPathExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith - (buildsDirPath + "/" + scriptsBuildsPaths.front() , CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(mappedBuildPathExistsResult); + std::shared_ptr mappedBuildPathExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith + < + const ghc::filesystem::path&, + CO_ANY_TYPE + > + ( + buildsDirPath + "/" + scriptsBuildsPaths.front(), + CO_ANY + ) + .Returns(true) + .Times(1) + .ReturnsResult(); //When mapped build path doesn't exist - std::shared_ptr mappedBuildPathNotExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith - (buildsDirPath + "/" + scriptsBuildsPaths.at(1) , CO_ANY) - .Returns(false) - .Times(1) - .AssignResult(mappedBuildPathNotExistsResult); + std::shared_ptr mappedBuildPathNotExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith + < + const ghc::filesystem::path&, + CO_ANY_TYPE + > + ( + buildsDirPath + "/" + scriptsBuildsPaths.at(1), + CO_ANY + ) + .Returns(false) + .Times(1) + .ReturnsResult(); static_assert(defaultMappingsCount == 2, "Update test"); ); @@ -352,29 +363,29 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //Hash script path - std::shared_ptr hashResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, operator()) - .WhenCalledWith(scriptsPaths.at(2) + "0") - .Returns(15) - .Times(1) - .AssignResult(hashResult); + std::shared_ptr hashResult = + CO_SETUP_OVERRIDE (OverrideInstance, operator()) + .WhenCalledWith(scriptsPaths.at(2) + "0") + .Returns(15) + .Times(1) + .ReturnsResult(); //New build mapping doesn't exist - std::shared_ptr newMappedBuildPathExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith - (buildsDirPath + "/" + scriptsBuildsPaths.at(2), CO_ANY) - .Returns(false) - .Times(1) - .AssignResult(newMappedBuildPathExistsResult); + std::shared_ptr newMappedBuildPathExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith + (buildsDirPath + "/" + scriptsBuildsPaths.at(2), CO_ANY) + .Returns(false) + .Times(1) + .ReturnsResult(); //Create new build mappings directory - std::shared_ptr createNewMappedBuildPathResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) - .WhenCalledWith - (buildsDirPath + "/" + scriptsBuildsPaths.at(2), CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(createNewMappedBuildPathResult); + std::shared_ptr createNewMappedBuildPathResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) + .WhenCalledWith + (buildsDirPath + "/" + scriptsBuildsPaths.at(2), CO_ANY) + .Returns(true) + .Times(1) + .ReturnsResult(); ); ssTEST_OUTPUT_ASSERT( "CreateBuildMapping should succeed", buildsManager->CreateBuildMapping(scriptsPaths.at(2)), true); @@ -389,9 +400,12 @@ int main(int argc, char** argv) ssTEST_OUTPUT_ASSERT( "New mapping exists", BuildsManagerAccessor ::GetMappings(*buildsManager) .count(scriptsPaths.at(2)) == 1); - ssTEST_OUTPUT_ASSERT( "New mapping value is correct", - BuildsManagerAccessor ::GetMappings(*buildsManager) - .at(scriptsPaths.at(2)) == scriptsBuildsPaths.at(2)); + ssTEST_OUTPUT_ASSERT + ( + "New mapping value is correct", + BuildsManagerAccessor::GetMappings(*buildsManager).at(scriptsPaths.at(2)) == + scriptsBuildsPaths.at(2) + ); }; ssTEST("CreateBuildMapping Should Create Build Mapping When Hashed Output Is Not Unique") @@ -401,19 +415,19 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //Hash script path not unique (first attempt) - std::shared_ptr hashNotUniqueResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, operator()) - .WhenCalledWith(scriptsPaths.at(2) + "0") - .Returns(10) - .Times(1) - .AssignResult(hashNotUniqueResult); + std::shared_ptr hashNotUniqueResult = + CO_SETUP_OVERRIDE (OverrideInstance, operator()) + .WhenCalledWith(scriptsPaths.at(2) + "0") + .Returns(10) + .Times(1) + .ReturnsResult(); //Hash script path unique (second attempt) - std::shared_ptr hashUniqueResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, operator()) - .WhenCalledWith(scriptsPaths.at(2) + "1") - .Returns(15) - .Times(1) - .AssignResult(hashUniqueResult); + std::shared_ptr hashUniqueResult = + CO_SETUP_OVERRIDE (OverrideInstance, operator()) + .WhenCalledWith(scriptsPaths.at(2) + "1") + .Returns(15) + .Times(1) + .ReturnsResult(); CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) .WhenCalledWith (buildsDirPath + "/" + scriptsBuildsPaths.at(2), CO_ANY) @@ -429,12 +443,17 @@ int main(int argc, char** argv) hashNotUniqueResult->GetSucceedCount() == 1); ssTEST_OUTPUT_ASSERT( "Hash script path unique (second attempt)", hashUniqueResult->LastStatusSucceed()); - ssTEST_OUTPUT_ASSERT( "New mapping exists", - BuildsManagerAccessor ::GetMappings(*buildsManager) - .count(scriptsPaths.at(2)) == 1); - ssTEST_OUTPUT_ASSERT( "New mapping value is correct", - BuildsManagerAccessor ::GetMappings(*buildsManager) - .at(scriptsPaths.at(2)) == scriptsBuildsPaths.at(2)); + ssTEST_OUTPUT_ASSERT + ( + "New mapping exists", + BuildsManagerAccessor::GetMappings(*buildsManager).count(scriptsPaths.at(2)) == 1 + ); + ssTEST_OUTPUT_ASSERT + ( + "New mapping value is correct", + BuildsManagerAccessor::GetMappings(*buildsManager).at(scriptsPaths.at(2)) == + scriptsBuildsPaths.at(2) + ); }; ssTEST("CreateBuildMapping Should Return True When Mapping For Script Exists") @@ -493,11 +512,11 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //CreateBuildMapping should not be called - std::shared_ptr createBuildMappingResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, CreateBuildMapping) - .Returns(false) - .OverrideObject(buildsManager.get()) - .AssignResult(createBuildMappingResult); + std::shared_ptr createBuildMappingResult = + CO_SETUP_OVERRIDE (OverrideInstance, CreateBuildMapping) + .Returns(false) + .OverrideObject(buildsManager.get()) + .ReturnsResult(); ghc::filesystem::path outPath; ); ssTEST_OUTPUT_ASSERT( "GetBuildMapping should Succeed", @@ -515,24 +534,24 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //CreateBuildMapping should be called - std::shared_ptr createBuildMappingResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, CreateBuildMapping) - .WhenCalledWith(scriptsPaths.at(2)) - .Returns(true) - .Times(1) - .OverrideObject(buildsManager.get()) - .WhenCalledExpectedly_Do - ( - [&buildsManager, &scriptsPaths, &scriptsBuildsPaths](...) - { - BuildsManagerAccessor::GetMappings(*buildsManager) - [scriptsPaths.at(2)] = scriptsBuildsPaths.at(2); - - BuildsManagerAccessor::GetReverseMappings(*buildsManager) - [scriptsBuildsPaths.at(2)] = scriptsPaths.at(2); - } - ) - .AssignResult(createBuildMappingResult); + std::shared_ptr createBuildMappingResult = + CO_SETUP_OVERRIDE (OverrideInstance, CreateBuildMapping) + .WhenCalledWith(scriptsPaths.at(2)) + .Returns(true) + .Times(1) + .OverrideObject(buildsManager.get()) + .WhenCalledExpectedly_Do + ( + [&buildsManager, &scriptsPaths, &scriptsBuildsPaths](...) + { + BuildsManagerAccessor::GetMappings(*buildsManager) + [scriptsPaths.at(2)] = scriptsBuildsPaths.at(2); + + BuildsManagerAccessor::GetReverseMappings(*buildsManager) + [scriptsBuildsPaths.at(2)] = scriptsPaths.at(2); + } + ) + .ReturnsResult(); ghc::filesystem::path outPath; ); ssTEST_OUTPUT_ASSERT( "GetBuildMapping should Succeed", @@ -569,34 +588,34 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //Output to mappings file - std::shared_ptr ofstreamResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_ofstream) - .WhenCalledWith(mappingsFilePath) - .Returns() - .Times(1) - .AssignResult(ofstreamResult); + std::shared_ptr ofstreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ofstream) + .WhenCalledWith(mappingsFilePath) + .Returns() + .Times(1) + .ReturnsResult(); //Checking if mappings file is created - std::shared_ptr ofstreamIsOpenResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, is_open) - .Returns(true) - .Times(1) - .AssignResult(ofstreamIsOpenResult); + std::shared_ptr ofstreamIsOpenResult = + CO_SETUP_OVERRIDE (OverrideInstance, is_open) + .Returns(true) + .Times(1) + .ReturnsResult(); //Closing mappings file - std::shared_ptr ofstreamCloseResult = CreateOverrideResult(); std::string writeResult; - CO_SETUP_OVERRIDE (OverrideInstance, close) - .Returns() - .Times(1) - .WhenCalledExpectedly_Do - ( - [&](void* instance, const std::vector&) - { - writeResult = - static_cast(instance)-> - StringStream.str(); - } - ) - .AssignResult(ofstreamCloseResult); + std::shared_ptr ofstreamCloseResult = + CO_SETUP_OVERRIDE (OverrideInstance, close) + .Returns() + .Times(1) + .WhenCalledExpectedly_Do + ( + [&](void* instance, const std::vector&) + { + writeResult = + static_cast(instance)-> + StringStream.str(); + } + ) + .ReturnsResult(); ); ssTEST_OUTPUT_ASSERT( buildsManager->SaveBuildsMappings() == true); diff --git a/Src/Tests/IncludeManagerTest.cpp b/Src/Tests/IncludeManagerTest.cpp index c293e6b..74004ce 100644 --- a/Src/Tests/IncludeManagerTest.cpp +++ b/Src/Tests/IncludeManagerTest.cpp @@ -77,22 +77,21 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //Check if directory exists - std::shared_ptr dirExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(includeMapsPath, CO_ANY) - .Returns(false) - .Times(1) - .AssignResult(dirExistsResult); - + std::shared_ptr dirExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(includeMapsPath, CO_ANY) + .Returns(false) + .Times(1) + .ReturnsResult(); //Create directory - std::shared_ptr createDirResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) - .WhenCalledWith(includeMapsPath, CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(createDirResult); + std::shared_ptr createDirResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) + .WhenCalledWith(includeMapsPath, CO_ANY) + .Returns(true) + .Times(1) + .ReturnsResult(); ); ssTEST_OUTPUT_ASSERT( "Initialize should succeed", @@ -112,19 +111,18 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //Check if directory exists - std::shared_ptr dirExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(includeMapsPath, CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(dirExistsResult); - + std::shared_ptr dirExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(includeMapsPath, CO_ANY) + .Returns(true) + .Times(1) + .ReturnsResult(); //Create directory should not be called - std::shared_ptr createDirResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) - .Times(0) - .AssignResult(createDirResult); + std::shared_ptr createDirResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) + .Times(0) + .ReturnsResult(); ); ssTEST_OUTPUT_ASSERT( "Initialize should succeed", @@ -144,22 +142,21 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //Check if directory exists - std::shared_ptr dirExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(includeMapsPath, CO_ANY) - .Returns(false) - .Times(1) - .AssignResult(dirExistsResult); - + std::shared_ptr dirExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(includeMapsPath, CO_ANY) + .Returns(false) + .Times(1) + .ReturnsResult(); //Create directory fails - std::shared_ptr createDirResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) - .WhenCalledWith(includeMapsPath, CO_ANY) - .Returns(false) - .Times(1) - .AssignResult(createDirResult); + std::shared_ptr createDirResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_create_directories) + .WhenCalledWith(includeMapsPath, CO_ANY) + .Returns(false) + .Times(1) + .ReturnsResult(); ); ssTEST_OUTPUT_ASSERT( "Initialize should fail", @@ -183,45 +180,42 @@ int main(int argc, char** argv) //Mock GetRecordPath const std::string recordPath = absPathPrefix + "/tmp/Build/IncludeMaps/test.Includes"; - std::shared_ptr getRecordPathResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) - .WhenCalledWith(sourcePaths[0]) - .Returns(recordPath) - .Times(1) - .OverrideObject(includeManager.get()) - .AssignResult(getRecordPathResult); - + std::shared_ptr getRecordPathResult = + CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) + .WhenCalledWith(sourcePaths[0]) + .Returns(recordPath) + .Times(1) + .OverrideObject(includeManager.get()) + .ReturnsResult(); //Open output file - std::shared_ptr ofstreamResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_ofstream) - .WhenCalledWith(recordPath) - .Returns() - .Times(1) - .AssignResult(ofstreamResult); - + std::shared_ptr ofstreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ofstream) + .WhenCalledWith(recordPath) + .Returns() + .Times(1) + .ReturnsResult(); //Check if file is opened - std::shared_ptr isOpenResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, is_open) - .Returns(true) - .Times(1) - .AssignResult(isOpenResult); - + std::shared_ptr isOpenResult = + CO_SETUP_OVERRIDE (OverrideInstance, is_open) + .Returns(true) + .Times(1) + .ReturnsResult(); //Capture content on close std::string writeResult; - std::shared_ptr closeResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, close) - .Returns() - .Times(1) - .WhenCalledExpectedly_Do - ( - [&](void* instance, const std::vector&) - { - writeResult = - static_cast(instance)-> - StringStream.str(); - } - ) - .AssignResult(closeResult); + std::shared_ptr closeResult = + CO_SETUP_OVERRIDE (OverrideInstance, close) + .Returns() + .Times(1) + .WhenCalledExpectedly_Do + ( + [&](void* instance, const std::vector&) + { + writeResult = + static_cast(instance)-> + StringStream.str(); + } + ) + .ReturnsResult(); ); //Initialize first @@ -279,26 +273,24 @@ int main(int argc, char** argv) ( //Test when file open fails const std::string recordPath = absPathPrefix + "/tmp/Build/IncludeMaps/test.Includes"; - std::shared_ptr getRecordPathResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) - .WhenCalledWith(sourcePaths[0]) - .Returns(recordPath) - .Times(1) - .OverrideObject(includeManager.get()) - .AssignResult(getRecordPathResult); - - std::shared_ptr ofstreamResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_ofstream) - .WhenCalledWith(recordPath) - .Returns() - .Times(1) - .AssignResult(ofstreamResult); - - std::shared_ptr isOpenResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, is_open) - .Returns(false) - .Times(1) - .AssignResult(isOpenResult); + std::shared_ptr getRecordPathResult = + CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) + .WhenCalledWith(sourcePaths[0]) + .Returns(recordPath) + .Times(1) + .OverrideObject(includeManager.get()) + .ReturnsResult(); + std::shared_ptr ofstreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ofstream) + .WhenCalledWith(recordPath) + .Returns() + .Times(1) + .ReturnsResult(); + std::shared_ptr isOpenResult = + CO_SETUP_OVERRIDE (OverrideInstance, is_open) + .Returns(false) + .Times(1) + .ReturnsResult(); ); ssTEST_OUTPUT_ASSERT( "WriteIncludeRecord should fail when file open fails", @@ -321,73 +313,66 @@ int main(int argc, char** argv) .WhenCalledWith(includeMapsPath, CO_ANY) .Returns(true); - //Mock GetRecordPath const std::string recordPath = absPathPrefix + "/tmp/Build/IncludeMaps/test.Includes"; - std::shared_ptr getRecordPathResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) - .WhenCalledWith(sourcePaths[0]) - .Returns(recordPath) - .Times(1) - .OverrideObject(includeManager.get()) - .AssignResult(getRecordPathResult); - + std::shared_ptr getRecordPathResult = + CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) + .WhenCalledWith(sourcePaths[0]) + .Returns(recordPath) + .Times(1) + .OverrideObject(includeManager.get()) + .ReturnsResult(); //Check if record file exists - std::shared_ptr recordExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(recordPath, CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(recordExistsResult); - + std::shared_ptr recordExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(recordPath, CO_ANY) + .Returns(true) + .Times(1) + .ReturnsResult(); //Mock last_write_time const auto recordTime = ghc::filesystem::file_time_type::clock::now(); - std::shared_ptr lastWriteResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(recordPath, CO_ANY) - .Returns(recordTime) - .Times(1) - .AssignResult(lastWriteResult); - + std::shared_ptr lastWriteResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(recordPath, CO_ANY) + .Returns(recordTime) + .Times(1) + .ReturnsResult(); //Open input file - std::shared_ptr ifstreamResult = CreateOverrideResult(); + std::shared_ptr ifstreamResult = CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) .WhenCalledWith(recordPath) .Returns() .Times(1) - .AssignResult(ifstreamResult); - + .ReturnsResult(); //Check if file is opened - std::shared_ptr isOpenResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, is_open) - .Returns(true) - .Times(1) - .AssignResult(isOpenResult); - + std::shared_ptr isOpenResult = + CO_SETUP_OVERRIDE (OverrideInstance, is_open) + .Returns(true) + .Times(1) + .ReturnsResult(); //Mock getline to return includes - std::shared_ptr getlineResult = CreateOverrideResult(); int callCount = 0; - CO_SETUP_OVERRIDE (OverrideInstance, Mock_getline) - .Returns(true) - .Times(3) - .WhenCalledExpectedly_Do - ( - [&callCount, &includePaths](void*, const std::vector& args) - { - std::string& line = *static_cast(args[1]); - line = includePaths[callCount++]; - } - ) - .AssignResult(getlineResult); - + std::shared_ptr getlineResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_getline) + .Returns(true) + .Times(3) + .WhenCalledExpectedly_Do + ( + [&callCount, &includePaths](void*, const std::vector& args) + { + std::string& line = *static_cast(args[1]); + line = includePaths[callCount++]; + } + ) + .ReturnsResult(); //Mock getline to return false for end of file - std::shared_ptr endOfFileResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_getline) - .Returns(false) - .Times(1) - .AssignResult(endOfFileResult); + std::shared_ptr endOfFileResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_getline) + .Returns(false) + .Times(1) + .ReturnsResult(); ); //Initialize first @@ -448,21 +433,20 @@ int main(int argc, char** argv) ( //Test when record doesn't exist const std::string recordPath = absPathPrefix + "/tmp/Build/IncludeMaps/test.Includes"; - std::shared_ptr getRecordPathResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) - .WhenCalledWith(sourcePaths[0]) - .Returns(recordPath) - .Times(1) - .OverrideObject(includeManager.get()) - .AssignResult(getRecordPathResult); - - std::shared_ptr recordExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(recordPath, CO_ANY) - .Returns(false) - .Times(1) - .AssignResult(recordExistsResult); + std::shared_ptr getRecordPathResult = + CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) + .WhenCalledWith(sourcePaths[0]) + .Returns(recordPath) + .Times(1) + .OverrideObject(includeManager.get()) + .ReturnsResult(); + std::shared_ptr recordExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(recordPath, CO_ANY) + .Returns(false) + .Times(1) + .ReturnsResult(); ); std::vector outIncludes; @@ -493,14 +477,13 @@ int main(int argc, char** argv) ( //Test when file open fails const std::string recordPath = absPathPrefix + "/tmp/Build/IncludeMaps/test.Includes"; - std::shared_ptr getRecordPathResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) - .WhenCalledWith(sourcePaths[0]) - .Returns(recordPath) - .Times(1) - .OverrideObject(includeManager.get()) - .AssignResult(getRecordPathResult); - + std::shared_ptr getRecordPathResult = + CO_SETUP_OVERRIDE (OverrideInstance, GetRecordPath) + .WhenCalledWith(sourcePaths[0]) + .Returns(recordPath) + .Times(1) + .OverrideObject(includeManager.get()) + .ReturnsResult(); CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) .WhenCalledWith(recordPath, CO_ANY) @@ -508,26 +491,24 @@ int main(int argc, char** argv) .Times(1); const auto recordTime = ghc::filesystem::file_time_type::clock::now(); - std::shared_ptr lastWriteResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(recordPath, CO_ANY) - .Returns(recordTime) - .Times(1) - .AssignResult(lastWriteResult); - - std::shared_ptr ifstreamResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) - .WhenCalledWith(recordPath) - .Returns() - .Times(1) - .AssignResult(ifstreamResult); - - std::shared_ptr isOpenResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, is_open) - .Returns(false) - .Times(1) - .AssignResult(isOpenResult); + std::shared_ptr lastWriteResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(recordPath, CO_ANY) + .Returns(recordTime) + .Times(1) + .ReturnsResult(); + std::shared_ptr ifstreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) + .WhenCalledWith(recordPath) + .Returns() + .Times(1) + .ReturnsResult(); + std::shared_ptr isOpenResult = + CO_SETUP_OVERRIDE (OverrideInstance, is_open) + .Returns(false) + .Times(1) + .ReturnsResult(); ); std::vector outIncludes; @@ -559,31 +540,29 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( //Mock source file time - std::shared_ptr sourceTimeResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(sourcePaths[0], CO_ANY) - .Returns(sourceTime) - .Times(1) - .AssignResult(sourceTimeResult); - + std::shared_ptr sourceTimeResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(sourcePaths[0], CO_ANY) + .Returns(sourceTime) + .Times(1) + .ReturnsResult(); //Mock include file time (shouldn't be called since source is newer) - std::shared_ptr includeTimeResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(includePaths[0], CO_ANY) - .Returns(includeTime) - .Times(0) - .AssignResult(includeTimeResult); - + std::shared_ptr includeTimeResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(includePaths[0], CO_ANY) + .Returns(includeTime) + .Times(0) + .ReturnsResult(); //Mock include file exists (shouldn't be called since source is newer) - std::shared_ptr includeExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(includePaths[0], CO_ANY) - .Returns(true) - .Times(0) - .AssignResult(includeExistsResult); + std::shared_ptr includeExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(includePaths[0], CO_ANY) + .Returns(true) + .Times(0) + .ReturnsResult(); std::vector includes = { includePaths[0] }; ); @@ -610,31 +589,29 @@ int main(int argc, char** argv) const auto includeTime = recordTime + std::chrono::seconds(1); //Mock source file time - std::shared_ptr sourceTimeResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(sourcePaths[0], CO_ANY) - .Returns(sourceTime) - .Times(1) - .AssignResult(sourceTimeResult); - + std::shared_ptr sourceTimeResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(sourcePaths[0], CO_ANY) + .Returns(sourceTime) + .Times(1) + .ReturnsResult(); //Mock include file exists - std::shared_ptr includeExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(includePaths[0], CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(includeExistsResult); - + std::shared_ptr includeExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(includePaths[0], CO_ANY) + .Returns(true) + .Times(1) + .ReturnsResult(); //Mock include file time - std::shared_ptr includeTimeResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(includePaths[0], CO_ANY) - .Returns(includeTime) - .Times(1) - .AssignResult(includeTimeResult); + std::shared_ptr includeTimeResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(includePaths[0], CO_ANY) + .Returns(includeTime) + .Times(1) + .ReturnsResult(); std::vector includes = { includePaths[0] }; ); @@ -662,31 +639,31 @@ int main(int argc, char** argv) const auto includeTime = recordTime - std::chrono::seconds(2); //Mock source file time - std::shared_ptr sourceTimeResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(sourcePaths[0], CO_ANY) - .Returns(sourceTime) - .Times(1) - .AssignResult(sourceTimeResult); + std::shared_ptr sourceTimeResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(sourcePaths[0], CO_ANY) + .Returns(sourceTime) + .Times(1) + .ReturnsResult(); //Mock include file exists - std::shared_ptr includeExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(includePaths[0], CO_ANY) - .Returns(true) - .Times(1) - .AssignResult(includeExistsResult); + std::shared_ptr includeExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(includePaths[0], CO_ANY) + .Returns(true) + .Times(1) + .ReturnsResult(); //Mock include file time - std::shared_ptr includeTimeResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(includePaths[0], CO_ANY) - .Returns(includeTime) - .Times(1) - .AssignResult(includeTimeResult); + std::shared_ptr includeTimeResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(includePaths[0], CO_ANY) + .Returns(includeTime) + .Times(1) + .ReturnsResult(); std::vector includes = { includePaths[0] }; ); @@ -713,36 +690,36 @@ int main(int argc, char** argv) const auto sourceTime = recordTime - std::chrono::seconds(1); //Mock source file time - std::shared_ptr sourceTimeResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(sourcePaths[0], CO_ANY) - .Returns(sourceTime) - .Times(1) - .AssignResult(sourceTimeResult); + std::shared_ptr sourceTimeResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(sourcePaths[0], CO_ANY) + .Returns(sourceTime) + .Times(1) + .ReturnsResult(); //Mock first include file exists (false) - std::shared_ptr include1ExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(includePaths[0], CO_ANY) - .Returns(false) - .Times(1) - .AssignResult(include1ExistsResult); + std::shared_ptr include1ExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(includePaths[0], CO_ANY) + .Returns(false) + .Times(1) + .ReturnsResult(); //Mock second include file exists (true) - std::shared_ptr include2ExistsResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(includePaths[1], CO_ANY) - .AssignResult(include2ExistsResult); + std::shared_ptr include2ExistsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(includePaths[1], CO_ANY) + .ReturnsResult(); //Mock second include file time - std::shared_ptr include2TimeResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) - .WhenCalledWith(includePaths[1], CO_ANY) - .AssignResult(include2TimeResult); + std::shared_ptr include2TimeResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_last_write_time) + .WhenCalledWith(includePaths[1], CO_ANY) + .ReturnsResult(); std::vector includes = { includePaths[0], includePaths[1] }; ); @@ -788,67 +765,70 @@ int main(int argc, char** argv) //Mock hash for first source file - std::shared_ptr hash1Result = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, operator()) - .If - ( - [&sourcePaths, ProcessPath](void*, const std::vector& args) - { - if(args.empty()) - return false; - if( ProcessPath(*static_cast(args.at(0))) == - sourcePaths[0]) + std::shared_ptr hash1Result = + CO_SETUP_OVERRIDE (OverrideInstance, operator()) + .If + ( + [&sourcePaths, ProcessPath](void*, + const std::vector& args) { - return true; + if(args.empty()) + return false; + if( ProcessPath(*static_cast(args.at(0))) == + sourcePaths[0]) + { + return true; + } + return false; } - return false; - } - ) - .Returns(123) - .Times(1) - .AssignResult(hash1Result); + ) + .Returns(123) + .Times(1) + .ReturnsResult(); //Mock hash for second source file - std::shared_ptr hash2Result = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, operator()) - .If - ( - [&sourcePaths, ProcessPath](void*, const std::vector& args) - { - if(args.empty()) - return false; - if( ProcessPath(*static_cast(args.at(0))) == - sourcePaths[1]) + std::shared_ptr hash2Result = + CO_SETUP_OVERRIDE (OverrideInstance, operator()) + .If + ( + [&sourcePaths, ProcessPath](void*, + const std::vector& args) { - return true; + if(args.empty()) + return false; + if( ProcessPath(*static_cast(args.at(0))) == + sourcePaths[1]) + { + return true; + } + return false; } - return false; - } - ) - .Returns(456) - .Times(1) - .AssignResult(hash2Result); + ) + .Returns(456) + .Times(1) + .ReturnsResult(); //Mock hash for third source file - std::shared_ptr hash3Result = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, operator()) - .If - ( - [&sourcePaths, ProcessPath](void*, const std::vector& args) - { - if(args.empty()) - return false; - if( ProcessPath(*static_cast(args.at(0))) == - sourcePaths[2]) + std::shared_ptr hash3Result = + CO_SETUP_OVERRIDE (OverrideInstance, operator()) + .If + ( + [&sourcePaths, ProcessPath](void*, + const std::vector& args) { - return true; + if(args.empty()) + return false; + if( ProcessPath(*static_cast(args.at(0))) == + sourcePaths[2]) + { + return true; + } + return false; } - return false; - } - ) - .Returns(789) - .Times(1) - .AssignResult(hash3Result); + ) + .Returns(789) + .Times(1) + .ReturnsResult(); ); //Initialize first From 9662e63844b4acf35b2c241063ac50ee546e0bbf Mon Sep 17 00:00:00 2001 From: Neko Box Coder Date: Sat, 3 May 2025 20:55:33 +0100 Subject: [PATCH 2/5] Adding the ability to import other profile files --- CMakeLists.txt | 12 +- DefaultYAMLs/CommonFileTypes.yaml | 47 +++ DefaultYAMLs/DefaultUserConfig.yaml | 434 +--------------------------- DefaultYAMLs/g++.yaml | 237 +++++++++++++++ DefaultYAMLs/vs2022_v17+.yaml | 137 +++++++++ External/Embed2C | 2 +- Include/runcpp2/ParseUtil.hpp | 5 +- Src/Tests/ConfigParsingTest.cpp | 365 +++++++++++++++++++---- Src/runcpp2/ConfigParsing.cpp | 166 +++++++++-- Src/runcpp2/DependenciesHelper.cpp | 6 +- Src/runcpp2/ParseUtil.cpp | 25 +- 11 files changed, 923 insertions(+), 513 deletions(-) create mode 100644 DefaultYAMLs/CommonFileTypes.yaml create mode 100644 DefaultYAMLs/g++.yaml create mode 100644 DefaultYAMLs/vs2022_v17+.yaml diff --git a/CMakeLists.txt b/CMakeLists.txt index 83d5527..d5883a7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -111,8 +111,18 @@ if(RUNCPP2_UPDATE_DEFAULT_YAMLS OR EMBEDDED_FILE_SIZE LESS 1024) message(WARNING "Please build Embed2C first") return() else() - set(FILES_TO_EMBED "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/DefaultUserConfig.yaml" + set(FILES_TO_EMBED "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/DefaultUserConfig.yaml" "DefaultUserConfig" + + "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/CommonFileTypes.yaml" + "CommonFileTypes" + + "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/g++.yaml" + "G_PlusPlus" + + "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/vs2022_v17+.yaml" + "Vs2022_v17Plus" + "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/DefaultScriptInfo.yaml" "DefaultScriptInfo" ) diff --git a/DefaultYAMLs/CommonFileTypes.yaml b/DefaultYAMLs/CommonFileTypes.yaml new file mode 100644 index 0000000..5cdb1f0 --- /dev/null +++ b/DefaultYAMLs/CommonFileTypes.yaml @@ -0,0 +1,47 @@ +# DO NOT modify this file. Changes will be overwritten when there's a reset or update + +FilesTypes: + # The file properties for the files to be **linked** as object file for each platform + ObjectLinkFile: + Prefix: + DefaultPlatform: "" + Extension: + Windows: ".obj" + Unix: ".o" + # The file properties for the files to be **linked** as shared libraries for each platform + SharedLinkFile: + Prefix: + Windows: "" + Linux: "lib" + MacOS: "" + Extension: + Windows: ".lib" + Linux: ".so" + MacOS: ".dylib" + # The file properties for the files to be **copied** as shared libraries for each platform + SharedLibraryFile: + Prefix: + Windows: "" + Linux: "lib" + MacOS: "" + Extension: + Windows: ".dll" + Linux: ".so" + MacOS: ".dylib" + # The file properties for the files to be linked as static libraries for each platform + StaticLinkFile: + Prefix: + Unix: "lib" + Windows: "" + Extension: + Windows: ".lib" + Unix: ".a" + # (Optional) The file properties for debug symbols to be copied alongside the binary + # for each platform + DebugSymbolFile: + Prefix: + Windows: "" + Unix: "" + Extension: + Windows: ".pdb" + Unix: "" diff --git a/DefaultYAMLs/DefaultUserConfig.yaml b/DefaultYAMLs/DefaultUserConfig.yaml index a63d433..ff6c25f 100644 --- a/DefaultYAMLs/DefaultUserConfig.yaml +++ b/DefaultYAMLs/DefaultUserConfig.yaml @@ -1,102 +1,3 @@ -# List of anchors that will be aliased later -Templates: - vs2022_v17+_CompileFlags: &vs2022_v17+_CompileFlags - Flags: "/nologo /W4 /diagnostics:caret /utf-8 /Gm- /MDd /EHar /TP /std:c++17 /GR /RTC1 /Zc:inline /Zi" - - "g++_CompileRunParts": &g++_CompileRunParts - - Type: Once - CommandPart: "{Executable} -c {CompileFlags}" - - Type: Repeats - CommandPart: " -D{DefineNameOnly}=" - - Type: Repeats - CommandPart: " \"-D{DefineName}={DefineValue}\"" - - Type: Repeats - CommandPart: " -I\"{IncludeDirectoryPath}\"" - - Type: Once - CommandPart: " \"{InputFilePath}\" -o \"{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}\"" - - "g++_CompileExpectedOutputFiles": &g++_CompileExpectedOutputFiles - - "{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}" - - "vs2022_v17+_CompileRunParts": &vs2022_v17+_CompileRunParts - - Type: Once - CommandPart: "{Executable} /c {CompileFlags}" - - Type: Repeats - CommandPart: " /D{DefineNameOnly}=" - - Type: Repeats - CommandPart: " \"/D{DefineName}={DefineValue}\"" - - Type: Repeats - CommandPart: " /I\"{IncludeDirectoryPath}\"" - - Type: Once - CommandPart: " /Fo\"{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}\" \ - /Fd\"{OutputFileDirectory}{/}{DebugSymbolFile.Prefix}{InputFileName}{DebugSymbolFile.Extension}\" \ - \"{InputFilePath}\"" - - "vs2022_v17+_CompileExpectedOutputFiles": &vs2022_v17+_CompileExpectedOutputFiles - - "{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}" - - "{OutputFileDirectory}{/}{DebugSymbolFile.Prefix}{InputFileName}{DebugSymbolFile.Extension}" - - # The following fields set the prefixes and extensions for each type of the files - # If the name of an object files are libtest.so and libtest2.so, - # the prefixes and extensions are "lib" and ".so" - - # TODO: Add support for custom platform - # Each of the platform dependent settings can be listed under - # - DefaultPlatform - # - Windows - # - Linux - # - MacOS - # - Unix - FilesTypes: &CommonFilesTypes - # The file properties for the files to be **linked** as object file for each platform - ObjectLinkFile: - Prefix: - DefaultPlatform: "" - Extension: - Windows: ".obj" - Unix: ".o" - - # The file properties for the files to be **linked** as shared libraries for each platform - SharedLinkFile: - Prefix: - Windows: "" - Linux: "lib" - MacOS: "" - Extension: - Windows: ".lib" - Linux: ".so" - MacOS: ".dylib" - - # The file properties for the files to be **copied** as shared libraries for each platform - SharedLibraryFile: - Prefix: - Windows: "" - Linux: "lib" - MacOS: "" - Extension: - Windows: ".dll" - Linux: ".so" - MacOS: ".dylib" - - # The file properties for the files to be linked as static libraries for each platform - StaticLinkFile: - Prefix: - Unix: "lib" - Windows: "" - Extension: - Windows: ".lib" - Unix: ".a" - - # (Optional) The file properties for debug symbols to be copied alongside the binary - # for each platform - DebugSymbolFile: - Prefix: - Windows: "" - Unix: "" - Extension: - Windows: ".pdb" - Unix: "" - # WARNING: All command substitutions in this file are passed directly to the shell. # Exercise caution when using variables or user-provided input in your build commands # to prevent potential security vulnerabilities. @@ -107,336 +8,7 @@ PreferredProfile: Windows: "msvc" # List of compiler/linker profiles that instruct how to compile/link +# See "./Default/g++.yaml" for the documentation of each field in a profile entry Profiles: - # Name (case sensitive) of the profile that can be queried from a script -- Name: "g++" - - # (Optional) Name aliases (case sensitive) of the current profile - NameAliases: ["mingw"] - - # The file extensions associated with the profile - FileExtensions: [.cpp, .cc, .cxx] - - # The languages supported by the profile - Languages: ["c++"] - - # (Optional) The commands to run in **shell** before calling the compiler/linker for each platform. - # This is run inside the root build directory. - # Setup: - # DefaultPlatform: [] - - # (Optional) The commands to run in **shell** after calling the compiler/linker for each platform. - # This is run inside the root build directory. - # Cleanup: - # DefaultPlatform: [] - - # The file properties for the object files for each platform. - FilesTypes: *CommonFilesTypes - - # Specify the compiler settings - Compiler: - # (Optional) The command to be prepend for each compile command in **shell** for each platform - # PreRun: - # DefaultPlatform: "" - - # Shell command to use for checking if the executable exists or not - CheckExistence: - DefaultPlatform: "g++ -v" - - # Here are a list of substitution strings for RunParts, Setup and Cleanup. - # To escape '{' and '}' to avoid substitutioon, simply repeat the '{' or '}' character again. - # So "${MyBashVariable}" will become "${{MyBashVariable}}" - - # {Executable}: Compiler executable - # {CompileFlags}: Compile flags from config and override - # {InputFileName}: Name of the input file (without directory path and extension) - # {InputFileExtension}: Extension of the input file - # {InputFileDirectory}: Directory of the input file - # {InputFilePath}: Full path to the input file - # {OutputFileDirectory}: Directory of all the output files - # {/}: Filesystem separator for the host platform - - # {SharedLibraryFile.Prefix} - # {SharedLinkFile.Prefix} - # {StaticLinkFile.Prefix} - # {ObjectLinkFile.Prefix} - # {DebugSymbolFile.Prefix} - - # {SharedLibraryFile.Extension} - # {SharedLinkFile.Extension} - # {StaticLinkFile.Extension} - # {ObjectLinkFile.Extension} - # {DebugSymbolFile.Extension} - - # Below are iterable substitution strings, must be inside "Repeats" run type: - # {IncludeDirectoryPath}: Path to all the include directories - # {DefineNameOnly}: All the defines without a value specified (equivalent to #define X) - # {DefineName}: Name of all the defines that has a value specified - # {DefineValue}: Value of all the defines that has a value specified (use together with {DefineName}) - CompileTypes: - Executable: - DefaultPlatform: - # Default flags to be substituted as {CompileFlags} - Flags: "-std=c++17 -Wall -g" - - # The executable to be substituted as {Executable} - Executable: "g++" - - # The components for the command to be run - RunParts: *g++_CompileRunParts - - # What files to be expected as output for the command - ExpectedOutputFiles: *g++_CompileExpectedOutputFiles - - # (Optional) The commands to run in **shell** BEFORE compiling - # This is run inside the .runcpp2 directory where the build happens. - # Setup: [] - - # (Optional) The commands to run in **shell** AFTER compiling - # This is run inside the .runcpp2 directory where the build happens. - # Cleanup: [] - ExecutableShared: - DefaultPlatform: - Flags: "-std=c++17 -Wall -g -fpic" - Executable: "g++" - RunParts: *g++_CompileRunParts - ExpectedOutputFiles: *g++_CompileExpectedOutputFiles - # Setup: [] - # Cleanup: [] - Static: - DefaultPlatform: - Flags: "-std=c++17 -Wall -g" - Executable: "g++" - RunParts: *g++_CompileRunParts - ExpectedOutputFiles: *g++_CompileExpectedOutputFiles - # Setup: [] - # Cleanup: [] - Shared: - DefaultPlatform: - Flags: "-std=c++17 -Wall -g -fpic" - Executable: "g++" - RunParts: *g++_CompileRunParts - ExpectedOutputFiles: *g++_CompileExpectedOutputFiles - # Setup: [] - # Cleanup: [] - - # Specify the linker settings - Linker: - CheckExistence: - DefaultPlatform: "g++ -v" - - # Here are a list of substitution strings for RunParts, Setup and Cleanup - # {Executable}: Linker executable - # {LinkFlags}: Link flags from config and override - # {OutputFileName}: Name of all the output files (without directory path and extension) - # {OutputFileDirectory}: Directory of all the output files - # {/}: Filesystem separator for the host platform - - # {SharedLibraryFile.Prefix} - # {SharedLinkFile.Prefix} - # {StaticLinkFile.Prefix} - # {ObjectLinkFile.Prefix} - # {DebugSymbolFile.Prefix} - - # {SharedLibraryFile.Extension} - # {SharedLinkFile.Extension} - # {StaticLinkFile.Extension} - # {ObjectLinkFile.Extension} - # {DebugSymbolFile.Extension} - - # Below are iterable substitution strings, must be inside "Repeats" run type: - # {LinkFileName}: Name of the file to be linked, regardless of the build type - # {LinkFileExtension}: File Extension of the file to be linked, regardless of the build type - # {LinkFileDirectory}: Directory of the file to be linked, regardless of the build type - # {LinkFilePath}: Full path to the file to be linked, regardless of the build type - - # {LinkObjectFileName}: Name of the object file to be linked - # {LinkObjectFileExtension}: File Extension of the object file to be linked - # {LinkObjectFileDirectory}: Directory of the object file to be linked - # {LinkObjectFilePath}: Full path to the object file to be linked - - # {LinkSharedFileName}: Name of the shared file to be linked - # {LinkSharedFileExtension}: File Extension of the shared file to be linked - # {LinkSharedFileDirectory}: Directory of the shared file to be linked - # {LinkSharedFilePath}: Full path to the shared file to be linked - - # {LinkStaticFileName}: Name of the static file to be linked - # {LinkStaticFileExtension}: File Extension of the static file to be linked - # {LinkStaticFileDirectory}: Directory of the static file to be linked - # {LinkStaticFilePath}: Full path to the static file to be linked - LinkTypes: - Executable: - Unix: - Flags: "-Wl,-rpath,\\$ORIGIN" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}"] - # Setup: [] - # Cleanup: [] - Windows: - Flags: "-Wl,-rpath,\\$ORIGIN" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}.exe\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] - # Setup: [] - # Cleanup: [] - ExecutableShared: - DefaultPlatform: - Flags: "-shared -Wl,-rpath,\\$ORIGIN" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] - # Setup: [] - # Cleanup: [] - Static: - DefaultPlatform: - Flags: "" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] - # Setup: [] - # Cleanup: [] - Shared: - DefaultPlatform: - Flags: "-shared -Wl,-rpath,\\$ORIGIN" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] - # Setup: [] - # Cleanup: [] - -# https://learn.microsoft.com/en-us/cpp/overview/compiler-versions?view=msvc-170 -- Name: "vs2022_v17+" - NameAliases: ["msvc1930+", "msvc"] - Languages: ["c++"] - FileExtensions: [.cpp, .cc, .cxx] - FilesTypes: *CommonFilesTypes - Setup: - Windows: - - >- - for /f "usebackq tokens=*" %i in (`CALL "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" - -version "[17.0,18.0)" -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do ( - echo "%i\VC\Auxiliary\Build\vcvarsall.bat" x64 > .\prerun.bat - ) - Cleanup: - Windows: [ "del .\\prerun.bat" ] - Compiler: - PreRun: - Windows: ".\\prerun.bat" - CheckExistence: - Windows: "where.exe CL.exe" - CompileTypes: - Executable: - Windows: - <<: *vs2022_v17+_CompileFlags - Executable: "CL.exe" - RunParts: *vs2022_v17+_CompileRunParts - ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles - ExecutableShared: - Windows: - <<: *vs2022_v17+_CompileFlags - Executable: "CL.exe" - RunParts: *vs2022_v17+_CompileRunParts - ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles - Static: - Windows: - <<: *vs2022_v17+_CompileFlags - Executable: "CL.exe" - RunParts: *vs2022_v17+_CompileRunParts - ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles - Shared: - Windows: - <<: *vs2022_v17+_CompileFlags - Executable: "CL.exe" - RunParts: *vs2022_v17+_CompileRunParts - ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles - Linker: - PreRun: - Windows: ".\\prerun.bat" - CheckExistence: - Windows: "where.exe link.exe" - LinkTypes: - Executable: - Windows: - Flags: >- - /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib - oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE - /DEBUG /MANIFESTUAC:"level='asInvoker'" - Executable: "link.exe" - RunParts: - - Type: Once - CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{OutputFileName}.exe" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] - ExecutableShared: - Windows: - Flags: >- - /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib - oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE - /DEBUG /DLL /MANIFESTUAC:"level='asInvoker'" - Executable: "link.exe" - RunParts: - - Type: Once - CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" - /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" - /DEF:".\temp.def" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] - Setup: [ "echo EXPORTS > .\\temp.def", "echo. main @1 >> .\\temp.def" ] - Cleanup: [ "del .\\temp.def" ] - Static: - Windows: - Flags: "/NOLOGO" - Executable: "lib.exe" - RunParts: - - Type: Once - CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}" - /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] - Shared: - Windows: - Flags: >- - /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib - oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE - /DEBUG /DLL /MANIFESTUAC:"level='asInvoker'" - Executable: "link.exe" - RunParts: - - Type: Once - CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" - /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] - +- Import: "./Default/g++.yaml" +- Import: "./Default/vs2022_v17+.yaml" diff --git a/DefaultYAMLs/g++.yaml b/DefaultYAMLs/g++.yaml new file mode 100644 index 0000000..4db8ed2 --- /dev/null +++ b/DefaultYAMLs/g++.yaml @@ -0,0 +1,237 @@ +# DO NOT modify this file. Changes will be overwritten when there's a reset or update + +# List of anchors that will be aliased later. `Template` is **NOT** part of a profile +Templates: + "g++_CompileRunParts": &g++_CompileRunParts + - Type: Once + CommandPart: "{Executable} -c {CompileFlags}" + - Type: Repeats + CommandPart: " -D{DefineNameOnly}=" + - Type: Repeats + CommandPart: " \"-D{DefineName}={DefineValue}\"" + - Type: Repeats + CommandPart: " -I\"{IncludeDirectoryPath}\"" + - Type: Once + CommandPart: " \"{InputFilePath}\" -o \"{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}\"" + + "g++_CompileExpectedOutputFiles": &g++_CompileExpectedOutputFiles + - "{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}" + +# Name (case sensitive) of the profile that can be queried from a script +Name: "g++" + +# (Optional) Name aliases (case sensitive) of the current profile +NameAliases: ["mingw"] + +# The file extensions associated with the profile +FileExtensions: [.cpp, .cc, .cxx] + +# The languages supported by the profile +Languages: ["c++"] + +# (Optional) The commands to run in **shell** before calling the compiler/linker for each platform. +# This is run inside the root build directory. +# Setup: +# DefaultPlatform: [] + +# (Optional) The commands to run in **shell** after calling the compiler/linker for each platform. +# This is run inside the root build directory. +# Cleanup: +# DefaultPlatform: [] + +# The file properties for the object files for each platform. +# See "./CommonFileTypes.yaml" for FilesTypes +# FilesTypes: ... +Import: "./CommonFileTypes.yaml" + +# Specify the compiler settings +Compiler: + # (Optional) The command to be prepend for each compile command in **shell** for each platform + # PreRun: + # DefaultPlatform: "" + + # Shell command to use for checking if the executable exists or not + CheckExistence: + DefaultPlatform: "g++ -v" + + # Here are a list of substitution strings for RunParts, Setup and Cleanup. + # To escape '{' and '}' to avoid substitutioon, simply repeat the '{' or '}' character again. + # So "${MyBashVariable}" will become "${{MyBashVariable}}" + + # {Executable}: Compiler executable + # {CompileFlags}: Compile flags from config and override + # {InputFileName}: Name of the input file (without directory path and extension) + # {InputFileExtension}: Extension of the input file + # {InputFileDirectory}: Directory of the input file + # {InputFilePath}: Full path to the input file + # {OutputFileDirectory}: Directory of all the output files + # {/}: Filesystem separator for the host platform + + # {SharedLibraryFile.Prefix} + # {SharedLinkFile.Prefix} + # {StaticLinkFile.Prefix} + # {ObjectLinkFile.Prefix} + # {DebugSymbolFile.Prefix} + + # {SharedLibraryFile.Extension} + # {SharedLinkFile.Extension} + # {StaticLinkFile.Extension} + # {ObjectLinkFile.Extension} + # {DebugSymbolFile.Extension} + + # Below are iterable substitution strings, must be inside "Repeats" run type: + # {IncludeDirectoryPath}: Path to all the include directories + # {DefineNameOnly}: All the defines without a value specified (equivalent to #define X) + # {DefineName}: Name of all the defines that has a value specified + # {DefineValue}: Value of all the defines that has a value specified (use together with {DefineName}) + CompileTypes: + Executable: + DefaultPlatform: + # Default flags to be substituted as {CompileFlags} + Flags: "-std=c++17 -Wall -g" + + # The executable to be substituted as {Executable} + Executable: "g++" + + # The components for the command to be run + RunParts: *g++_CompileRunParts + + # What files to be expected as output for the command + ExpectedOutputFiles: *g++_CompileExpectedOutputFiles + + # (Optional) The commands to run in **shell** BEFORE compiling + # This is run inside the .runcpp2 directory where the build happens. + # Setup: [] + + # (Optional) The commands to run in **shell** AFTER compiling + # This is run inside the .runcpp2 directory where the build happens. + # Cleanup: [] + ExecutableShared: + DefaultPlatform: + Flags: "-std=c++17 -Wall -g -fpic" + Executable: "g++" + RunParts: *g++_CompileRunParts + ExpectedOutputFiles: *g++_CompileExpectedOutputFiles + # Setup: [] + # Cleanup: [] + Static: + DefaultPlatform: + Flags: "-std=c++17 -Wall -g" + Executable: "g++" + RunParts: *g++_CompileRunParts + ExpectedOutputFiles: *g++_CompileExpectedOutputFiles + # Setup: [] + # Cleanup: [] + Shared: + DefaultPlatform: + Flags: "-std=c++17 -Wall -g -fpic" + Executable: "g++" + RunParts: *g++_CompileRunParts + ExpectedOutputFiles: *g++_CompileExpectedOutputFiles + # Setup: [] + # Cleanup: [] + +# Specify the linker settings +Linker: + CheckExistence: + DefaultPlatform: "g++ -v" + + # Here are a list of substitution strings for RunParts, Setup and Cleanup + # {Executable}: Linker executable + # {LinkFlags}: Link flags from config and override + # {OutputFileName}: Name of all the output files (without directory path and extension) + # {OutputFileDirectory}: Directory of all the output files + # {/}: Filesystem separator for the host platform + + # {SharedLibraryFile.Prefix} + # {SharedLinkFile.Prefix} + # {StaticLinkFile.Prefix} + # {ObjectLinkFile.Prefix} + # {DebugSymbolFile.Prefix} + + # {SharedLibraryFile.Extension} + # {SharedLinkFile.Extension} + # {StaticLinkFile.Extension} + # {ObjectLinkFile.Extension} + # {DebugSymbolFile.Extension} + + # Below are iterable substitution strings, must be inside "Repeats" run type: + # {LinkFileName}: Name of the file to be linked, regardless of the build type + # {LinkFileExtension}: File Extension of the file to be linked, regardless of the build type + # {LinkFileDirectory}: Directory of the file to be linked, regardless of the build type + # {LinkFilePath}: Full path to the file to be linked, regardless of the build type + + # {LinkObjectFileName}: Name of the object file to be linked + # {LinkObjectFileExtension}: File Extension of the object file to be linked + # {LinkObjectFileDirectory}: Directory of the object file to be linked + # {LinkObjectFilePath}: Full path to the object file to be linked + + # {LinkSharedFileName}: Name of the shared file to be linked + # {LinkSharedFileExtension}: File Extension of the shared file to be linked + # {LinkSharedFileDirectory}: Directory of the shared file to be linked + # {LinkSharedFilePath}: Full path to the shared file to be linked + + # {LinkStaticFileName}: Name of the static file to be linked + # {LinkStaticFileExtension}: File Extension of the static file to be linked + # {LinkStaticFileDirectory}: Directory of the static file to be linked + # {LinkStaticFilePath}: Full path to the static file to be linked + LinkTypes: + Executable: + Unix: + Flags: "-Wl,-rpath,\\$ORIGIN" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}"] + # Setup: [] + # Cleanup: [] + Windows: + Flags: "-Wl,-rpath,\\$ORIGIN" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}.exe\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] + # Setup: [] + # Cleanup: [] + ExecutableShared: + DefaultPlatform: + Flags: "-shared -Wl,-rpath,\\$ORIGIN" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + # Setup: [] + # Cleanup: [] + Static: + DefaultPlatform: + Flags: "" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] + # Setup: [] + # Cleanup: [] + Shared: + DefaultPlatform: + Flags: "-shared -Wl,-rpath,\\$ORIGIN" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + # Setup: [] + # Cleanup: [] diff --git a/DefaultYAMLs/vs2022_v17+.yaml b/DefaultYAMLs/vs2022_v17+.yaml new file mode 100644 index 0000000..b92d5c6 --- /dev/null +++ b/DefaultYAMLs/vs2022_v17+.yaml @@ -0,0 +1,137 @@ +# DO NOT modify this file. Changes will be overwritten when there's a reset or update + +# List of anchors that will be aliased later. `Template` is **NOT** part of a profile +Templates: + vs2022_v17+_CompileFlags: &vs2022_v17+_CompileFlags + Flags: "/nologo /W4 /diagnostics:caret /utf-8 /Gm- /MDd /EHar /TP /std:c++17 /GR /RTC1 /Zc:inline /Zi" + "vs2022_v17+_CompileRunParts": &vs2022_v17+_CompileRunParts + - Type: Once + CommandPart: "{Executable} /c {CompileFlags}" + - Type: Repeats + CommandPart: " /D{DefineNameOnly}=" + - Type: Repeats + CommandPart: " \"/D{DefineName}={DefineValue}\"" + - Type: Repeats + CommandPart: " /I\"{IncludeDirectoryPath}\"" + - Type: Once + CommandPart: " /Fo\"{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}\" \ + /Fd\"{OutputFileDirectory}{/}{DebugSymbolFile.Prefix}{InputFileName}{DebugSymbolFile.Extension}\" \ + \"{InputFilePath}\"" + "vs2022_v17+_CompileExpectedOutputFiles": &vs2022_v17+_CompileExpectedOutputFiles + - "{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}" + - "{OutputFileDirectory}{/}{DebugSymbolFile.Prefix}{InputFileName}{DebugSymbolFile.Extension}" + +# https://learn.microsoft.com/en-us/cpp/overview/compiler-versions?view=msvc-170 +Name: "vs2022_v17+" +NameAliases: ["msvc1930+", "msvc"] +FileExtensions: [.cpp, .cc, .cxx] +Languages: ["c++"] +Import: "./CommonFileTypes.yaml" +Setup: + Windows: + - >- + for /f "usebackq tokens=*" %i in (`CALL "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" + -version "[17.0,18.0)" -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do ( + echo "%i\VC\Auxiliary\Build\vcvarsall.bat" x64 > .\prerun.bat + ) +Cleanup: + Windows: [ "del .\\prerun.bat" ] +Compiler: + PreRun: + Windows: ".\\prerun.bat" + CheckExistence: + Windows: "where.exe CL.exe" + CompileTypes: + Executable: + Windows: + <<: *vs2022_v17+_CompileFlags + Executable: "CL.exe" + RunParts: *vs2022_v17+_CompileRunParts + ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles + ExecutableShared: + Windows: + <<: *vs2022_v17+_CompileFlags + Executable: "CL.exe" + RunParts: *vs2022_v17+_CompileRunParts + ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles + Static: + Windows: + <<: *vs2022_v17+_CompileFlags + Executable: "CL.exe" + RunParts: *vs2022_v17+_CompileRunParts + ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles + Shared: + Windows: + <<: *vs2022_v17+_CompileFlags + Executable: "CL.exe" + RunParts: *vs2022_v17+_CompileRunParts + ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles +Linker: + PreRun: + Windows: ".\\prerun.bat" + CheckExistence: + Windows: "where.exe link.exe" + LinkTypes: + Executable: + Windows: + Flags: >- + /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib + oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE + /DEBUG /MANIFESTUAC:"level='asInvoker'" + Executable: "link.exe" + RunParts: + - Type: Once + CommandPart: >- + {Executable} {LinkFlags} + /OUT:"{OutputFileDirectory}{/}{OutputFileName}.exe" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] + ExecutableShared: + Windows: + Flags: >- + /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib + oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE + /DEBUG /DLL /MANIFESTUAC:"level='asInvoker'" + Executable: "link.exe" + RunParts: + - Type: Once + CommandPart: >- + {Executable} {LinkFlags} + /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" + /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" + /DEF:".\temp.def" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + Setup: [ "echo EXPORTS > .\\temp.def", "echo. main @1 >> .\\temp.def" ] + Cleanup: [ "del .\\temp.def" ] + Static: + Windows: + Flags: "/NOLOGO" + Executable: "lib.exe" + RunParts: + - Type: Once + CommandPart: >- + {Executable} {LinkFlags} + /OUT:"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}" + /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] + Shared: + Windows: + Flags: >- + /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib + oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE + /DEBUG /DLL /MANIFESTUAC:"level='asInvoker'" + Executable: "link.exe" + RunParts: + - Type: Once + CommandPart: >- + {Executable} {LinkFlags} + /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" + /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] diff --git a/External/Embed2C b/External/Embed2C index 045fc67..c94bf6c 160000 --- a/External/Embed2C +++ b/External/Embed2C @@ -1 +1 @@ -Subproject commit 045fc67ac07ad106611ab3cb37cb7c87a8905ada +Subproject commit c94bf6cc7f677a05a64df77ef50ba58953c0156e diff --git a/Include/runcpp2/ParseUtil.hpp b/Include/runcpp2/ParseUtil.hpp index 8868111..4291703 100644 --- a/Include/runcpp2/ParseUtil.hpp +++ b/Include/runcpp2/ParseUtil.hpp @@ -36,7 +36,10 @@ namespace runcpp2 bool GetParsableInfo(const std::string& contentToParse, std::string& outParsableInfo); bool ResolveYAML_Stream(ryml::Tree& rootTree, - ryml::ConstNodeRef& outRootNode); + ryml::NodeRef& outRootNode); + + //NOTE: Tree of both nodeToMergeTo and nodeToMergeFrom needs to be alive to be valid + bool MergeYAML_NodeChildren(ryml::NodeRef nodeToMergeFrom, ryml::NodeRef nodeToMergeTo); bool ExistAndHasChild( ryml::ConstNodeRef node, const std::string& childName, diff --git a/Src/Tests/ConfigParsingTest.cpp b/Src/Tests/ConfigParsingTest.cpp index 02b790d..10bdffe 100644 --- a/Src/Tests/ConfigParsingTest.cpp +++ b/Src/Tests/ConfigParsingTest.cpp @@ -19,6 +19,13 @@ CO_DECLARE_INSTANCE(OverrideInstance); //Mock DefaultUserConfig for testing extern "C" const uint8_t DefaultUserConfig[] = {0}; extern "C" const size_t DefaultUserConfig_size = 0; +extern "C" const uint8_t CommonFileTypes[] = {0}; +extern "C" const size_t CommonFileTypes_size = 0; +extern "C" const uint8_t G_PlusPlus[] = {0}; +extern "C" const size_t G_PlusPlus_size = 0; +extern "C" const uint8_t Vs2022_v17Plus[] = {0}; +extern "C" const size_t Vs2022_v17Plus_size = 0; + int main(int argc, char** argv) { @@ -29,53 +36,80 @@ int main(int argc, char** argv) using namespace CppOverride; std::string configPath; - std::shared_ptr existsResult = CreateOverrideResult(); - std::shared_ptr isDirResult = CreateOverrideResult(); - std::shared_ptr ifstreamResult = CreateOverrideResult(); - std::shared_ptr ifstreamSucceedResult = CreateOverrideResult(); - std::shared_ptr writeDefaultConfigResult = CreateOverrideResult(); - std::shared_ptr rdbufResult = CreateOverrideResult(); + std::shared_ptr existsResult; + std::shared_ptr isDirResult; + std::shared_ptr ifstreamResult; + std::shared_ptr ifstreamSucceedResult; + std::shared_ptr writeDefaultConfigResult; + std::shared_ptr rdbufResult; + void* userConfigIfstreamInstance = nullptr; ssTEST_COMMON_SETUP { CO_CLEAR_ALL_OVERRIDE_SETUP(OverrideInstance); ssLOG_SET_CURRENT_THREAD_TARGET_LEVEL(ssLOG_LEVEL_WARNING); - configPath = "TestConfig.yaml"; - CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) - .WhenCalledWith(configPath, CO_ANY) - .Returns(true) - .AssignResult(existsResult); - - CO_SETUP_OVERRIDE (OverrideInstance, Mock_is_directory) - .WhenCalledWith(configPath, CO_ANY) - .Returns(false) - .AssignResult(isDirResult); - - CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) - .Returns() - .AssignResult(ifstreamResult); - - CO_SETUP_OVERRIDE (OverrideInstance, operator!) - .Returns(false) - .AssignResult(ifstreamSucceedResult); - - CO_SETUP_OVERRIDE (OverrideInstance, WriteDefaultConfig) - .Returns(false) - .AssignResult(writeDefaultConfigResult); + configPath = "some/config/dir/UserConfig.yaml"; + existsResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith(configPath, CO_ANY) + .Returns(true) + .ReturnsResult(); + isDirResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_is_directory) + .WhenCalledWith(configPath, CO_ANY) + .Returns(false) + .ReturnsResult(); + ifstreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) + .WhenCalledWith(configPath) + .WhenCalledExpectedly_Do + ( + [&userConfigIfstreamInstance] + (void* instance, const std::vector&) + { + userConfigIfstreamInstance = instance; + } + ) + .ReturnsResult(); + ifstreamSucceedResult = + CO_SETUP_OVERRIDE (OverrideInstance, operator!) + .If + ( + [&userConfigIfstreamInstance] + (void* instance, const std::vector&) -> bool + { + return instance == userConfigIfstreamInstance; + } + ) + .Returns(false) + .ReturnsResult(); + writeDefaultConfigResult = + CO_SETUP_OVERRIDE (OverrideInstance, WriteDefaultConfig) + .Returns(false) + .ReturnsResult(); }; auto commonOverrideStatusCheck = [&]() { - ssTEST_OUTPUT_ASSERT(existsResult->LastStatusSucceed()); - ssTEST_OUTPUT_ASSERT(isDirResult->LastStatusSucceed()); - ssTEST_OUTPUT_ASSERT(ifstreamResult->LastStatusSucceed()); - ssTEST_OUTPUT_ASSERT(ifstreamSucceedResult->LastStatusSucceed()); - ssTEST_OUTPUT_ASSERT(rdbufResult->LastStatusSucceed()); + ssTEST_OUTPUT_ASSERT("", existsResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", isDirResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", ifstreamResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", ifstreamSucceedResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", rdbufResult->GetSucceedCount(), 1); ssTEST_OUTPUT_ASSERT( "WriteDefaultConfig() should not be called", writeDefaultConfigResult->GetStatusCount(), 0); }; + auto commonDefaultOverrideSetup = [&]() + { + CO_SETUP_OVERRIDE(OverrideInstance, Mock_exists).Returns(false); + CO_SETUP_OVERRIDE(OverrideInstance, Mock_is_directory).Returns(false); + CO_SETUP_OVERRIDE(OverrideInstance, operator!).Returns(false); + CO_SETUP_OVERRIDE(OverrideInstance, WriteDefaultConfig).Returns(false); + CO_SETUP_OVERRIDE(OverrideInstance, rdbuf).Returns(""); + }; + ssTEST_COMMON_CLEANUP { ssLOG_SET_CURRENT_THREAD_TARGET_LEVEL(ssLOG_LEVEL_WARNING); @@ -86,6 +120,7 @@ int main(int argc, char** argv) ifstreamSucceedResult = CreateOverrideResult(); writeDefaultConfigResult = CreateOverrideResult(); rdbufResult = CreateOverrideResult(); + userConfigIfstreamInstance = nullptr; }; ssTEST("ReadUserConfig Should Parse PreferredProfile As String Correctly") @@ -132,10 +167,11 @@ int main(int argc, char** argv) Name: "g++3" )"; - CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) - .Returns(yamlStr) - .Times(1) - .AssignResult(rdbufResult); + rdbufResult = CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) + .Returns(yamlStr) + .Times(1) + .ReturnsResult(); + commonDefaultOverrideSetup(); std::vector profiles; std::string preferredProfile; @@ -198,18 +234,18 @@ int main(int argc, char** argv) Name: "g++3" )"; - CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) - .Returns(yamlStr) - .Times(2) - .AssignResult(rdbufResult); - - std::shared_ptr getPlatformNamesResult = CreateOverrideResult(); - CO_SETUP_OVERRIDE (OverrideInstance, GetPlatformNames) - .Returns>({"MacOS", - "Unix", - "DefaultPlatform"}) - .Times(1) - .AssignResult(getPlatformNamesResult); + rdbufResult = CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) + .Returns(yamlStr) + .Times(1) + .ReturnsResult(); + std::shared_ptr getPlatformNamesResult = + CO_SETUP_OVERRIDE (OverrideInstance, GetPlatformNames) + .Returns>({"MacOS", + "Unix", + "DefaultPlatform"}) + .Times(1) + .ReturnsResult(); + commonDefaultOverrideSetup(); std::vector profiles; std::string preferredProfile; @@ -228,14 +264,22 @@ int main(int argc, char** argv) ssTEST_OUTPUT_SETUP ( + ssTEST_CALL_COMMON_CLEANUP(); + ssTEST_CALL_COMMON_SETUP(); + profiles.clear(); + preferredProfile.clear(); + + CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) + .Returns(yamlStr) + .Times(1) + .AssignsResult(rdbufResult); CO_SETUP_OVERRIDE (OverrideInstance, GetPlatformNames) .Returns>({"Linux", "Unix", "DefaultPlatform"}) .Times(1) - .AssignResult(getPlatformNamesResult); - profiles.clear(); - preferredProfile.clear(); + .AssignsResult(getPlatformNamesResult); + commonDefaultOverrideSetup(); ); ssTEST_OUTPUT_EXECUTION @@ -250,6 +294,223 @@ int main(int argc, char** argv) preferredProfile == "g++"); }; + ssTEST("ReadUserConfig Should Import Profile From External YAML File") + { + ssTEST_OUTPUT_SETUP + ( + const char* mainConfigYamlStr = R"( + PreferredProfile: "imported-profile" + Profiles: + - Import: "Default/g++.yaml" + - Name: "second-profile" + FileExtensions: [.cpp, .cc, .cxx] + Languages: ["c++"] + FilesTypes: + ObjectLinkFile: &PrefixExtensionTemplate + Prefix: + DefaultPlatform: "prefix" + Extension: + DefaultPlatform: ".extension" + SharedLinkFile: *PrefixExtensionTemplate + SharedLibraryFile: *PrefixExtensionTemplate + StaticLinkFile: *PrefixExtensionTemplate + DebugSymbolFile: *PrefixExtensionTemplate + Compiler: + CheckExistence: + DefaultPlatform: "g++ -v" + CompileTypes: &TypeInfoEntries + Executable: &DefaultTypeInfo + DefaultPlatform: + Flags: "Flags" + Executable: "g++" + RunParts: [] + ExpectedOutputFiles: [] + ExecutableShared: *DefaultTypeInfo + Static: *DefaultTypeInfo + Shared: *DefaultTypeInfo + Linker: + CheckExistence: + DefaultPlatform: "g++ -v" + LinkTypes: *TypeInfoEntries + )"; + + const char* importedProfileYamlStr = R"( + Name: "imported-profile" + NameAliases: ["gcc"] + FileExtensions: [.cpp, .cc] + Languages: ["c++"] + Import: "filetypes.yaml" + Compiler: + CheckExistence: + DefaultPlatform: "imported-gcc -v" + CompileTypes: &TypeInfoEntries + Executable: &DefaultTypeInfo + DefaultPlatform: + Flags: "Imported-Flags" + Executable: "imported-gcc" + RunParts: [] + ExpectedOutputFiles: [] + ExecutableShared: *DefaultTypeInfo + Static: *DefaultTypeInfo + Shared: *DefaultTypeInfo + Linker: + CheckExistence: + DefaultPlatform: "imported-gcc -v" + LinkTypes: *TypeInfoEntries + )"; + + const char* importedFiletypesYamlStr = R"( + FilesTypes: + ObjectLinkFile: &PrefixExtensionTemplate + Prefix: + DefaultPlatform: "file-prefix" + Extension: + DefaultPlatform: ".file-ext" + SharedLinkFile: *PrefixExtensionTemplate + SharedLibraryFile: *PrefixExtensionTemplate + StaticLinkFile: *PrefixExtensionTemplate + DebugSymbolFile: *PrefixExtensionTemplate + )"; + + //Mock for main config file + rdbufResult = CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) + .Returns(mainConfigYamlStr) + .Times(1) + .If + ( + [&userConfigIfstreamInstance] + (void* instance, const std::vector&) -> bool + { + return instance == userConfigIfstreamInstance; + } + ) + .ReturnsResult(); + + //Setup filesystem exist for the import yaml files + std::string firstExpectedImportPath = "some/config/dir/Default/g++.yaml"; + std::string secondExpectedImportPath = "some/config/dir/Default/filetypes.yaml"; + + std::shared_ptr firstImportFileExistResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith( firstExpectedImportPath, + CO_ANY) + .Returns(true) + .ReturnsResult(); + std::shared_ptr secondImportFileExistResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith( secondExpectedImportPath, + CO_ANY) + .Returns(true) + .ReturnsResult(); + + //Record if there's an ifstream created with import paths + void* firstImportIfstreamInstance = nullptr; + void* secondImportIfstreamInstance = nullptr; + std::shared_ptr firstImportedFileStreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) + .WhenCalledWith + (firstExpectedImportPath) + .Times(1) + .WhenCalledExpectedly_Do + ( + [&firstImportIfstreamInstance] + (void* instance, const std::vector&) + { + firstImportIfstreamInstance = instance; + } + ) + .ReturnsResult(); + std::shared_ptr secondImportedFileStreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) + .WhenCalledWith + (secondExpectedImportPath) + .Times(1) + .WhenCalledExpectedly_Do + ( + [&secondImportIfstreamInstance] + (void* instance, const std::vector&) + { + secondImportIfstreamInstance = instance; + } + ) + .ReturnsResult(); + + //Mock for rdbuf call with specific path check for import files + std::shared_ptr firstImportedFileRdbufResult = + CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) + .Returns(importedProfileYamlStr) + .Times(1) + .If + ( + [&firstImportIfstreamInstance] + (void* instance, const std::vector&) -> bool + { + return instance == firstImportIfstreamInstance; + } + ) + .ReturnsResult(); + std::shared_ptr secondImportedFileRdbufResult = + CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) + .Returns(importedFiletypesYamlStr) + .Times(1) + .If + ( + [&secondImportIfstreamInstance] + (void* instance, const std::vector&) -> bool + { + return instance == secondImportIfstreamInstance; + } + ) + .ReturnsResult(); + commonDefaultOverrideSetup(); + + std::vector profiles; + std::string preferredProfile; + ); + + ssTEST_OUTPUT_EXECUTION + ( + bool parseResult = runcpp2::ReadUserConfig(profiles, preferredProfile, configPath); + ); + + commonOverrideStatusCheck(); + ssTEST_OUTPUT_ASSERT("", firstImportFileExistResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", secondImportFileExistResult->GetSucceedCount(), 1); + + ssTEST_OUTPUT_ASSERT("", firstImportedFileStreamResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", secondImportedFileStreamResult->GetSucceedCount(), 1); + + ssTEST_OUTPUT_ASSERT("", firstImportedFileRdbufResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", secondImportedFileRdbufResult->GetSucceedCount(), 1); + + ssTEST_OUTPUT_ASSERT("ReadUserConfig should succeed", parseResult); + ssTEST_OUTPUT_ASSERT("Should parse 2 profiles (1 imported + 1 inline)", profiles.size(), 2); + if(!profiles.empty()) + { + ssTEST_OUTPUT_ASSERT( "First profile should be the imported one", + profiles[0].Name, + "imported-profile"); + ssTEST_OUTPUT_ASSERT( "First profile should have the imported executable", + profiles[0] .Compiler + .OutputTypes + .Executable.at("DefaultPlatform") + .Executable, + "imported-gcc"); + ssTEST_OUTPUT_ASSERT( "First profile should have nested imported filetype", + profiles[0].FilesTypes.SharedLinkFile.Prefix.at("DefaultPlatform"), + "file-prefix"); + ssTEST_OUTPUT_ASSERT( "First profile should have correct name aliases", + profiles[0].NameAliases.size() == 1 && + profiles[0].NameAliases.find("gcc") != + profiles[0].NameAliases.end()); + ssTEST_OUTPUT_ASSERT( "PreferredProfile should match the imported profile", + preferredProfile, + "imported-profile"); + } + }; + ssTEST_END_TEST_GROUP(); return 0; diff --git a/Src/runcpp2/ConfigParsing.cpp b/Src/runcpp2/ConfigParsing.cpp index ec91d30..2556b43 100644 --- a/Src/runcpp2/ConfigParsing.cpp +++ b/Src/runcpp2/ConfigParsing.cpp @@ -16,10 +16,80 @@ extern "C" const uint8_t DefaultUserConfig[]; extern "C" const size_t DefaultUserConfig_size; +extern "C" const uint8_t CommonFileTypes[]; +extern "C" const size_t CommonFileTypes_size; +extern "C" const uint8_t G_PlusPlus[]; +extern "C" const size_t G_PlusPlus_size; +extern "C" const uint8_t Vs2022_v17Plus[]; +extern "C" const size_t Vs2022_v17Plus_size; + namespace { + bool ResovleProfileImport( ryml::NodeRef currentProfileNode, + const std::string& configPath, + std::vector& importProfileTrees) + { + INTERNAL_RUNCPP2_SAFE_START(); + + ssLOG_FUNC_INFO(); + + ghc::filesystem::path currentImportFilePath = configPath; + while(runcpp2::ExistAndHasChild(currentProfileNode, "Import")) + { + if(!INTERNAL_RUNCPP2_BIT_CONTANTS( currentProfileNode["Import"].type().type, + ryml::NodeType_e::KEYVAL)) + { + ssLOG_ERROR("Import must be a path to a YAML file"); + return false; + } + + ghc::filesystem::path currentImportDir = currentImportFilePath; + currentImportDir = currentImportDir.parent_path(); + currentImportFilePath = + currentImportDir / runcpp2::GetValue(currentProfileNode["Import"]); + + std::error_code ec; + if(!ghc::filesystem::exists(currentImportFilePath, ec)) + { + ssLOG_ERROR("Import path doesn't exist: " << currentImportFilePath.string()); + return false; + } + + //Read compiler profiles + std::ifstream importProfileFile(currentImportFilePath); + if(!importProfileFile) + { + ssLOG_ERROR("Failed to open profile import file: " << currentImportFilePath); + return false; + } + std::stringstream buffer; + buffer << importProfileFile.rdbuf(); + + ryml::NodeRef importProfileNode; + importProfileTrees.emplace_back(); + importProfileTrees.back() = ryml::parse_in_arena(buffer.str().c_str()); + if(!runcpp2::ResolveYAML_Stream(importProfileTrees.back(), importProfileNode)) + return false; + + if(!runcpp2::MergeYAML_NodeChildren(importProfileNode, currentProfileNode)) + return false; + + //Replace the current import field if the import profile has an import field + if(runcpp2::ExistAndHasChild(importProfileNode, "Import")) + currentProfileNode["Import"] << runcpp2::GetValue(importProfileNode["Import"]); + //Otherwise, remove the current import field + else + currentProfileNode.remove_child("Import"); + } + + return true; + + INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false); + } + bool ParseUserConfig( const std::string& userConfigString, + const std::string& configPath, std::vector& outProfiles, std::string& outPreferredProfile) { @@ -27,9 +97,8 @@ namespace ssLOG_FUNC_INFO(); - std::string temp = userConfigString; - ryml::Tree rootTree = ryml::parse_in_place(c4::to_substr(temp)); - ryml::ConstNodeRef configNode; + ryml::Tree rootTree = ryml::parse_in_arena(userConfigString.c_str()); + ryml::NodeRef configNode; if(!runcpp2::ResolveYAML_Stream(rootTree, configNode)) return false; @@ -42,7 +111,7 @@ namespace return false; } - ryml::ConstNodeRef profilesNode = configNode["Profiles"]; + ryml::NodeRef profilesNode = configNode["Profiles"]; if(profilesNode.num_children() == 0) { @@ -51,19 +120,28 @@ namespace } ssLOG_INFO(profilesNode.num_children() << " profiles found in user config"); + std::vector importProfileTrees; for(int i = 0; i < profilesNode.num_children(); ++i) { ssLOG_INFO("Parsing profile at index " << i); - ryml::ConstNodeRef currentProfileNode = profilesNode[i]; + if(!INTERNAL_RUNCPP2_BIT_CONTANTS(profilesNode[i].type().type, ryml::NodeType_e::MAP)) + { + ssLOG_ERROR("Profile entry must be a map"); + return false; + } + + if(!ResovleProfileImport(profilesNode[i], configPath, importProfileTrees)) + return false; + outProfiles.push_back({}); - if(!outProfiles.back().ParseYAML_Node(currentProfileNode)) + if(!outProfiles.back().ParseYAML_Node(profilesNode[i])) { outProfiles.erase(outProfiles.end() - 1); ssLOG_ERROR("Failed to parse compiler profile at index " << i); return false; } - } + } //for(int i = 0; i < profilesNode.num_children(); ++i) if(outProfiles.empty()) { @@ -83,7 +161,8 @@ namespace { PlatformName platform = runcpp2::GetKey(preferredProfilesMapNode[i]); ryml::ConstNodeRef currentNode = preferredProfilesMapNode[i]; - if(!INTERNAL_RUNCPP2_BIT_CONTANTS(currentNode.type().type, ryml::NodeType_e::KEYVAL)) + if(!INTERNAL_RUNCPP2_BIT_CONTANTS( currentNode.type().type, + ryml::NodeType_e::KEYVAL)) { ssLOG_ERROR("Failed to parse PreferredProfile map. " "Keyval is expected in each platform"); @@ -92,7 +171,8 @@ namespace currentNode >> preferredProfiles[platform]; } - const std::string* selectedProfile = runcpp2::GetValueFromPlatformMap(preferredProfiles); + const std::string* selectedProfile = + runcpp2::GetValueFromPlatformMap(preferredProfiles); outPreferredProfile = selectedProfile != nullptr ? *selectedProfile : outPreferredProfile; } @@ -113,7 +193,7 @@ namespace outPreferredProfile = outProfiles.front().Name; ssLOG_WARNING("PreferredProfile is empty. Using the first profile name"); } - } + } //if(runcpp2::ExistAndHasChild(configNode, "PreferredProfile")) return true; @@ -123,6 +203,8 @@ namespace std::string runcpp2::GetConfigFilePath() { + CO_OVERRIDE_IMPL(OverrideInstance, std::string, ()); + //Check if user config exists char configDirC_Str[MAX_PATH] = {0}; @@ -210,15 +292,54 @@ bool runcpp2::WriteDefaultConfig(const std::string& userConfigPath) while(true); } - //Create default compiler profiles - std::ofstream configFile(userConfigPath, std::ios::binary); - if(!configFile) + //Create user config + { + std::ofstream configFile(userConfigPath, std::ios::binary); + if(!configFile) + { + ssLOG_ERROR("Failed to create default config file: " << userConfigPath); + return false; + } + configFile.write((const char*)DefaultUserConfig, DefaultUserConfig_size); + } + + ghc::filesystem::path userConfigDirectory = userConfigPath; + userConfigDirectory = userConfigDirectory.parent_path(); + ghc::filesystem::path defaultYamlDirectory = userConfigDirectory / "Default"; + + //Default configs + if(!ghc::filesystem::exists(defaultYamlDirectory , _)) + { + if(!ghc::filesystem::create_directories(defaultYamlDirectory, _)) + { + ssLOG_ERROR("Failed to create directory: " << defaultYamlDirectory.string()); + return false; + } + } + + //Writing default profiles + auto writeDefaultConfig = + [&defaultYamlDirectory] + (ghc::filesystem::path outputPath, const uint8_t* outputContent, size_t outputSize) + { + const ghc::filesystem::path currentOutputPath = defaultYamlDirectory / outputPath; + std::ofstream defaultFile(currentOutputPath.string(), std::ios::binary); + if(!defaultFile) + { + ssLOG_ERROR("Failed to create default config file: " << currentOutputPath.string()); + return false; + } + defaultFile.write((const char*)outputContent, outputSize); + return true; + }; + + if( !writeDefaultConfig("CommonFileTypes.yaml", CommonFileTypes, CommonFileTypes_size) || + !writeDefaultConfig("g++.yaml", G_PlusPlus, G_PlusPlus_size) || + !writeDefaultConfig("vs2022_v17+.yaml", Vs2022_v17Plus, Vs2022_v17Plus_size)) { - ssLOG_ERROR("Failed to create default config file: " << userConfigPath); return false; } - configFile.write((const char*)DefaultUserConfig, DefaultUserConfig_size); - configFile.close(); + return true; } @@ -258,18 +379,18 @@ bool runcpp2::ReadUserConfig( std::vector& outProfiles, //Read compiler profiles std::string userConfigContent; { - std::ifstream userConfigFilePath(configPath); - if(!userConfigFilePath) + std::ifstream userConfigFile(configPath); + if(!userConfigFile) { ssLOG_ERROR("Failed to open config file: " << configPath); return false; } std::stringstream buffer; - buffer << userConfigFilePath.rdbuf(); + buffer << userConfigFile.rdbuf(); userConfigContent = buffer.str(); } - if(!ParseUserConfig(userConfigContent, outProfiles, outPreferredProfile)) + if(!ParseUserConfig(userConfigContent, configPath, outProfiles, outPreferredProfile)) { ssLOG_ERROR("Failed to parse config file: " << configPath); return false; @@ -289,10 +410,9 @@ bool runcpp2::ParseScriptInfo( const std::string& scriptInfo, return true; ryml::Tree scriptTree; - std::string temp = scriptInfo; - scriptTree = ryml::parse_in_place(c4::to_substr(temp)); + scriptTree = ryml::parse_in_arena(scriptInfo.c_str()); - ryml::ConstNodeRef rootScriptNode; + ryml::NodeRef rootScriptNode; if(!runcpp2::ResolveYAML_Stream(scriptTree, rootScriptNode)) return false; diff --git a/Src/runcpp2/DependenciesHelper.cpp b/Src/runcpp2/DependenciesHelper.cpp index 0eb61c1..69c466a 100644 --- a/Src/runcpp2/DependenciesHelper.cpp +++ b/Src/runcpp2/DependenciesHelper.cpp @@ -1020,7 +1020,7 @@ bool runcpp2::HandleImport( Data::DependencyInfo& dependency, } //Parse the YAML file - ryml::ConstNodeRef resolvedTree; + ryml::NodeRef resolvedRootNode; ryml::Tree importedTree; std::string content; { @@ -1036,7 +1036,7 @@ bool runcpp2::HandleImport( Data::DependencyInfo& dependency, importedTree = ryml::parse_in_place(c4::to_substr(content)); - if(!runcpp2::ResolveYAML_Stream(importedTree, resolvedTree)) + if(!runcpp2::ResolveYAML_Stream(importedTree, resolvedRootNode)) return false; } @@ -1058,7 +1058,7 @@ bool runcpp2::HandleImport( Data::DependencyInfo& dependency, dependency = Data::DependencyInfo(); //Parse the imported dependency - if(!dependency.ParseYAML_Node(resolvedTree)) + if(!dependency.ParseYAML_Node(resolvedRootNode)) { ssLOG_ERROR("Failed to parse imported dependency: " << fullPath); diff --git a/Src/runcpp2/ParseUtil.cpp b/Src/runcpp2/ParseUtil.cpp index 0ec9987..b14232d 100644 --- a/Src/runcpp2/ParseUtil.cpp +++ b/Src/runcpp2/ParseUtil.cpp @@ -294,7 +294,7 @@ bool runcpp2::GetParsableInfo(const std::string& contentToParse, std::string& ou } bool runcpp2::ResolveYAML_Stream( ryml::Tree& rootTree, - ryml::ConstNodeRef& outRootNode) + ryml::NodeRef& outRootNode) { ssLOG_FUNC_DEBUG(); @@ -333,6 +333,29 @@ bool runcpp2::ResolveYAML_Stream( ryml::Tree& rootTree, INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false); } +bool runcpp2::MergeYAML_NodeChildren(ryml::NodeRef nodeToMergeFrom, ryml::NodeRef nodeToMergeTo) +{ + ssLOG_FUNC_DEBUG(); + + INTERNAL_RUNCPP2_SAFE_START(); + + if(!nodeToMergeFrom.is_map() || !nodeToMergeTo.is_map()) + { + ssLOG_ERROR("Merge node is not map"); + return false; + } + + for(int i = 0; i < nodeToMergeFrom.num_children(); ++i) + { + if(!ExistAndHasChild(nodeToMergeTo, GetKey(nodeToMergeFrom[i]), true)) + nodeToMergeFrom[i].duplicate(nodeToMergeTo, {}); + } + + return true; + + INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false); +} + bool runcpp2::ExistAndHasChild( ryml::ConstNodeRef node, const std::string& childName, bool nullable) From 66cca481600c68ab9e1dfd6e8a0fe209df069f4a Mon Sep 17 00:00:00 2001 From: Neko Box Coder Date: Sat, 3 May 2025 21:04:29 +0100 Subject: [PATCH 3/5] Updating default YAML paths for CI to work --- CMakeLists.txt | 6 +++--- DefaultYAMLs/{ => Default}/CommonFileTypes.yaml | 0 DefaultYAMLs/{ => Default}/g++.yaml | 2 ++ DefaultYAMLs/{ => Default}/vs2022_v17+.yaml | 0 4 files changed, 5 insertions(+), 3 deletions(-) rename DefaultYAMLs/{ => Default}/CommonFileTypes.yaml (100%) rename DefaultYAMLs/{ => Default}/g++.yaml (99%) rename DefaultYAMLs/{ => Default}/vs2022_v17+.yaml (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d5883a7..8e74f90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,13 +114,13 @@ if(RUNCPP2_UPDATE_DEFAULT_YAMLS OR EMBEDDED_FILE_SIZE LESS 1024) set(FILES_TO_EMBED "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/DefaultUserConfig.yaml" "DefaultUserConfig" - "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/CommonFileTypes.yaml" + "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/Default/CommonFileTypes.yaml" "CommonFileTypes" - "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/g++.yaml" + "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/Default/g++.yaml" "G_PlusPlus" - "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/vs2022_v17+.yaml" + "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/Default/vs2022_v17+.yaml" "Vs2022_v17Plus" "${CMAKE_CURRENT_LIST_DIR}/DefaultYAMLs/DefaultScriptInfo.yaml" diff --git a/DefaultYAMLs/CommonFileTypes.yaml b/DefaultYAMLs/Default/CommonFileTypes.yaml similarity index 100% rename from DefaultYAMLs/CommonFileTypes.yaml rename to DefaultYAMLs/Default/CommonFileTypes.yaml diff --git a/DefaultYAMLs/g++.yaml b/DefaultYAMLs/Default/g++.yaml similarity index 99% rename from DefaultYAMLs/g++.yaml rename to DefaultYAMLs/Default/g++.yaml index 4db8ed2..613f759 100644 --- a/DefaultYAMLs/g++.yaml +++ b/DefaultYAMLs/Default/g++.yaml @@ -42,6 +42,8 @@ Languages: ["c++"] # The file properties for the object files for each platform. # See "./CommonFileTypes.yaml" for FilesTypes # FilesTypes: ... + +# We can use the "Import" field to import other yaml files. We are importing "FilesTypes" here Import: "./CommonFileTypes.yaml" # Specify the compiler settings diff --git a/DefaultYAMLs/vs2022_v17+.yaml b/DefaultYAMLs/Default/vs2022_v17+.yaml similarity index 100% rename from DefaultYAMLs/vs2022_v17+.yaml rename to DefaultYAMLs/Default/vs2022_v17+.yaml From 0ce82137a29237982c19d12396a31792e7ddbc78 Mon Sep 17 00:00:00 2001 From: Neko Box Coder Date: Sat, 3 May 2025 21:06:23 +0100 Subject: [PATCH 4/5] Updating documentation --- mkdocs/docs/TODO.md | 2 +- mkdocs/docs/user_config.md | 823 +++++++++++++++++++------------------ 2 files changed, 417 insertions(+), 408 deletions(-) diff --git a/mkdocs/docs/TODO.md b/mkdocs/docs/TODO.md index deec465..bb4d6b5 100644 --- a/mkdocs/docs/TODO.md +++ b/mkdocs/docs/TODO.md @@ -15,11 +15,11 @@ - Substituted string: `-I ".\"` - Where the path contains escape character which escaped the wrapping quotes - Add platform map for PreferredProfile for user config + - Add ability to reference local YAML file for config profiles ## Planned ### v0.3.0 -- Add ability to reference local YAML for user config - Add interactive tutorials and redo documentations - Allow runcpp2 to be library for scriptable pipeline diff --git a/mkdocs/docs/user_config.md b/mkdocs/docs/user_config.md index 86713b7..2830070 100644 --- a/mkdocs/docs/user_config.md +++ b/mkdocs/docs/user_config.md @@ -2,13 +2,30 @@ **TODO** -## Default +## `UserConfig.yaml` ```yaml -# List of anchors that will be aliased later +# WARNING: All command substitutions in this file are passed directly to the shell. +# Exercise caution when using variables or user-provided input in your build commands +# to prevent potential security vulnerabilities. + +# A profile to be used if not specified while running the build script +PreferredProfile: + DefaultPlatform: "g++" + Windows: "msvc" + +# List of compiler/linker profiles that instruct how to compile/link +# See "./Default/g++.yaml" for the documentation of each field in a profile entry +Profiles: +- Import: "./Default/g++.yaml" +- Import: "./Default/vs2022_v17+.yaml" +``` + +## `Default/g++.yaml` +```yaml +# DO NOT modify this file. Changes will be overwritten when there's a reset or update + +# List of anchors that will be aliased later. `Template` is **NOT** part of a profile Templates: - vs2022_v17+_CompileFlags: &vs2022_v17+_CompileFlags - Flags: "/nologo /W4 /diagnostics:caret /utf-8 /Gm- /MDd /EHar /TP /std:c++17 /GR /RTC1 /Zc:inline /Zi" - "g++_CompileRunParts": &g++_CompileRunParts - Type: Once CommandPart: "{Executable} -c {CompileFlags}" @@ -23,7 +40,238 @@ Templates: "g++_CompileExpectedOutputFiles": &g++_CompileExpectedOutputFiles - "{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}" + +# Name (case sensitive) of the profile that can be queried from a script +Name: "g++" + +# (Optional) Name aliases (case sensitive) of the current profile +NameAliases: ["mingw"] + +# The file extensions associated with the profile +FileExtensions: [.cpp, .cc, .cxx] + +# The languages supported by the profile +Languages: ["c++"] + +# (Optional) The commands to run in **shell** before calling the compiler/linker for each platform. +# This is run inside the root build directory. +# Setup: +# DefaultPlatform: [] + +# (Optional) The commands to run in **shell** after calling the compiler/linker for each platform. +# This is run inside the root build directory. +# Cleanup: +# DefaultPlatform: [] + +# The file properties for the object files for each platform. +# See "./CommonFileTypes.yaml" for FilesTypes +# FilesTypes: ... + +# We can use the "Import" field to import other yaml files. We are importing "FilesTypes" here +Import: "./CommonFileTypes.yaml" + +# Specify the compiler settings +Compiler: + # (Optional) The command to be prepend for each compile command in **shell** for each platform + # PreRun: + # DefaultPlatform: "" + + # Shell command to use for checking if the executable exists or not + CheckExistence: + DefaultPlatform: "g++ -v" + + # Here are a list of substitution strings for RunParts, Setup and Cleanup. + # To escape '{' and '}' to avoid substitutioon, simply repeat the '{' or '}' character again. + # So "${MyBashVariable}" will become "${{MyBashVariable}}" + + # {Executable}: Compiler executable + # {CompileFlags}: Compile flags from config and override + # {InputFileName}: Name of the input file (without directory path and extension) + # {InputFileExtension}: Extension of the input file + # {InputFileDirectory}: Directory of the input file + # {InputFilePath}: Full path to the input file + # {OutputFileDirectory}: Directory of all the output files + # {/}: Filesystem separator for the host platform + + # {SharedLibraryFile.Prefix} + # {SharedLinkFile.Prefix} + # {StaticLinkFile.Prefix} + # {ObjectLinkFile.Prefix} + # {DebugSymbolFile.Prefix} + + # {SharedLibraryFile.Extension} + # {SharedLinkFile.Extension} + # {StaticLinkFile.Extension} + # {ObjectLinkFile.Extension} + # {DebugSymbolFile.Extension} + + # Below are iterable substitution strings, must be inside "Repeats" run type: + # {IncludeDirectoryPath}: Path to all the include directories + # {DefineNameOnly}: All the defines without a value specified (equivalent to #define X) + # {DefineName}: Name of all the defines that has a value specified + # {DefineValue}: Value of all the defines that has a value specified (use together with {DefineName}) + CompileTypes: + Executable: + DefaultPlatform: + # Default flags to be substituted as {CompileFlags} + Flags: "-std=c++17 -Wall -g" + + # The executable to be substituted as {Executable} + Executable: "g++" + + # The components for the command to be run + RunParts: *g++_CompileRunParts + + # What files to be expected as output for the command + ExpectedOutputFiles: *g++_CompileExpectedOutputFiles + + # (Optional) The commands to run in **shell** BEFORE compiling + # This is run inside the .runcpp2 directory where the build happens. + # Setup: [] + + # (Optional) The commands to run in **shell** AFTER compiling + # This is run inside the .runcpp2 directory where the build happens. + # Cleanup: [] + ExecutableShared: + DefaultPlatform: + Flags: "-std=c++17 -Wall -g -fpic" + Executable: "g++" + RunParts: *g++_CompileRunParts + ExpectedOutputFiles: *g++_CompileExpectedOutputFiles + # Setup: [] + # Cleanup: [] + Static: + DefaultPlatform: + Flags: "-std=c++17 -Wall -g" + Executable: "g++" + RunParts: *g++_CompileRunParts + ExpectedOutputFiles: *g++_CompileExpectedOutputFiles + # Setup: [] + # Cleanup: [] + Shared: + DefaultPlatform: + Flags: "-std=c++17 -Wall -g -fpic" + Executable: "g++" + RunParts: *g++_CompileRunParts + ExpectedOutputFiles: *g++_CompileExpectedOutputFiles + # Setup: [] + # Cleanup: [] + +# Specify the linker settings +Linker: + CheckExistence: + DefaultPlatform: "g++ -v" + + # Here are a list of substitution strings for RunParts, Setup and Cleanup + # {Executable}: Linker executable + # {LinkFlags}: Link flags from config and override + # {OutputFileName}: Name of all the output files (without directory path and extension) + # {OutputFileDirectory}: Directory of all the output files + # {/}: Filesystem separator for the host platform + + # {SharedLibraryFile.Prefix} + # {SharedLinkFile.Prefix} + # {StaticLinkFile.Prefix} + # {ObjectLinkFile.Prefix} + # {DebugSymbolFile.Prefix} + + # {SharedLibraryFile.Extension} + # {SharedLinkFile.Extension} + # {StaticLinkFile.Extension} + # {ObjectLinkFile.Extension} + # {DebugSymbolFile.Extension} + # Below are iterable substitution strings, must be inside "Repeats" run type: + # {LinkFileName}: Name of the file to be linked, regardless of the build type + # {LinkFileExtension}: File Extension of the file to be linked, regardless of the build type + # {LinkFileDirectory}: Directory of the file to be linked, regardless of the build type + # {LinkFilePath}: Full path to the file to be linked, regardless of the build type + + # {LinkObjectFileName}: Name of the object file to be linked + # {LinkObjectFileExtension}: File Extension of the object file to be linked + # {LinkObjectFileDirectory}: Directory of the object file to be linked + # {LinkObjectFilePath}: Full path to the object file to be linked + + # {LinkSharedFileName}: Name of the shared file to be linked + # {LinkSharedFileExtension}: File Extension of the shared file to be linked + # {LinkSharedFileDirectory}: Directory of the shared file to be linked + # {LinkSharedFilePath}: Full path to the shared file to be linked + + # {LinkStaticFileName}: Name of the static file to be linked + # {LinkStaticFileExtension}: File Extension of the static file to be linked + # {LinkStaticFileDirectory}: Directory of the static file to be linked + # {LinkStaticFilePath}: Full path to the static file to be linked + LinkTypes: + Executable: + Unix: + Flags: "-Wl,-rpath,\\$ORIGIN" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}"] + # Setup: [] + # Cleanup: [] + Windows: + Flags: "-Wl,-rpath,\\$ORIGIN" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}.exe\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] + # Setup: [] + # Cleanup: [] + ExecutableShared: + DefaultPlatform: + Flags: "-shared -Wl,-rpath,\\$ORIGIN" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + # Setup: [] + # Cleanup: [] + Static: + DefaultPlatform: + Flags: "" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] + # Setup: [] + # Cleanup: [] + Shared: + DefaultPlatform: + Flags: "-shared -Wl,-rpath,\\$ORIGIN" + Executable: "g++" + RunParts: + - Type: Once + CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + # Setup: [] + # Cleanup: [] + +``` + +## `Default/vs2022_v17+.yaml` +```yaml +# DO NOT modify this file. Changes will be overwritten when there's a reset or update + +# List of anchors that will be aliased later. `Template` is **NOT** part of a profile +Templates: + vs2022_v17+_CompileFlags: &vs2022_v17+_CompileFlags + Flags: "/nologo /W4 /diagnostics:caret /utf-8 /Gm- /MDd /EHar /TP /std:c++17 /GR /RTC1 /Zc:inline /Zi" "vs2022_v17+_CompileRunParts": &vs2022_v17+_CompileRunParts - Type: Once CommandPart: "{Executable} /c {CompileFlags}" @@ -37,414 +285,175 @@ Templates: CommandPart: " /Fo\"{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}\" \ /Fd\"{OutputFileDirectory}{/}{DebugSymbolFile.Prefix}{InputFileName}{DebugSymbolFile.Extension}\" \ \"{InputFilePath}\"" - "vs2022_v17+_CompileExpectedOutputFiles": &vs2022_v17+_CompileExpectedOutputFiles - "{OutputFileDirectory}{/}{ObjectLinkFile.Prefix}{InputFileName}{ObjectLinkFile.Extension}" - "{OutputFileDirectory}{/}{DebugSymbolFile.Prefix}{InputFileName}{DebugSymbolFile.Extension}" - # The following fields set the prefixes and extensions for each type of the files - # If the name of an object files are libtest.so and libtest2.so, - # the prefixes and extensions are "lib" and ".so" - - # TODO: Add support for custom platform - # Each of the platform dependent settings can be listed under - # - DefaultPlatform - # - Windows - # - Linux - # - MacOS - # - Unix - FilesTypes: &CommonFilesTypes - # The file properties for the files to be **linked** as object file for each platform - ObjectLinkFile: - Prefix: - DefaultPlatform: "" - Extension: - Windows: ".obj" - Unix: ".o" - - # The file properties for the files to be **linked** as shared libraries for each platform - SharedLinkFile: - Prefix: - Windows: "" - Linux: "lib" - MacOS: "" - Extension: - Windows: ".lib" - Linux: ".so" - MacOS: ".dylib" - - # The file properties for the files to be **copied** as shared libraries for each platform - SharedLibraryFile: - Prefix: - Windows: "" - Linux: "lib" - MacOS: "" - Extension: - Windows: ".dll" - Linux: ".so" - MacOS: ".dylib" - - # The file properties for the files to be linked as static libraries for each platform - StaticLinkFile: - Prefix: - Unix: "lib" - Windows: "" - Extension: - Windows: ".lib" - Unix: ".a" - - # (Optional) The file properties for debug symbols to be copied alongside the binary - # for each platform - DebugSymbolFile: - Prefix: - Windows: "" - Unix: "" - Extension: - Windows: ".pdb" - Unix: "" - -# WARNING: All command substitutions in this file are passed directly to the shell. -# Exercise caution when using variables or user-provided input in your build commands -# to prevent potential security vulnerabilities. - -# A profile to be used if not specified while running the build script -PreferredProfile: - DefaultPlatform: "g++" - Windows: "msvc" +# https://learn.microsoft.com/en-us/cpp/overview/compiler-versions?view=msvc-170 +Name: "vs2022_v17+" +NameAliases: ["msvc1930+", "msvc"] +FileExtensions: [.cpp, .cc, .cxx] +Languages: ["c++"] +Import: "./CommonFileTypes.yaml" +Setup: + Windows: + - >- + for /f "usebackq tokens=*" %i in (`CALL "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" + -version "[17.0,18.0)" -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do ( + echo "%i\VC\Auxiliary\Build\vcvarsall.bat" x64 > .\prerun.bat + ) +Cleanup: + Windows: [ "del .\\prerun.bat" ] +Compiler: + PreRun: + Windows: ".\\prerun.bat" + CheckExistence: + Windows: "where.exe CL.exe" + CompileTypes: + Executable: + Windows: + <<: *vs2022_v17+_CompileFlags + Executable: "CL.exe" + RunParts: *vs2022_v17+_CompileRunParts + ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles + ExecutableShared: + Windows: + <<: *vs2022_v17+_CompileFlags + Executable: "CL.exe" + RunParts: *vs2022_v17+_CompileRunParts + ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles + Static: + Windows: + <<: *vs2022_v17+_CompileFlags + Executable: "CL.exe" + RunParts: *vs2022_v17+_CompileRunParts + ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles + Shared: + Windows: + <<: *vs2022_v17+_CompileFlags + Executable: "CL.exe" + RunParts: *vs2022_v17+_CompileRunParts + ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles +Linker: + PreRun: + Windows: ".\\prerun.bat" + CheckExistence: + Windows: "where.exe link.exe" + LinkTypes: + Executable: + Windows: + Flags: >- + /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib + oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE + /DEBUG /MANIFESTUAC:"level='asInvoker'" + Executable: "link.exe" + RunParts: + - Type: Once + CommandPart: >- + {Executable} {LinkFlags} + /OUT:"{OutputFileDirectory}{/}{OutputFileName}.exe" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] + ExecutableShared: + Windows: + Flags: >- + /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib + oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE + /DEBUG /DLL /MANIFESTUAC:"level='asInvoker'" + Executable: "link.exe" + RunParts: + - Type: Once + CommandPart: >- + {Executable} {LinkFlags} + /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" + /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" + /DEF:".\temp.def" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] + Setup: [ "echo EXPORTS > .\\temp.def", "echo. main @1 >> .\\temp.def" ] + Cleanup: [ "del .\\temp.def" ] + Static: + Windows: + Flags: "/NOLOGO" + Executable: "lib.exe" + RunParts: + - Type: Once + CommandPart: >- + {Executable} {LinkFlags} + /OUT:"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}" + /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] + Shared: + Windows: + Flags: >- + /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib + oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE + /DEBUG /DLL /MANIFESTUAC:"level='asInvoker'" + Executable: "link.exe" + RunParts: + - Type: Once + CommandPart: >- + {Executable} {LinkFlags} + /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" + /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" + - Type: Repeats + CommandPart: " \"{LinkFilePath}\"" + ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] -# List of compiler/linker profiles that instruct how to compile/link -Profiles: - # Name (case sensitive) of the profile that can be queried from a script -- Name: "g++" - - # (Optional) Name aliases (case sensitive) of the current profile - NameAliases: ["mingw"] - - # The file extensions associated with the profile - FileExtensions: [.cpp, .cc, .cxx] - - # The languages supported by the profile - Languages: ["c++"] - - # (Optional) The commands to run in **shell** before calling the compiler/linker for each platform. - # This is run inside the root build directory. - # Setup: - # DefaultPlatform: [] - - # (Optional) The commands to run in **shell** after calling the compiler/linker for each platform. - # This is run inside the root build directory. - # Cleanup: - # DefaultPlatform: [] - - # The file properties for the object files for each platform. - FilesTypes: *CommonFilesTypes - - # Specify the compiler settings - Compiler: - # (Optional) The command to be prepend for each compile command in **shell** for each platform - # PreRun: - # DefaultPlatform: "" - - # Shell command to use for checking if the executable exists or not - CheckExistence: - DefaultPlatform: "g++ -v" - - # Here are a list of substitution strings for RunParts, Setup and Cleanup. - # To escape '{' and '}' to avoid substitutioon, simply repeat the '{' or '}' character again. - # So "${MyBashVariable}" will become "${{MyBashVariable}}" - - # {Executable}: Compiler executable - # {CompileFlags}: Compile flags from config and override - # {InputFileName}: Name of the input file (without directory path and extension) - # {InputFileExtension}: Extension of the input file - # {InputFileDirectory}: Directory of the input file - # {InputFilePath}: Full path to the input file - # {OutputFileDirectory}: Directory of all the output files - # {/}: Filesystem separator for the host platform - - # {SharedLibraryFile.Prefix} - # {SharedLinkFile.Prefix} - # {StaticLinkFile.Prefix} - # {ObjectLinkFile.Prefix} - # {DebugSymbolFile.Prefix} - - # {SharedLibraryFile.Extension} - # {SharedLinkFile.Extension} - # {StaticLinkFile.Extension} - # {ObjectLinkFile.Extension} - # {DebugSymbolFile.Extension} - - # Below are iterable substitution strings, must be inside "Repeats" run type: - # {IncludeDirectoryPath}: Path to all the include directories - # {DefineNameOnly}: All the defines without a value specified (equivalent to #define X) - # {DefineName}: Name of all the defines that has a value specified - # {DefineValue}: Value of all the defines that has a value specified (use together with {DefineName}) - CompileTypes: - Executable: - DefaultPlatform: - # Default flags to be substituted as {CompileFlags} - Flags: "-std=c++17 -Wall -g" - - # The executable to be substituted as {Executable} - Executable: "g++" - - # The components for the command to be run - RunParts: *g++_CompileRunParts - - # What files to be expected as output for the command - ExpectedOutputFiles: *g++_CompileExpectedOutputFiles - - # (Optional) The commands to run in **shell** BEFORE compiling - # This is run inside the .runcpp2 directory where the build happens. - # Setup: [] - - # (Optional) The commands to run in **shell** AFTER compiling - # This is run inside the .runcpp2 directory where the build happens. - # Cleanup: [] - ExecutableShared: - DefaultPlatform: - Flags: "-std=c++17 -Wall -g -fpic" - Executable: "g++" - RunParts: *g++_CompileRunParts - ExpectedOutputFiles: *g++_CompileExpectedOutputFiles - # Setup: [] - # Cleanup: [] - Static: - DefaultPlatform: - Flags: "-std=c++17 -Wall -g" - Executable: "g++" - RunParts: *g++_CompileRunParts - ExpectedOutputFiles: *g++_CompileExpectedOutputFiles - # Setup: [] - # Cleanup: [] - Shared: - DefaultPlatform: - Flags: "-std=c++17 -Wall -g -fpic" - Executable: "g++" - RunParts: *g++_CompileRunParts - ExpectedOutputFiles: *g++_CompileExpectedOutputFiles - # Setup: [] - # Cleanup: [] - - # Specify the linker settings - Linker: - CheckExistence: - DefaultPlatform: "g++ -v" - - # Here are a list of substitution strings for RunParts, Setup and Cleanup - # {Executable}: Linker executable - # {LinkFlags}: Link flags from config and override - # {OutputFileName}: Name of all the output files (without directory path and extension) - # {OutputFileDirectory}: Directory of all the output files - # {/}: Filesystem separator for the host platform - - # {SharedLibraryFile.Prefix} - # {SharedLinkFile.Prefix} - # {StaticLinkFile.Prefix} - # {ObjectLinkFile.Prefix} - # {DebugSymbolFile.Prefix} - - # {SharedLibraryFile.Extension} - # {SharedLinkFile.Extension} - # {StaticLinkFile.Extension} - # {ObjectLinkFile.Extension} - # {DebugSymbolFile.Extension} - - # Below are iterable substitution strings, must be inside "Repeats" run type: - # {LinkFileName}: Name of the file to be linked, regardless of the build type - # {LinkFileExtension}: File Extension of the file to be linked, regardless of the build type - # {LinkFileDirectory}: Directory of the file to be linked, regardless of the build type - # {LinkFilePath}: Full path to the file to be linked, regardless of the build type - - # {LinkObjectFileName}: Name of the object file to be linked - # {LinkObjectFileExtension}: File Extension of the object file to be linked - # {LinkObjectFileDirectory}: Directory of the object file to be linked - # {LinkObjectFilePath}: Full path to the object file to be linked - - # {LinkSharedFileName}: Name of the shared file to be linked - # {LinkSharedFileExtension}: File Extension of the shared file to be linked - # {LinkSharedFileDirectory}: Directory of the shared file to be linked - # {LinkSharedFilePath}: Full path to the shared file to be linked - - # {LinkStaticFileName}: Name of the static file to be linked - # {LinkStaticFileExtension}: File Extension of the static file to be linked - # {LinkStaticFileDirectory}: Directory of the static file to be linked - # {LinkStaticFilePath}: Full path to the static file to be linked - LinkTypes: - Executable: - Unix: - Flags: "-Wl,-rpath,\\$ORIGIN" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}"] - # Setup: [] - # Cleanup: [] - Windows: - Flags: "-Wl,-rpath,\\$ORIGIN" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{OutputFileName}.exe\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] - # Setup: [] - # Cleanup: [] - ExecutableShared: - DefaultPlatform: - Flags: "-shared -Wl,-rpath,\\$ORIGIN" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] - # Setup: [] - # Cleanup: [] - Static: - DefaultPlatform: - Flags: "" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] - # Setup: [] - # Cleanup: [] - Shared: - DefaultPlatform: - Flags: "-shared -Wl,-rpath,\\$ORIGIN" - Executable: "g++" - RunParts: - - Type: Once - CommandPart: "{Executable} {LinkFlags} -o \"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}\"" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] - # Setup: [] - # Cleanup: [] +``` -# https://learn.microsoft.com/en-us/cpp/overview/compiler-versions?view=msvc-170 -- Name: "vs2022_v17+" - NameAliases: ["msvc1930+", "msvc"] - Languages: ["c++"] - FileExtensions: [.cpp, .cc, .cxx] - FilesTypes: *CommonFilesTypes - Setup: - Windows: - - >- - for /f "usebackq tokens=*" %i in (`CALL "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" - -version "[17.0,18.0)" -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) do ( - echo "%i\VC\Auxiliary\Build\vcvarsall.bat" x64 > .\prerun.bat - ) - Cleanup: - Windows: [ "del .\\prerun.bat" ] - Compiler: - PreRun: - Windows: ".\\prerun.bat" - CheckExistence: - Windows: "where.exe CL.exe" - CompileTypes: - Executable: - Windows: - <<: *vs2022_v17+_CompileFlags - Executable: "CL.exe" - RunParts: *vs2022_v17+_CompileRunParts - ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles - ExecutableShared: - Windows: - <<: *vs2022_v17+_CompileFlags - Executable: "CL.exe" - RunParts: *vs2022_v17+_CompileRunParts - ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles - Static: - Windows: - <<: *vs2022_v17+_CompileFlags - Executable: "CL.exe" - RunParts: *vs2022_v17+_CompileRunParts - ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles - Shared: - Windows: - <<: *vs2022_v17+_CompileFlags - Executable: "CL.exe" - RunParts: *vs2022_v17+_CompileRunParts - ExpectedOutputFiles: *vs2022_v17+_CompileExpectedOutputFiles - Linker: - PreRun: - Windows: ".\\prerun.bat" - CheckExistence: - Windows: "where.exe link.exe" - LinkTypes: - Executable: - Windows: - Flags: >- - /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib - oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE - /DEBUG /MANIFESTUAC:"level='asInvoker'" - Executable: "link.exe" - RunParts: - - Type: Once - CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{OutputFileName}.exe" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{OutputFileName}.exe"] - ExecutableShared: - Windows: - Flags: >- - /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib - oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE - /DEBUG /DLL /MANIFESTUAC:"level='asInvoker'" - Executable: "link.exe" - RunParts: - - Type: Once - CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" - /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" - /DEF:".\temp.def" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] - Setup: [ "echo EXPORTS > .\\temp.def", "echo. main @1 >> .\\temp.def" ] - Cleanup: [ "del .\\temp.def" ] - Static: - Windows: - Flags: "/NOLOGO" - Executable: "lib.exe" - RunParts: - - Type: Once - CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}" - /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{StaticLinkFile.Prefix}{OutputFileName}{StaticLinkFile.Extension}"] - Shared: - Windows: - Flags: >- - /NOLOGO kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib - oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /manifest:embed /SUBSYSTEM:CONSOLE - /DEBUG /DLL /MANIFESTUAC:"level='asInvoker'" - Executable: "link.exe" - RunParts: - - Type: Once - CommandPart: >- - {Executable} {LinkFlags} - /OUT:"{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}" - /IMPLIB:"{OutputFileDirectory}{/}{SharedLinkFile.Prefix}{OutputFileName}{SharedLinkFile.Extension}" - - Type: Repeats - CommandPart: " \"{LinkFilePath}\"" - ExpectedOutputFiles: ["{OutputFileDirectory}{/}{SharedLibraryFile.Prefix}{OutputFileName}{SharedLibraryFile.Extension}"] +## `Default/CommonFileTypes.yaml` +```yaml +# DO NOT modify this file. Changes will be overwritten when there's a reset or update +FilesTypes: + # The file properties for the files to be **linked** as object file for each platform + ObjectLinkFile: + Prefix: + DefaultPlatform: "" + Extension: + Windows: ".obj" + Unix: ".o" + # The file properties for the files to be **linked** as shared libraries for each platform + SharedLinkFile: + Prefix: + Windows: "" + Linux: "lib" + MacOS: "" + Extension: + Windows: ".lib" + Linux: ".so" + MacOS: ".dylib" + # The file properties for the files to be **copied** as shared libraries for each platform + SharedLibraryFile: + Prefix: + Windows: "" + Linux: "lib" + MacOS: "" + Extension: + Windows: ".dll" + Linux: ".so" + MacOS: ".dylib" + # The file properties for the files to be linked as static libraries for each platform + StaticLinkFile: + Prefix: + Unix: "lib" + Windows: "" + Extension: + Windows: ".lib" + Unix: ".a" + # (Optional) The file properties for debug symbols to be copied alongside the binary + # for each platform + DebugSymbolFile: + Prefix: + Windows: "" + Unix: "" + Extension: + Windows: ".pdb" + Unix: "" ``` From 260963dbb263dc85ef04eeed61f7e5946d033d88 Mon Sep 17 00:00:00 2001 From: Neko Box Coder Date: Sun, 4 May 2025 00:01:28 +0100 Subject: [PATCH 5/5] Allowing profile import to either be a single path or a list of paths --- DefaultYAMLs/Default/g++.yaml | 4 +- Src/Tests/ConfigParsingTest.cpp | 117 +++++++++++++++++++++++--------- Src/runcpp2/ConfigParsing.cpp | 55 ++++++++++++--- 3 files changed, 132 insertions(+), 44 deletions(-) diff --git a/DefaultYAMLs/Default/g++.yaml b/DefaultYAMLs/Default/g++.yaml index 613f759..bc1037e 100644 --- a/DefaultYAMLs/Default/g++.yaml +++ b/DefaultYAMLs/Default/g++.yaml @@ -43,7 +43,9 @@ Languages: ["c++"] # See "./CommonFileTypes.yaml" for FilesTypes # FilesTypes: ... -# We can use the "Import" field to import other yaml files. We are importing "FilesTypes" here +# (Optional) We can use the "Import" field to import other yaml files. We are importing "FilesTypes" here. +# Import can either be a single path or a list of paths. +# All the fields in the imported yaml files will be merged together Import: "./CommonFileTypes.yaml" # Specify the compiler settings diff --git a/Src/Tests/ConfigParsingTest.cpp b/Src/Tests/ConfigParsingTest.cpp index 10bdffe..22995cf 100644 --- a/Src/Tests/ConfigParsingTest.cpp +++ b/Src/Tests/ConfigParsingTest.cpp @@ -301,7 +301,8 @@ int main(int argc, char** argv) const char* mainConfigYamlStr = R"( PreferredProfile: "imported-profile" Profiles: - - Import: "Default/g++.yaml" + - Import: ["Default/gcc.yaml", "Default/gccCompilerLinker.yaml"] + - Name: "second-profile" FileExtensions: [.cpp, .cc, .cxx] Languages: ["c++"] @@ -334,12 +335,15 @@ int main(int argc, char** argv) LinkTypes: *TypeInfoEntries )"; - const char* importedProfileYamlStr = R"( + const char* importedGccProfileYamlStr = R"( Name: "imported-profile" - NameAliases: ["gcc"] + NameAliases: ["g++"] FileExtensions: [.cpp, .cc] Languages: ["c++"] Import: "filetypes.yaml" + )"; + + const char* importedCompilerLinkerYamlStr = R"( Compiler: CheckExistence: DefaultPlatform: "imported-gcc -v" @@ -387,80 +391,124 @@ int main(int argc, char** argv) .ReturnsResult(); //Setup filesystem exist for the import yaml files - std::string firstExpectedImportPath = "some/config/dir/Default/g++.yaml"; - std::string secondExpectedImportPath = "some/config/dir/Default/filetypes.yaml"; + std::string gccExpectedImportPath = "some/config/dir/Default/gcc.yaml"; + std::string filetypesExpectedImportPath = "some/config/dir/Default/filetypes.yaml"; + std::string gccCompilerLinkerExpectedImportPath = + "some/config/dir/Default/gccCompilerLinker.yaml"; - std::shared_ptr firstImportFileExistResult = + std::shared_ptr gccImportFileExistResult = CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) .WhenCalledWith( firstExpectedImportPath, + CO_ANY_TYPE>( gccExpectedImportPath, CO_ANY) .Returns(true) .ReturnsResult(); - std::shared_ptr secondImportFileExistResult = + std::shared_ptr filetypesImportFileExistResult = CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) .WhenCalledWith( secondExpectedImportPath, + CO_ANY_TYPE>( filetypesExpectedImportPath, CO_ANY) .Returns(true) .ReturnsResult(); + std::shared_ptr gccCompilerLinkerImportFileExistResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_exists) + .WhenCalledWith + < + const std::string&, + CO_ANY_TYPE + > + ( + gccCompilerLinkerExpectedImportPath, + CO_ANY + ) + .Returns(true) + .ReturnsResult(); //Record if there's an ifstream created with import paths - void* firstImportIfstreamInstance = nullptr; - void* secondImportIfstreamInstance = nullptr; - std::shared_ptr firstImportedFileStreamResult = + void* gccImportIfstreamInstance = nullptr; + void* filetypesImportIfstreamInstance = nullptr; + void* gccCompilerLinkerImportIfstreamInstance = nullptr; + std::shared_ptr gccImportedFileStreamResult = + CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) + .WhenCalledWith + (gccExpectedImportPath) + .Times(1) + .WhenCalledExpectedly_Do + ( + [&gccImportIfstreamInstance] + (void* instance, const std::vector&) + { + gccImportIfstreamInstance = instance; + } + ) + .ReturnsResult(); + std::shared_ptr filetypesImportedFileStreamResult = CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) .WhenCalledWith - (firstExpectedImportPath) + (filetypesExpectedImportPath) .Times(1) .WhenCalledExpectedly_Do ( - [&firstImportIfstreamInstance] + [&filetypesImportIfstreamInstance] (void* instance, const std::vector&) { - firstImportIfstreamInstance = instance; + filetypesImportIfstreamInstance = instance; } ) .ReturnsResult(); - std::shared_ptr secondImportedFileStreamResult = + std::shared_ptr gccCompilerLinkerImportedFileStreamResult = CO_SETUP_OVERRIDE (OverrideInstance, Mock_ifstream) .WhenCalledWith - (secondExpectedImportPath) + (gccCompilerLinkerExpectedImportPath) .Times(1) .WhenCalledExpectedly_Do ( - [&secondImportIfstreamInstance] + [&gccCompilerLinkerImportIfstreamInstance] (void* instance, const std::vector&) { - secondImportIfstreamInstance = instance; + gccCompilerLinkerImportIfstreamInstance = instance; } ) .ReturnsResult(); //Mock for rdbuf call with specific path check for import files - std::shared_ptr firstImportedFileRdbufResult = + std::shared_ptr gccImportedFileRdbufResult = CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) - .Returns(importedProfileYamlStr) + .Returns(importedGccProfileYamlStr) .Times(1) .If ( - [&firstImportIfstreamInstance] + [&gccImportIfstreamInstance] (void* instance, const std::vector&) -> bool { - return instance == firstImportIfstreamInstance; + return instance == gccImportIfstreamInstance; } ) .ReturnsResult(); - std::shared_ptr secondImportedFileRdbufResult = + std::shared_ptr filetypesImportedFileRdbufResult = CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) .Returns(importedFiletypesYamlStr) .Times(1) .If ( - [&secondImportIfstreamInstance] + [&filetypesImportIfstreamInstance] + (void* instance, const std::vector&) -> bool + { + return instance == filetypesImportIfstreamInstance; + } + ) + .ReturnsResult(); + std::shared_ptr gccCompilerLinkerImportedFileRdbufResult = + CO_SETUP_OVERRIDE (OverrideInstance, rdbuf) + .Returns(importedCompilerLinkerYamlStr) + .Times(1) + .If + ( + [&gccCompilerLinkerImportIfstreamInstance] (void* instance, const std::vector&) -> bool { - return instance == secondImportIfstreamInstance; + return instance == + gccCompilerLinkerImportIfstreamInstance; } ) .ReturnsResult(); @@ -476,14 +524,17 @@ int main(int argc, char** argv) ); commonOverrideStatusCheck(); - ssTEST_OUTPUT_ASSERT("", firstImportFileExistResult->GetSucceedCount(), 1); - ssTEST_OUTPUT_ASSERT("", secondImportFileExistResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", gccImportFileExistResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", filetypesImportFileExistResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", gccCompilerLinkerImportFileExistResult->GetSucceedCount(), 1); - ssTEST_OUTPUT_ASSERT("", firstImportedFileStreamResult->GetSucceedCount(), 1); - ssTEST_OUTPUT_ASSERT("", secondImportedFileStreamResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", gccImportedFileStreamResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", filetypesImportedFileStreamResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", gccCompilerLinkerImportedFileStreamResult->GetSucceedCount(), 1); - ssTEST_OUTPUT_ASSERT("", firstImportedFileRdbufResult->GetSucceedCount(), 1); - ssTEST_OUTPUT_ASSERT("", secondImportedFileRdbufResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", gccImportedFileRdbufResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", filetypesImportedFileRdbufResult->GetSucceedCount(), 1); + ssTEST_OUTPUT_ASSERT("", gccCompilerLinkerImportedFileRdbufResult->GetSucceedCount(), 1); ssTEST_OUTPUT_ASSERT("ReadUserConfig should succeed", parseResult); ssTEST_OUTPUT_ASSERT("Should parse 2 profiles (1 imported + 1 inline)", profiles.size(), 2); @@ -503,7 +554,7 @@ int main(int argc, char** argv) "file-prefix"); ssTEST_OUTPUT_ASSERT( "First profile should have correct name aliases", profiles[0].NameAliases.size() == 1 && - profiles[0].NameAliases.find("gcc") != + profiles[0].NameAliases.find("g++") != profiles[0].NameAliases.end()); ssTEST_OUTPUT_ASSERT( "PreferredProfile should match the imported profile", preferredProfile, diff --git a/Src/runcpp2/ConfigParsing.cpp b/Src/runcpp2/ConfigParsing.cpp index 2556b43..3afe062 100644 --- a/Src/runcpp2/ConfigParsing.cpp +++ b/Src/runcpp2/ConfigParsing.cpp @@ -35,19 +35,51 @@ namespace ssLOG_FUNC_INFO(); ghc::filesystem::path currentImportFilePath = configPath; - while(runcpp2::ExistAndHasChild(currentProfileNode, "Import")) + std::stack pathsToImport; + while(runcpp2::ExistAndHasChild(currentProfileNode, "Import") || !pathsToImport.empty()) { - if(!INTERNAL_RUNCPP2_BIT_CONTANTS( currentProfileNode["Import"].type().type, - ryml::NodeType_e::KEYVAL)) + //If we import field, we should deal with it instead + if(runcpp2::ExistAndHasChild(currentProfileNode, "Import")) { - ssLOG_ERROR("Import must be a path to a YAML file"); - return false; + const ryml::NodeType_e importNodeType = currentProfileNode["Import"].type().type; + if( !INTERNAL_RUNCPP2_BIT_CONTANTS(importNodeType, ryml::NodeType_e::KEYVAL) && + !INTERNAL_RUNCPP2_BIT_CONTANTS(importNodeType, ryml::NodeType_e::SEQ)) + { + ssLOG_ERROR("Import must be a path or sequence of paths of YAML file(s)"); + return false; + } + + ghc::filesystem::path currentImportDir = currentImportFilePath; + currentImportDir = currentImportDir.parent_path(); + if(currentProfileNode["Import"].is_keyval()) + { + pathsToImport.push( currentImportDir / + runcpp2::GetValue(currentProfileNode["Import"])); + } + else + { + if(currentProfileNode["Import"].num_children() == 0) + { + ssLOG_ERROR("An import sequence cannot be an empty"); + return false; + } + + for(int i = 0; i < currentProfileNode["Import"].num_children(); ++i) + { + if(!currentProfileNode["Import"][i].is_val()) + { + ssLOG_ERROR("It must be a sequence of paths"); + return false; + } + + pathsToImport.push( currentImportDir / + runcpp2::GetValue(currentProfileNode["Import"][i])); + } + } } - ghc::filesystem::path currentImportDir = currentImportFilePath; - currentImportDir = currentImportDir.parent_path(); - currentImportFilePath = - currentImportDir / runcpp2::GetValue(currentProfileNode["Import"]); + currentImportFilePath = pathsToImport.top(); + pathsToImport.pop(); std::error_code ec; if(!ghc::filesystem::exists(currentImportFilePath, ec)) @@ -77,7 +109,10 @@ namespace //Replace the current import field if the import profile has an import field if(runcpp2::ExistAndHasChild(importProfileNode, "Import")) - currentProfileNode["Import"] << runcpp2::GetValue(importProfileNode["Import"]); + { + currentProfileNode.remove_child("Import"); + importProfileNode["Import"].duplicate(currentProfileNode, {}); + } //Otherwise, remove the current import field else currentProfileNode.remove_child("Import");