diff --git a/.gitmodules b/.gitmodules index 98e24794..cd2562f2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "Dependencies/openssl"] path = Dependencies/openssl url = https://github.com/openssl/openssl.git +[submodule "Dependencies/Opal"] + path = Dependencies/Opal + url = https://github.com/mwasplund/Opal.git diff --git a/Dependencies/Opal b/Dependencies/Opal new file mode 160000 index 00000000..6597368c --- /dev/null +++ b/Dependencies/Opal @@ -0,0 +1 @@ +Subproject commit 6597368c88df75ad852d41d03deb2e42a0c3cce2 diff --git a/Dependencies/cpp-httplib b/Dependencies/cpp-httplib index 53de8210..4199e5b5 160000 --- a/Dependencies/cpp-httplib +++ b/Dependencies/cpp-httplib @@ -1 +1 @@ -Subproject commit 53de8210c9441ab99350f4f4d3d4125b629928c5 +Subproject commit 4199e5b5100f697a1d876bb58165981c7f9ab80c diff --git a/Docs/Samples.md b/Docs/Samples.md index bf1a3c57..d51c1e43 100644 --- a/Docs/Samples.md +++ b/Docs/Samples.md @@ -1,161 +1,11 @@ # Samples These samples are a small set of all the cool things you can do with the Soup Build System. The source for these samples can be found in the main Soup repository in the Samples folder. -## Simple Console Application - +## [Simple Console Application](Samples/SimpleConsoleApplication) This is the smallest amount of code to get a console application building using Soup. -### Recipe.toml -The Recipe file that sets the name, type, version and the single source file. -``` -Name = "SimpleConsoleApplication" -Type = "Executable" -Version = "1.1.3" -Source = [ - "Main.cpp" -] -``` - -### Main.cpp -A simple main method that prints our "Hello World, Soup Style!" and returns a success status. -``` -#include - -int main() -{ - std::cout << "Hello World, Soup Style!" << std::endl; - return 0; -} -``` - -### .gitignore -A simple git ignore file to exclude all Soup build output. -``` -out/ -``` - -## Module Console Application - +## [Module Console Application](Samples/ModuleConsoleApplication) This is a console application that uses a single module interface file used inside the same projects. -### Recipe.toml -The Recipe file that sets the name, type, version, the public interface module and the single source file. -``` -Name = "ModuleConsoleApplication" -Type = "Executable" -Version = "1.2.5" -Public = "Module.cpp" -Source = [ - "Main.cpp" -] -``` - -### Module.cpp -A module interface file that exports a single sample class. -``` -module; - -// Include all standard library headers in the global module -#include - -export module ModuleConsoleApplication; - -export class Helper -{ -public: - static std::string GetName() - { - return "Soup"; - } -}; -``` - -### Main.cpp -A simple main method that prints our "Hello World, Soup Style!" by using the module from the previous file. -``` -#include - -import ModuleConsoleApplication; - -int main() -{ - std::cout << "Hello World, " << Helper::GetName() << " Style!" << std::endl; - return 0; -} -``` - -### .gitignore -A simple git ignore file to exclude all Soup build output. -``` -out/ -``` - -## Static Library Reference - +## [Static Library Reference](Samples/StaticLibraryReference) This is a console application that has a single static library dependency. - -### MyLibrary/Recipe.toml -The Recipe file that defines the static library "MyLibrary". -``` -Name = "MyLibrary" -Version = "1.0.0" -Public = "Module.cpp" -``` - -### MyLibrary/Module.cpp -A module interface file that exports a single sample class. -``` -module; - -// Include all standard library headers in the global module -#include - -export module MyLibrary; - -export namespace MyLibrary -{ - class Helper - { - public: - static std::string GetName() - { - return "Soup"; - } - }; -} -``` - -### MyApplication/Recipe.toml -The Recipe file that defines the executable "MyApplication". -``` -Name = "MyApplication" -Type = "Executable" -Version = "1.0.0" -Dependencies = [ - "../MyLibrary/" -] -Source = [ - "Main.cpp" -] -``` - -### MyApplication/Main.cpp -A simple main method that prints our "Hello World, Soup Style!" by using the module from the library. -``` -#include - -import MyLibrary; -using namespace MyLibrary; - -int main() -{ - std::cout << "Hello World, " << Helper::GetName() << " Style!" << std::endl; - return 0; -} -``` - -### .gitignore -A simple git ignore file to exclude all Soup build output. -``` -out/ -``` diff --git a/Docs/Samples/ModuleConsoleApplication.md b/Docs/Samples/ModuleConsoleApplication.md new file mode 100644 index 00000000..bbdec128 --- /dev/null +++ b/Docs/Samples/ModuleConsoleApplication.md @@ -0,0 +1,54 @@ +# Module Console Application +This is a console application that uses a single module interface file used inside the same projects. + +## Recipe.toml +The Recipe file that sets the name, type, version, the public interface module and the single source file. +``` +Name = "ModuleConsoleApplication" +Type = "Executable" +Version = "1.2.5" +Public = "Module.cpp" +Source = [ + "Main.cpp" +] +``` + +## Module.cpp +A module interface file that exports a single sample class. +``` +module; + +// Include all standard library headers in the global module +#include + +export module ModuleConsoleApplication; + +export class Helper +{ +public: + static std::string GetName() + { + return "Soup"; + } +}; +``` + +## Main.cpp +A simple main method that prints our "Hello World, Soup Style!" by using the module from the previous file. +``` +#include + +import ModuleConsoleApplication; + +int main() +{ + std::cout << "Hello World, " << Helper::GetName() << " Style!" << std::endl; + return 0; +} +``` + +## .gitignore +A simple git ignore file to exclude all Soup build output. +``` +out/ +``` \ No newline at end of file diff --git a/Docs/Samples/SimpleConsoleApplication.md b/Docs/Samples/SimpleConsoleApplication.md new file mode 100644 index 00000000..b2eb4be8 --- /dev/null +++ b/Docs/Samples/SimpleConsoleApplication.md @@ -0,0 +1,31 @@ +# Simple Console Application +This is the smallest amount of code to get a console application building using Soup. + +## Recipe.toml +The Recipe file that sets the name, type, version and the single source file. +``` +Name = "SimpleConsoleApplication" +Type = "Executable" +Version = "1.1.3" +Source = [ + "Main.cpp" +] +``` + +## Main.cpp +A simple main method that prints our "Hello World, Soup Style!" and returns a success status. +``` +#include + +int main() +{ + std::cout << "Hello World, Soup Style!" << std::endl; + return 0; +} +``` + +## .gitignore +A simple git ignore file to exclude all Soup build output. +``` +out/ +``` \ No newline at end of file diff --git a/Docs/Samples/StaticLibraryReference.md b/Docs/Samples/StaticLibraryReference.md new file mode 100644 index 00000000..3daa7e43 --- /dev/null +++ b/Docs/Samples/StaticLibraryReference.md @@ -0,0 +1,68 @@ +# Static Library Reference +This is a console application that has a single static library dependency. + +## MyLibrary/Recipe.toml +The Recipe file that defines the static library "MyLibrary". +``` +Name = "MyLibrary" +Version = "1.0.0" +Public = "Module.cpp" +``` + +## MyLibrary/Module.cpp +A module interface file that exports a single sample class. +``` +module; + +// Include all standard library headers in the global module +#include + +export module MyLibrary; + +export namespace MyLibrary +{ + class Helper + { + public: + static std::string GetName() + { + return "Soup"; + } + }; +} +``` + +## MyApplication/Recipe.toml +The Recipe file that defines the executable "MyApplication". +``` +Name = "MyApplication" +Type = "Executable" +Version = "1.0.0" +Dependencies = [ + "../MyLibrary/" +] +Source = [ + "Main.cpp" +] +``` + +## MyApplication/Main.cpp +A simple main method that prints our "Hello World, Soup Style!" by using the module from the library. +``` +#include + +import MyLibrary; +using namespace MyLibrary; + +int main() +{ + std::cout << "Hello World, " << Helper::GetName() << " Style!" << std::endl; + return 0; +} +``` + +## .gitignore +A simple git ignore file to exclude all Soup build output. +``` +out/ +``` diff --git a/Scripts/alltest.cmd b/Scripts/alltest.cmd index 87948e94..1c93351c 100644 --- a/Scripts/alltest.cmd +++ b/Scripts/alltest.cmd @@ -2,17 +2,27 @@ SET ScriptsDir=%~dp0 SET SourceDir=%ScriptsDir%..\Source\ -pushd %SourceDir%\Compiler\Clang.UnitTests\ +pushd %SourceDir%\Build\Extensions.UnitTests\ call soup build call soup run popd -pushd %SourceDir%\Compiler\MSVC.UnitTests\ +pushd %SourceDir%\Extensions\Compiler\Core.UnitTests\ call soup build call soup run popd -pushd %SourceDir%\Core.UnitTests\ +pushd %SourceDir%\Extensions\Compiler\Clang.UnitTests\ +call soup build +call soup run +popd + +pushd %SourceDir%\Extensions\Compiler\MSVC.UnitTests\ +call soup build +call soup run +popd + +pushd %SourceDir%\Client\Core.UnitTests\ call soup build call soup run popd \ No newline at end of file diff --git a/Scripts/soup.cmd b/Scripts/soup.cmd index 3bce3575..9105dc05 100644 --- a/Scripts/soup.cmd +++ b/Scripts/soup.cmd @@ -1,6 +1,6 @@ @echo off SET ScriptsDir=%~dp0 -SET ClientDir=%ScriptsDir%..\Source\Client +SET ClientDir=%ScriptsDir%..\Source\Client\CLI SET OutDir=%ClientDir%\out SET BinaryDir=%OutDir%\bin SET RunDir=%OutDir%\run diff --git a/Scripts/soupd.cmd b/Scripts/soupd.cmd index e3338625..dae382b2 100644 --- a/Scripts/soupd.cmd +++ b/Scripts/soupd.cmd @@ -1,6 +1,6 @@ @echo off SET ScriptsDir=%~dp0 -SET ClientDir=%ScriptsDir%..\Source\Client +SET ClientDir=%ScriptsDir%..\Source\Client\CLI SET OutDir=%ClientDir%\out SET BinaryDir=%OutDir%\bin SET RunDir=%OutDir%\run diff --git a/Source/Engine/Definition/IBuildState.h b/Source/Build/Core/IBuildState.h similarity index 100% rename from Source/Engine/Definition/IBuildState.h rename to Source/Build/Core/IBuildState.h diff --git a/Source/Engine/Definition/IBuildSystem.h b/Source/Build/Core/IBuildSystem.h similarity index 100% rename from Source/Engine/Definition/IBuildSystem.h rename to Source/Build/Core/IBuildSystem.h diff --git a/Source/Engine/Definition/IBuildTask.h b/Source/Build/Core/IBuildTask.h similarity index 81% rename from Source/Engine/Definition/IBuildTask.h rename to Source/Build/Core/IBuildTask.h index 4fef0584..390c0b37 100644 --- a/Source/Engine/Definition/IBuildTask.h +++ b/Source/Build/Core/IBuildTask.h @@ -17,6 +17,9 @@ namespace Soup::Build { public: virtual const char* GetName() const noexcept = 0; + virtual IList& GetRunBeforeList() noexcept = 0; + virtual IList& GetRunAfterList() noexcept = 0; + virtual OperationResult Execute(IBuildState& state) noexcept = 0; }; } diff --git a/Source/Engine/Definition/IGraphNode.h b/Source/Build/Core/IGraphNode.h similarity index 100% rename from Source/Engine/Definition/IGraphNode.h rename to Source/Build/Core/IGraphNode.h diff --git a/Source/Engine/Definition/IList.h b/Source/Build/Core/IList.h similarity index 100% rename from Source/Engine/Definition/IList.h rename to Source/Build/Core/IList.h diff --git a/Source/Engine/Definition/IValue.h b/Source/Build/Core/IValue.h similarity index 100% rename from Source/Engine/Definition/IValue.h rename to Source/Build/Core/IValue.h diff --git a/Source/Engine/Definition/IValueList.h b/Source/Build/Core/IValueList.h similarity index 100% rename from Source/Engine/Definition/IValueList.h rename to Source/Build/Core/IValueList.h diff --git a/Source/Engine/Definition/IValuePrimitive.h b/Source/Build/Core/IValuePrimitive.h similarity index 100% rename from Source/Engine/Definition/IValuePrimitive.h rename to Source/Build/Core/IValuePrimitive.h diff --git a/Source/Engine/Definition/IValueTable.h b/Source/Build/Core/IValueTable.h similarity index 100% rename from Source/Engine/Definition/IValueTable.h rename to Source/Build/Core/IValueTable.h diff --git a/Source/Engine/Definition/Module.cpp b/Source/Build/Core/Module.cpp similarity index 81% rename from Source/Engine/Definition/Module.cpp rename to Source/Build/Core/Module.cpp index bf19b3ce..57c19c14 100644 --- a/Source/Engine/Definition/Module.cpp +++ b/Source/Build/Core/Module.cpp @@ -2,7 +2,7 @@ #include -export module SoupEngineDefinition; +export module Soup.Build; import Opal; using namespace Opal; diff --git a/Source/Engine/Definition/OperationResult.h b/Source/Build/Core/OperationResult.h similarity index 100% rename from Source/Engine/Definition/OperationResult.h rename to Source/Build/Core/OperationResult.h diff --git a/Source/Build/Core/Recipe.toml b/Source/Build/Core/Recipe.toml new file mode 100644 index 00000000..8b2295c1 --- /dev/null +++ b/Source/Build/Core/Recipe.toml @@ -0,0 +1,8 @@ +Name = "Soup.Build" +Version = "0.2.0" +Dependencies = [ + # "../../../Dependencies/Opal/Source/", + "Opal@0.1.1", +] + +Public = "Module.cpp" diff --git a/Source/Build/Extensions.UnitTests/Recipe.toml b/Source/Build/Extensions.UnitTests/Recipe.toml new file mode 100644 index 00000000..facc6ac8 --- /dev/null +++ b/Source/Build/Extensions.UnitTests/Recipe.toml @@ -0,0 +1,14 @@ +Name = "SoupBuildExtensionsUnitTests" +Version = "1.0.0" +Type = "Executable" +Dependencies = [ + "../Extensions/", + "../../TestUtilities/", + "SoupTest@0.1.0", +] +Source = [ + "gen/Main.cpp" +] +IncludePaths = [ + "./", +] diff --git a/Source/Core.UnitTests/Package/RecipeLanguageVersionTests.h b/Source/Build/Extensions.UnitTests/RecipeLanguageVersionTests.h similarity index 96% rename from Source/Core.UnitTests/Package/RecipeLanguageVersionTests.h rename to Source/Build/Extensions.UnitTests/RecipeLanguageVersionTests.h index 351523a9..82e17f75 100644 --- a/Source/Core.UnitTests/Package/RecipeLanguageVersionTests.h +++ b/Source/Build/Extensions.UnitTests/RecipeLanguageVersionTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::UnitTests +namespace Soup::Build::Extensions::UnitTests { class RecipeLanguageVersionTests { diff --git a/Source/Core.UnitTests/Package/RecipeTypeTests.h b/Source/Build/Extensions.UnitTests/RecipeTypeTests.h similarity index 95% rename from Source/Core.UnitTests/Package/RecipeTypeTests.h rename to Source/Build/Extensions.UnitTests/RecipeTypeTests.h index 7720efc8..05d1ed2a 100644 --- a/Source/Core.UnitTests/Package/RecipeTypeTests.h +++ b/Source/Build/Extensions.UnitTests/RecipeTypeTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::UnitTests +namespace Soup::Build::Extensions::UnitTests { class RecipeTypeTests { diff --git a/Source/Build/Extensions.UnitTests/gen/Main.cpp b/Source/Build/Extensions.UnitTests/gen/Main.cpp new file mode 100644 index 00000000..aa40258a --- /dev/null +++ b/Source/Build/Extensions.UnitTests/gen/Main.cpp @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include +#include + +import Opal; +import Soup.Build.Extensions; +import json11; +import SoupTest; +import SoupTestUtilities; + +using namespace Opal; +using namespace Opal::System; +using namespace SoupTest; + +#include "RecipeLanguageVersionTests.gen.h" +#include "RecipeTypeTests.gen.h" + +int main() +{ + std::cout << "Running Tests..." << std::endl; + + TestState state = { 0, 0 }; + + state += RunRecipeLanguageVersionTests(); + state += RunRecipeTypeTests(); + + std::cout << state.PassCount << " PASSED." << std::endl; + std::cout << state.FailCount << " FAILED." << std::endl; + + return 0; +} diff --git a/Source/Core.UnitTests/gen/Package/RecipeLanguageVersionTests.gen.h b/Source/Build/Extensions.UnitTests/gen/RecipeLanguageVersionTests.gen.h similarity index 60% rename from Source/Core.UnitTests/gen/Package/RecipeLanguageVersionTests.gen.h rename to Source/Build/Extensions.UnitTests/gen/RecipeLanguageVersionTests.gen.h index 4d6f7681..d91f4dfc 100644 --- a/Source/Core.UnitTests/gen/Package/RecipeLanguageVersionTests.gen.h +++ b/Source/Build/Extensions.UnitTests/gen/RecipeLanguageVersionTests.gen.h @@ -1,19 +1,19 @@ #pragma once -#include "Package/RecipeLanguageVersionTests.h" +#include "RecipeLanguageVersionTests.h" TestState RunRecipeLanguageVersionTests() { auto className = "RecipeLanguageVersionTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP11, \"C++11\")", [&testClass]() { testClass->ToStringValues(Soup::RecipeLanguageVersion::CPP11, "C++11"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP14, \"C++14\")", [&testClass]() { testClass->ToStringValues(Soup::RecipeLanguageVersion::CPP14, "C++14"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP17, \"C++17\")", [&testClass]() { testClass->ToStringValues(Soup::RecipeLanguageVersion::CPP17, "C++17"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP20, \"C++17\")", [&testClass]() { testClass->ToStringValues(Soup::RecipeLanguageVersion::CPP20, "C++20"); }); - state += SoupTest::RunTest(className, "ParseValues(\"C++11\", Soup::RecipeLanguageVersion::CPP11)", [&testClass]() { testClass->ParseValues("C++11", Soup::RecipeLanguageVersion::CPP11); }); - state += SoupTest::RunTest(className, "ParseValues(\"C++14\", Soup::RecipeLanguageVersion::CPP14)", [&testClass]() { testClass->ParseValues("C++14", Soup::RecipeLanguageVersion::CPP14); }); - state += SoupTest::RunTest(className, "ParseValues(\"C++17\", Soup::RecipeLanguageVersion::CPP17)", [&testClass]() { testClass->ParseValues("C++17", Soup::RecipeLanguageVersion::CPP17); }); - state += SoupTest::RunTest(className, "ParseValues(\"C++20\", Soup::RecipeLanguageVersion::CPP20)", [&testClass]() { testClass->ParseValues("C++20", Soup::RecipeLanguageVersion::CPP20); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP11, \"C++11\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeLanguageVersion::CPP11, "C++11"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP14, \"C++14\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeLanguageVersion::CPP14, "C++14"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP17, \"C++17\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeLanguageVersion::CPP17, "C++17"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeLanguageVersion::CPP20, \"C++17\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeLanguageVersion::CPP20, "C++20"); }); + state += SoupTest::RunTest(className, "ParseValues(\"C++11\", Soup::RecipeLanguageVersion::CPP11)", [&testClass]() { testClass->ParseValues("C++11", Soup::Build::Extensions::RecipeLanguageVersion::CPP11); }); + state += SoupTest::RunTest(className, "ParseValues(\"C++14\", Soup::RecipeLanguageVersion::CPP14)", [&testClass]() { testClass->ParseValues("C++14", Soup::Build::Extensions::RecipeLanguageVersion::CPP14); }); + state += SoupTest::RunTest(className, "ParseValues(\"C++17\", Soup::RecipeLanguageVersion::CPP17)", [&testClass]() { testClass->ParseValues("C++17", Soup::Build::Extensions::RecipeLanguageVersion::CPP17); }); + state += SoupTest::RunTest(className, "ParseValues(\"C++20\", Soup::RecipeLanguageVersion::CPP20)", [&testClass]() { testClass->ParseValues("C++20", Soup::Build::Extensions::RecipeLanguageVersion::CPP20); }); state += SoupTest::RunTest(className, "ParseGarbageThrows", [&testClass]() { testClass->ParseGarbageThrows(); }); return state; diff --git a/Source/Core.UnitTests/gen/Package/RecipeTypeTests.gen.h b/Source/Build/Extensions.UnitTests/gen/RecipeTypeTests.gen.h similarity index 59% rename from Source/Core.UnitTests/gen/Package/RecipeTypeTests.gen.h rename to Source/Build/Extensions.UnitTests/gen/RecipeTypeTests.gen.h index 181d42e8..cb1c24dd 100644 --- a/Source/Core.UnitTests/gen/Package/RecipeTypeTests.gen.h +++ b/Source/Build/Extensions.UnitTests/gen/RecipeTypeTests.gen.h @@ -1,17 +1,17 @@ #pragma once -#include "Package/RecipeTypeTests.h" +#include "RecipeTypeTests.h" TestState RunRecipeTypeTests() { auto className = "RecipeTypeTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::Executable, \"Executable\")", [&testClass]() { testClass->ToStringValues(Soup::RecipeType::Executable, "Executable"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::StaticLibrary, \"StaticLibrary\")", [&testClass]() { testClass->ToStringValues(Soup::RecipeType::StaticLibrary, "StaticLibrary"); }); - state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::DynamicLibrary, \"DynamicLibrary\")", [&testClass]() { testClass->ToStringValues(Soup::RecipeType::DynamicLibrary, "DynamicLibrary"); }); - state += SoupTest::RunTest(className, "ParseValues(\"Executable\", Soup::RecipeType::Executable)", [&testClass]() { testClass->ParseValues("Executable", Soup::RecipeType::Executable); }); - state += SoupTest::RunTest(className, "ParseValues(\"StaticLibrary\", Soup::RecipeType::StaticLibrary)", [&testClass]() { testClass->ParseValues("StaticLibrary", Soup::RecipeType::StaticLibrary); }); - state += SoupTest::RunTest(className, "ParseValues(\"DynamicLibrary\", Soup::RecipeType::DynamicLibrary)", [&testClass]() { testClass->ParseValues("DynamicLibrary", Soup::RecipeType::DynamicLibrary); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::Executable, \"Executable\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeType::Executable, "Executable"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::StaticLibrary, \"StaticLibrary\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeType::StaticLibrary, "StaticLibrary"); }); + state += SoupTest::RunTest(className, "ToStringValues(Soup::RecipeType::DynamicLibrary, \"DynamicLibrary\")", [&testClass]() { testClass->ToStringValues(Soup::Build::Extensions::RecipeType::DynamicLibrary, "DynamicLibrary"); }); + state += SoupTest::RunTest(className, "ParseValues(\"Executable\", Soup::RecipeType::Executable)", [&testClass]() { testClass->ParseValues("Executable", Soup::Build::Extensions::RecipeType::Executable); }); + state += SoupTest::RunTest(className, "ParseValues(\"StaticLibrary\", Soup::RecipeType::StaticLibrary)", [&testClass]() { testClass->ParseValues("StaticLibrary", Soup::Build::Extensions::RecipeType::StaticLibrary); }); + state += SoupTest::RunTest(className, "ParseValues(\"DynamicLibrary\", Soup::RecipeType::DynamicLibrary)", [&testClass]() { testClass->ParseValues("DynamicLibrary", Soup::Build::Extensions::RecipeType::DynamicLibrary); }); state += SoupTest::RunTest(className, "ParseGarbageThrows", [&testClass]() { testClass->ParseGarbageThrows(); }); return state; diff --git a/Source/Engine/Wrapper/BuildStateWrapper.h b/Source/Build/Extensions/BuildStateWrapper.h similarity index 95% rename from Source/Engine/Wrapper/BuildStateWrapper.h rename to Source/Build/Extensions/BuildStateWrapper.h index 1deee112..290caf55 100644 --- a/Source/Engine/Wrapper/BuildStateWrapper.h +++ b/Source/Build/Extensions/BuildStateWrapper.h @@ -6,7 +6,7 @@ #include "GraphNodeWrapper.h" #include "ValueTableWrapper.h" -namespace Soup::Build +namespace Soup::Build::Extensions { /// /// Build Property Bag Extension used to make the IBuildState interface more usable diff --git a/Source/Engine/Wrapper/GraphNodeExtensions.h b/Source/Build/Extensions/GraphNodeExtensions.h similarity index 94% rename from Source/Engine/Wrapper/GraphNodeExtensions.h rename to Source/Build/Extensions/GraphNodeExtensions.h index c3f479c9..d19b58dd 100644 --- a/Source/Engine/Wrapper/GraphNodeExtensions.h +++ b/Source/Build/Extensions/GraphNodeExtensions.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Extensions { /// /// Build graph node extension methods diff --git a/Source/Engine/Wrapper/GraphNodeListWrapper.cpp b/Source/Build/Extensions/GraphNodeListWrapper.cpp similarity index 93% rename from Source/Engine/Wrapper/GraphNodeListWrapper.cpp rename to Source/Build/Extensions/GraphNodeListWrapper.cpp index ce4b9411..16b8a1ec 100644 --- a/Source/Engine/Wrapper/GraphNodeListWrapper.cpp +++ b/Source/Build/Extensions/GraphNodeListWrapper.cpp @@ -9,11 +9,11 @@ module; #include #include -module SoupEngineWrapper; +module Soup.Build.Extensions; using namespace Opal; -namespace Soup::Build +namespace Soup::Build::Extensions { GraphNodeListWrapper::GraphNodeListWrapper(IList& value) : _value(value) diff --git a/Source/Engine/Wrapper/GraphNodeListWrapper.h b/Source/Build/Extensions/GraphNodeListWrapper.h similarity index 93% rename from Source/Engine/Wrapper/GraphNodeListWrapper.h rename to Source/Build/Extensions/GraphNodeListWrapper.h index b088fefb..8ddc1ffb 100644 --- a/Source/Engine/Wrapper/GraphNodeListWrapper.h +++ b/Source/Build/Extensions/GraphNodeListWrapper.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Extensions { export class GraphNodeWrapper; diff --git a/Source/Engine/Wrapper/GraphNodeWrapper.h b/Source/Build/Extensions/GraphNodeWrapper.h similarity index 94% rename from Source/Engine/Wrapper/GraphNodeWrapper.h rename to Source/Build/Extensions/GraphNodeWrapper.h index 943aea11..49eb7a49 100644 --- a/Source/Engine/Wrapper/GraphNodeWrapper.h +++ b/Source/Build/Extensions/GraphNodeWrapper.h @@ -6,7 +6,7 @@ #include "StringListWrapper.h" #include "GraphNodeListWrapper.h" -namespace Soup::Build +namespace Soup::Build::Extensions { /// /// Build Property Bag Extension used to make the IGraphNode interface more usable diff --git a/Source/Engine/Wrapper/Module.cpp b/Source/Build/Extensions/Module.cpp similarity index 66% rename from Source/Engine/Wrapper/Module.cpp rename to Source/Build/Extensions/Module.cpp index b1268414..67556010 100644 --- a/Source/Engine/Wrapper/Module.cpp +++ b/Source/Build/Extensions/Module.cpp @@ -6,9 +6,9 @@ #include #include -export module SoupEngineWrapper; +export module Soup.Build.Extensions; import Opal; -import SoupEngineDefinition; +import Soup.Build; using namespace Opal; @@ -16,3 +16,6 @@ using namespace Opal; #include "GraphNodeExtensions.h" #include "ValueListWrapper.h" #include "ValuePrimitiveWrapper.h" + +#include "RecipeLanguageVersion.h" +#include "RecipeType.h" diff --git a/Source/Build/Extensions/Recipe.toml b/Source/Build/Extensions/Recipe.toml new file mode 100644 index 00000000..15afa6b2 --- /dev/null +++ b/Source/Build/Extensions/Recipe.toml @@ -0,0 +1,14 @@ +Name = "Soup.Build.Extensions" +Version = "0.2.0" +Dependencies = [ + # "../../../Dependencies/Opal/Source/", + "../Core/", + # "Soup.Build@0.2.0", + "Opal@0.1.1", +] + +Public = "Module.cpp" +Source = [ + "GraphNodeListWrapper.cpp", + "ValueWrapper.cpp", +] diff --git a/Source/Core/Package/RecipeLanguageVersion.h b/Source/Build/Extensions/RecipeLanguageVersion.h similarity index 97% rename from Source/Core/Package/RecipeLanguageVersion.h rename to Source/Build/Extensions/RecipeLanguageVersion.h index 89f3b3b9..f76bbc62 100644 --- a/Source/Core/Package/RecipeLanguageVersion.h +++ b/Source/Build/Extensions/RecipeLanguageVersion.h @@ -2,7 +2,7 @@ // Copyright (c) Soup. All rights reserved. // -namespace Soup +namespace Soup::Build::Extensions { /// /// The enumeration of recipe language versions diff --git a/Source/Core/Package/RecipeType.h b/Source/Build/Extensions/RecipeType.h similarity index 97% rename from Source/Core/Package/RecipeType.h rename to Source/Build/Extensions/RecipeType.h index d5b81dbc..08c3b1e5 100644 --- a/Source/Core/Package/RecipeType.h +++ b/Source/Build/Extensions/RecipeType.h @@ -2,7 +2,7 @@ // Copyright (c) Soup. All rights reserved. // -namespace Soup +namespace Soup::Build::Extensions { /// /// The enumeration of recipe types diff --git a/Source/Engine/Wrapper/StringListWrapper.h b/Source/Build/Extensions/StringListWrapper.h similarity index 93% rename from Source/Engine/Wrapper/StringListWrapper.h rename to Source/Build/Extensions/StringListWrapper.h index ea29891d..62e7b58b 100644 --- a/Source/Engine/Wrapper/StringListWrapper.h +++ b/Source/Build/Extensions/StringListWrapper.h @@ -4,12 +4,12 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Extensions { /// /// Build State property list implementation, string specialization /// - class StringListWrapper + export class StringListWrapper { public: /// diff --git a/Source/Engine/Wrapper/ValueListWrapper.h b/Source/Build/Extensions/ValueListWrapper.h similarity index 94% rename from Source/Engine/Wrapper/ValueListWrapper.h rename to Source/Build/Extensions/ValueListWrapper.h index 6a695c45..37d0ab24 100644 --- a/Source/Engine/Wrapper/ValueListWrapper.h +++ b/Source/Build/Extensions/ValueListWrapper.h @@ -5,7 +5,7 @@ #pragma once #include "ValueWrapper.h" -namespace Soup::Build +namespace Soup::Build::Extensions { /// /// Build State property list implementation, string specialization diff --git a/Source/Engine/Wrapper/ValuePrimitiveWrapper.h b/Source/Build/Extensions/ValuePrimitiveWrapper.h similarity index 92% rename from Source/Engine/Wrapper/ValuePrimitiveWrapper.h rename to Source/Build/Extensions/ValuePrimitiveWrapper.h index 7ad5364e..cc50b210 100644 --- a/Source/Engine/Wrapper/ValuePrimitiveWrapper.h +++ b/Source/Build/Extensions/ValuePrimitiveWrapper.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Extensions { /// /// Build State property list implementation, string specialization diff --git a/Source/Engine/Wrapper/ValueTableWrapper.h b/Source/Build/Extensions/ValueTableWrapper.h similarity index 94% rename from Source/Engine/Wrapper/ValueTableWrapper.h rename to Source/Build/Extensions/ValueTableWrapper.h index f76b174d..39bf4f83 100644 --- a/Source/Engine/Wrapper/ValueTableWrapper.h +++ b/Source/Build/Extensions/ValueTableWrapper.h @@ -6,7 +6,7 @@ #include "ValueWrapper.h" #include "ValuePrimitiveWrapper.h" -namespace Soup::Build +namespace Soup::Build::Extensions { /// /// Build Property Table Extension used to make the IValueTable interface more usable diff --git a/Source/Engine/Wrapper/ValueWrapper.cpp b/Source/Build/Extensions/ValueWrapper.cpp similarity index 94% rename from Source/Engine/Wrapper/ValueWrapper.cpp rename to Source/Build/Extensions/ValueWrapper.cpp index 32d5230b..4092574c 100644 --- a/Source/Engine/Wrapper/ValueWrapper.cpp +++ b/Source/Build/Extensions/ValueWrapper.cpp @@ -9,11 +9,11 @@ module; #include #include -module SoupEngineWrapper; +module Soup.Build.Extensions; using namespace Opal; -namespace Soup::Build +namespace Soup::Build::Extensions { ValueWrapper::ValueWrapper(IValue& value) : diff --git a/Source/Engine/Wrapper/ValueWrapper.h b/Source/Build/Extensions/ValueWrapper.h similarity index 94% rename from Source/Engine/Wrapper/ValueWrapper.h rename to Source/Build/Extensions/ValueWrapper.h index bfff1adf..fa42203c 100644 --- a/Source/Engine/Wrapper/ValueWrapper.h +++ b/Source/Build/Extensions/ValueWrapper.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Extensions { export class ValueTableWrapper; export class ValueListWrapper; diff --git a/Source/Engine/Core/BuildGraphNode.h b/Source/Build/Runtime/BuildGraphNode.h similarity index 94% rename from Source/Engine/Core/BuildGraphNode.h rename to Source/Build/Runtime/BuildGraphNode.h index 6061c5ab..8d833f22 100644 --- a/Source/Engine/Core/BuildGraphNode.h +++ b/Source/Build/Runtime/BuildGraphNode.h @@ -6,7 +6,7 @@ #include "StringList.h" #include "BuildGraphNodeList.h" -namespace Soup::Build +namespace Soup::Build::Runtime { /// /// A graph node that represents a single operation in the build diff --git a/Source/Engine/Core/BuildGraphNodeList.cpp b/Source/Build/Runtime/BuildGraphNodeList.cpp similarity index 92% rename from Source/Engine/Core/BuildGraphNodeList.cpp rename to Source/Build/Runtime/BuildGraphNodeList.cpp index 58df3281..27ad4ca9 100644 --- a/Source/Engine/Core/BuildGraphNodeList.cpp +++ b/Source/Build/Runtime/BuildGraphNodeList.cpp @@ -11,11 +11,11 @@ module; #include #include -module SoupEngineCore; +module Soup.Build.Runtime; using namespace Opal; -namespace Soup::Build +namespace Soup::Build::Runtime { BuildGraphNodeList::BuildGraphNodeList() : _values() diff --git a/Source/Engine/Core/BuildGraphNodeList.h b/Source/Build/Runtime/BuildGraphNodeList.h similarity index 94% rename from Source/Engine/Core/BuildGraphNodeList.h rename to Source/Build/Runtime/BuildGraphNodeList.h index 69db2bf4..90f3c7a2 100644 --- a/Source/Engine/Core/BuildGraphNodeList.h +++ b/Source/Build/Runtime/BuildGraphNodeList.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Runtime { export class BuildGraphNode; diff --git a/Source/Engine/Core/BuildSimpleList.h b/Source/Build/Runtime/BuildSimpleList.h similarity index 92% rename from Source/Engine/Core/BuildSimpleList.h rename to Source/Build/Runtime/BuildSimpleList.h index 2ff88d8c..cd3075b9 100644 --- a/Source/Engine/Core/BuildSimpleList.h +++ b/Source/Build/Runtime/BuildSimpleList.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Runtime { /// /// Build list implementation for simple objects diff --git a/Source/Engine/Core/BuildState.h b/Source/Build/Runtime/BuildState.h similarity index 90% rename from Source/Engine/Core/BuildState.h rename to Source/Build/Runtime/BuildState.h index 84d58fee..a8f3901f 100644 --- a/Source/Engine/Core/BuildState.h +++ b/Source/Build/Runtime/BuildState.h @@ -6,7 +6,7 @@ #include "BuildGraphNode.h" #include "ValueTable.h" -namespace Soup::Build +namespace Soup::Build::Runtime { /// /// Build State Extension interface @@ -144,7 +144,7 @@ namespace Soup::Build /// void CombineChildState(BuildState& childState) { - CombineListState(childState._parentState, ValueTableWrapper(_activeState)); + CombineListState(childState._parentState, Extensions::ValueTableWrapper(_activeState)); } void LogActive() @@ -157,7 +157,7 @@ namespace Soup::Build /// Combine the table and list structure from the input state into the target /// Note: Ignores primitive value properties on a table /// - void CombineListState(ValueTable& input, ValueTableWrapper target) + void CombineListState(ValueTable& input, Extensions::ValueTableWrapper target) { // Enumerate over all property values // Recursively combine tables and concatenate lists @@ -176,7 +176,7 @@ namespace Soup::Build case ValueType::List: // Attempt to create the list on the target and concatenate the input target.EnsureValue(name).EnsureList().Append( - ValueListWrapper(value.AsList())); + Extensions::ValueListWrapper(value.AsList())); break; default: // Ignore all other types diff --git a/Source/Build/Runtime/BuildSystem.h b/Source/Build/Runtime/BuildSystem.h new file mode 100644 index 00000000..3e1be7f5 --- /dev/null +++ b/Source/Build/Runtime/BuildSystem.h @@ -0,0 +1,211 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once +#include "BuildState.h" + +namespace Soup::Build::Runtime +{ + class BuildTaskContainer + { + public: + BuildTaskContainer( + Memory::Reference task, + std::vector runBeforeList, + std::vector runAfterList) : + Task(std::move(task)), + RunBeforeList(std::move(runBeforeList)), + RunAfterList(std::move(runAfterList)), + HasRun(false) + { + } + + Memory::Reference Task; + std::vector RunBeforeList; + std::vector RunAfterList; + std::vector RunAfterClosureList; + bool HasRun; + }; + + /// + /// The build system implementation + /// + export class BuildSystem : public IBuildSystem + { + public: + /// + /// Initializes a new instance of the class. + /// + BuildSystem() : + _tasks() + { + } + + /// + /// Register task + /// + OperationResult RegisterTask(IBuildTask* task) noexcept override final + { + try + { + Memory::Reference ourTask = task; + + std::string taskName = ourTask->GetName(); + Log::Diag("RegisterTask: " + taskName); + + auto taskContainer = BuildTaskContainer( + ourTask, + Extensions::StringListWrapper(ourTask->GetRunBeforeList()).CopyAsStringVector(), + Extensions::StringListWrapper(ourTask->GetRunAfterList()).CopyAsStringVector()); + + std::stringstream runBeforeMessage; + runBeforeMessage << "RunBefore ["; + bool isFirst = true; + for (auto& name : taskContainer.RunBeforeList) + { + if (!isFirst) + runBeforeMessage << ", "; + + runBeforeMessage << "\"" << name << "\""; + isFirst = false; + } + + runBeforeMessage << "]"; + Log::Diag(runBeforeMessage.str()); + + std::stringstream runAfterMessage; + runAfterMessage << "RunAfter ["; + isFirst = true; + for (auto& name : taskContainer.RunAfterList) + { + if (!isFirst) + runAfterMessage << ", "; + + runAfterMessage << "\"" << name << "\""; + isFirst = false; + } + + runAfterMessage << "]"; + Log::Diag(runAfterMessage.str()); + + auto insertResult = _tasks.try_emplace(taskName, std::move(taskContainer)); + if (!insertResult.second) + { + Log::HighPriority("A task with the provided name has already been registered: " + taskName); + return -2; + } + + return 0; + } + catch (...) + { + // Unknown error + return -1; + } + } + + /// + /// Get the set of added include paths + /// + void Execute(BuildState& state) + { + // Setup each task to have a complete list of tasks that must run before itself + // Note: this is required to combine other tasks run before lists with the tasks + // own run after list + for (auto& task : _tasks) + { + auto& taskContainer = task.second; + + // Copy their own run after list + std::copy( + taskContainer.RunAfterList.begin(), + taskContainer.RunAfterList.end(), + std::back_inserter(taskContainer.RunAfterClosureList)); + + // Add ourself to all tasks in our run before list + for (auto& runBefore : taskContainer.RunBeforeList) + { + // Try to find the other task + auto findResult = _tasks.find(runBefore); + if (findResult != _tasks.end()) + { + auto& beforeTaskContainer = findResult->second; + beforeTaskContainer.RunAfterClosureList.push_back(task.first); + } + } + } + + // Run all tasks in the order they were registered + // ensuring they are run in the correct dependency order + auto currentTask = FindNextTask(); + while (currentTask != _tasks.end()) + { + Log::Info("TaskStart: " + currentTask->first); + auto status = currentTask->second.Task->Execute(state); + if (status != 0) + { + Log::Error("TaskFailed: " + std::to_string(status)); + throw std::runtime_error("Task Failed"); + } + else + { + Log::Info("TaskDone: " + currentTask->first); + } + + state.LogActive(); + currentTask->second.HasRun = true; + currentTask = FindNextTask(); + } + } + + private: + /// + /// Try to find the next task that has yet to be run and is ready + /// Returns false if all tasks have been run + /// Throws error if we hit a deadlock + /// + std::unordered_map::iterator FindNextTask() + { + // Find the next task that is ready to be run + bool hasAnyStillWaiting = false; + auto taskItr = _tasks.begin(); + for (;taskItr != _tasks.end(); taskItr++) + { + // Check if this task has run already, + // if not check if all if all upstream tasks have finished + auto& taskContainer = taskItr->second; + if (!taskContainer.HasRun) + { + hasAnyStillWaiting = true; + + // Check if all of their run after dependencies have already finished + bool hasDependencyPending = false; + for (auto& runBefore : taskContainer.RunAfterClosureList) + { + auto findResult = _tasks.find(runBefore); + if (findResult != _tasks.end() && !findResult->second.HasRun) + { + // Found a dependency that hasn't run, keep trying + hasDependencyPending = true; + break; + } + } + + // All dependencies have finished + // Let's run this one + if (!hasDependencyPending) + return taskItr; + } + } + + if (!hasAnyStillWaiting) + return _tasks.end(); + else + throw std::runtime_error("Hit deadlock in build task dependencies."); + } + + private: + std::unordered_map _tasks; + }; +} diff --git a/Source/Engine/Core/Module.cpp b/Source/Build/Runtime/Module.cpp similarity index 67% rename from Source/Engine/Core/Module.cpp rename to Source/Build/Runtime/Module.cpp index 06199833..377f553f 100644 --- a/Source/Engine/Core/Module.cpp +++ b/Source/Build/Runtime/Module.cpp @@ -2,16 +2,17 @@ #include #include +#include #include #include #include #include -export module SoupEngineCore; +export module Soup.Build.Runtime; import Opal; -import SoupEngineDefinition; -import SoupEngineWrapper; +import Soup.Build; +import Soup.Build.Extensions; using namespace Opal; diff --git a/Source/Build/Runtime/Recipe.toml b/Source/Build/Runtime/Recipe.toml new file mode 100644 index 00000000..fa028847 --- /dev/null +++ b/Source/Build/Runtime/Recipe.toml @@ -0,0 +1,17 @@ +Name = "Soup.Build.Runtime" +Version = "0.1.0" + +Dependencies = [ + # "../../../Dependencies/Opal/Source/", + "../Core/", + # "Soup.Build@0.2.0", + "../Extensions/", + # "Soup.Build.Extensions@0.2.0", + "Opal@0.1.1", +] + +Public = "Module.cpp" +Source = [ + "BuildGraphNodeList.cpp", + "Value.cpp", +] diff --git a/Source/Engine/Core/StringList.h b/Source/Build/Runtime/StringList.h similarity index 90% rename from Source/Engine/Core/StringList.h rename to Source/Build/Runtime/StringList.h index fe801bc7..8d1f8f88 100644 --- a/Source/Engine/Core/StringList.h +++ b/Source/Build/Runtime/StringList.h @@ -4,9 +4,9 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Runtime { - class StringList : public IList + export class StringList : public IList { public: /// diff --git a/Source/Engine/Core/Value.cpp b/Source/Build/Runtime/Value.cpp similarity index 94% rename from Source/Engine/Core/Value.cpp rename to Source/Build/Runtime/Value.cpp index 59874668..527dfba6 100644 --- a/Source/Engine/Core/Value.cpp +++ b/Source/Build/Runtime/Value.cpp @@ -11,11 +11,11 @@ module; #include #include -module SoupEngineCore; +module Soup.Build.Runtime; using namespace Opal; -namespace Soup::Build +namespace Soup::Build::Runtime { Value::Value() : diff --git a/Source/Engine/Core/Value.h b/Source/Build/Runtime/Value.h similarity index 94% rename from Source/Engine/Core/Value.h rename to Source/Build/Runtime/Value.h index b7885ce7..7d4790b8 100644 --- a/Source/Engine/Core/Value.h +++ b/Source/Build/Runtime/Value.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Runtime { export class ValueTable; export class ValueList; diff --git a/Source/Engine/Core/ValueList.h b/Source/Build/Runtime/ValueList.h similarity index 92% rename from Source/Engine/Core/ValueList.h rename to Source/Build/Runtime/ValueList.h index 00ce9c03..872c581d 100644 --- a/Source/Engine/Core/ValueList.h +++ b/Source/Build/Runtime/ValueList.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Build::Runtime { /// /// Build list implementation for simple objects diff --git a/Source/Engine/Core/ValuePrimitive.h b/Source/Build/Runtime/ValuePrimitive.h similarity index 93% rename from Source/Engine/Core/ValuePrimitive.h rename to Source/Build/Runtime/ValuePrimitive.h index 51d4a49f..d875fe6f 100644 --- a/Source/Engine/Core/ValuePrimitive.h +++ b/Source/Build/Runtime/ValuePrimitive.h @@ -6,7 +6,7 @@ #include "Value.h" #include "ValueList.h" -namespace Soup::Build +namespace Soup::Build::Runtime { /// /// Build State Extension interface diff --git a/Source/Engine/Core/ValueTable.h b/Source/Build/Runtime/ValueTable.h similarity index 93% rename from Source/Engine/Core/ValueTable.h rename to Source/Build/Runtime/ValueTable.h index 3df23973..11b3bda2 100644 --- a/Source/Engine/Core/ValueTable.h +++ b/Source/Build/Runtime/ValueTable.h @@ -6,7 +6,7 @@ #include "Value.h" #include "ValueList.h" -namespace Soup::Build +namespace Soup::Build::Runtime { /// /// Build State Extension interface diff --git a/Source/Client.UnitTests/Commands/BuildCommandTests.h b/Source/Client/CLI.UnitTests/Commands/BuildCommandTests.h similarity index 100% rename from Source/Client.UnitTests/Commands/BuildCommandTests.h rename to Source/Client/CLI.UnitTests/Commands/BuildCommandTests.h diff --git a/Source/Client.UnitTests/Commands/InitializeCommandTests.h b/Source/Client/CLI.UnitTests/Commands/InitializeCommandTests.h similarity index 100% rename from Source/Client.UnitTests/Commands/InitializeCommandTests.h rename to Source/Client/CLI.UnitTests/Commands/InitializeCommandTests.h diff --git a/Source/Client.UnitTests/Commands/InstallCommandTests.h b/Source/Client/CLI.UnitTests/Commands/InstallCommandTests.h similarity index 100% rename from Source/Client.UnitTests/Commands/InstallCommandTests.h rename to Source/Client/CLI.UnitTests/Commands/InstallCommandTests.h diff --git a/Source/Client.UnitTests/Commands/PackCommandTests.h b/Source/Client/CLI.UnitTests/Commands/PackCommandTests.h similarity index 100% rename from Source/Client.UnitTests/Commands/PackCommandTests.h rename to Source/Client/CLI.UnitTests/Commands/PackCommandTests.h diff --git a/Source/Client.UnitTests/Commands/PublishCommandTests.h b/Source/Client/CLI.UnitTests/Commands/PublishCommandTests.h similarity index 100% rename from Source/Client.UnitTests/Commands/PublishCommandTests.h rename to Source/Client/CLI.UnitTests/Commands/PublishCommandTests.h diff --git a/Source/Client.UnitTests/Commands/VersionCommandTests.h b/Source/Client/CLI.UnitTests/Commands/VersionCommandTests.h similarity index 100% rename from Source/Client.UnitTests/Commands/VersionCommandTests.h rename to Source/Client/CLI.UnitTests/Commands/VersionCommandTests.h diff --git a/Source/Client.UnitTests/Commands/ViewCommandTests.h b/Source/Client/CLI.UnitTests/Commands/ViewCommandTests.h similarity index 100% rename from Source/Client.UnitTests/Commands/ViewCommandTests.h rename to Source/Client/CLI.UnitTests/Commands/ViewCommandTests.h diff --git a/Source/Client.UnitTests/Recipe.json b/Source/Client/CLI.UnitTests/Recipe.json similarity index 100% rename from Source/Client.UnitTests/Recipe.json rename to Source/Client/CLI.UnitTests/Recipe.json diff --git a/Source/Client.UnitTests/gen/Commands/BuildCommandTests.gen.h b/Source/Client/CLI.UnitTests/gen/Commands/BuildCommandTests.gen.h similarity index 100% rename from Source/Client.UnitTests/gen/Commands/BuildCommandTests.gen.h rename to Source/Client/CLI.UnitTests/gen/Commands/BuildCommandTests.gen.h diff --git a/Source/Client.UnitTests/gen/Commands/InitializeCommandTests.gen.h b/Source/Client/CLI.UnitTests/gen/Commands/InitializeCommandTests.gen.h similarity index 100% rename from Source/Client.UnitTests/gen/Commands/InitializeCommandTests.gen.h rename to Source/Client/CLI.UnitTests/gen/Commands/InitializeCommandTests.gen.h diff --git a/Source/Client.UnitTests/gen/Commands/InstallCommandTests.gen.h b/Source/Client/CLI.UnitTests/gen/Commands/InstallCommandTests.gen.h similarity index 100% rename from Source/Client.UnitTests/gen/Commands/InstallCommandTests.gen.h rename to Source/Client/CLI.UnitTests/gen/Commands/InstallCommandTests.gen.h diff --git a/Source/Client.UnitTests/gen/Commands/PackCommandTests.gen.h b/Source/Client/CLI.UnitTests/gen/Commands/PackCommandTests.gen.h similarity index 100% rename from Source/Client.UnitTests/gen/Commands/PackCommandTests.gen.h rename to Source/Client/CLI.UnitTests/gen/Commands/PackCommandTests.gen.h diff --git a/Source/Client.UnitTests/gen/Commands/PublishCommandTests.gen.h b/Source/Client/CLI.UnitTests/gen/Commands/PublishCommandTests.gen.h similarity index 100% rename from Source/Client.UnitTests/gen/Commands/PublishCommandTests.gen.h rename to Source/Client/CLI.UnitTests/gen/Commands/PublishCommandTests.gen.h diff --git a/Source/Client.UnitTests/gen/Commands/VersionCommandTests.gen.h b/Source/Client/CLI.UnitTests/gen/Commands/VersionCommandTests.gen.h similarity index 100% rename from Source/Client.UnitTests/gen/Commands/VersionCommandTests.gen.h rename to Source/Client/CLI.UnitTests/gen/Commands/VersionCommandTests.gen.h diff --git a/Source/Client.UnitTests/gen/Commands/ViewCommandTests.gen.h b/Source/Client/CLI.UnitTests/gen/Commands/ViewCommandTests.gen.h similarity index 100% rename from Source/Client.UnitTests/gen/Commands/ViewCommandTests.gen.h rename to Source/Client/CLI.UnitTests/gen/Commands/ViewCommandTests.gen.h diff --git a/Source/Client.UnitTests/gen/Main.cpp b/Source/Client/CLI.UnitTests/gen/Main.cpp similarity index 100% rename from Source/Client.UnitTests/gen/Main.cpp rename to Source/Client/CLI.UnitTests/gen/Main.cpp diff --git a/Source/Client/Commands/BuildCommand.h b/Source/Client/CLI/Commands/BuildCommand.h similarity index 92% rename from Source/Client/Commands/BuildCommand.h rename to Source/Client/CLI/Commands/BuildCommand.h index b56ba3e2..eba94c20 100644 --- a/Source/Client/Commands/BuildCommand.h +++ b/Source/Client/CLI/Commands/BuildCommand.h @@ -30,7 +30,7 @@ namespace Soup::Client Log::Diag("BuildCommand::Run"); // Load the user config - auto config = LocalUserConfigExtensions::LoadFromFile(); + auto config = LocalUserConfigExtensions::LoadFromFile(); auto workingDirectory = Path(); if (_options.Path.empty()) @@ -62,6 +62,8 @@ namespace Soup::Client // Setup the build arguments auto arguments = RecipeBuildArguments(); arguments.ForceRebuild = _options.Force; + arguments.SkipRun = _options.SkipRun; + if (!_options.Flavor.empty()) arguments.Flavor = _options.Flavor; else @@ -133,7 +135,7 @@ namespace Soup::Client Log::Info("Begin Build:"); auto startTime = std::chrono::high_resolution_clock::now(); - auto buildManager = Build::RecipeBuildManager(systemCompiler, runtimeCompiler); + auto buildManager = Build::Runtime::RecipeBuildManager(systemCompiler, runtimeCompiler); buildManager.Execute(workingDirectory, recipe, arguments); auto endTime = std::chrono::high_resolution_clock::now(); diff --git a/Source/Client/Commands/ICommand.h b/Source/Client/CLI/Commands/ICommand.h similarity index 100% rename from Source/Client/Commands/ICommand.h rename to Source/Client/CLI/Commands/ICommand.h diff --git a/Source/Client/Commands/InitializeCommand.h b/Source/Client/CLI/Commands/InitializeCommand.h similarity index 93% rename from Source/Client/Commands/InitializeCommand.h rename to Source/Client/CLI/Commands/InitializeCommand.h index f7eafc23..922caf3b 100644 --- a/Source/Client/Commands/InitializeCommand.h +++ b/Source/Client/CLI/Commands/InitializeCommand.h @@ -40,7 +40,7 @@ namespace Soup::Client workingDirectory.GetFileName(), SemanticVersion(1, 0, 0)); - recipe.SetType(RecipeType::Executable); + recipe.SetType(Build::Extensions::RecipeType::Executable); recipe.SetSource(std::vector({ "Main.cpp", })); diff --git a/Source/Client/Commands/InstallCommand.h b/Source/Client/CLI/Commands/InstallCommand.h similarity index 100% rename from Source/Client/Commands/InstallCommand.h rename to Source/Client/CLI/Commands/InstallCommand.h diff --git a/Source/Client/Commands/PackCommand.h b/Source/Client/CLI/Commands/PackCommand.h similarity index 100% rename from Source/Client/Commands/PackCommand.h rename to Source/Client/CLI/Commands/PackCommand.h diff --git a/Source/Client/Commands/PublishCommand.h b/Source/Client/CLI/Commands/PublishCommand.h similarity index 100% rename from Source/Client/Commands/PublishCommand.h rename to Source/Client/CLI/Commands/PublishCommand.h diff --git a/Source/Client/Commands/RunCommand.h b/Source/Client/CLI/Commands/RunCommand.h similarity index 90% rename from Source/Client/Commands/RunCommand.h rename to Source/Client/CLI/Commands/RunCommand.h index 46606f86..2e3ef4b3 100644 --- a/Source/Client/Commands/RunCommand.h +++ b/Source/Client/CLI/Commands/RunCommand.h @@ -30,7 +30,7 @@ namespace Soup::Client Log::Diag("RunCommand::Run"); // Load the user config - auto config = LocalUserConfigExtensions::LoadFromFile(); + auto config = LocalUserConfigExtensions::LoadFromFile(); auto workingDirectory = System::IFileSystem::Current().GetCurrentDirectory2(); auto recipePath = @@ -44,7 +44,7 @@ namespace Soup::Client } // Ensure that this is an executable - if (recipe.GetType() != RecipeType::Executable) + if (recipe.GetType() != Build::Extensions::RecipeType::Executable) { Log::Error("Cannot run a project not of type executable"); return; diff --git a/Source/Client/Commands/VersionCommand.h b/Source/Client/CLI/Commands/VersionCommand.h similarity index 96% rename from Source/Client/Commands/VersionCommand.h rename to Source/Client/CLI/Commands/VersionCommand.h index e7bb0cdf..24807f27 100644 --- a/Source/Client/Commands/VersionCommand.h +++ b/Source/Client/CLI/Commands/VersionCommand.h @@ -31,7 +31,7 @@ namespace Soup::Client // TODO var version = Assembly.GetExecutingAssembly().GetName().Version; // Log::Message($"{version.Major}.{version.Minor}.{version.Build}"); - Log::HighPriority("0.6.1"); + Log::HighPriority("0.6.2"); } private: diff --git a/Source/Client/Commands/ViewCommand.h b/Source/Client/CLI/Commands/ViewCommand.h similarity index 100% rename from Source/Client/Commands/ViewCommand.h rename to Source/Client/CLI/Commands/ViewCommand.h diff --git a/Source/Client/LocalUserConfig.json b/Source/Client/CLI/LocalUserConfig.json similarity index 100% rename from Source/Client/LocalUserConfig.json rename to Source/Client/CLI/LocalUserConfig.json diff --git a/Source/Client/Main.cpp b/Source/Client/CLI/Main.cpp similarity index 90% rename from Source/Client/Main.cpp rename to Source/Client/CLI/Main.cpp index 5067029e..66c2fd0d 100644 --- a/Source/Client/Main.cpp +++ b/Source/Client/CLI/Main.cpp @@ -11,6 +11,7 @@ #include import Opal; +import Opal.Extensions; import SoupCore; using namespace Opal; diff --git a/Source/Client/Options/ArgumentsParser.h b/Source/Client/CLI/Options/ArgumentsParser.h similarity index 95% rename from Source/Client/Options/ArgumentsParser.h rename to Source/Client/CLI/Options/ArgumentsParser.h index 6f3018e4..61d0bf3b 100644 --- a/Source/Client/Options/ArgumentsParser.h +++ b/Source/Client/CLI/Options/ArgumentsParser.h @@ -52,6 +52,8 @@ namespace Soup::Client } options->Verbosity = CheckVerbosity(unusedArgs); + + options->SkipRun = IsFlagSet("skipRun", unusedArgs); options->Force = IsFlagSet("force", unusedArgs); auto flavorValue = std::string(); diff --git a/Source/Client/Options/BuildOptions.h b/Source/Client/CLI/Options/BuildOptions.h similarity index 79% rename from Source/Client/Options/BuildOptions.h rename to Source/Client/CLI/Options/BuildOptions.h index 3d6fddcf..db76226c 100644 --- a/Source/Client/Options/BuildOptions.h +++ b/Source/Client/CLI/Options/BuildOptions.h @@ -20,6 +20,12 @@ namespace Soup::Client [[Args::Option("path", Index = 0, HelpText = "Path to the package to build.")]] std::string Path; + /// + /// Gets or sets a value indicating whether to skip the execution of the build operations + /// + [[Args::Option("skipRun", Default = false, HelpText = "Do not run the build operations.")]] + bool SkipRun; + /// /// Gets or sets a value indicating whether to force a build /// diff --git a/Source/Client/Options/InitializeOptions.h b/Source/Client/CLI/Options/InitializeOptions.h similarity index 100% rename from Source/Client/Options/InitializeOptions.h rename to Source/Client/CLI/Options/InitializeOptions.h diff --git a/Source/Client/Options/InstallOptions.h b/Source/Client/CLI/Options/InstallOptions.h similarity index 100% rename from Source/Client/Options/InstallOptions.h rename to Source/Client/CLI/Options/InstallOptions.h diff --git a/Source/Client/Options/PackOptions.h b/Source/Client/CLI/Options/PackOptions.h similarity index 100% rename from Source/Client/Options/PackOptions.h rename to Source/Client/CLI/Options/PackOptions.h diff --git a/Source/Client/Options/PublishOptions.h b/Source/Client/CLI/Options/PublishOptions.h similarity index 100% rename from Source/Client/Options/PublishOptions.h rename to Source/Client/CLI/Options/PublishOptions.h diff --git a/Source/Client/Options/RunOptions.h b/Source/Client/CLI/Options/RunOptions.h similarity index 100% rename from Source/Client/Options/RunOptions.h rename to Source/Client/CLI/Options/RunOptions.h diff --git a/Source/Client/Options/SharedOptions.h b/Source/Client/CLI/Options/SharedOptions.h similarity index 100% rename from Source/Client/Options/SharedOptions.h rename to Source/Client/CLI/Options/SharedOptions.h diff --git a/Source/Client/Options/VersionOptions.h b/Source/Client/CLI/Options/VersionOptions.h similarity index 100% rename from Source/Client/Options/VersionOptions.h rename to Source/Client/CLI/Options/VersionOptions.h diff --git a/Source/Client/Options/ViewOptions.h b/Source/Client/CLI/Options/ViewOptions.h similarity index 100% rename from Source/Client/Options/ViewOptions.h rename to Source/Client/CLI/Options/ViewOptions.h diff --git a/Source/Client/Program.h b/Source/Client/CLI/Program.h similarity index 100% rename from Source/Client/Program.h rename to Source/Client/CLI/Program.h diff --git a/Source/Client/Recipe.toml b/Source/Client/CLI/Recipe.toml similarity index 74% rename from Source/Client/Recipe.toml rename to Source/Client/CLI/Recipe.toml index 06967b40..c61cc65f 100644 --- a/Source/Client/Recipe.toml +++ b/Source/Client/CLI/Recipe.toml @@ -1,11 +1,11 @@ Name = "Soup" -Version = "0.6.1" +Version = "0.6.2" Type = "Executable" # Ensure the core build extensions are runtime dependencies Dependencies = [ "../Core/", - "../RecipeBuildExtension/", + "../../Extensions/RecipeBuild/", ] Source = [ diff --git a/Source/Core.UnitTests/Api/Models/PackageCreateModelTests.cs b/Source/Client/Core.UnitTests/Api/Models/PackageCreateModelTests.cs similarity index 100% rename from Source/Core.UnitTests/Api/Models/PackageCreateModelTests.cs rename to Source/Client/Core.UnitTests/Api/Models/PackageCreateModelTests.cs diff --git a/Source/Core.UnitTests/Api/Models/PackageResultModelTests.cs b/Source/Client/Core.UnitTests/Api/Models/PackageResultModelTests.cs similarity index 100% rename from Source/Core.UnitTests/Api/Models/PackageResultModelTests.cs rename to Source/Client/Core.UnitTests/Api/Models/PackageResultModelTests.cs diff --git a/Source/Core.UnitTests/Api/Models/PackageSummaryModelTests.cs b/Source/Client/Core.UnitTests/Api/Models/PackageSummaryModelTests.cs similarity index 100% rename from Source/Core.UnitTests/Api/Models/PackageSummaryModelTests.cs rename to Source/Client/Core.UnitTests/Api/Models/PackageSummaryModelTests.cs diff --git a/Source/Core.UnitTests/Api/Models/PackageUpdateModelTests.cs b/Source/Client/Core.UnitTests/Api/Models/PackageUpdateModelTests.cs similarity index 100% rename from Source/Core.UnitTests/Api/Models/PackageUpdateModelTests.cs rename to Source/Client/Core.UnitTests/Api/Models/PackageUpdateModelTests.cs diff --git a/Source/Core.UnitTests/Api/Models/PublicationResultModelTests.cs b/Source/Client/Core.UnitTests/Api/Models/PublicationResultModelTests.cs similarity index 100% rename from Source/Core.UnitTests/Api/Models/PublicationResultModelTests.cs rename to Source/Client/Core.UnitTests/Api/Models/PublicationResultModelTests.cs diff --git a/Source/Core.UnitTests/Api/Models/PublicationSummaryModelTests.cs b/Source/Client/Core.UnitTests/Api/Models/PublicationSummaryModelTests.cs similarity index 100% rename from Source/Core.UnitTests/Api/Models/PublicationSummaryModelTests.cs rename to Source/Client/Core.UnitTests/Api/Models/PublicationSummaryModelTests.cs diff --git a/Source/Core.UnitTests/Api/SoupApiJsonModelsTests.h b/Source/Client/Core.UnitTests/Api/SoupApiJsonModelsTests.h similarity index 100% rename from Source/Core.UnitTests/Api/SoupApiJsonModelsTests.h rename to Source/Client/Core.UnitTests/Api/SoupApiJsonModelsTests.h diff --git a/Source/Core.UnitTests/Api/SoupApiTests.h b/Source/Client/Core.UnitTests/Api/SoupApiTests.h similarity index 100% rename from Source/Core.UnitTests/Api/SoupApiTests.h rename to Source/Client/Core.UnitTests/Api/SoupApiTests.h diff --git a/Source/Core.UnitTests/Build/Runner/BuildHistoryCheckerTests.h b/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryCheckerTests.h similarity index 100% rename from Source/Core.UnitTests/Build/Runner/BuildHistoryCheckerTests.h rename to Source/Client/Core.UnitTests/Build/Runner/BuildHistoryCheckerTests.h diff --git a/Source/Core.UnitTests/Build/Runner/BuildHistoryJsonTests.h b/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryJsonTests.h similarity index 100% rename from Source/Core.UnitTests/Build/Runner/BuildHistoryJsonTests.h rename to Source/Client/Core.UnitTests/Build/Runner/BuildHistoryJsonTests.h diff --git a/Source/Core.UnitTests/Build/Runner/BuildHistoryManagerTests.h b/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryManagerTests.h similarity index 100% rename from Source/Core.UnitTests/Build/Runner/BuildHistoryManagerTests.h rename to Source/Client/Core.UnitTests/Build/Runner/BuildHistoryManagerTests.h diff --git a/Source/Core.UnitTests/Build/Runner/BuildHistoryTests.h b/Source/Client/Core.UnitTests/Build/Runner/BuildHistoryTests.h similarity index 100% rename from Source/Core.UnitTests/Build/Runner/BuildHistoryTests.h rename to Source/Client/Core.UnitTests/Build/Runner/BuildHistoryTests.h diff --git a/Source/Core.UnitTests/Build/Runner/BuildRunnerTests.h b/Source/Client/Core.UnitTests/Build/Runner/BuildRunnerTests.h similarity index 96% rename from Source/Core.UnitTests/Build/Runner/BuildRunnerTests.h rename to Source/Client/Core.UnitTests/Build/Runner/BuildRunnerTests.h index 80d9e5c5..14a31056 100644 --- a/Source/Core.UnitTests/Build/Runner/BuildRunnerTests.h +++ b/Source/Client/Core.UnitTests/Build/Runner/BuildRunnerTests.h @@ -33,7 +33,7 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto nodes = std::vector>(); + auto nodes = std::vector>(); auto objectDirectory = Path("out/obj/release/"); auto forceBuild = true; uut.Execute(nodes, objectDirectory, forceBuild); @@ -83,7 +83,7 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto nodes = std::vector>(); + auto nodes = std::vector>(); auto objectDirectory = Path("out/obj/release/"); auto forceBuild = false; uut.Execute(nodes, objectDirectory, forceBuild); @@ -137,8 +137,8 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto nodes = std::vector>({ - new BuildGraphNode( + auto nodes = std::vector>({ + new Runtime::BuildGraphNode( "TestCommand: 1", "Command.exe", "Arguments", @@ -203,8 +203,8 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto nodes = std::vector>({ - new BuildGraphNode( + auto nodes = std::vector>({ + new Runtime::BuildGraphNode( "TestCommand: 1", "Command.exe", "Arguments", @@ -281,8 +281,8 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto nodes = std::vector>({ - new BuildGraphNode( + auto nodes = std::vector>({ + new Runtime::BuildGraphNode( "TestCommand: 1", "Command.exe", "Arguments", @@ -360,8 +360,8 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto nodes = std::vector>({ - new BuildGraphNode( + auto nodes = std::vector>({ + new Runtime::BuildGraphNode( "TestCommand: 1", "Command.exe", "Arguments", @@ -447,8 +447,8 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto nodes = std::vector>({ - new BuildGraphNode( + auto nodes = std::vector>({ + new Runtime::BuildGraphNode( "TestCommand: 1", "Command.exe", "Arguments", @@ -539,8 +539,8 @@ namespace Soup::Build::UnitTests auto uut = BuildRunner(Path("C:/BuildDirectory/")); // Setup the input build state - auto nodes = std::vector>({ - new BuildGraphNode( + auto nodes = std::vector>({ + new Runtime::BuildGraphNode( "TestCommand: 1", "Command.exe", "Arguments", diff --git a/Source/Core.UnitTests/Config/LocalUserConfigExtensionsTests.h b/Source/Client/Core.UnitTests/Config/LocalUserConfigExtensionsTests.h similarity index 100% rename from Source/Core.UnitTests/Config/LocalUserConfigExtensionsTests.h rename to Source/Client/Core.UnitTests/Config/LocalUserConfigExtensionsTests.h diff --git a/Source/Core.UnitTests/Config/LocalUserConfigJsonTests.h b/Source/Client/Core.UnitTests/Config/LocalUserConfigJsonTests.h similarity index 100% rename from Source/Core.UnitTests/Config/LocalUserConfigJsonTests.h rename to Source/Client/Core.UnitTests/Config/LocalUserConfigJsonTests.h diff --git a/Source/Core.UnitTests/Config/LocalUserConfigTests.h b/Source/Client/Core.UnitTests/Config/LocalUserConfigTests.h similarity index 100% rename from Source/Core.UnitTests/Config/LocalUserConfigTests.h rename to Source/Client/Core.UnitTests/Config/LocalUserConfigTests.h diff --git a/Source/Core.UnitTests/Package/PackageManagerTests.h b/Source/Client/Core.UnitTests/Package/PackageManagerTests.h similarity index 98% rename from Source/Core.UnitTests/Package/PackageManagerTests.h rename to Source/Client/Core.UnitTests/Package/PackageManagerTests.h index 29d52b8c..f6553d5c 100644 --- a/Source/Core.UnitTests/Package/PackageManagerTests.h +++ b/Source/Client/Core.UnitTests/Package/PackageManagerTests.h @@ -14,7 +14,7 @@ namespace Soup::UnitTests { // Register the test listener auto testListener = std::make_shared(); - auto scopedTraceListener = ScopedTraceListenerRegister(testListener); + auto scopedTraceListener = ScopedTraceListenerRegister(testListener); // Register the test file system auto fileSystem = std::make_shared(); @@ -57,7 +57,7 @@ namespace Soup::UnitTests { // Register the test listener auto testListener = std::make_shared(); - auto scopedTraceListener = ScopedTraceListenerRegister(testListener); + auto scopedTraceListener = ScopedTraceListenerRegister(testListener); // Register the test file system auto fileSystem = std::make_shared(); @@ -137,7 +137,7 @@ namespace Soup::UnitTests { // Register the test listener auto testListener = std::make_shared(); - auto scopedTraceListener = ScopedTraceListenerRegister(testListener); + auto scopedTraceListener = ScopedTraceListenerRegister(testListener); // Register the test file system auto fileSystem = std::make_shared(); @@ -272,7 +272,7 @@ namespace Soup::UnitTests { // Register the test listener auto testListener = std::make_shared(); - auto scopedTraceListener = ScopedTraceListenerRegister(testListener); + auto scopedTraceListener = ScopedTraceListenerRegister(testListener); // Register the test file system auto fileSystem = std::make_shared(); @@ -386,7 +386,7 @@ Dependencies = [ { // Register the test listener auto testListener = std::make_shared(); - auto scopedTraceListener = ScopedTraceListenerRegister(testListener); + auto scopedTraceListener = ScopedTraceListenerRegister(testListener); // Register the test file system auto fileSystem = std::make_shared(); @@ -534,7 +534,7 @@ Dependencies = [ { // Register the test listener auto testListener = std::make_shared(); - auto scopedTraceListener = ScopedTraceListenerRegister(testListener); + auto scopedTraceListener = ScopedTraceListenerRegister(testListener); // Register the test file system auto fileSystem = std::make_shared(); @@ -964,7 +964,7 @@ Dependencies = [ // Name = "TheirPackage" // Version = "2.2.2" // Dependencies = [ - // "MyDependency@1.0.0", + // "MyDependency@1.0.0", // ] auto archive = std::vector( { diff --git a/Source/Core.UnitTests/Package/PackageReferenceTests.h b/Source/Client/Core.UnitTests/Package/PackageReferenceTests.h similarity index 100% rename from Source/Core.UnitTests/Package/PackageReferenceTests.h rename to Source/Client/Core.UnitTests/Package/PackageReferenceTests.h diff --git a/Source/Core.UnitTests/Package/RecipeBuildManagerTests.h b/Source/Client/Core.UnitTests/Package/RecipeBuildManagerTests.h similarity index 90% rename from Source/Core.UnitTests/Package/RecipeBuildManagerTests.h rename to Source/Client/Core.UnitTests/Package/RecipeBuildManagerTests.h index bcf410ef..7fff6e25 100644 --- a/Source/Core.UnitTests/Package/RecipeBuildManagerTests.h +++ b/Source/Client/Core.UnitTests/Package/RecipeBuildManagerTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::UnitTests +namespace Soup::Build::Runtime::UnitTests { class RecipeBuildManagerTests { diff --git a/Source/Core.UnitTests/Package/RecipeBuilderTests.h b/Source/Client/Core.UnitTests/Package/RecipeBuilderTests.h similarity index 100% rename from Source/Core.UnitTests/Package/RecipeBuilderTests.h rename to Source/Client/Core.UnitTests/Package/RecipeBuilderTests.h diff --git a/Source/Core.UnitTests/Package/RecipeExtensionsTests.h b/Source/Client/Core.UnitTests/Package/RecipeExtensionsTests.h similarity index 98% rename from Source/Core.UnitTests/Package/RecipeExtensionsTests.h rename to Source/Client/Core.UnitTests/Package/RecipeExtensionsTests.h index 0c3892d9..b617af2e 100644 --- a/Source/Core.UnitTests/Package/RecipeExtensionsTests.h +++ b/Source/Client/Core.UnitTests/Package/RecipeExtensionsTests.h @@ -77,7 +77,7 @@ namespace Soup::Build::UnitTests Assert::AreEqual( std::vector({ "DIAG: Load Recipe: TestFiles/GarbageRecipe/Recipe.toml", - "ERRO: Deserialize Threw: Parsing the Recipe Toml failed: [error] toml::parse_key_value_pair: missing key-value separator `=`\n --> Recipe.toml\n | \n 1 | garbage\n | ^ should be `=`", + "ERRO: Deserialize Threw: Parsing the Recipe Toml failed: [error] toml::parse_key_value_pair: missing key-value separator `=`\n --> TestFiles/GarbageRecipe/Recipe.toml\n | \n 1 | garbage\n | ^ should be `=`", "INFO: Failed to parse Recipe.", }), testListener->GetMessages(), diff --git a/Source/Core.UnitTests/Package/RecipeJsonTests.h b/Source/Client/Core.UnitTests/Package/RecipeJsonTests.h similarity index 94% rename from Source/Core.UnitTests/Package/RecipeJsonTests.h rename to Source/Client/Core.UnitTests/Package/RecipeJsonTests.h index 33037fbd..3a29a01a 100644 --- a/Source/Core.UnitTests/Package/RecipeJsonTests.h +++ b/Source/Client/Core.UnitTests/Package/RecipeJsonTests.h @@ -82,8 +82,8 @@ namespace Soup::Build::UnitTests auto expected = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector(), std::vector(), "Public.cpp", @@ -119,8 +119,8 @@ namespace Soup::Build::UnitTests auto recipe = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector(), std::vector(), "Public.cpp", diff --git a/Source/Core.UnitTests/Package/RecipeTests.h b/Source/Client/Core.UnitTests/Package/RecipeTests.h similarity index 84% rename from Source/Core.UnitTests/Package/RecipeTests.h rename to Source/Client/Core.UnitTests/Package/RecipeTests.h index 8a135b2f..7af049db 100644 --- a/Source/Core.UnitTests/Package/RecipeTests.h +++ b/Source/Client/Core.UnitTests/Package/RecipeTests.h @@ -32,8 +32,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP20, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP20, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -54,9 +54,9 @@ namespace Soup::Build::UnitTests Assert::AreEqual("MyPackage", uut.GetName(), "Verify name matches expected."); Assert::AreEqual(SemanticVersion(1, 2, 3), uut.GetVersion(), "Verify version is correct."); Assert::IsTrue(uut.HasType(), "Verify has type."); - Assert::AreEqual(RecipeType::Executable, uut.GetType(), "Verify type is correct."); + Assert::AreEqual(Build::Extensions::RecipeType::Executable, uut.GetType(), "Verify type is correct."); Assert::IsTrue(uut.HasLanguageVersion(), "Verify has language version."); - Assert::AreEqual(RecipeLanguageVersion::CPP20, uut.GetLanguageVersion(), "Verify language version is correct."); + Assert::AreEqual(Build::Extensions::RecipeLanguageVersion::CPP20, uut.GetLanguageVersion(), "Verify language version is correct."); Assert::IsTrue(uut.HasDependencies(), "Verify has dependencies."); Assert::AreEqual( std::vector({ @@ -110,8 +110,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -133,8 +133,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -161,8 +161,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -184,8 +184,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage2", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -212,8 +212,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -235,8 +235,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(11, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -263,8 +263,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -286,8 +286,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::StaticLibrary, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::StaticLibrary, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -314,8 +314,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -338,7 +338,7 @@ namespace Soup::Build::UnitTests "MyPackage", SemanticVersion(1, 2, 3), std::nullopt, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -365,8 +365,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -388,8 +388,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP20, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP20, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -416,8 +416,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -439,7 +439,7 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, + Build::Extensions::RecipeType::Executable, std::nullopt, std::vector({ PackageReference(Path("../OtherPackage")), @@ -467,8 +467,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -490,8 +490,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ }), std::vector({ @@ -517,8 +517,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -540,8 +540,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::nullopt, std::vector({ PackageReference(Path("../BuildTask")), @@ -566,8 +566,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -589,8 +589,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -616,8 +616,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -639,8 +639,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -665,8 +665,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -688,8 +688,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -716,8 +716,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -739,8 +739,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -767,8 +767,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -790,8 +790,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -817,8 +817,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -840,8 +840,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -866,8 +866,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -889,8 +889,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -916,8 +916,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -939,8 +939,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -965,8 +965,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -988,8 +988,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -1015,8 +1015,8 @@ namespace Soup::Build::UnitTests auto uut = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), @@ -1038,8 +1038,8 @@ namespace Soup::Build::UnitTests Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector({ PackageReference(Path("../OtherPackage")), }), diff --git a/Source/Core.UnitTests/Package/RecipeTomlTests.h b/Source/Client/Core.UnitTests/Package/RecipeTomlTests.h similarity index 76% rename from Source/Core.UnitTests/Package/RecipeTomlTests.h rename to Source/Client/Core.UnitTests/Package/RecipeTomlTests.h index 40d836cb..2a0bb1bc 100644 --- a/Source/Core.UnitTests/Package/RecipeTomlTests.h +++ b/Source/Client/Core.UnitTests/Package/RecipeTomlTests.h @@ -12,47 +12,51 @@ namespace Soup::Build::UnitTests [[Fact]] void Deserialize_GarbageThrows() { + auto recipeFile = Path("Recipe.toml"); auto recipe = std::stringstream("garbage"); - Assert::ThrowsRuntimeError([&recipe]() { - auto actual = RecipeToml::Deserialize(recipe); + Assert::ThrowsRuntimeError([&recipeFile, &recipe]() { + auto actual = RecipeToml::Deserialize(recipeFile, recipe); }); } [[Fact]] void Deserialize_MissingNameThrows() { + auto recipeFile = Path("Recipe.toml"); auto recipe = std::stringstream( R"( Version="1.2.3" )"); - Assert::ThrowsRuntimeError([&recipe]() { - auto actual = RecipeToml::Deserialize(recipe); + Assert::ThrowsRuntimeError([&recipeFile, &recipe]() { + auto actual = RecipeToml::Deserialize(recipeFile, recipe); }); } [[Fact]] void Deserialize_MissingVersionThrows() { + auto recipeFile = Path("Recipe.toml"); auto recipe = std::stringstream( R"( Name="MyPackage" )"); - Assert::ThrowsRuntimeError([&recipe]() { - auto actual = RecipeToml::Deserialize(recipe); + Assert::ThrowsRuntimeError([&recipeFile, &recipe]() { + auto actual = RecipeToml::Deserialize(recipeFile, recipe); }); } [[Fact]] void Deserialize_Simple() { + auto recipeFile = Path("Recipe.toml"); auto recipe = std::stringstream( R"( Name="MyPackage" Version="1.2.3" )"); - auto actual = RecipeToml::Deserialize(recipe); + auto actual = RecipeToml::Deserialize(recipeFile, recipe); auto expected = Recipe( "MyPackage", @@ -64,13 +68,14 @@ namespace Soup::Build::UnitTests [[Fact]] void Deserialize_Comments() { + auto recipeFile = Path("Recipe.toml"); auto recipe = std::stringstream( R"( # This is an awesome project Name="MyPackage" Version="1.2.3" )"); - auto actual = RecipeToml::Deserialize(recipe); + auto actual = RecipeToml::Deserialize(recipeFile, recipe); auto expected = Recipe( "MyPackage", @@ -84,6 +89,7 @@ namespace Soup::Build::UnitTests [[Fact]] void Deserialize_AllProperties() { + auto recipeFile = Path("Recipe.toml"); auto recipe = std::stringstream( R"( Name="MyPackage" @@ -97,13 +103,13 @@ namespace Soup::Build::UnitTests IncludePaths=[] Defines=[] )"); - auto actual = RecipeToml::Deserialize(recipe); + auto actual = RecipeToml::Deserialize(recipeFile, recipe); auto expected = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector(), std::vector(), "Public.cpp", @@ -117,6 +123,7 @@ namespace Soup::Build::UnitTests [[Fact]] void Serialize_Simple() { + auto recipeFile = Path("Recipe.toml"); auto recipe = Recipe( "MyPackage", SemanticVersion(1, 2, 3)); @@ -135,6 +142,7 @@ Version = "1.2.3" [[Fact]] void Serialize_Comments() { + auto recipeFile = Path("Recipe.toml"); auto recipe = Recipe( "MyPackage", SemanticVersion(1, 2, 3)); @@ -156,11 +164,12 @@ Version = "1.2.3" [[Fact]] void Serialize_AllProperties() { + auto recipeFile = Path("Recipe.toml"); auto recipe = Recipe( "MyPackage", SemanticVersion(1, 2, 3), - RecipeType::Executable, - RecipeLanguageVersion::CPP17, + Build::Extensions::RecipeType::Executable, + Build::Extensions::RecipeLanguageVersion::CPP17, std::vector(), std::vector(), "Public.cpp", diff --git a/Source/Client/Core.UnitTests/Recipe.toml b/Source/Client/Core.UnitTests/Recipe.toml new file mode 100644 index 00000000..0bf47a5d --- /dev/null +++ b/Source/Client/Core.UnitTests/Recipe.toml @@ -0,0 +1,17 @@ +Name = "SoupCoreUnitTests" +Version = "1.0.0" +Type = "Executable" +Dependencies = [ + # "../../Dependencies/json11/", + # "../../Dependencies/SoupTest/Assert/", + "../Core/", + "../../TestUtilities/", + "json11@1.0.0", + "SoupTest@0.1.0", +] +Source = [ + "gen/Main.cpp" +] +IncludePaths = [ + "./", +] diff --git a/Source/Core.UnitTests/Utils/PathTests.h b/Source/Client/Core.UnitTests/Utils/PathTests.h similarity index 100% rename from Source/Core.UnitTests/Utils/PathTests.h rename to Source/Client/Core.UnitTests/Utils/PathTests.h diff --git a/Source/Core.UnitTests/Utils/SemanticVersionTests.h b/Source/Client/Core.UnitTests/Utils/SemanticVersionTests.h similarity index 100% rename from Source/Core.UnitTests/Utils/SemanticVersionTests.h rename to Source/Client/Core.UnitTests/Utils/SemanticVersionTests.h diff --git a/Source/Core.UnitTests/gen/Api/SoupApiJsonModelsTests.gen.h b/Source/Client/Core.UnitTests/gen/Api/SoupApiJsonModelsTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Api/SoupApiJsonModelsTests.gen.h rename to Source/Client/Core.UnitTests/gen/Api/SoupApiJsonModelsTests.gen.h diff --git a/Source/Core.UnitTests/gen/Api/SoupApiTests.gen.h b/Source/Client/Core.UnitTests/gen/Api/SoupApiTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Api/SoupApiTests.gen.h rename to Source/Client/Core.UnitTests/gen/Api/SoupApiTests.gen.h diff --git a/Source/Core.UnitTests/gen/Build/Runner/BuildHistoryCheckerTests.gen.h b/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryCheckerTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Build/Runner/BuildHistoryCheckerTests.gen.h rename to Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryCheckerTests.gen.h diff --git a/Source/Core.UnitTests/gen/Build/Runner/BuildHistoryJsonTests.gen.h b/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryJsonTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Build/Runner/BuildHistoryJsonTests.gen.h rename to Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryJsonTests.gen.h diff --git a/Source/Core.UnitTests/gen/Build/Runner/BuildHistoryManagerTests.gen.h b/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryManagerTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Build/Runner/BuildHistoryManagerTests.gen.h rename to Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryManagerTests.gen.h diff --git a/Source/Core.UnitTests/gen/Build/Runner/BuildHistoryTests.gen.h b/Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Build/Runner/BuildHistoryTests.gen.h rename to Source/Client/Core.UnitTests/gen/Build/Runner/BuildHistoryTests.gen.h diff --git a/Source/Core.UnitTests/gen/Build/Runner/BuildRunnerTests.gen.h b/Source/Client/Core.UnitTests/gen/Build/Runner/BuildRunnerTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Build/Runner/BuildRunnerTests.gen.h rename to Source/Client/Core.UnitTests/gen/Build/Runner/BuildRunnerTests.gen.h diff --git a/Source/Core.UnitTests/gen/Config/LocalUserConfigExtensionsTests.gen.h b/Source/Client/Core.UnitTests/gen/Config/LocalUserConfigExtensionsTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Config/LocalUserConfigExtensionsTests.gen.h rename to Source/Client/Core.UnitTests/gen/Config/LocalUserConfigExtensionsTests.gen.h diff --git a/Source/Core.UnitTests/gen/Config/LocalUserConfigJsonTests.gen.h b/Source/Client/Core.UnitTests/gen/Config/LocalUserConfigJsonTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Config/LocalUserConfigJsonTests.gen.h rename to Source/Client/Core.UnitTests/gen/Config/LocalUserConfigJsonTests.gen.h diff --git a/Source/Core.UnitTests/gen/Config/LocalUserConfigTests.gen.h b/Source/Client/Core.UnitTests/gen/Config/LocalUserConfigTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Config/LocalUserConfigTests.gen.h rename to Source/Client/Core.UnitTests/gen/Config/LocalUserConfigTests.gen.h diff --git a/Source/Core.UnitTests/gen/Main.cpp b/Source/Client/Core.UnitTests/gen/Main.cpp similarity index 86% rename from Source/Core.UnitTests/gen/Main.cpp rename to Source/Client/Core.UnitTests/gen/Main.cpp index c512b467..bc85065d 100644 --- a/Source/Core.UnitTests/gen/Main.cpp +++ b/Source/Client/Core.UnitTests/gen/Main.cpp @@ -7,14 +7,15 @@ #include import Opal; +import Opal.Extensions; import SoupCore; import json11; import SoupTest; +import SoupTestUtilities; using namespace Opal; using namespace Opal::System; using namespace SoupTest; -import SoupTestUtilities; #include "Api/SoupApiTests.gen.h" #include "Api/SoupApiJsonModelsTests.gen.h" @@ -25,8 +26,6 @@ import SoupTestUtilities; #include "Build/Runner/BuildHistoryManagerTests.gen.h" #include "Build/Runner/BuildRunnerTests.gen.h" -#include "Build/BuildEngineTests.gen.h" - #include "Config/LocalUserConfigExtensionsTests.gen.h" #include "Config/LocalUserConfigJsonTests.gen.h" #include "Config/LocalUserConfigTests.gen.h" @@ -36,11 +35,9 @@ import SoupTestUtilities; #include "Package/RecipeBuilderTests.gen.h" #include "Package/RecipeBuildManagerTests.gen.h" #include "Package/RecipeExtensionsTests.gen.h" -#include "Package/RecipeLanguageVersionTests.gen.h" #include "Package/RecipeJsonTests.gen.h" #include "Package/RecipeTests.gen.h" #include "Package/RecipeTomlTests.gen.h" -#include "Package/RecipeTypeTests.gen.h" #include "Utils/PathTests.gen.h" #include "Utils/SemanticVersionTests.gen.h" @@ -60,8 +57,6 @@ int main() state += RunBuildHistoryManagerTests(); state += RunBuildRunnerTests(); - state += RunBuildEngineTests(); - state += RunLocalUserConfigExtensionsTests(); state += RunLocalUserConfigJsonTests(); state += RunLocalUserConfigTests(); @@ -71,11 +66,9 @@ int main() state += RunRecipeBuilderTests(); state += RunRecipeBuildManagerTests(); state += RunRecipeExtensionsTests(); - state += RunRecipeLanguageVersionTests(); state += RunRecipeJsonTests(); state += RunRecipeTests(); state += RunRecipeTomlTests(); - state += RunRecipeTypeTests(); state += RunPathTests(); state += RunSemanticVersionTests(); diff --git a/Source/Core.UnitTests/gen/Package/PackageManagerTests.gen.h b/Source/Client/Core.UnitTests/gen/Package/PackageManagerTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Package/PackageManagerTests.gen.h rename to Source/Client/Core.UnitTests/gen/Package/PackageManagerTests.gen.h diff --git a/Source/Core.UnitTests/gen/Package/PackageReferenceTests.gen.h b/Source/Client/Core.UnitTests/gen/Package/PackageReferenceTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Package/PackageReferenceTests.gen.h rename to Source/Client/Core.UnitTests/gen/Package/PackageReferenceTests.gen.h diff --git a/Source/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h b/Source/Client/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h similarity index 73% rename from Source/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h rename to Source/Client/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h index c2703123..aa3ed1e7 100644 --- a/Source/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h +++ b/Source/Client/Core.UnitTests/gen/Package/RecipeBuildManagerTests.gen.h @@ -4,7 +4,7 @@ TestState RunRecipeBuildManagerTests() { auto className = "RecipeBuildManagerTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; state += SoupTest::RunTest(className, "Initialize", [&testClass]() { testClass->Initialize(); }); diff --git a/Source/Core.UnitTests/gen/Package/RecipeBuilderTests.gen.h b/Source/Client/Core.UnitTests/gen/Package/RecipeBuilderTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Package/RecipeBuilderTests.gen.h rename to Source/Client/Core.UnitTests/gen/Package/RecipeBuilderTests.gen.h diff --git a/Source/Core.UnitTests/gen/Package/RecipeExtensionsTests.gen.h b/Source/Client/Core.UnitTests/gen/Package/RecipeExtensionsTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Package/RecipeExtensionsTests.gen.h rename to Source/Client/Core.UnitTests/gen/Package/RecipeExtensionsTests.gen.h diff --git a/Source/Core.UnitTests/gen/Package/RecipeJsonTests.gen.h b/Source/Client/Core.UnitTests/gen/Package/RecipeJsonTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Package/RecipeJsonTests.gen.h rename to Source/Client/Core.UnitTests/gen/Package/RecipeJsonTests.gen.h diff --git a/Source/Core.UnitTests/gen/Package/RecipeTests.gen.h b/Source/Client/Core.UnitTests/gen/Package/RecipeTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Package/RecipeTests.gen.h rename to Source/Client/Core.UnitTests/gen/Package/RecipeTests.gen.h diff --git a/Source/Core.UnitTests/gen/Package/RecipeTomlTests.gen.h b/Source/Client/Core.UnitTests/gen/Package/RecipeTomlTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Package/RecipeTomlTests.gen.h rename to Source/Client/Core.UnitTests/gen/Package/RecipeTomlTests.gen.h diff --git a/Source/Core.UnitTests/gen/Utils/PathTests.gen.h b/Source/Client/Core.UnitTests/gen/Utils/PathTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Utils/PathTests.gen.h rename to Source/Client/Core.UnitTests/gen/Utils/PathTests.gen.h diff --git a/Source/Core.UnitTests/gen/Utils/SemanticVersionTests.gen.h b/Source/Client/Core.UnitTests/gen/Utils/SemanticVersionTests.gen.h similarity index 100% rename from Source/Core.UnitTests/gen/Utils/SemanticVersionTests.gen.h rename to Source/Client/Core.UnitTests/gen/Utils/SemanticVersionTests.gen.h diff --git a/Source/Client/Core/Api/ApiException.h b/Source/Client/Core/Api/ApiException.h new file mode 100644 index 00000000..3dbd517d --- /dev/null +++ b/Source/Client/Core/Api/ApiException.h @@ -0,0 +1,32 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once + +namespace Soup::Api +{ + /// + /// Api Exception + /// + class ApiException : public std::runtime_error + { + public: + /// + /// Initializes a new instance of the class. + /// + ApiException(const std::string& function, Network::HttpStatusCode statusCode) : + std::runtime_error("ApiFailed[" + function + "] " + std::to_string((int)statusCode)), + _statusCode(statusCode) + { + } + + Network::HttpStatusCode GetStatusCode() const + { + return _statusCode; + } + + private: + Network::HttpStatusCode _statusCode; + }; +} diff --git a/Source/Client/Core/Api/ApiStatusResult.h b/Source/Client/Core/Api/ApiStatusResult.h new file mode 100644 index 00000000..ac745e3f --- /dev/null +++ b/Source/Client/Core/Api/ApiStatusResult.h @@ -0,0 +1,28 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once + +namespace Soup::Api +{ + /// + /// Api Status Result + /// + template + class ApiStatusResult + { + public: + /// + /// Initializes a new instance of the class. + /// + ApiStatusResult(TStatus status, TResult result) : + Status(status), + Result(std::move(result)) + { + } + + TStatus Status; + TResult Result; + }; +} diff --git a/Source/Core/Api/Models/PackageCreateOrUpdateModel.h b/Source/Client/Core/Api/Models/PackageCreateOrUpdateModel.h similarity index 100% rename from Source/Core/Api/Models/PackageCreateOrUpdateModel.h rename to Source/Client/Core/Api/Models/PackageCreateOrUpdateModel.h diff --git a/Source/Core/Api/Models/PackageResultModel.h b/Source/Client/Core/Api/Models/PackageResultModel.h similarity index 95% rename from Source/Core/Api/Models/PackageResultModel.h rename to Source/Client/Core/Api/Models/PackageResultModel.h index acdbd46d..6aff8796 100644 --- a/Source/Core/Api/Models/PackageResultModel.h +++ b/Source/Client/Core/Api/Models/PackageResultModel.h @@ -12,6 +12,13 @@ namespace Soup::Api export class PackageResultModel { public: + PackageResultModel() : + _name(), + _description(), + _latest() + { + } + PackageResultModel( std::string name) : _name(std::move(name)), diff --git a/Source/Core/Api/Models/PackageSummaryModel.cs b/Source/Client/Core/Api/Models/PackageSummaryModel.cs similarity index 100% rename from Source/Core/Api/Models/PackageSummaryModel.cs rename to Source/Client/Core/Api/Models/PackageSummaryModel.cs diff --git a/Source/Core/Api/Models/PackageUpdateModel.cs b/Source/Client/Core/Api/Models/PackageUpdateModel.cs similarity index 100% rename from Source/Core/Api/Models/PackageUpdateModel.cs rename to Source/Client/Core/Api/Models/PackageUpdateModel.cs diff --git a/Source/Core/Api/Models/PublicationResultModel.cs b/Source/Client/Core/Api/Models/PublicationResultModel.cs similarity index 100% rename from Source/Core/Api/Models/PublicationResultModel.cs rename to Source/Client/Core/Api/Models/PublicationResultModel.cs diff --git a/Source/Core/Api/Models/PublicationSummaryModel.cs b/Source/Client/Core/Api/Models/PublicationSummaryModel.cs similarity index 100% rename from Source/Core/Api/Models/PublicationSummaryModel.cs rename to Source/Client/Core/Api/Models/PublicationSummaryModel.cs diff --git a/Source/Core/Api/Models/SearchModel.cs b/Source/Client/Core/Api/Models/SearchModel.cs similarity index 100% rename from Source/Core/Api/Models/SearchModel.cs rename to Source/Client/Core/Api/Models/SearchModel.cs diff --git a/Source/Client/Core/Api/SoupApi.h b/Source/Client/Core/Api/SoupApi.h new file mode 100644 index 00000000..8a84d2f6 --- /dev/null +++ b/Source/Client/Core/Api/SoupApi.h @@ -0,0 +1,230 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once +#include "SoupApiJsonModels.h" +#include "ApiException.h" +#include "../Auth/Models/ClientCredentialsTokenModel.h" + +namespace Soup::Api +{ + export enum class CreatePackageResult + { + Success, + Forbidden, + }; + + export enum class PublishPackageResult + { + Success, + PackageDoesNotExist, + AlreadyExists, + Forbidden, + }; + + /// + /// Represents a collection of functions to interact with the API endpoints + /// + export class SoupApi + { + private: + static const std::string_view ServiceEndpoint; + static const int ServicePort; + + public: + /// + /// Download a package version as an archive + /// + static std::string DownloadPackage(std::string_view name, SemanticVersion version) + { + auto client = Network::INetworkManager::Current().CreateClient( + ServiceEndpoint, + ServicePort); + + auto urlBuilder = std::stringstream(); + urlBuilder << "/v1/packages/" << name << "/v" << version.ToString() << "/download"; + auto localPath = urlBuilder.str(); + + Log::Diag(std::string(ServiceEndpoint) + std::to_string(ServicePort) + localPath); + auto response = client->Get(localPath); + + // Verify that we got a success + if (response.StatusCode != Network::HttpStatusCode::Ok) + { + throw ApiException("DownloadPackage", response.StatusCode); + } + + return response.Body; + } + + /// + /// Get the metadata for a package identified by the unique name + /// + static PackageResultModel GetPackage(std::string_view name) + { + auto client = Network::INetworkManager::Current().CreateClient( + ServiceEndpoint, + ServicePort); + + auto urlBuilder = std::stringstream(); + urlBuilder << "/v1/packages/" << name; + auto localPath = urlBuilder.str(); + + Log::Diag(std::string(ServiceEndpoint) + std::to_string(ServicePort) + localPath); + auto response = client->Get(localPath); + + // Verify that we got a success + if (response.StatusCode != Network::HttpStatusCode::Ok) + { + throw ApiException("GetPackage", response.StatusCode); + } + + // Parse the return result + auto result = SoupApiJsonModels::ParsePackageResult(response.Body); + return result; + } + + /// + /// Get a package publication metadata + /// + // Task GetPublicationAsync(string name, SemanticVersion version) + // { + // using (HttpClient client = new HttpClient()) + // { + // var url = $"{Constants.SoupRESTEndpointV1}/packages/{name}/{version}"; + // Log.Verbose(url); + // var response = await client.GetAsync(url); + + // // Verify that we got a success + // response.EnsureSuccessStatusCode(); + + // // Parse the return result + // var content = await response.Content.ReadAsStringAsync(); + // var result = JsonConvert.DeserializeObject(content); + + // return result; + // } + // } + + /// + /// Publish a new package version as an archive + /// + static PublishPackageResult PublishPackage( + const ClientCredentialsTokenModel& token, + std::string_view name, + SemanticVersion version, + std::istream& value) + { + auto client = Network::INetworkManager::Current().CreateClient( + ServiceEndpoint, + ServicePort); + + client->SetAuthenticationToken("Bearer", token.AccessToken); + + auto urlBuilder = std::stringstream(); + urlBuilder << "/v1/packages/" << name << "/v" << version.ToString(); + auto localPath = urlBuilder.str(); + + auto contentType = "application/x-7z-compressed"; + + Log::Diag(std::string(ServiceEndpoint) + std::to_string(ServicePort) + localPath); + auto response = client->Put(localPath, contentType, value); + + // Verify that we got a success + switch (response.StatusCode) + { + case Network::HttpStatusCode::Created: + return PublishPackageResult::Success; + case Network::HttpStatusCode::NotFound: + return PublishPackageResult::PackageDoesNotExist; + case Network::HttpStatusCode::Conflict: + return PublishPackageResult::AlreadyExists; + case Network::HttpStatusCode::Forbidden: + return PublishPackageResult::Forbidden; + default: + throw Api::ApiException("PublishPackage", response.StatusCode); + } + } + + /// + /// Create a package + /// + static std::pair CreatePackage( + const ClientCredentialsTokenModel& token, + std::string_view name, + const PackageCreateOrUpdateModel& model) + { + auto client = Network::INetworkManager::Current().CreateClient( + ServiceEndpoint, + ServicePort); + + client->SetAuthenticationToken("Bearer", token.AccessToken); + + auto urlBuilder = std::stringstream(); + urlBuilder << "/v1/packages/" << name; + auto localPath = urlBuilder.str(); + + std::stringstream content; + SoupApiJsonModels::SerializePackageCreateOrUpdate(model, content); + + auto contentType = "application/json"; + + Log::Diag(std::string(ServiceEndpoint) + std::to_string(ServicePort) + localPath); + auto response = client->Put(localPath, contentType, content); + + // Verify that we got a success + switch (response.StatusCode) + { + case Network::HttpStatusCode::Created: + { + // Parse the return result + auto result = SoupApiJsonModels::ParsePackageResult(response.Body); + return std::make_pair( + CreatePackageResult::Success, + std::move(result)); + } + case Network::HttpStatusCode::Forbidden: + { + return std::make_pair( + CreatePackageResult::Forbidden, + PackageResultModel()); + } + default: + { + throw Api::ApiException("CreatePackage", response.StatusCode); + } + } + } + + /// + /// Search for a package using the query string + /// + // Task SearchPackagesAsync(string q) + // { + // using (HttpClient client = new HttpClient()) + // { + // var url = $"{Constants.SoupRESTEndpointV1}/packages?q={q}"; + // Log.Verbose(url); + // var response = await client.GetAsync(url); + + // // Verify that we got a success + // response.EnsureSuccessStatusCode(); + + // // Parse the return result + // var content = await response.Content.ReadAsStringAsync(); + // var result = JsonConvert.DeserializeObject(content); + + // return result; + // } + // } + }; + +#ifdef LOCAL_DEBUG + /*static*/ const std::string_view SoupApi::ServiceEndpoint = "localhost"; + /*static*/ const int SoupApi::ServicePort = 7071; +#else + /*static*/ const std::string_view SoupApi::ServiceEndpoint = "api.soupbuild.com"; + /*static*/ const int SoupApi::ServicePort = 443; +#endif +} diff --git a/Source/Core/Api/SoupApiJsonModels.h b/Source/Client/Core/Api/SoupApiJsonModels.h similarity index 100% rename from Source/Core/Api/SoupApiJsonModels.h rename to Source/Client/Core/Api/SoupApiJsonModels.h diff --git a/Source/Core/Auth/Models/ClientCredentialsTokenModel.h b/Source/Client/Core/Auth/Models/ClientCredentialsTokenModel.h similarity index 100% rename from Source/Core/Auth/Models/ClientCredentialsTokenModel.h rename to Source/Client/Core/Auth/Models/ClientCredentialsTokenModel.h diff --git a/Source/Core/Auth/Models/OpenIdConfigurationModel.h b/Source/Client/Core/Auth/Models/OpenIdConfigurationModel.h similarity index 100% rename from Source/Core/Auth/Models/OpenIdConfigurationModel.h rename to Source/Client/Core/Auth/Models/OpenIdConfigurationModel.h diff --git a/Source/Client/Core/Auth/SoupAuth.h b/Source/Client/Core/Auth/SoupAuth.h new file mode 100644 index 00000000..b0fd82a9 --- /dev/null +++ b/Source/Client/Core/Auth/SoupAuth.h @@ -0,0 +1,143 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once +#include "SoupAuthJsonModels.h" +#include "../Api/ApiException.h" +#include "../Api/ApiStatusResult.h" + +namespace Soup::Api +{ + enum class RequestClientCredentialsTokenResult + { + Success, + InvalidUserNameOrPassword, + }; + + /// + /// Represents a collection of functions to interact with the Auth endpoints + /// + class SoupAuth + { + private: + static const std::string_view ServiceEndpoint; + static const int ServicePort; + + public: + /// + /// Get the OpenId configuration + /// + static OpenIdConfigurationModel GetOpenIdConfiguration() + { + auto client = Network::INetworkManager::Current().CreateClient( + ServiceEndpoint, + ServicePort); + + auto urlBuilder = std::stringstream(); + urlBuilder << "/.well-known/openid-configuration"; + auto localPath = urlBuilder.str(); + + Log::Diag(std::string(ServiceEndpoint) + std::to_string(ServicePort) + localPath); + auto response = client->Get(localPath); + + // Verify that we got a success + if (response.StatusCode != Network::HttpStatusCode::Ok) + { + throw ApiException("GetOpenIdConfiguration", response.StatusCode); + } + + // Parse the return result + auto result = SoupAuthJsonModels::ParseOpenIdConfigurationResult(response.Body); + return result; + } + + /// + /// Get the OpenId configuration + /// + static ApiStatusResult RequestClientCredentialsToken( + const std::string& tokenEndpoint, + const std::string& userName, + const std::string& password) + { + // TODO: Implement an opal url class + // https://stackoverflow.com/questions/5620235/cpp-regular-expression-to-validate-url/31613265 + auto urlParserRegex = std::regex( + R"(^(([^:\/?#]+):)?(//([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)", + std::regex::extended); + std::smatch urlParts; + if (!std::regex_match(tokenEndpoint, urlParts, urlParserRegex)) + { + throw std::runtime_error("Invalid token endpoint url."); + } + + auto scheme = urlParts[2].str(); + auto authority = urlParts[4].str(); + auto path = urlParts[5].str(); + auto query = urlParts[7].str(); + auto fragment = urlParts[9].str(); + + auto endpoint = authority; + auto port = 80; + if (scheme == "https") + { + port = 443; + } + + auto portDelimiter = authority.find(':'); + if (portDelimiter != std::string::npos) + { + endpoint = authority.substr(0, portDelimiter); + port = std::stoi(authority.substr(portDelimiter + 1)); + } + + auto client = Network::INetworkManager::Current().CreateClient( + endpoint, + port); + + auto urlBuilder = std::stringstream(); + urlBuilder << path << query << fragment; + auto localPath = urlBuilder.str(); + + auto secret = "secret_for_client"; + auto scope = "soup_api"; + auto clientId = "soup.client"; + + auto content = std::stringstream(); + content << "grant_type=password"; + content << "&username=" << httplib::detail::encode_url(userName); + content << "&password=" << httplib::detail::encode_url(password); + content << "&scope=" << httplib::detail::encode_url(scope); + content << "&client_id=" << httplib::detail::encode_url(clientId); + + auto contentType = "application/x-www-form-urlencoded"; + + Log::Diag(endpoint + std::to_string(port) + localPath); + auto response = client->Post(localPath, contentType, content); + + // Verify that we got a success + switch (response.StatusCode) + { + case Network::HttpStatusCode::Ok: + // Parse the return result + return ApiStatusResult( + RequestClientCredentialsTokenResult::Success, + SoupAuthJsonModels::ParseClientCredentialsTokenModel(response.Body)); + case Network::HttpStatusCode::BadRequest: + return ApiStatusResult( + RequestClientCredentialsTokenResult::InvalidUserNameOrPassword, + ClientCredentialsTokenModel()); + default: + throw ApiException("RequestClientCredentialsToken", response.StatusCode); + } + } + }; + +#ifdef LOCAL_DEBUG + /*static*/ const std::string_view SoupAuth::ServiceEndpoint = "localhost"; + /*static*/ const int SoupAuth::ServicePort = 5051; +#else + /*static*/ const std::string_view SoupAuth::ServiceEndpoint = "auth.soupbuild.com"; + /*static*/ const int SoupAuth::ServicePort = 443; +#endif +} diff --git a/Source/Core/Auth/SoupAuthJsonModels.h b/Source/Client/Core/Auth/SoupAuthJsonModels.h similarity index 100% rename from Source/Core/Auth/SoupAuthJsonModels.h rename to Source/Client/Core/Auth/SoupAuthJsonModels.h diff --git a/Source/Core/Build/Runner/BuildHistory.h b/Source/Client/Core/Build/Runner/BuildHistory.h similarity index 100% rename from Source/Core/Build/Runner/BuildHistory.h rename to Source/Client/Core/Build/Runner/BuildHistory.h diff --git a/Source/Core/Build/Runner/BuildHistoryChecker.h b/Source/Client/Core/Build/Runner/BuildHistoryChecker.h similarity index 100% rename from Source/Core/Build/Runner/BuildHistoryChecker.h rename to Source/Client/Core/Build/Runner/BuildHistoryChecker.h diff --git a/Source/Core/Build/Runner/BuildHistoryJson.h b/Source/Client/Core/Build/Runner/BuildHistoryJson.h similarity index 100% rename from Source/Core/Build/Runner/BuildHistoryJson.h rename to Source/Client/Core/Build/Runner/BuildHistoryJson.h diff --git a/Source/Core/Build/Runner/BuildHistoryManager.h b/Source/Client/Core/Build/Runner/BuildHistoryManager.h similarity index 100% rename from Source/Core/Build/Runner/BuildHistoryManager.h rename to Source/Client/Core/Build/Runner/BuildHistoryManager.h diff --git a/Source/Core/Build/Runner/BuildRunner.h b/Source/Client/Core/Build/Runner/BuildRunner.h similarity index 94% rename from Source/Core/Build/Runner/BuildRunner.h rename to Source/Client/Core/Build/Runner/BuildRunner.h index 6a052eba..ce03c1f2 100644 --- a/Source/Core/Build/Runner/BuildRunner.h +++ b/Source/Client/Core/Build/Runner/BuildRunner.h @@ -25,7 +25,7 @@ namespace Soup::Build } void Execute( - const std::vector>& nodes, + const std::vector>& nodes, const Path& objectDirectory, bool forceBuild) { @@ -62,7 +62,7 @@ namespace Soup::Build /// Build dependencies /// void BuildDependencies( - const std::vector>& nodes, + const std::vector>& nodes, const std::set& parentSet) { for (auto& node : nodes) @@ -95,7 +95,7 @@ namespace Soup::Build /// Execute the collection of build nodes /// void CheckExecuteNodes( - const std::vector>& nodes, + const std::vector>& nodes, bool forceBuild) { for (auto& node : nodes) @@ -125,7 +125,7 @@ namespace Soup::Build /// Execute a single build node and all of its children /// void ExecuteNode( - const BuildGraphNode& node, + const Runtime::BuildGraphNode& node, bool forceBuild) { bool buildRequired = forceBuild; @@ -256,7 +256,7 @@ namespace Soup::Build } bool TryParsesHeaderIncludes( - const BuildGraphNode& node, + const Runtime::BuildGraphNode& node, const std::string& output, std::vector& headerIncludes, std::stringstream& cleanOutput) diff --git a/Source/Core/Build/Runner/CompileResult.h b/Source/Client/Core/Build/Runner/CompileResult.h similarity index 100% rename from Source/Core/Build/Runner/CompileResult.h rename to Source/Client/Core/Build/Runner/CompileResult.h diff --git a/Source/Core/Config/LocalUserConfig.h b/Source/Client/Core/Config/LocalUserConfig.h similarity index 100% rename from Source/Core/Config/LocalUserConfig.h rename to Source/Client/Core/Config/LocalUserConfig.h diff --git a/Source/Core/Config/LocalUserConfigExtensions.h b/Source/Client/Core/Config/LocalUserConfigExtensions.h similarity index 100% rename from Source/Core/Config/LocalUserConfigExtensions.h rename to Source/Client/Core/Config/LocalUserConfigExtensions.h diff --git a/Source/Core/Config/LocalUserConfigJson.h b/Source/Client/Core/Config/LocalUserConfigJson.h similarity index 100% rename from Source/Core/Config/LocalUserConfigJson.h rename to Source/Client/Core/Config/LocalUserConfigJson.h diff --git a/Source/Core/Constants.h b/Source/Client/Core/Constants.h similarity index 100% rename from Source/Core/Constants.h rename to Source/Client/Core/Constants.h diff --git a/Source/Core/Module.cpp b/Source/Client/Core/Module.cpp similarity index 75% rename from Source/Core/Module.cpp rename to Source/Client/Core/Module.cpp index 03cf0114..5c5c972d 100644 --- a/Source/Core/Module.cpp +++ b/Source/Client/Core/Module.cpp @@ -19,9 +19,10 @@ export module SoupCore; import Opal; -import SoupEngineDefinition; -import SoupEngineWrapper; -import SoupEngineCore; +import Opal.Extensions; +import Soup.Build; +import Soup.Build.Extensions; +import Soup.Build.Runtime; import LzmaSdk; import json11; import toml11; @@ -39,15 +40,8 @@ using namespace Opal; #include "Build/Runner/BuildHistoryManager.h" #include "Build/Runner/BuildRunner.h" -#include "Build/BuildEngine.h" -#include "Build/BuildUtilities.h" - #include "Config/LocalUserConfigExtensions.h" -#include "Compiler/ICompiler.h" -#include "Compiler/CompileArguments.h" -#include "Compiler/MockCompiler.h" - #include "Package/PackageManager.h" #include "Package/Recipe.h" #include "Package/RecipeBuildManager.h" diff --git a/Source/Core/Package/LzmaExtractCallback.h b/Source/Client/Core/Package/LzmaExtractCallback.h similarity index 96% rename from Source/Core/Package/LzmaExtractCallback.h rename to Source/Client/Core/Package/LzmaExtractCallback.h index cc95440e..eb04cbd6 100644 --- a/Source/Core/Package/LzmaExtractCallback.h +++ b/Source/Client/Core/Package/LzmaExtractCallback.h @@ -90,7 +90,7 @@ namespace Soup } // if (_extractMode && _processedFileInfo.AttribDefined) - // NWindows::NFile::NDir::SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib); + // NWindows::NFile::NDir::SetFileAttrib_PosixHighDetect(_diskFilePath, _processedFileInfo.Attrib); } private: diff --git a/Source/Core/Package/LzmaInStream.h b/Source/Client/Core/Package/LzmaInStream.h similarity index 100% rename from Source/Core/Package/LzmaInStream.h rename to Source/Client/Core/Package/LzmaInStream.h diff --git a/Source/Core/Package/LzmaOutStream.h b/Source/Client/Core/Package/LzmaOutStream.h similarity index 100% rename from Source/Core/Package/LzmaOutStream.h rename to Source/Client/Core/Package/LzmaOutStream.h diff --git a/Source/Core/Package/LzmaSequentialOutStream.h b/Source/Client/Core/Package/LzmaSequentialOutStream.h similarity index 100% rename from Source/Core/Package/LzmaSequentialOutStream.h rename to Source/Client/Core/Package/LzmaSequentialOutStream.h diff --git a/Source/Core/Package/LzmaUpdateCallback.h b/Source/Client/Core/Package/LzmaUpdateCallback.h similarity index 100% rename from Source/Core/Package/LzmaUpdateCallback.h rename to Source/Client/Core/Package/LzmaUpdateCallback.h diff --git a/Source/Core/Package/PackageManager.h b/Source/Client/Core/Package/PackageManager.h similarity index 90% rename from Source/Core/Package/PackageManager.h rename to Source/Client/Core/Package/PackageManager.h index 1e7afb90..13d2cbfb 100644 --- a/Source/Core/Package/PackageManager.h +++ b/Source/Client/Core/Package/PackageManager.h @@ -233,6 +233,9 @@ namespace Soup case Api::PublishPackageResult::AlreadyExists: Log::HighPriority("A Package with this version already exists"); break; + case Api::PublishPackageResult::Forbidden: + Log::HighPriority("User account forbidden to create package. Make sure you have verified your email."); + break; default: throw std::runtime_error("Unknown PublishPackageResult"); } @@ -247,28 +250,46 @@ namespace Soup tokenResult.Result, recipe.GetName(), createModel); - - // Retry - Log::HighPriority("Retry publish package"); - - // Reset the archive file - auto& archiveStream = archiveFile->GetInStream(); - archiveStream.clear(); - archiveStream.seekg(0, std::ios::beg); - - publishResult = Api::SoupApi::PublishPackage( - tokenResult.Result, - recipe.GetName(), - recipe.GetVersion(), - archiveStream); - switch (publishResult) + + switch (createdPackage.first) { - case Api::PublishPackageResult::Success: - // All Good + case Api::CreatePackageResult::Success: + { Log::Info("Package version created"); + + // Retry + Log::HighPriority("Retry publish package"); + + // Reset the archive file + auto& archiveStream = archiveFile->GetInStream(); + archiveStream.clear(); + archiveStream.seekg(0, std::ios::beg); + + publishResult = Api::SoupApi::PublishPackage( + tokenResult.Result, + recipe.GetName(), + recipe.GetVersion(), + archiveStream); + switch (publishResult) + { + case Api::PublishPackageResult::Success: + // All Good + Log::Info("Package version created"); + break; + default: + throw std::runtime_error("Unknown PublishPackageResult"); + } + break; + } + case Api::CreatePackageResult::Forbidden: + { + Log::HighPriority("User account forbidden to create package. Make sure you have verified your email."); break; + } default: + { throw std::runtime_error("Unknown PublishPackageResult"); + } } } } diff --git a/Source/Core/Package/PackageReference.h b/Source/Client/Core/Package/PackageReference.h similarity index 100% rename from Source/Core/Package/PackageReference.h rename to Source/Client/Core/Package/PackageReference.h diff --git a/Source/Core/Package/Recipe.h b/Source/Client/Core/Package/Recipe.h similarity index 95% rename from Source/Core/Package/Recipe.h rename to Source/Client/Core/Package/Recipe.h index 8059bbf5..41a5455c 100644 --- a/Source/Core/Package/Recipe.h +++ b/Source/Client/Core/Package/Recipe.h @@ -4,8 +4,6 @@ #pragma once #include "PackageReference.h" -#include "RecipeType.h" -#include "RecipeLanguageVersion.h" #include "RecipeValue.h" namespace Soup @@ -56,8 +54,8 @@ namespace Soup Recipe( std::string_view name, SemanticVersion version, - std::optional type, - std::optional languageVersion, + std::optional type, + std::optional languageVersion, std::optional> dependencies, std::optional> extensions, std::optional publicFile, @@ -146,15 +144,15 @@ namespace Soup return HasValue(Property_Type); } - RecipeType GetType() + Build::Extensions::RecipeType GetType() { if (!HasType()) throw std::runtime_error("No type."); - return ParseRecipeType(GetValue(Property_Type).AsString()); + return Build::Extensions::ParseRecipeType(GetValue(Property_Type).AsString()); } - void SetType(RecipeType value) + void SetType(Build::Extensions::RecipeType value) { return EnsureValue(Property_Type).SetValueString(ToString(value)); } @@ -167,16 +165,16 @@ namespace Soup return HasValue(Property_Language); } - RecipeLanguageVersion GetLanguageVersion() + Build::Extensions::RecipeLanguageVersion GetLanguageVersion() { if (!HasLanguageVersion()) throw std::runtime_error("No language version."); - return ParseRecipeLanguageVersion( + return Build::Extensions::ParseRecipeLanguageVersion( GetValue(Property_Language).AsString()); } - void SetLanguageVersion(RecipeLanguageVersion value) + void SetLanguageVersion(Build::Extensions::RecipeLanguageVersion value) { return EnsureValue(Property_Language).SetValueString(ToString(value)); } diff --git a/Source/Core/Package/RecipeBuildArguments.h b/Source/Client/Core/Package/RecipeBuildArguments.h similarity index 90% rename from Source/Core/Package/RecipeBuildArguments.h rename to Source/Client/Core/Package/RecipeBuildArguments.h index a70007cd..4989ad2e 100644 --- a/Source/Core/Package/RecipeBuildArguments.h +++ b/Source/Client/Core/Package/RecipeBuildArguments.h @@ -45,6 +45,11 @@ namespace Soup /// std::vector PlatformLibraries; + /// + /// Gets or sets a value indicating whether to skip running the build operations + /// + bool SkipRun; + /// /// Gets or sets a value indicating whether to force a rebuild /// diff --git a/Source/Core/Package/RecipeBuildManager.h b/Source/Client/Core/Package/RecipeBuildManager.h similarity index 91% rename from Source/Core/Package/RecipeBuildManager.h rename to Source/Client/Core/Package/RecipeBuildManager.h index 0e13dd63..4badf240 100644 --- a/Source/Core/Package/RecipeBuildManager.h +++ b/Source/Client/Core/Package/RecipeBuildManager.h @@ -7,7 +7,7 @@ #include "RecipeExtensions.h" #include "Build/Runner/BuildRunner.h" -namespace Soup::Build +namespace Soup::Build::Runtime { /// /// The recipe build manager that knows how to perform the correct build for a recipe @@ -311,7 +311,7 @@ namespace Soup::Build { // Create a new build system for the requested build auto buildSystem = BuildSystem(); - auto activeState = ValueTableWrapper(state.GetActiveState()); + auto activeState = Extensions::ValueTableWrapper(state.GetActiveState()); // Select the correct compiler to use std::string activeCompiler = ""; @@ -326,11 +326,16 @@ namespace Soup::Build activeCompiler = _runtimeCompiler; } + auto binaryDirectory = RecipeExtensions::GetBinaryDirectory(_systemCompiler, arguments.Flavor); + auto objectDirectory = RecipeExtensions::GetObjectDirectory(_systemCompiler, arguments.Flavor); + // Set the input properties activeState.EnsureValue("PackageRoot").SetValueString(packageRoot.ToString()); activeState.EnsureValue("ForceRebuild").SetValueBoolean(arguments.ForceRebuild); // TOOD: Remove? activeState.EnsureValue("BuildFlavor").SetValueString(arguments.Flavor); activeState.EnsureValue("CompilerName").SetValueString(activeCompiler); + activeState.EnsureValue("BinaryDirectory").SetValueString(binaryDirectory.ToString()); + activeState.EnsureValue("ObjectDirectory").SetValueString(objectDirectory.ToString()); activeState.EnsureValue("PlatformLibraries").SetValueStringList(arguments.PlatformLibraries); activeState.EnsureValue("PlatformIncludePaths").SetValueStringList(arguments.PlatformIncludePaths); activeState.EnsureValue("PlatformLibraryPaths").SetValueStringList(arguments.PlatformLibraryPaths); @@ -353,7 +358,7 @@ namespace Soup::Build auto packagePath = RecipeExtensions::GetPackageReferencePath(packageRoot, dependency); auto libraryPath = RecipeExtensions::GetRecipeOutputPath( packagePath, - RecipeExtensions::GetBinaryDirectory(_systemCompiler, arguments.Flavor), + binaryDirectory, std::string("dll")); auto library = RunBuildExtension(libraryPath, buildSystem); @@ -366,14 +371,16 @@ namespace Soup::Build // Find the output object directory so we can use it in the runner auto buildTable = activeState.GetValue("Build").AsTable(); - auto objectDirectory = Path(buildTable.GetValue("ObjectDirectory").AsString().GetValue()); - - // Execute the build nodes - auto runner = BuildRunner(packageRoot); - runner.Execute( - state.GetBuildNodes(), - objectDirectory, - arguments.ForceRebuild); + + if (!arguments.SkipRun) + { + // Execute the build nodes + auto runner = BuildRunner(packageRoot); + runner.Execute( + state.GetBuildNodes(), + objectDirectory, + arguments.ForceRebuild); + } } } diff --git a/Source/Core/Package/RecipeExtensions.h b/Source/Client/Core/Package/RecipeExtensions.h similarity index 94% rename from Source/Core/Package/RecipeExtensions.h rename to Source/Client/Core/Package/RecipeExtensions.h index b2bf4b38..54d6e1dd 100644 --- a/Source/Core/Package/RecipeExtensions.h +++ b/Source/Client/Core/Package/RecipeExtensions.h @@ -34,7 +34,9 @@ namespace Soup // Read the contents of the recipe file try { - result = RecipeToml::Deserialize(file->GetInStream()); + result = RecipeToml::Deserialize( + recipeFile, + file->GetInStream()); return true; } catch (std::exception& ex) diff --git a/Source/Core/Package/RecipeJson.h b/Source/Client/Core/Package/RecipeJson.h similarity index 100% rename from Source/Core/Package/RecipeJson.h rename to Source/Client/Core/Package/RecipeJson.h diff --git a/Source/Core/Package/RecipeToml.h b/Source/Client/Core/Package/RecipeToml.h similarity index 92% rename from Source/Core/Package/RecipeToml.h rename to Source/Client/Core/Package/RecipeToml.h index 13750855..d577b603 100644 --- a/Source/Core/Package/RecipeToml.h +++ b/Source/Client/Core/Package/RecipeToml.h @@ -20,12 +20,14 @@ namespace Soup /// /// Load from stream /// - static Recipe Deserialize(std::istream& stream) + static Recipe Deserialize( + const Path& recipeFile, + std::istream& stream) { try { // Read the contents of the recipe file - auto root = toml::parse(stream, "Recipe.toml"); + auto root = toml::parse(stream, recipeFile.ToString()); if (!root.is_table()) throw std::runtime_error("Recipe Toml file root must be a table."); diff --git a/Source/Core/Package/RecipeValue.h b/Source/Client/Core/Package/RecipeValue.h similarity index 100% rename from Source/Core/Package/RecipeValue.h rename to Source/Client/Core/Package/RecipeValue.h diff --git a/Source/Client/Core/Recipe.toml b/Source/Client/Core/Recipe.toml new file mode 100644 index 00000000..e8998d99 --- /dev/null +++ b/Source/Client/Core/Recipe.toml @@ -0,0 +1,25 @@ +Name = "SoupCore" +Version = "0.1.0" + +Dependencies = [ + "../../../Dependencies/LzmaSdk/CPP/Library/", + # "../../../Dependencies/json11/", + "json11@1.0.0", + # "../../../Dependencies/toml11/", + "toml11@1.0.0", + "../OpalExtensions/", + "../../Build/Core/", + # "Soup.Build@0.2.0", + "../../Build/Extensions/", + # "Soup.Build.Extensions@0.2.0", + "../../Build/Runtime/", +] +Defines = [ + # "LOCAL_DEBUG", +] +Public = "Module.cpp" +IncludePaths = [ + "./", + "Compiler/", + "Utils/", +] diff --git a/Source/Core/Utils/HandledException.h b/Source/Client/Core/Utils/HandledException.h similarity index 100% rename from Source/Core/Utils/HandledException.h rename to Source/Client/Core/Utils/HandledException.h diff --git a/Source/Core/Utils/Helpers.h b/Source/Client/Core/Utils/Helpers.h similarity index 100% rename from Source/Core/Utils/Helpers.h rename to Source/Client/Core/Utils/Helpers.h diff --git a/Source/Client/OpalExtensions/Module.cpp b/Source/Client/OpalExtensions/Module.cpp new file mode 100644 index 00000000..e6f93556 --- /dev/null +++ b/Source/Client/OpalExtensions/Module.cpp @@ -0,0 +1,31 @@ +module; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif + +export module Opal.Extensions; + +import HttpLib; + +#include "Network/HttpLibNetworkManager.h" +#include "Network/MockNetworkManager.h" +#include "Network/ScopedNetworkManagerRegister.h" diff --git a/Source/Opal/Network/BasicCredentialsManager.h b/Source/Client/OpalExtensions/Network/BasicCredentialsManager.h similarity index 100% rename from Source/Opal/Network/BasicCredentialsManager.h rename to Source/Client/OpalExtensions/Network/BasicCredentialsManager.h diff --git a/Source/Opal/Network/HttpLibClient.h b/Source/Client/OpalExtensions/Network/HttpLibClient.h similarity index 93% rename from Source/Opal/Network/HttpLibClient.h rename to Source/Client/OpalExtensions/Network/HttpLibClient.h index af6226c5..715536dd 100644 --- a/Source/Opal/Network/HttpLibClient.h +++ b/Source/Client/OpalExtensions/Network/HttpLibClient.h @@ -25,7 +25,9 @@ namespace Opal::Network _client = std::make_unique(host, port); // Enable proxy for fiddler - // _client->set_proxy("127.0.0.1", 8888); + #ifdef ENABLE_FIDDLER_PROXY + _client->set_proxy("127.0.0.1", 8888); + #endif } /// diff --git a/Source/Opal/Network/HttpLibNetworkManager.h b/Source/Client/OpalExtensions/Network/HttpLibNetworkManager.h similarity index 100% rename from Source/Opal/Network/HttpLibNetworkManager.h rename to Source/Client/OpalExtensions/Network/HttpLibNetworkManager.h diff --git a/Source/Opal/Network/HttpResponse.h b/Source/Client/OpalExtensions/Network/HttpResponse.h similarity index 100% rename from Source/Opal/Network/HttpResponse.h rename to Source/Client/OpalExtensions/Network/HttpResponse.h diff --git a/Source/Opal/Network/HttpStatusCode.h b/Source/Client/OpalExtensions/Network/HttpStatusCode.h similarity index 100% rename from Source/Opal/Network/HttpStatusCode.h rename to Source/Client/OpalExtensions/Network/HttpStatusCode.h diff --git a/Source/Opal/Network/IHttpClient.h b/Source/Client/OpalExtensions/Network/IHttpClient.h similarity index 100% rename from Source/Opal/Network/IHttpClient.h rename to Source/Client/OpalExtensions/Network/IHttpClient.h diff --git a/Source/Opal/Network/INetworkManager.h b/Source/Client/OpalExtensions/Network/INetworkManager.h similarity index 100% rename from Source/Opal/Network/INetworkManager.h rename to Source/Client/OpalExtensions/Network/INetworkManager.h diff --git a/Source/Opal/Network/MockHttpClient.h b/Source/Client/OpalExtensions/Network/MockHttpClient.h similarity index 100% rename from Source/Opal/Network/MockHttpClient.h rename to Source/Client/OpalExtensions/Network/MockHttpClient.h diff --git a/Source/Opal/Network/MockNetworkManager.h b/Source/Client/OpalExtensions/Network/MockNetworkManager.h similarity index 100% rename from Source/Opal/Network/MockNetworkManager.h rename to Source/Client/OpalExtensions/Network/MockNetworkManager.h diff --git a/Source/Opal/Network/ScopedNetworkManagerRegister.h b/Source/Client/OpalExtensions/Network/ScopedNetworkManagerRegister.h similarity index 100% rename from Source/Opal/Network/ScopedNetworkManagerRegister.h rename to Source/Client/OpalExtensions/Network/ScopedNetworkManagerRegister.h diff --git a/Source/Client/OpalExtensions/Network/TLSClient.h b/Source/Client/OpalExtensions/Network/TLSClient.h new file mode 100644 index 00000000..1a8ba2e7 --- /dev/null +++ b/Source/Client/OpalExtensions/Network/TLSClient.h @@ -0,0 +1,362 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +#pragma once + +#include "BasicCredentialsManager.h" + +namespace Opal::Network +{ + typedef SOCKET socket_type; + + inline socket_type invalid_socket() { return INVALID_SOCKET; } + + inline int close(int fd) + { + return ::closesocket(fd); + } + + inline int send(int s, const uint8_t* buf, size_t len, int flags) + { + return ::send(s, reinterpret_cast(buf), static_cast(len), flags); + } + + inline int read(int s, void* buf, size_t len) + { + return ::recv(s, reinterpret_cast(buf), static_cast(len), 0); + } + + class TLSClient final : public Botan::TLS::Callbacks + { + public: + TLSClient() + { + // TODO init_sockets(); + } + + ~TLSClient() + { + // TODO stop_sockets(); + } + + void DoIt() + { + // TODO client cert auth + const std::string host = "www.soupbuild.com"; + const uint16_t port = 443; + const std::string transport = "tcp"; + const std::string next_protos = ""; + const bool use_system_cert_store = true; + const std::string trusted_CAs = ""; + + auto session_mgr = std::make_unique(rng()); + + auto policy = std::make_unique(); + + const bool use_tcp = (transport == "tcp"); + + const std::vector protocols_to_offer = Botan::split_on(next_protos, ','); + + Botan::TLS::Protocol_Version version = Botan::TLS::Protocol_Version::TLS_V12; + + if (policy->acceptable_protocol_version(version) == false) + { + throw std::runtime_error("The policy specified does not allow the requested TLS version"); + } + + struct sockaddr_storage addrbuf; + std::string hostname; + if(!host.empty() && + inet_pton(AF_INET, host.c_str(), &addrbuf) != 1 && + inet_pton(AF_INET6, host.c_str(), &addrbuf) != 1) + { + hostname = host; + } + + m_sockfd = connect_to_host(host, port, use_tcp); + + BasicCredentialsManager creds(use_system_cert_store, trusted_CAs); + + Botan::TLS::Client client( + *this, + *session_mgr, + creds, + *policy, + rng(), + Botan::TLS::Server_Information(hostname, port), + version, + protocols_to_offer); + + bool first_active = true; + + while (!client.is_closed()) + { + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(m_sockfd, &readfds); + + if(client.is_active()) + { + // FD_SET(STDIN_FILENO, &readfds); + if (first_active && !protocols_to_offer.empty()) + { + std::string app = client.application_protocol(); + if (app != "") + { + Log::HighPriority("Server choose protocol: " + client.application_protocol()); + } + + first_active = false; + } + } + + struct timeval timeout = { 1, 0 }; + + ::select(static_cast(m_sockfd + 1), &readfds, nullptr, nullptr, &timeout); + + if (FD_ISSET(m_sockfd, &readfds)) + { + uint8_t buf[4 * 1024] = { 0 }; + + auto got = read(m_sockfd, buf, sizeof(buf)); + + if (got == 0) + { + Log::HighPriority("EOF on socket"); + break; + } + else if (got == -1) + { + Log::HighPriority("Socket error: " + std::to_string(errno)); + continue; + } + + client.received_data(buf, got); + } + + // if (FD_ISSET(STDIN_FILENO, &readfds)) + // { + // uint8_t buf[1024] = { 0 }; + // ssize_t got = read(STDIN_FILENO, buf, sizeof(buf)); + + // if (got == 0) + // { + // Log::HighPriority("EOF on stdin"); + // client.close(); + // break; + // } + // else if (got == -1) + // { + // Log::HighPriority("Stdin error: " + errno + " " + err_to_string(errno)); + // continue; + // } + + // if(got == 2 && buf[1] == '\n') + // { + // char cmd = buf[0]; + + // if(cmd == 'R' || cmd == 'r') + // { + // Log::HighPriority("Client initiated renegotiation"); + // client.renegotiate(cmd == 'R'); + // } + // else if(cmd == 'Q') + // { + // Log::HighPriority("Client initiated close"); + // client.close(); + // } + // } + // else + // { + // client.send(buf, got); + // } + // } + + if (client.timeout_check()) + { + Log::HighPriority("Timeout detected"); + } + } + + close(m_sockfd); + } + + private: + Botan::RandomNumberGenerator& rng() + { + if (m_rng == nullptr) + { + m_rng = std::make_unique(); + } + + return *m_rng.get(); + } + + socket_type connect_to_host(const std::string& host, uint16_t port, bool tcp) + { + addrinfo hints; + Botan::clear_mem(&hints, 1); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = tcp ? SOCK_STREAM : SOCK_DGRAM; + addrinfo* res, *rp = nullptr; + + if (::getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res) != 0) + { + throw std::runtime_error("getaddrinfo failed for " + host); + } + + socket_type fd = 0; + + for (rp = res; rp != nullptr; rp = rp->ai_next) + { + fd = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + + if (fd == invalid_socket()) + { + continue; + } + + if (::connect(fd, rp->ai_addr, static_cast(rp->ai_addrlen)) != 0) + { + close(fd); + continue; + } + + break; + } + + ::freeaddrinfo(res); + + if (rp == nullptr) // no address succeeded + { + throw std::runtime_error("connect failed"); + } + + return fd; + } + + void tls_verify_cert_chain( + const std::vector& cert_chain, + const std::vector>& ocsp, + const std::vector& trusted_roots, + Botan::Usage_Type usage, + const std::string& hostname, + const Botan::TLS::Policy& policy) override + { + if (cert_chain.empty()) + { + throw Botan::Invalid_Argument("Certificate chain was empty"); + } + + Botan::Path_Validation_Restrictions restrictions( + false, // TODO: policy.require_cert_revocation_info(), + policy.minimum_signature_strength()); + + auto ocsp_timeout = std::chrono::milliseconds(1000); + + Botan::Path_Validation_Result result = Botan::x509_path_validate( + cert_chain, + restrictions, + trusted_roots, + hostname, + usage, + std::chrono::system_clock::now(), + ocsp_timeout, + ocsp); + + Log::HighPriority("Certificate validation status: " + result.result_string()); + if (result.successful_validation()) + { + auto status = result.all_statuses(); + + if (status.size() > 0 && status[0].count(Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD)) + { + Log::HighPriority("Valid OCSP response for this server"); + } + } + } + + bool tls_session_established(const Botan::TLS::Session& session) override + { + Log::HighPriority("Handshake complete, " + session.version().to_string() + + " using " + session.ciphersuite().to_string()); + + // if (!session.session_id().empty()) + // { + // output() << "Session ID " << Botan::hex_encode(session.session_id()) << "\n"; + // } + + // if (!session.session_ticket().empty()) + // { + // output() << "Session ticket " << Botan::hex_encode(session.session_ticket()) << "\n"; + // } + + // if (flag_set("print-certs")) + // { + // const std::vector& certs = session.peer_certs(); + + // for (size_t i = 0; i != certs.size(); ++i) + // { + // output() << "Certificate " << i + 1 << "/" << certs.size() << "\n"; + // output() << certs[i].to_string(); + // output() << certs[i].PEM_encode(); + // } + // } + + return true; + } + + // static void dgram_socket_write(int sockfd, const uint8_t buf[], size_t length) + // { + // int r = ::send(sockfd, buf, length, MSG_NOSIGNAL); + + // if (r == -1) + // { + // throw CLI_Error("Socket write failed errno=" + std::to_string(errno)); + // } + // } + + void tls_emit_data(const uint8_t buf[], size_t length) override + { + size_t offset = 0; + + while (length) + { + ssize_t sent = send(m_sockfd, buf + offset, length, 0); + + if (sent == -1) + { + if (errno == EINTR) + { + sent = 0; + } + else + { + throw std::runtime_error("Socket write failed errno=" + std::to_string(errno)); + } + } + + offset += sent; + length -= sent; + } + } + + void tls_alert(Botan::TLS::Alert alert) override + { + Log::Error("Alert: " + alert.type_string()); + } + + void tls_record_received(uint64_t /*seq_no*/, const uint8_t buf[], size_t buf_size) override + { + for (size_t i = 0; i != buf_size; ++i) + { + // output() << buf[i]; + } + } + + private: + std::unique_ptr m_rng; + socket_type m_sockfd = invalid_socket(); + }; +} diff --git a/Source/Client/OpalExtensions/Recipe.toml b/Source/Client/OpalExtensions/Recipe.toml new file mode 100644 index 00000000..02823586 --- /dev/null +++ b/Source/Client/OpalExtensions/Recipe.toml @@ -0,0 +1,12 @@ +Name = "Opal.Extensions" +Version = "0.1.0" +Public = "Module.cpp" +Dependencies = [ + "../../../Dependencies/cpp-httplib/", + # "../../../Dependencies/Opal/Source/", + "Opal@0.1.1", + # "httplib@1.0.0", +] +Defines = [ + # "ENABLE_FIDDLER_PROXY", +] \ No newline at end of file diff --git a/Source/Compiler/Clang/Module.cppm b/Source/Compiler/Clang/Module.cppm deleted file mode 100644 index 5f792dc7..00000000 --- a/Source/Compiler/Clang/Module.cppm +++ /dev/null @@ -1 +0,0 @@ -#include "Module.cpp" \ No newline at end of file diff --git a/Source/Compiler/GCC/Compiler.cs b/Source/Compiler/GCC/Compiler.cs deleted file mode 100644 index 4282814a..00000000 --- a/Source/Compiler/GCC/Compiler.cs +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -namespace Soup.Compiler.GCC -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Threading.Tasks; - - /// - /// The GCC compiler implementation - /// - public class Compiler : ICompiler - { - /// - /// Gets the unique name for the compiler - /// - public string Name => "GCC"; - - /// - /// Gets the object file extension for the compiler - /// - public string ObjectFileExtension => "obj"; - - /// - /// Gets the module file extension for the compiler - /// - public string ModuleFileExtension => "huh"; - - /// - /// Gets the static library file extension for the compiler - /// TODO: This is platform specific - /// - public string StaticLibraryFileExtension => "lib"; - - /// - /// Compile - /// - public Task CompileAsync(CompileArguments args) - { - string compiler = "g++-m"; - using (Process process = new Process()) - { - process.StartInfo.UseShellExecute = false; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.FileName = compiler; - process.StartInfo.WorkingDirectory = args.RootDirectory; - process.StartInfo.Arguments = BuildCompilerArguments(args); - process.Start(); - - while (!process.StandardOutput.EndOfStream) - { - string line = process.StandardOutput.ReadLine(); - ProcessLine(line); - } - - process.WaitForExit(); - - if (process.ExitCode != 0) - { - throw new InvalidOperationException(); - } - - return Task.FromResult(new CompileResults()); - } - } - - /// - /// Link Library - /// - public Task LinkLibraryAsync(LinkerArguments args) - { - return Task.CompletedTask; - } - - /// - /// Link Executable - /// - public Task LinkExecutableAsync(LinkerArguments args) - { - return Task.CompletedTask; - } - - private static string BuildCompilerArguments(CompileArguments args) - { - var commandArgs = new List(); - - // Set the Standard Library implementation - // commandArgs.Add("-stdlib=libc++"); - - // Set the language version - commandArgs.Add("-std=c++20"); - - // Enable experimental modules - commandArgs.Add("-fmodules-ts"); - - commandArgs.Add("-c"); - - // Lastly add the file - commandArgs.AddRange(args.SourceFiles); - - return string.Join(" ", commandArgs); - } - - private static void ProcessLine(string line) - { - Log.Info(line); - } - } -} diff --git a/Source/Core.UnitTests/Recipe.toml b/Source/Core.UnitTests/Recipe.toml deleted file mode 100644 index 37b95d9a..00000000 --- a/Source/Core.UnitTests/Recipe.toml +++ /dev/null @@ -1,16 +0,0 @@ -Name = "SoupCoreUnitTests" -Version = "1.0.0" -Type = "Executable" -Dependencies = [ - # "../../Dependencies/json11/", - "../../Dependencies/SoupTest/Assert/", - "../Core/", - "../TestUtilities/", - "json11@1.0.0", -] -Source = [ - "gen/Main.cpp" -] -IncludePaths = [ - "./", -] diff --git a/Source/Core/Api/ApiException.h b/Source/Core/Api/ApiException.h deleted file mode 100644 index aa2a71df..00000000 --- a/Source/Core/Api/ApiException.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Soup::Api -{ - /// - /// Api Exception - /// - class ApiException : public std::runtime_error - { - public: - /// - /// Initializes a new instance of the class. - /// - ApiException(const std::string& function, Network::HttpStatusCode statusCode) : - std::runtime_error("ApiFailed[" + function + "] " + std::to_string((int)statusCode)), - _statusCode(statusCode) - { - } - - Network::HttpStatusCode GetStatusCode() const - { - return _statusCode; - } - - private: - Network::HttpStatusCode _statusCode; - }; -} diff --git a/Source/Core/Api/ApiStatusResult.h b/Source/Core/Api/ApiStatusResult.h deleted file mode 100644 index 86809c4c..00000000 --- a/Source/Core/Api/ApiStatusResult.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Soup::Api -{ - /// - /// Api Status Result - /// - template - class ApiStatusResult - { - public: - /// - /// Initializes a new instance of the class. - /// - ApiStatusResult(TStatus status, TResult result) : - Status(status), - Result(std::move(result)) - { - } - - TStatus Status; - TResult Result; - }; -} diff --git a/Source/Core/Api/SoupApi.h b/Source/Core/Api/SoupApi.h deleted file mode 100644 index 6af2e67b..00000000 --- a/Source/Core/Api/SoupApi.h +++ /dev/null @@ -1,209 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "SoupApiJsonModels.h" -#include "ApiException.h" -#include "../Auth/Models/ClientCredentialsTokenModel.h" - -namespace Soup::Api -{ - export enum class PublishPackageResult - { - Success, - PackageDoesNotExist, - AlreadyExists, - }; - - /// - /// Represents a collection of functions to interact with the API endpoints - /// - export class SoupApi - { - private: - static const std::string_view ServiceEndpoint; - static const int ServicePort; - - public: - /// - /// Download a package version as an archive - /// - static std::string DownloadPackage(std::string_view name, SemanticVersion version) - { - auto client = Network::INetworkManager::Current().CreateClient( - ServiceEndpoint, - ServicePort); - - auto urlBuilder = std::stringstream(); - urlBuilder << "/v1/packages/" << name << "/v" << version.ToString() << "/download"; - auto url = urlBuilder.str(); - - Log::Diag(url); - auto response = client->Get(url); - - // Verify that we got a success - if (response.StatusCode != Network::HttpStatusCode::Ok) - { - throw ApiException("DownloadPackage", response.StatusCode); - } - - return response.Body; - } - - /// - /// Get the metadata for a package identified by the unique name - /// - static PackageResultModel GetPackage(std::string_view name) - { - auto client = Network::INetworkManager::Current().CreateClient( - ServiceEndpoint, - ServicePort); - - auto urlBuilder = std::stringstream(); - urlBuilder << "/v1/packages/" << name; - auto url = urlBuilder.str(); - - Log::Diag(url); - auto response = client->Get(url); - - // Verify that we got a success - if (response.StatusCode != Network::HttpStatusCode::Ok) - { - throw ApiException("GetPackage", response.StatusCode); - } - - // Parse the return result - auto result = SoupApiJsonModels::ParsePackageResult(response.Body); - return result; - } - - /// - /// Get a package publication metadata - /// - // Task GetPublicationAsync(string name, SemanticVersion version) - // { - // using (HttpClient client = new HttpClient()) - // { - // var url = $"{Constants.SoupRESTEndpointV1}/packages/{name}/{version}"; - // Log.Verbose(url); - // var response = await client.GetAsync(url); - - // // Verify that we got a success - // response.EnsureSuccessStatusCode(); - - // // Parse the return result - // var content = await response.Content.ReadAsStringAsync(); - // var result = JsonConvert.DeserializeObject(content); - - // return result; - // } - // } - - /// - /// Publish a new package version as an archive - /// - static PublishPackageResult PublishPackage( - const ClientCredentialsTokenModel& token, - std::string_view name, - SemanticVersion version, - std::istream& value) - { - auto client = Network::INetworkManager::Current().CreateClient( - ServiceEndpoint, - ServicePort); - - client->SetAuthenticationToken("Bearer", token.AccessToken); - - auto urlBuilder = std::stringstream(); - urlBuilder << "/v1/packages/" << name << "/v" << version.ToString(); - auto url = urlBuilder.str(); - - auto contentType = "application/x-7z-compressed"; - - Log::Diag(url); - auto response = client->Put(url, contentType, value); - - // Verify that we got a success - switch (response.StatusCode) - { - case Network::HttpStatusCode::Created: - return PublishPackageResult::Success; - case Network::HttpStatusCode::NotFound: - return PublishPackageResult::PackageDoesNotExist; - case Network::HttpStatusCode::Conflict: - return PublishPackageResult::AlreadyExists; - default: - throw Api::ApiException("PublishPackage", response.StatusCode); - } - } - - /// - /// Create a package - /// - static PackageResultModel CreatePackage( - const ClientCredentialsTokenModel& token, - std::string_view name, - const PackageCreateOrUpdateModel& model) - { - auto client = Network::INetworkManager::Current().CreateClient( - ServiceEndpoint, - ServicePort); - - client->SetAuthenticationToken("Bearer", token.AccessToken); - - auto urlBuilder = std::stringstream(); - urlBuilder << "/v1/packages/" << name; - auto url = urlBuilder.str(); - - std::stringstream content; - SoupApiJsonModels::SerializePackageCreateOrUpdate(model, content); - - auto contentType = "application/json"; - - Log::Diag(url); - auto response = client->Put(url, contentType, content); - - // Verify that we got a success - if (response.StatusCode != Network::HttpStatusCode::Created) - { - throw ApiException("CreatePackage", response.StatusCode); - } - - // Parse the return result - auto result = SoupApiJsonModels::ParsePackageResult(response.Body); - return result; - } - - /// - /// Search for a package using the query string - /// - // Task SearchPackagesAsync(string q) - // { - // using (HttpClient client = new HttpClient()) - // { - // var url = $"{Constants.SoupRESTEndpointV1}/packages?q={q}"; - // Log.Verbose(url); - // var response = await client.GetAsync(url); - - // // Verify that we got a success - // response.EnsureSuccessStatusCode(); - - // // Parse the return result - // var content = await response.Content.ReadAsStringAsync(); - // var result = JsonConvert.DeserializeObject(content); - - // return result; - // } - // } - }; - -// #define LOCAL_DEBUG -#ifdef LOCAL_DEBUG - /*static*/ const std::string_view SoupApi::ServiceEndpoint = "localhost"; - /*static*/ const int SoupApi::ServicePort = 7071; -#else - /*static*/ const std::string_view SoupApi::ServiceEndpoint = "api.soupbuild.com"; - /*static*/ const int SoupApi::ServicePort = 443; -#endif -} diff --git a/Source/Core/Auth/SoupAuth.h b/Source/Core/Auth/SoupAuth.h deleted file mode 100644 index 9f8c5ba1..00000000 --- a/Source/Core/Auth/SoupAuth.h +++ /dev/null @@ -1,143 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "SoupAuthJsonModels.h" -#include "../Api/ApiException.h" -#include "../Api/ApiStatusResult.h" - -namespace Soup::Api -{ - enum class RequestClientCredentialsTokenResult - { - Success, - InvalidUserNameOrPassword, - }; - - /// - /// Represents a collection of functions to interact with the Auth endpoints - /// - class SoupAuth - { - private: - static const std::string_view ServiceEndpoint; - static const int ServicePort; - - public: - /// - /// Get the OpenId configuration - /// - static OpenIdConfigurationModel GetOpenIdConfiguration() - { - auto client = Network::INetworkManager::Current().CreateClient( - ServiceEndpoint, - ServicePort); - - auto urlBuilder = std::stringstream(); - urlBuilder << "/.well-known/openid-configuration"; - auto url = urlBuilder.str(); - - Log::Diag(url); - auto response = client->Get(url); - - // Verify that we got a success - if (response.StatusCode != Network::HttpStatusCode::Ok) - { - throw ApiException("GetOpenIdConfiguration", response.StatusCode); - } - - // Parse the return result - auto result = SoupAuthJsonModels::ParseOpenIdConfigurationResult(response.Body); - return result; - } - - /// - /// Get the OpenId configuration - /// - static ApiStatusResult RequestClientCredentialsToken( - const std::string& tokenEndpoint, - const std::string& userName, - const std::string& password) - { - // TODO: Implement an opal url class - // https://stackoverflow.com/questions/5620235/cpp-regular-expression-to-validate-url/31613265 - auto urlParserRegex = std::regex( - R"(^(([^:\/?#]+):)?(//([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?)", - std::regex::extended); - std::smatch urlParts; - if (!std::regex_match(tokenEndpoint, urlParts, urlParserRegex)) - { - throw std::runtime_error("Invalid token endpoint url."); - } - - auto scheme = urlParts[2].str(); - auto authority = urlParts[4].str(); - auto path = urlParts[5].str(); - auto query = urlParts[7].str(); - auto fragment = urlParts[9].str(); - - auto endpoint = authority; - auto port = 80; - if (scheme == "https") - { - port = 443; - } - - auto portDelimiter = authority.find(':'); - if (portDelimiter != std::string::npos) - { - endpoint = authority.substr(0, portDelimiter); - port = std::stoi(authority.substr(portDelimiter + 1)); - } - - auto client = Network::INetworkManager::Current().CreateClient( - endpoint, - port); - - auto urlBuilder = std::stringstream(); - urlBuilder << path << query << fragment; - auto url = urlBuilder.str(); - - auto secret = "secret_for_client"; - - auto content = std::stringstream(); - content << "grant_type=password"; - content << "&username=" << userName; - content << "&password=" << password; - content << "&scope=soup_api"; - content << "&client_id=soup.client"; - content << "&client_secret=" << secret; - - auto contentType = "application/x-www-form-urlencoded"; - - Log::Diag(url); - auto response = client->Post(url, contentType, content); - - // Verify that we got a success - switch (response.StatusCode) - { - case Network::HttpStatusCode::Ok: - // Parse the return result - return ApiStatusResult( - RequestClientCredentialsTokenResult::Success, - SoupAuthJsonModels::ParseClientCredentialsTokenModel(response.Body)); - case Network::HttpStatusCode::BadRequest: - return ApiStatusResult( - RequestClientCredentialsTokenResult::InvalidUserNameOrPassword, - ClientCredentialsTokenModel()); - default: - throw ApiException("RequestClientCredentialsToken", response.StatusCode); - } - } - }; - -// #define LOCAL_DEBUG -#ifdef LOCAL_DEBUG - /*static*/ const std::string_view SoupAuth::ServiceEndpoint = "localhost"; - /*static*/ const int SoupAuth::ServicePort = 5051; -#else - /*static*/ const std::string_view SoupAuth::ServiceEndpoint = "auth.soupbuild.com"; - /*static*/ const int SoupAuth::ServicePort = 443; -#endif -} diff --git a/Source/Core/Recipe.toml b/Source/Core/Recipe.toml deleted file mode 100644 index e4179104..00000000 --- a/Source/Core/Recipe.toml +++ /dev/null @@ -1,20 +0,0 @@ -Name = "SoupCore" -Version = "0.1.0" - -Dependencies = [ - "../../Dependencies/LzmaSdk/CPP/Library/", - # "../../Dependencies/json11/", - "../../Dependencies/toml11/", - "../Opal/", - "../Engine/Definition/", - "../Engine/Core/", - "../Engine/Wrapper/", - "json11@1.0.0", -] - -Public = "Module.cpp" -IncludePaths = [ - "./", - "Compiler/", - "Utils/", -] diff --git a/Source/Engine/Core/BuildSystem.h b/Source/Engine/Core/BuildSystem.h deleted file mode 100644 index ba86974f..00000000 --- a/Source/Engine/Core/BuildSystem.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "BuildState.h" - -namespace Soup::Build -{ - /// - /// The build system implementation - /// - export class BuildSystem : public IBuildSystem - { - public: - /// - /// Initializes a new instance of the class. - /// - BuildSystem() : - _tasks() - { - } - - /// - /// Register task - /// - OperationResult RegisterTask(IBuildTask* task) noexcept override final - { - try - { - Log::Diag(std::string("RegisterTask: ") + task->GetName()); - _tasks.push_back(task); - return 0; - } - catch (...) - { - // Unknown error - return -1; - } - } - - /// - /// Get the set of added include paths - /// - void Execute(BuildState& state) - { - for (auto& task : _tasks) - { - Log::Info(std::string("TaskStart: ") + task->GetName()); - auto status = task->Execute(state); - if (status != 0) - { - Log::Error("TaskFailed: " + std::to_string(status)); - } - else - { - Log::Info(std::string("TaskDone: ") + task->GetName()); - } - - state.LogActive(); - } - } - - private: - std::vector> _tasks; - }; -} diff --git a/Source/Engine/Core/Recipe.toml b/Source/Engine/Core/Recipe.toml deleted file mode 100644 index 934fde11..00000000 --- a/Source/Engine/Core/Recipe.toml +++ /dev/null @@ -1,14 +0,0 @@ -Name = "SoupEngineCore" -Version = "0.1.0" - -Dependencies = [ - "../../Opal/", - "../Definition/", - "../Wrapper/", -] - -Public = "Module.cpp" -Source = [ - "BuildGraphNodeList.cpp", - "Value.cpp", -] diff --git a/Source/Engine/Definition/Recipe.toml b/Source/Engine/Definition/Recipe.toml deleted file mode 100644 index bbc9336a..00000000 --- a/Source/Engine/Definition/Recipe.toml +++ /dev/null @@ -1,7 +0,0 @@ -Name = "SoupEngineDefinition" -Version = "1.0.0" -Dependencies = [ - "../../Opal/", -] - -Public = "Module.cpp" diff --git a/Source/Engine/Wrapper/Recipe.toml b/Source/Engine/Wrapper/Recipe.toml deleted file mode 100644 index 4e9e7d48..00000000 --- a/Source/Engine/Wrapper/Recipe.toml +++ /dev/null @@ -1,12 +0,0 @@ -Name = "SoupEngineWrapper" -Version = "1.0.0" -Dependencies = [ - "../../Opal/", - "../Definition/" -] - -Public = "Module.cpp" -Source = [ - "GraphNodeListWrapper.cpp", - "ValueWrapper.cpp", -] diff --git a/Source/Compiler/Clang.UnitTests/CompilerArgumentBuilderTests.h b/Source/Extensions/Compiler/Clang.UnitTests/CompilerArgumentBuilderTests.h similarity index 100% rename from Source/Compiler/Clang.UnitTests/CompilerArgumentBuilderTests.h rename to Source/Extensions/Compiler/Clang.UnitTests/CompilerArgumentBuilderTests.h diff --git a/Source/Compiler/Clang.UnitTests/CompilerTests.h b/Source/Extensions/Compiler/Clang.UnitTests/CompilerTests.h similarity index 77% rename from Source/Compiler/Clang.UnitTests/CompilerTests.h rename to Source/Extensions/Compiler/Clang.UnitTests/CompilerTests.h index bb40ca81..d4b6e2e9 100644 --- a/Source/Compiler/Clang.UnitTests/CompilerTests.h +++ b/Source/Extensions/Compiler/Clang.UnitTests/CompilerTests.h @@ -30,12 +30,12 @@ namespace Soup::Compiler::Clang::UnitTests arguments.TargetFile = Path("obj/File.o"); arguments.RootDirectory = Path("Source"); - auto buildState = Build::BuildState(Build::ValueTable()); - auto result = uut.CreateCompileNode(Build::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); + auto result = uut.CreateCompileNode(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::BuildGraphNode( + auto expected = Memory::Reference( + new Build::Runtime::BuildGraphNode( "File.cpp", "C:/Clang/bin/clang++.exe", "-nostdinc -Wno-unknown-attributes -Xclang -flto-visibility-public-std -std=c++11 -c File.cpp -o obj/File.o", @@ -70,12 +70,12 @@ namespace Soup::Compiler::Clang::UnitTests }); arguments.ExportModule = true; - auto buildState = Build::BuildState(Build::ValueTable()); - auto result = uut.CreateCompileNode(Build::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); + auto result = uut.CreateCompileNode(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::BuildGraphNode( + auto expected = Memory::Reference( + new Build::Runtime::BuildGraphNode( "File.cpp", "C:/Clang/bin/clang++.exe", "-nostdinc -Wno-unknown-attributes -Xclang -flto-visibility-public-std -std=c++11 -I\"Includes\" -DDEBUG -fmodule-file=\"Module.pcm\" --precompile File.cpp -o obj/File.pcm", @@ -87,8 +87,8 @@ namespace Soup::Compiler::Clang::UnitTests std::vector({ "obj/File.pcm", }), - std::vector>({ - new Build::BuildGraphNode( + std::vector>({ + new Build::Runtime::BuildGraphNode( "obj/File.pcm", "C:/Clang/bin/clang++.exe", "-nostdinc -Wno-unknown-attributes -Xclang -flto-visibility-public-std -std=c++11 -c obj/File.pcm -o obj/File.obj", @@ -117,12 +117,12 @@ namespace Soup::Compiler::Clang::UnitTests Path("File.mock.o"), }); - auto buildState = Build::BuildState(Build::ValueTable()); - auto result = uut.CreateLinkNode(Build::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); + auto result = uut.CreateLinkNode(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::BuildGraphNode( + auto expected = Memory::Reference( + new Build::Runtime::BuildGraphNode( "Library.mock.a", "C:/Clang/bin/llvm-ar.exe", "rc Library.mock.a File.mock.o", @@ -153,12 +153,12 @@ namespace Soup::Compiler::Clang::UnitTests Path("Library.mock.a"), }); - auto buildState = Build::BuildState(Build::ValueTable()); - auto result = uut.CreateLinkNode(Build::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); + auto result = uut.CreateLinkNode(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::BuildGraphNode( + auto expected = Memory::Reference( + new Build::Runtime::BuildGraphNode( "Something.exe", "C:/Clang/bin/lld-link.exe", "/nologo /subsystem:console /machine:X64 /out:\"Something.exe\" Library.mock.a File.mock.o", diff --git a/Source/Compiler/Clang.UnitTests/LinkerArgumentBuilderTests.h b/Source/Extensions/Compiler/Clang.UnitTests/LinkerArgumentBuilderTests.h similarity index 100% rename from Source/Compiler/Clang.UnitTests/LinkerArgumentBuilderTests.h rename to Source/Extensions/Compiler/Clang.UnitTests/LinkerArgumentBuilderTests.h diff --git a/Source/Compiler/Clang.UnitTests/Recipe.toml b/Source/Extensions/Compiler/Clang.UnitTests/Recipe.toml similarity index 60% rename from Source/Compiler/Clang.UnitTests/Recipe.toml rename to Source/Extensions/Compiler/Clang.UnitTests/Recipe.toml index d5f89937..ab2294ff 100644 --- a/Source/Compiler/Clang.UnitTests/Recipe.toml +++ b/Source/Extensions/Compiler/Clang.UnitTests/Recipe.toml @@ -2,9 +2,10 @@ Name = "SoupCompilerClangUnitTests" Version = "1.0.0" Type = "Executable" Dependencies = [ - "../../../Dependencies/SoupTest/Assert/", + # "../../../Dependencies/SoupTest/Assert/", "../Clang/", - "../../TestUtilities/", + "../../../TestUtilities/", + "SoupTest@0.1.0", ] Source = [ diff --git a/Source/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h b/Source/Extensions/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h similarity index 81% rename from Source/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h rename to Source/Extensions/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h index 365f4ee4..c1007177 100644 --- a/Source/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h +++ b/Source/Extensions/Compiler/Clang.UnitTests/gen/CompilerArgumentBuilderTests.gen.h @@ -10,13 +10,13 @@ TestState RunCompilerArgumentBuilderTests() state += SoupTest::RunTest(className, "EmptyTargetFile_Throws", [&testClass]() { testClass->EmptyTargetFile_Throws(); }); state += SoupTest::RunTest(className, "DefaultParameters", [&testClass]() { testClass->DefaultParameters(); }); state += SoupTest::RunTest(className, "SingleArgument_GenerateIncludeTree", [&testClass]() { testClass->SingleArgument_GenerateIncludeTree(); }); - state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP11, \"-std=c++11\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP11, "-std=c++11"); }); - state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP14, \"-std=c++14\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP14, "-std=c++14"); }); - state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP17, \"-std=c++17\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP17, "-std=c++17"); }); + state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP11, \"-std=c++11\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP11, "-std=c++11"); }); + state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP14, \"-std=c++14\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP14, "-std=c++14"); }); + state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP17, \"-std=c++17\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP17, "-std=c++17"); }); state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard_CPP20", [&testClass]() { testClass->SingleArgument_LanguageStandard_CPP20(); }); state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel_Disabled", [&testClass]() { testClass->SingleArgument_OptimizationLevel_Disabled(); }); - state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Size, \"-Oz\")", [&testClass]() { testClass->SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Size, "-Oz"); }); - state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Speed, \"-O3\")", [&testClass]() { testClass->SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Speed, "-O3"); }); + state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Size, \"-Oz\")", [&testClass]() { testClass->SingleArgument_OptimizationLevel(Soup::Compiler::OptimizationLevel::Size, "-Oz"); }); + state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Speed, \"-O3\")", [&testClass]() { testClass->SingleArgument_OptimizationLevel(Soup::Compiler::OptimizationLevel::Speed, "-O3"); }); state += SoupTest::RunTest(className, "SingleArgument_GenerateDebugInformation", [&testClass]() { testClass->SingleArgument_GenerateDebugInformation(); }); state += SoupTest::RunTest(className, "SingleArgument_IncludePaths", [&testClass]() { testClass->SingleArgument_IncludePaths(); }); state += SoupTest::RunTest(className, "SingleArgument_PreprocessorDefinitions", [&testClass]() { testClass->SingleArgument_PreprocessorDefinitions(); }); diff --git a/Source/Compiler/Clang.UnitTests/gen/CompilerTests.gen.h b/Source/Extensions/Compiler/Clang.UnitTests/gen/CompilerTests.gen.h similarity index 100% rename from Source/Compiler/Clang.UnitTests/gen/CompilerTests.gen.h rename to Source/Extensions/Compiler/Clang.UnitTests/gen/CompilerTests.gen.h diff --git a/Source/Compiler/Clang.UnitTests/gen/LinkerArgumentBuilderTests.gen.h b/Source/Extensions/Compiler/Clang.UnitTests/gen/LinkerArgumentBuilderTests.gen.h similarity index 100% rename from Source/Compiler/Clang.UnitTests/gen/LinkerArgumentBuilderTests.gen.h rename to Source/Extensions/Compiler/Clang.UnitTests/gen/LinkerArgumentBuilderTests.gen.h diff --git a/Source/Compiler/Clang.UnitTests/gen/Main.cpp b/Source/Extensions/Compiler/Clang.UnitTests/gen/Main.cpp similarity index 84% rename from Source/Compiler/Clang.UnitTests/gen/Main.cpp rename to Source/Extensions/Compiler/Clang.UnitTests/gen/Main.cpp index ed48330c..c7323111 100644 --- a/Source/Compiler/Clang.UnitTests/gen/Main.cpp +++ b/Source/Extensions/Compiler/Clang.UnitTests/gen/Main.cpp @@ -6,13 +6,13 @@ #include import Opal; -import SoupCore; +import SoupCompiler; import SoupCompilerClang; import SoupTest; import SoupTestUtilities; -import SoupEngineDefinition; -import SoupEngineWrapper; -import SoupEngineCore; +import Soup.Build; +import Soup.Build.Extensions; +import Soup.Build.Runtime; using namespace Opal; using namespace Opal::System; diff --git a/Source/Compiler/Clang/ArgumentBuilder.h b/Source/Extensions/Compiler/Clang/ArgumentBuilder.h similarity index 100% rename from Source/Compiler/Clang/ArgumentBuilder.h rename to Source/Extensions/Compiler/Clang/ArgumentBuilder.h diff --git a/Source/Compiler/Clang/Compiler.h b/Source/Extensions/Compiler/Clang/Compiler.h similarity index 90% rename from Source/Compiler/Clang/Compiler.h rename to Source/Extensions/Compiler/Clang/Compiler.h index 0a435e52..2b2dc78d 100644 --- a/Source/Compiler/Clang/Compiler.h +++ b/Source/Extensions/Compiler/Clang/Compiler.h @@ -68,8 +68,8 @@ namespace Soup::Compiler::Clang /// /// Compile /// - Build::GraphNodeWrapper CreateCompileNode( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CreateCompileNode( + Build::Extensions::BuildStateWrapper& state, const CompileArguments& args) const override final { // Clang decided to do their module compilation in two stages @@ -87,8 +87,8 @@ namespace Soup::Compiler::Clang /// /// Link /// - Build::GraphNodeWrapper CreateLinkNode( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CreateLinkNode( + Build::Extensions::BuildStateWrapper& state, const LinkArguments& args) const override final { // Select the correct executable for linking libraries or executables @@ -123,8 +123,8 @@ namespace Soup::Compiler::Clang } private: - Build::GraphNodeWrapper CompileStandard( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CompileStandard( + Build::Extensions::BuildStateWrapper& state, const CompileArguments& args) const { auto executablePath = _toolPath + Path(CompilerExecutable); @@ -145,8 +145,8 @@ namespace Soup::Compiler::Clang return buildNode; } - Build::GraphNodeWrapper CompileModuleInterfaceUnit( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CompileModuleInterfaceUnit( + Build::Extensions::BuildStateWrapper& state, const CompileArguments& args) const { auto executablePath = _toolPath + Path(CompilerExecutable); @@ -211,7 +211,7 @@ namespace Soup::Compiler::Clang std::move(compileObjectOutputFiles)); // Ensure the compile node runs after the precompile - Build::GraphNodeExtensions::AddLeafChild(precompiledModuleBuildNode, compileBuildNode); + Build::Extensions::GraphNodeExtensions::AddLeafChild(precompiledModuleBuildNode, compileBuildNode); return precompiledModuleBuildNode; } diff --git a/Source/Compiler/Clang/Module.cpp b/Source/Extensions/Compiler/Clang/Module.cpp similarity index 87% rename from Source/Compiler/Clang/Module.cpp rename to Source/Extensions/Compiler/Clang/Module.cpp index b4b4891c..b26abaef 100644 --- a/Source/Compiler/Clang/Module.cpp +++ b/Source/Extensions/Compiler/Clang/Module.cpp @@ -10,7 +10,7 @@ export module SoupCompilerClang; import Opal; -import SoupCore; +import SoupCompiler; import SoupCompilerMSVC; using namespace Opal; diff --git a/Source/Compiler/Clang/Recipe.toml b/Source/Extensions/Compiler/Clang/Recipe.toml similarity index 80% rename from Source/Compiler/Clang/Recipe.toml rename to Source/Extensions/Compiler/Clang/Recipe.toml index 0c9c9750..cdd50b97 100644 --- a/Source/Compiler/Clang/Recipe.toml +++ b/Source/Extensions/Compiler/Clang/Recipe.toml @@ -1,7 +1,7 @@ Name = "SoupCompilerClang" Version = "0.1.0" Dependencies = [ - "../../Core/", + "../Core/", "../MSVC/", ] diff --git a/Source/Core.UnitTests/Build/BuildEngineTests.h b/Source/Extensions/Compiler/Core.UnitTests/BuildEngineTests.h similarity index 88% rename from Source/Core.UnitTests/Build/BuildEngineTests.h rename to Source/Extensions/Compiler/Core.UnitTests/BuildEngineTests.h index e362aaee..fad2f3f1 100644 --- a/Source/Core.UnitTests/Build/BuildEngineTests.h +++ b/Source/Extensions/Compiler/Core.UnitTests/BuildEngineTests.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build::UnitTests +namespace Soup::Compiler::UnitTests { class BuildEngineTests { @@ -44,8 +44,8 @@ namespace Soup::Build::UnitTests }); auto uut = BuildEngine(compiler); - auto buildState = BuildState(); - auto result = uut.Execute(BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(); + auto result = uut.Execute(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify expected logs Assert::AreEqual( @@ -95,8 +95,8 @@ namespace Soup::Build::UnitTests // Verify build state auto expectedLinkNode = - Memory::Reference( - new BuildGraphNode( + Memory::Reference( + new Build::Runtime::BuildGraphNode( "MockLink: 1", "MockLinker.exe", "Arguments", @@ -109,8 +109,8 @@ namespace Soup::Build::UnitTests }))); auto expectedCompileNode = - Memory::Reference( - new BuildGraphNode( + Memory::Reference( + new Build::Runtime::BuildGraphNode( "MockCompile: 1", "MockCompiler.exe", "Arguments", @@ -121,12 +121,12 @@ namespace Soup::Build::UnitTests std::vector({ "OutputFile.out", }), - std::vector>({ + std::vector>({ expectedLinkNode, }))); - auto expectedBuildNodes = std::vector>({ - new BuildGraphNode( + auto expectedBuildNodes = std::vector>({ + new Build::Runtime::BuildGraphNode( "MakeDir [C:/root/obj]", "C:/Windows/System32/cmd.exe", "/C if not exist \"C:/root/obj\" mkdir \"C:/root/obj\"", @@ -135,10 +135,10 @@ namespace Soup::Build::UnitTests std::vector({ "C:/root/obj", }), - std::vector>({ + std::vector>({ expectedCompileNode, })), - new BuildGraphNode( + new Build::Runtime::BuildGraphNode( "MakeDir [C:/root/bin]", "C:/Windows/System32/cmd.exe", "/C if not exist \"C:/root/bin\" mkdir \"C:/root/bin\"", @@ -147,7 +147,7 @@ namespace Soup::Build::UnitTests std::vector({ "C:/root/bin", }), - std::vector>({ + std::vector>({ expectedCompileNode, })), }); @@ -210,8 +210,8 @@ namespace Soup::Build::UnitTests }); auto uut = BuildEngine(compiler); - auto buildState = BuildState(); - auto result = uut.Execute(BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(); + auto result = uut.Execute(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify expected logs Assert::AreEqual( @@ -283,8 +283,8 @@ namespace Soup::Build::UnitTests // Verify build state auto expectedLinkNode = - Memory::Reference( - new BuildGraphNode( + Memory::Reference( + new Build::Runtime::BuildGraphNode( "MockLink: 1", "MockLinker.exe", "Arguments", @@ -296,8 +296,8 @@ namespace Soup::Build::UnitTests "OutputFile.out", }))); - auto expectedCompileNodes = std::vector>({ - new BuildGraphNode( + auto expectedCompileNodes = std::vector>({ + new Build::Runtime::BuildGraphNode( "MockCompile: 1", "MockCompiler.exe", "Arguments", @@ -308,10 +308,10 @@ namespace Soup::Build::UnitTests std::vector({ "OutputFile.out", }), - std::vector>({ + std::vector>({ expectedLinkNode, })), - new BuildGraphNode( + new Build::Runtime::BuildGraphNode( "MockCompile: 2", "MockCompiler.exe", "Arguments", @@ -322,10 +322,10 @@ namespace Soup::Build::UnitTests std::vector({ "OutputFile.out", }), - std::vector>({ + std::vector>({ expectedLinkNode, })), - new BuildGraphNode( + new Build::Runtime::BuildGraphNode( "MockCompile: 3", "MockCompiler.exe", "Arguments", @@ -336,13 +336,13 @@ namespace Soup::Build::UnitTests std::vector({ "OutputFile.out", }), - std::vector>({ + std::vector>({ expectedLinkNode, })), }); - auto expectedBuildNodes = std::vector>({ - new BuildGraphNode( + auto expectedBuildNodes = std::vector>({ + new Build::Runtime::BuildGraphNode( "MakeDir [C:/root/obj]", "C:/Windows/System32/cmd.exe", "/C if not exist \"C:/root/obj\" mkdir \"C:/root/obj\"", @@ -352,7 +352,7 @@ namespace Soup::Build::UnitTests "C:/root/obj", }), expectedCompileNodes), - new BuildGraphNode( + new Build::Runtime::BuildGraphNode( "MakeDir [C:/root/bin]", "C:/Windows/System32/cmd.exe", "/C if not exist \"C:/root/bin\" mkdir \"C:/root/bin\"", @@ -431,8 +431,8 @@ namespace Soup::Build::UnitTests }); auto uut = BuildEngine(compiler); - auto buildState = BuildState(); - auto result = uut.Execute(BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(); + auto result = uut.Execute(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify expected logs Assert::AreEqual( @@ -518,8 +518,8 @@ namespace Soup::Build::UnitTests // Verify build state auto expectedLinkNode = - Memory::Reference( - new BuildGraphNode( + Memory::Reference( + new Build::Runtime::BuildGraphNode( "MockLink: 1", "MockLinker.exe", "Arguments", @@ -531,8 +531,8 @@ namespace Soup::Build::UnitTests "OutputFile.out", }))); - auto expectedCompileSourceNodes = std::vector>({ - new BuildGraphNode( + auto expectedCompileSourceNodes = std::vector>({ + new Build::Runtime::BuildGraphNode( "MockCompile: 2", "MockCompiler.exe", "Arguments", @@ -543,10 +543,10 @@ namespace Soup::Build::UnitTests std::vector({ "OutputFile.out", }), - std::vector>({ + std::vector>({ expectedLinkNode, })), - new BuildGraphNode( + new Build::Runtime::BuildGraphNode( "MockCompile: 3", "MockCompiler.exe", "Arguments", @@ -557,10 +557,10 @@ namespace Soup::Build::UnitTests std::vector({ "OutputFile.out", }), - std::vector>({ + std::vector>({ expectedLinkNode, })), - new BuildGraphNode( + new Build::Runtime::BuildGraphNode( "MockCompile: 4", "MockCompiler.exe", "Arguments", @@ -571,14 +571,14 @@ namespace Soup::Build::UnitTests std::vector({ "OutputFile.out", }), - std::vector>({ + std::vector>({ expectedLinkNode, })), }); auto expectedCopyModuleInterfaceNode = - Memory::Reference( - new BuildGraphNode( + Memory::Reference( + new Build::Runtime::BuildGraphNode( "Copy [C:/root/obj/Public.mock.bmi] -> [C:/root/bin/Library.mock.bmi]", "C:/Windows/System32/cmd.exe", "/C copy /Y \"C:\\root\\obj\\Public.mock.bmi\" \"C:\\root\\bin\\Library.mock.bmi\"", @@ -592,8 +592,8 @@ namespace Soup::Build::UnitTests expectedCompileSourceNodes)); auto expectedCompileModuleNode = - Memory::Reference( - new BuildGraphNode( + Memory::Reference( + new Build::Runtime::BuildGraphNode( "MockCompile: 1", "MockCompiler.exe", "Arguments", @@ -604,12 +604,12 @@ namespace Soup::Build::UnitTests std::vector({ "OutputFile.out", }), - std::vector>({ + std::vector>({ expectedCopyModuleInterfaceNode, }))); - auto expectedBuildNodes = std::vector>({ - new BuildGraphNode( + auto expectedBuildNodes = std::vector>({ + new Build::Runtime::BuildGraphNode( "MakeDir [C:/root/obj]", "C:/Windows/System32/cmd.exe", "/C if not exist \"C:/root/obj\" mkdir \"C:/root/obj\"", @@ -618,10 +618,10 @@ namespace Soup::Build::UnitTests std::vector({ "C:/root/obj", }), - std::vector>({ + std::vector>({ expectedCompileModuleNode, })), - new BuildGraphNode( + new Build::Runtime::BuildGraphNode( "MakeDir [C:/root/bin]", "C:/Windows/System32/cmd.exe", "/C if not exist \"C:/root/bin\" mkdir \"C:/root/bin\"", @@ -630,7 +630,7 @@ namespace Soup::Build::UnitTests std::vector({ "C:/root/bin", }), - std::vector>({ + std::vector>({ expectedCompileModuleNode, })), }); @@ -696,8 +696,8 @@ namespace Soup::Build::UnitTests }); auto uut = BuildEngine(compiler); - auto buildState = BuildState(); - auto result = uut.Execute(BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(); + auto result = uut.Execute(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify expected logs Assert::AreEqual( @@ -756,8 +756,8 @@ namespace Soup::Build::UnitTests // Verify build state auto expectedLinkNode = - Memory::Reference( - new BuildGraphNode( + Memory::Reference( + new Build::Runtime::BuildGraphNode( "MockLink: 1", "MockLinker.exe", "Arguments", @@ -770,8 +770,8 @@ namespace Soup::Build::UnitTests }))); auto expectedCopyModuleInterfaceNode = - Memory::Reference( - new BuildGraphNode( + Memory::Reference( + new Build::Runtime::BuildGraphNode( "Copy [C:/root/obj/Public.mock.bmi] -> [C:/root/bin/Library.mock.bmi]", "C:/Windows/System32/cmd.exe", "/C copy /Y \"C:\\root\\obj\\Public.mock.bmi\" \"C:\\root\\bin\\Library.mock.bmi\"", @@ -782,13 +782,13 @@ namespace Soup::Build::UnitTests std::vector({ "C:/root/bin/Library.mock.bmi", }), - std::vector>({ + std::vector>({ expectedLinkNode, }))); auto expectedCompileModuleNode = - Memory::Reference( - new BuildGraphNode( + Memory::Reference( + new Build::Runtime::BuildGraphNode( "MockCompile: 1", "MockCompiler.exe", "Arguments", @@ -799,12 +799,12 @@ namespace Soup::Build::UnitTests std::vector({ "OutputFile.out", }), - std::vector>({ + std::vector>({ expectedCopyModuleInterfaceNode, }))); - auto expectedBuildNodes = std::vector>({ - new BuildGraphNode( + auto expectedBuildNodes = std::vector>({ + new Build::Runtime::BuildGraphNode( "MakeDir [C:/root/obj]", "C:/Windows/System32/cmd.exe", "/C if not exist \"C:/root/obj\" mkdir \"C:/root/obj\"", @@ -813,10 +813,10 @@ namespace Soup::Build::UnitTests std::vector({ "C:/root/obj", }), - std::vector>({ + std::vector>({ expectedCompileModuleNode, })), - new BuildGraphNode( + new Build::Runtime::BuildGraphNode( "MakeDir [C:/root/bin]", "C:/Windows/System32/cmd.exe", "/C if not exist \"C:/root/bin\" mkdir \"C:/root/bin\"", @@ -825,7 +825,7 @@ namespace Soup::Build::UnitTests std::vector({ "C:/root/bin", }), - std::vector>({ + std::vector>({ expectedCompileModuleNode, })), }); diff --git a/Source/Extensions/Compiler/Core.UnitTests/Recipe.toml b/Source/Extensions/Compiler/Core.UnitTests/Recipe.toml new file mode 100644 index 00000000..ef0cf09a --- /dev/null +++ b/Source/Extensions/Compiler/Core.UnitTests/Recipe.toml @@ -0,0 +1,15 @@ +Name = "SoupCompilerCoreUnitTests" +Version = "1.0.0" +Type = "Executable" +Dependencies = [ + "../Core/", + "../../../Build/Runtime/", + "../../../TestUtilities/", + "SoupTest@0.1.0", +] +Source = [ + "gen/Main.cpp" +] +IncludePaths = [ + "./", +] diff --git a/Source/Core.UnitTests/gen/Build/BuildEngineTests.gen.h b/Source/Extensions/Compiler/Core.UnitTests/gen/BuildEngineTests.gen.h similarity index 85% rename from Source/Core.UnitTests/gen/Build/BuildEngineTests.gen.h rename to Source/Extensions/Compiler/Core.UnitTests/gen/BuildEngineTests.gen.h index 493d0d0a..141fc26b 100644 --- a/Source/Core.UnitTests/gen/Build/BuildEngineTests.gen.h +++ b/Source/Extensions/Compiler/Core.UnitTests/gen/BuildEngineTests.gen.h @@ -1,10 +1,10 @@ #pragma once -#include "Build/BuildEngineTests.h" +#include "BuildEngineTests.h" TestState RunBuildEngineTests() { auto className = "BuildEngineTests"; - auto testClass = std::make_shared(); + auto testClass = std::make_shared(); TestState state = { 0, 0 }; state += SoupTest::RunTest(className, "Initialize_Success", [&testClass]() { testClass->Initialize_Success(); }); state += SoupTest::RunTest(className, "Build_Executable", [&testClass]() { testClass->Build_Executable(); }); diff --git a/Source/Extensions/Compiler/Core.UnitTests/gen/Main.cpp b/Source/Extensions/Compiler/Core.UnitTests/gen/Main.cpp new file mode 100644 index 00000000..16455312 --- /dev/null +++ b/Source/Extensions/Compiler/Core.UnitTests/gen/Main.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +#include +#include + +import Opal; +import Soup.Build.Runtime; +import SoupCompiler; +import SoupTest; +import SoupTestUtilities; + +using namespace Opal; +using namespace Opal::System; +using namespace SoupTest; + +#include "BuildEngineTests.gen.h" + +int main() +{ + std::cout << "Running Tests..." << std::endl; + + TestState state = { 0, 0 }; + + state += RunBuildEngineTests(); + + std::cout << state.PassCount << " PASSED." << std::endl; + std::cout << state.FailCount << " FAILED." << std::endl; + + return 0; +} diff --git a/Source/Core/Build/BuildArguments.h b/Source/Extensions/Compiler/Core/BuildArguments.h similarity index 94% rename from Source/Core/Build/BuildArguments.h rename to Source/Extensions/Compiler/Core/BuildArguments.h index 1c7831d2..d9edfe1a 100644 --- a/Source/Core/Build/BuildArguments.h +++ b/Source/Extensions/Compiler/Core/BuildArguments.h @@ -3,9 +3,9 @@ // #pragma once -#include "Compiler/ICompiler.h" +#include "ICompiler.h" -namespace Soup::Build +namespace Soup::Compiler { /// /// The enumeration of build optimization levels diff --git a/Source/Core/Build/BuildEngine.h b/Source/Extensions/Compiler/Core/BuildEngine.h similarity index 81% rename from Source/Core/Build/BuildEngine.h rename to Source/Extensions/Compiler/Core/BuildEngine.h index 0c010e46..7a86139d 100644 --- a/Source/Core/Build/BuildEngine.h +++ b/Source/Extensions/Compiler/Core/BuildEngine.h @@ -6,9 +6,9 @@ #include "BuildArguments.h" #include "BuildResult.h" #include "BuildUtilities.h" -#include "Compiler/ICompiler.h" +#include "ICompiler.h" -namespace Soup::Build +namespace Soup::Compiler { /// /// The build engine @@ -25,7 +25,7 @@ namespace Soup::Build /// Generate the required build nodes for the requested build /// BuildResult Execute( - Soup::Build::BuildStateWrapper& buildState, + Soup::Build::Extensions::BuildStateWrapper& buildState, const BuildArguments& arguments) { auto result = BuildResult(); @@ -42,9 +42,9 @@ namespace Soup::Build auto objectDirectry = arguments.WorkingDirectory + arguments.ObjectDirectory; auto binaryDirectry = arguments.WorkingDirectory + arguments.BinaryDirectory; result.BuildNodes.push_back( - Soup::Build::BuildUtilities::CreateCreateDirectoryNode(buildState, objectDirectry)); + BuildUtilities::CreateCreateDirectoryNode(buildState, objectDirectry)); result.BuildNodes.push_back( - Soup::Build::BuildUtilities::CreateCreateDirectoryNode(buildState, binaryDirectry)); + BuildUtilities::CreateCreateDirectoryNode(buildState, binaryDirectry)); // Perform the core compilation of the source files CoreCompile(buildState, arguments, result); @@ -63,14 +63,14 @@ namespace Soup::Build /// Compile the module and source files /// void CoreCompile( - Soup::Build::BuildStateWrapper& buildState, + Soup::Build::Extensions::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { - auto rootCompileNodes = std::vector(); + auto rootCompileNodes = std::vector(); // Compile the module interface unit if present - auto moduleCompileNode = Soup::Build::GraphNodeWrapper(); + auto moduleCompileNode = Soup::Build::Extensions::GraphNodeWrapper(); if (!arguments.ModuleInterfaceSourceFile.IsEmpty()) { CompileModuleInterfaceUnit( @@ -88,11 +88,11 @@ namespace Soup::Build arguments.WorkingDirectory + arguments.BinaryDirectory + Path(arguments.TargetName + "." + std::string(_compiler->GetModuleFileExtension())); - auto copyInterfaceNode = Soup::Build::BuildUtilities::CreateCopyFileNode( + auto copyInterfaceNode = BuildUtilities::CreateCopyFileNode( buildState, objectModuleInterfaceFile, binaryOutputModuleInterfaceFile); - Soup::Build::GraphNodeExtensions::AddLeafChild(result.BuildNodes, copyInterfaceNode); + Soup::Build::Extensions::GraphNodeExtensions::AddLeafChild(result.BuildNodes, copyInterfaceNode); // Add output module interface to the parent set of modules // This will allow the module implementation units access as well as downstream @@ -114,7 +114,7 @@ namespace Soup::Build /// Returns true if the file was compiled /// void CompileModuleInterfaceUnit( - Soup::Build::BuildStateWrapper& buildState, + Soup::Build::Extensions::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { @@ -125,7 +125,7 @@ namespace Soup::Build targetFile.SetFileExtension(_compiler->GetObjectFileExtension()); // Setup the shared properties - auto compileArguments = Soup::CompileArguments(); + auto compileArguments = CompileArguments(); compileArguments.Standard = arguments.LanguageStandard; compileArguments.Optimize = Convert(arguments.OptimizationLevel); compileArguments.RootDirectory = arguments.WorkingDirectory; @@ -146,14 +146,14 @@ namespace Soup::Build auto compileNode = _compiler->CreateCompileNode(buildState, compileArguments); // Run after the module interface unit compile - Soup::Build::GraphNodeExtensions::AddLeafChild(result.BuildNodes, compileNode); + Soup::Build::Extensions::GraphNodeExtensions::AddLeafChild(result.BuildNodes, compileNode); } /// /// Compile the supporting source files /// void CompileSourceFiles( - Soup::Build::BuildStateWrapper& buildState, + Soup::Build::Extensions::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { @@ -161,7 +161,7 @@ namespace Soup::Build buildState.LogInfo("Compiling source files"); // Setup the shared properties - auto compileArguments = Soup::CompileArguments(); + auto compileArguments = CompileArguments(); compileArguments.Standard = arguments.LanguageStandard; compileArguments.Optimize = Convert(arguments.OptimizationLevel); compileArguments.RootDirectory = arguments.WorkingDirectory; @@ -180,7 +180,7 @@ namespace Soup::Build std::back_inserter(compileArguments.IncludeModules)); // Compile the individual translation units - auto buildNodes = std::vector(); + auto buildNodes = std::vector(); for (auto& file : arguments.SourceFiles) { buildState.LogInfo("Generate Compile Node: " + file.ToString()); @@ -194,14 +194,14 @@ namespace Soup::Build } // Run the core compile next - Soup::Build::GraphNodeExtensions::AddLeafChildren(result.BuildNodes, buildNodes); + Soup::Build::Extensions::GraphNodeExtensions::AddLeafChildren(result.BuildNodes, buildNodes); } /// /// Link the library /// void CoreLink( - Soup::Build::BuildStateWrapper& buildState, + Soup::Build::Extensions::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { @@ -235,7 +235,7 @@ namespace Soup::Build buildState.LogInfo("Linking target"); - auto linkArguments = Soup::LinkArguments(); + auto linkArguments = LinkArguments(); linkArguments.TargetFile = std::move(targetFile); linkArguments.ImplementationFile = std::move(implementationFile); @@ -260,7 +260,7 @@ namespace Soup::Build { case BuildTargetType::StaticLibrary: { - linkArguments.TargetType = Soup::LinkTarget::StaticLibrary; + linkArguments.TargetType = LinkTarget::StaticLibrary; // Add the library as a link dependency and all transitive libraries result.LinkDependencies = arguments.LinkDependencies; @@ -269,7 +269,7 @@ namespace Soup::Build } case BuildTargetType::DynamicLibrary: { - linkArguments.TargetType = Soup::LinkTarget::DynamicLibrary; + linkArguments.TargetType = LinkTarget::DynamicLibrary; // Add the DLL as a runtime dependency result.RuntimeDependencies.push_back(linkArguments.RootDirectory + linkArguments.TargetFile); @@ -281,7 +281,7 @@ namespace Soup::Build } case BuildTargetType::Executable: { - linkArguments.TargetType = Soup::LinkTarget::Executable; + linkArguments.TargetType = LinkTarget::Executable; // All link dependencies stop here. break; @@ -316,45 +316,45 @@ namespace Soup::Build auto linkNode = _compiler->CreateLinkNode(buildState, linkArguments); // Run the link node - Soup::Build::GraphNodeExtensions::AddLeafChild(result.BuildNodes, linkNode); + Soup::Build::Extensions::GraphNodeExtensions::AddLeafChild(result.BuildNodes, linkNode); } /// /// Copy runtime dependencies /// void CopyRuntimeDependencies( - Soup::Build::BuildStateWrapper& buildState, + Soup::Build::Extensions::BuildStateWrapper& buildState, const BuildArguments& arguments, BuildResult& result) { if (arguments.TargetType == BuildTargetType::Executable || arguments.TargetType == BuildTargetType::DynamicLibrary) { - auto copyNodes = std::vector(); + auto copyNodes = std::vector(); for (auto source : arguments.RuntimeDependencies) { auto target = arguments.WorkingDirectory + arguments.BinaryDirectory + Path(source.GetFileName()); - auto node = Soup::Build::BuildUtilities::CreateCopyFileNode(buildState, source, target); + auto node = BuildUtilities::CreateCopyFileNode(buildState, source, target); copyNodes.push_back(node); } if (!copyNodes.empty()) { - Soup::Build::GraphNodeExtensions::AddLeafChildren(result.BuildNodes, copyNodes); + Soup::Build::Extensions::GraphNodeExtensions::AddLeafChildren(result.BuildNodes, copyNodes); } } } - Soup::OptimizationLevel Convert(BuildOptimizationLevel value) + Soup::Compiler::OptimizationLevel Convert(BuildOptimizationLevel value) { switch (value) { case BuildOptimizationLevel::None: - return Soup::OptimizationLevel::None; + return Soup::Compiler::OptimizationLevel::None; case BuildOptimizationLevel::Speed: - return Soup::OptimizationLevel::Speed; + return Soup::Compiler::OptimizationLevel::Speed; case BuildOptimizationLevel::Size: - return Soup::OptimizationLevel::Size; + return Soup::Compiler::OptimizationLevel::Size; default: throw std::runtime_error("Unknown BuildOptimizationLevel."); } diff --git a/Source/Core/Build/BuildResult.h b/Source/Extensions/Compiler/Core/BuildResult.h similarity index 84% rename from Source/Core/Build/BuildResult.h rename to Source/Extensions/Compiler/Core/BuildResult.h index cb6f85eb..bdcd3ebc 100644 --- a/Source/Core/Build/BuildResult.h +++ b/Source/Extensions/Compiler/Core/BuildResult.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Compiler { /// /// The build result @@ -14,7 +14,7 @@ namespace Soup::Build /// /// Gets or sets the resulting root build nodes /// - std::vector BuildNodes; + std::vector BuildNodes; /// /// Gets or sets the list of module dependencies diff --git a/Source/Core/Build/BuildUtilities.h b/Source/Extensions/Compiler/Core/BuildUtilities.h similarity index 77% rename from Source/Core/Build/BuildUtilities.h rename to Source/Extensions/Compiler/Core/BuildUtilities.h index 22e88f9b..d22eaa0f 100644 --- a/Source/Core/Build/BuildUtilities.h +++ b/Source/Extensions/Compiler/Core/BuildUtilities.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup::Build +namespace Soup::Compiler { /// /// The build utilities class @@ -15,8 +15,8 @@ namespace Soup::Build /// /// Create a build node that will copy a file /// - static GraphNodeWrapper CreateCopyFileNode( - BuildStateWrapper& state, + static Soup::Build::Extensions::GraphNodeWrapper CreateCopyFileNode( + Soup::Build::Extensions::BuildStateWrapper& state, const Path& source, const Path& destination) { @@ -48,8 +48,8 @@ namespace Soup::Build /// /// Create a build node that will create a directory /// - static GraphNodeWrapper CreateCreateDirectoryNode( - BuildStateWrapper& state, + static Soup::Build::Extensions::GraphNodeWrapper CreateCreateDirectoryNode( + Soup::Build::Extensions::BuildStateWrapper& state, const Path& directory) { auto titleStream = std::stringstream(); @@ -67,12 +67,12 @@ namespace Soup::Build arguments << "/C if not exist \"" << directory.ToString() << "\" mkdir \"" << directory.ToString() << "\""; return state.CreateNode( - titleStream.str(), - std::move(program), - arguments.str(), - std::move(workingDirectory), - std::move(inputFiles), - std::move(outputFiles)); + titleStream.str(), + std::move(program), + arguments.str(), + std::move(workingDirectory), + std::move(inputFiles), + std::move(outputFiles)); } }; } diff --git a/Source/Core/Compiler/CompileArguments.h b/Source/Extensions/Compiler/Core/CompileArguments.h similarity index 92% rename from Source/Core/Compiler/CompileArguments.h rename to Source/Extensions/Compiler/Core/CompileArguments.h index 7ad11874..e5d68061 100644 --- a/Source/Core/Compiler/CompileArguments.h +++ b/Source/Extensions/Compiler/Core/CompileArguments.h @@ -4,7 +4,7 @@ #pragma once -namespace Soup +namespace Soup::Compiler { /// /// The enumeration of language standards @@ -172,8 +172,8 @@ namespace Soup { auto stringBuilder = std::stringstream(); stringBuilder << "[" << - ::Soup::ToString(Standard) << ", " << - ::Soup::ToString(Optimize) << ", " << + ::Soup::Compiler::ToString(Standard) << ", " << + ::Soup::Compiler::ToString(Optimize) << ", " << RootDirectory.ToString() << ", ["; for (auto& value : PreprocessorDefinitions) diff --git a/Source/Core/Compiler/ICompiler.h b/Source/Extensions/Compiler/Core/ICompiler.h similarity index 81% rename from Source/Core/Compiler/ICompiler.h rename to Source/Extensions/Compiler/Core/ICompiler.h index 876c8688..16293255 100644 --- a/Source/Core/Compiler/ICompiler.h +++ b/Source/Extensions/Compiler/Core/ICompiler.h @@ -6,7 +6,7 @@ #include "CompileArguments.h" #include "LinkArguments.h" -namespace Soup +namespace Soup::Compiler { /// /// The compiler interface definition @@ -45,15 +45,15 @@ namespace Soup /// Compile /// // TODO: Should this state be replaced with a factory to limit access? - virtual Build::GraphNodeWrapper CreateCompileNode( - Build::BuildStateWrapper& state, + virtual Build::Extensions::GraphNodeWrapper CreateCompileNode( + Build::Extensions::BuildStateWrapper& state, const CompileArguments& args) const = 0; /// /// Link /// - virtual Build::GraphNodeWrapper CreateLinkNode( - Build::BuildStateWrapper& state, + virtual Build::Extensions::GraphNodeWrapper CreateLinkNode( + Build::Extensions::BuildStateWrapper& state, const LinkArguments& args) const = 0; }; } diff --git a/Source/Core/Compiler/LinkArguments.h b/Source/Extensions/Compiler/Core/LinkArguments.h similarity index 97% rename from Source/Core/Compiler/LinkArguments.h rename to Source/Extensions/Compiler/Core/LinkArguments.h index 97ccef53..9efdf022 100644 --- a/Source/Core/Compiler/LinkArguments.h +++ b/Source/Extensions/Compiler/Core/LinkArguments.h @@ -2,7 +2,7 @@ // Copyright (c) Soup. All rights reserved. // -namespace Soup +namespace Soup::Compiler { /// /// The enumeration of link targets @@ -117,7 +117,7 @@ namespace Soup auto stringBuilder = std::stringstream(); stringBuilder << "[" << TargetFile.ToString() << ", " << - ::Soup::ToString(TargetType) << ", " << + ::Soup::Compiler::ToString(TargetType) << ", " << RootDirectory.ToString() << ", ["; for (auto& value : ObjectFiles) diff --git a/Source/Core/Compiler/MockCompiler.h b/Source/Extensions/Compiler/Core/MockCompiler.h similarity index 89% rename from Source/Core/Compiler/MockCompiler.h rename to Source/Extensions/Compiler/Core/MockCompiler.h index 62bb2859..824c5d51 100644 --- a/Source/Core/Compiler/MockCompiler.h +++ b/Source/Extensions/Compiler/Core/MockCompiler.h @@ -83,8 +83,8 @@ namespace Soup::Compiler::Mock /// /// Compile /// - Build::GraphNodeWrapper CreateCompileNode( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CreateCompileNode( + Build::Extensions::BuildStateWrapper& state, const CompileArguments& args) const override final { _compileRequests.push_back(args); @@ -104,8 +104,8 @@ namespace Soup::Compiler::Mock /// /// Link /// - Build::GraphNodeWrapper CreateLinkNode( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CreateLinkNode( + Build::Extensions::BuildStateWrapper& state, const LinkArguments& args) const override final { _linkRequests.push_back(args); diff --git a/Source/Extensions/Compiler/Core/Module.cpp b/Source/Extensions/Compiler/Core/Module.cpp new file mode 100644 index 00000000..3bb1b063 --- /dev/null +++ b/Source/Extensions/Compiler/Core/Module.cpp @@ -0,0 +1,22 @@ +module; + +#include +#include +#include +#include +#include +#include + +export module SoupCompiler; + +import Opal; +import Soup.Build.Extensions; + +using namespace Opal; + +#include "ICompiler.h" +#include "CompileArguments.h" +#include "MockCompiler.h" + +#include "BuildEngine.h" +#include "BuildUtilities.h" diff --git a/Source/Extensions/Compiler/Core/Recipe.toml b/Source/Extensions/Compiler/Core/Recipe.toml new file mode 100644 index 00000000..fbbdf5a0 --- /dev/null +++ b/Source/Extensions/Compiler/Core/Recipe.toml @@ -0,0 +1,10 @@ +Name = "SoupCompilerCore" +Version = "0.1.0" +Dependencies = [ + # "../../../Dependencies/Opal/Source/", + "Opal@0.1.1", + "../../../Build/Extensions/", + # "Soup.Build.Extensions@0.2.0", +] + +Public = "Module.cpp" diff --git a/Source/Compiler/GCC/Compiler.GCC.csproj b/Source/Extensions/Compiler/GCC/Compiler.GCC.csproj similarity index 100% rename from Source/Compiler/GCC/Compiler.GCC.csproj rename to Source/Extensions/Compiler/GCC/Compiler.GCC.csproj diff --git a/Source/Extensions/Compiler/GCC/Compiler.cs b/Source/Extensions/Compiler/GCC/Compiler.cs new file mode 100644 index 00000000..34f2a52e --- /dev/null +++ b/Source/Extensions/Compiler/GCC/Compiler.cs @@ -0,0 +1,112 @@ +// +// Copyright (c) Soup. All rights reserved. +// + +namespace Soup.Compiler.GCC +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Threading.Tasks; + + /// + /// The GCC compiler implementation + /// + public class Compiler : ICompiler + { + /// + /// Gets the unique name for the compiler + /// + public string Name => "GCC"; + + /// + /// Gets the object file extension for the compiler + /// + public string ObjectFileExtension => "obj"; + + /// + /// Gets the module file extension for the compiler + /// + public string ModuleFileExtension => "huh"; + + /// + /// Gets the static library file extension for the compiler + /// TODO: This is platform specific + /// + public string StaticLibraryFileExtension => "lib"; + + /// + /// Compile + /// + public Task CompileAsync(CompileArguments args) + { + string compiler = "g++-m"; + using (Process process = new Process()) + { + process.StartInfo.UseShellExecute = false; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.FileName = compiler; + process.StartInfo.WorkingDirectory = args.RootDirectory; + process.StartInfo.Arguments = BuildCompilerArguments(args); + process.Start(); + + while (!process.StandardOutput.EndOfStream) + { + string line = process.StandardOutput.ReadLine(); + ProcessLine(line); + } + + process.WaitForExit(); + + if (process.ExitCode != 0) + { + throw new InvalidOperationException(); + } + + return Task.FromResult(new CompileResults()); + } + } + + /// + /// Link Library + /// + public Task LinkLibraryAsync(LinkerArguments args) + { + return Task.CompletedTask; + } + + /// + /// Link Executable + /// + public Task LinkExecutableAsync(LinkerArguments args) + { + return Task.CompletedTask; + } + + private static string BuildCompilerArguments(CompileArguments args) + { + var commandArgs = new List(); + + // Set the Standard Library implementation + // commandArgs.Add("-stdlib=libc++"); + + // Set the language version + commandArgs.Add("-std=c++20"); + + // Enable experimental modules + commandArgs.Add("-fmodules-ts"); + + commandArgs.Add("-c"); + + // Lastly add the file + commandArgs.AddRange(args.SourceFiles); + + return string.Join(" ", commandArgs); + } + + private static void ProcessLine(string line) + { + Log.Info(line); + } + } +} diff --git a/Source/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h b/Source/Extensions/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h similarity index 98% rename from Source/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h rename to Source/Extensions/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h index 72e7076d..e4d91921 100644 --- a/Source/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h +++ b/Source/Extensions/Compiler/MSVC.UnitTests/CompilerArgumentBuilderTests.h @@ -134,9 +134,9 @@ namespace Soup::Compiler::MSVC::UnitTests } [[Theory]] - [[InlineData(Soup::LanguageStandard::CPP11, "/std:c++11")]] - [[InlineData(Soup::LanguageStandard::CPP14, "/std:c++14")]] - [[InlineData(Soup::LanguageStandard::CPP17, "/clang:-std=c++17")]] + [[InlineData(Soup::Compiler::LanguageStandard::CPP11, "/std:c++11")]] + [[InlineData(Soup::Compiler::LanguageStandard::CPP14, "/std:c++14")]] + [[InlineData(Soup::Compiler::LanguageStandard::CPP17, "/clang:-std=c++17")]] void SingleArgument_LanguageStandard(LanguageStandard standard, std::string expectedFlag) { CompileArguments arguments = {}; diff --git a/Source/Compiler/MSVC.UnitTests/CompilerTests.h b/Source/Extensions/Compiler/MSVC.UnitTests/CompilerTests.h similarity index 79% rename from Source/Compiler/MSVC.UnitTests/CompilerTests.h rename to Source/Extensions/Compiler/MSVC.UnitTests/CompilerTests.h index 7d372616..ade13dfe 100644 --- a/Source/Compiler/MSVC.UnitTests/CompilerTests.h +++ b/Source/Extensions/Compiler/MSVC.UnitTests/CompilerTests.h @@ -38,12 +38,12 @@ namespace Soup::Compiler::MSVC::UnitTests arguments.TargetFile = Path("obj/File.obj"); arguments.RootDirectory = Path("Source"); - auto buildState = Build::BuildState(Build::ValueTable()); - auto result = uut.CreateCompileNode(Build::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); + auto result = uut.CreateCompileNode(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::BuildGraphNode( + auto expected = Memory::Reference( + new Build::Runtime::BuildGraphNode( "File.cpp", "bin/mock.cl.exe", "/nologo /Zc:__cplusplus /std:c++11 /Od /X /RTC1 /EHsc /MT /bigobj /c File.cpp /Fo\"obj/File.obj\"", @@ -82,12 +82,12 @@ namespace Soup::Compiler::MSVC::UnitTests }); arguments.ExportModule = true; - auto buildState = Build::BuildState(Build::ValueTable()); - auto result = uut.CreateCompileNode(Build::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); + auto result = uut.CreateCompileNode(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::BuildGraphNode( + auto expected = Memory::Reference( + new Build::Runtime::BuildGraphNode( "File.cpp", "bin/mock.cl.exe", "/nologo /Zc:__cplusplus /std:c++11 /Od /I\"Includes\" /DDEBUG /X /RTC1 /EHsc /MT /module:reference \"Module.pcm\" /module:interface /module:output \"obj/File.ifc\" /bigobj /c File.cpp /Fo\"obj/File.obj\"", @@ -121,12 +121,12 @@ namespace Soup::Compiler::MSVC::UnitTests Path("File.mock.obj"), }); - auto buildState = Build::BuildState(Build::ValueTable()); - auto result = uut.CreateLinkNode(Build::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); + auto result = uut.CreateLinkNode(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::BuildGraphNode( + auto expected = Memory::Reference( + new Build::Runtime::BuildGraphNode( "Library.mock.a", "bin/mock.lib.exe", "/nologo /machine:X64 /out:\"Library.mock.a\" File.mock.obj", @@ -161,12 +161,12 @@ namespace Soup::Compiler::MSVC::UnitTests Path("Library.mock.a"), }); - auto buildState = Build::BuildState(Build::ValueTable()); - auto result = uut.CreateLinkNode(Build::BuildStateWrapper(buildState), arguments); + auto buildState = Build::Runtime::BuildState(Build::Runtime::ValueTable()); + auto result = uut.CreateLinkNode(Build::Extensions::BuildStateWrapper(buildState), arguments); // Verify result - auto expected = Memory::Reference( - new Build::BuildGraphNode( + auto expected = Memory::Reference( + new Build::Runtime::BuildGraphNode( "Something.exe", "bin/mock.link.exe", "/nologo /subsystem:console /machine:X64 /out:\"Something.exe\" Library.mock.a File.mock.obj", diff --git a/Source/Compiler/MSVC.UnitTests/LinkerArgumentBuilderTests.h b/Source/Extensions/Compiler/MSVC.UnitTests/LinkerArgumentBuilderTests.h similarity index 100% rename from Source/Compiler/MSVC.UnitTests/LinkerArgumentBuilderTests.h rename to Source/Extensions/Compiler/MSVC.UnitTests/LinkerArgumentBuilderTests.h diff --git a/Source/Compiler/MSVC.UnitTests/Recipe.toml b/Source/Extensions/Compiler/MSVC.UnitTests/Recipe.toml similarity index 60% rename from Source/Compiler/MSVC.UnitTests/Recipe.toml rename to Source/Extensions/Compiler/MSVC.UnitTests/Recipe.toml index bb19bd9b..496926b2 100644 --- a/Source/Compiler/MSVC.UnitTests/Recipe.toml +++ b/Source/Extensions/Compiler/MSVC.UnitTests/Recipe.toml @@ -2,9 +2,10 @@ Name = "SoupCompilerMSVCUnitTests" Version = "1.0.0" Type = "Executable" Dependencies = [ - "../../../Dependencies/SoupTest/Assert/", + # "../../../Dependencies/SoupTest/Assert/", "../MSVC/", - "../../TestUtilities/", + "../../../TestUtilities/", + "SoupTest@0.1.0", ] Source = [ "gen/Main.cpp", diff --git a/Source/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h b/Source/Extensions/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h similarity index 81% rename from Source/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h rename to Source/Extensions/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h index 04d2964b..46e4570b 100644 --- a/Source/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h +++ b/Source/Extensions/Compiler/MSVC.UnitTests/gen/CompilerArgumentBuilderTests.gen.h @@ -10,13 +10,13 @@ TestState RunCompilerArgumentBuilderTests() state += SoupTest::RunTest(className, "EmptyTargetFile_Throws", [&testClass]() { testClass->EmptyTargetFile_Throws(); }); state += SoupTest::RunTest(className, "DefaultParameters", [&testClass]() { testClass->DefaultParameters(); }); state += SoupTest::RunTest(className, "SingleArgument_GenerateIncludeTree", [&testClass]() { testClass->SingleArgument_GenerateIncludeTree(); }); - state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP11, \"/std:c++11\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP11, "/std:c++11"); }); - state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP14, \"/std:c++14\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP14, "/std:c++14"); }); - state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP17, \"/std:c++17\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP17, "/std:c++17"); }); + state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP11, \"/std:c++11\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP11, "/std:c++11"); }); + state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP14, \"/std:c++14\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP14, "/std:c++14"); }); + state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard(Soup::LanguageStandard::CPP17, \"/std:c++17\")", [&testClass]() { testClass->SingleArgument_LanguageStandard(Soup::Compiler::LanguageStandard::CPP17, "/std:c++17"); }); state += SoupTest::RunTest(className, "SingleArgument_LanguageStandard_CPP20", [&testClass]() { testClass->SingleArgument_LanguageStandard_CPP20(); }); state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel_Disabled", [&testClass]() { testClass->SingleArgument_OptimizationLevel_Disabled(); }); - state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Size, \"/Os\")", [&testClass]() { testClass->SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Size, "/Os"); }); - state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Speed, \"/Ot\")", [&testClass]() { testClass->SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Speed, "/Ot"); }); + state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Size, \"/Os\")", [&testClass]() { testClass->SingleArgument_OptimizationLevel(Soup::Compiler::OptimizationLevel::Size, "/Os"); }); + state += SoupTest::RunTest(className, "SingleArgument_OptimizationLevel(Soup::OptimizationLevel::Speed, \"/Ot\")", [&testClass]() { testClass->SingleArgument_OptimizationLevel(Soup::Compiler::OptimizationLevel::Speed, "/Ot"); }); state += SoupTest::RunTest(className, "SingleArgument_GenerateDebugInformation", [&testClass]() { testClass->SingleArgument_GenerateDebugInformation(); }); state += SoupTest::RunTest(className, "SingleArgument_IncludePaths", [&testClass]() { testClass->SingleArgument_IncludePaths(); }); state += SoupTest::RunTest(className, "SingleArgument_PreprocessorDefinitions", [&testClass]() { testClass->SingleArgument_PreprocessorDefinitions(); }); diff --git a/Source/Compiler/MSVC.UnitTests/gen/CompilerTests.gen.h b/Source/Extensions/Compiler/MSVC.UnitTests/gen/CompilerTests.gen.h similarity index 100% rename from Source/Compiler/MSVC.UnitTests/gen/CompilerTests.gen.h rename to Source/Extensions/Compiler/MSVC.UnitTests/gen/CompilerTests.gen.h diff --git a/Source/Compiler/MSVC.UnitTests/gen/LinkerArgumentBuilderTests.gen.h b/Source/Extensions/Compiler/MSVC.UnitTests/gen/LinkerArgumentBuilderTests.gen.h similarity index 100% rename from Source/Compiler/MSVC.UnitTests/gen/LinkerArgumentBuilderTests.gen.h rename to Source/Extensions/Compiler/MSVC.UnitTests/gen/LinkerArgumentBuilderTests.gen.h diff --git a/Source/Compiler/MSVC.UnitTests/gen/Main.cpp b/Source/Extensions/Compiler/MSVC.UnitTests/gen/Main.cpp similarity index 84% rename from Source/Compiler/MSVC.UnitTests/gen/Main.cpp rename to Source/Extensions/Compiler/MSVC.UnitTests/gen/Main.cpp index 9ae60cf4..9b30f3de 100644 --- a/Source/Compiler/MSVC.UnitTests/gen/Main.cpp +++ b/Source/Extensions/Compiler/MSVC.UnitTests/gen/Main.cpp @@ -6,11 +6,11 @@ #include import Opal; -import SoupCore; +import SoupCompiler; import SoupCompilerMSVC; -import SoupEngineDefinition; -import SoupEngineWrapper; -import SoupEngineCore; +import Soup.Build; +import Soup.Build.Extensions; +import Soup.Build.Runtime; import SoupTest; import SoupTestUtilities; diff --git a/Source/Compiler/MSVC/ArgumentBuilder.h b/Source/Extensions/Compiler/MSVC/ArgumentBuilder.h similarity index 100% rename from Source/Compiler/MSVC/ArgumentBuilder.h rename to Source/Extensions/Compiler/MSVC/ArgumentBuilder.h diff --git a/Source/Compiler/MSVC/Compiler.h b/Source/Extensions/Compiler/MSVC/Compiler.h similarity index 89% rename from Source/Compiler/MSVC/Compiler.h rename to Source/Extensions/Compiler/MSVC/Compiler.h index d94f25f2..a27a61de 100644 --- a/Source/Compiler/MSVC/Compiler.h +++ b/Source/Extensions/Compiler/MSVC/Compiler.h @@ -66,8 +66,8 @@ namespace Soup::Compiler::MSVC /// /// Compile /// - Build::GraphNodeWrapper CreateCompileNode( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CreateCompileNode( + Build::Extensions::BuildStateWrapper& state, const CompileArguments& args) const override final { // Clang decided to do their module compilation in two stages @@ -85,8 +85,8 @@ namespace Soup::Compiler::MSVC /// /// Link /// - Build::GraphNodeWrapper CreateLinkNode( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CreateLinkNode( + Build::Extensions::BuildStateWrapper& state, const LinkArguments& args) const override final { // Select the correct executable for linking libraries or executables @@ -121,8 +121,8 @@ namespace Soup::Compiler::MSVC } private: - Build::GraphNodeWrapper CompileStandard( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CompileStandard( + Build::Extensions::BuildStateWrapper& state, const CompileArguments& args) const { auto executablePath = _toolsPath + _compilerExecutable; @@ -144,8 +144,8 @@ namespace Soup::Compiler::MSVC return buildNode; } - Build::GraphNodeWrapper CompileModuleInterfaceUnit( - Build::BuildStateWrapper& state, + Build::Extensions::GraphNodeWrapper CompileModuleInterfaceUnit( + Build::Extensions::BuildStateWrapper& state, const CompileArguments& args) const { auto executablePath = _toolsPath + _compilerExecutable; diff --git a/Source/Compiler/MSVC/Module.cpp b/Source/Extensions/Compiler/MSVC/Module.cpp similarity index 85% rename from Source/Compiler/MSVC/Module.cpp rename to Source/Extensions/Compiler/MSVC/Module.cpp index 71ba2b8c..b47f51f6 100644 --- a/Source/Compiler/MSVC/Module.cpp +++ b/Source/Extensions/Compiler/MSVC/Module.cpp @@ -9,7 +9,7 @@ export module SoupCompilerMSVC; import Opal; -import SoupCore; +import SoupCompiler; using namespace Opal; diff --git a/Source/Compiler/MSVC/Recipe.toml b/Source/Extensions/Compiler/MSVC/Recipe.toml similarity index 78% rename from Source/Compiler/MSVC/Recipe.toml rename to Source/Extensions/Compiler/MSVC/Recipe.toml index 44506387..ac5d7e0f 100644 --- a/Source/Compiler/MSVC/Recipe.toml +++ b/Source/Extensions/Compiler/MSVC/Recipe.toml @@ -1,7 +1,7 @@ Name = "SoupCompilerMSVC" Version = "0.1.0" Dependencies = [ - "../../Core/", + "../Core/", ] Public = "Module.cpp" diff --git a/Source/RecipeBuildExtension.UnitTests/Recipe.json b/Source/Extensions/RecipeBuild.UnitTests/Recipe.json similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/Recipe.json rename to Source/Extensions/RecipeBuild.UnitTests/Recipe.json diff --git a/Source/RecipeBuildExtension.UnitTests/Tasks/BuildTaskTests.h b/Source/Extensions/RecipeBuild.UnitTests/Tasks/BuildTaskTests.h similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/Tasks/BuildTaskTests.h rename to Source/Extensions/RecipeBuild.UnitTests/Tasks/BuildTaskTests.h diff --git a/Source/RecipeBuildExtension.UnitTests/Tasks/RecipeBuildTaskTests.h b/Source/Extensions/RecipeBuild.UnitTests/Tasks/RecipeBuildTaskTests.h similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/Tasks/RecipeBuildTaskTests.h rename to Source/Extensions/RecipeBuild.UnitTests/Tasks/RecipeBuildTaskTests.h diff --git a/Source/RecipeBuildExtension.UnitTests/Tasks/ResolveToolsTaskTests.h b/Source/Extensions/RecipeBuild.UnitTests/Tasks/ResolveToolsTaskTests.h similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/Tasks/ResolveToolsTaskTests.h rename to Source/Extensions/RecipeBuild.UnitTests/Tasks/ResolveToolsTaskTests.h diff --git a/Source/RecipeBuildExtension.UnitTests/Tasks/StandardLibraryIncludeTaskTests.h b/Source/Extensions/RecipeBuild.UnitTests/Tasks/StandardLibraryIncludeTaskTests.h similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/Tasks/StandardLibraryIncludeTaskTests.h rename to Source/Extensions/RecipeBuild.UnitTests/Tasks/StandardLibraryIncludeTaskTests.h diff --git a/Source/RecipeBuildExtension.UnitTests/gen/Main.cpp b/Source/Extensions/RecipeBuild.UnitTests/gen/Main.cpp similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/gen/Main.cpp rename to Source/Extensions/RecipeBuild.UnitTests/gen/Main.cpp diff --git a/Source/RecipeBuildExtension.UnitTests/gen/Tasks/BuildTaskTests.gen.h b/Source/Extensions/RecipeBuild.UnitTests/gen/Tasks/BuildTaskTests.gen.h similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/gen/Tasks/BuildTaskTests.gen.h rename to Source/Extensions/RecipeBuild.UnitTests/gen/Tasks/BuildTaskTests.gen.h diff --git a/Source/RecipeBuildExtension.UnitTests/gen/Tasks/RecipeBuildTaskTests.gen.h b/Source/Extensions/RecipeBuild.UnitTests/gen/Tasks/RecipeBuildTaskTests.gen.h similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/gen/Tasks/RecipeBuildTaskTests.gen.h rename to Source/Extensions/RecipeBuild.UnitTests/gen/Tasks/RecipeBuildTaskTests.gen.h diff --git a/Source/RecipeBuildExtension.UnitTests/gen/Tasks/ResolveToolsTaskTests.gen.h b/Source/Extensions/RecipeBuild.UnitTests/gen/Tasks/ResolveToolsTaskTests.gen.h similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/gen/Tasks/ResolveToolsTaskTests.gen.h rename to Source/Extensions/RecipeBuild.UnitTests/gen/Tasks/ResolveToolsTaskTests.gen.h diff --git a/Source/RecipeBuildExtension.UnitTests/gen/Tasks/StandardLibraryIncludeTaskTests.gen.h b/Source/Extensions/RecipeBuild.UnitTests/gen/Tasks/StandardLibraryIncludeTaskTests.gen.h similarity index 100% rename from Source/RecipeBuildExtension.UnitTests/gen/Tasks/StandardLibraryIncludeTaskTests.gen.h rename to Source/Extensions/RecipeBuild.UnitTests/gen/Tasks/StandardLibraryIncludeTaskTests.gen.h diff --git a/Source/RecipeBuildExtension/Module.cpp b/Source/Extensions/RecipeBuild/Module.cpp similarity index 81% rename from Source/RecipeBuildExtension/Module.cpp rename to Source/Extensions/RecipeBuild/Module.cpp index e8031185..20d8ba46 100644 --- a/Source/RecipeBuildExtension/Module.cpp +++ b/Source/Extensions/RecipeBuild/Module.cpp @@ -22,11 +22,10 @@ module; export module RecipeBuild; import Opal; -import json11; -import SoupEngineDefinition; -import SoupEngineWrapper; -import SoupEngineCore; -import SoupCore; +import Soup.Build; +import Soup.Build.Extensions; +import Soup.Build.Runtime; +import SoupCompiler; import SoupCompilerClang; import SoupCompilerMSVC; diff --git a/Source/RecipeBuildExtension/Recipe.toml b/Source/Extensions/RecipeBuild/Recipe.toml similarity index 63% rename from Source/RecipeBuildExtension/Recipe.toml rename to Source/Extensions/RecipeBuild/Recipe.toml index 8ce0491f..050ec04b 100644 --- a/Source/RecipeBuildExtension/Recipe.toml +++ b/Source/Extensions/RecipeBuild/Recipe.toml @@ -2,8 +2,10 @@ Name = "RecipeBuildExtension" Type = "DynamicLibrary" Version = "1.0.0" Dependencies = [ - "../Opal/", - "../Core/", + # "../../Dependencies/Opal/Source/", + "Opal@0.1.1", + "../../Build/Runtime/", + "../Compiler/Core/", "../Compiler/Clang/", "../Compiler/MSVC/", ] diff --git a/Source/RecipeBuildExtension/RegisterBuildExtension.cpp b/Source/Extensions/RecipeBuild/RegisterBuildExtension.cpp similarity index 87% rename from Source/RecipeBuildExtension/RegisterBuildExtension.cpp rename to Source/Extensions/RecipeBuild/RegisterBuildExtension.cpp index 4c57f1b9..913de8f8 100644 --- a/Source/RecipeBuildExtension/RegisterBuildExtension.cpp +++ b/Source/Extensions/RecipeBuild/RegisterBuildExtension.cpp @@ -25,10 +25,10 @@ module RecipeBuild; using namespace Opal; -std::shared_ptr CreateMSVCCompiler(Soup::Build::ValueTableWrapper& activeState) +std::shared_ptr CreateMSVCCompiler(Soup::Build::Extensions::ValueTableWrapper& activeState) { auto visualCompilerToolsRoot = activeState.GetValue("MSVC.VCToolsRoot").AsString().GetValue(); - std::shared_ptr compiler = std::make_shared( + std::shared_ptr compiler = std::make_shared( Path(visualCompilerToolsRoot) + Path("bin/Hostx64/x64/"), Path("cl.exe"), Path("link.exe"), diff --git a/Source/RecipeBuildExtension/Tasks/BuildTask.h b/Source/Extensions/RecipeBuild/Tasks/BuildTask.h similarity index 80% rename from Source/RecipeBuildExtension/Tasks/BuildTask.h rename to Source/Extensions/RecipeBuild/Tasks/BuildTask.h index d25d19c6..81a9a38b 100644 --- a/Source/RecipeBuildExtension/Tasks/BuildTask.h +++ b/Source/Extensions/RecipeBuild/Tasks/BuildTask.h @@ -6,7 +6,7 @@ namespace RecipeBuild { - export using CreateCompiler = std::function(Soup::Build::ValueTableWrapper&)>; + export using CreateCompiler = std::function(Soup::Build::Extensions::ValueTableWrapper&)>; export using CompilerFactory = std::map; /// @@ -28,13 +28,29 @@ namespace RecipeBuild return "Build"; } + /// + /// Get the run before list + /// + Soup::Build::IList& GetRunBeforeList() noexcept override final + { + return _runBeforeList; + } + + /// + /// Get the run after list + /// + Soup::Build::IList& GetRunAfterList() noexcept override final + { + return _runAfterList; + } + /// /// The Core build task /// Soup::Build::OperationResult Execute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); try { @@ -57,18 +73,18 @@ namespace RecipeBuild /// The Core build task /// Soup::Build::OperationResult Execute( - Soup::Build::BuildStateWrapper& buildState) + Soup::Build::Extensions::BuildStateWrapper& buildState) { auto activeState = buildState.GetActiveState(); auto parentState = buildState.GetParentState(); auto buildTable = activeState.GetValue("Build").AsTable(); - auto arguments = Soup::Build::BuildArguments(); + auto arguments = Soup::Compiler::BuildArguments(); arguments.TargetName = buildTable.GetValue("TargetName").AsString().GetValue(); - arguments.TargetType = static_cast( + arguments.TargetType = static_cast( buildTable.GetValue("TargetType").AsInteger().GetValue()); - arguments.LanguageStandard = static_cast( + arguments.LanguageStandard = static_cast( buildTable.GetValue("LanguageStandard").AsInteger().GetValue()); arguments.WorkingDirectory = Path(buildTable.GetValue("WorkingDirectory").AsString().GetValue()); arguments.ObjectDirectory = Path(buildTable.GetValue("ObjectDirectory").AsString().GetValue()); @@ -118,12 +134,12 @@ namespace RecipeBuild if (buildTable.HasValue("OptimizationLevel")) { - arguments.OptimizationLevel = static_cast( + arguments.OptimizationLevel = static_cast( buildTable.GetValue("OptimizationLevel").AsInteger().GetValue()); } else { - arguments.OptimizationLevel = Soup::Build::BuildOptimizationLevel::None; + arguments.OptimizationLevel = Soup::Compiler::BuildOptimizationLevel::None; } if (buildTable.HasValue("GenerateSourceDebugInfo")) @@ -170,7 +186,7 @@ namespace RecipeBuild auto createCompiler = findCompilerFactory->second; auto compiler = createCompiler(activeState); - auto buildEngine = Soup::Build::BuildEngine(compiler); + auto buildEngine = Soup::Compiler::BuildEngine(compiler); auto buildResult = buildEngine.Execute(buildState, arguments); // Always pass along required input to parent build tasks @@ -204,5 +220,7 @@ namespace RecipeBuild private: CompilerFactory _compilerFactory; + Soup::Build::Runtime::StringList _runBeforeList; + Soup::Build::Runtime::StringList _runAfterList; }; } diff --git a/Source/RecipeBuildExtension/Tasks/RecipeBuildTask.h b/Source/Extensions/RecipeBuild/Tasks/RecipeBuildTask.h similarity index 73% rename from Source/RecipeBuildExtension/Tasks/RecipeBuildTask.h rename to Source/Extensions/RecipeBuild/Tasks/RecipeBuildTask.h index 5ca3a316..30cef5b4 100644 --- a/Source/RecipeBuildExtension/Tasks/RecipeBuildTask.h +++ b/Source/Extensions/RecipeBuild/Tasks/RecipeBuildTask.h @@ -12,6 +12,12 @@ namespace RecipeBuild export class RecipeBuildTask : public Memory::ReferenceCounted { public: + RecipeBuildTask() : + _runBeforeList({ "Build" }), + _runAfterList({ "ResolveTools" }) + { + } + /// /// Get the task name /// @@ -20,13 +26,29 @@ namespace RecipeBuild return "RecipeBuild"; } + /// + /// Get the run before list + /// + Soup::Build::IList& GetRunBeforeList() noexcept override final + { + return _runBeforeList; + } + + /// + /// Get the run after list + /// + Soup::Build::IList& GetRunAfterList() noexcept override final + { + return _runAfterList; + } + /// /// The Core Execute task /// Soup::Build::OperationResult Execute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); try { @@ -49,7 +71,7 @@ namespace RecipeBuild /// Internal implementation that can throw /// Soup::Build::OperationResult Execute( - Soup::Build::BuildStateWrapper& buildState) + Soup::Build::Extensions::BuildStateWrapper& buildState) { auto rootTable = buildState.GetActiveState(); auto recipeTable = rootTable.GetValue("Recipe").AsTable(); @@ -128,8 +150,8 @@ namespace RecipeBuild preprocessorDefinitions.push_back("SOUP_BUILD"); // Build up arguments to build this individual recipe - auto binaryDirectory = Soup::RecipeExtensions::GetBinaryDirectory(compilerName, buildFlavor); - auto objectDirectory = Soup::RecipeExtensions::GetObjectDirectory(compilerName, buildFlavor); + auto binaryDirectory = rootTable.GetValue("BinaryDirectory").AsString().GetValue(); + auto objectDirectory = rootTable.GetValue("ObjectDirectory").AsString().GetValue(); // Load the module interface file if present auto moduleInterfaceSourceFile = std::string(); @@ -153,7 +175,7 @@ namespace RecipeBuild sourceFiles = recipeTable.GetValue("Source").AsList().CopyAsStringVector(); } // Set the correct optimization level for the requested flavor - auto optimizationLevel = Soup::Build::BuildOptimizationLevel::None; + auto optimizationLevel = Soup::Compiler::BuildOptimizationLevel::None; bool generateSourceDebugInfo = false; if (buildFlavor == "debug") { @@ -163,7 +185,7 @@ namespace RecipeBuild else if (buildFlavor == "release") { preprocessorDefinitions.push_back("RELEASE"); - optimizationLevel = Soup::Build::BuildOptimizationLevel::Speed; + optimizationLevel = Soup::Compiler::BuildOptimizationLevel::Speed; } else { @@ -173,8 +195,8 @@ namespace RecipeBuild buildTable.EnsureValue("TargetName").SetValueString(name); buildTable.EnsureValue("WorkingDirectory").SetValueString(packageRoot.ToString()); - buildTable.EnsureValue("ObjectDirectory").SetValueString(objectDirectory.ToString()); - buildTable.EnsureValue("BinaryDirectory").SetValueString(binaryDirectory.ToString()); + buildTable.EnsureValue("ObjectDirectory").SetValueString(objectDirectory); + buildTable.EnsureValue("BinaryDirectory").SetValueString(binaryDirectory); buildTable.EnsureValue("ModuleInterfaceSourceFile").SetValueString(moduleInterfaceSourceFile); buildTable.EnsureValue("PlatformLibraries").SetValuePathList(platformLibraries); buildTable.EnsureValue("LinkLibraries").SetValuePathList(linkLibraries); @@ -186,23 +208,23 @@ namespace RecipeBuild buildTable.EnsureValue("GenerateSourceDebugInfo").SetValueBoolean(generateSourceDebugInfo); // Convert the recipe type to the required build type - Soup::Build::BuildTargetType targetType; - auto recipeType = Soup::RecipeType::StaticLibrary; + Soup::Compiler::BuildTargetType targetType; + auto recipeType = Soup::Build::Extensions::RecipeType::StaticLibrary; if (recipeTable.HasValue("Type")) { - recipeType = Soup::ParseRecipeType(recipeTable.GetValue("Type").AsString().GetValue()); + recipeType = Soup::Build::Extensions::ParseRecipeType(recipeTable.GetValue("Type").AsString().GetValue()); } switch (recipeType) { - case Soup::RecipeType::StaticLibrary: - targetType = Soup::Build::BuildTargetType::StaticLibrary; + case Soup::Build::Extensions::RecipeType::StaticLibrary: + targetType = Soup::Compiler::BuildTargetType::StaticLibrary; break; - case Soup::RecipeType::DynamicLibrary: - targetType = Soup::Build::BuildTargetType::DynamicLibrary; + case Soup::Build::Extensions::RecipeType::DynamicLibrary: + targetType = Soup::Compiler::BuildTargetType::DynamicLibrary; break; - case Soup::RecipeType::Executable: - targetType = Soup::Build::BuildTargetType::Executable; + case Soup::Build::Extensions::RecipeType::Executable: + targetType = Soup::Compiler::BuildTargetType::Executable; break; default: throw std::runtime_error("Unknown build target type."); @@ -211,27 +233,27 @@ namespace RecipeBuild buildTable.EnsureValue("TargetType").SetValueInteger(static_cast(targetType)); // Convert the recipe language version to the required build language - auto recipeLanguageVersion = Soup::RecipeLanguageVersion::CPP20; + auto recipeLanguageVersion = Soup::Build::Extensions::RecipeLanguageVersion::CPP20; if (recipeTable.HasValue("Language")) { - recipeLanguageVersion = Soup::ParseRecipeLanguageVersion( + recipeLanguageVersion = Soup::Build::Extensions::ParseRecipeLanguageVersion( recipeTable.GetValue("Language").AsString().GetValue()); } - Soup::LanguageStandard languageStandard; + Soup::Compiler::LanguageStandard languageStandard; switch (recipeLanguageVersion) { - case Soup::RecipeLanguageVersion::CPP11: - languageStandard = Soup::LanguageStandard::CPP11; + case Soup::Build::Extensions::RecipeLanguageVersion::CPP11: + languageStandard = Soup::Compiler::LanguageStandard::CPP11; break; - case Soup::RecipeLanguageVersion::CPP14: - languageStandard = Soup::LanguageStandard::CPP14; + case Soup::Build::Extensions::RecipeLanguageVersion::CPP14: + languageStandard = Soup::Compiler::LanguageStandard::CPP14; break; - case Soup::RecipeLanguageVersion::CPP17: - languageStandard = Soup::LanguageStandard::CPP17; + case Soup::Build::Extensions::RecipeLanguageVersion::CPP17: + languageStandard = Soup::Compiler::LanguageStandard::CPP17; break; - case Soup::RecipeLanguageVersion::CPP20: - languageStandard = Soup::LanguageStandard::CPP20; + case Soup::Build::Extensions::RecipeLanguageVersion::CPP20: + languageStandard = Soup::Compiler::LanguageStandard::CPP20; break; default: throw std::runtime_error("Unknown recipe language version."); @@ -241,5 +263,9 @@ namespace RecipeBuild return 0; } + + private: + Soup::Build::Runtime::StringList _runBeforeList; + Soup::Build::Runtime::StringList _runAfterList; }; } diff --git a/Source/RecipeBuildExtension/Tasks/ResolveToolsTask.h b/Source/Extensions/RecipeBuild/Tasks/ResolveToolsTask.h similarity index 86% rename from Source/RecipeBuildExtension/Tasks/ResolveToolsTask.h rename to Source/Extensions/RecipeBuild/Tasks/ResolveToolsTask.h index 17c8c7bc..552295f5 100644 --- a/Source/RecipeBuildExtension/Tasks/ResolveToolsTask.h +++ b/Source/Extensions/RecipeBuild/Tasks/ResolveToolsTask.h @@ -20,13 +20,29 @@ namespace RecipeBuild return "ResolveTools"; } + /// + /// Get the run before list + /// + Soup::Build::IList& GetRunBeforeList() noexcept override final + { + return _runBeforeList; + } + + /// + /// Get the run after list + /// + Soup::Build::IList& GetRunAfterList() noexcept override final + { + return _runAfterList; + } + /// /// The Core Execute task /// Soup::Build::OperationResult Execute( Soup::Build::IBuildState& buildState) noexcept override final { - auto buildStateWrapper = Soup::Build::BuildStateWrapper(buildState); + auto buildStateWrapper = Soup::Build::Extensions::BuildStateWrapper(buildState); try { @@ -49,7 +65,7 @@ namespace RecipeBuild /// The Core Execute task /// Soup::Build::OperationResult Execute( - Soup::Build::BuildStateWrapper& buildState) + Soup::Build::Extensions::BuildStateWrapper& buildState) { auto state = buildState.GetActiveState(); @@ -104,7 +120,7 @@ namespace RecipeBuild } private: - Path FindVSInstallRoot(Soup::Build::BuildStateWrapper& buildState) + Path FindVSInstallRoot(Soup::Build::Extensions::BuildStateWrapper& buildState) { // Find a copy of visual studio that has the required VisualCompiler auto executablePath = Path("C:/Program Files (x86)/Microsoft Visual Studio/Installer/vswhere.exe"); @@ -159,7 +175,7 @@ namespace RecipeBuild } std::string FindDefaultVCToolsVersion( - Soup::Build::BuildStateWrapper& buildState, + Soup::Build::Extensions::BuildStateWrapper& buildState, const Path& visualStudioInstallRoot) { // Check the default tools version @@ -186,7 +202,7 @@ namespace RecipeBuild } std::string FindNewestWindows10KitVersion( - Soup::Build::BuildStateWrapper& buildState, + Soup::Build::Extensions::BuildStateWrapper& buildState, const Path& windows10KitIncludePath) { // Check the default tools version @@ -224,5 +240,9 @@ namespace RecipeBuild return argumentString.str(); } + + private: + Soup::Build::Runtime::StringList _runBeforeList; + Soup::Build::Runtime::StringList _runAfterList; }; } diff --git a/Source/RecipeBuildExtension/Tasks/StandardLibraryIncludeTask.h b/Source/Extensions/RecipeBuild/Tasks/StandardLibraryIncludeTask.h similarity index 57% rename from Source/RecipeBuildExtension/Tasks/StandardLibraryIncludeTask.h rename to Source/Extensions/RecipeBuild/Tasks/StandardLibraryIncludeTask.h index a080f774..c2a30095 100644 --- a/Source/RecipeBuildExtension/Tasks/StandardLibraryIncludeTask.h +++ b/Source/Extensions/RecipeBuild/Tasks/StandardLibraryIncludeTask.h @@ -20,6 +20,22 @@ namespace RecipeBuild return "StandardLibraryInclude"; } + /// + /// Get the run before list + /// + Soup::Build::IList& GetRunBeforeList() noexcept override final + { + return _runBeforeList; + } + + /// + /// Get the run after list + /// + Soup::Build::IList& GetRunAfterList() noexcept override final + { + return _runAfterList; + } + /// /// The Core Execute task /// @@ -28,7 +44,7 @@ namespace RecipeBuild { try { - auto state = Soup::Build::BuildStateWrapper(buildState); + auto state = Soup::Build::Extensions::BuildStateWrapper(buildState); return 0; } @@ -38,5 +54,9 @@ namespace RecipeBuild return -1; } } + + private: + Soup::Build::Runtime::StringList _runBeforeList; + Soup::Build::Runtime::StringList _runAfterList; }; } diff --git a/Source/TestExtension/Module.cpp b/Source/Extensions/TestExtension/Module.cpp similarity index 100% rename from Source/TestExtension/Module.cpp rename to Source/Extensions/TestExtension/Module.cpp diff --git a/Source/TestExtension/Recipe.toml b/Source/Extensions/TestExtension/Recipe.toml similarity index 82% rename from Source/TestExtension/Recipe.toml rename to Source/Extensions/TestExtension/Recipe.toml index 4dff7e4e..a86ee12d 100644 --- a/Source/TestExtension/Recipe.toml +++ b/Source/Extensions/TestExtension/Recipe.toml @@ -3,7 +3,7 @@ Type = "DynamicLibrary" Version = "1.0.0" Dependencies = [ - "../Core/", + "../Client/Core/", ] Public = "Module.cpp" diff --git a/Source/Extensions/TestExtension/RegisterBuildExtension.cpp b/Source/Extensions/TestExtension/RegisterBuildExtension.cpp new file mode 100644 index 00000000..e47350ac --- /dev/null +++ b/Source/Extensions/TestExtension/RegisterBuildExtension.cpp @@ -0,0 +1,15 @@ +module; + +#define DllExport __declspec(dllexport) + +module TestExtension; + +extern "C" +{ + DllExport int RegisterBuildExtension(Soup::Build::IBuildSystem& buildSystem) + { + Opal::Memory::Reference testBuildTask = new TestBuildTask(); + buildSystem.RegisterTask(testBuildTask); + return 0; + } +} \ No newline at end of file diff --git a/Source/TestExtension/Tasks/TestBuildTask.h b/Source/Extensions/TestExtension/Tasks/TestBuildTask.h similarity index 100% rename from Source/TestExtension/Tasks/TestBuildTask.h rename to Source/Extensions/TestExtension/Tasks/TestBuildTask.h diff --git a/Source/Opal/Core/Path.h b/Source/Opal/Core/Path.h deleted file mode 100644 index 08824d7b..00000000 --- a/Source/Opal/Core/Path.h +++ /dev/null @@ -1,465 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// -#pragma once - -namespace Opal -{ - /// - /// A container for a path string - /// - export class Path - { - private: - static constexpr char DirectorySeparator = '/'; - static constexpr char AlternateDirectorySeparator = '\\'; - static constexpr std::string_view AllValidDirectorySeparators = "/\\"; - static constexpr char LetterDriveSpecifier = ':'; - static constexpr char FileExtensionSeparator = '.'; - static constexpr std::string_view RelativeDirectory = "."; - static constexpr std::string_view ParentDirectory = ".."; - - public: - /// - /// Initializes a new instance of the class. - /// - Path() : - _root(), - _directories(), - _filename() - { - } - - /// - /// Initializes a new instance of the class. - /// - Path(std::string_view value) : - _root(), - _directories(), - _filename() - { - ParsePath(value); - NormalizeDirectories(); - } - - /// - /// Gets a value indicating whether the path is empty - /// - bool IsEmpty() const - { - return _root.empty() && - _directories.empty() && - _filename.empty(); - } - - /// - /// Gets a value indicating whether the path has a root - /// - bool HasRoot() const - { - return !_root.empty(); - } - - /// - /// Gets the path root - /// - std::string GetRoot() const - { - return _root; - } - - /// - /// Gets the parent directory - /// - Path GetParent() const - { - auto result = Path(); - - // Take the root from the left hand side - result._root = _root; - - // If there is a filename then return the directory - // Otherwise return one less directory - if (HasFileName()) - { - // Pass along the directories - result._directories = _directories; - } - else - { - result._directories.reserve(_directories.size() - 1); - for (int i = 0; i < _directories.size() - 1; i++) - { - result._directories.push_back(_directories[0]); - } - } - - return result; - } - - /// - /// Gets a value indicating whether the path has a file name - /// - bool HasFileName() const - { - return !_filename.empty(); - } - - /// - /// Gets the file name - /// - std::string GetFileName() const - { - return _filename; - } - - /// - /// Gets a value indicating whether the file name has an stem - /// - bool HasFileStem() const - { - return !GetFileStem().empty(); - } - - /// - /// Gets the file name minus the extension - /// - std::string GetFileStem() const - { - // Everything before the last period is the stem - auto lastSeparator = _filename.find_last_of(FileExtensionSeparator); - if (lastSeparator != std::string::npos) - { - return _filename.substr(0, lastSeparator); - } - else - { - // Return the entire filename if no extension - return _filename; - } - } - - /// - /// Gets a value indicating whether the file name has an extension - /// - bool HasFileExtension() const - { - return !GetFileExtension().empty(); - } - - /// - /// Gets the file extension - /// - std::string GetFileExtension() const - { - // Everything after and including the last period is the extension - auto lastSeparator = _filename.find_last_of(FileExtensionSeparator); - if (lastSeparator != std::string::npos) - { - return _filename.substr(lastSeparator); - } - else - { - // Return the empty string - return ""; - } - } - - /// - /// Set the filename - /// - void SetFilename(std::string_view value) - { - _filename = std::string(value); - } - - /// - /// Set the file extension - /// - void SetFileExtension(std::string_view value) - { - // TODO: This could be faster if alocate string size and memcopy - _filename = GetFileStem() + FileExtensionSeparator + std::string(value); - } - - /// - /// Get a path relative to the provided base - /// - Path GetRelativeTo(const Path& base) - { - // If the root does not match then there is no way to get a relative path - // simply return a copy of this path - if ((base.HasRoot() && HasRoot() && base._root != this->_root) || - (base.HasRoot() ^ this->HasRoot())) - { - return *this; - } - - // Force the base filenames as directories - auto baseDirectories = base._directories; - if (base.HasFileName()) - { - baseDirectories.push_back(base._filename); - } - - // Determine how many of the directories match - int minDirectories = std::min(baseDirectories.size(), this->_directories.size()); - int countMatching = 0; - for (int i = 0; i < minDirectories; i++) - { - if (baseDirectories[i] != this->_directories[i]) - { - break; - } - - countMatching++; - } - - auto result = Path(); - - // Add in up directories for any not matching in the base - for (int i = countMatching; i < baseDirectories.size(); i++) - { - result._directories.push_back(std::string(ParentDirectory)); - } - - // Copy over the remaining entities from the target path - for (int i = countMatching; i < this->_directories.size(); i++) - { - result._directories.push_back(this->_directories[i]); - } - - // Set the file if present - if (this->HasFileName()) - { - result._filename = this->_filename; - } - - return result; - } - - /// - /// Equality operator - /// - bool operator ==(const Path& rhs) const - { - return _root == rhs._root && - _directories == rhs._directories && - _filename == rhs._filename; - } - - bool operator !=(const Path& rhs) const - { - return _root != rhs._root || - _directories != rhs._directories || - _filename != rhs._filename; - } - - bool operator <(const Path& rhs) const - { - // TODO: Tests and better implementation - return ToString() < rhs.ToString(); - } - - /// - /// Concatenate paths - /// - Path operator +(const Path& rhs) const - { - if (rhs.HasRoot()) - { - throw std::runtime_error( - "Cannot combine a rooted path on the right hand side: " + rhs.ToString()); - } - - auto result = Path(); - - // Take the root from the left hand side - result._root = _root; - - // Combine the directories - result._directories.reserve( - _directories.size() + rhs._directories.size()); - result._directories.insert( - result._directories.end(), - _directories.begin(), - _directories.end()); - - // Convert the left hand side filename to a directory - if (HasFileName()) - { - result._directories.push_back(_filename); - } - - result._directories.insert( - result._directories.end(), - rhs._directories.begin(), - rhs._directories.end()); - - // Take the filename from the right hand side - result._filename = rhs._filename; - - result.NormalizeDirectories(); - - return result; - } - - /// - /// Convert to string - /// - std::string ToString() const - { - return ToString(DirectorySeparator); - } - - std::string ToAlternateString() const - { - return ToString(AlternateDirectorySeparator); - } - -private: - void ParsePath(std::string_view value) - { - size_t current = 0; - size_t next = 0; - bool isFirst = true; - while ((next = value.find_first_of(AllValidDirectorySeparators, current)) != std::string::npos) - { - auto directory = value.substr(current, next - current); - - // Check if the first entry is a root - if (isFirst) - { - if (IsRoot(directory)) - { - _root = std::string(directory); - } - else - { - _directories.push_back(std::string(directory)); - } - - isFirst = false; - } - else - { - _directories.push_back(std::string(directory)); - } - - current = next + 1; - } - - // Check if there are characters beyond the last separator - if (current != value.size()) - { - auto directory = value.substr(current, next - current); - - // Check if still on the first entry - // Could be empty root or single filename - if (isFirst) - { - if (IsRoot(directory)) - { - _root = std::move(directory); - } - else - { - _filename = std::move(directory); - } - - isFirst = false; - } - else - { - _filename = std::move(directory); - } - } - } - - bool IsRoot(std::string_view value) - { - // Check for drive letter - if (value.size() == 2) - { - if (std::isalpha(value[0]) && value[1] == LetterDriveSpecifier) - { - return true; - } - } - - return false; - } - - void NormalizeDirectories() - { - // Remove as many up directories as we can - for (size_t i = 0; i < _directories.size(); i++) - { - // Remove the empty and current directories - if (_directories.at(i).empty() || _directories.at(i) == RelativeDirectory) - { - _directories.erase( - _directories.begin() + (i), - _directories.begin() + (i + 1)); - i -= 1; - } - else - { - // Check if we can combine any parent directories - // Allow the first directory to remain a parent - if (i != 0) - { - // Remove a parent directory if possible - if ( _directories.at(i) == ParentDirectory && - _directories.at(i - 1) != ParentDirectory) - { - // Remove the directories and move back - _directories.erase( - _directories.begin() + (i - 1), - _directories.begin() + (i + 1)); - i -= 2; - } - } - } - } - } - - /// - /// Convert to string with the provided directory separator - /// - std::string ToString(char directorySeparator) const - { - std::stringstream stringBuilder; - - if (IsEmpty()) - { - // If the path is empty then add the single relative directory - stringBuilder << RelativeDirectory << directorySeparator; - } - else - { - if (HasRoot()) - { - stringBuilder << _root << directorySeparator; - } - - for (size_t i = 0; i < _directories.size(); i++) - { - stringBuilder << _directories[i] << directorySeparator; - } - - if (HasFileName()) - { - stringBuilder << _filename; - } - } - - return stringBuilder.str(); - } - - private: - std::string _root; - std::vector _directories; - std::string _filename; - }; -} diff --git a/Source/Opal/Core/SemanticVersion.h b/Source/Opal/Core/SemanticVersion.h deleted file mode 100644 index 00aa34e2..00000000 --- a/Source/Opal/Core/SemanticVersion.h +++ /dev/null @@ -1,159 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// -#pragma once - -namespace Opal -{ - /// - /// The semantic version class - /// - export class SemanticVersion - { - public: - /// - /// Try parse the value - /// - static bool TryParse(const std::string& value, SemanticVersion& result) - { - // TODO: Invert this so TryParse is the default and Parse adds an exception - // it is way faster in the fail case - try - { - result = Parse(value); - return true; - } - catch (...) - { - } - - result = SemanticVersion(); - return false; - } - - /// - /// Parse the value - /// - static SemanticVersion Parse(const std::string& value) - { - // Parse the integer values - std::vector values; - auto stream = std::istringstream(value); - std::string stringValue; - while (std::getline(stream, stringValue, '.')) - { - auto intValue = std::stoi(stringValue); - values.push_back(intValue); - } - - if (values.size() != 3) - { - throw std::runtime_error("The version string must have three values."); - } - - return SemanticVersion( - values[0], - values[1], - values[2]); - } - - public: - /// - /// Initializes a new instance of the class. - /// - SemanticVersion() : - _major(0), - _minor(0), - _patch(0) - { - } - - /// - /// Initializes a new instance of the class. - /// - SemanticVersion(short major, short minor, short patch) : - _major(major), - _minor(minor), - _patch(patch) - { - } - - /// - /// Gets or sets the version major - /// - int GetMajor() const - { - return _major; - } - - /// - /// Gets or sets the version minor - /// - int GetMinor() const - { - return _minor; - } - - /// - /// Gets or sets the version patch - /// - int GetPatch() const - { - return _patch; - } - - /// - /// Equality operator - /// - bool operator ==(const SemanticVersion& rhs) const - { - return _major == rhs. _major && - _minor == rhs. _minor && - _patch == rhs. _patch; - } - - /// - /// Inequality operator - /// - bool operator !=(const SemanticVersion& rhs) const - { - return _major != rhs. _major || - _minor != rhs. _minor || - _patch != rhs. _patch; - } - - /// - /// Comparison operator - /// - bool operator <(const SemanticVersion& rhs) const - { - return _major < rhs. _major || - _minor < rhs. _minor || - _patch < rhs. _patch; - } - bool operator >(const SemanticVersion& rhs) const - { - return _major > rhs. _major || - _minor > rhs. _minor || - _patch > rhs. _patch; - } - - /// - /// Convert to string - /// - std::string ToString() const - { - // "{Major}.{Minor}.{Patch}" - std::stringstream stringBuilder; - stringBuilder << _major << "."; - stringBuilder << _minor << "."; - stringBuilder << _patch; - return stringBuilder.str(); - } - - private: - int _major; - int _minor; - int _patch; - }; -} diff --git a/Source/Opal/IO/IConsoleInputStream.h b/Source/Opal/IO/IConsoleInputStream.h deleted file mode 100644 index e479c52c..00000000 --- a/Source/Opal/IO/IConsoleInputStream.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Opal::IO -{ - /// - /// The console input stream interface - /// Interface mainly used to allow for unit testing client code - /// - export class IConsoleInputStream - { - public: - /// - /// Read a line from the stream - /// - virtual std::string ReadLine() = 0; - - /// - /// Read a password from the stream - /// - virtual std::string ReadPassword() = 0; - }; -} diff --git a/Source/Opal/IO/IConsoleManager.h b/Source/Opal/IO/IConsoleManager.h deleted file mode 100644 index 0ae06b17..00000000 --- a/Source/Opal/IO/IConsoleManager.h +++ /dev/null @@ -1,46 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IConsoleInputStream.h" - -namespace Opal::IO -{ - /// - /// The input manager interface - /// Interface mainly used to allow for unit testing client code - /// - export class IConsoleManager - { - public: - /// - /// Gets the current active manager - /// - static IConsoleManager& Current() - { - if (_current == nullptr) - throw std::runtime_error("No console manager implementation registered."); - return *_current; - } - - /// - /// Register a new active input manager - /// - static void Register(std::shared_ptr manager) - { - _current = std::move(manager); - } - - public: - /// - /// Get the standard input stream - /// - virtual std::shared_ptr GetStandardInput() = 0; - - private: - static std::shared_ptr _current; - }; - - std::shared_ptr IConsoleManager::_current = nullptr; -} diff --git a/Source/Opal/IO/MockConsoleInputStream.h b/Source/Opal/IO/MockConsoleInputStream.h deleted file mode 100644 index ab43e4f4..00000000 --- a/Source/Opal/IO/MockConsoleInputStream.h +++ /dev/null @@ -1,71 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IConsoleInputStream.h" - -namespace Opal::IO -{ - /// - /// A mock Console Input Stream - /// - export class MockConsoleInputStream : public IConsoleInputStream - { - public: - /// - /// Initializes a new instance of the class. - /// - MockConsoleInputStream(std::vector& parentRequests) : - _parentRequests(parentRequests), - _readPasswordResponse(), - _readLineResponse() - { - } - - /// - /// Set the response for a read password request - /// - void SetReadPasswordResponse(std::string response) - { - _readPasswordResponse = response; - } - - /// - /// Set the response for a read line request - /// - void SetReadLineResponse(std::string response) - { - _readLineResponse = response; - } - - /// - /// Read a line from the stream - /// - virtual std::string ReadLine() override final - { - auto message = std::stringstream(); - message << "ReadLine: " << _readLineResponse; - _parentRequests.push_back(message.str()); - - return _readLineResponse; - } - - /// - /// Read a password from the stream - /// - virtual std::string ReadPassword() override final - { - auto message = std::stringstream(); - message << "ReadPassword: " << _readPasswordResponse; - _parentRequests.push_back(message.str()); - - return _readPasswordResponse; - } - - private: - std::vector& _parentRequests; - std::string _readPasswordResponse; - std::string _readLineResponse; - }; -} diff --git a/Source/Opal/IO/MockConsoleManager.h b/Source/Opal/IO/MockConsoleManager.h deleted file mode 100644 index 6edf4a3f..00000000 --- a/Source/Opal/IO/MockConsoleManager.h +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IConsoleManager.h" -#include "MockConsoleInputStream.h" - -namespace Opal::IO -{ - /// - /// The mock console manager - /// TODO: Move into test project - /// - export class MockConsoleManager : public IConsoleManager - { - public: - /// - /// Initializes a new instance of the class. - /// - MockConsoleManager() : - _requests(), - _standardInput(std::make_shared(_requests)) - { - } - - /// - /// Get the requests - /// - const std::vector& GetRequests() const - { - return _requests; - } - - /// - /// Get the mock input stream - /// - MockConsoleInputStream& GetMockInputStream() - { - return *_standardInput; - } - - /// - /// Get the standard input stream - /// - std::shared_ptr GetStandardInput() override final - { - auto message = std::stringstream(); - message << "GetStandardInput"; - _requests.push_back(message.str()); - - return _standardInput; - } - - private: - std::vector _requests; - std::shared_ptr _standardInput; - }; -} diff --git a/Source/Opal/IO/ScopedConsoleManagerRegister.h b/Source/Opal/IO/ScopedConsoleManagerRegister.h deleted file mode 100644 index 92ce3465..00000000 --- a/Source/Opal/IO/ScopedConsoleManagerRegister.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IConsoleManager.h" - -namespace Opal::IO -{ - /// - /// A scopped network manager registration helper - /// - export class ScopedConsoleManagerRegister - { - public: - /// - /// Initializes a new instance of the class. - /// - ScopedConsoleManagerRegister(std::shared_ptr manager) - { - IConsoleManager::Register(std::move(manager)); - } - - /// - /// Finalizes an instance of the class. - /// - ~ScopedConsoleManagerRegister() - { - IConsoleManager::Register(nullptr); - } - }; -} diff --git a/Source/Opal/IO/SystemConsoleInputStream.h b/Source/Opal/IO/SystemConsoleInputStream.h deleted file mode 100644 index 533406cd..00000000 --- a/Source/Opal/IO/SystemConsoleInputStream.h +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IConsoleInputStream.h" - -namespace Opal::IO -{ - /// - /// The system console input stream implementation - /// - export class SystemConsoleInputStream : public IConsoleInputStream - { - public: - /// - /// Initializes a new instance of the class. - /// - SystemConsoleInputStream() - { -#ifdef WIN32 - _inputHandle = GetStdHandle(STD_INPUT_HANDLE); - if (_inputHandle == INVALID_HANDLE_VALUE) - throw std::runtime_error("GetStdHandle Failed"); -#endif - } - - ~SystemConsoleInputStream() - { -#ifdef WIN32 - _inputHandle = INVALID_HANDLE_VALUE; -#endif - } - - /// - /// Read a line from the stream - /// - std::string ReadLine() override final - { - std::string result; - std::getline(std::cin, result); - return result; - } - - /// - /// Read a password from the stream - /// - std::string ReadPassword() override final - { -#ifdef WIN32 - const char Backspace = 8; - const char Return = 13; - - // Save off the original state - DWORD previousMode; - if (!GetConsoleMode(_inputHandle, &previousMode)) - throw std::runtime_error("GetConsoleMode Failed"); - - // Disable echo input and read individual characters - DWORD currentMode = previousMode & ~(ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT); - if (!SetConsoleMode(_inputHandle, currentMode)) - throw std::runtime_error("SetConsoleMode Failed"); - - // Read until we get a return character - std::string password; - unsigned char character = 0; - DWORD charactersRead; - while (ReadConsoleA(_inputHandle, &character, 1, &charactersRead, nullptr)) - { - if (character == Return) - { - std::cout << std::endl; - break; - } - else if (character == Backspace) - { - // If not empty then remove a single character - if (!password.empty()) - { - std::cout << "\b \b"; - password.resize(password.length() - 1); - } - } - else - { - password += character; - std::cout << '*'; - } - } - - // Restore the original state - if (!SetConsoleMode(_inputHandle, previousMode)) - throw std::runtime_error("SetConsoleMode Failed"); - - return password; -#else - // www.cplusplus.com/articles/E6vU7k9E/ - #error Linux Not Implemented -#endif - } - - private: -#ifdef WIN32 - HANDLE _inputHandle; -#else - #error Linux Not Implemented -#endif - }; -} diff --git a/Source/Opal/IO/SystemConsoleManager.h b/Source/Opal/IO/SystemConsoleManager.h deleted file mode 100644 index 0ca0477d..00000000 --- a/Source/Opal/IO/SystemConsoleManager.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IConsoleManager.h" -#include "SystemConsoleInputStream.h" - -namespace Opal::IO -{ - /// - /// The system console manager - /// - export class SystemConsoleManager : public IConsoleManager - { - public: - /// - /// Initializes a new instance of the class. - /// - SystemConsoleManager() - { - } - - /// - /// Get the standard input stream - /// - virtual std::shared_ptr GetStandardInput() override final - { - return std::make_shared(); - } - }; -} diff --git a/Source/Opal/Logger/ConsoleTraceListener.h b/Source/Opal/Logger/ConsoleTraceListener.h deleted file mode 100644 index 2b615866..00000000 --- a/Source/Opal/Logger/ConsoleTraceListener.h +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "TraceListener.h" - -namespace Opal -{ - /// - /// Console logger that wraps the base - /// - export class ConsoleTraceListener : public TraceListener - { - public: - /// - /// Initializes a new instance of the class. - /// - ConsoleTraceListener() : - TraceListener() - { - } - - /// - /// Initializes a new instance of the class. - /// - ConsoleTraceListener( - std::string name, - std::shared_ptr filter, - bool showEventType, - bool showEventId) : - TraceListener( - std::move(name), - std::move(filter), - showEventType, - showEventId) - { - } - - /// - /// Writes a message and newline terminator - /// - virtual void WriteLine(const std::string& message) override final - { - // if (NeedIndent) - // { - // WriteIndent(); - // } - - SetConsoleColor(); - std::cout << message << std::endl; - // TODO: restore color - - // NeedIndent = true; - } - - private: - void SetConsoleColor() - { - // TODO - // switch (_currentEvent) - // { - // case TraceEventType.Error: - // Console.ForegroundColor = ConsoleColor.Red; - // break; - // case TraceEventType.Warning: - // Console.ForegroundColor = ConsoleColor.Yellow; - // break; - // } - } - }; -} diff --git a/Source/Opal/Logger/EventTypeFilter.h b/Source/Opal/Logger/EventTypeFilter.h deleted file mode 100644 index 0c3598a8..00000000 --- a/Source/Opal/Logger/EventTypeFilter.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "TraceListener.h" - -namespace Opal -{ - export class EventTypeFilter : public IEventFilter - { - public: - EventTypeFilter(TraceEventFlag eventTypes) : - _types(static_cast(eventTypes)) - { - } - - void Set(TraceEventFlag eventType) - { - _types = static_cast(eventType); - } - - void Disable(TraceEventFlag eventType) - { - _types &= ~static_cast(eventType); - } - - void Enable(TraceEventFlag eventType) - { - _types |= static_cast(eventType); - } - - bool IsEnabled(TraceEventFlag eventType) - { - auto typeValue = static_cast(eventType); - return ( _types & typeValue) == typeValue; - } - - virtual bool ShouldTrace(TraceEventFlag eventType) override final - { - return IsEnabled(eventType); - } - - private: - uint32_t _types; - }; -} diff --git a/Source/Opal/Logger/Log.h b/Source/Opal/Logger/Log.h deleted file mode 100644 index 04869b2d..00000000 --- a/Source/Opal/Logger/Log.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "EventTypeFilter.h" - -namespace Opal -{ - /// - /// The static logger class - /// - export class Log - { - public: - /// - /// Register the single event listener - /// - static void RegisterListener(std::shared_ptr listener) - { - s_listener = std::move(listener); - } - - /// - /// Get access to the single event listener - /// - static TraceListener& EnsureListener() - { - if (s_listener == nullptr) - throw std::runtime_error("No Listener registered."); - return *s_listener; - } - - /// - /// Set the active ids to use for each event - /// - static void SetActiveId(int value) - { - s_activeId = value; - } - - /// - /// Log a high priority message - /// - static void HighPriority(std::string_view message, int id) - { - EnsureListener().TraceEvent(TraceEventFlag::HighPriority, id, message); - } - static void HighPriority(std::string_view message) - { - HighPriority(message, s_activeId); - } - - /// - /// Log a generic infomational message - /// - static void Info(std::string_view message, int id) - { - EnsureListener().TraceEvent(TraceEventFlag::Information, id, message); - } - static void Info(std::string_view message) - { - Info(message, s_activeId); - } - - /// - /// Log a diagnostic message - /// - static void Diag(std::string_view message, int id) - { - EnsureListener().TraceEvent(TraceEventFlag::Diagnostic, id, message); - } - static void Diag(std::string_view message) - { - Diag(message, s_activeId); - } - - - /// - /// Log a warning message - /// - static void Warning(std::string_view message, int id) - { - EnsureListener().TraceEvent(TraceEventFlag::Warning, id, message); - } - static void Warning(std::string_view message) - { - Warning(message, s_activeId); - } - - /// - /// Log an error message - /// - static void Error(std::string_view message, int id) - { - EnsureListener().TraceEvent(TraceEventFlag::Error, id, message); - } - static void Error(std::string_view message) - { - Error(message, s_activeId); - } - - private: - static int s_activeId; - static std::shared_ptr s_listener; - }; - - int Log::s_activeId = 0; - std::shared_ptr Log::s_listener = nullptr; -} diff --git a/Source/Opal/Logger/ScopedTraceListenerRegister.h b/Source/Opal/Logger/ScopedTraceListenerRegister.h deleted file mode 100644 index 84c190c2..00000000 --- a/Source/Opal/Logger/ScopedTraceListenerRegister.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "TraceListener.h" - -namespace Opal -{ - /// - /// A scopped trace listener registration helper - /// - export class ScopedTraceListenerRegister - { - public: - /// - /// Initializes a new instance of the class. - /// - ScopedTraceListenerRegister(std::shared_ptr listener) - { - Log::RegisterListener(std::move(listener)); - } - - /// - /// Finalizes an instance of the class. - /// - ~ScopedTraceListenerRegister() - { - Log::RegisterListener(nullptr); - } - }; -} diff --git a/Source/Opal/Logger/TestTraceListener.h b/Source/Opal/Logger/TestTraceListener.h deleted file mode 100644 index a985e63b..00000000 --- a/Source/Opal/Logger/TestTraceListener.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "TraceListener.h" - -namespace Opal -{ - /// - /// Test logger that wraps the base - /// - export class TestTraceListener : public TraceListener - { - public: - /// - /// Initializes a new instance of the class. - /// - TestTraceListener() : - TraceListener("", nullptr, true, false), - _messages() - { - } - - /// - /// Get the messages - /// - const std::vector& GetMessages() const - { - return _messages; - } - - /// - /// Writes a message and newline terminator - /// - virtual void WriteLine(const std::string& message) override final - { - auto line = std::string(message); - _messages.push_back(std::move(line)); - } - - private: - std::vector _messages; - }; -} diff --git a/Source/Opal/Logger/TextWriterExtendedTraceListener.cs b/Source/Opal/Logger/TextWriterExtendedTraceListener.cs deleted file mode 100644 index 0de6e803..00000000 --- a/Source/Opal/Logger/TextWriterExtendedTraceListener.cs +++ /dev/null @@ -1,307 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -namespace Opal -{ - using System; - using System.IO; - using System.Text; - - /// - /// A clone of the that utilizes the - /// - public class TextWriterExtendedTraceListener : ExtendedTraceListener - { - private TextWriter _writer; - private string _fileName = null; - - /// - /// Initializes a new instance of the class with - /// as the output recipient. - /// - public TextWriterExtendedTraceListener() - { - } - - /// - /// Initializes a new instance of the class, using the - /// stream as the recipient of the debugging and tracing output. - /// - public TextWriterExtendedTraceListener(Stream stream) - : this(stream, string.Empty) - { - } - - /// - /// Initializes a new instance of the class with the - /// specified name and using the stream as the recipient of the debugging and tracing output. - /// - public TextWriterExtendedTraceListener(Stream stream, string name) - : base(name) - { - _writer = new StreamWriter( - stream ?? throw new ArgumentNullException(nameof(stream))); - } - - /// - /// Initializes a new instance of the class using the - /// specified writer as recipient of the tracing or debugging output. - /// - public TextWriterExtendedTraceListener(TextWriter writer) - : this(writer, string.Empty) - { - } - - /// - /// Initializes a new instance of the class with the - /// specified name and using the specified writer as recipient of the tracing or - /// debugging output. - /// - public TextWriterExtendedTraceListener(TextWriter writer, string name) - : base(name) - { - _writer = writer ?? throw new ArgumentNullException(nameof(writer)); - } - - /// - /// Initializes a new instance of the class - /// - public TextWriterExtendedTraceListener(string fileName) - { - _fileName = fileName; - } - - /// - /// Initializes a new instance of the class - /// - public TextWriterExtendedTraceListener(string fileName, string name) - : base(name) - { - _fileName = fileName; - } - - /// - /// Gets or sets the text writer that receives the tracing - /// or debugging output. - /// - public TextWriter Writer - { - get - { - EnsureWriter(); - return _writer; - } - - set - { - _writer = value; - } - } - - /// - /// Closes the so that it no longer - /// receives tracing or debugging output. - /// - public override void Close() - { - if (_writer != null) - { - try - { - _writer.Close(); - } - catch (ObjectDisposedException) - { - } - } - - _writer = null; - } - - /// - /// Flushes the output buffer for the . - /// - public override void Flush() - { - if (!EnsureWriter()) - { - return; - } - - try - { - _writer.Flush(); - } - catch (ObjectDisposedException) - { - } - } - - /// - /// Writes a message - /// to this instance's . - /// - public override void Write(string message) - { - if (!EnsureWriter()) - { - return; - } - - if (NeedIndent) - { - WriteIndent(); - } - - try - { - _writer.Write(message); - } - catch (ObjectDisposedException) - { - } - } - - /// - /// Writes a message - /// to this instance's followed by a line terminator. The - /// default line terminator is a carriage return followed by a line feed (\r\n). - /// - public override void WriteLine(string message) - { - if (!EnsureWriter()) - { - return; - } - - if (NeedIndent) - { - WriteIndent(); - } - - try - { - _writer.WriteLine(message); - NeedIndent = true; - } - catch (ObjectDisposedException) - { - } - } - - /// - /// Dispose - /// - protected override void Dispose(bool disposing) - { - try - { - if (disposing) - { - Close(); - } - else - { - // clean up resources - if (_writer != null) - { - try - { - _writer.Close(); - } - catch (ObjectDisposedException) - { - } - } - - _writer = null; - } - } - finally - { - base.Dispose(disposing); - } - } - - private static Encoding GetEncodingWithFallback(Encoding encoding) - { - // Clone it and set the "?" replacement fallback - Encoding fallbackEncoding = (Encoding)encoding.Clone(); - fallbackEncoding.EncoderFallback = EncoderFallback.ReplacementFallback; - fallbackEncoding.DecoderFallback = DecoderFallback.ReplacementFallback; - - return fallbackEncoding; - } - - /// - /// This uses a machine resource, scoped by the fileName variable. - /// - private bool EnsureWriter() - { - bool ret = true; - - if (_writer == null) - { - ret = false; - - if (_fileName == null) - { - return ret; - } - - // StreamWriter by default uses UTF8Encoding which will throw on invalid encoding errors. - // This can cause the internal StreamWriter's state to be irrecoverable. It is bad for tracing - // APIs to throw on encoding errors. Instead, we should provide a "?" replacement fallback - // encoding to substitute illegal chars. For ex, In case of high surrogate character - // D800-DBFF without a following low surrogate character DC00-DFFF - // NOTE: We also need to use an encoding that does't emit BOM whic is StreamWriter's default - Encoding noBOMwithFallback = GetEncodingWithFallback(new UTF8Encoding(false)); - - // To support multiple appdomains/instances tracing to the same file, - // we will try to open the given file for append but if we encounter - // IO errors, we will prefix the file name with a unique GUID value - // and try one more time - string fullPath = Path.GetFullPath(_fileName); - string dirPath = Path.GetDirectoryName(fullPath); - string fileNameOnly = Path.GetFileName(fullPath); - - for (int i = 0; i < 2; i++) - { - try - { - _writer = new StreamWriter(fullPath, true, noBOMwithFallback, 4096); - ret = true; - break; - } - catch (IOException) - { - fileNameOnly = Guid.NewGuid().ToString() + fileNameOnly; - fullPath = Path.Combine(dirPath, fileNameOnly); - continue; - } - catch (UnauthorizedAccessException) - { - // ERROR_ACCESS_DENIED, mostly ACL issues - break; - } - catch (Exception) - { - break; - } - } - - if (!ret) - { - // Disable tracing to this listener. Every Write will be nop. - // We need to think of a central way to deal with the listener - // init errors in the future. The default should be that we eat - // up any errors from listener and optionally notify the user - _fileName = null; - } - } - - return ret; - } - } -} diff --git a/Source/Opal/Logger/TraceListener.h b/Source/Opal/Logger/TraceListener.h deleted file mode 100644 index d4bd4082..00000000 --- a/Source/Opal/Logger/TraceListener.h +++ /dev/null @@ -1,197 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Opal -{ - export enum class TraceEventFlag : uint32_t - { - // High Priority message. - HighPriority = 1 << 0, - // Informational message. - Information = 1 << 1, - // Diagnostic trace. - Diagnostic = 1 << 2, - // Noncritical problem. - Warning = 1 << 3, - // Recoverable error. - Error = 1 << 4, - // Fatal error or application crash. - Critical = 1 << 5, - }; - - class IEventFilter - { - public: - virtual bool ShouldTrace(TraceEventFlag eventType) = 0; - }; - - /// - /// Base trace listener used to determine what events and properties to include in logs - /// - class TraceListener - { - protected: - /// - /// Initializes a new instance of the class. - /// - TraceListener() : - TraceListener("", nullptr, true, true) - { - } - - /// - /// Initializes a new instance of the class using the specified name as the - /// listener. - /// - TraceListener( - std::string name, - std::shared_ptr filter, - bool showEventType, - bool showEventId) : - _name(std::move(name)), - _filter(std::move(filter)), - _showEventType(showEventType), - _showEventId(showEventId) - { - } - - /// - /// Implementation dependant write methods - /// - virtual void WriteLine(const std::string& message) = 0; - - public: - /// - /// Gets a value indicating whether there is a custom event filter - /// - bool HasFilter() const - { - return _filter != nullptr; - } - - /// - /// Gets or sets a value indicating whether to show or hide the event type - /// - bool GetShowEventType() const - { - return _showEventType; - } - - /// - /// Gets or sets a value indicating whether to show or hide the event id - /// - bool GetShowEventId() const - { - return _showEventId; - } - void SetShowEventId(bool value) - { - _showEventId = value; - } - - /// - /// All other TraceEvent methods come through this one. - /// - void TraceEvent( - TraceEventFlag eventType, - int id, - std::string_view message) - { - if (HasFilter() && ! _filter->ShouldTrace(eventType)) - { - return; - } - - // Build up the resulting message with required header/footer - auto builder = std::stringstream(); - WriteHeader(builder, eventType, id); - builder << message; - - bool isEmpty = builder.rdbuf()->in_avail() == 0; - if (isEmpty) - WriteLine(""); - else - WriteLine(builder.str()); - } - - /// - /// Trace Event - /// - // void TraceEvent( - // string source, - // TraceEventFlag eventType, - // int id, - // string format, - // params object[] args) - // { - // if (Filter != null && !Filter.ShouldTrace( source, eventType, id, format, args, null, null)) - // { - // return; - // } - - // WriteHeader(source, eventType, id); - // if (args != null) - // { - // WriteLine(string.Format(CultureInfo.InvariantCulture, format, args)); - // } - // else - // { - // WriteLine(format); - // } - // } - - private: - /// - /// Write the header to the target listener - /// - void WriteHeader( - std::ostream& stream, - TraceEventFlag eventType, - int id) - { - if (GetShowEventType()) - { - switch (eventType) - { - case TraceEventFlag::HighPriority: - stream << "HIGH"; - break; - case TraceEventFlag::Information: - stream << "INFO"; - break; - case TraceEventFlag::Diagnostic: - stream << "DIAG"; - break; - case TraceEventFlag::Warning: - stream << "WARN"; - break; - case TraceEventFlag::Error: - stream << "ERRO"; - break; - case TraceEventFlag::Critical: - stream << "CRIT"; - break; - default: - stream << "UNKN"; - break; - } - - stream << ": "; - } - - if (GetShowEventId()) - { - stream << std::to_string(id) << ">"; - } - } - - private: - std::string _name; - std::shared_ptr _filter; - bool _showEventType; - bool _showEventId; - }; -} diff --git a/Source/Opal/Memory/IReferenceCounted.h b/Source/Opal/Memory/IReferenceCounted.h deleted file mode 100644 index e369780c..00000000 --- a/Source/Opal/Memory/IReferenceCounted.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// -#pragma once - -namespace Opal::Memory -{ - /// - /// A container for a path string - /// - export class IReferenceCounted - { - public: - /// - /// Virtual destructor to ensure proper cleanup when deleting this as a base - /// Note: This could be a private destructor to force delete through the release reference - /// but that would be very restrictive on other code bases that wish to use this in some scenarios. - /// - virtual ~IReferenceCounted() noexcept - { - } - - /// - /// Adds a reference to the object - /// Note: These methods are marked as const to allow for constant references - /// This will require the implementation to use a mutable reference count. - /// - virtual void AddReference() const noexcept = 0; - - /// - /// Releases a reference to the object and destructs if this is the last reference - /// - virtual void ReleaseReference() const noexcept = 0; - }; -} diff --git a/Source/Opal/Memory/Reference.h b/Source/Opal/Memory/Reference.h deleted file mode 100644 index b354c8fb..00000000 --- a/Source/Opal/Memory/Reference.h +++ /dev/null @@ -1,131 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// -#pragma once -#include "IReferenceCounted.h" - -namespace Opal::Memory -{ - /// - /// A basic reference counted smart pointer. - /// - export template - class Reference - { - public: - /// - /// Default initializer with null pointer - /// - Reference() noexcept : - _reference(nullptr) - { - } - - /// - /// Special initializer that allows for creation with null pointer - /// - Reference(std::nullptr_t) noexcept : - _reference(nullptr) - { - } - - /// - /// Initializer that takes in a raw pointer. - /// - Reference(T* reference) noexcept : - _reference(nullptr) - { - Assign(reference); - } - - /// - /// Initializes a copy instance of the Reference class - /// - Reference(const Reference& reference) noexcept : - _reference(nullptr) - { - Assign(reference._reference); - } - - /// - /// Assignment operator - /// - Reference& operator=(const Reference& reference) noexcept - { - Assign(reference._reference); - return *this; - } - - /// - /// Finalize an instance of the Reference class - /// - ~Reference() noexcept - { - Assign(nullptr); - } - - /// - /// Pointer operator overloads - /// - operator T*() noexcept - { - return _reference; - } - - operator const T*() const noexcept - { - return _reference; - } - - T* operator->() noexcept - { - return _reference; - } - - const T* operator->() const noexcept - { - return _reference; - } - - template - bool operator==(const Reference& rhs) noexcept - { - return GetRaw() == rhs.GetRaw(); - } - - /// - /// Get the raw pointer value - /// - T* GetRaw() noexcept - { - return _reference; - } - - private: - /// - /// Assign the reference to a new value - /// - inline void Assign(T* reference) noexcept - { - // Add an initial reference to the incoming pointer to ensure we never assign - // a pointer that has been lost - if (reference != nullptr) - { - reference->AddReference(); - } - - // Move out the old reference and replace it with the new - auto previousReference = _reference; - _reference = reference; - - // Release the old reference if it was valid - if (previousReference != nullptr) - { - previousReference->ReleaseReference(); - } - } - - private: - T* _reference; - }; -} diff --git a/Source/Opal/Memory/ReferenceCounted.h b/Source/Opal/Memory/ReferenceCounted.h deleted file mode 100644 index 7a828e9e..00000000 --- a/Source/Opal/Memory/ReferenceCounted.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// -#pragma once -#include "IReferenceCounted.h" - -namespace Opal::Memory -{ - /// - /// The shared implementation of a thread safe reference counted object - /// - export template - class ReferenceCounted : public T - { - protected: - /// - /// Initializes a new instance of the ReferenceCounted class - /// Note: Protected to only allow inherited use - /// - ReferenceCounted() noexcept : - _referenceCount(0) - { - } - - /// - /// Initializes a copy instance of the ReferenceCounted class - /// Note: Protected to only allow inherited use - /// and forces the reference count back to zero. - /// - ReferenceCounted(const ReferenceCounted&) noexcept : - _referenceCount(0) - { - } - - /// - /// Assignment operator - /// - ReferenceCounted& operator=(const ReferenceCounted&) noexcept - { - return *this; - } - - /// - /// Finalizes an instance of ReferenceCounted class - /// - virtual ~ReferenceCounted() noexcept - { - } - - public: - /// - /// Adds a reference to the object - /// - void AddReference() const noexcept override final - { - _referenceCount++; - } - - /// - /// Releases a reference to the object and destructs if this is the last reference - /// - void ReleaseReference() const noexcept override final - { - auto currentCount = --_referenceCount; - if (currentCount == 0) - { - delete this; - } - else if (currentCount < 0) - { - std::abort(); - } - } - - private: - mutable std::atomic _referenceCount; - }; -} diff --git a/Source/Opal/Module.cpp b/Source/Opal/Module.cpp deleted file mode 100644 index db2dc5d2..00000000 --- a/Source/Opal/Module.cpp +++ /dev/null @@ -1,59 +0,0 @@ -module; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif - -export module Opal; - -import HttpLib; - -#include "Core/Path.h" -#include "Core/SemanticVersion.h" - -#include "IO/SystemConsoleManager.h" -#include "IO/MockConsoleManager.h" -#include "IO/ScopedConsoleManagerRegister.h" - -#include "Logger/Log.h" -#include "Logger/ConsoleTraceListener.h" -#include "Logger/ScopedTraceListenerRegister.h" -#include "Logger/TestTraceListener.h" - -#include "Memory/IReferenceCounted.h" -#include "Memory/Reference.h" -#include "Memory/ReferenceCounted.h" - -#include "Network/HttpLibNetworkManager.h" -#include "Network/MockNetworkManager.h" -#include "Network/ScopedNetworkManagerRegister.h" - -#include "System/SmartHandle.h" -#include "System/DynamicLibraryManager.h" -#include "System/ProcessManager.h" -#include "System/MockEnvironment.h" -#include "System/MockFileSystem.h" -#include "System/MockProcessManager.h" -#include "System/PlatformProcessManager.h" -#include "System/ScopedFileSystemRegister.h" -#include "System/ScopedProcessManagerRegister.h" -#include "System/STLEnvironment.h" -#include "System/STLFileSystem.h" diff --git a/Source/Opal/Network/TLSClient.h b/Source/Opal/Network/TLSClient.h deleted file mode 100644 index 7c1e9433..00000000 --- a/Source/Opal/Network/TLSClient.h +++ /dev/null @@ -1,362 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -#include "BasicCredentialsManager.h" - -namespace Opal::Network -{ - typedef SOCKET socket_type; - - inline socket_type invalid_socket() { return INVALID_SOCKET; } - - inline int close(int fd) - { - return ::closesocket(fd); - } - - inline int send(int s, const uint8_t* buf, size_t len, int flags) - { - return ::send(s, reinterpret_cast(buf), static_cast(len), flags); - } - - inline int read(int s, void* buf, size_t len) - { - return ::recv(s, reinterpret_cast(buf), static_cast(len), 0); - } - - class TLSClient final : public Botan::TLS::Callbacks - { - public: - TLSClient() - { - // TODO init_sockets(); - } - - ~TLSClient() - { - // TODO stop_sockets(); - } - - void DoIt() - { - // TODO client cert auth - const std::string host = "www.soupbuild.com"; - const uint16_t port = 443; - const std::string transport = "tcp"; - const std::string next_protos = ""; - const bool use_system_cert_store = true; - const std::string trusted_CAs = ""; - - auto session_mgr = std::make_unique(rng()); - - auto policy = std::make_unique(); - - const bool use_tcp = (transport == "tcp"); - - const std::vector protocols_to_offer = Botan::split_on(next_protos, ','); - - Botan::TLS::Protocol_Version version = Botan::TLS::Protocol_Version::TLS_V12; - - if (policy->acceptable_protocol_version(version) == false) - { - throw std::runtime_error("The policy specified does not allow the requested TLS version"); - } - - struct sockaddr_storage addrbuf; - std::string hostname; - if(!host.empty() && - inet_pton(AF_INET, host.c_str(), &addrbuf) != 1 && - inet_pton(AF_INET6, host.c_str(), &addrbuf) != 1) - { - hostname = host; - } - - m_sockfd = connect_to_host(host, port, use_tcp); - - BasicCredentialsManager creds(use_system_cert_store, trusted_CAs); - - Botan::TLS::Client client( - *this, - *session_mgr, - creds, - *policy, - rng(), - Botan::TLS::Server_Information(hostname, port), - version, - protocols_to_offer); - - bool first_active = true; - - while (!client.is_closed()) - { - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(m_sockfd, &readfds); - - if(client.is_active()) - { - // FD_SET(STDIN_FILENO, &readfds); - if(first_active && !protocols_to_offer.empty()) - { - std::string app = client.application_protocol(); - if(app != "") - { - Log::HighPriority("Server choose protocol: " + client.application_protocol()); - } - - first_active = false; - } - } - - struct timeval timeout = { 1, 0 }; - - ::select(static_cast(m_sockfd + 1), &readfds, nullptr, nullptr, &timeout); - - if(FD_ISSET(m_sockfd, &readfds)) - { - uint8_t buf[4 * 1024] = { 0 }; - - auto got = read(m_sockfd, buf, sizeof(buf)); - - if (got == 0) - { - Log::HighPriority("EOF on socket"); - break; - } - else if (got == -1) - { - Log::HighPriority("Socket error: " + std::to_string(errno)); - continue; - } - - client.received_data(buf, got); - } - - // if (FD_ISSET(STDIN_FILENO, &readfds)) - // { - // uint8_t buf[1024] = { 0 }; - // ssize_t got = read(STDIN_FILENO, buf, sizeof(buf)); - - // if (got == 0) - // { - // Log::HighPriority("EOF on stdin"); - // client.close(); - // break; - // } - // else if (got == -1) - // { - // Log::HighPriority("Stdin error: " + errno + " " + err_to_string(errno)); - // continue; - // } - - // if(got == 2 && buf[1] == '\n') - // { - // char cmd = buf[0]; - - // if(cmd == 'R' || cmd == 'r') - // { - // Log::HighPriority("Client initiated renegotiation"); - // client.renegotiate(cmd == 'R'); - // } - // else if(cmd == 'Q') - // { - // Log::HighPriority("Client initiated close"); - // client.close(); - // } - // } - // else - // { - // client.send(buf, got); - // } - // } - - if (client.timeout_check()) - { - Log::HighPriority("Timeout detected"); - } - } - - close(m_sockfd); - } - - private: - Botan::RandomNumberGenerator& rng() - { - if (m_rng == nullptr) - { - m_rng = std::make_unique(); - } - - return *m_rng.get(); - } - - socket_type connect_to_host(const std::string& host, uint16_t port, bool tcp) - { - addrinfo hints; - Botan::clear_mem(&hints, 1); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = tcp ? SOCK_STREAM : SOCK_DGRAM; - addrinfo* res, *rp = nullptr; - - if (::getaddrinfo(host.c_str(), std::to_string(port).c_str(), &hints, &res) != 0) - { - throw std::runtime_error("getaddrinfo failed for " + host); - } - - socket_type fd = 0; - - for (rp = res; rp != nullptr; rp = rp->ai_next) - { - fd = ::socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - - if (fd == invalid_socket()) - { - continue; - } - - if (::connect(fd, rp->ai_addr, static_cast(rp->ai_addrlen)) != 0) - { - close(fd); - continue; - } - - break; - } - - ::freeaddrinfo(res); - - if (rp == nullptr) // no address succeeded - { - throw std::runtime_error("connect failed"); - } - - return fd; - } - - void tls_verify_cert_chain( - const std::vector& cert_chain, - const std::vector>& ocsp, - const std::vector& trusted_roots, - Botan::Usage_Type usage, - const std::string& hostname, - const Botan::TLS::Policy& policy) override - { - if (cert_chain.empty()) - { - throw Botan::Invalid_Argument("Certificate chain was empty"); - } - - Botan::Path_Validation_Restrictions restrictions( - false, // TODO: policy.require_cert_revocation_info(), - policy.minimum_signature_strength()); - - auto ocsp_timeout = std::chrono::milliseconds(1000); - - Botan::Path_Validation_Result result = Botan::x509_path_validate( - cert_chain, - restrictions, - trusted_roots, - hostname, - usage, - std::chrono::system_clock::now(), - ocsp_timeout, - ocsp); - - Log::HighPriority("Certificate validation status: " + result.result_string()); - if (result.successful_validation()) - { - auto status = result.all_statuses(); - - if (status.size() > 0 && status[0].count(Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD)) - { - Log::HighPriority("Valid OCSP response for this server"); - } - } - } - - bool tls_session_established(const Botan::TLS::Session& session) override - { - Log::HighPriority("Handshake complete, " + session.version().to_string() - + " using " + session.ciphersuite().to_string()); - - // if (!session.session_id().empty()) - // { - // output() << "Session ID " << Botan::hex_encode(session.session_id()) << "\n"; - // } - - // if (!session.session_ticket().empty()) - // { - // output() << "Session ticket " << Botan::hex_encode(session.session_ticket()) << "\n"; - // } - - // if (flag_set("print-certs")) - // { - // const std::vector& certs = session.peer_certs(); - - // for (size_t i = 0; i != certs.size(); ++i) - // { - // output() << "Certificate " << i + 1 << "/" << certs.size() << "\n"; - // output() << certs[i].to_string(); - // output() << certs[i].PEM_encode(); - // } - // } - - return true; - } - - // static void dgram_socket_write(int sockfd, const uint8_t buf[], size_t length) - // { - // int r = ::send(sockfd, buf, length, MSG_NOSIGNAL); - - // if (r == -1) - // { - // throw CLI_Error("Socket write failed errno=" + std::to_string(errno)); - // } - // } - - void tls_emit_data(const uint8_t buf[], size_t length) override - { - size_t offset = 0; - - while (length) - { - ssize_t sent = send(m_sockfd, buf + offset, length, 0); - - if (sent == -1) - { - if (errno == EINTR) - { - sent = 0; - } - else - { - throw std::runtime_error("Socket write failed errno=" + std::to_string(errno)); - } - } - - offset += sent; - length -= sent; - } - } - - void tls_alert(Botan::TLS::Alert alert) override - { - Log::Error("Alert: " + alert.type_string()); - } - - void tls_record_received(uint64_t /*seq_no*/, const uint8_t buf[], size_t buf_size) override - { - for (size_t i = 0; i != buf_size; ++i) - { - // output() << buf[i]; - } - } - - private: - std::unique_ptr m_rng; - socket_type m_sockfd = invalid_socket(); - }; -} diff --git a/Source/Opal/Recipe.toml b/Source/Opal/Recipe.toml deleted file mode 100644 index 5339529b..00000000 --- a/Source/Opal/Recipe.toml +++ /dev/null @@ -1,7 +0,0 @@ -Name = "Opal" -Version = "0.1.0" -Public = "Module.cpp" - -Dependencies = [ - "../../Dependencies/cpp-httplib/", -] \ No newline at end of file diff --git a/Source/Opal/System/DynamicLibraryManager.h b/Source/Opal/System/DynamicLibraryManager.h deleted file mode 100644 index 8fd63e3d..00000000 --- a/Source/Opal/System/DynamicLibraryManager.h +++ /dev/null @@ -1,121 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Opal::System -{ - /// - /// A platform specific dynamic library manager - /// - export class Library - { - public: - Library(HINSTANCE handle) : - _handle(handle) - { - } - - Library(Library&& other) : - _handle(std::move(other._handle)) - { - other._handle = nullptr; - } - - Library(Library& other) = delete; - - ~Library() - { - // Free the DLL module. - if (_handle != nullptr) - { - auto result = FreeLibrary(_handle); - // Ignore failures - _handle = nullptr; - } - } - - typedef void (*StringCallback)(const char*); - - void EnumerateDLLFunctions(StringCallback callback) - { - // If the handle is valid, try to get the function address. - if (_handle == nullptr) - throw "ERROR Failed to get library handle"; - - auto header = (PIMAGE_NT_HEADERS)((BYTE*)_handle + ((PIMAGE_DOS_HEADER)_handle)->e_lfanew); - if (header->Signature != IMAGE_NT_SIGNATURE) - throw "Signature is not IMAGE_NT_SIGNATURE"; - if (header->OptionalHeader.NumberOfRvaAndSizes == 0) - throw "No Rva and sizes"; - - auto exports = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)_handle + - header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); - if (exports->AddressOfNames == 0) - throw "AddressOfNames is null"; - - auto names = (BYTE**)((size_t)_handle + exports->AddressOfNames); - for (int i = 0; i < exports->NumberOfNames; i++) - callback((char*)_handle + (size_t)names[i]); - } - - /// - /// Get a function by name and casted to the requested type - /// - void* GetFunction(const char* name) - { - // If the handle is valid, try to get the function address. - if (_handle == nullptr) - throw "ERROR Failed to get library handle"; - - auto processAddress = GetProcAddress(_handle, name); - - // Verify the address is valid - if (processAddress == nullptr) - throw GetLastError(); - - return (void*)processAddress; - } - - /// - /// Get a function by name and casted to the requested type - /// - template - T GetFunction(const char* name) - { - auto typeProcessAddress = (T)GetFunction(name); - - // Verify the type matches - if (typeProcessAddress == nullptr) - throw "Failed to cast finction address."; - - return typeProcessAddress; - } - - private: - HINSTANCE _handle; - }; - - /// - /// A platform specific dynamic library manager - /// - export class DynamicLibraryManager - { - public: - static Library LoadDynamicLibrary(const char* libraryName) - { - // Get a handle to the DLL module. - auto libraryHandle = ::LoadLibrary(TEXT(libraryName)); - - // If the handle is valid, try to get the function address. - if (libraryHandle == nullptr) - { - auto lastError = GetLastError(); - throw "ERROR Failed to get library handle"; - } - - return Library(libraryHandle); - } - }; -} diff --git a/Source/Opal/System/IEnvironment.h b/Source/Opal/System/IEnvironment.h deleted file mode 100644 index 7bb21b3c..00000000 --- a/Source/Opal/System/IEnvironment.h +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Opal::System -{ - /// - /// The environment interface - /// Interface mainly used to allow for unit testing client code - /// - export class IEnvironment - { - public: - /// - /// Gets the current active environments - /// - static IEnvironment& Current() - { - if (_current == nullptr) - throw std::runtime_error("No environment implementation registered."); - return *_current; - } - - /// - /// Register a new active process manager - /// - static void Register(std::shared_ptr value) - { - _current = std::move(value); - } - - public: - /// - /// Gets the value of an environment variable - /// - virtual std::string GetEnvironmentVariable(std::string_view name) = 0; - - private: - static std::shared_ptr _current; - }; - - std::shared_ptr IEnvironment::_current = nullptr; -} diff --git a/Source/Opal/System/IFile.h b/Source/Opal/System/IFile.h deleted file mode 100644 index 0763f2df..00000000 --- a/Source/Opal/System/IFile.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Opal::System -{ - /// - /// The file interface - /// Interface mainly used to allow for unit testing client code - /// - export class IFile - { - public: - /// - /// Close the file - /// - virtual void Close() = 0; - }; -} diff --git a/Source/Opal/System/IFileSystem.h b/Source/Opal/System/IFileSystem.h deleted file mode 100644 index 9a64f71e..00000000 --- a/Source/Opal/System/IFileSystem.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IInputFile.h" -#include "IOutputFile.h" - -namespace Opal::System -{ - export struct DirectoryEntry - { - Path Path; - bool IsDirectory; - }; - - /// - /// The file system interface - /// Interface mainly used to allow for unit testing client code - /// - export class IFileSystem - { - public: - /// - /// Gets the current active file system - /// - static IFileSystem& Current() - { - if (_current == nullptr) - throw std::runtime_error("No file system implementation registered."); - return *_current; - } - - /// - /// Register a new active file system - /// - static void Register(std::shared_ptr fileSystem) - { - _current = std::move(fileSystem); - } - - public: - /// - /// Gets the current user profile directory - /// - virtual Path GetUserProfileDirectory() = 0; - - /// - /// Gets the current directory for the running processes - /// - virtual Path GetCurrentDirectory2() = 0; - - /// - /// Gets a value indicating whether the directory/file exists - /// - virtual bool Exists(const Path& path) = 0; - - /// - /// Get the last write time of the file/directory - /// TODO: This should be a better representation of datetime... - /// - virtual std::time_t GetLastWriteTime(const Path& path) = 0; - - /// - /// Set the last write time of the file/directory - /// TODO: This should be a better representation of datetime... - /// - virtual void SetLastWriteTime(const Path& path, std::time_t value) = 0; - - /// - /// Open the requested file as a stream to read - /// - virtual std::shared_ptr OpenRead(const Path& path, bool isBinary) = 0; - - /// - /// Open the requested file as a stream to write - /// - virtual std::shared_ptr OpenWrite(const Path& path, bool isBinary) = 0; - - /// - /// Rename the source file to the destination - /// - virtual void Rename(const Path& source, const Path& destination) = 0; - - /// - /// Copy the source file to the destination - /// - virtual void CopyFile2(const Path& source, const Path& destination) = 0; - - /// - /// Create the directory at the requested path - /// - virtual void CreateDirectory2(const Path& path) = 0; - - /// - /// Get the children of a directory - /// - virtual std::vector GetDirectoryChildren(const Path& path) = 0; - - /// - /// Delete the directory - /// - virtual void DeleteDirectory(const Path& path, bool recursive) = 0; - - private: - static std::shared_ptr _current; - }; - - std::shared_ptr IFileSystem::_current = nullptr; -} diff --git a/Source/Opal/System/IInputFile.h b/Source/Opal/System/IInputFile.h deleted file mode 100644 index a9c167e1..00000000 --- a/Source/Opal/System/IInputFile.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IFile.h" - -namespace Opal::System -{ - /// - /// The input file interface - /// Interface mainly used to allow for unit testing client code - /// - export class IInputFile : virtual public IFile - { - public: - /// - /// Gets the input stream - /// - virtual std::istream& GetInStream() = 0; - }; -} diff --git a/Source/Opal/System/IOutputFile.h b/Source/Opal/System/IOutputFile.h deleted file mode 100644 index 50c597e7..00000000 --- a/Source/Opal/System/IOutputFile.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IFile.h" - -namespace Opal::System -{ - /// - /// The output file interface - /// Interface mainly used to allow for unit testing client code - /// - export class IOutputFile : virtual public IFile - { - public: - /// - /// Gets the output stream - /// - virtual std::ostream& GetOutStream() = 0; - }; -} diff --git a/Source/Opal/System/IProcessManager.h b/Source/Opal/System/IProcessManager.h deleted file mode 100644 index 6dfd2199..00000000 --- a/Source/Opal/System/IProcessManager.h +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Opal::System -{ - export struct ProcessResult - { - int ExitCode; - std::string StdOut; - std::string StdErr; - }; - - /// - /// The process manager interface - /// Interface mainly used to allow for unit testing client code - /// - export class IProcessManager - { - public: - /// - /// Gets the current active process manager - /// - static IProcessManager& Current() - { - if (_current == nullptr) - throw std::runtime_error("No process manager implementation registered."); - return *_current; - } - - /// - /// Register a new active process manager - /// - static void Register(std::shared_ptr value) - { - _current = std::move(value); - } - - public: - /// - /// Gets the process file name - /// - virtual Path GetProcessFileName() = 0; - - /// - /// Creates a process for the provided executable path - /// - virtual ProcessResult Execute( - const Path& application, - const std::string& arguments, - const Path& workingDirectory) = 0; - - private: - static std::shared_ptr _current; - }; - - std::shared_ptr IProcessManager::_current = nullptr; -} diff --git a/Source/Opal/System/MockEnvironment.h b/Source/Opal/System/MockEnvironment.h deleted file mode 100644 index 12ee234c..00000000 --- a/Source/Opal/System/MockEnvironment.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IEnvironment.h" - -namespace Opal::System -{ - /// - /// The mock environment - /// TODO: Move into test project - /// - export class MockEnvironment : public IEnvironment - { - public: - /// - /// Initializes a new instance of the class. - /// - MockEnvironment() : - _requests() - { - } - - /// - /// Get the load requests - /// - const std::vector& GetRequests() const - { - return _requests; - } - - /// - /// Gets the value of an environment variable - /// - std::string GetEnvironmentVariable(std::string_view name) override final - { - std::stringstream message; - message << "GetEnvironmentVariable: " << name; - - _requests.push_back(message.str()); - return "value"; - } - - private: - std::vector _requests; - }; -} diff --git a/Source/Opal/System/MockFile.h b/Source/Opal/System/MockFile.h deleted file mode 100644 index 6ca6196a..00000000 --- a/Source/Opal/System/MockFile.h +++ /dev/null @@ -1,96 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IFileSystem.h" - -namespace Opal::System -{ - export class MockFile - { - public: - MockFile(std::stringstream content, std::time_t lastWriteTime) : - Content(std::move(content)), - LastWriteTime(lastWriteTime) - { - } - - MockFile(std::stringstream content) : - Content(std::move(content)), - LastWriteTime() - { - } - - MockFile(std::time_t lastWriteTime) : - Content(), - LastWriteTime(lastWriteTime) - { - } - - MockFile() : - Content(), - LastWriteTime() - { - } - - std::stringstream Content; - std::time_t LastWriteTime; - }; - - class MockOutputFile : public IOutputFile - { - public: - MockOutputFile(std::shared_ptr file) : - _file(std::move(file)) - { - } - - /// - /// Gets the file stream - /// - std::ostream& GetOutStream() override final - { - return _file->Content; - } - - /// - /// Close the file stream - /// - void Close() override final - { - // Ignore for now - } - - private: - std::shared_ptr _file; - }; - - class MockInputFile : public IInputFile - { - public: - MockInputFile(std::shared_ptr file) : - _file(std::move(file)) - { - } - - /// - /// Gets the file stream - /// - std::istream& GetInStream() override final - { - return _file->Content; - } - - /// - /// Close the file stream - /// - void Close() override final - { - // Ignore for now - } - - private: - std::shared_ptr _file; - }; -} diff --git a/Source/Opal/System/MockFileSystem.h b/Source/Opal/System/MockFileSystem.h deleted file mode 100644 index 5b84892d..00000000 --- a/Source/Opal/System/MockFileSystem.h +++ /dev/null @@ -1,252 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IFileSystem.h" -#include "MockFile.h" - -namespace Opal::System -{ - /// - /// The mock file system - /// TODO: Move into test project - /// - export class MockFileSystem : public IFileSystem - { - public: - /// - /// Initializes a new instance of the class. - /// - MockFileSystem() : - _requests(), - _files() - { - } - - /// - /// Get the load requests - /// - const std::vector& GetRequests() const - { - return _requests; - } - - /// - /// Create a test file - /// - void CreateMockFile(Path path, std::shared_ptr file) - { - _files.emplace( - std::move(path), - std::move(file)); - } - - /// - /// Create a test file - /// - std::shared_ptr GetMockFile(Path path) - { - auto file = _files.find(path); - if (file != _files.end()) - { - return file->second; - } - else - { - auto message = "Cannot find file: " + path.ToString(); - throw std::runtime_error(message); - } - } - - /// - /// Gets the current user profile directory - /// - Path GetUserProfileDirectory() override final - { - _requests.push_back("GetCurrentDirectory"); - - return Path("C:/Users/Me/"); - } - - /// - /// Gets the current directory for the running processes - /// - Path GetCurrentDirectory2() override final - { - _requests.push_back("GetCurrentDirectory"); - - return Path("C:/Current/"); - } - - /// - /// Gets a value indicating whether the directory/file exists - /// - bool Exists(const Path& path) override final - { - std::stringstream message; - message << "Exists: " << path.ToString(); - _requests.push_back(message.str()); - - auto file = _files.find(path); - return file != _files.end(); - } - - /// - /// Get the last write time of the file/directory - /// - std::time_t GetLastWriteTime(const Path& path) override final - { - std::stringstream message; - message << "GetLastWriteTime: " << path.ToString(); - _requests.push_back(message.str()); - - auto file = _files.find(path); - if (file != _files.end()) - { - return file->second->LastWriteTime; - } - else - { - auto message = "Cannot find file for last write time: " + path.ToString(); - throw std::runtime_error(message); - } - } - - /// - /// Set the last write time of the file/directory - /// - void SetLastWriteTime(const Path& path, std::time_t value) override final - { - std::stringstream message; - message << "SetLastWriteTime: " << path.ToString(); - _requests.push_back(message.str()); - } - - /// - /// Open the requested file as a stream to read - /// - std::shared_ptr OpenRead(const Path& path, bool isBinary) override final - { - std::stringstream message; - if (isBinary) - { - message << "OpenReadBinary: " << path.ToString(); - } - else - { - message << "OpenRead: " << path.ToString(); - } - _requests.push_back(message.str()); - - auto file = _files.find(path); - if (file != _files.end()) - { - // Reset the existing content offset and return it. - auto& content = file->second->Content; - content.seekg(0); - return std::make_shared(file->second); - } - else - { - auto message = "Cannot open read: " + path.ToString(); - throw std::runtime_error(message); - } - } - - /// - /// Open the requested file as a stream to write - /// - std::shared_ptr OpenWrite(const Path& path, bool isBinary) override final - { - std::stringstream message; - if (isBinary) - { - message << "OpenWriteBinary: " << path.ToString(); - } - else - { - message << "OpenWrite: " << path.ToString(); - } - _requests.push_back(message.str()); - - auto file = _files.find(path); - if (file != _files.end()) - { - // Reset the existing content offset and return it. - auto& content = file->second->Content; - content.str(""); - content.clear(); - return std::make_shared(file->second); - } - else - { - // Create the file if it does not exist - auto insert = _files.emplace(path, std::make_shared()); - return std::make_shared(insert.first->second); - } - } - - /// - /// Rename the source file to the destination - /// - virtual void Rename(const Path& source, const Path& destination) override final - { - std::stringstream message; - message << "Rename: [" << source.ToString() << "] -> [" << destination.ToString() << "]"; - _requests.push_back(message.str()); - } - - /// - /// Copy the source file to the destination - /// - void CopyFile2(const Path& source, const Path& destination) override final - { - std::stringstream message; - message << "CopyFile: [" << source.ToString() << "] -> [" << destination.ToString() << "]"; - _requests.push_back(message.str()); - } - - /// - /// Create the directory at the requested path - /// - void CreateDirectory2(const Path& path) override final - { - std::stringstream message; - message << "CreateDirectory: " << path.ToString(); - _requests.push_back(message.str()); - } - - /// - /// Get the children of a directory - /// - std::vector GetDirectoryChildren(const Path& path) override final - { - std::stringstream message; - message << "GetDirectoryChildren: " << path.ToString(); - _requests.push_back(message.str()); - - auto result = std::vector(); - return result; - } - - /// - /// Delete the directory - /// - void DeleteDirectory(const Path& path, bool recursive) override final - { - std::stringstream message; - if (recursive) - message << "DeleteDirectoryRecursive: "; - else - message << "DeleteDirectory: "; - - message << path.ToString(); - _requests.push_back(message.str()); - } - - private: - std::vector _requests; - std::map> _files; - }; -} diff --git a/Source/Opal/System/MockProcessManager.h b/Source/Opal/System/MockProcessManager.h deleted file mode 100644 index 9c15eaf4..00000000 --- a/Source/Opal/System/MockProcessManager.h +++ /dev/null @@ -1,105 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IProcessManager.h" - -namespace Opal::System -{ - /// - /// The mock process manager - /// TODO: Move into test project - /// - export class MockProcessManager : public IProcessManager - { - public: - /// - /// Initializes a new instance of the class. - /// - MockProcessManager() : - _requests(), - _processFileName(Path("C:/testlocation/SoupCMDTest.exe")), - _executeResults() - { - } - - /// - /// Initializes a new instance of the class. - /// - MockProcessManager(Path processFileName) : - _requests(), - _processFileName(std::move(processFileName)), - _executeResults() - { - } - - /// - /// Create a result - /// - void RegisterExecuteResult(std::string command, std::string output) - { - _executeResults.emplace( - std::move(command), - std::move(output)); - } - - /// - /// Get the load requests - /// - const std::vector& GetRequests() const - { - return _requests; - } - - /// - /// Gets the process file name - /// - Path GetProcessFileName() override final - { - std::stringstream message; - message << "GetProcessFileName"; - - _requests.push_back(message.str()); - return _processFileName; - } - - /// - /// Creates a process for the provided executable path - /// - ProcessResult Execute( - const Path& application, - const std::string& arguments, - const Path& workingDirectory) override final - { - std::stringstream message; - message << "Execute: [" << workingDirectory.ToString() << "] " << application.ToString() << " " << arguments; - - _requests.push_back(message.str()); - - // Check if there is a registered output - auto findOutput = _executeResults.find(message.str()); - if (findOutput != _executeResults.end()) - { - return { - 0, - findOutput->second, - std::string(), - }; - } - else - { - return { - 0, - std::string(), - std::string(), - }; - } - } - - private: - std::vector _requests; - Path _processFileName; - std::map _executeResults; - }; -} diff --git a/Source/Opal/System/PlatformProcessManager.h b/Source/Opal/System/PlatformProcessManager.h deleted file mode 100644 index a759e1f1..00000000 --- a/Source/Opal/System/PlatformProcessManager.h +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IProcessManager.h" -#include "ProcessManager.h" - -namespace Opal::System -{ - /// - /// A platform specific process executable using system - /// - export class PlatformProcessManager : public IProcessManager - { - public: - /// - /// Initializes a new instance of the class. - /// - PlatformProcessManager() - { - } - - /// - /// Gets the process file name - /// - Path GetProcessFileName() override final - { - try - { - auto buffer = std::array(); - ProcessManager::GetProcessFileName(buffer.data(), buffer.size()); - return Path(std::string(buffer.data(), buffer.size())); - } - catch (unsigned long error) - { - // Convert raw error into a std exception - throw std::runtime_error("GetProcessFileName Failed: " + std::to_string(error)); - } - catch (const char* message) - { - // Convert raw message into a std exception - throw std::runtime_error(message); - } - } - - /// - /// Creates a process for the provided executable path - /// - ProcessResult Execute( - const Path& application, - const std::string& arguments, - const Path& workingDirectory) override final - { - std::stringstream argumentsValue; - argumentsValue << "\"" << application.ToAlternateString() << "\"" << " " << arguments; - - std::string argumentsString = argumentsValue.str(); - - // Aggregate all the output - std::stringstream stdOut; - std::stringstream stdErr; - - // Convert to c style since we do not have access to stdlib in this helper - // TODO: Remove crazyness when we get a good implementation of modules - auto outputCallback = [](void* context, const char* value, int length) - { - auto& stdOut = *reinterpret_cast(context); - stdOut << value; - }; - auto errorCallback = [](void* context, const char* value, int length) - { - auto& stdErr = *reinterpret_cast(context); - stdErr << value; - }; - - int exitCode = ProcessManager::Execute( - application.ToString().c_str(), - const_cast(argumentsString.c_str()), - workingDirectory.ToString().c_str(), - outputCallback, - &stdOut, - errorCallback, - &stdErr); - - return { - exitCode, - stdOut.str(), - stdErr.str(), - }; - } - }; -} diff --git a/Source/Opal/System/ProcessManager.h b/Source/Opal/System/ProcessManager.h deleted file mode 100644 index 20612bf8..00000000 --- a/Source/Opal/System/ProcessManager.h +++ /dev/null @@ -1,174 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Opal::System -{ - /// - /// A platform specific process executable using system - /// - export class ProcessManager - { - public: - typedef void OutputCallBackFunction(void* context, const char*, int); - - static void GetProcessFileName(char* buffer, int length) - { - // Pass in null handle to get current process information - auto handle = nullptr; - auto sizeRead = GetModuleFileNameA( - handle, - buffer, - length); - if (sizeRead == 0) - { - throw GetLastError(); - } - else if (sizeRead == length) - { - // Note: This may have perfectly fit, but we are being lazy - throw "Ran out of room in the buffer"; - } - } - - /// - /// Creates a process for the provided executable path - /// - static int Execute( - const char* application, - char* arguments, - const char* workingDirectory, - OutputCallBackFunction stdOutputCallback, - void* stdOutputContext, - OutputCallBackFunction stdErrorCallback, - void* stdErrorContext) - { - // Setup the input/output streams - - // TODO: We need to read from the buffer to ensure it doesn't deadlock on the wait forever - int pipeBufferSize = 5 * 1024 * 1024; - - // Set the bInheritHandle flag so pipe handles are inherited. - SECURITY_ATTRIBUTES securityAttributes; - securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); - securityAttributes.bInheritHandle = true; - securityAttributes.lpSecurityDescriptor = nullptr; - - // Create a pipe for the child process's STDOUT. - SmartHandle childStdOutRead; - SmartHandle childStdOutWrite; - if (!CreatePipe(&childStdOutRead._handle, &childStdOutWrite._handle, &securityAttributes, pipeBufferSize)) - return -1; - - // Ensure the read handle to the pipe for STDOUT is not inherited. - if (!SetHandleInformation(childStdOutRead._handle, HANDLE_FLAG_INHERIT, 0)) - return -1; - - // Create a pipe for the child process's STDERR. - SmartHandle childStdErrRead; - SmartHandle childStdErrWrite; - if (!CreatePipe(&childStdErrRead._handle, &childStdErrWrite._handle, &securityAttributes, pipeBufferSize)) - return -1; - - // Ensure the read handle to the pipe for STDERR is not inherited. - if (!SetHandleInformation(childStdErrRead._handle, HANDLE_FLAG_INHERIT, 0)) - return -1; - - // Create a pipe for the child process's STDIN. - SmartHandle childStdInRead; - SmartHandle childStdInWrite; - if (!CreatePipe(&childStdInRead._handle, &childStdInWrite._handle, &securityAttributes, 0)) - return -1; - - // Ensure the write handle to the pipe for STDIN is not inherited. - if (!SetHandleInformation(childStdInWrite._handle, HANDLE_FLAG_INHERIT, 0)) - return -1; - - // Setup the process creation parameters - LPSECURITY_ATTRIBUTES processAttributes = nullptr; - LPSECURITY_ATTRIBUTES threadAttributes = nullptr; - bool inheritHandles = true; - DWORD creationFlags = 0; - void* environment = nullptr; - - STARTUPINFOA startupInfo = {}; - ZeroMemory(&startupInfo, sizeof(STARTUPINFOA)); - startupInfo.cb = sizeof(startupInfo); - startupInfo.hStdError = childStdErrWrite._handle; - startupInfo.hStdOutput = childStdOutWrite._handle; - startupInfo.hStdInput = childStdInRead._handle; - startupInfo.dwFlags |= STARTF_USESTDHANDLES; - - PROCESS_INFORMATION processInfo = {}; - ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION)); - - // Start the process - if (!CreateProcessA( - application, - arguments, - processAttributes, - threadAttributes, - inheritHandles, - creationFlags, - environment, - workingDirectory, - &startupInfo, - &processInfo)) - { - return GetLastError(); - } - - // Throw the process and thread handles into smart pointers to ensure they are cleaned up - auto processHandle = SmartHandle(processInfo.hProcess); - auto threadHandle = SmartHandle(processInfo.hThread); - - // Wait until child process exits. - WaitForSingleObject(processHandle._handle, INFINITE); - - // Get the exit code - DWORD exitCode; - if (!GetExitCodeProcess(processHandle._handle, &exitCode)) - return -1; - - // Close the child write handle to ensure we stop reading - childStdOutWrite.Close(); - childStdErrWrite.Close(); - - // Read all and write to stdout - // TODO: May want to switch over to a background thread with peak to read in order - DWORD dwRead = -1; - const int BufferSize = 256; - char buffer[BufferSize + 1]; - - // Read on output - while (true) - { - if(!ReadFile(childStdOutRead._handle, buffer, BufferSize, &dwRead, nullptr)) - break; - if (dwRead == 0) - break; - - // Make the string null terminated - buffer[dwRead] = '\0'; - stdOutputCallback(stdOutputContext, buffer, dwRead); - } - - // Read all errors - while (true) - { - if(!ReadFile(childStdErrRead._handle, buffer, BufferSize, &dwRead, nullptr)) - break; - if (dwRead == 0) - break; - - // Make the string null terminated - buffer[dwRead] = '\0'; - stdErrorCallback(stdErrorContext, buffer, dwRead); - } - - return exitCode; - } - }; -} diff --git a/Source/Opal/System/STLEnvironment.h b/Source/Opal/System/STLEnvironment.h deleted file mode 100644 index e796f695..00000000 --- a/Source/Opal/System/STLEnvironment.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IEnvironment.h" - -namespace Opal::System -{ - /// - /// The standard library file system - /// - export class STLEnvironment : public IEnvironment - { - public: - /// - /// Initializes a new instance of the class. - /// - STLEnvironment() - { - } - - /// - /// Gets the value of an environment variable - /// - std::string GetEnvironmentVariable(std::string_view name) override final - { - auto value = std::getenv(name.data()); - return value; - } - }; -} diff --git a/Source/Opal/System/STLFileSystem.h b/Source/Opal/System/STLFileSystem.h deleted file mode 100644 index 43565374..00000000 --- a/Source/Opal/System/STLFileSystem.h +++ /dev/null @@ -1,241 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IFileSystem.h" -#include "STLInputFile.h" -#include "STLOutputFile.h" - -namespace Opal::System -{ - /// - /// The standard library file system - /// - export class STLFileSystem : public IFileSystem - { - public: - /// - /// Initializes a new instance of the class. - /// - STLFileSystem() - { - } - - /// - /// Gets the current user profile directory - /// - Path GetUserProfileDirectory() override final - { - #ifdef _WIN32 - - char userProfile[MAX_PATH]; - HRESULT result = SHGetFolderPath( - nullptr, - CSIDL_PROFILE, - nullptr, - SHGFP_TYPE_CURRENT, - userProfile); - if (result != S_OK) - throw std::runtime_error("SHGetFolderPath failed."); - - return Path(userProfile); - - #else - #error NOT IMPLEMENTED - #endif - } - - /// - /// Gets the current directory for the running processes - /// - Path GetCurrentDirectory2() override final - { - auto current = std::filesystem::current_path(); - return Path(current.string()); - } - - /// - /// Gets a value indicating whether the directory/file exists - /// - bool Exists(const Path& path) override final - { - return std::filesystem::exists(path.ToString()); - } - - /// - /// Get the last write time of the file/directory - /// - std::time_t GetLastWriteTime(const Path& path) override final - { - // TODO: Remove when C++20 is ready - #if defined ( _WIN32 ) - struct _stat64 fileInfo; - if (_stat64(path.ToString().c_str(), &fileInfo) != 0) - throw std::runtime_error("Failed to get last write time."); - return fileInfo.st_mtime; - #else - auto fileTime = std::filesystem::last_write_time(path.ToString()); - auto systemTime = std::chrono::file_time::to_sys(fileTime); - auto time = std::chrono::system_time::clock::to_time_t(systemTime); - return time; - #endif - } - - /// - /// Set the last write time of the file/directory - /// - void SetLastWriteTime(const Path& path, std::time_t value) override final - { - // TODO: Remove when C++20 is ready - #if defined ( _WIN32 ) - // Open a handle on the file - auto fileHandle = CreateFile( - path.ToString().c_str(), - GENERIC_WRITE, - FILE_SHARE_READ, - nullptr, - OPEN_EXISTING, - 0, - nullptr); - - auto fileTime = TimetToFileTime(value); - - if (!SetFileTime( - fileHandle, - (LPFILETIME)nullptr, - (LPFILETIME)nullptr, - &fileTime)) - { - auto error = GetLastError(); - throw std::runtime_error("Failed to set file time: " + std::to_string(error)); - } - - if (!CloseHandle(fileHandle)) - { - auto error = GetLastError(); - throw std::runtime_error("Failed to close file handle: " + std::to_string(error)); - } - #else - auto systemTime = std::chrono::system_clock::from_time_t(value); - auto fileTime = std::chrono::file_time::from_sys(systemTime); - std::filesystem::last_write_time(path.ToString(), fileTime); - #endif - } - - /// - /// Open the requested file as a stream to read - /// - std::shared_ptr OpenRead(const Path& path, bool isBinary) override final - { - int mode = std::fstream::in; - if (isBinary) - { - mode = mode | std::fstream::binary; - } - - auto file = std::fstream(path.ToString(), mode); - if (file.fail()) - { - auto message = "OpenRead Failed: File missing. " + path.ToString(); - throw std::runtime_error(std::move(message)); - } - - return std::make_shared(std::move(file)); - } - - /// - /// Open the requested file as a stream to write - /// - std::shared_ptr OpenWrite(const Path& path, bool isBinary) override final - { - int mode = std::fstream::out; - if (isBinary) - { - mode = mode | std::fstream::binary; - } - - auto file = std::fstream(path.ToString(), mode); - if (file.fail()) - { - auto message = "OpenWrite Failed: " + path.ToString(); - throw std::runtime_error(std::move(message)); - } - - return std::make_shared(std::move(file)); - } - - /// - /// Rename the source file to the destination - /// - virtual void Rename(const Path& source, const Path& destination) override final - { - std::filesystem::rename( - source.ToString(), - destination.ToString()); - } - - /// - /// Copy the source file to the destination - /// - void CopyFile2(const Path& source, const Path& destination) override final - { - std::filesystem::copy( - source.ToString(), - destination.ToString(), - std::filesystem::copy_options::overwrite_existing); - } - - /// - /// Create the directory at the requested path - /// - void CreateDirectory2(const Path& path) override final - { - std::filesystem::create_directories(path.ToString()); - } - - /// - /// Get the children of a directory - /// - std::vector GetDirectoryChildren(const Path& path) override final - { - auto result = std::vector(); - for(auto& child : std::filesystem::directory_iterator(path.ToString())) - { - result.push_back( - { - Path(child.path().string()), - child.is_directory() - }); - } - - return result; - } - - /// - /// Delete the directory - /// - void DeleteDirectory(const Path& path, bool recursive) override final - { - if (recursive) - { - std::filesystem::remove_all(path.ToString()); - } - else - { - std::filesystem::remove(path.ToString()); - } - } - - private: - FILETIME TimetToFileTime(std::time_t time) - { - LONGLONG ll = Int32x32To64(time, 10000000) + 116444736000000000; - FILETIME result; - result.dwLowDateTime = (DWORD) ll; - result.dwHighDateTime = ll >>32; - - return result; - } - }; -} diff --git a/Source/Opal/System/STLInputFile.h b/Source/Opal/System/STLInputFile.h deleted file mode 100644 index 55316374..00000000 --- a/Source/Opal/System/STLInputFile.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IInputFile.h" - -namespace Opal::System -{ - - /// - /// The standard library input file implementation - /// - class STLInputFile : public IInputFile - { - public: - STLInputFile(std::fstream stream) : - _stream(std::move(stream)) - { - } - - /// - /// Gets the file stream - /// - std::istream& GetInStream() override final - { - return _stream; - } - - /// - /// Close the file stream - /// - void Close() override final - { - _stream.close(); - } - - private: - std::fstream _stream; - }; -} diff --git a/Source/Opal/System/STLOutputFile.h b/Source/Opal/System/STLOutputFile.h deleted file mode 100644 index 3ebc1ad9..00000000 --- a/Source/Opal/System/STLOutputFile.h +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IOutputFile.h" - -namespace Opal::System -{ - - /// - /// The standard library output file implementation - /// - class STLOutputFile : public IOutputFile - { - public: - STLOutputFile(std::fstream stream) : - _stream(std::move(stream)) - { - } - - /// - /// Get the file stream - /// - std::ostream& GetOutStream() override final - { - return _stream; - } - - /// - /// Close the file stream - /// - void Close() override final - { - _stream.close(); - } - - private: - std::fstream _stream; - }; -} diff --git a/Source/Opal/System/ScopedFileSystemRegister.h b/Source/Opal/System/ScopedFileSystemRegister.h deleted file mode 100644 index 91fe9c22..00000000 --- a/Source/Opal/System/ScopedFileSystemRegister.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IFileSystem.h" - -namespace Opal::System -{ - /// - /// A scopped file system registration helper - /// - export class ScopedFileSystemRegister - { - public: - /// - /// Initializes a new instance of the class. - /// - ScopedFileSystemRegister(std::shared_ptr listener) - { - IFileSystem::Register(std::move(listener)); - } - - /// - /// Finalizes an instance of the class. - /// - ~ScopedFileSystemRegister() - { - IFileSystem::Register(nullptr); - } - }; -} diff --git a/Source/Opal/System/ScopedProcessManagerRegister.h b/Source/Opal/System/ScopedProcessManagerRegister.h deleted file mode 100644 index fbba6531..00000000 --- a/Source/Opal/System/ScopedProcessManagerRegister.h +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once -#include "IProcessManager.h" - -namespace Opal::System -{ - /// - /// A scopped process manager registration helper - /// - export class ScopedProcessManagerRegister - { - public: - /// - /// Initializes a new instance of the class. - /// - ScopedProcessManagerRegister(std::shared_ptr listener) - { - IProcessManager::Register(std::move(listener)); - } - - /// - /// Finalizes an instance of the class. - /// - ~ScopedProcessManagerRegister() - { - IProcessManager::Register(nullptr); - } - }; -} diff --git a/Source/Opal/System/SmartHandle.h b/Source/Opal/System/SmartHandle.h deleted file mode 100644 index 2f8c32c7..00000000 --- a/Source/Opal/System/SmartHandle.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// Copyright (c) Soup. All rights reserved. -// - -#pragma once - -namespace Opal::System -{ - struct SmartHandle - { - SmartHandle(HANDLE handle) : - _handle(handle) - { - } - - SmartHandle() : - _handle(INVALID_HANDLE_VALUE) - { - } - - ~SmartHandle() - { - Close(); - } - - void Close() - { - if (_handle != INVALID_HANDLE_VALUE) - { - if (!CloseHandle(_handle)) - throw "TODO: Better error"; - _handle = INVALID_HANDLE_VALUE; - } - } - - HANDLE _handle; - }; -} diff --git a/Source/Parse/BitReader.cpp b/Source/Parse/BitReader.cpp deleted file mode 100644 index 71254e98..00000000 --- a/Source/Parse/BitReader.cpp +++ /dev/null @@ -1,172 +0,0 @@ - -#include "BitReader.h" - -using namespace Soup; - -BitReader::BitReader(std::istream& stream) : - m_stream(stream), - m_buffer(0), - m_bufferBitSize(0) -{ -} - -uint32_t BitReader::Read(size_t countBits) -{ - // std::cout << "Read: " << countBits << " " << GetBitIndex() << std::endl; - constexpr size_t ResultBitSize = sizeof(uint32_t) * 8; - constexpr size_t BufferBitSize = sizeof(uint64_t) * 8; - if (countBits == 0 || countBits > ResultBitSize) - throw std::runtime_error("The countBits is outside of the allowed range."); - - // Ensure we have enough data loaded into the buffer - while (m_bufferBitSize < countBits) - { - // Read a byte and put it in the buffer - char value; - auto prevLoc = m_stream.tellg(); - if (!m_stream.read(&value, 1)) - throw std::runtime_error("Failed read."); - - uint64_t expandValue = 0xFF & (uint64_t)value; - // std::cout << "ReadVal: 0x" << std::hex << expandValue << " 0x" << prevLoc << " 0x" << m_stream.tellg() << std::dec << std::endl; - - m_buffer |= expandValue << m_bufferBitSize; - m_bufferBitSize += 8; - // std::cout << "Buffer: 0x" << std::hex << m_buffer << std::dec << " " << m_bufferBitSize << std::endl; - - if (m_bufferBitSize > BufferBitSize) - { - std::cout << "Read: " << countBits << " " << GetBitIndex() << std::endl; - throw std::runtime_error("Ran out of room in the buffer: " + std::to_string(m_bufferBitSize)); - } - } - - // Pull out the requested number of bits - // Note: Ensure the shifted value is 64 bits to have room to go beyond the 32 bit buffer - uint64_t valueMask = (0x1LL << countBits) - 1; - uint32_t result = m_buffer & valueMask; - - // Shift the remaining bits to the start of the buffer - m_buffer = (m_buffer & ~valueMask) >> countBits; - m_bufferBitSize -= countBits; - - // std::cout << "ReadResult: " << result << " " << m_bufferBitSize << std::endl; - return result; -} - -uint32_t BitReader::ReadVBR32(size_t countBits) -{ - // std::cout << "ReadVBR32: " << countBits << " " << std::endl; - constexpr size_t ResultBitSize = sizeof(uint32_t) * 8; - - // Setup the continuation and value masks - uint32_t continuationFlagMask = 0x1 << (countBits - 1); - uint32_t valueMask = continuationFlagMask - 1; - - // Read chucks until the upper flag is not set - uint32_t result = 0; - uint32_t index = 0; - uint32_t maxIndex = ResultBitSize - (countBits - 1); - while (index <= maxIndex) - { - // Read the next chunk - uint32_t chunk = Read(countBits); - - // Combine the new chunk into the final result - result |= (chunk & valueMask) << index; - - // Check if we have a continuation flag set - if ((chunk & continuationFlagMask) == 0) - return result; - - // Update the index offset for the current value bits - index += countBits - 1; - } - - std::cout << countBits << std::endl; - throw std::runtime_error("Ran out of room in the requested buffer size: " + std::to_string(index)); -} - -// TODO: Template implementation for both types -uint64_t BitReader::ReadVBR64(size_t countBits) -{ - // std::cout << "ReadVBR64: " << countBits << " " << std::endl; - constexpr size_t ResultBitSize = sizeof(uint64_t) * 8; - - // Setup the continuation and value masks - uint64_t continuationFlagMask = 0x1 << (countBits - 1); - uint64_t valueMask = continuationFlagMask - 1; - - // Read chucks until the upper flag is not set - uint64_t result = 0; - uint64_t index = 0; - uint64_t maxIndex = ResultBitSize - (countBits - 1); - while (index <= maxIndex) - { - // Read the next chunk - uint32_t chunk = Read(countBits); - - // Combine the new chunk into the final result - result |= (chunk & valueMask) << index; - - // Check if we have a continuation flag set - if ((chunk & continuationFlagMask) == 0) - return result; - - // Update the index offset for the current value bits - index += countBits - 1; - } - - std::cout << countBits << std::endl; - throw std::runtime_error("Ran out of room in the requested buffer size: " + std::to_string(index)); -} - -void BitReader::Align32Bit() -{ - // Calcuate the offset to get to the next 32 bit word - auto currentBitOffset = GetBitIndex(); - auto currentWordOffset = currentBitOffset % 32; - if (currentWordOffset != 0) - { - auto nextWordOffset = 32 - currentWordOffset; - - // Read to the next word - // std::cout << "Align32Bit: " << currentBitOffset << " " << currentWordOffset << " " << nextWordOffset << std::endl; - auto ignoreResult = Read(nextWordOffset); - - // std::cout << "Align32Bit SKIP: 0x" << std::hex << ignoreResult << std::dec << std::endl; - } -} - -size_t BitReader::GetBitIndex() -{ - size_t streamByteLocation = m_stream.tellg(); - return (streamByteLocation * 8) - m_bufferBitSize; -} - -void BitReader::SeekByteOffset(size_t offset) -{ - // std::cout << "SeekByteOffset: " << offset << std::endl; - if ((m_bufferBitSize % 8) != 0) - throw std::runtime_error("Cannot seek byte offset when not aligned to a byte."); - - // First subtract the number of bytes available in the buffer - auto bufferByteSize = m_bufferBitSize / 8; - auto bytesRemovedFromBuffer = std::min(bufferByteSize, offset); - m_bufferBitSize -= bytesRemovedFromBuffer * 8; - offset -= bytesRemovedFromBuffer; - - // Perform the seek if required - if (offset > 0) - { - if (!m_stream.seekg(offset, m_stream.cur)) - throw std::runtime_error("Failed to seek stream."); - } -} - -bool BitReader::AtEndOfStream() const -{ - bool atEndOfStream = m_stream.peek() == std::char_traits::eof(); - // std::cout << "AtEndOfStream: " << atEndOfStream << " " << m_bufferBitSize << std::endl; - return atEndOfStream && m_bufferBitSize == 0; -} \ No newline at end of file diff --git a/Source/Parse/BitReader.h b/Source/Parse/BitReader.h deleted file mode 100644 index b3e3564b..00000000 --- a/Source/Parse/BitReader.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -namespace Soup -{ - class BitReader - { - public: - BitReader(std::istream& stream); - uint32_t Read(size_t countBits); - uint32_t ReadVBR32(size_t countBits); - uint64_t ReadVBR64(size_t countBits); - void Align32Bit(); - size_t GetBitIndex(); - void SeekByteOffset(size_t offset); - bool AtEndOfStream() const; - - private: - std::istream& m_stream; - uint64_t m_buffer; - size_t m_bufferBitSize; - }; -} diff --git a/Source/Parse/LLVMBitCodeParser.cpp b/Source/Parse/LLVMBitCodeParser.cpp deleted file mode 100644 index 9f9232cd..00000000 --- a/Source/Parse/LLVMBitCodeParser.cpp +++ /dev/null @@ -1,816 +0,0 @@ - -#include "LLVMBitCodeParser.h" - -using namespace Soup; - -template -void ReadBytes(std::istream &stream, std::array &result) -{ - if (!stream.read(result.data(), result.size())) - throw std::runtime_error("Failed read."); -} - -char ReadByte(std::istream &stream) -{ - char result; - if (!stream.read(&result, 1)) - throw std::runtime_error("Failed read."); - return result; -} - -void LLVMBitCodeParser::Parse(std::istream &stream) -{ - std::cout << "Parse" << std::endl; - - // Verify this is Clang Serialized AST Bitstream - std::array headerSignature; - ReadBytes(stream, headerSignature); - if (headerSignature[0] != 'C' || - headerSignature[1] != 'P' || - headerSignature[2] != 'C' || - headerSignature[3] != 'H') - { - throw std::runtime_error("File signture was not expected type."); - } - - // Setup the initial context - m_reader = std::make_unique(stream); - size_t initialAbbreviationLength = 2; - - // Read until end of stream - while (!m_reader->AtEndOfStream()) - { - auto code = static_cast(m_reader->Read(initialAbbreviationLength)); - switch (code) - { - case StandardAbbreviationId::EnterSubBlock: - ParseRootBlock(); - break; - default: - throw std::runtime_error( - std::string("Unexpected StandardAbbreviationId In Root: ") + std::to_string(static_cast(code))); - } - } - - m_reader = nullptr; - std::cout << "Done." << std::endl; -} - -BlockContext& LLVMBitCodeParser::GetActiveContext() -{ - return m_context.top(); -} - -std::string_view LLVMBitCodeParser::GetBlockName(uint32_t blockId) -{ - if (blockId < FirstApplicationBlockId) - { - switch (static_cast(blockId)) - { - case StandardBlockId::BlockInfo: - return "BLOCK_INFO"; - default: - return "UNKNOWN_STANDARD"; - } - } - else - { - auto blockInfoResult = std::find_if( - m_blocks.begin(), - m_blocks.end(), - [blockId](const BlockInfo &value) { return value.Id == blockId; }); - if (blockInfoResult != m_blocks.end()) - { - return blockInfoResult->Name; - } - else - { - return "UNKNOWN"; - } - } -} - -std::string_view LLVMBitCodeParser::GetRecordName(uint32_t blockId, uint32_t code) -{ - if (blockId < FirstApplicationBlockId) - { - switch (static_cast(blockId)) - { - case StandardBlockId::BlockInfo: - return "UNKNOWN (BLOCK_INFO)"; - default: - return "UNKNOWN (STANDARD)"; - } - } - else - { - auto blockInfoResult = std::find_if( - m_blocks.begin(), - m_blocks.end(), - [blockId](const BlockInfo &value) { return value.Id == blockId; }); - if (blockInfoResult != m_blocks.end()) - { - auto recordInfoResult = std::find_if( - blockInfoResult->Records.begin(), - blockInfoResult->Records.end(), - [code](const RecordInfo &value) { return value.Id == code; }); - if (recordInfoResult != blockInfoResult->Records.end()) - { - return recordInfoResult->Name; - } - else - { - return "UNKNOWN"; - } - } - else - { - return "UNKNOWN (MISSING BLOCK)"; - } - } -} - -void LLVMBitCodeParser::ParseRootBlock() -{ - // Read the new block and add a new context to the stack - m_context.emplace(); - GetActiveContext().BlockId = m_reader->ReadVBR32(8); - GetActiveContext().AbbreviationLength = m_reader->ReadVBR32(4); - m_reader->Align32Bit(); - - auto blockLength = m_reader->Read(32); - std::cout << "EnterSubBlock: " << GetBlockName(GetActiveContext().BlockId) << std::endl; - - if (GetActiveContext().BlockId < FirstApplicationBlockId) - { - switch (static_cast(GetActiveContext().BlockId)) - { - case StandardBlockId::BlockInfo: - ParseBlockInfoBlock(); - break; - default: - throw std::runtime_error("Unknown stadard block id."); - } - } - else - { - switch (static_cast(GetActiveContext().BlockId)) - { - case ClangAST::BlockId::AST: - ParseASTBlock(); - break; - case ClangAST::BlockId::Control: - ParseControlBlock(); - break; - default: - // Skip unknown block - std::cout << "Skip Block" << std::endl; - m_reader->SeekByteOffset(blockLength * 4); - } - } - - // Pop this context - m_context.pop(); -} - -void LLVMBitCodeParser::ParseBlockInfoBlock() -{ - // Read until we hit an end block - BlockInfo* activeBlock = nullptr; - while (true) - { - auto code = m_reader->Read(GetActiveContext().AbbreviationLength); - switch (static_cast(code)) - { - case StandardAbbreviationId::DefineAbbreviation: - { - GetActiveContext().Abbreviations.push_back(ParseDefineAbbreviation()); - break; - } - case StandardAbbreviationId::UnabbreviatedRecord: - { - auto record = ParseUnabbreviatedRecord(); - switch (static_cast(record.Code)) - { - case BlockRecordId::SetBlockId: - { - if (record.Operands.size() != 1) - throw std::runtime_error("A SetBlockId record must have exactly one operand."); - - // Create the new block info - m_blocks.emplace_back(); - activeBlock = &*std::prev(m_blocks.end()); - // Downcast the 64 bit value to the 32 bit id - activeBlock->Id = static_cast(record.Operands[0]); - break; - } - case BlockRecordId::BlockName: - { - if (activeBlock == nullptr) - throw std::runtime_error("Cannot set BlockName without an active block."); - activeBlock->Name = std::string(record.Operands.begin(), record.Operands.end()); - break; - } - case BlockRecordId::SetRecordName: - { - if (activeBlock == nullptr) - throw std::runtime_error("Cannot set RecordName without an active block."); - if (record.Operands.size() < 1) - throw std::runtime_error("Set RecordName must have at least one operand."); - auto recordInfo = RecordInfo(); - recordInfo.Id = static_cast(record.Operands[0]); - recordInfo.Name = std::string(record.Operands.begin() + 1, record.Operands.end()); - activeBlock->Records.push_back(std::move(recordInfo)); - break; - } - default: - { - throw std::runtime_error("Unknown BlockInfoBlock Record."); - } - } - break; - } - case StandardAbbreviationId::EndBlock: - { - std::cout << "EndBlock" << std::endl; - m_reader->Align32Bit(); - return; - } - default: - { - throw std::runtime_error( - std::string("Unexpected StandardAbbreviationId In BlockInfoBlock: ") + std::to_string(static_cast(code))); - } - } - } -} - -BitCodeAbbreviation LLVMBitCodeParser::ParseDefineAbbreviation() -{ - auto result = BitCodeAbbreviation(); - auto numberOperands = m_reader->ReadVBR32(5); - result.Operands.reserve(numberOperands); - - for (auto i = 0; i < numberOperands; i++) - { - auto operand = BitCodeAbbreviationOperand(); - operand.IsLiteral = static_cast(m_reader->Read(1)); - if (operand.IsLiteral) - { - operand.Value = m_reader->ReadVBR32(8); - } - else - { - operand.Encoding = static_cast(m_reader->Read(3)); - switch (operand.Encoding) - { - case AbbreviationEncoding::Fixed: - case AbbreviationEncoding::VBR: - operand.Value = m_reader->ReadVBR32(5); - break; - case AbbreviationEncoding::Array: - case AbbreviationEncoding::Char6: - case AbbreviationEncoding::Blob: - break; - default: - throw std::runtime_error("Unknown AbbreviationEncoding"); - } - } - - result.Operands.push_back(std::move(operand)); - } - - return result; -} - -UnabbreviatedRecord LLVMBitCodeParser::ParseUnabbreviatedRecord() -{ - UnabbreviatedRecord result = {}; - result.Code = m_reader->ReadVBR32(6); - auto numberOperands = m_reader->ReadVBR32(6); - result.Operands.reserve(numberOperands); - - for (auto i = 0; i < numberOperands; i++) - { - auto operand = m_reader->ReadVBR64(6); - result.Operands.push_back(operand); - } - - return result; -} - -uint64_t LLVMBitCodeParser::ReadSingleOperand(const BitCodeAbbreviationOperand& operand) -{ - if (operand.IsLiteral) - { - return operand.Value; - } - else - { - switch (operand.Encoding) - { - case AbbreviationEncoding::Fixed: - return m_reader->Read(operand.Value); - case AbbreviationEncoding::VBR: - return m_reader->ReadVBR64(operand.Value); - case AbbreviationEncoding::Char6: - return m_reader->Read(6); - case AbbreviationEncoding::Array: - case AbbreviationEncoding::Blob: - throw std::runtime_error("Expected a single value encoding."); - default: - throw std::runtime_error("Unknown AbbreviationEncoding"); - } - } -} - -BitCodeRecord LLVMBitCodeParser::ParseRecord(uint32_t abbreviationId) -{ - auto result = BitCodeRecord(); - - auto abbreviationIndex = abbreviationId - FirstApplicationAbbreviationId; - if (abbreviationIndex >= GetActiveContext().Abbreviations.size()) - throw std::runtime_error("Unknown application defined abbreviation id: " + std::to_string(abbreviationId)); - auto& abbreviation = GetActiveContext().Abbreviations[abbreviationIndex]; - - // read the record code - if (abbreviation.Operands.empty()) - throw std::runtime_error("Abbreviation must have at least one operand."); - result.Code = ReadSingleOperand(abbreviation.Operands[0]); - // std::cout << "Parse Record: " << GetRecordName(blockId, result.Code) << std::endl; - - // Read the remaining operands - for (auto i = 1; i < abbreviation.Operands.size(); i++) - { - auto& operand = abbreviation.Operands[i]; - if (operand.IsLiteral || (operand.Encoding != AbbreviationEncoding::Array && operand.Encoding != AbbreviationEncoding::Blob)) - { - auto value = ReadSingleOperand(operand); - result.Values.push_back(value); - } - else - { - // Parse the complex cases - switch (operand.Encoding) - { - case AbbreviationEncoding::Array: - { - if (i != abbreviation.Operands.size() - 2) - throw std::runtime_error("A array can only occur as the second to last operand."); - - auto arraySize = m_reader->ReadVBR32(6); - auto& typeOperand = abbreviation.Operands[++i]; - - for (auto arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) - { - auto value = ReadSingleOperand(typeOperand); - result.Values.push_back(value); - } - - break; - } - case AbbreviationEncoding::Blob: - { - if (i != abbreviation.Operands.size() - 1) - throw std::runtime_error("A blob can only occur as the last operand."); - - auto blobSize = m_reader->ReadVBR32(6); - m_reader->Align32Bit(); - - for (auto blobIndex = 0; blobIndex < blobSize; blobIndex++) - { - auto value = m_reader->Read(8); - result.Values.push_back(value); - } - - m_reader->Align32Bit(); - break; - } - default: - { - throw std::runtime_error("Unexpected AbbreviationEncoding"); - } - } - } - } - - return result; -} - -void LLVMBitCodeParser::ParseControlBlock() -{ - // Read until we hit an end block - while (true) - { - auto abbreviationId = m_reader->Read(GetActiveContext().AbbreviationLength); - if (abbreviationId < FirstApplicationAbbreviationId) - { - switch (static_cast(abbreviationId)) - { - case StandardAbbreviationId::EnterSubBlock: - { - // Read the new block and add a new context to the stack - m_context.emplace(); - GetActiveContext().BlockId = m_reader->ReadVBR32(8); - GetActiveContext().AbbreviationLength = m_reader->ReadVBR32(4); - m_reader->Align32Bit(); - auto blockLength = m_reader->Read(32); - - std::cout << "EnterSubBlock: " << GetBlockName(GetActiveContext().BlockId) << std::endl; - std::cout << "Skip Block" << std::endl; - m_reader->SeekByteOffset(blockLength * 4); - - // Pop this context - m_context.pop(); - break; - } - case StandardAbbreviationId::DefineAbbreviation: - { - GetActiveContext().Abbreviations.push_back(ParseDefineAbbreviation()); - break; - } - case StandardAbbreviationId::UnabbreviatedRecord: - { - auto record = ParseUnabbreviatedRecord(); - break; - } - case StandardAbbreviationId::EndBlock: - { - std::cout << "EndBlock" << std::endl; - m_reader->Align32Bit(); - return; - } - default: - { - throw std::runtime_error( - std::string("Unexpected AbbreviationId In ControlBlock: ") + - std::to_string(abbreviationId)); - } - } - } - else - { - auto record = ParseRecord(abbreviationId); - // TODO - } - } -} - - -void LLVMBitCodeParser::ParseASTBlock() -{ - // Read until we hit an end block - while (true) - { - auto abbreviationId = m_reader->Read(GetActiveContext().AbbreviationLength); - if (abbreviationId < FirstApplicationAbbreviationId) - { - switch (static_cast(abbreviationId)) - { - case StandardAbbreviationId::EnterSubBlock: - { - // Read the new block and add a new context to the stack - m_context.emplace(); - GetActiveContext().BlockId = m_reader->ReadVBR32(8); - GetActiveContext().AbbreviationLength = m_reader->ReadVBR32(4); - m_reader->Align32Bit(); - auto blockLength = m_reader->Read(32); - - std::cout << "EnterSubBlock: " << GetBlockName(GetActiveContext().BlockId) << std::endl; - switch (static_cast(GetActiveContext().BlockId)) - { - case ClangAST::BlockId::DeclTypes: - ParseDeclTypesBlock(); - break; - default: - // Skip unknown block - std::cout << "Skip Block" << std::endl; - m_reader->SeekByteOffset(blockLength * 4); - } - - // Pop this context - m_context.pop(); - - break; - } - case StandardAbbreviationId::DefineAbbreviation: - { - GetActiveContext().Abbreviations.push_back(ParseDefineAbbreviation()); - break; - } - case StandardAbbreviationId::UnabbreviatedRecord: - { - auto record = ParseUnabbreviatedRecord(); - break; - } - case StandardAbbreviationId::EndBlock: - { - std::cout << "EndBlock" << std::endl; - m_reader->Align32Bit(); - return; - } - default: - { - throw std::runtime_error( - std::string("Unexpected AbbreviationId In ASTBlock: ") + - std::to_string(abbreviationId)); - } - } - } - else - { - auto record = ParseRecord(abbreviationId); - // TODO - } - } -} - -void LLVMBitCodeParser::ParseDeclTypesBlock() -{ - // Read until we hit an end block - while (true) - { - auto abbreviationId = m_reader->Read(GetActiveContext().AbbreviationLength); - if (abbreviationId < FirstApplicationAbbreviationId) - { - switch (static_cast(abbreviationId)) - { - case StandardAbbreviationId::EnterSubBlock: - { - // Read the new block and add a new context to the stack - m_context.emplace(); - GetActiveContext().BlockId = m_reader->ReadVBR32(8); - GetActiveContext().AbbreviationLength = m_reader->ReadVBR32(4); - m_reader->Align32Bit(); - auto blockLength = m_reader->Read(32); - - std::cout << "EnterSubBlock: " << GetBlockName(GetActiveContext().BlockId) << std::endl; - switch (static_cast(GetActiveContext().BlockId)) - { - default: - // Skip unknown block - std::cout << "Skip Block" << std::endl; - m_reader->SeekByteOffset(blockLength * 4); - } - - // Pop this context - m_context.pop(); - - break; - } - case StandardAbbreviationId::DefineAbbreviation: - { - GetActiveContext().Abbreviations.push_back(ParseDefineAbbreviation()); - break; - } - case StandardAbbreviationId::UnabbreviatedRecord: - { - std::cout << "UnabbreviatedRecord: " << std::endl; - ParseExternalCPPBaseSpecifiers(); - break; - } - case StandardAbbreviationId::EndBlock: - { - std::cout << "EndBlock" << std::endl; - m_reader->Align32Bit(); - return; - } - default: - { - throw std::runtime_error( - std::string("Unexpected AbbreviationId In DeclTypesBlock: ") + - std::to_string(abbreviationId)); - } - } - } - else - { - // The first record should be a declaration context - auto record = ParseRecord(abbreviationId); - std::cout << "RECORD: " << record.Code << std::endl; - } - } -} - -void ParseTypeSourceInfo(const std::vector& values, uint32_t& index) -{ - auto typeId = values[index++]; - std::cout << "ParseTypeSourceInfo: " << typeId << std::endl; - // TODO: -} - -void LLVMBitCodeParser::ParseExternalCPPBaseSpecifiers() -{ - auto record = ParseUnabbreviatedRecord(); - if (static_cast(record.Code) != ClangAST::DeclarationCode::CPP_BaseSpecifiers) - throw std::runtime_error("Record must be CPP_BaseSpecifiers"); - - uint32_t index = 0; - auto basesCount = record.Operands[index++]; - for (auto i = 0; i < basesCount; i++) - { - auto isVirtual = static_cast(record.Operands[index++]); - auto isBaseOfClass = static_cast(record.Operands[index++]); - auto accessSpecifier = static_cast(record.Operands[index++]); - auto inheritConstructors = static_cast(record.Operands[index++]); - - // Parse the type info source location - ParseTypeSourceInfo(record.Operands, index); - - auto rawSourceBegin = record.Operands[index++]; - auto rawSourceEnd = record.Operands[index++]; - - auto rawEllipsisLocation = record.Operands[index++]; - - std::cout << "CPPBaseSpecifier: " << isVirtual << " " << isBaseOfClass << " " << static_cast(accessSpecifier) << std::endl; - } - - // TODO - // if (index != record.Operands.size()) - // throw std::runtime_error("Did not consume entire record: CPP_BaseSpecifiers"); -} - -void LLVMBitCodeParser::ParseDeclarationContext(const BitCodeRecord& record) -{ - if (static_cast(record.Code) != ClangAST::DeclarationCode::ContextLexical) - throw std::runtime_error("Record must be ContextLexical"); - - auto blockId = static_cast(ClangAST::BlockId::DeclTypes); - std::cout << record.Values.size() << std::endl; - for (auto value : record.Values) - { - auto abbreviationId = m_reader->Read(GetActiveContext().AbbreviationLength); - auto otherRecord = ParseUnabbreviatedRecord(); - //auto declarationRecord = ParseRecord(abbreviationId); - std::cout << value << " : " << otherRecord.Code << std::endl; - } -} - -void LLVMBitCodeParser::ParseDeclaration(const BitCodeRecord& record) -{ - switch (static_cast(record.Code)) - { - case ClangAST::DeclarationCode::TypeDef: - throw std::runtime_error("NOT_IMPLEMENTED: TypeDef"); - case ClangAST::DeclarationCode::TypeAlias: - throw std::runtime_error("NOT_IMPLEMENTED: TypeAlias"); - case ClangAST::DeclarationCode::Enum: - throw std::runtime_error("NOT_IMPLEMENTED: Enum"); - case ClangAST::DeclarationCode::Record: - throw std::runtime_error("NOT_IMPLEMENTED: Record"); - case ClangAST::DeclarationCode::EnumConstant: - throw std::runtime_error("NOT_IMPLEMENTED: EnumConstant"); - case ClangAST::DeclarationCode::Function: - throw std::runtime_error("NOT_IMPLEMENTED: Function"); - case ClangAST::DeclarationCode::Method: - throw std::runtime_error("NOT_IMPLEMENTED: Method"); - case ClangAST::DeclarationCode::ObjC_Interface: - throw std::runtime_error("NOT_IMPLEMENTED: ObjC_Interface"); - case ClangAST::DeclarationCode::ObjC_Protocol: - throw std::runtime_error("NOT_IMPLEMENTED: ObjC_Protocol"); - case ClangAST::DeclarationCode::ObjC_IVar: - throw std::runtime_error("NOT_IMPLEMENTED: ObjC_IVar"); - case ClangAST::DeclarationCode::ObjC_AtDefsField: - throw std::runtime_error("NOT_IMPLEMENTED: ObjC_AtDefsField"); - case ClangAST::DeclarationCode::ObjC_Category: - throw std::runtime_error("NOT_IMPLEMENTED: ObjC_Category"); - case ClangAST::DeclarationCode::OBJC_CategoryImpl: - throw std::runtime_error("NOT_IMPLEMENTED: OBJC_CategoryImpl"); - case ClangAST::DeclarationCode::OBJC_Implementation: - throw std::runtime_error("NOT_IMPLEMENTED: OBJC_Implementation"); - case ClangAST::DeclarationCode::OBJC_CompatibleAlias: - throw std::runtime_error("NOT_IMPLEMENTED: OBJC_CompatibleAlias"); - case ClangAST::DeclarationCode::OBJC_Property: - throw std::runtime_error("NOT_IMPLEMENTED: OBJC_Property"); - case ClangAST::DeclarationCode::OBJC_PropertyImpl: - throw std::runtime_error("NOT_IMPLEMENTED: OBJC_PropertyImpl"); - case ClangAST::DeclarationCode::Field: - throw std::runtime_error("NOT_IMPLEMENTED: Field"); - case ClangAST::DeclarationCode::MS_Property: - throw std::runtime_error("NOT_IMPLEMENTED: MS_Property"); - case ClangAST::DeclarationCode::Var: - throw std::runtime_error("NOT_IMPLEMENTED: Var"); - case ClangAST::DeclarationCode::ImplicitParam: - throw std::runtime_error("NOT_IMPLEMENTED: ImplicitParam"); - case ClangAST::DeclarationCode::ParmVar: - throw std::runtime_error("NOT_IMPLEMENTED: ParmVar"); - case ClangAST::DeclarationCode::Decomposition: - throw std::runtime_error("NOT_IMPLEMENTED: Decomposition"); - case ClangAST::DeclarationCode::Binding: - throw std::runtime_error("NOT_IMPLEMENTED: Binding"); - case ClangAST::DeclarationCode::FileScopeASM: - throw std::runtime_error("NOT_IMPLEMENTED: FileScopeASM"); - case ClangAST::DeclarationCode::Block: - throw std::runtime_error("NOT_IMPLEMENTED: Block"); - case ClangAST::DeclarationCode::Captured: - throw std::runtime_error("NOT_IMPLEMENTED: Captured"); - case ClangAST::DeclarationCode::ContextLexical: - throw std::runtime_error("NOT_IMPLEMENTED: ContextLexical"); - case ClangAST::DeclarationCode::ContextVisible: - throw std::runtime_error("NOT_IMPLEMENTED: ContextVisible"); - case ClangAST::DeclarationCode::Label: - throw std::runtime_error("NOT_IMPLEMENTED: Label"); - case ClangAST::DeclarationCode::Namespace: - throw std::runtime_error("NOT_IMPLEMENTED: Namespace"); - case ClangAST::DeclarationCode::NamespaceAlias: - throw std::runtime_error("NOT_IMPLEMENTED: NamespaceAlias"); - case ClangAST::DeclarationCode::Using: - throw std::runtime_error("NOT_IMPLEMENTED: Using"); - case ClangAST::DeclarationCode::UsingPack: - throw std::runtime_error("NOT_IMPLEMENTED: UsingPack"); - case ClangAST::DeclarationCode::UsingShadow: - throw std::runtime_error("NOT_IMPLEMENTED: UsingShadow"); - case ClangAST::DeclarationCode::ConstrutorUsingShadow: - throw std::runtime_error("NOT_IMPLEMENTED: ConstrutorUsingShadow"); - case ClangAST::DeclarationCode::UsingDirective: - throw std::runtime_error("NOT_IMPLEMENTED: UsingDirective"); - case ClangAST::DeclarationCode::UnresolvedUsingValue: - throw std::runtime_error("NOT_IMPLEMENTED: UnresolvedUsingValue"); - case ClangAST::DeclarationCode::UnresolvedUsingTypename: - throw std::runtime_error("NOT_IMPLEMENTED: UnresolvedUsingTypename"); - case ClangAST::DeclarationCode::LinkageSpec: - throw std::runtime_error("NOT_IMPLEMENTED: LinkageSpec"); - case ClangAST::DeclarationCode::Export: - throw std::runtime_error("NOT_IMPLEMENTED: Export"); - case ClangAST::DeclarationCode::CPP_Record: - throw std::runtime_error("NOT_IMPLEMENTED: CPP_Record"); - case ClangAST::DeclarationCode::CPP_DeductionGuide: - throw std::runtime_error("NOT_IMPLEMENTED: CPP_DeductionGuide"); - case ClangAST::DeclarationCode::CPP_Method: - throw std::runtime_error("NOT_IMPLEMENTED: CPP_Method"); - case ClangAST::DeclarationCode::CPP_Constructor: - throw std::runtime_error("NOT_IMPLEMENTED: CPP_Constructor"); - case ClangAST::DeclarationCode::CPP_Destructor: - throw std::runtime_error("NOT_IMPLEMENTED: CPP_Destructor"); - case ClangAST::DeclarationCode::CPP_Conversion: - throw std::runtime_error("NOT_IMPLEMENTED: CPP_Conversion"); - case ClangAST::DeclarationCode::AccessSpec: - throw std::runtime_error("NOT_IMPLEMENTED: AccessSpec"); - case ClangAST::DeclarationCode::Friend: - throw std::runtime_error("NOT_IMPLEMENTED: Friend"); - case ClangAST::DeclarationCode::FriendTemplate: - throw std::runtime_error("NOT_IMPLEMENTED: FriendTemplate"); - case ClangAST::DeclarationCode::ClassTemplate: - throw std::runtime_error("NOT_IMPLEMENTED: ClassTemplate"); - case ClangAST::DeclarationCode::ClassTemplateSpecialization: - throw std::runtime_error("NOT_IMPLEMENTED: ClassTemplateSpecialization"); - case ClangAST::DeclarationCode::ClassTemplatePartialSpecialization: - throw std::runtime_error("NOT_IMPLEMENTED: ClassTemplatePartialSpecialization"); - case ClangAST::DeclarationCode::VarTemplate: - throw std::runtime_error("NOT_IMPLEMENTED: VarTemplate"); - case ClangAST::DeclarationCode::VarTemplateSpecialization: - throw std::runtime_error("NOT_IMPLEMENTED: VarTemplateSpecialization"); - case ClangAST::DeclarationCode::VarTemplatePartialSpecialization: - throw std::runtime_error("NOT_IMPLEMENTED: VarTemplatePartialSpecialization"); - case ClangAST::DeclarationCode::FunctionTemplate: - throw std::runtime_error("NOT_IMPLEMENTED: FunctionTemplate"); - case ClangAST::DeclarationCode::TemplateTypeParm: - throw std::runtime_error("NOT_IMPLEMENTED: TemplateTypeParm"); - case ClangAST::DeclarationCode::NonTypeTemplateParm: - throw std::runtime_error("NOT_IMPLEMENTED: NonTypeTemplateParm"); - case ClangAST::DeclarationCode::TemplateTemplateParm: - throw std::runtime_error("NOT_IMPLEMENTED: TemplateTemplateParm"); - case ClangAST::DeclarationCode::TypeAliasTemplate: - throw std::runtime_error("NOT_IMPLEMENTED: TypeAliasTemplate"); - case ClangAST::DeclarationCode::Concept: - throw std::runtime_error("NOT_IMPLEMENTED: Concept"); - case ClangAST::DeclarationCode::StaticAssert: - throw std::runtime_error("NOT_IMPLEMENTED: StaticAssert"); - case ClangAST::DeclarationCode::CPP_BaseSpecifiers: - throw std::runtime_error("NOT_IMPLEMENTED: CPP_BaseSpecifiers"); - case ClangAST::DeclarationCode::CPP_ConstructorInitializers: - throw std::runtime_error("NOT_IMPLEMENTED: CPP_ConstructorInitializers"); - case ClangAST::DeclarationCode::IndirectField: - throw std::runtime_error("NOT_IMPLEMENTED: IndirectField"); - case ClangAST::DeclarationCode::ExpandedNonTypeTemplateParmPack: - throw std::runtime_error("NOT_IMPLEMENTED: ExpandedNonTypeTemplateParmPack"); - case ClangAST::DeclarationCode::ExpandedTemplateTemplateParmPack: - throw std::runtime_error("NOT_IMPLEMENTED: ExpandedTemplateTemplateParmPack"); - case ClangAST::DeclarationCode::ClassScopeFunctionSpecification: - throw std::runtime_error("NOT_IMPLEMENTED: ClassScopeFunctionSpecification"); - case ClangAST::DeclarationCode::Import: - throw std::runtime_error("NOT_IMPLEMENTED: Import"); - case ClangAST::DeclarationCode::OMP_ThreadPrivate: - throw std::runtime_error("NOT_IMPLEMENTED: OMP_ThreadPrivate"); - case ClangAST::DeclarationCode::OMP_Requires: - throw std::runtime_error("NOT_IMPLEMENTED: OMP_Requires"); - case ClangAST::DeclarationCode::OMP_Allocate: - throw std::runtime_error("NOT_IMPLEMENTED: OMP_Allocate"); - case ClangAST::DeclarationCode::Empty: - throw std::runtime_error("NOT_IMPLEMENTED: Empty"); - case ClangAST::DeclarationCode::ObjC_TypeParam: - throw std::runtime_error("NOT_IMPLEMENTED: ObjC_TypeParam"); - case ClangAST::DeclarationCode::OMP_CaptureDExpr: - throw std::runtime_error("NOT_IMPLEMENTED: OMP_CaptureDExpr"); - case ClangAST::DeclarationCode::PragmaComment: - throw std::runtime_error("NOT_IMPLEMENTED: PragmaComment"); - case ClangAST::DeclarationCode::PagmaDetectMismatch: - throw std::runtime_error("NOT_IMPLEMENTED: PagmaDetectMismatch"); - case ClangAST::DeclarationCode::OMP_DeclareMapper: - throw std::runtime_error("NOT_IMPLEMENTED: OMP_DeclareMapper"); - case ClangAST::DeclarationCode::OMP_DeclareReduction: - throw std::runtime_error("NOT_IMPLEMENTED: OMP_DeclareReduction"); - default: - throw std::runtime_error("Unknown ClangAST::DeclarationCode record: " + std::to_string(record.Code)); - } -} \ No newline at end of file diff --git a/Source/Parse/LLVMBitCodeParser.h b/Source/Parse/LLVMBitCodeParser.h deleted file mode 100644 index b825da7f..00000000 --- a/Source/Parse/LLVMBitCodeParser.h +++ /dev/null @@ -1,439 +0,0 @@ -#pragma once -#include "BitReader.h" - -namespace Soup -{ - constexpr uint32_t FirstApplicationAbbreviationId = 4; - enum class StandardAbbreviationId : char - { - // This abbrev ID marks the end of the current block. - EndBlock = 0, - // This abbrev ID marks the beginning of a new block. - EnterSubBlock = 1, - // This defines a new abbreviation. - DefineAbbreviation = 2, - // This ID specifies the definition of an unabbreviated record. - UnabbreviatedRecord = 3, - }; - - constexpr uint32_t FirstApplicationBlockId = 8; - enum class StandardBlockId - { - BlockInfo = 0, - }; - - enum class BlockRecordId - { - SetBlockId = 1, - BlockName = 2, - SetRecordName = 3, - }; - - enum class AbbreviationEncoding - { - Fixed = 1, - VBR = 2, - Array = 3, - Char6 = 4, - Blob = 5, - }; - - namespace ClangAST - { - enum class BlockId - { - AST = FirstApplicationBlockId, - SourceManager, - Preprocessor, - DeclTypes, - PreprocessorDetail, - SubModule, - Comments, - Control, - InputFiles, - Options, - Extension, - UnhashedControl, - }; - - // Record codes for each kind of declaration in the Clang AST. - enum class DeclarationCode - { - FirstElement = 51, - TypeDef = FirstElement, - TypeAlias, - Enum, - Record, - EnumConstant, - Function, - Method, - ObjC_Interface, - ObjC_Protocol, - ObjC_IVar, - ObjC_AtDefsField, - ObjC_Category, - OBJC_CategoryImpl, - OBJC_Implementation, - OBJC_CompatibleAlias, - OBJC_Property, - OBJC_PropertyImpl, - Field, - MS_Property, - Var, - ImplicitParam, - ParmVar, - Decomposition, - Binding, - FileScopeASM, - Block, - Captured, - ContextLexical, - ContextVisible, - Label, - Namespace, - NamespaceAlias, - Using, - UsingPack, - UsingShadow, - ConstrutorUsingShadow, - UsingDirective, - UnresolvedUsingValue, - UnresolvedUsingTypename, - LinkageSpec, - Export, - CPP_Record, - CPP_DeductionGuide, - CPP_Method, - CPP_Constructor, - CPP_Destructor, - CPP_Conversion, - AccessSpec, - Friend, - FriendTemplate, - ClassTemplate, - ClassTemplateSpecialization, - ClassTemplatePartialSpecialization, - VarTemplate, - VarTemplateSpecialization, - VarTemplatePartialSpecialization, - FunctionTemplate, - TemplateTypeParm, - NonTypeTemplateParm, - TemplateTemplateParm, - TypeAliasTemplate, - Concept, - StaticAssert, - CPP_BaseSpecifiers, - CPP_ConstructorInitializers, - IndirectField, - ExpandedNonTypeTemplateParmPack, - ExpandedTemplateTemplateParmPack, - ClassScopeFunctionSpecification, - Import, - OMP_ThreadPrivate, - OMP_Requires, - OMP_Allocate, - Empty, - ObjC_TypeParam, - OMP_CaptureDExpr, - PragmaComment, - PagmaDetectMismatch, - OMP_DeclareMapper, - OMP_DeclareReduction, - LastElement = OMP_DeclareReduction, - }; - - // Record codes for each kind of statement or expression. - enum class StatementCode - { - FirstElement = static_cast(DeclarationCode::LastElement) + 1, - STMT_STOP = FirstElement, - STMT_NULL_PTR, - STMT_REF_PTR, - STMT_NULL, - STMT_COMPOUND, - STMT_CASE, - STMT_DEFAULT, - STMT_LABEL, - STMT_ATTRIBUTED, - STMT_IF, - STMT_SWITCH, - STMT_WHILE, - STMT_DO, - STMT_FOR, - STMT_GOTO, - STMT_INDIRECT_GOTO, - STMT_CONTINUE, - STMT_BREAK, - STMT_RETURN, - STMT_DECL, - STMT_CAPTURED, - STMT_GCCASM, - STMT_MSASM, - EXPR_CONSTANT, - EXPR_PREDEFINED, - EXPR_DECL_REF, - EXPR_INTEGER_LITERAL, - EXPR_FLOATING_LITERAL, - EXPR_IMAGINARY_LITERAL, - EXPR_STRING_LITERAL, - EXPR_CHARACTER_LITERAL, - EXPR_PAREN, - EXPR_PAREN_LIST, - EXPR_UNARY_OPERATOR, - EXPR_OFFSETOF, - EXPR_SIZEOF_ALIGN_OF, - EXPR_ARRAY_SUBSCRIPT, - EXPR_CALL, - EXPR_MEMBER, - EXPR_BINARY_OPERATOR, - EXPR_COMPOUND_ASSIGN_OPERATOR, - EXPR_CONDITIONAL_OPERATOR, - EXPR_IMPLICIT_CAST, - EXPR_CSTYLE_CAST, - EXPR_COMPOUND_LITERAL, - EXPR_EXT_VECTOR_ELEMENT, - EXPR_INIT_LIST, - EXPR_DESIGNATED_INIT, - EXPR_DESIGNATED_INIT_UPDATE, - EXPR_NO_INIT, - EXPR_ARRAY_INIT_LOOP, - EXPR_ARRAY_INIT_INDEX, - EXPR_IMPLICIT_VALUE_INIT, - EXPR_VA_ARG, - EXPR_ADDR_LABEL, - EXPR_STMT, - EXPR_CHOOSE, - EXPR_GNU_NULL, - EXPR_SOURCE_LOC, - EXPR_SHUFFLE_VECTOR, - EXPR_CONVERT_VECTOR, - EXPR_BLOCK, - EXPR_GENERIC_SELECTION, - EXPR_PSEUDO_OBJECT, - EXPR_ATOMIC, - EXPR_OBJC_STRING_LITERAL, - EXPR_OBJC_BOXED_EXPRESSION, - EXPR_OBJC_ARRAY_LITERAL, - EXPR_OBJC_DICTIONARY_LITERAL, - EXPR_OBJC_ENCODE, - EXPR_OBJC_SELECTOR_EXPR, - EXPR_OBJC_PROTOCOL_EXPR, - EXPR_OBJC_IVAR_REF_EXPR, - EXPR_OBJC_PROPERTY_REF_EXPR, - EXPR_OBJC_SUBSCRIPT_REF_EXPR, - EXPR_OBJC_KVC_REF_EXPR, - EXPR_OBJC_MESSAGE_EXPR, - EXPR_OBJC_ISA, - EXPR_OBJC_INDIRECT_COPY_RESTORE, - STMT_OBJC_FOR_COLLECTION, - STMT_OBJC_CATCH, - STMT_OBJC_FINALLY, - STMT_OBJC_AT_TRY, - STMT_OBJC_AT_SYNCHRONIZED, - STMT_OBJC_AT_THROW, - STMT_OBJC_AUTORELEASE_POOL, - EXPR_OBJC_BOOL_LITERAL, - EXPR_OBJC_AVAILABILITY_CHECK, - STMT_CXX_CATCH, - STMT_CXX_TRY, - STMT_CXX_FOR_RANGE, - EXPR_CXX_OPERATOR_CALL, - EXPR_CXX_MEMBER_CALL, - EXPR_CXX_CONSTRUCT, - EXPR_CXX_INHERITED_CTOR_INIT, - EXPR_CXX_TEMPORARY_OBJECT, - EXPR_CXX_STATIC_CAST, - EXPR_CXX_DYNAMIC_CAST, - EXPR_CXX_REINTERPRET_CAST, - EXPR_CXX_CONST_CAST, - EXPR_CXX_FUNCTIONAL_CAST, - EXPR_USER_DEFINED_LITERAL, - EXPR_CXX_STD_INITIALIZER_LIST, - EXPR_CXX_BOOL_LITERAL, - EXPR_CXX_NULL_PTR_LITERAL, - EXPR_CXX_TYPEID_EXPR, - EXPR_CXX_TYPEID_TYPE, - EXPR_CXX_THIS, - EXPR_CXX_THROW, - EXPR_CXX_DEFAULT_ARG, - EXPR_CXX_DEFAULT_INIT, - EXPR_CXX_BIND_TEMPORARY, - EXPR_CXX_SCALAR_VALUE_INIT, - EXPR_CXX_NEW, - EXPR_CXX_DELETE, - EXPR_CXX_PSEUDO_DESTRUCTOR, - EXPR_EXPR_WITH_CLEANUPS, - EXPR_CXX_DEPENDENT_SCOPE_MEMBER, - EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, - EXPR_CXX_UNRESOLVED_CONSTRUCT, - EXPR_CXX_UNRESOLVED_MEMBER, - EXPR_CXX_UNRESOLVED_LOOKUP, - EXPR_CXX_EXPRESSION_TRAIT, - EXPR_CXX_NOEXCEPT, - EXPR_OPAQUE_VALUE, - EXPR_BINARY_CONDITIONAL_OPERATOR, - EXPR_TYPE_TRAIT, - EXPR_ARRAY_TYPE_TRAIT, - EXPR_PACK_EXPANSION, - EXPR_SIZEOF_PACK, - EXPR_SUBST_NON_TYPE_TEMPLATE_PARM, - EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK, - EXPR_FUNCTION_PARM_PACK, - EXPR_MATERIALIZE_TEMPORARY, - EXPR_CXX_FOLD, - EXPR_CUDA_KERNEL_CALL, - EXPR_ASTYPE, - EXPR_CXX_PROPERTY_REF_EXPR, - EXPR_CXX_PROPERTY_SUBSCRIPT_EXPR, - EXPR_CXX_UUIDOF_EXPR, - EXPR_CXX_UUIDOF_TYPE, - STMT_SEH_LEAVE, - STMT_SEH_EXCEPT, - STMT_SEH_FINALLY, - STMT_SEH_TRY, - STMT_OMP_PARALLEL_DIRECTIVE, - STMT_OMP_SIMD_DIRECTIVE, - STMT_OMP_FOR_DIRECTIVE, - STMT_OMP_FOR_SIMD_DIRECTIVE, - STMT_OMP_SECTIONS_DIRECTIVE, - STMT_OMP_SECTION_DIRECTIVE, - STMT_OMP_SINGLE_DIRECTIVE, - STMT_OMP_MASTER_DIRECTIVE, - STMT_OMP_CRITICAL_DIRECTIVE, - STMT_OMP_PARALLEL_FOR_DIRECTIVE, - STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE, - STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE, - STMT_OMP_TASK_DIRECTIVE, - STMT_OMP_TASKYIELD_DIRECTIVE, - STMT_OMP_BARRIER_DIRECTIVE, - STMT_OMP_TASKWAIT_DIRECTIVE, - STMT_OMP_FLUSH_DIRECTIVE, - STMT_OMP_ORDERED_DIRECTIVE, - STMT_OMP_ATOMIC_DIRECTIVE, - STMT_OMP_TARGET_DIRECTIVE, - STMT_OMP_TARGET_DATA_DIRECTIVE, - STMT_OMP_TARGET_ENTER_DATA_DIRECTIVE, - STMT_OMP_TARGET_EXIT_DATA_DIRECTIVE, - STMT_OMP_TARGET_PARALLEL_DIRECTIVE, - STMT_OMP_TARGET_PARALLEL_FOR_DIRECTIVE, - STMT_OMP_TEAMS_DIRECTIVE, - STMT_OMP_TASKGROUP_DIRECTIVE, - STMT_OMP_CANCELLATION_POINT_DIRECTIVE, - STMT_OMP_CANCEL_DIRECTIVE, - STMT_OMP_TASKLOOP_DIRECTIVE, - STMT_OMP_TASKLOOP_SIMD_DIRECTIVE, - STMT_OMP_DISTRIBUTE_DIRECTIVE, - STMT_OMP_TARGET_UPDATE_DIRECTIVE, - STMT_OMP_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE, - STMT_OMP_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE, - STMT_OMP_DISTRIBUTE_SIMD_DIRECTIVE, - STMT_OMP_TARGET_PARALLEL_FOR_SIMD_DIRECTIVE, - STMT_OMP_TARGET_SIMD_DIRECTIVE, - STMT_OMP_TEAMS_DISTRIBUTE_DIRECTIVE, - STMT_OMP_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE, - STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE, - STMT_OMP_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE, - STMT_OMP_TARGET_TEAMS_DIRECTIVE, - STMT_OMP_TARGET_TEAMS_DISTRIBUTE_DIRECTIVE, - STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_DIRECTIVE, - STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE, - STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE, - EXPR_OMP_ARRAY_SECTION, - EXPR_OBJC_BRIDGED_CAST, - STMT_MS_DEPENDENT_EXISTS, - EXPR_LAMBDA, - STMT_COROUTINE_BODY, - STMT_CORETURN, - EXPR_COAWAIT, - EXPR_COYIELD, - EXPR_DEPENDENT_COAWAIT, - LastElement = EXPR_DEPENDENT_COAWAIT, - }; - - enum class AccessSpecifier - { - Public, - Protected, - Private, - None - }; - } - - struct UnabbreviatedRecord - { - uint32_t Code; - std::vector Operands; - }; - - struct RecordInfo - { - uint32_t Id; - std::string Name; - }; - - struct BlockInfo - { - uint32_t Id; - std::string Name; - std::vector Records; - }; - - struct BitCodeAbbreviationOperand - { - bool IsLiteral; - AbbreviationEncoding Encoding; - uint32_t Value; - }; - - struct BitCodeAbbreviation - { - std::vector Operands; - }; - - struct BitCodeRecord - { - uint32_t Code; - std::vector Values; - }; - - struct BlockContext - { - uint32_t BlockId; - uint32_t AbbreviationLength; - std::vector Abbreviations; - }; - - class LLVMBitCodeParser - { - public: - void Parse(std::istream& stream); - - private: - BlockContext& GetActiveContext(); - std::string_view GetBlockName(uint32_t blockId); - std::string_view GetRecordName(uint32_t blockId, uint32_t code); - void ParseRootBlock(); - void ParseBlockInfoBlock(); - BitCodeAbbreviation ParseDefineAbbreviation(); - UnabbreviatedRecord ParseUnabbreviatedRecord(); - uint64_t ReadSingleOperand(const BitCodeAbbreviationOperand& operand); - BitCodeRecord ParseRecord(uint32_t abbreviationId); - - // Clang AST Parsing - void ParseControlBlock(); - void ParseASTBlock(); - void ParseDeclTypesBlock(); - - void ParseExternalCPPBaseSpecifiers(); - void ParseDeclarationContext(const BitCodeRecord& record); - void ParseDeclaration(const BitCodeRecord& record); - - private: - std::vector m_blocks; - - // Active context - std::unique_ptr m_reader; - std::stack m_context; - }; -} diff --git a/Source/Parse/Main.cpp b/Source/Parse/Main.cpp deleted file mode 100644 index c010ec82..00000000 --- a/Source/Parse/Main.cpp +++ /dev/null @@ -1,26 +0,0 @@ - -#include "LLVMBitCodeParser.h" - -int main() -{ - try - { - auto stream = std::fstream( - "D:/Repos/Soup/Source/Core/out/obj/Clang/Module.pcm", - std::ios_base::in | std::ios_base::binary); - auto parser = Soup::LLVMBitCodeParser(); - parser.Parse(stream); - } - catch (const std::exception& ex) - { - std::cout << std::string("Error: ") + ex.what() << std::endl; - return -1; - } - catch (...) - { - std::cout << "Unknown Error!" << std::endl; - return -1; - } - - return 0; -} \ No newline at end of file diff --git a/Source/Parse/Recipe.json b/Source/Parse/Recipe.json deleted file mode 100644 index f8a1661e..00000000 --- a/Source/Parse/Recipe.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "Parse", - "version": "1.0.0", - "type": "Executable", - "dependencies": [ - ], - "source": [ - "BitReader.cpp", - "LLVMBitCodeParser.cpp", - "Main.cpp" - ] - } \ No newline at end of file diff --git a/Source/TestExtension/RegisterBuildExtension.cpp b/Source/TestExtension/RegisterBuildExtension.cpp deleted file mode 100644 index 4c1d651a..00000000 --- a/Source/TestExtension/RegisterBuildExtension.cpp +++ /dev/null @@ -1,15 +0,0 @@ -module; - -#define DllExport __declspec(dllexport) - -module TestExtension; - -extern "C" -{ - DllExport int RegisterBuildExtension(Soup::Build::IBuildSystem& buildSystem) - { - Opal::Memory::Reference testBuildTask = new TestBuildTask(); - buildSystem.RegisterTask(testBuildTask); - return 0; - } -} \ No newline at end of file diff --git a/Source/TestUtilities/AssertExtensions.h b/Source/TestUtilities/AssertExtensions.h index 24585ca5..b7ce20e1 100644 --- a/Source/TestUtilities/AssertExtensions.h +++ b/Source/TestUtilities/AssertExtensions.h @@ -10,8 +10,8 @@ namespace Soup { public: static void AreEqual( - Build::GraphNodeWrapper& expected, - Build::GraphNodeWrapper& actual) + Build::Extensions::GraphNodeWrapper& expected, + Build::Extensions::GraphNodeWrapper& actual) { Assert::AreEqual( expected.GetTitle(), @@ -42,26 +42,26 @@ namespace Soup } static void AreEqual( - Memory::Reference& expected, - Memory::Reference& actual) + Memory::Reference& expected, + Memory::Reference& actual) { AreEqual( - Build::GraphNodeWrapper(expected), - Build::GraphNodeWrapper(actual)); + Build::Extensions::GraphNodeWrapper(expected), + Build::Extensions::GraphNodeWrapper(actual)); } static void AreEqual( - Memory::Reference& expected, - Build::GraphNodeWrapper& actual) + Memory::Reference& expected, + Build::Extensions::GraphNodeWrapper& actual) { AreEqual( - Build::GraphNodeWrapper(expected), + Build::Extensions::GraphNodeWrapper(expected), actual); } static void AreEqual( - Build::GraphNodeListWrapper& expected, - Build::GraphNodeListWrapper& actual) + Build::Extensions::GraphNodeListWrapper& expected, + Build::Extensions::GraphNodeListWrapper& actual) { Assert::AreEqual( expected.GetSize(), @@ -75,8 +75,8 @@ namespace Soup } static void AreEqual( - std::vector>& expected, - std::vector& actual) + std::vector>& expected, + std::vector& actual) { Assert::AreEqual( expected.size(), diff --git a/Source/TestUtilities/Module.cpp b/Source/TestUtilities/Module.cpp index 829954a8..f61e6f29 100644 --- a/Source/TestUtilities/Module.cpp +++ b/Source/TestUtilities/Module.cpp @@ -10,9 +10,9 @@ export module SoupTestUtilities; import Opal; import SoupCore; import SoupTest; -import SoupEngineDefinition; -import SoupEngineWrapper; -import SoupEngineCore; +import Soup.Build; +import Soup.Build.Extensions; +import Soup.Build.Runtime; using namespace Opal; using namespace SoupTest; diff --git a/Source/TestUtilities/Recipe.toml b/Source/TestUtilities/Recipe.toml index 21edb2cd..5ca041be 100644 --- a/Source/TestUtilities/Recipe.toml +++ b/Source/TestUtilities/Recipe.toml @@ -1,9 +1,11 @@ Name = "SoupTestUtilities" Version = "0.1.0" Dependencies = [ - "../../Dependencies/SoupTest/Assert/", - "../Opal/", - "../Engine/Core/", - "../Core/", + # "../../Dependencies/SoupTest/Assert/", + "SoupTest@0.1.0", + # "../../Dependencies/Opal/Source/", + "Opal@0.1.1", + "../Build/Runtime/", + "../Client/Core/", ] Public = "Module.cpp"