From a6a1722cfa94caa5db98848679b99377bc5a0112 Mon Sep 17 00:00:00 2001 From: Billy O'Neal Date: Tue, 27 Oct 2020 20:48:14 -0700 Subject: [PATCH] [vcpkg, jsonnet, openssl-uwp] Enable use of the system powershell-core if it is present. (#13805) --- ports/jsonnet/CONTROL | 1 + ports/jsonnet/portfile.cmake | 5 ++- ports/openssl-uwp/CONTROL | 1 + ports/openssl-uwp/EnableUWPSupport.patch | 2 +- scripts/addPoshVcpkgToPowershellProfile.ps1 | 6 +-- scripts/buildsystems/msbuild/vcpkg.targets | 41 +++++++++++++++---- scripts/buildsystems/vcpkg.cmake | 20 ++++++++- .../cmake/vcpkg_copy_tool_dependencies.cmake | 10 ++--- toolsrc/include/vcpkg/base/files.h | 13 +++++- toolsrc/include/vcpkg/tools.h | 1 + toolsrc/src/vcpkg-test/files.cpp | 15 +++++++ toolsrc/src/vcpkg/base/files.cpp | 33 +++++++++++++-- toolsrc/src/vcpkg/build.cpp | 7 ---- toolsrc/src/vcpkg/tools.cpp | 38 +++++++++++++++++ 14 files changed, 160 insertions(+), 33 deletions(-) diff --git a/ports/jsonnet/CONTROL b/ports/jsonnet/CONTROL index 99d73af6cdc..b069a6b1b80 100644 --- a/ports/jsonnet/CONTROL +++ b/ports/jsonnet/CONTROL @@ -1,5 +1,6 @@ Source: jsonnet Version: 0.16.0 +Port-Version: 1 Homepage: https://github.com/google/jsonnet Description: Jsonnet - The data templating language Build-Depends: nlohmann-json diff --git a/ports/jsonnet/portfile.cmake b/ports/jsonnet/portfile.cmake index 77e8b878396..b2769cd854d 100644 --- a/ports/jsonnet/portfile.cmake +++ b/ports/jsonnet/portfile.cmake @@ -15,8 +15,9 @@ vcpkg_from_github( ) if(VCPKG_TARGET_IS_WINDOWS) - vcpkg_execute_required_process( - COMMAND Powershell -Command "((Get-Content -AsByteStream \"${SOURCE_PATH}/stdlib/std.jsonnet\") -join ',') + ',0' | Out-File -Encoding Ascii \"${SOURCE_PATH}/core/std.jsonnet.h\"" + find_program(PWSH_PATH pwsh) + vcpkg_execute_required_process( + COMMAND "${PWSH_PATH}" -Command "((Get-Content -AsByteStream \"${SOURCE_PATH}/stdlib/std.jsonnet\") -join ',') + ',0' | Out-File -Encoding Ascii \"${SOURCE_PATH}/core/std.jsonnet.h\"" WORKING_DIRECTORY "${SOURCE_PATH}" LOGNAME "std.jsonnet" ) diff --git a/ports/openssl-uwp/CONTROL b/ports/openssl-uwp/CONTROL index 6d42b3af094..cdf818e330c 100644 --- a/ports/openssl-uwp/CONTROL +++ b/ports/openssl-uwp/CONTROL @@ -1,4 +1,5 @@ Source: openssl-uwp Version: 1.1.1h +Port-Version: 1 Description: OpenSSL is an open source project that provides a robust, commercial-grade, and full-featured toolkit for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. It is also a general-purpose cryptography library. Supports: uwp diff --git a/ports/openssl-uwp/EnableUWPSupport.patch b/ports/openssl-uwp/EnableUWPSupport.patch index d534b9b4a67..4313220f118 100644 --- a/ports/openssl-uwp/EnableUWPSupport.patch +++ b/ports/openssl-uwp/EnableUWPSupport.patch @@ -54,7 +54,7 @@ index d478f42b0f..e0fb70daca 100644 +my $UWP_info = {}; +sub UWP_info { + unless (%$UWP_info) { -+ my $SDKver = `powershell -Command \"& {\$(Get-Item \\\"hklm:\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\\").GetValue(\\\"CurrentVersion\\\")}\"`; ++ my $SDKver = `pwsh.exe -Command \"& {\$(Get-Item \\\"hklm:\\SOFTWARE\\WOW6432Node\\Microsoft\\Microsoft SDKs\\Windows\\\").GetValue(\\\"CurrentVersion\\\")}\"`; + $SDKver =~ s|\R$||; + my @SDKver_split = split(/\./, $SDKver); + # SDK version older than 10.0.17763 don't support our ASM builds diff --git a/scripts/addPoshVcpkgToPowershellProfile.ps1 b/scripts/addPoshVcpkgToPowershellProfile.ps1 index 1dd27aacff5..185f658c984 100644 --- a/scripts/addPoshVcpkgToPowershellProfile.ps1 +++ b/scripts/addPoshVcpkgToPowershellProfile.ps1 @@ -16,7 +16,7 @@ function findExistingImportModuleDirectives([Parameter(Mandatory=$true)][string] $scriptsDir = split-path -parent $script:MyInvocation.MyCommand.Definition $profileEntry = "Import-Module '$scriptsDir\posh-vcpkg'" -$profilePath = $PROFILE # Implicit powershell variable +$profilePath = $PROFILE # Implicit PowerShell variable $profileDir = Split-Path $profilePath -Parent if (!(Test-Path $profileDir)) { @@ -33,7 +33,7 @@ if ($existingImports.Count -gt 0) $existingImportsOut = $existingImports -join "`n " Write-Host "`nposh-vcpkg is already imported to your PowerShell profile. The following entries were found:" Write-Host " $existingImportsOut" - Write-Host "`nPlease make sure you have started a new Powershell window for the changes to take effect." + Write-Host "`nPlease make sure you have started a new PowerShell window for the changes to take effect." return } @@ -53,4 +53,4 @@ if (Test-Path $profilePath) } Add-Content $profilePath -Value "`n$profileEntry" -Encoding UTF8 -Write-Host "`nSuccessfully added posh-vcpkg to your PowerShell profile. Please start a new Powershell window for the changes to take effect." +Write-Host "`nSuccessfully added posh-vcpkg to your PowerShell profile. Please start a new PowerShell window for the changes to take effect." diff --git a/scripts/buildsystems/msbuild/vcpkg.targets b/scripts/buildsystems/msbuild/vcpkg.targets index a9c3395590b..5013d764a24 100644 --- a/scripts/buildsystems/msbuild/vcpkg.targets +++ b/scripts/buildsystems/msbuild/vcpkg.targets @@ -103,18 +103,45 @@ + + File="$(TLogLocation)$(ProjectName).write.1u.tlog" + Lines="^$(TargetPath);$([System.IO.Path]::Combine($(ProjectDir),$(IntDir)))vcpkg.applocal.log" Encoding="Unicode"/> + + <_VcpkgAppLocalPowerShellCommonArguments>-ExecutionPolicy Bypass -noprofile -File "$(MSBuildThisFileDirectory)applocal.ps1" "$(TargetPath)" "$(VcpkgCurrentInstalledDir)$(VcpkgConfigSubdir)bin" "$(TLogLocation)$(ProjectName).write.1u.tlog" "$(IntDir)vcpkg.applocal.log" + + + Command="pwsh.exe $(_VcpkgAppLocalPowerShellCommonArguments)" + StandardOutputImportance="Normal" + StandardErrorImportance="Normal" + IgnoreExitCode="true" + UseCommandProcessor="false"> + - + + + + + + + + - - + + diff --git a/scripts/buildsystems/vcpkg.cmake b/scripts/buildsystems/vcpkg.cmake index 08d0c8d200c..dab5b73a619 100644 --- a/scripts/buildsystems/vcpkg.cmake +++ b/scripts/buildsystems/vcpkg.cmake @@ -395,6 +395,20 @@ endif() option(VCPKG_APPLOCAL_DEPS "Automatically copy dependencies into the output directory for executables." ON) option(X_VCPKG_APPLOCAL_DEPS_SERIALIZED "(experimental) Add USES_TERMINAL to VCPKG_APPLOCAL_DEPS to force serialization." OFF) +function(_vcpkg_set_powershell_path) + # Attempt to use pwsh if it is present; otherwise use powershell + if (NOT DEFINED _VCPKG_POWERSHELL_PATH) + find_program(_VCPKG_PWSH_PATH pwsh) + if (_VCPKG_PWSH_PATH-NOTFOUND) + message(DEBUG "vcpkg: Could not find PowerShell Core; falling back to PowerShell") + find_program(_VCPKG_BUILTIN_POWERSHELL_PATH powershell REQUIRED) + set(_VCPKG_POWERSHELL_PATH "${_VCPKG_BUILTIN_POWERSHELL_PATH}" CACHE INTERNAL "The path to the PowerShell implementation to use.") + else() + set(_VCPKG_POWERSHELL_PATH "${_VCPKG_PWSH_PATH}" CACHE INTERNAL "The path to the PowerShell implementation to use.") + endif() + endif() # _VCPKG_POWERSHELL_PATH +endfunction() + function(add_executable name) _add_executable(${ARGV}) list(FIND ARGV "IMPORTED" IMPORTED_IDX) @@ -403,12 +417,13 @@ function(add_executable name) if(IMPORTED_IDX EQUAL -1 AND ALIAS_IDX EQUAL -1) if(VCPKG_APPLOCAL_DEPS) if(_VCPKG_TARGET_TRIPLET_PLAT MATCHES "windows|uwp") + _vcpkg_set_powershell_path() set(EXTRA_OPTIONS "") if(X_VCPKG_APPLOCAL_DEPS_SERIALIZED) set(EXTRA_OPTIONS USES_TERMINAL) endif() add_custom_command(TARGET ${name} POST_BUILD - COMMAND powershell -noprofile -executionpolicy Bypass -file ${_VCPKG_TOOLCHAIN_DIR}/msbuild/applocal.ps1 + COMMAND "${_VCPKG_POWERSHELL_PATH}" -noprofile -executionpolicy Bypass -file "${_VCPKG_TOOLCHAIN_DIR}/msbuild/applocal.ps1" -targetBinary $ -installedDir "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}$<$:/debug>/bin" -OutVariable out @@ -437,8 +452,9 @@ function(add_library name) if(IMPORTED_IDX EQUAL -1 AND INTERFACE_IDX EQUAL -1 AND ALIAS_IDX EQUAL -1) get_target_property(IS_LIBRARY_SHARED ${name} TYPE) if(VCPKG_APPLOCAL_DEPS AND _VCPKG_TARGET_TRIPLET_PLAT MATCHES "windows|uwp" AND (IS_LIBRARY_SHARED STREQUAL "SHARED_LIBRARY" OR IS_LIBRARY_SHARED STREQUAL "MODULE_LIBRARY")) + _vcpkg_set_powershell_path() add_custom_command(TARGET ${name} POST_BUILD - COMMAND powershell -noprofile -executionpolicy Bypass -file ${_VCPKG_TOOLCHAIN_DIR}/msbuild/applocal.ps1 + COMMAND "${_VCPKG_POWERSHELL_PATH}" -noprofile -executionpolicy Bypass -file "${_VCPKG_TOOLCHAIN_DIR}/msbuild/applocal.ps1" -targetBinary $ -installedDir "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}$<$:/debug>/bin" -OutVariable out diff --git a/scripts/cmake/vcpkg_copy_tool_dependencies.cmake b/scripts/cmake/vcpkg_copy_tool_dependencies.cmake index 1784a4d145c..681c80461f9 100644 --- a/scripts/cmake/vcpkg_copy_tool_dependencies.cmake +++ b/scripts/cmake/vcpkg_copy_tool_dependencies.cmake @@ -17,16 +17,16 @@ ## * [glib](https://github.com/Microsoft/vcpkg/blob/master/ports/glib/portfile.cmake) ## * [fltk](https://github.com/Microsoft/vcpkg/blob/master/ports/fltk/portfile.cmake) function(vcpkg_copy_tool_dependencies TOOL_DIR) - find_program(PS_EXE powershell PATHS ${DOWNLOADS}/tool) - if (PS_EXE-NOTFOUND) - message(FATAL_ERROR "Could not find powershell in vcpkg tools, please open an issue to report this.") + find_program(PWSH_EXE pwsh) + if (PWSH_EXE-NOTFOUND) + message(FATAL_ERROR "Could not find PowerShell Core; please open an issue to report this.") endif() macro(search_for_dependencies PATH_TO_SEARCH) file(GLOB TOOLS ${TOOL_DIR}/*.exe ${TOOL_DIR}/*.dll) foreach(TOOL ${TOOLS}) vcpkg_execute_required_process( - COMMAND ${PS_EXE} -noprofile -executionpolicy Bypass -nologo - -file ${SCRIPTS}/buildsystems/msbuild/applocal.ps1 + COMMAND "${PWSH_EXE}" -noprofile -executionpolicy Bypass -nologo + -file "${SCRIPTS}/buildsystems/msbuild/applocal.ps1" -targetBinary ${TOOL} -installedDir ${PATH_TO_SEARCH} WORKING_DIRECTORY ${VCPKG_ROOT_DIR} diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h index 71e386a5cf2..607a75c8eed 100644 --- a/toolsrc/include/vcpkg/base/files.h +++ b/toolsrc/include/vcpkg/base/files.h @@ -234,10 +234,19 @@ namespace vcpkg::Files void print_paths(const std::vector& paths); - /// Performs "lhs / rhs" according to the C++17 Filesystem Library Specification. - /// This function exists as a workaround for TS implementations. + // Performs "lhs / rhs" according to the C++17 Filesystem Library Specification. + // This function exists as a workaround for TS implementations. fs::path combine(const fs::path& lhs, const fs::path& rhs); +#if defined(_WIN32) + constexpr char preferred_separator = '\\'; +#else + constexpr char preferred_separator = '/'; +#endif // _WIN32 + + // Adds file as a new path element to the end of base, with an additional slash if necessary + std::string add_filename(StringView base, StringView file); + #if defined(_WIN32) fs::path win32_fix_path_case(const fs::path& source); #endif // _WIN32 diff --git a/toolsrc/include/vcpkg/tools.h b/toolsrc/include/vcpkg/tools.h index f9618a52dcb..8f0398a5ce6 100644 --- a/toolsrc/include/vcpkg/tools.h +++ b/toolsrc/include/vcpkg/tools.h @@ -18,6 +18,7 @@ namespace vcpkg static const std::string GIT = "git"; static const std::string MONO = "mono"; static const std::string NINJA = "ninja"; + static const std::string POWERSHELL_CORE = "powershell-core"; static const std::string NUGET = "nuget"; static const std::string IFW_INSTALLER_BASE = "ifw_installerbase"; static const std::string IFW_BINARYCREATOR = "ifw_binarycreator"; diff --git a/toolsrc/src/vcpkg-test/files.cpp b/toolsrc/src/vcpkg-test/files.cpp index 429a4ba1538..94cf7e1ddb5 100644 --- a/toolsrc/src/vcpkg-test/files.cpp +++ b/toolsrc/src/vcpkg-test/files.cpp @@ -250,6 +250,21 @@ TEST_CASE ("win32_fix_path_case", "[files]") } #endif // _WIN32 +TEST_CASE ("add_filename", "[files]") +{ + using vcpkg::Files::add_filename; + using vcpkg::Files::preferred_separator; + + CHECK(add_filename("a/b", "c") == std::string("a/b") + preferred_separator + "c"); + CHECK(add_filename("a/b/", "c") == "a/b/c"); + CHECK(add_filename("a/b\\", "c") == "a/b\\c"); + CHECK(add_filename("", "c") == "c"); + + // note that we don't special case slashes in the second argument; the caller shouldn't do that + CHECK(add_filename("a/b/", "\\c") == "a/b/\\c"); + CHECK(add_filename("a/b\\", "/c") == "a/b\\/c"); +} + #if defined(CATCH_CONFIG_ENABLE_BENCHMARKING) TEST_CASE ("remove all -- benchmarks", "[files][!benchmark]") { diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index 2d82e1df17f..d00b9b7a60b 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -23,7 +23,6 @@ #include #include -#if defined(_WIN32) namespace { struct IsSlash @@ -32,7 +31,11 @@ namespace }; constexpr IsSlash is_slash; +} // unnamed namespace +#if defined(_WIN32) +namespace +{ template bool wide_starts_with(const std::wstring& haystack, const wchar_t (&needle)[N]) noexcept { @@ -1182,14 +1185,14 @@ namespace vcpkg::Files auto paths = Strings::split_paths(System::get_environment_variable("PATH").value_or_exit(VCPKG_LINE_INFO)); std::vector ret; - std::error_code ec; for (auto&& path : paths) { - auto base = path + "/" + name; + auto base = add_filename(path, name); + for (auto&& ext : EXTS) { auto p = fs::u8path(base + ext.c_str()); - if (Util::find(ret, p) == ret.end() && this->exists(p, ec)) + if (Util::find(ret, p) == ret.end() && this->exists(p, ignore_errors)) { ret.push_back(p); Debug::print("Found path: ", fs::u8string(p), '\n'); @@ -1372,4 +1375,26 @@ namespace vcpkg::Files return fs::path(std::move(in_progress)); } #endif // _WIN32 + + std::string add_filename(StringView base, StringView file) + { + std::string result; + const auto base_size = base.size(); + const auto file_size = file.size(); + if (base_size != 0 && !is_slash(base.data()[base_size - 1])) + { + result.reserve(base_size + file_size + 1); + result.append(base.data(), base_size); + result.push_back(preferred_separator); + result.append(file.data(), file_size); + } + else + { + result.reserve(base_size + file_size); + result.append(base.data(), base_size); + result.append(file.data(), file_size); + } + + return result; + } } diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 9b4e7b4287a..7eaaf6aad95 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -338,13 +338,6 @@ namespace vcpkg::Build return base_env.cmd_cache.get_lazy(build_env_cmd, [&]() { const fs::path& powershell_exe_path = paths.get_tool_exe("powershell-core"); - auto& fs = paths.get_filesystem(); - if (!fs.exists(powershell_exe_path.parent_path() / "powershell.exe")) - { - fs.copy( - powershell_exe_path, powershell_exe_path.parent_path() / "powershell.exe", fs::copy_options::none); - } - auto clean_env = System::get_modified_clean_environment( base_env.env_map, fs::u8string(powershell_exe_path.parent_path()) + ";"); if (build_env_cmd.empty()) diff --git a/toolsrc/src/vcpkg/tools.cpp b/toolsrc/src/vcpkg/tools.cpp index 5531a1daca3..d308290ae46 100644 --- a/toolsrc/src/vcpkg/tools.cpp +++ b/toolsrc/src/vcpkg/tools.cpp @@ -464,6 +464,36 @@ Mono JIT compiler version 6.8.0.105 (Debian 6.8.0.105+dfsg-2 Wed Feb 26 23:23:50 } }; + struct PowerShellCoreProvider : ToolProvider + { + std::string m_exe = "pwsh"; + + virtual const std::string& tool_data_name() const override { return m_exe; } + virtual const std::string& exe_stem() const override { return m_exe; } + virtual std::array default_min_version() const override { return {7, 0, 3}; } + + virtual Optional get_version(const VcpkgPaths&, const fs::path& path_to_exe) const override + { + const auto pwsh_invocation = System::cmd_execute_and_capture_output( + System::CmdLineBuilder().path_arg(path_to_exe).string_arg("--version").extract()); + if (pwsh_invocation.exit_code != 0) + { + return nullopt; + } + + // Sample output: PowerShell 7.0.3\r\n + auto output = std::move(pwsh_invocation.output); + if (!Strings::starts_with(output, "PowerShell ")) + { + Checks::exit_with_message( + VCPKG_LINE_INFO, "Unexpected format of powershell-core version string: %s", output); + } + + output.erase(0, 11); + return Strings::trim(std::move(output)); + } + }; + struct ToolCacheImpl final : ToolCache { vcpkg::Cache path_only_cache; @@ -511,6 +541,14 @@ Mono JIT compiler version 6.8.0.105 (Debian 6.8.0.105+dfsg-2 Wed Feb 26 23:23:50 } return get_path(paths, NinjaProvider()); } + if (tool == Tools::POWERSHELL_CORE) + { + if (System::get_environment_variable("VCPKG_FORCE_SYSTEM_BINARIES").has_value()) + { + return {"pwsh", "0"}; + } + return get_path(paths, PowerShellCoreProvider()); + } if (tool == Tools::NUGET) return get_path(paths, NuGetProvider()); if (tool == Tools::IFW_INSTALLER_BASE) return get_path(paths, IfwInstallerBaseProvider()); if (tool == Tools::MONO) return get_path(paths, MonoProvider());