aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorras0219 <533828+ras0219@users.noreply.github.com>2020-08-13 18:36:33 -0700
committerGitHub <noreply@github.com>2020-08-13 18:36:33 -0700
commit0b5bbe30d940c597242cefa899dc93168054e466 (patch)
treea02a36758c8d4f794194dd37b48a7649fc143ee3
parent5bb91a9452c2155e8ccd69c88629af24507249d4 (diff)
downloadvcpkg-0b5bbe30d940c597242cefa899dc93168054e466.tar.gz
vcpkg-0b5bbe30d940c597242cefa899dc93168054e466.zip
[vcpkg] Lift `--x-json` to a global option, implement experimental `x-package-info` command (#12845)
* [vcpkg] Improve error reporting in vcpkg::Json * [vcpkg] Lift --x-json to a common option * [vcpkg] Address warnings-as-errors in VS2015 * [vcpkg] Remove unused local * [vcpkg] Extract vcpkg::Install::get_cmake_usage * [vcpkg] Implement vcpkg::serialize_ipv(ipv, paths) * [vcpkg] Implement x-package-info to enable tooling * [vcpkg] Fixup tests to respect new cli mode Co-authored-by: Robert Schumacher <roschuma@microsoft.com>
-rw-r--r--toolsrc/include/vcpkg/base/json.h4
-rw-r--r--toolsrc/include/vcpkg/binaryparagraph.h2
-rw-r--r--toolsrc/include/vcpkg/commands.info.h13
-rw-r--r--toolsrc/include/vcpkg/install.h11
-rw-r--r--toolsrc/include/vcpkg/statusparagraph.h2
-rw-r--r--toolsrc/include/vcpkg/vcpkgcmdarguments.h4
-rw-r--r--toolsrc/src/vcpkg-test/commands.cpp3
-rw-r--r--toolsrc/src/vcpkg-test/manifests.cpp6
-rw-r--r--toolsrc/src/vcpkg-test/strings.cpp4
-rw-r--r--toolsrc/src/vcpkg-test/system.cpp4
-rw-r--r--toolsrc/src/vcpkg.cpp4
-rw-r--r--toolsrc/src/vcpkg/base/json.cpp10
-rw-r--r--toolsrc/src/vcpkg/commands.cpp3
-rw-r--r--toolsrc/src/vcpkg/commands.info.cpp146
-rw-r--r--toolsrc/src/vcpkg/commands.list.cpp8
-rw-r--r--toolsrc/src/vcpkg/install.cpp46
-rw-r--r--toolsrc/src/vcpkg/statusparagraphs.cpp40
-rw-r--r--toolsrc/src/vcpkg/vcpkgcmdarguments.cpp4
-rw-r--r--toolsrc/src/vcpkg/vcpkglib.cpp1
-rw-r--r--toolsrc/src/vcpkg/vcpkgpaths.cpp2
-rw-r--r--toolsrc/windows-bootstrap/vcpkglib/vcpkglib.vcxproj2
21 files changed, 287 insertions, 32 deletions
diff --git a/toolsrc/include/vcpkg/base/json.h b/toolsrc/include/vcpkg/base/json.h
index b7adde38f..a4ad44ebd 100644
--- a/toolsrc/include/vcpkg/base/json.h
+++ b/toolsrc/include/vcpkg/base/json.h
@@ -227,13 +227,13 @@ namespace vcpkg::Json
Value& operator[](StringView key) noexcept
{
auto res = this->get(key);
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, res);
+ vcpkg::Checks::check_exit(VCPKG_LINE_INFO, res, "missing key: \"%s\"", key);
return *res;
}
const Value& operator[](StringView key) const noexcept
{
auto res = this->get(key);
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, res);
+ vcpkg::Checks::check_exit(VCPKG_LINE_INFO, res, "missing key: \"%s\"", key);
return *res;
}
diff --git a/toolsrc/include/vcpkg/binaryparagraph.h b/toolsrc/include/vcpkg/binaryparagraph.h
index 2d2e4cf20..f10c41af0 100644
--- a/toolsrc/include/vcpkg/binaryparagraph.h
+++ b/toolsrc/include/vcpkg/binaryparagraph.h
@@ -39,7 +39,7 @@ namespace vcpkg
std::vector<std::string> default_features;
std::vector<std::string> dependencies;
std::string abi;
- Type type;
+ Type type = {Type::UNKNOWN};
};
bool operator==(const BinaryParagraph&, const BinaryParagraph&);
diff --git a/toolsrc/include/vcpkg/commands.info.h b/toolsrc/include/vcpkg/commands.info.h
new file mode 100644
index 000000000..556d1eb01
--- /dev/null
+++ b/toolsrc/include/vcpkg/commands.info.h
@@ -0,0 +1,13 @@
+#pragma once
+
+#include <vcpkg/commands.interface.h>
+
+namespace vcpkg::Commands::Info
+{
+ extern const CommandStructure COMMAND_STRUCTURE;
+
+ struct InfoCommand : PathsCommand
+ {
+ virtual void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const override;
+ };
+}
diff --git a/toolsrc/include/vcpkg/install.h b/toolsrc/include/vcpkg/install.h
index 0ba0932e0..f85d48d8d 100644
--- a/toolsrc/include/vcpkg/install.h
+++ b/toolsrc/include/vcpkg/install.h
@@ -2,6 +2,7 @@
#include <vcpkg/base/chrono.h>
+#include <vcpkg/binaryparagraph.h>
#include <vcpkg/build.h>
#include <vcpkg/dependencies.h>
#include <vcpkg/vcpkgcmdarguments.h>
@@ -90,6 +91,16 @@ namespace vcpkg::Install
const Build::IBuildLogsRecorder& build_logs_recorder,
const CMakeVars::CMakeVarProvider& var_provider);
+ struct CMakeUsageInfo
+ {
+ std::string message;
+ bool usage_file = false;
+ Optional<bool> header_only;
+ std::map<std::string, std::vector<std::string>> cmake_targets_map;
+ };
+
+ CMakeUsageInfo get_cmake_usage(const BinaryParagraph& bpgh, const VcpkgPaths& paths);
+
extern const CommandStructure COMMAND_STRUCTURE;
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, Triplet default_triplet);
diff --git a/toolsrc/include/vcpkg/statusparagraph.h b/toolsrc/include/vcpkg/statusparagraph.h
index dde4ecb19..cf4c3c046 100644
--- a/toolsrc/include/vcpkg/statusparagraph.h
+++ b/toolsrc/include/vcpkg/statusparagraph.h
@@ -61,4 +61,6 @@ namespace vcpkg
const StatusParagraph* core;
std::vector<const StatusParagraph*> features;
};
+
+ Json::Value serialize_ipv(const InstalledPackageView& ipv, const struct VcpkgPaths& paths);
}
diff --git a/toolsrc/include/vcpkg/vcpkgcmdarguments.h b/toolsrc/include/vcpkg/vcpkgcmdarguments.h
index 82c4f6dc2..84cd7c599 100644
--- a/toolsrc/include/vcpkg/vcpkgcmdarguments.h
+++ b/toolsrc/include/vcpkg/vcpkgcmdarguments.h
@@ -153,6 +153,9 @@ namespace vcpkg
constexpr static StringLiteral WAIT_FOR_LOCK_SWITCH = "x-wait-for-lock";
Optional<bool> wait_for_lock = nullopt;
+ constexpr static StringLiteral JSON_SWITCH = "x-json";
+ Optional<bool> json = nullopt;
+
// feature flags
constexpr static StringLiteral FEATURE_FLAGS_ENV = "VCPKG_FEATURE_FLAGS";
constexpr static StringLiteral FEATURE_FLAGS_ARG = "feature-flags";
@@ -169,6 +172,7 @@ namespace vcpkg
bool binary_caching_enabled() const { return binary_caching.value_or(true); }
bool compiler_tracking_enabled() const { return compiler_tracking.value_or(true); }
+ bool output_json() const { return json.value_or(false); }
std::string command;
std::vector<std::string> command_arguments;
diff --git a/toolsrc/src/vcpkg-test/commands.cpp b/toolsrc/src/vcpkg-test/commands.cpp
index eeefa3098..2c3779877 100644
--- a/toolsrc/src/vcpkg-test/commands.cpp
+++ b/toolsrc/src/vcpkg-test/commands.cpp
@@ -24,7 +24,7 @@ TEST_CASE ("get_available_basic_commands works", "[commands]")
TEST_CASE ("get_available_paths_commands works", "[commands]")
{
auto commands_list = Commands::get_available_paths_commands();
- CHECK(commands_list.size() == 18);
+ CHECK(commands_list.size() == 19);
CHECK(Commands::find("/?", commands_list) != nullptr);
CHECK(Commands::find("help", commands_list) != nullptr);
@@ -42,6 +42,7 @@ TEST_CASE ("get_available_paths_commands works", "[commands]")
CHECK(Commands::find("fetch", commands_list) != nullptr);
CHECK(Commands::find("x-ci-clean", commands_list) != nullptr);
CHECK(Commands::find("x-history", commands_list) != nullptr);
+ CHECK(Commands::find("x-package-info", commands_list) != nullptr);
CHECK(Commands::find("x-vsinstances", commands_list) != nullptr);
CHECK(Commands::find("x-format-manifest", commands_list) != nullptr);
diff --git a/toolsrc/src/vcpkg-test/manifests.cpp b/toolsrc/src/vcpkg-test/manifests.cpp
index 9fc041a19..4b450b7be 100644
--- a/toolsrc/src/vcpkg-test/manifests.cpp
+++ b/toolsrc/src/vcpkg-test/manifests.cpp
@@ -8,6 +8,10 @@
#include <vcpkg-test/util.h>
+#if defined(_MSC_VER)
+#pragma warning(disable : 6237)
+#endif
+
using namespace vcpkg;
using namespace vcpkg::Paragraphs;
using namespace vcpkg::Test;
@@ -248,7 +252,7 @@ TEST_CASE ("Serialize all the ports", "[manifests]")
std::vector<std::string> args_list = {"x-format-manifest"};
auto& fs = Files::get_real_filesystem();
auto args = VcpkgCmdArguments::create_from_arg_sequence(args_list.data(), args_list.data() + args_list.size());
- auto paths = VcpkgPaths{fs, args};
+ VcpkgPaths paths{fs, args};
std::vector<SourceControlFile> scfs;
diff --git a/toolsrc/src/vcpkg-test/strings.cpp b/toolsrc/src/vcpkg-test/strings.cpp
index 95a6de2af..cc45365e6 100644
--- a/toolsrc/src/vcpkg-test/strings.cpp
+++ b/toolsrc/src/vcpkg-test/strings.cpp
@@ -8,6 +8,10 @@
#include <utility>
#include <vector>
+#if defined(_MSC_VER)
+#pragma warning(disable : 6237)
+#endif
+
TEST_CASE ("b32 encoding", "[strings]")
{
using u64 = uint64_t;
diff --git a/toolsrc/src/vcpkg-test/system.cpp b/toolsrc/src/vcpkg-test/system.cpp
index 015406358..dec7b5769 100644
--- a/toolsrc/src/vcpkg-test/system.cpp
+++ b/toolsrc/src/vcpkg-test/system.cpp
@@ -11,6 +11,10 @@
#include <string>
+#if defined(_MSC_VER)
+#pragma warning(disable : 6237)
+#endif
+
using vcpkg::nullopt;
using vcpkg::Optional;
using vcpkg::StringView;
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp
index 0158b3755..d0df8749f 100644
--- a/toolsrc/src/vcpkg.cpp
+++ b/toolsrc/src/vcpkg.cpp
@@ -77,7 +77,9 @@ static void inner(vcpkg::Files::Filesystem& fs, const VcpkgCmdArguments& args)
paths.track_feature_flag_metrics();
fs.current_path(paths.root, VCPKG_LINE_INFO);
- if (args.command == "install" || args.command == "remove" || args.command == "export" || args.command == "update")
+ if ((args.command == "install" || args.command == "remove" || args.command == "export" ||
+ args.command == "update") &&
+ !args.output_json())
{
Commands::Version::warn_if_vcpkg_version_mismatch(paths);
std::string surveydate = *GlobalState::g_surveydate.lock();
diff --git a/toolsrc/src/vcpkg/base/json.cpp b/toolsrc/src/vcpkg/base/json.cpp
index 7536e09df..0a9422d66 100644
--- a/toolsrc/src/vcpkg/base/json.cpp
+++ b/toolsrc/src/vcpkg/base/json.cpp
@@ -141,30 +141,30 @@ namespace vcpkg::Json
}
StringView Value::string() const noexcept
{
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_string());
+ vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_string(), "json value is not string");
return underlying_->string;
}
const Array& Value::array() const& noexcept
{
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_array());
+ vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_array(), "json value is not array");
return underlying_->array;
}
Array& Value::array() & noexcept
{
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_array());
+ vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_array(), "json value is not array");
return underlying_->array;
}
Array&& Value::array() && noexcept { return std::move(this->array()); }
const Object& Value::object() const& noexcept
{
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_object());
+ vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_object(), "json value is not object");
return underlying_->object;
}
Object& Value::object() & noexcept
{
- vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_object());
+ vcpkg::Checks::check_exit(VCPKG_LINE_INFO, is_object(), "json value is not object");
return underlying_->object;
}
Object&& Value::object() && noexcept { return std::move(this->object()); }
diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp
index a455867ed..466cc11c0 100644
--- a/toolsrc/src/vcpkg/commands.cpp
+++ b/toolsrc/src/vcpkg/commands.cpp
@@ -15,6 +15,7 @@
#include <vcpkg/commands.format-manifest.h>
#include <vcpkg/commands.h>
#include <vcpkg/commands.hash.h>
+#include <vcpkg/commands.info.h>
#include <vcpkg/commands.integrate.h>
#include <vcpkg/commands.list.h>
#include <vcpkg/commands.owns.h>
@@ -49,6 +50,7 @@ namespace vcpkg::Commands
static const Help::HelpCommand help{};
static const Search::SearchCommand search{};
static const List::ListCommand list{};
+ static const Info::InfoCommand info{};
static const Integrate::IntegrateCommand integrate{};
static const Owns::OwnsCommand owns{};
static const Update::UpdateCommand update{};
@@ -80,6 +82,7 @@ namespace vcpkg::Commands
{"hash", &hash},
{"fetch", &fetch},
{"x-ci-clean", &ciclean},
+ {"x-package-info", &info},
{"x-history", &porthistory},
{"x-vsinstances", &vsinstances},
{"x-format-manifest", &format_manifest},
diff --git a/toolsrc/src/vcpkg/commands.info.cpp b/toolsrc/src/vcpkg/commands.info.cpp
new file mode 100644
index 000000000..afb2642c6
--- /dev/null
+++ b/toolsrc/src/vcpkg/commands.info.cpp
@@ -0,0 +1,146 @@
+#include "pch.h"
+
+#include <vcpkg/base/json.h>
+#include <vcpkg/base/parse.h>
+#include <vcpkg/base/stringliteral.h>
+
+#include <vcpkg/commands.info.h>
+#include <vcpkg/input.h>
+#include <vcpkg/install.h>
+#include <vcpkg/portfileprovider.h>
+#include <vcpkg/statusparagraphs.h>
+#include <vcpkg/vcpkglib.h>
+#include <vcpkg/versiont.h>
+
+namespace vcpkg::Commands::Info
+{
+ static constexpr StringLiteral OPTION_TRANSITIVE = "x-transitive";
+ static constexpr StringLiteral OPTION_INSTALLED = "x-installed";
+
+ static constexpr CommandSwitch INFO_SWITCHES[] = {
+ {OPTION_INSTALLED, "(experimental) Report on installed packages instead of available"},
+ {OPTION_TRANSITIVE, "(experimental) Also report on dependencies of installed packages"},
+ };
+
+ const CommandStructure COMMAND_STRUCTURE = {
+ Strings::format("Display detailed information on packages.\n%s",
+ create_example_string("x-package-info zlib openssl:x64-windows")),
+ 1,
+ SIZE_MAX,
+ {INFO_SWITCHES, {}},
+ nullptr,
+ };
+
+ void InfoCommand::perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) const
+ {
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
+ if (!args.output_json())
+ {
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "This command currently requires --%s", VcpkgCmdArguments::JSON_SWITCH);
+ }
+
+ const bool installed = Util::Sets::contains(options.switches, OPTION_INSTALLED);
+ const bool transitive = Util::Sets::contains(options.switches, OPTION_TRANSITIVE);
+
+ if (transitive && !installed)
+ {
+ Checks::exit_with_message(VCPKG_LINE_INFO, "--%s requires --%s", OPTION_TRANSITIVE, OPTION_INSTALLED);
+ }
+
+ if (installed)
+ {
+ const StatusParagraphs status_paragraphs = database_load_check(paths);
+ std::set<PackageSpec> specs_written;
+ std::vector<PackageSpec> specs_to_write;
+ for (auto&& arg : args.command_arguments)
+ {
+ Parse::ParserBase parser(arg, "<command>");
+ auto maybe_qpkg = parse_qualified_specifier(parser);
+ if (!parser.at_eof() || !maybe_qpkg)
+ {
+ parser.add_error("expected a package specifier");
+ }
+ else if (!maybe_qpkg.get()->triplet)
+ {
+ parser.add_error("expected an explicit triplet");
+ }
+ else if (maybe_qpkg.get()->features)
+ {
+ parser.add_error("unexpected list of features");
+ }
+ else if (maybe_qpkg.get()->platform)
+ {
+ parser.add_error("unexpected qualifier");
+ }
+ if (auto err = parser.get_error())
+ {
+ System::print2(err->format(), "\n");
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+
+ auto& qpkg = *maybe_qpkg.get();
+ auto t = Triplet::from_canonical_name(std::string(*qpkg.triplet.get()));
+ Input::check_triplet(t, paths);
+ specs_to_write.emplace_back(qpkg.name, t);
+ }
+ Json::Object response;
+ Json::Object results;
+ while (!specs_to_write.empty())
+ {
+ auto spec = std::move(specs_to_write.back());
+ specs_to_write.pop_back();
+ if (!specs_written.insert(spec).second) continue;
+ auto maybe_ipv = status_paragraphs.get_installed_package_view(spec);
+ if (auto ipv = maybe_ipv.get())
+ {
+ results.insert(spec.to_string(), serialize_ipv(*ipv, paths));
+ if (transitive)
+ {
+ auto deps = ipv->dependencies();
+ specs_to_write.insert(specs_to_write.end(),
+ std::make_move_iterator(deps.begin()),
+ std::make_move_iterator(deps.end()));
+ }
+ }
+ }
+ response.insert("results", std::move(results));
+ System::print2(Json::stringify(response, {}));
+ }
+ else
+ {
+ Json::Object response;
+ Json::Object results;
+ PortFileProvider::PathsPortFileProvider provider(paths, args.overlay_ports);
+
+ for (auto&& arg : args.command_arguments)
+ {
+ Parse::ParserBase parser(arg, "<command>");
+ auto maybe_pkg = parse_package_name(parser);
+ if (!parser.at_eof() || !maybe_pkg)
+ {
+ parser.add_error("expected only a package identifier");
+ }
+ if (auto err = parser.get_error())
+ {
+ System::print2(err->format(), "\n");
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+
+ auto& pkg = *maybe_pkg.get();
+
+ if (results.contains(pkg)) continue;
+
+ auto maybe_scfl = provider.get_control_file(pkg);
+
+ Json::Object obj;
+ if (auto pscfl = maybe_scfl.get())
+ {
+ results.insert(pkg, serialize_manifest(*pscfl->source_control_file));
+ }
+ }
+ response.insert("results", std::move(results));
+ System::print2(Json::stringify(response, {}));
+ }
+ }
+}
diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp
index 9385e4423..fcd2919ff 100644
--- a/toolsrc/src/vcpkg/commands.list.cpp
+++ b/toolsrc/src/vcpkg/commands.list.cpp
@@ -9,8 +9,6 @@ namespace vcpkg::Commands::List
{
static constexpr StringLiteral OPTION_FULLDESC = "x-full-desc"; // TODO: This should find a better home, eventually
- static constexpr StringLiteral OPTION_JSON = "--x-json";
-
static void do_print_json(std::vector<const vcpkg::StatusParagraph*> installed_packages)
{
Json::Object obj;
@@ -73,9 +71,8 @@ namespace vcpkg::Commands::List
}
}
- static constexpr std::array<CommandSwitch, 2> LIST_SWITCHES = {{
+ static constexpr std::array<CommandSwitch, 1> LIST_SWITCHES = {{
{OPTION_FULLDESC, "Do not truncate long text"},
- {OPTION_JSON, "List libraries in JSON format"},
}};
const CommandStructure COMMAND_STRUCTURE = {
@@ -113,7 +110,6 @@ namespace vcpkg::Commands::List
});
const auto enable_fulldesc = Util::Sets::contains(options.switches, OPTION_FULLDESC.to_string());
- const auto enable_json = Util::Sets::contains(options.switches, OPTION_JSON.to_string());
if (!args.command_arguments.empty())
{
@@ -124,7 +120,7 @@ namespace vcpkg::Commands::List
installed_packages = pghs;
}
- if (enable_json)
+ if (args.output_json())
{
do_print_json(installed_packages);
}
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
index e381b90a3..03ae77d98 100644
--- a/toolsrc/src/vcpkg/install.cpp
+++ b/toolsrc/src/vcpkg/install.cpp
@@ -574,20 +574,34 @@ namespace vcpkg::Install
static void print_cmake_information(const BinaryParagraph& bpgh, const VcpkgPaths& paths)
{
+ auto usage = get_cmake_usage(bpgh, paths);
+
+ if (!usage.message.empty())
+ {
+ System::print2(usage.message);
+ }
+ }
+
+ CMakeUsageInfo get_cmake_usage(const BinaryParagraph& bpgh, const VcpkgPaths& paths)
+ {
static const std::regex cmake_library_regex(R"(\badd_library\(([^\$\s\)]+)\s)",
std::regex_constants::ECMAScript);
+ CMakeUsageInfo ret;
+
auto& fs = paths.get_filesystem();
auto usage_file = paths.installed / bpgh.spec.triplet().canonical_name() / "share" / bpgh.spec.name() / "usage";
if (fs.exists(usage_file))
{
+ ret.usage_file = true;
auto maybe_contents = fs.read_contents(usage_file);
if (auto p_contents = maybe_contents.get())
{
- System::print2(*p_contents, '\n');
+ ret.message = std::move(*p_contents);
+ ret.message.push_back('\n');
}
- return;
+ return ret;
}
auto files = fs.read_lines(paths.listfile_path(bpgh));
@@ -652,6 +666,8 @@ namespace vcpkg::Install
}
}
+ ret.header_only = is_header_only;
+
if (library_targets.empty())
{
if (is_header_only && !header_path.empty())
@@ -670,20 +686,21 @@ namespace vcpkg::Install
"The package ", bpgh.spec, " is header only and can be used from CMake via:\n\n");
Strings::append(msg, " find_path(", name, "_INCLUDE_DIRS \"", header_path, "\")\n");
Strings::append(msg, " target_include_directories(main PRIVATE ${", name, "_INCLUDE_DIRS})\n\n");
- System::print2(msg);
+
+ ret.message = std::move(msg);
}
}
else
{
- System::print2("The package ", bpgh.spec, " provides CMake targets:\n\n");
+ auto msg = Strings::concat("The package ", bpgh.spec, " provides CMake targets:\n\n");
for (auto&& library_target_pair : library_targets)
{
auto config_it = config_files.find(library_target_pair.first);
if (config_it != config_files.end())
- System::printf(" find_package(%s CONFIG REQUIRED)\n", config_it->second);
+ Strings::append(msg, " find_package(", config_it->second, " CONFIG REQUIRED)\n ");
else
- System::printf(" find_package(%s CONFIG REQUIRED)\n", library_target_pair.first);
+ Strings::append(msg, " find_package(", library_target_pair.first, " CONFIG REQUIRED)\n ");
std::sort(library_target_pair.second.begin(),
library_target_pair.second.end(),
@@ -695,22 +712,27 @@ namespace vcpkg::Install
if (library_target_pair.second.size() <= 4)
{
- System::printf(" target_link_libraries(main PRIVATE %s)\n\n",
- Strings::join(" ", library_target_pair.second));
+ Strings::append(msg,
+ " target_link_libraries(main PRIVATE ",
+ Strings::join(" ", library_target_pair.second),
+ ")\n\n");
}
else
{
auto omitted = library_target_pair.second.size() - 4;
library_target_pair.second.erase(library_target_pair.second.begin() + 4,
library_target_pair.second.end());
- System::printf(" # Note: %zd target(s) were omitted.\n"
- " target_link_libraries(main PRIVATE %s)\n\n",
- omitted,
- Strings::join(" ", library_target_pair.second));
+ msg += Strings::format(" # Note: %zd target(s) were omitted.\n"
+ " target_link_libraries(main PRIVATE %s)\n\n",
+ omitted,
+ Strings::join(" ", library_target_pair.second));
}
}
+ ret.message = std::move(msg);
}
+ ret.cmake_targets_map = std::move(library_targets);
}
+ return ret;
}
///
diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp
index d42174289..ba1815224 100644
--- a/toolsrc/src/vcpkg/statusparagraphs.cpp
+++ b/toolsrc/src/vcpkg/statusparagraphs.cpp
@@ -1,6 +1,8 @@
#include <vcpkg/base/checks.h>
+#include <vcpkg/install.h>
#include <vcpkg/statusparagraphs.h>
+#include <vcpkg/vcpkgpaths.h>
namespace vcpkg
{
@@ -143,4 +145,42 @@ namespace vcpkg
out_str.push_back('\n');
}
}
+
+ Json::Value serialize_ipv(const InstalledPackageView& ipv, const VcpkgPaths& paths)
+ {
+ const auto& fs = paths.get_filesystem();
+ Json::Object iobj;
+ iobj.insert("version-string", Json::Value::string(ipv.core->package.version));
+ iobj.insert("port-version", Json::Value::integer(ipv.core->package.port_version));
+ iobj.insert("triplet", Json::Value::string(ipv.spec().triplet().to_string()));
+ iobj.insert("abi", Json::Value::string(ipv.core->package.abi));
+ Json::Array deps;
+ for (auto&& dep : ipv.dependencies())
+ deps.push_back(Json::Value::string(dep.to_string()));
+ if (deps.size() != 0)
+ {
+ iobj.insert("dependencies", std::move(deps));
+ }
+ Json::Array features;
+ for (auto&& feature : ipv.features)
+ {
+ features.push_back(Json::Value::string(feature->package.feature));
+ }
+ if (features.size() != 0)
+ {
+ iobj.insert("features", std::move(features));
+ }
+ auto usage = Install::get_cmake_usage(ipv.core->package, paths);
+ if (!usage.message.empty())
+ {
+ iobj.insert("usage", Json::Value::string(std::move(usage.message)));
+ }
+ auto owns_files = fs.read_lines(paths.listfile_path(ipv.core->package)).value_or_exit(VCPKG_LINE_INFO);
+ Json::Array owns;
+ for (auto&& owns_file : owns_files)
+ owns.push_back(Json::Value::string(std::move(owns_file)));
+
+ iobj.insert("owns", std::move(owns));
+ return Json::Value::object(std::move(iobj));
+ }
}
diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
index 7354dbae2..7377baafb 100644
--- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
+++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
@@ -308,6 +308,7 @@ namespace vcpkg
{FEATURE_PACKAGES_SWITCH, &VcpkgCmdArguments::feature_packages},
{BINARY_CACHING_SWITCH, &VcpkgCmdArguments::binary_caching},
{WAIT_FOR_LOCK_SWITCH, &VcpkgCmdArguments::wait_for_lock},
+ {JSON_SWITCH, &VcpkgCmdArguments::json},
};
bool found = false;
@@ -604,7 +605,7 @@ namespace vcpkg
void VcpkgCmdArguments::append_common_options(HelpTableFormatter& table)
{
static auto opt = [](StringView arg, StringView joiner, StringView value) {
- return Strings::format("--%s%s%s", arg, joiner, value);
+ return Strings::concat("--", arg, joiner, value);
};
table.format(opt(TRIPLET_ARG, " ", "<t>"), "Specify the target architecture triplet. See 'vcpkg help triplet'");
@@ -623,6 +624,7 @@ namespace vcpkg
table.format(opt(INSTALL_ROOT_DIR_ARG, "=", "<path>"), "(Experimental) Specify the install root directory");
table.format(opt(PACKAGES_ROOT_DIR_ARG, "=", "<path>"), "(Experimental) Specify the packages root directory");
table.format(opt(SCRIPTS_ROOT_DIR_ARG, "=", "<path>"), "(Experimental) Specify the scripts root directory");
+ table.format(opt(JSON_SWITCH, "", ""), "(Experimental) Request JSON output");
}
void VcpkgCmdArguments::imbue_from_environment()
diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp
index 801e39541..a158cf74b 100644
--- a/toolsrc/src/vcpkg/vcpkglib.cpp
+++ b/toolsrc/src/vcpkg/vcpkglib.cpp
@@ -172,7 +172,6 @@ namespace vcpkg
{
std::map<PackageSpec, InstalledPackageView> ipv_map;
- std::vector<InstalledPackageView> installed_packages;
for (auto&& pgh : status_db)
{
if (!pgh->is_installed()) continue;
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
index 2448d525d..6572b44f1 100644
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp
@@ -163,7 +163,7 @@ namespace vcpkg
else
{
// we ignore the manifest root dir if the user requests -manifest
- if (!manifest_root_dir.empty() && !args.manifest_mode.has_value())
+ if (!manifest_root_dir.empty() && !args.manifest_mode.has_value() && !args.output_json())
{
System::print2(System::Color::warning,
"Warning: manifest-root detected at ",
diff --git a/toolsrc/windows-bootstrap/vcpkglib/vcpkglib.vcxproj b/toolsrc/windows-bootstrap/vcpkglib/vcpkglib.vcxproj
index 2c980039e..660459024 100644
--- a/toolsrc/windows-bootstrap/vcpkglib/vcpkglib.vcxproj
+++ b/toolsrc/windows-bootstrap/vcpkglib/vcpkglib.vcxproj
@@ -197,6 +197,7 @@
<ClInclude Include="..\..\include\vcpkg\commands.fetch.h" />
<ClInclude Include="..\..\include\vcpkg\commands.format-manifest.h" />
<ClInclude Include="..\..\include\vcpkg\commands.hash.h" />
+ <ClInclude Include="..\..\include\vcpkg\commands.info.h" />
<ClInclude Include="..\..\include\vcpkg\commands.integrate.h" />
<ClInclude Include="..\..\include\vcpkg\commands.interface.h" />
<ClInclude Include="..\..\include\vcpkg\commands.list.h" />
@@ -284,6 +285,7 @@
<ClCompile Include="..\..\src\vcpkg\commands.fetch.cpp" />
<ClCompile Include="..\..\src\vcpkg\commands.format-manifest.cpp" />
<ClCompile Include="..\..\src\vcpkg\commands.hash.cpp" />
+ <ClCompile Include="..\..\src\vcpkg\commands.info.cpp" />
<ClCompile Include="..\..\src\vcpkg\commands.integrate.cpp" />
<ClCompile Include="..\..\src\vcpkg\commands.list.cpp" />
<ClCompile Include="..\..\src\vcpkg\commands.owns.cpp" />