aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorras0219 <robertallenschumacher@gmail.com>2020-07-01 11:36:09 -0700
committerGitHub <noreply@github.com>2020-07-01 11:36:09 -0700
commit135f91de1eef9e906eb7a5bcf323f6eff9a2b5da (patch)
tree71dfb029d57d3a205a8685bd357586148480d09c /toolsrc/src
parent42f70a42766ff3da9c0464dd78f1eed0e8ac3789 (diff)
downloadvcpkg-135f91de1eef9e906eb7a5bcf323f6eff9a2b5da.tar.gz
vcpkg-135f91de1eef9e906eb7a5bcf323f6eff9a2b5da.zip
[vcpkg] Implement --x-write-nuget-packages-config= setting for `install` and `x-set-installed` (#12138)
* [vcpkg] Implement --x-write-nuget-packages-config= setting for `install` and `x-set-installed`. * [vcpkg] Add end-to-end testing suite for install, remove, and binary caching * [vcpkg] Define `$TestingRoot in end-to-end-tests.ps1 * [vcpkg] Address CR comments Co-authored-by: Robert Schumacher <roschuma@microsoft.com>
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/vcpkg-test/binarycaching.cpp88
-rw-r--r--toolsrc/src/vcpkg/base/files.cpp16
-rw-r--r--toolsrc/src/vcpkg/binarycaching.cpp59
-rw-r--r--toolsrc/src/vcpkg/build.cpp7
-rw-r--r--toolsrc/src/vcpkg/commands.setinstalled.cpp30
-rw-r--r--toolsrc/src/vcpkg/install.cpp42
6 files changed, 217 insertions, 25 deletions
diff --git a/toolsrc/src/vcpkg-test/binarycaching.cpp b/toolsrc/src/vcpkg-test/binarycaching.cpp
index 817b85e03..b220b5ccb 100644
--- a/toolsrc/src/vcpkg-test/binarycaching.cpp
+++ b/toolsrc/src/vcpkg-test/binarycaching.cpp
@@ -1,10 +1,11 @@
#include <catch2/catch.hpp>
#include <vcpkg/binarycaching.private.h>
+#include <vcpkg/binarycaching.h>
#include <vcpkg/base/files.h>
+#include <vcpkg/dependencies.h>
#include <vcpkg/vcpkgcmdarguments.h>
#include <vcpkg/sourceparagraph.h>
#include <vcpkg/paragraphs.h>
-#include <vcpkg/dependencies.h>
#include <string>
using namespace vcpkg;
@@ -96,9 +97,9 @@ Features: a, b
Dependencies:
</description>
<packageTypes><packageType name="vcpkg"/></packageTypes>
- </metadata>
+ </metadata>
<files><file src=")" PKGPATH R"(" target=""/></files>
- </package>
+</package>
)";
auto expected_lines = Strings::split(expected, '\n');
auto nuspec_lines = Strings::split(nuspec, '\n');
@@ -123,8 +124,14 @@ TEST_CASE ("XmlSerializer", "[XmlSerializer]")
xml = XmlSerializer();
xml.emit_declaration();
- xml.start_complex_open_tag("a").text_attr("b", "<").text_attr("c", " ").finish_self_closing_complex_tag();
- REQUIRE(xml.buf == R"(<?xml version="1.0" encoding="utf-8"?><a b="&lt;" c=" "/>)");
+ xml.start_complex_open_tag("a")
+ .text_attr("b", "<")
+ .text_attr("c", " ")
+ .finish_self_closing_complex_tag()
+ .line_break();
+ xml.simple_tag("d", "e");
+ REQUIRE(xml.buf == R"(<?xml version="1.0" encoding="utf-8"?><a b="&lt;" c=" "/>)"
+ "\n<d>e</d>");
xml = XmlSerializer();
xml.start_complex_open_tag("a").finish_complex_open_tag();
@@ -134,5 +141,72 @@ TEST_CASE ("XmlSerializer", "[XmlSerializer]")
xml.line_break();
xml.open_tag("a").line_break().line_break();
xml.close_tag("a").line_break().line_break();
- REQUIRE(xml.buf == "\n<a>\n \n </a>\n\n");
-} \ No newline at end of file
+ REQUIRE(xml.buf == "\n<a>\n\n</a>\n\n");
+
+ xml = XmlSerializer();
+ xml.start_complex_open_tag("a")
+ .text_attr("b", "<")
+ .line_break()
+ .text_attr("c", " ")
+ .finish_complex_open_tag()
+ .line_break();
+ xml.simple_tag("d", "e").line_break();
+ REQUIRE(xml.buf == "<a b=\"&lt;\"\n c=\" \">\n <d>e</d>\n");
+}
+
+TEST_CASE ("generate_nuget_packages_config", "[generate_nuget_packages_config]")
+{
+ Dependencies::ActionPlan plan;
+ auto packageconfig = generate_nuget_packages_config(plan);
+ REQUIRE(packageconfig == R"(<?xml version="1.0" encoding="utf-8"?>
+<packages>
+</packages>
+)");
+
+ auto pghs = Paragraphs::parse_paragraphs(R"(
+Source: zlib
+Version: 1.5
+Description: a spiffy compression library wrapper
+)",
+ "<testdata>");
+ REQUIRE(pghs.has_value());
+ auto maybe_scf = SourceControlFile::parse_control_file(fs::path(), std::move(*pghs.get()));
+ REQUIRE(maybe_scf.has_value());
+ SourceControlFileLocation scfl{std::move(*maybe_scf.get()), fs::path()};
+ plan.install_actions.push_back(Dependencies::InstallPlanAction());
+ plan.install_actions[0].spec = PackageSpec("zlib", Triplet::X64_ANDROID);
+ plan.install_actions[0].source_control_file_location = scfl;
+ plan.install_actions[0].abi_info = Build::AbiInfo{};
+ plan.install_actions[0].abi_info.get()->package_abi = "packageabi";
+
+ packageconfig = generate_nuget_packages_config(plan);
+ REQUIRE(packageconfig == R"(<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="zlib_x64-android" version="1.5.0-packageabi"/>
+</packages>
+)");
+
+ auto pghs2 = Paragraphs::parse_paragraphs(R"(
+Source: zlib2
+Version: 1.52
+Description: a spiffy compression library wrapper
+)",
+ "<testdata>");
+ REQUIRE(pghs2.has_value());
+ auto maybe_scf2 = SourceControlFile::parse_control_file(fs::path(), std::move(*pghs2.get()));
+ REQUIRE(maybe_scf2.has_value());
+ SourceControlFileLocation scfl2{std::move(*maybe_scf2.get()), fs::path()};
+ plan.install_actions.push_back(Dependencies::InstallPlanAction());
+ plan.install_actions[1].spec = PackageSpec("zlib2", Triplet::X64_ANDROID);
+ plan.install_actions[1].source_control_file_location = scfl2;
+ plan.install_actions[1].abi_info = Build::AbiInfo{};
+ plan.install_actions[1].abi_info.get()->package_abi = "packageabi2";
+
+ packageconfig = generate_nuget_packages_config(plan);
+ REQUIRE(packageconfig == R"(<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="zlib_x64-android" version="1.5.0-packageabi"/>
+ <package id="zlib2_x64-android" version="1.52.0-packageabi2"/>
+</packages>
+)");
+}
diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp
index 9d9aecb69..2e39073ce 100644
--- a/toolsrc/src/vcpkg/base/files.cpp
+++ b/toolsrc/src/vcpkg/base/files.cpp
@@ -989,4 +989,20 @@ namespace vcpkg::Files
message.push_back('\n');
System::print2(message);
}
+
+ fs::path combine(const fs::path& lhs, const fs::path& rhs)
+ {
+#if VCPKG_USE_STD_FILESYSTEM
+ return lhs / rhs;
+#else // ^^^ VCPKG_USE_STD_FILESYSTEM // !VCPKG_USE_STD_FILESYSTEM vvv
+ if (rhs.is_absolute())
+ {
+ return rhs;
+ }
+ else
+ {
+ return lhs / rhs;
+ }
+#endif
+ }
}
diff --git a/toolsrc/src/vcpkg/binarycaching.cpp b/toolsrc/src/vcpkg/binarycaching.cpp
index 5bebc4fb8..532e07032 100644
--- a/toolsrc/src/vcpkg/binarycaching.cpp
+++ b/toolsrc/src/vcpkg/binarycaching.cpp
@@ -285,7 +285,7 @@ namespace
for (auto&& action : plan.install_actions)
{
auto& spec = action.spec;
- fs.remove_all_inside(paths.package_dir(spec), VCPKG_LINE_INFO);
+ fs.remove_all(paths.package_dir(spec), VCPKG_LINE_INFO);
nuget_refs.emplace_back(spec, NugetReference(action));
}
@@ -615,42 +615,57 @@ XmlSerializer& XmlSerializer::emit_declaration()
}
XmlSerializer& XmlSerializer::open_tag(StringLiteral sl)
{
+ emit_pending_indent();
Strings::append(buf, '<', sl, '>');
- indent += 2;
+ m_indent += 2;
return *this;
}
XmlSerializer& XmlSerializer::start_complex_open_tag(StringLiteral sl)
{
+ emit_pending_indent();
Strings::append(buf, '<', sl);
- indent += 2;
+ m_indent += 2;
return *this;
}
XmlSerializer& XmlSerializer::text_attr(StringLiteral name, StringView content)
{
- Strings::append(buf, ' ', name, "=\"");
+ if (m_pending_indent)
+ {
+ m_pending_indent = false;
+ buf.append(m_indent, ' ');
+ }
+ else
+ {
+ buf.push_back(' ');
+ }
+ Strings::append(buf, name, "=\"");
text(content);
Strings::append(buf, '"');
return *this;
}
XmlSerializer& XmlSerializer::finish_complex_open_tag()
{
+ emit_pending_indent();
Strings::append(buf, '>');
return *this;
}
XmlSerializer& XmlSerializer::finish_self_closing_complex_tag()
{
+ emit_pending_indent();
Strings::append(buf, "/>");
- indent -= 2;
+ m_indent -= 2;
return *this;
}
XmlSerializer& XmlSerializer::close_tag(StringLiteral sl)
{
+ m_indent -= 2;
+ emit_pending_indent();
Strings::append(buf, "</", sl, '>');
- indent -= 2;
return *this;
}
XmlSerializer& XmlSerializer::text(StringView sv)
{
+ emit_pending_indent();
for (auto ch : sv)
{
if (ch == '&')
@@ -682,12 +697,21 @@ XmlSerializer& XmlSerializer::text(StringView sv)
}
XmlSerializer& XmlSerializer::simple_tag(StringLiteral tag, StringView content)
{
- return open_tag(tag).text(content).close_tag(tag);
+ return emit_pending_indent().open_tag(tag).text(content).close_tag(tag);
}
XmlSerializer& XmlSerializer::line_break()
{
buf.push_back('\n');
- buf.append(indent, ' ');
+ m_pending_indent = true;
+ return *this;
+}
+XmlSerializer& XmlSerializer::emit_pending_indent()
+{
+ if (m_pending_indent)
+ {
+ m_pending_indent = false;
+ buf.append(m_indent, ' ');
+ }
return *this;
}
@@ -1118,3 +1142,22 @@ void vcpkg::help_topic_binary_caching(const VcpkgPaths&)
System::print2(tbl.m_str);
}
+
+std::string vcpkg::generate_nuget_packages_config(const Dependencies::ActionPlan& action)
+{
+ auto refs = Util::fmap(action.install_actions,
+ [&](const Dependencies::InstallPlanAction& ipa) { return NugetReference(ipa); });
+ XmlSerializer xml;
+ xml.emit_declaration().line_break();
+ xml.open_tag("packages").line_break();
+ for (auto&& ref : refs)
+ {
+ xml.start_complex_open_tag("package")
+ .text_attr("id", ref.id)
+ .text_attr("version", ref.version)
+ .finish_self_closing_complex_tag()
+ .line_break();
+ }
+ xml.close_tag("packages").line_break();
+ return std::move(xml.buf);
+}
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
index 5e2f8778b..7d2976165 100644
--- a/toolsrc/src/vcpkg/build.cpp
+++ b/toolsrc/src/vcpkg/build.cpp
@@ -484,8 +484,9 @@ namespace vcpkg::Build
env);
out_file.close();
- Checks::check_exit(
- VCPKG_LINE_INFO, !compiler_hash.empty(), "Error occured while detecting compiler information");
+ Checks::check_exit(VCPKG_LINE_INFO,
+ !compiler_hash.empty(),
+ "Error occured while detecting compiler information. Pass `--debug` for more information.");
Debug::print("Detecting compiler hash for triplet ", triplet, ": ", compiler_hash, "\n");
return compiler_hash;
@@ -866,6 +867,8 @@ namespace vcpkg::Build
for (auto it = action_plan.install_actions.begin(); it != action_plan.install_actions.end(); ++it)
{
auto& action = *it;
+ if (action.abi_info.has_value()) continue;
+
std::vector<AbiEntry> dependency_abis;
if (!Util::Enum::to_bool(action.build_options.only_downloads))
{
diff --git a/toolsrc/src/vcpkg/commands.setinstalled.cpp b/toolsrc/src/vcpkg/commands.setinstalled.cpp
index f52e4942b..df191ee3e 100644
--- a/toolsrc/src/vcpkg/commands.setinstalled.cpp
+++ b/toolsrc/src/vcpkg/commands.setinstalled.cpp
@@ -14,16 +14,22 @@
namespace vcpkg::Commands::SetInstalled
{
static constexpr StringLiteral OPTION_DRY_RUN = "--dry-run";
+ static constexpr StringLiteral OPTION_WRITE_PACKAGES_CONFIG = "--x-write-nuget-packages-config";
static constexpr CommandSwitch INSTALL_SWITCHES[] = {
{OPTION_DRY_RUN, "Do not actually build or install"},
};
+ static constexpr CommandSetting INSTALL_SETTINGS[] = {
+ {OPTION_WRITE_PACKAGES_CONFIG,
+ "Writes out a NuGet packages.config-formatted file for use with external binary caching.\n"
+ "See `vcpkg help binarycaching` for more information."},
+ };
const CommandStructure COMMAND_STRUCTURE = {
create_example_string(R"(x-set-installed <package>...)"),
0,
SIZE_MAX,
- {INSTALL_SWITCHES},
+ {INSTALL_SWITCHES, INSTALL_SETTINGS},
nullptr,
};
@@ -34,7 +40,8 @@ namespace vcpkg::Commands::SetInstalled
const CMakeVars::CMakeVarProvider& cmake_vars,
const std::vector<FullPackageSpec>& specs,
const Build::BuildPackageOptions& install_plan_options,
- DryRun dry_run)
+ DryRun dry_run,
+ const Optional<fs::path>& maybe_pkgsconfig)
{
// We have a set of user-requested specs.
// We need to know all the specs which are required to fulfill dependencies for those specs.
@@ -91,6 +98,16 @@ namespace vcpkg::Commands::SetInstalled
Dependencies::print_plan(action_plan, true, paths.ports);
+ if (auto p_pkgsconfig = maybe_pkgsconfig.get())
+ {
+ Build::compute_all_abis(paths, action_plan, cmake_vars, status_db);
+ auto& fs = paths.get_filesystem();
+ auto pkgsconfig_path = Files::combine(paths.original_cwd, *p_pkgsconfig);
+ auto pkgsconfig_contents = generate_nuget_packages_config(action_plan);
+ fs.write_contents(pkgsconfig_path, pkgsconfig_contents, VCPKG_LINE_INFO);
+ System::print2("Wrote NuGet packages config information to ", pkgsconfig_path.u8string(), "\n");
+ }
+
if (dry_run == DryRun::Yes)
{
Checks::exit_success(VCPKG_LINE_INFO);
@@ -142,6 +159,12 @@ namespace vcpkg::Commands::SetInstalled
PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
auto cmake_vars = CMakeVars::make_triplet_cmake_var_provider(paths);
+ Optional<fs::path> pkgsconfig;
+ auto it_pkgsconfig = options.settings.find(OPTION_WRITE_PACKAGES_CONFIG);
+ if (it_pkgsconfig != options.settings.end())
+ {
+ pkgsconfig = it_pkgsconfig->second;
+ }
perform_and_exit_ex(args,
paths,
provider,
@@ -149,6 +172,7 @@ namespace vcpkg::Commands::SetInstalled
*cmake_vars,
specs,
install_plan_options,
- dry_run ? DryRun::Yes : DryRun::No);
+ dry_run ? DryRun::Yes : DryRun::No,
+ pkgsconfig);
}
}
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
index 5750469ad..aa79bb1f2 100644
--- a/toolsrc/src/vcpkg/install.cpp
+++ b/toolsrc/src/vcpkg/install.cpp
@@ -500,6 +500,7 @@ namespace vcpkg::Install
static constexpr StringLiteral OPTION_XUNIT = "--x-xunit";
static constexpr StringLiteral OPTION_USE_ARIA2 = "--x-use-aria2";
static constexpr StringLiteral OPTION_CLEAN_AFTER_BUILD = "--clean-after-build";
+ static constexpr StringLiteral OPTION_WRITE_PACKAGES_CONFIG = "--x-write-nuget-packages-config";
static constexpr std::array<CommandSwitch, 8> INSTALL_SWITCHES = {{
{OPTION_DRY_RUN, "Do not actually build or install"},
@@ -511,8 +512,11 @@ namespace vcpkg::Install
{OPTION_USE_ARIA2, "Use aria2 to perform download tasks"},
{OPTION_CLEAN_AFTER_BUILD, "Clean buildtrees, packages and downloads after building each package"},
}};
- static constexpr std::array<CommandSetting, 1> INSTALL_SETTINGS = {{
+ static constexpr std::array<CommandSetting, 2> INSTALL_SETTINGS = {{
{OPTION_XUNIT, "File to output results in XUnit format (Internal use)"},
+ {OPTION_WRITE_PACKAGES_CONFIG,
+ "Writes out a NuGet packages.config-formatted file for use with external binary caching.\nSee `vcpkg help "
+ "binarycaching` for more information."},
}};
std::vector<std::string> get_all_port_names(const VcpkgPaths& paths)
@@ -654,7 +658,8 @@ namespace vcpkg::Install
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet)
{
// input sanitization
- const ParsedArguments options = args.parse_arguments(paths.manifest_mode_enabled() ? MANIFEST_COMMAND_STRUCTURE : COMMAND_STRUCTURE);
+ const ParsedArguments options =
+ args.parse_arguments(paths.manifest_mode_enabled() ? MANIFEST_COMMAND_STRUCTURE : COMMAND_STRUCTURE);
auto binaryprovider =
create_binary_provider_from_configs(paths, args.binary_sources).value_or_exit(VCPKG_LINE_INFO);
@@ -697,8 +702,10 @@ namespace vcpkg::Install
if (ec)
{
- Checks::exit_with_message(VCPKG_LINE_INFO, "Failed to load manifest file (%s): %s\n",
- path_to_manifest.u8string(), ec.message());
+ Checks::exit_with_message(VCPKG_LINE_INFO,
+ "Failed to load manifest file (%s): %s\n",
+ path_to_manifest.u8string(),
+ ec.message());
}
std::vector<FullPackageSpec> specs;
@@ -716,7 +723,21 @@ namespace vcpkg::Install
Checks::exit_fail(VCPKG_LINE_INFO);
}
- Commands::SetInstalled::perform_and_exit_ex(args, paths, provider, *binaryprovider, var_provider, specs, install_plan_options, dry_run ? Commands::DryRun::Yes : Commands::DryRun::No);
+ Optional<fs::path> pkgsconfig;
+ auto it_pkgsconfig = options.settings.find(OPTION_WRITE_PACKAGES_CONFIG);
+ if (it_pkgsconfig != options.settings.end())
+ {
+ pkgsconfig = fs::u8path(it_pkgsconfig->second);
+ }
+ Commands::SetInstalled::perform_and_exit_ex(args,
+ paths,
+ provider,
+ *binaryprovider,
+ var_provider,
+ specs,
+ install_plan_options,
+ dry_run ? Commands::DryRun::Yes : Commands::DryRun::No,
+ pkgsconfig);
}
const std::vector<FullPackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
@@ -799,6 +820,17 @@ namespace vcpkg::Install
Dependencies::print_plan(action_plan, is_recursive, paths.ports);
+ auto it_pkgsconfig = options.settings.find(OPTION_WRITE_PACKAGES_CONFIG);
+ if (it_pkgsconfig != options.settings.end())
+ {
+ Build::compute_all_abis(paths, action_plan, var_provider, status_db);
+
+ auto pkgsconfig_path = Files::combine(paths.original_cwd, fs::u8path(it_pkgsconfig->second));
+ auto pkgsconfig_contents = generate_nuget_packages_config(action_plan);
+ fs.write_contents(pkgsconfig_path, pkgsconfig_contents, VCPKG_LINE_INFO);
+ System::print2("Wrote NuGet packages config information to ", pkgsconfig_path.u8string(), "\n");
+ }
+
if (dry_run)
{
Checks::exit_success(VCPKG_LINE_INFO);