diff --git a/.gitmodules b/.gitmodules index 4499c89..b31da5c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -25,3 +25,6 @@ [submodule "CppOverride"] path = External/CppOverride url = https://github.com/Neko-Box-Coder/CppOverride.git +[submodule "variant"] + path = External/variant + url = https://github.com/mpark/variant.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 37b60f6..4112d9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,7 @@ add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/External/rapidyaml") add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/External/filesystem") add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/External/System2") add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/External/dylib") +add_subdirectory("${CMAKE_CURRENT_LIST_DIR}/External/variant") # Copy cfgpath.h configure_file( "${CMAKE_CURRENT_LIST_DIR}/External/cfgpath/cfgpath.h" @@ -124,6 +125,8 @@ add_library(runcpp2 STATIC "${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/DependencyInfo.cpp" "${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/DependencyLinkProperty.cpp" "${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/DependencySource.cpp" + "${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/GitSource.cpp" + "${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/LocalSource.cpp" "${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/FileProperties.cpp" "${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/FlagsOverrideInfo.cpp" "${CMAKE_CURRENT_LIST_DIR}/Src/runcpp2/Data/ProfilesCommands.cpp" @@ -150,7 +153,7 @@ add_library(runcpp2 STATIC target_include_directories(runcpp2 PUBLIC "${CMAKE_CURRENT_LIST_DIR}/Include") target_link_libraries(runcpp2 PRIVATE ssLogger System2 CppOverride dylib) -target_link_libraries(runcpp2 PUBLIC ghc_filesystem ryml::ryml) +target_link_libraries(runcpp2 PUBLIC ghc_filesystem ryml::ryml mpark_variant) if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(STANDARD_COMPILE_FLAGS "/utf-8;/W1;/DGHC_WIN_DISABLE_WSTRING_STORAGE_TYPE=1") diff --git a/DefaultYAMLs/DefaultScriptInfo.yaml b/DefaultYAMLs/DefaultScriptInfo.yaml index 66d2782..80f3ada 100644 --- a/DefaultYAMLs/DefaultScriptInfo.yaml +++ b/DefaultYAMLs/DefaultScriptInfo.yaml @@ -123,13 +123,23 @@ Dependencies: # The source of getting the dependency (Git, Local) Source: - # Git: Dependency exists in a git server, and needs to be cloned - # Local: Dependency exists in local filesystem - Type: Git + # (Optional) Import dependency configuration from a YAML file + # For Git source: Path is relative to the git repository root + # For Local source: Path is relative to the script directory. + # If neither source exists, local source with root script directory is assumed. + # ImportPath: "config/dependency.yaml" - # Git URL for Git type, path to a directory for Local type - Value: "https://github.com/MyUser/MyLibrary.git" - + # Git: Dependency or import YAML file exists in a git server, and needs to be cloned. + Git: + # Git repository URL + URL: "https://github.com/MyUser/MyLibrary.git" + + # Local: Dependency or import YAML file exists in local filesystem + # Local: + # # Path to the library directory + # Path: "./libs/LocalLibrary" + + # Library Type (Static, Object, Shared, Header) LibraryType: Static diff --git a/DefaultYAMLs/OldScriptInfoSchema.json b/DefaultYAMLs/OldScriptInfoSchema.json deleted file mode 100644 index 4649b14..0000000 --- a/DefaultYAMLs/OldScriptInfoSchema.json +++ /dev/null @@ -1,192 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Script dependencies", - "type": "object", - "properties": - { - "Language": { "type": "string" }, - "RequiredProfiles": - { - "type": "object", - "patternProperties": - { - "^.*$": - { - "type": "array", - "items": { "type":"string" } - } - }, - "additionalProperties": false - }, - "OverrideCompileFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": - { - "type": "object", - "patternProperties": - { - "^.*$": - { - "type": "object", - "properties": - { - "Remove": { "type": "string" }, - "Append": { "type": "string" } - }, - "additionalProperties": false, - "required": ["Remove", "Append"] - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "OverrideLinkFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": - { - "type": "object", - "patternProperties": - { - "^.*$": - { - "type": "object", - "properties": - { - "Remove": { "type": "string" }, - "Append": { "type": "string" } - }, - "additionalProperties": false, - "required": ["Remove", "Append"] - } - } - }, - "additionalProperties": false - }, - "additionalProperties": false - }, - "Dependencies": - { - "type": "array", - "items": - { - "type": "object", - "properties": - { - "Name": { "type": "string" }, - "Platforms": - { - "type": "array", - "items": { "type":"string" } - }, - "Source": - { - "type": "object", - "properties": - { - "Type": - { - "type": "string", - "enum": ["Git", "Local"] - }, - "Value": { "type": "string" } - }, - "required": ["Type", "Value"] - }, - "LibraryType": - { - "type": "string", - "enum": ["Static", "Object", "Shared", "Header"] - }, - "IncludePaths": - { - "type": "array", - "items": { "type":"string" } - }, - "LinkProperties": - { - "type": "object", - "patternProperties": - { - "^.*$": - { - "type": "object", - "properties": - { - "SearchLibraryNames": - { - "type": "array", - "items": { "type":"string" } - }, - "ExcludeLibraryNames": - { - "type": "array", - "items": { "type":"string" } - }, - "SearchDirectories": - { - "type": "array", - "items": { "type":"string" } - }, - "AdditionalLinkOptions": - { - "type": "object", - "properties": - { - "^.*$": - { - "type": "array", - "items": { "type":"string" } - } - } - } - }, - "required": ["SearchLibraryNames", "SearchDirectories"], - "additionalProperties": false - } - }, - "additionalProperties": false - }, - "Setup": - { - "type": "object", - "patternProperties": - { - "^.*$": - { - "type": "object", - "patternProperties": - { - "^.*$": - { - "type": "array", - "items": { "type":"string" } - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false - } - }, - "additionalProperties": false, - "required": - [ - "Name", - "Platforms", - "Source", - "LibraryType", - "LinkProperties" - ], - "uniqueItems": true - } - } - } -} \ No newline at end of file diff --git a/DefaultYAMLs/OldUserConfigSchema.json b/DefaultYAMLs/OldUserConfigSchema.json deleted file mode 100644 index a67865a..0000000 --- a/DefaultYAMLs/OldUserConfigSchema.json +++ /dev/null @@ -1,383 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Compiler profiles", - "type": "object", - "properties": - { - "PreferredProfile": { "type": "string" }, - "Profiles": - { - "type": "array", - "items": - { - "type": "object", - "properties": - { - "Name": { "type": "string" }, - "NameAliases": - { - "type": "array", - "items": { "type":"string" }, - "uniqueItems": true - }, - "FileExtensions" : - { - "type": "array", - "items": { "type":"string" }, - "uniqueItems": true - }, - "Languages": - { - "type": "array", - "items": { "type":"string" }, - "uniqueItems": true - }, - "SetupSteps" : - { - "type": "object", - "patternProperties": - { - "^.*$": - { - "type": "array", - "items": { "type":"string" } - } - }, - "additionalProperties": false - }, - "ObjectLinkFile": - { - "type": "object", - "properties": - { - "Prefix": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "Extension": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - } - }, - "additionalProperties": false, - "required": - [ - "Prefix", - "Extension" - ] - }, - "SharedLinkFile": - { - "type": "object", - "properties": - { - "Prefix": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "Extension": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - } - }, - "additionalProperties": false, - "required": - [ - "Prefix", - "Extension" - ] - }, - "SharedLibraryFile": - { - "type": "object", - "properties": - { - "Prefix": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "Extension": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - } - }, - "additionalProperties": false, - "required": - [ - "Prefix", - "Extension" - ] - }, - "StaticLinkFile": - { - "type": "object", - "properties": - { - "Prefix": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "Extension": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - } - }, - "additionalProperties": false, - "required": - [ - "Prefix", - "Extension" - ] - }, - "DebugSymbolFile": - { - "type": "object", - "properties": - { - "Prefix": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "Extension": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - } - }, - "additionalProperties": false, - "required": - [ - "Prefix", - "Extension" - ] - }, - "Compiler": - { - "type": "object", - "properties": - { - "EnvironmentSetup" : - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string"}, - "additionalProperties": false - }, - "additionalProperties": false - }, - "Executable": { "type": "string" }, - "CheckExistence": { "type": "string" }, - "DefaultCompileFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "ExecutableCompileFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "StaticLibCompileFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "SharedLibCompileFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "CompileArgs": - { - "type": "object", - "properties": - { - "CompilePart": { "type": "string" }, - "IncludePart": { "type": "string" }, - "InputPart": { "type": "string" }, - "OutputPart": { "type": "string" } - }, - "required": - [ - "CompilePart", - "IncludePart", - "InputPart", - "OutputPart" - ] - } - }, - "required": - [ - "Executable", - "CheckExistence", - "DefaultCompileFlags", - "ExecutableCompileFlags", - "StaticLibCompileFlags", - "SharedLibCompileFlags", - "CompileArgs" - ] - }, - "Linker": - { - "type": "object", - "properties": - { - "EnvironmentSetup" : - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string"}, - "additionalProperties": false - }, - "additionalProperties": false - }, - "Executable": { "type": "string" }, - "CheckExistence": { "type": "string" }, - "DefaultLinkFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "ExecutableLinkFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "StaticLibLinkFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "SharedLibLinkFlags": - { - "type": "object", - "patternProperties": - { - "^.*$": { "type": "string" } - }, - "additionalProperties": false - }, - "LinkArgs": - { - "type": "object", - "properties": - { - "OutputPart": { "type": "string" }, - "LinkPart": { "type": "string" } - }, - "required": - [ - "OutputPart", - "LinkPart" - ] - } - }, - "required": - [ - "Executable", - "CheckExistence", - "DefaultLinkFlags", - "ExecutableLinkFlags", - "StaticLibLinkFlags", - "SharedLibLinkFlags", - "LinkArgs" - ] - } - }, - "required": - [ - "Name", - "FileExtensions", - "Languages", - "ObjectLinkFile", - "SharedLinkFile", - "SharedLibraryFile", - "StaticLinkFile", - "Compiler", - "Linker" - ], - "uniqueItems": true - } - } - }, - "required": ["Profiles"] -} diff --git a/Examples/TestImport.yaml b/Examples/TestImport.yaml new file mode 100644 index 0000000..08bacc1 --- /dev/null +++ b/Examples/TestImport.yaml @@ -0,0 +1,11 @@ +Name: "System2.cpp" +Platforms: [DefaultPlatform] +Source: + Git: + URL: "https://github.com/Neko-Box-Coder/System2.cpp.git" +LibraryType: Header +IncludePaths: [".", "./External/System2"] +Setup: + DefaultPlatform: + DefaultProfile: + - "git submodule update --init --recursive" diff --git a/Examples/test.cpp b/Examples/test.cpp index 00cda4b..58919c4 100755 --- a/Examples/test.cpp +++ b/Examples/test.cpp @@ -63,8 +63,8 @@ PassScriptPath: true - Name: ssLogger Platforms: [Windows, Linux, MacOS] Source: - Type: Git - Value: "https://github.com/Neko-Box-Coder/ssLogger.git" + Git: + URL: "https://github.com/Neko-Box-Coder/ssLogger.git" LibraryType: Shared IncludePaths: ["Include"] LinkProperties: @@ -89,16 +89,20 @@ PassScriptPath: true - "./Include/ssLogger/ssLog.hpp" - Name: System2.cpp - Platforms: [DefaultPlatform] Source: - Type: Git - Value: "https://github.com/Neko-Box-Coder/System2.cpp.git" - LibraryType: Header - IncludePaths: [".", "./External/System2"] - Setup: - DefaultPlatform: - DefaultProfile: - - "git submodule update --init --recursive" + ImportPath: "./TestImport.yaml" + +# - Name: System2.cpp +# Platforms: [DefaultPlatform] +# Source: +# Git: +# URL: "https://github.com/Neko-Box-Coder/System2.cpp.git" +# LibraryType: Header +# IncludePaths: [".", "./External/System2"] +# Setup: +# DefaultPlatform: +# DefaultProfile: +# - "git submodule update --init --recursive" */ diff --git a/External/variant b/External/variant new file mode 160000 index 0000000..23cb94f --- /dev/null +++ b/External/variant @@ -0,0 +1 @@ +Subproject commit 23cb94f027d4ef33bf48133acc2695c7e5c6f1e7 diff --git a/Include/runcpp2/Data/DependencySource.hpp b/Include/runcpp2/Data/DependencySource.hpp index 4ba0328..d1b7d8c 100644 --- a/Include/runcpp2/Data/DependencySource.hpp +++ b/Include/runcpp2/Data/DependencySource.hpp @@ -1,10 +1,14 @@ #ifndef RUNCPP2_DATA_DEPENDENCY_SOURCE_HPP #define RUNCPP2_DATA_DEPENDENCY_SOURCE_HPP -#include "runcpp2/Data/DependencySourceType.hpp" +#include "runcpp2/Data/GitSource.hpp" +#include "runcpp2/Data/LocalSource.hpp" #include "runcpp2/YamlLib.hpp" +#include "ghc/filesystem.hpp" +#include "mpark/variant.hpp" -#include +#include +#include namespace runcpp2 { @@ -13,8 +17,9 @@ namespace runcpp2 class DependencySource { public: - DependencySourceType Type; - std::string Value; + mpark::variant Source; + ghc::filesystem::path ImportPath; + std::vector> ImportedSources; bool ParseYAML_Node(ryml::ConstNodeRef& node); std::string ToString(std::string indentation) const; diff --git a/Include/runcpp2/Data/DependencySourceType.hpp b/Include/runcpp2/Data/DependencySourceType.hpp deleted file mode 100644 index 53d149a..0000000 --- a/Include/runcpp2/Data/DependencySourceType.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef RUNCPP2_DATA_DEPENDENCY_SOURCE_TYPE_HPP -#define RUNCPP2_DATA_DEPENDENCY_SOURCE_TYPE_HPP - -namespace runcpp2 -{ - namespace Data - { - enum class DependencySourceType - { - GIT, - LOCAL, - COUNT - }; - } -} - -#endif \ No newline at end of file diff --git a/Include/runcpp2/Data/GitSource.hpp b/Include/runcpp2/Data/GitSource.hpp new file mode 100644 index 0000000..3c83886 --- /dev/null +++ b/Include/runcpp2/Data/GitSource.hpp @@ -0,0 +1,23 @@ +#ifndef RUNCPP2_DATA_GIT_SOURCE_HPP +#define RUNCPP2_DATA_GIT_SOURCE_HPP + +#include "runcpp2/YamlLib.hpp" +#include + +namespace runcpp2 +{ + namespace Data + { + class GitSource + { + public: + std::string URL; + + bool ParseYAML_Node(ryml::ConstNodeRef& node); + std::string ToString(std::string indentation) const; + bool Equals(const GitSource& other) const; + }; + } +} + +#endif \ No newline at end of file diff --git a/Include/runcpp2/Data/LocalSource.hpp b/Include/runcpp2/Data/LocalSource.hpp new file mode 100644 index 0000000..0322c11 --- /dev/null +++ b/Include/runcpp2/Data/LocalSource.hpp @@ -0,0 +1,23 @@ +#ifndef RUNCPP2_DATA_LOCAL_SOURCE_HPP +#define RUNCPP2_DATA_LOCAL_SOURCE_HPP + +#include "runcpp2/YamlLib.hpp" +#include + +namespace runcpp2 +{ + namespace Data + { + class LocalSource + { + public: + std::string Path; + + bool ParseYAML_Node(ryml::ConstNodeRef& node); + std::string ToString(std::string indentation) const; + bool Equals(const LocalSource& other) const; + }; + } +} + +#endif \ No newline at end of file diff --git a/Include/runcpp2/DependenciesHelper.hpp b/Include/runcpp2/DependenciesHelper.hpp index a9aeda5..bfd83c8 100644 --- a/Include/runcpp2/DependenciesHelper.hpp +++ b/Include/runcpp2/DependenciesHelper.hpp @@ -40,6 +40,13 @@ namespace runcpp2 const std::vector& dependenciesCopiesPaths, const Data::Profile& profile, std::vector& outBinariesPaths); + + bool HandleImport( Data::DependencyInfo& dependency, + const ghc::filesystem::path& basePath); + + bool ResolveImports(Data::ScriptInfo& scriptInfo, + const ghc::filesystem::path& scriptPath, + const ghc::filesystem::path& buildDir); } #endif diff --git a/Include/runcpp2/PipelineSteps.hpp b/Include/runcpp2/PipelineSteps.hpp index 7e21e4a..9f20b53 100644 --- a/Include/runcpp2/PipelineSteps.hpp +++ b/Include/runcpp2/PipelineSteps.hpp @@ -54,6 +54,10 @@ namespace runcpp2 BuildsManager& outBuildsManager, ghc::filesystem::path& outBuildDir, IncludeManager& outIncludeManager); + + PipelineResult ResolveScriptImports(Data::ScriptInfo& scriptInfo, + const ghc::filesystem::path& scriptPath, + const ghc::filesystem::path& buildDir); PipelineResult CheckScriptInfoChanges( const ghc::filesystem::path& buildDir, const Data::ScriptInfo& scriptInfo, diff --git a/Src/Tests/CMakeLists.txt b/Src/Tests/CMakeLists.txt index 9674f80..65ef931 100644 --- a/Src/Tests/CMakeLists.txt +++ b/Src/Tests/CMakeLists.txt @@ -18,7 +18,7 @@ target_compile_definitions(IncludeManagerTest PRIVATE INTERNAL_RUNCPP2_UNIT_TEST function(create_data_test TEST_NAME) add_executable("${TEST_NAME}" "${CMAKE_CURRENT_LIST_DIR}/Data/${TEST_NAME}.cpp") target_compile_options("${TEST_NAME}" PRIVATE "${STANDARD_COMPILE_FLAGS}") - target_compile_definitions("${TEST_NAME}" PRIVATE INTERNAL_RUNCPP2_UNIT_TESTS=1) + target_compile_definitions("${TEST_NAME}" PRIVATE INTERNAL_RUNCPP2_UNIT_TESTS=1 TERMCOLOR_USE_ANSI_ESCAPE_SEQUENCES=1) target_link_libraries("${TEST_NAME}" PUBLIC runcpp2 ssTest) endfunction() diff --git a/Src/Tests/Data/DependencyInfoTest.cpp b/Src/Tests/Data/DependencyInfoTest.cpp index 1ed13f8..49a6363 100644 --- a/Src/Tests/Data/DependencyInfoTest.cpp +++ b/Src/Tests/Data/DependencyInfoTest.cpp @@ -19,8 +19,8 @@ int main(int argc, char** argv) - Windows - Unix Source: - Type: Git - Value: https://github.com/user/mylibrary.git + Git: + URL: https://github.com/user/mylibrary.git LibraryType: Shared IncludePaths: - include @@ -101,12 +101,10 @@ int main(int argc, char** argv) ssTEST_OUTPUT_ASSERT("Include paths count", dependencyInfo.IncludePaths.size() == 2); //Verify Source - ssTEST_OUTPUT_ASSERT( "Source type", - dependencyInfo.Source.Type == - runcpp2::Data::DependencySourceType::GIT); - ssTEST_OUTPUT_ASSERT( "Source value", - dependencyInfo.Source.Value == - "https://github.com/user/mylibrary.git"); + const runcpp2::Data::GitSource* git = + mpark::get_if(&dependencyInfo.Source.Source); + ssTEST_OUTPUT_ASSERT("Should be Git source", git != nullptr); + ssTEST_OUTPUT_ASSERT("URL", git->URL == "https://github.com/user/mylibrary.git"); //Verify Link Properties ssTEST_OUTPUT_SETUP diff --git a/Src/Tests/Data/DependencySourceTest.cpp b/Src/Tests/Data/DependencySourceTest.cpp index e948d82..38e070a 100644 --- a/Src/Tests/Data/DependencySourceTest.cpp +++ b/Src/Tests/Data/DependencySourceTest.cpp @@ -9,13 +9,13 @@ int main(int argc, char** argv) ssTEST_INIT_TEST_GROUP(); - ssTEST("DependencySource Should Parse Valid YAML") + ssTEST("DependencySource Should Parse Git Source") { ssTEST_OUTPUT_SETUP ( const char* yamlStr = R"( - Type: Git - Value: https://github.com/user/repo.git + Git: + URL: https://github.com/user/repo.git )"; ryml::Tree tree = ryml::parse_in_arena(c4::to_csubstr(yamlStr)); @@ -33,9 +33,54 @@ int main(int argc, char** argv) ssTEST_OUTPUT_ASSERT("ParseYAML_Node should succeed", parseResult); //Verify parsed values - ssTEST_OUTPUT_ASSERT( "Type", - dependencySource.Type == runcpp2::Data::DependencySourceType::GIT); - ssTEST_OUTPUT_ASSERT("Value", dependencySource.Value, "https://github.com/user/repo.git"); + const runcpp2::Data::GitSource* git = + mpark::get_if(&dependencySource.Source); + ssTEST_OUTPUT_ASSERT("Should be Git source", git != nullptr); + ssTEST_OUTPUT_ASSERT("URL", git->URL == "https://github.com/user/repo.git"); + + //Test ToString() and Equals() + ssTEST_OUTPUT_EXECUTION + ( + std::string yamlOutput = dependencySource.ToString(""); + ryml::Tree outputTree = ryml::parse_in_arena(ryml::to_csubstr(yamlOutput)); + + runcpp2::Data::DependencySource parsedOutput; + nodeRef = outputTree.rootref(); + parsedOutput.ParseYAML_Node(nodeRef); + ); + + ssTEST_OUTPUT_ASSERT( "Parsed output should equal original", + dependencySource.Equals(parsedOutput)); + }; + + ssTEST("DependencySource Should Parse Local Source") + { + ssTEST_OUTPUT_SETUP + ( + const char* yamlStr = R"( + Local: + Path: ../external/mylib + )"; + + ryml::Tree tree = ryml::parse_in_arena(c4::to_csubstr(yamlStr)); + ryml::ConstNodeRef root = tree.rootref(); + + runcpp2::Data::DependencySource dependencySource; + ); + + ssTEST_OUTPUT_EXECUTION + ( + ryml::ConstNodeRef nodeRef = root; + bool parseResult = dependencySource.ParseYAML_Node(nodeRef); + ); + + ssTEST_OUTPUT_ASSERT("ParseYAML_Node should succeed", parseResult); + + //Verify parsed values + const runcpp2::Data::LocalSource* local = + mpark::get_if(&dependencySource.Source); + ssTEST_OUTPUT_ASSERT("Should be Local source", local != nullptr); + ssTEST_OUTPUT_ASSERT("Path", local->Path == "../external/mylib"); //Test ToString() and Equals() ssTEST_OUTPUT_EXECUTION diff --git a/Src/Tests/Data/ScriptInfoTest.cpp b/Src/Tests/Data/ScriptInfoTest.cpp index ba755ff..af3ef74 100644 --- a/Src/Tests/Data/ScriptInfoTest.cpp +++ b/Src/Tests/Data/ScriptInfoTest.cpp @@ -90,8 +90,8 @@ int main(int argc, char** argv) - MSVC - GCC Source: - Type: Git - Value: https://github.com/user/mylib.git + Git: + URL: https://github.com/user/mylib.git LibraryType: Shared IncludePaths: - include diff --git a/Src/runcpp2/Data/DependencyInfo.cpp b/Src/runcpp2/Data/DependencyInfo.cpp index c4d852d..2e36640 100644 --- a/Src/runcpp2/Data/DependencyInfo.cpp +++ b/Src/runcpp2/Data/DependencyInfo.cpp @@ -6,7 +6,33 @@ bool runcpp2::Data::DependencyInfo::ParseYAML_Node(ryml::ConstNodeRef& node) { INTERNAL_RUNCPP2_SAFE_START(); - + + //If import is needed, we only need to parse the Source section + do + { + if(!ExistAndHasChild(node, "Source")) + { + ssLOG_ERROR("DependencyInfo: Missing Source"); + return false; + } + + ryml::ConstNodeRef sourceNode = node["Source"]; + + if(!ExistAndHasChild(sourceNode, "ImportPath")) + break; + + if(!Source.ParseYAML_Node(sourceNode)) + { + ssLOG_ERROR("DependencyInfo: Failed to parse Source"); + return false; + } + + ssLOG_DEBUG("DependencyInfo: Importing from " << Source.ImportPath.string()); + ssLOG_DEBUG("Skipping the rest of the DependencyInfo"); + return true; + } + while(false); + std::vector requirements = { NodeRequirement("Name", ryml::NodeType_e::KEYVAL, true, false), diff --git a/Src/runcpp2/Data/DependencySource.cpp b/Src/runcpp2/Data/DependencySource.cpp index 0ee656d..a813b4c 100644 --- a/Src/runcpp2/Data/DependencySource.cpp +++ b/Src/runcpp2/Data/DependencySource.cpp @@ -7,53 +7,123 @@ bool runcpp2::Data::DependencySource::ParseYAML_Node(ryml::ConstNodeRef& node) { INTERNAL_RUNCPP2_SAFE_START(); - std::vector requirements = + if(ExistAndHasChild(node, "ImportPath")) { - NodeRequirement("Type", ryml::NodeType_e::KEYVAL, true, false), - NodeRequirement("Value", ryml::NodeType_e::KEYVAL, true, false) - }; + std::string importPathStr; + node["ImportPath"] >> importPathStr; + ImportPath = importPathStr; + + if(ImportPath.is_absolute()) + { + ssLOG_ERROR("DependencySource: ImportPath must be relative: " << ImportPath.string()); + return false; + } + } - if(!CheckNodeRequirements(node, requirements)) + if(ExistAndHasChild(node, "Git")) { - ssLOG_ERROR("DependencySource: Failed to meet requirements"); - return false; + if(ExistAndHasChild(node, "Local")) + { + ssLOG_ERROR("DependencySource: Both Git and Local sources found"); + return false; + } + + GitSource gitSource; + ryml::ConstNodeRef gitNode = node["Git"]; + if(!gitSource.ParseYAML_Node(gitNode)) + return false; + Source = gitSource; + return true; } - - static_assert((int)DependencySourceType::COUNT == 2, ""); - - if(node["Type"].val() == "Git") - Type = DependencySourceType::GIT; - else if(node["Type"].val() == "Local") - Type = DependencySourceType::LOCAL; - else + else if(ExistAndHasChild(node, "Local")) { - ssLOG_ERROR("DependencySource: Type is invalid"); - return false; + if(ExistAndHasChild(node, "Git")) + { + ssLOG_ERROR("DependencySource: Both Git and Local sources found"); + return false; + } + + LocalSource localSource; + ryml::ConstNodeRef localNode = node["Local"]; + if(!localSource.ParseYAML_Node(localNode)) + return false; + Source = localSource; + return true; + } + //If no source is found, we need to check if it's an imported source. + //If so, we assume it's a local source with path "./" + else if(!ImportPath.empty()) + { + LocalSource localSource; + localSource.Path = "./"; + Source = localSource; + return true; } - node["Value"] >> Value; - return true; + ssLOG_ERROR("DependencySource: Neither Git nor Local source found"); + return false; INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false); } std::string runcpp2::Data::DependencySource::ToString(std::string indentation) const -{ +{ std::string out; + if(!ImportPath.empty()) + out += indentation + "ImportPath: " + GetEscapedYAMLString(ImportPath.string()) + "\n"; - static_assert((int)DependencySourceType::COUNT == 2, ""); - - if(Type == DependencySourceType::GIT) - out += indentation + "Type: Git\n"; - else if(Type == DependencySourceType::LOCAL) - out += indentation + "Type: Local\n"; - - out += indentation + "Value: " + GetEscapedYAMLString(Value) + "\n"; - + if(mpark::get_if(&Source)) + { + const GitSource* git = mpark::get_if(&Source); + out += git->ToString(indentation); + } + else if(mpark::get_if(&Source)) + { + const LocalSource* local = mpark::get_if(&Source); + out += local->ToString(indentation); + } + else + { + ssLOG_ERROR("Invalid DependencySource type"); + return ""; + } return out; } bool runcpp2::Data::DependencySource::Equals(const DependencySource& other) const { - return Type == other.Type && Value == other.Value; + if(ImportPath != other.ImportPath) + return false; + + if(mpark::get_if(&Source)) + { + if(mpark::get_if(&other.Source)) + { + const GitSource* git = mpark::get_if(&Source); + const GitSource* otherGit = mpark::get_if(&other.Source); + return git->Equals(*otherGit); + } + else + { + ssLOG_ERROR("Invalid DependencySource type"); + return false; + } + } + else if(mpark::get_if(&Source)) + { + if(mpark::get_if(&other.Source)) + { + const LocalSource* local = mpark::get_if(&Source); + const LocalSource* otherLocal = mpark::get_if(&other.Source); + return local->Equals(*otherLocal); + } + else + { + ssLOG_ERROR("Invalid DependencySource type"); + return false; + } + } + + ssLOG_ERROR("Invalid DependencySource type"); + return false; } diff --git a/Src/runcpp2/Data/GitSource.cpp b/Src/runcpp2/Data/GitSource.cpp new file mode 100644 index 0000000..4481e21 --- /dev/null +++ b/Src/runcpp2/Data/GitSource.cpp @@ -0,0 +1,38 @@ +#include "runcpp2/Data/GitSource.hpp" +#include "runcpp2/Data/ParseCommon.hpp" +#include "runcpp2/ParseUtil.hpp" +#include "ssLogger/ssLog.hpp" + +bool runcpp2::Data::GitSource::ParseYAML_Node(ryml::ConstNodeRef& node) +{ + INTERNAL_RUNCPP2_SAFE_START(); + + std::vector requirements = + { + NodeRequirement("URL", ryml::NodeType_e::KEYVAL, true, false) + }; + + if(!CheckNodeRequirements(node, requirements)) + { + ssLOG_ERROR("GitSource: Failed to meet requirements"); + return false; + } + + node["URL"] >> URL; + return true; + + INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false); +} + +std::string runcpp2::Data::GitSource::ToString(std::string indentation) const +{ + std::string out; + out += indentation + "Git:\n"; + out += indentation + " URL: " + GetEscapedYAMLString(URL) + "\n"; + return out; +} + +bool runcpp2::Data::GitSource::Equals(const GitSource& other) const +{ + return URL == other.URL; +} \ No newline at end of file diff --git a/Src/runcpp2/Data/LocalSource.cpp b/Src/runcpp2/Data/LocalSource.cpp new file mode 100644 index 0000000..dcb1fe4 --- /dev/null +++ b/Src/runcpp2/Data/LocalSource.cpp @@ -0,0 +1,38 @@ +#include "runcpp2/Data/LocalSource.hpp" +#include "runcpp2/Data/ParseCommon.hpp" +#include "runcpp2/ParseUtil.hpp" +#include "ssLogger/ssLog.hpp" + +bool runcpp2::Data::LocalSource::ParseYAML_Node(ryml::ConstNodeRef& node) +{ + INTERNAL_RUNCPP2_SAFE_START(); + + std::vector requirements = + { + NodeRequirement("Path", ryml::NodeType_e::KEYVAL, true, false) + }; + + if(!CheckNodeRequirements(node, requirements)) + { + ssLOG_ERROR("LocalSource: Failed to meet requirements"); + return false; + } + + node["Path"] >> Path; + return true; + + INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false); +} + +std::string runcpp2::Data::LocalSource::ToString(std::string indentation) const +{ + std::string out; + out += indentation + "Local:\n"; + out += indentation + " Path: " + GetEscapedYAMLString(Path) + "\n"; + return out; +} + +bool runcpp2::Data::LocalSource::Equals(const LocalSource& other) const +{ + return Path == other.Path; +} \ No newline at end of file diff --git a/Src/runcpp2/DependenciesHelper.cpp b/Src/runcpp2/DependenciesHelper.cpp index fe72afa..1150289 100644 --- a/Src/runcpp2/DependenciesHelper.cpp +++ b/Src/runcpp2/DependenciesHelper.cpp @@ -1,79 +1,175 @@ #include "runcpp2/DependenciesHelper.hpp" -#include "ghc/filesystem.hpp" #include "runcpp2/PlatformUtil.hpp" #include "runcpp2/StringUtil.hpp" +#include "runcpp2/ParseUtil.hpp" + +#include "ghc/filesystem.hpp" #include "ssLogger/ssLog.hpp" #include namespace { + bool GetDependencyPath( const runcpp2::Data::DependencyInfo& dependency, + const ghc::filesystem::path& scriptPath, + const ghc::filesystem::path& buildDir, + ghc::filesystem::path& outCopyPath, + ghc::filesystem::path& outSourcePath) + { + ssLOG_FUNC_DEBUG(); + + ghc::filesystem::path scriptDirectory = scriptPath.parent_path(); + + const runcpp2::Data::DependencySource& currentSource = dependency.Source; + + if(mpark::get_if(¤tSource.Source)) + { + const runcpp2::Data::GitSource* git = + mpark::get_if(¤tSource.Source); + + size_t lastSlashFoundIndex = git->URL.find_last_of("/"); + size_t lastDotGitFoundIndex = git->URL.find_last_of(".git"); + + if( lastSlashFoundIndex == std::string::npos || + lastDotGitFoundIndex == std::string::npos || + lastDotGitFoundIndex < lastSlashFoundIndex) + { + ssLOG_ERROR("Invalid git url: " << git->URL); + return false; + } + else + { + std::string gitRepoName = + //+1 for / to not include it + git->URL.substr(lastSlashFoundIndex + 1, + //-1 for slash + lastDotGitFoundIndex - 1 - + //-(size - 1) for .git + (std::string(".git").size() - 1) - + lastSlashFoundIndex); + + outCopyPath = (buildDir / gitRepoName); + outSourcePath.clear(); + } + } + else if(mpark::get_if(¤tSource.Source)) + { + const runcpp2::Data::LocalSource* local = + mpark::get_if(¤tSource.Source); + + std::string localDepDirectoryName; + std::string curPath = local->Path; + + if(curPath.back() == '/') + curPath.pop_back(); + + if(!ghc::filesystem::is_directory(curPath)) + { + ssLOG_ERROR("Local dependency path is not a directory: " << curPath); + return false; + } + + localDepDirectoryName = ghc::filesystem::path(curPath).filename().string(); + + if(ghc::filesystem::path(curPath).is_relative()) + outSourcePath = (scriptDirectory / local->Path); + else + outSourcePath = (local->Path); + + + if(currentSource.ImportPath.empty()) + outCopyPath = (buildDir / localDepDirectoryName); + else + outCopyPath = outSourcePath; + } + + return true; + } + + bool PopulateLocalDependency( const runcpp2::Data::DependencyInfo& dependency, + const ghc::filesystem::path& copyPath, + const ghc::filesystem::path& sourcePath, + const ghc::filesystem::path& buildDir, + bool& outPrePopulated) + { + std::error_code e; + + if(ghc::filesystem::exists(copyPath, e)) + { + if(!ghc::filesystem::is_directory(copyPath, e)) + { + ssLOG_ERROR("Dependency path is a file: " << copyPath.string()); + ssLOG_ERROR("It should be a folder instead"); + return false; + } + outPrePopulated = true; + return true; + } + else + { + if(mpark::get_if(&(dependency.Source.Source))) + { + const runcpp2::Data::GitSource* git = + mpark::get_if(&(dependency.Source.Source)); + + std::string gitCloneCommand = "git clone " + git->URL; + + ssLOG_INFO("Running git clone command: " << gitCloneCommand << " in " << + buildDir.string()); + + int returnCode = 0; + std::string output; + if(!runcpp2::RunCommandAndGetOutput(gitCloneCommand, + output, + returnCode, + buildDir.string())) + { + ssLOG_ERROR("Failed to run git clone with result: " << returnCode); + ssLOG_ERROR("Output: \n" << output); + return false; + } + else + ssLOG_INFO("Output: \n" << output); + } + else if(mpark::get_if(&(dependency.Source.Source))) + { + //We don't need to copy the local directory if we just need the import file + if(dependency.Source.ImportPath.empty()) + ghc::filesystem::copy(copyPath, sourcePath, e); + } + + outPrePopulated = false; + return true; + } + } + bool PopulateLocalDependencies( const std::vector& dependencies, const std::vector& dependenciesCopiesPaths, const std::vector& dependenciesSourcesPaths, const ghc::filesystem::path& buildDir, std::vector& outPrePopulated) { - std::error_code _; + outPrePopulated.resize(dependencies.size()); + for(int i = 0; i < dependencies.size(); ++i) { - if(ghc::filesystem::exists(dependenciesCopiesPaths.at(i), _)) + if(!dependencies.at(i)->Source.ImportPath.empty()) { - if(!ghc::filesystem::is_directory(dependenciesCopiesPaths.at(i), _)) - { - ssLOG_ERROR("Dependency path is a file: " << dependenciesCopiesPaths.at(i)); - ssLOG_ERROR("It should be a folder instead"); - return false; - } - outPrePopulated.push_back(true); + ssLOG_ERROR("Dependency import not resolved before populating."); + return false; } - else + + bool prePopulated = false; + if(!PopulateLocalDependency(*dependencies.at(i), + ghc::filesystem::path(dependenciesCopiesPaths.at(i)), + ghc::filesystem::path(dependenciesSourcesPaths.at(i)), + buildDir, + prePopulated)) { - static_assert((int)runcpp2::Data::DependencySourceType::COUNT == 2, ""); - - switch(dependencies.at(i)->Source.Type) - { - case runcpp2::Data::DependencySourceType::GIT: - { - std::string gitCloneCommand = - "git clone " + dependencies.at(i)->Source.Value; - - ssLOG_INFO( "Running git clone command: " << gitCloneCommand << " in " << - buildDir.string()); - - int returnCode = 0; - std::string output; - if(!runcpp2::RunCommandAndGetOutput(gitCloneCommand, - output, - returnCode, - buildDir.string())) - { - ssLOG_ERROR("Failed to run git clone with result: " << returnCode); - ssLOG_ERROR("Output: \n" << output); - return false; - } - else - ssLOG_INFO("Output: \n" << output); - - break; - } - - case runcpp2::Data::DependencySourceType::LOCAL: - { - std::string sourcePath = dependenciesSourcesPaths.at(i); - std::string destinationPath = dependenciesCopiesPaths.at(i); - - //Copy the folder - ghc::filesystem::copy(destinationPath, sourcePath, _); - break; - } - - case runcpp2::Data::DependencySourceType::COUNT: - return false; - } - - outPrePopulated.push_back(false); + return false; } + + outPrePopulated.at(i) = prePopulated; } return true; @@ -261,67 +357,22 @@ bool runcpp2::GetDependenciesPaths( const std::vector& av { ssLOG_FUNC_DEBUG(); - ghc::filesystem::path scriptDirectory = scriptPath.parent_path(); - for(int i = 0; i < availableDependencies.size(); ++i) { - const Data::DependencySource& currentSource = availableDependencies.at(i)->Source; - - static_assert((int)Data::DependencySourceType::COUNT == 2, ""); + ghc::filesystem::path currentCopyPath; + ghc::filesystem::path currentSourcePath; - switch(currentSource.Type) + if(!GetDependencyPath( *availableDependencies.at(i), + scriptPath, + buildDir, + currentCopyPath, + currentSourcePath)) { - case Data::DependencySourceType::GIT: - { - size_t lastSlashFoundIndex = currentSource.Value.find_last_of("/"); - size_t lastDotGitFoundIndex = currentSource.Value.find_last_of(".git"); - - if( lastSlashFoundIndex == std::string::npos || - lastDotGitFoundIndex == std::string::npos || - lastDotGitFoundIndex < lastSlashFoundIndex) - { - ssLOG_ERROR("Invalid git url: " << currentSource.Value); - return false; - } - else - { - std::string gitRepoName = - //+1 for / to not include it - currentSource.Value.substr( lastSlashFoundIndex + 1, - //-1 for slash - lastDotGitFoundIndex - 1 - - //-(size - 1) for .git - (std::string(".git").size() - 1) - - lastSlashFoundIndex); - - outCopiesPaths.push_back(buildDir / gitRepoName); - outSourcesPaths.push_back(""); - } - break; - } - - case Data::DependencySourceType::LOCAL: - { - std::string localDepDirectoryName; - std::string curPath = currentSource.Value; - - if(curPath.back() == '/') - curPath.pop_back(); - - localDepDirectoryName = ghc::filesystem::path(curPath).filename().string(); - outCopiesPaths.push_back(buildDir / localDepDirectoryName); - - if(ghc::filesystem::path(curPath).is_relative()) - outSourcesPaths.push_back(scriptDirectory / currentSource.Value); - else - outSourcesPaths.push_back(currentSource.Value); - - break; - } - - case Data::DependencySourceType::COUNT: - return false; + return false; } + + outCopiesPaths.push_back(currentCopyPath.string()); + outSourcesPaths.push_back(currentSourcePath.string()); } return true; @@ -516,6 +567,9 @@ bool runcpp2::GatherDependenciesBinaries( const std::vector& outBinariesPaths) { + ssLOG_FUNC_DEBUG(); + + std::unordered_set binariesPathsSet; for(int i = 0; i < outBinariesPaths.size(); ++i) binariesPathsSet.insert(outBinariesPaths[i]); @@ -726,3 +780,132 @@ bool runcpp2::GatherDependenciesBinaries( const std::vector> previouslyImportedSources; + { + std::shared_ptr currentImportSource = + std::make_shared(dependency.Source); + + previouslyImportedSources = dependency.Source.ImportedSources; + + dependency.Source.ImportedSources.clear(); + currentImportSource->ImportedSources.clear(); + + previouslyImportedSources.push_back(currentImportSource); + } + + //Reset the current dependency before we parse the import dependency + dependency = Data::DependencyInfo(); + + //Parse the imported dependency + if(!dependency.ParseYAML_Node(resolvedTree)) + { + ssLOG_ERROR("Failed to parse imported dependency: " << fullPath); + + //Print the list of imported sources + for(int i = 0; i < previouslyImportedSources.size(); ++i) + { + ssLOG_ERROR("Imported source[" << i << "]: " << + previouslyImportedSources.at(i)->ImportPath.string()); + } + + return false; + } + + dependency.Source.ImportedSources = previouslyImportedSources; + return true; +} + +bool runcpp2::ResolveImports( Data::ScriptInfo& scriptInfo, + const ghc::filesystem::path& scriptPath, + const ghc::filesystem::path& buildDir) +{ + ssLOG_FUNC_INFO(); + INTERNAL_RUNCPP2_SAFE_START(); + + //For each dependency, check if import path exists + //for(Data::DependencyInfo& dependency : scriptInfo.Dependencies) + for(int i = 0; i < scriptInfo.Dependencies.size(); ++i) + { + Data::DependencyInfo& dependency = scriptInfo.Dependencies.at(i); + + //Check if import path exists + Data::DependencySource& source = dependency.Source; + if(source.ImportPath.empty()) + continue; + + if(!source.ImportPath.is_relative()) + { + ssLOG_ERROR("Import path is not relative: " << source.ImportPath.string()); + return false; + } + + ghc::filesystem::path copyPath; + ghc::filesystem::path sourcePath; + + if(!GetDependencyPath(dependency, scriptPath, buildDir, copyPath, sourcePath)) + return false; + + bool prePopulated = false; + if(!PopulateLocalDependency(dependency, copyPath, sourcePath, buildDir, prePopulated)) + return false; + + //Parse the import file + if(!HandleImport(dependency, copyPath)) + return false; + + //Check do we still have import path in the dependency. If so, we need to parse it again + if(!dependency.Source.ImportPath.empty()) + --i; + } + + return true; + + INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false); +} + diff --git a/Src/runcpp2/ParseUtil.cpp b/Src/runcpp2/ParseUtil.cpp index 383048d..d196bdd 100644 --- a/Src/runcpp2/ParseUtil.cpp +++ b/Src/runcpp2/ParseUtil.cpp @@ -273,6 +273,8 @@ bool runcpp2::GetParsableInfo(const std::string& contentToParse, std::string& ou bool runcpp2::ResolveYAML_Stream( ryml::Tree& rootTree, ryml::ConstNodeRef& outRootNode) { + ssLOG_FUNC_DEBUG(); + INTERNAL_RUNCPP2_SAFE_START(); //Resolve the merge keys in the yaml first @@ -313,6 +315,8 @@ bool runcpp2::ExistAndHasChild( const ryml::ConstNodeRef& node, bool nullable) { ssLOG_FUNC_DEBUG(); + + INTERNAL_RUNCPP2_SAFE_START(); if(node.num_children() > 0 && node.has_child(childName.c_str())) { @@ -326,6 +330,8 @@ bool runcpp2::ExistAndHasChild( const ryml::ConstNodeRef& node, } return false; + + INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(false); } std::string runcpp2::GetValue(ryml::ConstNodeRef node) diff --git a/Src/runcpp2/PipelineSteps.cpp b/Src/runcpp2/PipelineSteps.cpp index 94696cf..96b79e1 100644 --- a/Src/runcpp2/PipelineSteps.cpp +++ b/Src/runcpp2/PipelineSteps.cpp @@ -310,11 +310,14 @@ runcpp2::ParseAndValidateScriptInfo(const ghc::filesystem::path& absoluteScriptP ssLOG_FUNC_INFO(); INTERNAL_RUNCPP2_SAFE_START(); + //TODO: Record last script info write time. Use last script info if possible to reduce disk io + //Check if there's script info as yaml file instead std::error_code e; std::string parsableInfo; std::ifstream inputFile; - std::string dedicatedYamlLoc = ProcessPath(scriptDirectory.string() +"/" + scriptName + ".yaml"); + ghc::filesystem::path dedicatedYamlLoc = + scriptDirectory / ghc::filesystem::path(scriptName + ".yaml"); if(ghc::filesystem::exists(dedicatedYamlLoc, e)) { @@ -480,6 +483,26 @@ runcpp2::InitializeBuildDirectory( const ghc::filesystem::path& configDir, INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(PipelineResult::UNEXPECTED_FAILURE); } +runcpp2::PipelineResult +runcpp2::ResolveScriptImports( Data::ScriptInfo& scriptInfo, + const ghc::filesystem::path& scriptPath, + const ghc::filesystem::path& buildDir) +{ + ssLOG_FUNC_INFO(); + INTERNAL_RUNCPP2_SAFE_START(); + + //Resolve all the script info imports first before evaluating it + if(!ResolveImports(scriptInfo, scriptPath, buildDir)) + { + ssLOG_ERROR("Failed to resolve imports"); + return PipelineResult::UNEXPECTED_FAILURE; + } + + return PipelineResult::SUCCESS; + + INTERNAL_RUNCPP2_SAFE_CATCH_RETURN(PipelineResult::UNEXPECTED_FAILURE); +} + runcpp2::PipelineResult runcpp2::CheckScriptInfoChanges(const ghc::filesystem::path& buildDir, const Data::ScriptInfo& scriptInfo, @@ -492,7 +515,7 @@ runcpp2::CheckScriptInfoChanges(const ghc::filesystem::path& buildDir, { ssLOG_FUNC_INFO(); INTERNAL_RUNCPP2_SAFE_START(); - + ghc::filesystem::path lastScriptInfoFilePath = buildDir / "LastScriptInfo.yaml"; Data::ScriptInfo lastScriptInfoFromDisk; diff --git a/Src/runcpp2/main.cpp b/Src/runcpp2/main.cpp index 473426b..e467369 100644 --- a/Src/runcpp2/main.cpp +++ b/Src/runcpp2/main.cpp @@ -328,8 +328,8 @@ int main(int argc, char* argv[]) return 0; } - // Check if the version flag is present - if (currentOptions.count(runcpp2::CmdOptions::VERSION)) + //Check if the version flag is present + if(currentOptions.count(runcpp2::CmdOptions::VERSION)) { ssLOG_BASE("runcpp2 version " << RUNCPP2_VERSION); return 0; diff --git a/Src/runcpp2/runcpp2.cpp b/Src/runcpp2/runcpp2.cpp index 5a16075..4d28197 100644 --- a/Src/runcpp2/runcpp2.cpp +++ b/Src/runcpp2/runcpp2.cpp @@ -486,6 +486,11 @@ runcpp2::StartPipeline( const std::string& scriptPath, buildsManager); } + //Resolve imports + result = ResolveScriptImports(scriptInfo, absoluteScriptPath, buildDir); + if(result != PipelineResult::SUCCESS) + return result; + //Check if script info has changed if provided bool recompileNeeded = false; bool relinkNeeded = false; diff --git a/TODO.md b/TODO.md index 3ec6196..0c4af50 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,7 @@ TODO: - Allow runcpp2 to be library - Ability to compile runcpp2 as single cpp +- Ability to skip DefaultPlatform and DefaultProfile - Async compile - Check last run is shared lib or executable. Reset cache when necessary if different type - Handle escape characters at the end @@ -13,14 +14,13 @@ TODO: - Separate git and local source options - Add branch/tag option for git - Add initialize submodule option for git +- Record last script info write time for `ParseAndValidateScriptInfo()` - Migrate to libyaml - Add wildcard support for filenames and extensions - Add tests and examples (On Windows as well) - Make SearchLibraryNames and SearchDirectories optional (?) - Add cache limit - Add system source type for dependencies -- Add local YAML source type for dependencies -- Add optional url YAML source type for dependencies - Add ability to reference local YAML for user config - Add version for user config and prompt for update - Output compile_command.json