diff --git a/recipes/msix/all/CMakeLists.txt b/recipes/msix/all/CMakeLists.txt new file mode 100644 index 0000000000000..c477e0c1e565e --- /dev/null +++ b/recipes/msix/all/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 2.8.0) +project(cmake_wrapper) + +include(conanbuildinfo.cmake) +conan_basic_setup(TARGETS) + +add_subdirectory("source_subfolder") diff --git a/recipes/msix/all/conandata.yml b/recipes/msix/all/conandata.yml new file mode 100644 index 0000000000000..ef22231170ffe --- /dev/null +++ b/recipes/msix/all/conandata.yml @@ -0,0 +1,10 @@ +sources: + "1.7": + url: "https://github.com/microsoft/msix-packaging/archive/refs/tags/v1.7.zip" + sha256: "23179d577d0b9d34e93374ae38284ab9f1247ff6cc9175851983fb114ab00087" +patches: + "1.7": + - base_path: "source_subfolder" + patch_file: "patches/1.7/cmake.patch" + - base_path: "source_subfolder" + patch_file: "patches/1.7/signaturevalidator.patch" diff --git a/recipes/msix/all/conanfile.py b/recipes/msix/all/conanfile.py new file mode 100644 index 0000000000000..470d43cd5b916 --- /dev/null +++ b/recipes/msix/all/conanfile.py @@ -0,0 +1,158 @@ +import os +from conans import CMake, ConanFile, tools +from conans.errors import ConanInvalidConfiguration + + +required_conan_version = ">=1.33.0" + + +class MsixConan(ConanFile): + name = "msix" + license = "MIT" + url = "https://github.com/conan-io/conan-center-index" + homepage = "https://github.com/microsoft/msix-packaging" + description = "An SDK for creating MSIX packages" + topics = ("msix", "sdk", "packaging", "conan-recipe") + + settings = "os", "compiler", "build_type", "arch" + options = { + "shared": [True, False], + "fPIC": [True, False], + "crypto_lib": ["crypt32", "openssl"], + "pack": [True, False], + "skip_bundles": [True, False], + "use_external_zlib": [True, False], + "use_validation_parser": [True, False], + "xml_parser": ["applexml", "javaxml", "msxml6", "xerces"] + } + default_options = { + "shared": False, + "fPIC": True, + "crypto_lib": "openssl", + "pack": False, + "skip_bundles": False, + "use_external_zlib": True, + "use_validation_parser": False, + "xml_parser": "msxml6" + } + + generators = "cmake" + exports_sources = "CMakeLists.txt", "patches/**" + + _cmake = None + + @property + def _minimum_compilers_version(self): + return { + "Visual Studio": "15" + } + + @property + def _source_subfolder(self): + return "source_subfolder" + + def _configure_cmake(self): + if self._cmake: + return self._cmake + self._cmake = CMake(self) + if self.settings.os == "Android": + self._cmake.definitions["AOSP"] = True + if self.settings.os == "Linux": + self._cmake.definitions["LINUX"] = True + if self.settings.os == "Macos": + self._cmake.definitions["MACOS"] = True + self._cmake.definitions["CRYPTO_LIB"] = self.options.crypto_lib + self._cmake.definitions["MSIX_PACK"] = self.options.pack + self._cmake.definitions["MSIX_SAMPLES"] = False + self._cmake.definitions["MSIX_TESTS"] = False + self._cmake.definitions["SKIP_BUNDLES"] = self.options.skip_bundles + self._cmake.definitions["USE_MSIX_SDK_ZLIB"] = self.options.use_external_zlib + self._cmake.definitions["USE_SHARED_ZLIB"] = self.options["zlib"].shared + self._cmake.definitions["USE_VALIDATION_PARSER"] = self.options.use_validation_parser + self._cmake.definitions["XML_PARSER"] = self.options.xml_parser + self._cmake.definitions["CALCULATE_VERSION"] = False + self._cmake.definitions["ENABLE_NUGET_PACKAGING"] = False + self._cmake.configure() + return self._cmake + + def _validate_compiler_settings(self): + compiler = self.settings.compiler + if compiler.get_safe("cppstd"): + tools.check_min_cppstd(self, "17") + + min_version = self._minimum_compilers_version.get(str(self.settings.compiler)) + if not min_version: + self.output.warn("{} recipe lacks information about the {} compiler support.".format( + self.name, self.settings.compiler)) + elif tools.Version(self.settings.compiler.version) < min_version: + raise ConanInvalidConfiguration("{} requires C++17 support. The current compiler {} {} does not support it.".format( + self.name, self.settings.compiler, self.settings.compiler.version)) + + def config_options(self): + if self.settings.os == "Windows": + del self.options.fPIC + self.options.crypto_lib = "crypt32" + + def configure(self): + if self.options.shared: + del self.options.fPIC + + def requirements(self): + if self.settings.os == "Linux" and not self.options.skip_bundles: + self.requires("icu/69.1") + if self.options.crypto_lib == "openssl": + self.requires("openssl/1.0.2t") + if self.options.use_external_zlib: + self.requires("zlib/1.2.11") + if self.options.xml_parser == "xerces": + self.requires("xerces-c/3.2.3") + + def validate(self): + if self.settings.os != "Android" and self.options.xml_parser == "javaxml": + raise ConanInvalidConfiguration("javaxml is supported only for Android") + if self.settings.os == "Linux" and self.settings.compiler != "clang": + raise ConanInvalidConfiguration("Only clang is supported on Linux") + if self.settings.os != "Macos" and self.options.xml_parser == "applexml": + raise ConanInvalidConfiguration("applexml is supported only for MacOS") + if self.settings.os != "Windows" and self.options.crypto_lib == "crypt32": + raise ConanInvalidConfiguration("crypt32 is supported only for Windows") + if self.settings.os != "Windows" and self.options.xml_parser == "msxml6": + raise ConanInvalidConfiguration("msxml6 is supported only for Windows") + if self.options.pack: + if self.settings.os == "Macos": + if not self.options.use_external_zlib: + raise ConanInvalidConfiguration("Using libCompression APIs and packaging features is not supported") + if self.options.xml_parser != "xerces": + raise ConanInvalidConfiguration("Xerces is the only supported parser for MacOS pack") + if not self.options.use_validation_parser: + raise ConanInvalidConfiguration("Packaging requires validation parser") + if (self.options.xml_parser == "xerces" and + self.options["xerces-c"].char_type != "char16_t"): + raise ConanInvalidConfiguration("Only char16_t is supported for xerces-c") + + self._validate_compiler_settings() + + def source(self): + tools.get(**self.conan_data["sources"][self.version], destination=self._source_subfolder, strip_root=True) + + def build(self): + for patch in self.conan_data.get("patches", {}).get(self.version, []): + tools.patch(**patch) + cmake = self._configure_cmake() + cmake.build() + + def package(self): + cmake = self._configure_cmake() + cmake.install() + self.copy("LICENSE", dst="licenses", src=self._source_subfolder) + + def package_info(self): + self.cpp_info.libs = tools.collect_libs(self) + if self.settings.os == "Windows": + self.cpp_info.system_libs = ["runtimeobject"] + if self.settings.compiler == "Visual Studio": + self.cpp_info.system_libs.append("delayimp") + if self.options.crypto_lib == "crypt32": + self.cpp_info.system_libs.extend(["bcrypt", "crypt32", "wintrust"]) + if self.options.xml_parser == "msxml6": + self.cpp_info.system_libs.append("msxml6") diff --git a/recipes/msix/all/patches/1.7/cmake.patch b/recipes/msix/all/patches/1.7/cmake.patch new file mode 100644 index 0000000000000..b64f3d1cd79c0 --- /dev/null +++ b/recipes/msix/all/patches/1.7/cmake.patch @@ -0,0 +1,233 @@ + CMakeLists.txt | 18 +++++++----- + src/CMakeLists.txt | 1 - + src/makemsix/CMakeLists.txt | 3 ++ + src/msix/CMakeLists.txt | 67 ++++++++++++++++----------------------------- + 4 files changed, 37 insertions(+), 52 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index dc5908cd..b2e857a5 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -21,11 +21,13 @@ if(POLICY CMP0077) + cmake_policy(SET CMP0077 NEW) + endif() + ++if(CALCULATE_VERSION) + # Default version is 0.0.0 + set(VERSION_MAJOR "0") + set(VERSION_MINOR "0") + set(VERSION_PATCH "0") + set(GIT_BRANCH_NAME "master") ++endif() + + # CMake useful variables + set(MSIX_PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR}) +@@ -35,6 +37,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") + ++if(CALCULATE_VERSION) + ## Git (and its revision) + find_package(Git) # QUIET) # if we don't find git or FindGit.cmake is not on the system we ignore it. + +@@ -77,15 +80,22 @@ if(GIT_FOUND) + else() + message("git not found.") + endif() ++endif() + ++if(CALCULATE_VERSION) + # Set the version number of your project here (format is MAJOR.MINOR.PATCHLEVEL - e.g. 1.0.0) + set(MSIX_VERSION ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}) + message(STATUS "MSIX Packaging SDK version ${MSIX_VERSION}") + message(STATUS "MSIX Packaging SDK branch name ${GIT_BRANCH_NAME}") + add_definitions(-DSDK_VERSION="${MSIX_VERSION}") ++else() ++message(STATUS "MSIX Packaging SDK version ${PROJECT_VERSION}") ++add_definitions(-DSDK_VERSION="${PROJECT_VERSION}") ++endif() + # Validates CMake options. + include(msix_options) + ++if(ENABLE_NUGET_PACKAGING) + # Configure Package.nuspec + if(WIN32) + set(MSIX_NUGET_NAME "Microsoft.MSIX.Packaging.Windows") +@@ -103,6 +113,7 @@ configure_file(${MSIX_PROJECT_ROOT}/Package.nuspec.cmakein ${MSIX_BINARY_ROOT}/P + configure_file(${MSIX_PROJECT_ROOT}/Microsoft.MSIX.Packaging.targets ${MSIX_BINARY_ROOT}/build/native/${MSIX_NUGET_NAME}.targets) + message(STATUS "Package.Nuspec created") + message(STATUS "--------------------------------") ++endif() + + # Configure license txt + configure_file(${MSIX_PROJECT_ROOT}/LICENSE ${MSIX_BINARY_ROOT}/build/LICENSE) +@@ -170,9 +181,6 @@ if((MACOS) OR (IOS)) + message(FATAL_ERROR "Unsupported iOS version: ${IOS_DEPLOYMENT_TARGET}, this project requires at least iOS version 10.0") + endif() + endif() +-elseif(AOSP OR LINUX) +- # Static libraries must be position independent to be linked with a shared object. +- set(CMAKE_POSITION_INDEPENDENT_CODE ON) + endif() + + # Mac needed variables +@@ -183,10 +191,6 @@ set(CMAKE_MACOSX_RPATH ON) + #set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") + #set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + +-add_subdirectory(lib) +-message(STATUS "libs processed") + add_subdirectory(src) + message(STATUS "src processed") +-add_subdirectory(sample) +-message(STATUS "sample processed") + message(STATUS "DONE!") +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index a2655a7b..5d224b64 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -6,4 +6,3 @@ cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) + + add_subdirectory(msix) + add_subdirectory(makemsix) +-add_subdirectory(test) +diff --git a/src/makemsix/CMakeLists.txt b/src/makemsix/CMakeLists.txt +index 92b082e6..ebae9789 100644 +--- a/src/makemsix/CMakeLists.txt ++++ b/src/makemsix/CMakeLists.txt +@@ -24,3 +24,6 @@ target_include_directories(${PROJECT_NAME} PRIVATE ${MSIX_BINARY_ROOT}/src/msix) + + add_dependencies(${PROJECT_NAME} msix) + target_link_libraries(${PROJECT_NAME} msix) ++ ++# define installing rules for target files ++install(TARGETS ${PROJECT_NAME}) +diff --git a/src/msix/CMakeLists.txt b/src/msix/CMakeLists.txt +index 75d3afdf..e1fb2984 100644 +--- a/src/msix/CMakeLists.txt ++++ b/src/msix/CMakeLists.txt +@@ -6,6 +6,11 @@ cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR) + + project(msix) + ++# Define the library ++add_library(${PROJECT_NAME} ++ msix.cpp ++) ++ + # Handle exports and flags we need to set + list(APPEND MSIX_UNPACK_EXPORTS + "UnpackPackage" +@@ -144,7 +149,7 @@ if(NOT SKIP_BUNDLES) + if (WIN32) + list(APPEND MsixSrc PAL/Applicability/Win32/Applicability.cpp) + elseif(LINUX) +- find_package(ICU REQUIRED COMPONENTS uc) ++ target_link_libraries(${PROJECT_NAME} PRIVATE CONAN_PKG::icu) + list(APPEND MsixSrc PAL/Applicability/Linux/Applicability.cpp) + elseif(AOSP) + list(APPEND MsixSrc PAL/Applicability/AOSP/Applicability.cpp) +@@ -195,14 +200,16 @@ if(CRYPTO_LIB MATCHES crypt32) + PAL/Signature/Win32/SignatureValidator.cpp + ) + elseif(CRYPTO_LIB MATCHES openssl) +- if(OpenSSL_FOUND) +- list(APPEND MsixSrc +- PAL/Crypto/OpenSSL/Crypto.cpp +- PAL/Signature/OpenSSL/SignatureValidator.cpp +- ) ++ list(APPEND MsixSrc ++ PAL/Crypto/OpenSSL/Crypto.cpp ++ PAL/Signature/OpenSSL/SignatureValidator.cpp ++ ) ++ if((IOS) OR (MACOS)) ++ target_link_libraries(${PROJECT_NAME} PRIVATE CONAN_PKG::openssl -Wl,-dead_strip) ++ elseif(NOT MSVC) ++ target_link_libraries(${PROJECT_NAME} PRIVATE CONAN_PKG::openssl -Wl,--gc-sections) + else() +- # ... and were done here... :/ +- message(FATAL_ERROR "OpenSSL NOT FOUND!") ++ target_link_libraries(${PROJECT_NAME} PRIVATE CONAN_PKG::openssl) + endif() + endif() + +@@ -220,14 +227,7 @@ foreach(FILE ${MsixSrc}) + message(STATUS "\t${FILE}") + endforeach() + +-# Define the library +-add_library(${PROJECT_NAME} SHARED +- msix.cpp +- ${MsixSrc} +-) +- +-# Adding dependency to the third party libs directory +-add_dependencies(${PROJECT_NAME} LIBS) ++target_sources(${PROJECT_NAME} PRIVATE ${MsixSrc}) + + # Copy out public headers to /src/unpack + configure_file(../inc/MSIXWindows.hpp ${CMAKE_CURRENT_BINARY_DIR}/MSIXWindows.hpp ) +@@ -260,7 +260,7 @@ if(WIN32) + "/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll") + string(REPLACE ";" " " DELAYFLAGS "${DELAYFLAGS}") + set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS "${DELAYFLAGS} /LTCG") +- set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS " /DEF:windowsexports.def") ++ set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS " /DEF:${CMAKE_CURRENT_BINARY_DIR}/windowsexports.def") + if(USE_STATIC_MSVC) + if(CMAKE_BUILD_TYPE MATCHES Debug) + set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS " /NODEFAULTLIB:MSVCRTD") +@@ -285,29 +285,20 @@ if(((IOS) OR (MACOS)) AND (NOT USE_MSIX_SDK_ZLIB)) + target_link_libraries(${PROJECT_NAME} PRIVATE libcompression.dylib) + elseif((AOSP) AND (NOT USE_MSIX_SDK_ZLIB)) + # for AOSP, use the libz.so from the android ndk. +- find_package(ZLIB REQUIRED) + target_link_libraries(${PROJECT_NAME} PRIVATE -lz) +-else() # WIN32 or USE_MSIX_SDK_ZLIB +- target_include_directories(${PROJECT_NAME} PRIVATE +- ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/zlib +- ${MSIX_PROJECT_ROOT}/lib/zlib +- ) ++else() + if(USE_SHARED_ZLIB) + message(STATUS "MSIX takes a dynamic dependency on zlib") +- target_link_libraries(${PROJECT_NAME} PRIVATE zlib) ++ target_link_libraries(${PROJECT_NAME} PRIVATE CONAN_PKG::zlib) + else() + message(STATUS "MSIX takes a static dependency on zlib") +- target_link_libraries(${PROJECT_NAME} PRIVATE zlibstatic) ++ target_link_libraries(${PROJECT_NAME} PRIVATE CONAN_PKG::zlib) + endif() + endif() + + # Parser + if(XML_PARSER MATCHES xerces) +- target_include_directories(${PROJECT_NAME} PRIVATE +- ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/xerces/src +- ${MSIX_PROJECT_ROOT}/lib/xerces/src +- ) +- target_link_libraries(${PROJECT_NAME} PRIVATE xerces-c) ++ target_link_libraries(${PROJECT_NAME} PRIVATE CONAN_PKG::xerces-c) + endif() + + if(XML_PARSER MATCHES applexml) +@@ -363,18 +354,6 @@ endif() + if((IOS) OR (MACOS)) + target_link_libraries(${PROJECT_NAME} PRIVATE ${COREFOUNDATION_LIBRARY} ${FOUNDATION_LIBRARY}) + endif() +-if(LINUX) +- target_link_libraries(${PROJECT_NAME} PRIVATE ${ICU_LIBRARIES}) +-endif() + +-if(OpenSSL_FOUND) +- # include the libraries needed to use OpenSSL +- target_include_directories(${PROJECT_NAME} PRIVATE ${OpenSSL_INCLUDE_PATH}) +- if((IOS) OR (MACOS)) +- target_link_libraries(${PROJECT_NAME} PRIVATE crypto -Wl,-dead_strip) +- elseif(NOT MSVC) +- target_link_libraries(${PROJECT_NAME} PRIVATE crypto -Wl,--gc-sections) +- else() +- target_link_libraries(${PROJECT_NAME} PRIVATE crypto) +- endif() +-endif() ++# define installing rules for target files ++install(TARGETS ${PROJECT_NAME}) diff --git a/recipes/msix/all/patches/1.7/signaturevalidator.patch b/recipes/msix/all/patches/1.7/signaturevalidator.patch new file mode 100644 index 0000000000000..bc8cdf9e699db --- /dev/null +++ b/recipes/msix/all/patches/1.7/signaturevalidator.patch @@ -0,0 +1,39 @@ +diff --git a/src/msix/PAL/Signature/OpenSSL/SignatureValidator.cpp b/src/msix/PAL/Signature/OpenSSL/SignatureValidator.cpp +index 1cc34b20..ccbf68dc 100644 +--- a/src/msix/PAL/Signature/OpenSSL/SignatureValidator.cpp ++++ b/src/msix/PAL/Signature/OpenSSL/SignatureValidator.cpp +@@ -94,11 +94,10 @@ namespace MSIX + STACK_OF(X509) *certStack = p7.get()->d.sign->cert; + for (int i = 0; i < sk_X509_num(certStack); i++) + { +- X509* cert = sk_X509_value(certStack, i); +- STACK_OF(X509_EXTENSION) *exts = cert->cert_info->extensions; +- for (int i = 0; i < sk_X509_EXTENSION_num(exts); i++) ++ X509* cert = sk_X509_value(certStack, i); ++ for (int i = 0; i < X509_get_ext_count(cert); i++) + { +- X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); ++ X509_EXTENSION *ext = X509_get_ext(cert, i); + if (ext) + { + if (X509_EXTENSION_get_object(ext)) +@@ -106,7 +105,7 @@ namespace MSIX + unique_BIO extbio(BIO_new(BIO_s_mem())); + if (!X509V3_EXT_print(extbio.get(), ext, 0, 0)) + { +- M_ASN1_OCTET_STRING_print(extbio.get(), ext->value); ++ M_ASN1_OCTET_STRING_print(extbio.get(), X509_EXTENSION_get_data(ext)); + } + // null terminate the string. + BIO_write(extbio.get(), "", 1); +@@ -207,8 +206,8 @@ namespace MSIX + // If we encounter an expired cert error (which is fine) or a critical extension (most MS + // certs contain MS-specific extensions that OpenSSL doesn't know how to evaluate), + // just return success +- if (!ok && (ctx->error == X509_V_ERR_CERT_HAS_EXPIRED || +- ctx->error == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)) ++ if (!ok && (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED || ++ X509_STORE_CTX_get_error(ctx) == X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION)) + { + ok = static_cast(true); + } diff --git a/recipes/msix/all/test_package/CMakeLists.txt b/recipes/msix/all/test_package/CMakeLists.txt new file mode 100644 index 0000000000000..e28b2e2b66dd9 --- /dev/null +++ b/recipes/msix/all/test_package/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.1) +project(test_package CXX) + +include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) +conan_basic_setup(TARGETS) + +add_executable(${PROJECT_NAME} example.cpp) + +conan_target_link_libraries(${PROJECT_NAME}) diff --git a/recipes/msix/all/test_package/conanfile.py b/recipes/msix/all/test_package/conanfile.py new file mode 100644 index 0000000000000..bee328a3e1aa7 --- /dev/null +++ b/recipes/msix/all/test_package/conanfile.py @@ -0,0 +1,17 @@ +import os +from conans import ConanFile, CMake, tools + + +class MsixTestConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake" + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if not tools.cross_building(self): + bin_path = os.path.join("bin", "test_package") + self.run(bin_path, run_environment=True) diff --git a/recipes/msix/all/test_package/example.cpp b/recipes/msix/all/test_package/example.cpp new file mode 100644 index 0000000000000..292160c8862d6 --- /dev/null +++ b/recipes/msix/all/test_package/example.cpp @@ -0,0 +1,26 @@ +#include + +LPVOID STDMETHODCALLTYPE MyAllocate(SIZE_T cb) { + return std::malloc(cb); +} + +void STDMETHODCALLTYPE MyFree(LPVOID pv) { + std::free(pv); +} + +int main() { + IAppxFactory* appxFactory; + + HRESULT creationResult = CoCreateAppxFactoryWithHeap( + MyAllocate, + MyFree, + MSIX_VALIDATION_OPTION::MSIX_VALIDATION_OPTION_FULL, + &appxFactory + ); + + if (FAILED(creationResult)) { + return creationResult; + } + + return 0; +} diff --git a/recipes/msix/config.yml b/recipes/msix/config.yml new file mode 100644 index 0000000000000..a03e932e1cf87 --- /dev/null +++ b/recipes/msix/config.yml @@ -0,0 +1,3 @@ +versions: + "1.7": + folder: "all"