aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorBarath Kannan <barathsotd@gmail.com>2017-12-27 16:57:43 +1100
committerBarath Kannan <barathsotd@gmail.com>2017-12-27 16:57:43 +1100
commitd8f0ea999983892b8e5e49340ece3474ee257156 (patch)
treece9b615075350d90d0b7312874bae6dd202fe93b /toolsrc/src
parent22e9a2b25db21e1d1a1f75786442f2c90ae0db0c (diff)
parent6e05f9cdf5cf4d53153214f4d4b29133b368bc4d (diff)
downloadvcpkg-d8f0ea999983892b8e5e49340ece3474ee257156.tar.gz
vcpkg-d8f0ea999983892b8e5e49340ece3474ee257156.zip
resolve merge conflicts
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/tests.chrono.cpp41
-rw-r--r--toolsrc/src/tests.plan.cpp150
-rw-r--r--toolsrc/src/tests.update.cpp34
-rw-r--r--toolsrc/src/vcpkg.cpp97
-rw-r--r--toolsrc/src/vcpkg/base/checks.cpp9
-rw-r--r--toolsrc/src/vcpkg/base/chrono.cpp76
-rw-r--r--toolsrc/src/vcpkg/base/files.cpp3
-rw-r--r--toolsrc/src/vcpkg/base/system.cpp92
-rw-r--r--toolsrc/src/vcpkg/binaryparagraph.cpp5
-rw-r--r--toolsrc/src/vcpkg/build.cpp82
-rw-r--r--toolsrc/src/vcpkg/commands.ci.cpp18
-rw-r--r--toolsrc/src/vcpkg/commands.contact.cpp13
-rw-r--r--toolsrc/src/vcpkg/commands.cpp3
-rw-r--r--toolsrc/src/vcpkg/commands.create.cpp3
-rw-r--r--toolsrc/src/vcpkg/commands.env.cpp2
-rw-r--r--toolsrc/src/vcpkg/commands.integrate.cpp16
-rw-r--r--toolsrc/src/vcpkg/commands.list.cpp8
-rw-r--r--toolsrc/src/vcpkg/commands.portsdiff.cpp13
-rw-r--r--toolsrc/src/vcpkg/commands.upgrade.cpp180
-rw-r--r--toolsrc/src/vcpkg/commands.version.cpp7
-rw-r--r--toolsrc/src/vcpkg/dependencies.cpp429
-rw-r--r--toolsrc/src/vcpkg/export.cpp9
-rw-r--r--toolsrc/src/vcpkg/globalstate.cpp4
-rw-r--r--toolsrc/src/vcpkg/help.cpp1
-rw-r--r--toolsrc/src/vcpkg/install.cpp297
-rw-r--r--toolsrc/src/vcpkg/metrics.cpp46
-rw-r--r--toolsrc/src/vcpkg/packagespec.cpp37
-rw-r--r--toolsrc/src/vcpkg/paragraphs.cpp12
-rw-r--r--toolsrc/src/vcpkg/postbuildlint.buildtype.cpp2
-rw-r--r--toolsrc/src/vcpkg/postbuildlint.cpp61
-rw-r--r--toolsrc/src/vcpkg/remove.cpp9
-rw-r--r--toolsrc/src/vcpkg/update.cpp40
-rw-r--r--toolsrc/src/vcpkg/userconfig.cpp88
-rw-r--r--toolsrc/src/vcpkg/vcpkglib.cpp24
-rw-r--r--toolsrc/src/vcpkg/vcpkgpaths.cpp140
35 files changed, 1416 insertions, 635 deletions
diff --git a/toolsrc/src/tests.chrono.cpp b/toolsrc/src/tests.chrono.cpp
new file mode 100644
index 000000000..269cdca58
--- /dev/null
+++ b/toolsrc/src/tests.chrono.cpp
@@ -0,0 +1,41 @@
+#include "tests.pch.h"
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+
+namespace Chrono = vcpkg::Chrono;
+
+namespace UnitTest1
+{
+ class ChronoTests : public TestClass<ChronoTests>
+ {
+ TEST_METHOD(parse_time)
+ {
+ auto timestring = "1990-02-03T04:05:06.0Z";
+ auto maybe_time = Chrono::CTime::parse(timestring);
+
+ Assert::IsTrue(maybe_time.has_value());
+
+ Assert::AreEqual(timestring, maybe_time.get()->to_string().c_str());
+ }
+
+ TEST_METHOD(parse_time_blank)
+ {
+ auto maybe_time = Chrono::CTime::parse("");
+
+ Assert::IsFalse(maybe_time.has_value());
+ }
+
+ TEST_METHOD(time_difference)
+ {
+ auto maybe_time1 = Chrono::CTime::parse("1990-02-03T04:05:06.0Z");
+ auto maybe_time2 = Chrono::CTime::parse("1990-02-10T04:05:06.0Z");
+
+ Assert::IsTrue(maybe_time1.has_value());
+ Assert::IsTrue(maybe_time2.has_value());
+
+ auto delta = maybe_time2.get()->to_time_point() - maybe_time1.get()->to_time_point();
+
+ Assert::AreEqual(24 * 7, std::chrono::duration_cast<std::chrono::hours>(delta).count());
+ }
+ };
+}
diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp
index 122a4ffef..781588c91 100644
--- a/toolsrc/src/tests.plan.cpp
+++ b/toolsrc/src/tests.plan.cpp
@@ -36,7 +36,7 @@ namespace UnitTest1
std::vector<std::string> vec,
const Triplet& triplet = Triplet::X86_WINDOWS)
{
- const auto& plan = install_action->install_plan.value_or_exit(VCPKG_LINE_INFO);
+ const auto& plan = install_action->install_action.value_or_exit(VCPKG_LINE_INFO);
const auto& feature_list = plan.feature_list;
Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str());
@@ -61,7 +61,7 @@ namespace UnitTest1
std::string pkg_name,
const Triplet& triplet = Triplet::X86_WINDOWS)
{
- const auto& plan = remove_action->remove_plan.value_or_exit(VCPKG_LINE_INFO);
+ const auto& plan = remove_action->remove_action.value_or_exit(VCPKG_LINE_INFO);
Assert::AreEqual(plan.spec.triplet().to_string().c_str(), triplet.to_string().c_str());
Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str());
}
@@ -98,7 +98,7 @@ namespace UnitTest1
auto spec_b = spec_map.emplace("b", "c");
auto spec_c = spec_map.emplace("c");
- Dependencies::MapPortFile map_port(spec_map.map);
+ Dependencies::MapPortFileProvider map_port(spec_map.map);
auto install_plan =
Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
@@ -122,7 +122,7 @@ namespace UnitTest1
auto spec_g = spec_map.emplace("g");
auto spec_h = spec_map.emplace("h");
- Dependencies::MapPortFile map_port(spec_map.map);
+ Dependencies::MapPortFileProvider map_port(spec_map.map);
auto install_plan = Dependencies::create_install_plan(
map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs)));
@@ -162,7 +162,7 @@ namespace UnitTest1
StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(1), install_plan.size());
- auto p = install_plan[0].install_plan.get();
+ auto p = install_plan[0].install_action.get();
Assert::IsNotNull(p);
Assert::AreEqual("a", p->spec.name().c_str());
Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type);
@@ -183,13 +183,13 @@ namespace UnitTest1
StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(2), install_plan.size());
- auto p = install_plan[0].install_plan.get();
+ auto p = install_plan[0].install_action.get();
Assert::IsNotNull(p);
Assert::AreEqual("b", p->spec.name().c_str());
Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type);
Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type);
- auto p2 = install_plan[1].install_plan.get();
+ auto p2 = install_plan[1].install_action.get();
Assert::IsNotNull(p2);
Assert::AreEqual("a", p2->spec.name().c_str());
Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type);
@@ -215,7 +215,7 @@ namespace UnitTest1
auto spec_j = spec_map.emplace("j", "k");
auto spec_k = spec_map.emplace("k");
- Dependencies::MapPortFile map_port(spec_map.map);
+ Dependencies::MapPortFileProvider map_port(spec_map.map);
auto install_plan =
Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
@@ -521,4 +521,138 @@ namespace UnitTest1
Assert::AreEqual("expat", remove_plan[2].spec.name().c_str());
}
};
+
+ class UpgradePlanTests : public TestClass<UpgradePlanTests>
+ {
+ TEST_METHOD(basic_upgrade_scheme)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>> pghs;
+ pghs.push_back(make_status_pgh("a"));
+ StatusParagraphs status_db(std::move(pghs));
+
+ PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+ auto spec_a = spec_map.emplace("a");
+
+ Dependencies::MapPortFileProvider provider(spec_map.map);
+ Dependencies::PackageGraph graph(provider, status_db);
+
+ graph.upgrade(spec_a);
+
+ auto plan = graph.serialize();
+
+ Assert::AreEqual(size_t(2), plan.size());
+ Assert::AreEqual("a", plan[0].spec().name().c_str());
+ Assert::IsTrue(plan[0].remove_action.has_value());
+ Assert::AreEqual("a", plan[1].spec().name().c_str());
+ Assert::IsTrue(plan[1].install_action.has_value());
+ }
+
+ TEST_METHOD(basic_upgrade_scheme_with_recurse)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>> pghs;
+ pghs.push_back(make_status_pgh("a"));
+ pghs.push_back(make_status_pgh("b", "a"));
+ StatusParagraphs status_db(std::move(pghs));
+
+ PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+ auto spec_a = spec_map.emplace("a");
+ spec_map.emplace("b", "a");
+
+ Dependencies::MapPortFileProvider provider(spec_map.map);
+ Dependencies::PackageGraph graph(provider, status_db);
+
+ graph.upgrade(spec_a);
+
+ auto plan = graph.serialize();
+
+ Assert::AreEqual(size_t(4), plan.size());
+ Assert::AreEqual("b", plan[0].spec().name().c_str());
+ Assert::IsTrue(plan[0].remove_action.has_value());
+
+ Assert::AreEqual("a", plan[1].spec().name().c_str());
+ Assert::IsTrue(plan[1].remove_action.has_value());
+
+ Assert::AreEqual("a", plan[2].spec().name().c_str());
+ Assert::IsTrue(plan[2].install_action.has_value());
+
+ Assert::AreEqual("b", plan[3].spec().name().c_str());
+ Assert::IsTrue(plan[3].install_action.has_value());
+ }
+
+ TEST_METHOD(basic_upgrade_scheme_with_bystander)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>> pghs;
+ pghs.push_back(make_status_pgh("a"));
+ pghs.push_back(make_status_pgh("b"));
+ StatusParagraphs status_db(std::move(pghs));
+
+ PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+ auto spec_a = spec_map.emplace("a");
+ spec_map.emplace("b", "a");
+
+ Dependencies::MapPortFileProvider provider(spec_map.map);
+ Dependencies::PackageGraph graph(provider, status_db);
+
+ graph.upgrade(spec_a);
+
+ auto plan = graph.serialize();
+
+ Assert::AreEqual(size_t(2), plan.size());
+ Assert::AreEqual("a", plan[0].spec().name().c_str());
+ Assert::IsTrue(plan[0].remove_action.has_value());
+ Assert::AreEqual("a", plan[1].spec().name().c_str());
+ Assert::IsTrue(plan[1].install_action.has_value());
+ }
+
+ TEST_METHOD(basic_upgrade_scheme_with_new_dep)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>> pghs;
+ pghs.push_back(make_status_pgh("a"));
+ StatusParagraphs status_db(std::move(pghs));
+
+ PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+ auto spec_a = spec_map.emplace("a", "b");
+ spec_map.emplace("b");
+
+ Dependencies::MapPortFileProvider provider(spec_map.map);
+ Dependencies::PackageGraph graph(provider, status_db);
+
+ graph.upgrade(spec_a);
+
+ auto plan = graph.serialize();
+
+ Assert::AreEqual(size_t(3), plan.size());
+ Assert::AreEqual("a", plan[0].spec().name().c_str());
+ Assert::IsTrue(plan[0].remove_action.has_value());
+ Assert::AreEqual("b", plan[1].spec().name().c_str());
+ Assert::IsTrue(plan[1].install_action.has_value());
+ Assert::AreEqual("a", plan[2].spec().name().c_str());
+ Assert::IsTrue(plan[2].install_action.has_value());
+ }
+
+ TEST_METHOD(basic_upgrade_scheme_with_features)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>> pghs;
+ pghs.push_back(make_status_pgh("a"));
+ pghs.push_back(make_status_feature_pgh("a", "a1"));
+ StatusParagraphs status_db(std::move(pghs));
+
+ PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+ auto spec_a = spec_map.emplace("a", "", {{"a1", ""}});
+
+ Dependencies::MapPortFileProvider provider(spec_map.map);
+ Dependencies::PackageGraph graph(provider, status_db);
+
+ graph.upgrade(spec_a);
+
+ auto plan = graph.serialize();
+
+ Assert::AreEqual(size_t(2), plan.size());
+
+ Assert::AreEqual("a", plan[0].spec().name().c_str());
+ Assert::IsTrue(plan[0].remove_action.has_value());
+
+ features_check(&plan[1], "a", {"core", "a1"});
+ }
+ };
}
diff --git a/toolsrc/src/tests.update.cpp b/toolsrc/src/tests.update.cpp
index 06ae797f4..b6e487c17 100644
--- a/toolsrc/src/tests.update.cpp
+++ b/toolsrc/src/tests.update.cpp
@@ -9,6 +9,8 @@ using namespace vcpkg::Update;
namespace UnitTest1
{
+ using Pgh = std::vector<std::unordered_map<std::string, std::string>>;
+
class UpdateTests : public TestClass<UpdateTests>
{
TEST_METHOD(find_outdated_packages_basic)
@@ -19,10 +21,12 @@ namespace UnitTest1
StatusParagraphs status_db(std::move(status_paragraphs));
- std::map<std::string, VersionT> port_versions;
- port_versions["a"] = VersionT("0");
+ std::unordered_map<std::string, SourceControlFile> map;
+ auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}}));
+ map.emplace("a", std::move(*scf));
+ Dependencies::MapPortFileProvider provider(map);
- auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(port_versions, status_db),
+ auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db),
&OutdatedPackage::compare_by_name);
Assert::AreEqual(size_t(1), pkgs.size());
@@ -41,10 +45,12 @@ namespace UnitTest1
StatusParagraphs status_db(std::move(status_paragraphs));
- std::map<std::string, VersionT> port_versions;
- port_versions["a"] = VersionT("0");
+ std::unordered_map<std::string, SourceControlFile> map;
+ auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}}));
+ map.emplace("a", std::move(*scf));
+ Dependencies::MapPortFileProvider provider(map);
- auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(port_versions, status_db),
+ auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db),
&OutdatedPackage::compare_by_name);
Assert::AreEqual(size_t(1), pkgs.size());
@@ -65,10 +71,12 @@ namespace UnitTest1
StatusParagraphs status_db(std::move(status_paragraphs));
- std::map<std::string, VersionT> port_versions;
- port_versions["a"] = VersionT("0");
+ std::unordered_map<std::string, SourceControlFile> map;
+ auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "0"}}}));
+ map.emplace("a", std::move(*scf));
+ Dependencies::MapPortFileProvider provider(map);
- auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(port_versions, status_db),
+ auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db),
&OutdatedPackage::compare_by_name);
Assert::AreEqual(size_t(1), pkgs.size());
@@ -84,10 +92,12 @@ namespace UnitTest1
StatusParagraphs status_db(std::move(status_paragraphs));
- std::map<std::string, VersionT> port_versions;
- port_versions["a"] = VersionT("2");
+ std::unordered_map<std::string, SourceControlFile> map;
+ auto scf = unwrap(SourceControlFile::parse_control_file(Pgh{{{"Source", "a"}, {"Version", "2"}}}));
+ map.emplace("a", std::move(*scf));
+ Dependencies::MapPortFileProvider provider(map);
- auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(port_versions, status_db),
+ auto pkgs = SortedVector<OutdatedPackage>(Update::find_outdated_packages(provider, status_db),
&OutdatedPackage::compare_by_name);
Assert::AreEqual(size_t(0), pkgs.size());
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp
index 5642f937c..094ea1dc5 100644
--- a/toolsrc/src/vcpkg.cpp
+++ b/toolsrc/src/vcpkg.cpp
@@ -20,11 +20,13 @@
#include <vcpkg/input.h>
#include <vcpkg/metrics.h>
#include <vcpkg/paragraphs.h>
+#include <vcpkg/userconfig.h>
#include <vcpkg/vcpkglib.h>
#include <cassert>
#include <fstream>
#include <memory>
+#include <random>
#pragma comment(lib, "ole32")
#pragma comment(lib, "shell32")
@@ -110,6 +112,28 @@ static void inner(const VcpkgCmdArguments& args)
if (args.command != "autocomplete")
{
Commands::Version::warn_if_vcpkg_version_mismatch(paths);
+ std::string surveydate = *GlobalState::g_surveydate.lock();
+ auto maybe_surveydate = Chrono::CTime::parse(surveydate);
+ if (auto p_surveydate = maybe_surveydate.get())
+ {
+ auto delta = std::chrono::system_clock::now() - p_surveydate->to_time_point();
+ // 24 hours/day * 30 days/month
+ if (std::chrono::duration_cast<std::chrono::hours>(delta).count() > 24 * 30)
+ {
+ std::default_random_engine generator(
+ static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count()));
+ std::uniform_int_distribution<int> distribution(1, 4);
+
+ if (distribution(generator) == 1)
+ {
+ Metrics::g_metrics.lock()->track_property("surveyprompt", "true");
+ System::println(
+ System::Color::success,
+ "Your feedback is important to improve Vcpkg! Please take 3 minutes to complete our survey "
+ "by running: vcpkg contact --survey");
+ }
+ }
+ }
}
if (const auto command_function = find_command(Commands::get_available_commands_type_b()))
@@ -148,80 +172,41 @@ static void inner(const VcpkgCmdArguments& args)
static void load_config()
{
#if defined(_WIN32)
- fs::path localappdata;
- {
- // Config path in AppDataLocal
- wchar_t* localappdatapath = nullptr;
- if (S_OK != SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localappdatapath)) __fastfail(1);
- localappdata = localappdatapath;
- CoTaskMemFree(localappdatapath);
- }
-
- std::string user_id, user_time, user_mac;
- try
- {
- auto maybe_pghs = Paragraphs::get_paragraphs(Files::get_real_filesystem(), localappdata / "vcpkg" / "config");
- if (const auto p_pghs = maybe_pghs.get())
- {
- const auto& pghs = *p_pghs;
+ auto& fs = Files::get_real_filesystem();
- std::unordered_map<std::string, std::string> keys;
- if (pghs.size() > 0) keys = pghs[0];
-
- for (size_t x = 1; x < pghs.size(); ++x)
- {
- for (auto&& p : pghs[x])
- keys.insert(p);
- }
-
- user_id = keys["User-Id"];
- user_time = keys["User-Since"];
- user_mac = keys["Mac-Hash"];
- }
- }
- catch (...)
- {
- }
+ auto config = UserConfig::try_read_data(fs);
bool write_config = false;
// config file not found, could not be read, or invalid
- if (user_id.empty() || user_time.empty())
+ if (config.user_id.empty() || config.user_time.empty())
{
- ::vcpkg::Metrics::Metrics::init_user_information(user_id, user_time);
+ ::vcpkg::Metrics::Metrics::init_user_information(config.user_id, config.user_time);
write_config = true;
}
- if (user_mac.empty())
+ if (config.user_mac.empty())
{
- user_mac = Metrics::get_MAC_user();
+ config.user_mac = Metrics::get_MAC_user();
write_config = true;
}
{
auto locked_metrics = Metrics::g_metrics.lock();
- locked_metrics->set_user_information(user_id, user_time);
- locked_metrics->track_property("user_mac", user_mac);
+ locked_metrics->set_user_information(config.user_id, config.user_time);
+ locked_metrics->track_property("user_mac", config.user_mac);
}
+ if (config.last_completed_survey.empty())
+ {
+ config.last_completed_survey = config.user_time;
+ }
+
+ GlobalState::g_surveydate.lock()->assign(config.last_completed_survey);
+
if (write_config)
{
- try
- {
- std::error_code ec;
- auto& fs = Files::get_real_filesystem();
- fs.create_directory(localappdata / "vcpkg", ec);
- fs.write_contents(localappdata / "vcpkg" / "config",
- Strings::format("User-Id: %s\n"
- "User-Since: %s\n"
- "Mac-Hash: %s\n",
- user_id,
- user_time,
- user_mac));
- }
- catch (...)
- {
- }
+ config.try_write_data(fs);
}
#endif
}
@@ -255,7 +240,7 @@ int main(const int argc, const char* const* const argv)
{
if (argc == 0) std::abort();
- *GlobalState::timer.lock() = Chrono::ElapsedTime::create_started();
+ *GlobalState::timer.lock() = Chrono::ElapsedTimer::create_started();
#if defined(_WIN32)
GlobalState::g_init_console_cp = GetConsoleCP();
diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp
index ed28d6e2b..23f2cc630 100644
--- a/toolsrc/src/vcpkg/base/checks.cpp
+++ b/toolsrc/src/vcpkg/base/checks.cpp
@@ -49,8 +49,7 @@ namespace vcpkg::Checks
#else
void register_console_ctrl_handler() {}
#endif
-
- [[noreturn]] void unreachable(const LineInfo& line_info)
+ void unreachable(const LineInfo& line_info)
{
System::println(System::Color::error, "Error: Unreachable code was reached");
System::println(System::Color::error, line_info.to_string()); // Always print line_info here
@@ -61,13 +60,13 @@ namespace vcpkg::Checks
#endif
}
- [[noreturn]] void exit_with_code(const LineInfo& line_info, const int exit_code)
+ void exit_with_code(const LineInfo& line_info, const int exit_code)
{
Debug::println(System::Color::error, line_info.to_string());
cleanup_and_exit(exit_code);
}
- [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView error_message)
+ void exit_with_message(const LineInfo& line_info, const CStringView error_message)
{
System::println(System::Color::error, error_message);
exit_fail(line_info);
@@ -77,7 +76,7 @@ namespace vcpkg::Checks
{
if (!expression)
{
- exit_with_message(line_info, "");
+ exit_fail(line_info);
}
}
diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp
index 5d28909fc..00f8ba3f1 100644
--- a/toolsrc/src/vcpkg/base/chrono.cpp
+++ b/toolsrc/src/vcpkg/base/chrono.cpp
@@ -50,12 +50,82 @@ namespace vcpkg::Chrono
return Strings::format("%.4g ns", nanos_as_double);
}
- ElapsedTime ElapsedTime::create_started()
+ ElapsedTimer ElapsedTimer::create_started()
{
- ElapsedTime t;
+ ElapsedTimer t;
t.m_start_tick = std::chrono::high_resolution_clock::now();
return t;
}
- std::string ElapsedTime::to_string() const { return format_time_userfriendly(elapsed<std::chrono::nanoseconds>()); }
+ std::string ElapsedTime::to_string() const { return format_time_userfriendly(as<std::chrono::nanoseconds>()); }
+
+ std::string ElapsedTimer::to_string() const { return elapsed().to_string(); }
+
+ Optional<CTime> CTime::get_current_date_time()
+ {
+ CTime ret;
+
+#if defined(_WIN32)
+ struct _timeb timebuffer;
+
+ _ftime_s(&timebuffer);
+
+ const errno_t err = gmtime_s(&ret.m_tm, &timebuffer.time);
+
+ if (err)
+ {
+ return nullopt;
+ }
+#else
+ time_t now = {0};
+ time(&now);
+ auto null_if_failed = gmtime_r(&now, &ret.m_tm);
+ if (null_if_failed == nullptr)
+ {
+ return nullopt;
+ }
+#endif
+
+ return ret;
+ }
+
+ Optional<CTime> CTime::parse(CStringView str)
+ {
+ CTime ret;
+ auto assigned =
+#if defined(_WIN32)
+ sscanf_s
+#else
+ sscanf
+#endif
+ (str.c_str(),
+ "%d-%d-%dT%d:%d:%d.",
+ &ret.m_tm.tm_year,
+ &ret.m_tm.tm_mon,
+ &ret.m_tm.tm_mday,
+ &ret.m_tm.tm_hour,
+ &ret.m_tm.tm_min,
+ &ret.m_tm.tm_sec);
+ if (assigned != 6) return nullopt;
+ if (ret.m_tm.tm_year < 1900) return nullopt;
+ ret.m_tm.tm_year -= 1900;
+ if (ret.m_tm.tm_mon < 1) return nullopt;
+ ret.m_tm.tm_mon -= 1;
+ mktime(&ret.m_tm);
+ return ret;
+ }
+
+ std::string CTime::to_string() const
+ {
+ std::array<char, 80> date;
+ date.fill(0);
+
+ strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S.0Z", &m_tm);
+ return &date[0];
+ }
+ std::chrono::system_clock::time_point CTime::to_time_point() const
+ {
+ auto t = mktime(&m_tm);
+ return std::chrono::system_clock::from_time_t(t);
+ }
}
diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp
index 6e43debb1..8c9e137ed 100644
--- a/toolsrc/src/vcpkg/base/files.cpp
+++ b/toolsrc/src/vcpkg/base/files.cpp
@@ -72,7 +72,8 @@ namespace vcpkg::Files
{
std::vector<fs::path> ret;
- fs::stdfs::recursive_directory_iterator b(dir), e{};
+ std::error_code ec;
+ fs::stdfs::recursive_directory_iterator b(dir, ec), e{};
for (; b != e; ++b)
{
ret.push_back(b->path());
diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp
index 47096ed63..625ee6ce0 100644
--- a/toolsrc/src/vcpkg/base/system.cpp
+++ b/toolsrc/src/vcpkg/base/system.cpp
@@ -51,11 +51,21 @@ namespace vcpkg::System
CPUArchitecture get_host_processor()
{
+#if defined(_WIN32)
auto w6432 = get_environment_variable("PROCESSOR_ARCHITEW6432");
if (const auto p = w6432.get()) return to_cpu_architecture(*p).value_or_exit(VCPKG_LINE_INFO);
const auto procarch = get_environment_variable("PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO);
return to_cpu_architecture(procarch).value_or_exit(VCPKG_LINE_INFO);
+#else
+#if defined(__x86_64__) || defined(_M_X64)
+ return CPUArchitecture::X64;
+#elif defined(__x86__) || defined(_M_X86)
+ return CPUArchitecture::X86;
+#else
+#error "Unknown host architecture"
+#endif
+#endif
}
std::vector<CPUArchitecture> get_supported_host_architectures()
@@ -72,6 +82,53 @@ namespace vcpkg::System
return supported_architectures;
}
+ CMakeVariable::CMakeVariable(const CStringView varname, const char* varvalue)
+ : s(Strings::format(R"("-D%s=%s")", varname, varvalue))
+ {
+ }
+ CMakeVariable::CMakeVariable(const CStringView varname, const std::string& varvalue)
+ : CMakeVariable(varname, varvalue.c_str())
+ {
+ }
+ CMakeVariable::CMakeVariable(const CStringView varname, const fs::path& path)
+ : CMakeVariable(varname, path.generic_u8string())
+ {
+ }
+
+ std::string make_cmake_cmd(const fs::path& cmake_exe,
+ const fs::path& cmake_script,
+ const std::vector<CMakeVariable>& pass_variables)
+ {
+ const std::string cmd_cmake_pass_variables = Strings::join(" ", pass_variables, [](auto&& v) { return v.s; });
+ return Strings::format(
+ R"("%s" %s -P "%s")", cmake_exe.u8string(), cmd_cmake_pass_variables, cmake_script.generic_u8string());
+ }
+
+ PowershellParameter::PowershellParameter(const CStringView varname, const char* varvalue)
+ : s(Strings::format(R"(-%s '%s')", varname, varvalue))
+ {
+ }
+
+ PowershellParameter::PowershellParameter(const CStringView varname, const std::string& varvalue)
+ : PowershellParameter(varname, varvalue.c_str())
+ {
+ }
+
+ PowershellParameter::PowershellParameter(const CStringView varname, const fs::path& path)
+ : PowershellParameter(varname, path.generic_u8string())
+ {
+ }
+
+ static std::string make_powershell_cmd(const fs::path& script_path,
+ const std::vector<PowershellParameter>& parameters)
+ {
+ const std::string args = Strings::join(" ", parameters, [](auto&& v) { return v.s; });
+
+ // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned
+ return Strings::format(
+ R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args);
+ }
+
int cmd_execute_clean(const CStringView cmd_line)
{
#if defined(_WIN32)
@@ -145,6 +202,8 @@ namespace vcpkg::System
env_cstr.append(Strings::to_utf16(NEW_PATH));
env_cstr.push_back(L'\0');
+ env_cstr.append(L"VSLANG=1033");
+ env_cstr.push_back(L'\0');
STARTUPINFOW startup_info;
memset(&startup_info, 0, sizeof(STARTUPINFOW));
@@ -270,14 +329,37 @@ namespace vcpkg::System
#endif
}
+ void powershell_execute(const std::string& title,
+ const fs::path& script_path,
+ const std::vector<PowershellParameter>& parameters)
+ {
+ const std::string cmd = make_powershell_cmd(script_path, parameters);
+ const int rc = System::cmd_execute(cmd);
+
+ if (rc)
+ {
+ System::println(Color::error,
+ "%s\n"
+ "Could not run:\n"
+ " '%s'",
+ title,
+ script_path.generic_string());
+
+ {
+ auto locked_metrics = Metrics::g_metrics.lock();
+ locked_metrics->track_property("error", "powershell script failed");
+ locked_metrics->track_property("title", title);
+ }
+
+ Checks::exit_with_code(VCPKG_LINE_INFO, rc);
+ }
+ }
+
std::string powershell_execute_and_capture_output(const std::string& title,
const fs::path& script_path,
- const CStringView args)
+ const std::vector<PowershellParameter>& parameters)
{
- // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned
- const std::string cmd = Strings::format(
- R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args);
-
+ const std::string cmd = make_powershell_cmd(script_path, parameters);
auto rc = System::cmd_execute_and_capture_output(cmd);
if (rc.exit_code)
diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp
index c7136b713..7c9e905e8 100644
--- a/toolsrc/src/vcpkg/binaryparagraph.cpp
+++ b/toolsrc/src/vcpkg/binaryparagraph.cpp
@@ -92,8 +92,9 @@ namespace vcpkg
std::string BinaryParagraph::displayname() const
{
- const auto f = this->feature.empty() ? "core" : this->feature;
- return Strings::format("%s[%s]:%s", this->spec.name(), f, this->spec.triplet());
+ if (this->feature.empty() || this->feature == "core")
+ return Strings::format("%s:%s", this->spec.name(), this->spec.triplet());
+ return Strings::format("%s[%s]:%s", this->spec.name(), this->feature, this->spec.triplet());
}
std::string BinaryParagraph::dir() const { return this->spec.dir(); }
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
index e3787a97e..f43d8788e 100644
--- a/toolsrc/src/vcpkg/build.cpp
+++ b/toolsrc/src/vcpkg/build.cpp
@@ -67,7 +67,7 @@ namespace vcpkg::Build::Command
const Build::BuildPackageConfig build_config{
*scf, spec.triplet(), fs::path{port_dir}, build_package_options, features_as_set};
- const auto build_timer = Chrono::ElapsedTime::create_started();
+ const auto build_timer = Chrono::ElapsedTimer::create_started();
const auto result = Build::build_package(paths, build_config, status_db);
System::println("Elapsed time for package %s: %s", spec.to_string(), build_timer.to_string());
@@ -203,6 +203,10 @@ namespace vcpkg::Build
std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset)
{
+ if (pre_build_info.external_toolchain_file)
+ return Strings::format(
+ R"("%s" %s 2>&1)", toolset.vcvarsall.u8string(), Strings::join(" ", toolset.vcvarsall_options));
+
const char* tonull = " >nul";
if (GlobalState::debugging)
{
@@ -256,13 +260,13 @@ namespace vcpkg::Build
const BuildPackageConfig& config,
const StatusParagraphs& status_db)
{
- const PackageSpec spec =
- PackageSpec::from_name_and_triplet(config.src.name, config.triplet).value_or_exit(VCPKG_LINE_INFO);
+ const PackageSpec spec = PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, config.triplet)
+ .value_or_exit(VCPKG_LINE_INFO);
const Triplet& triplet = config.triplet;
{
std::vector<PackageSpec> missing_specs;
- for (auto&& dep : filter_dependencies(config.src.depends, triplet))
+ for (auto&& dep : filter_dependencies(config.scf.core_paragraph->depends, triplet))
{
if (status_db.find_installed(dep, triplet) == status_db.end())
{
@@ -286,27 +290,23 @@ namespace vcpkg::Build
std::string features;
if (GlobalState::feature_packages)
{
- if (config.feature_list)
+ for (auto&& feature : config.feature_list)
{
- for (auto&& feature : *config.feature_list)
- {
- features.append(feature + ";");
- }
- if (features.size() > 0)
- {
- features.pop_back();
- }
+ features.append(feature + ";");
+ }
+ if (features.size() > 0)
+ {
+ features.pop_back();
}
}
- const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path);
-
- const std::string cmd_launch_cmake = make_cmake_cmd(
+ const Toolset& toolset = paths.get_toolset(pre_build_info);
+ const std::string cmd_launch_cmake = System::make_cmake_cmd(
cmake_exe_path,
ports_cmake_script_path,
{
{"CMD", "BUILD"},
- {"PORT", config.src.name},
+ {"PORT", config.scf.core_paragraph->name},
{"CURRENT_PORT_DIR", config.port_dir / "/."},
{"TARGET_TRIPLET", triplet.canonical_name()},
{"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()},
@@ -320,7 +320,7 @@ namespace vcpkg::Build
const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset);
const std::string command = Strings::format(R"(%s && %s)", cmd_set_environment, cmd_launch_cmake);
- const auto timer = Chrono::ElapsedTime::create_started();
+ const auto timer = Chrono::ElapsedTimer::create_started();
const int return_code = System::cmd_execute_clean(command);
const auto buildtimeus = timer.microseconds();
@@ -340,7 +340,7 @@ namespace vcpkg::Build
const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec));
const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info);
- auto bcf = create_binary_control_file(config.src, triplet, build_info);
+ auto bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info);
if (error_count != 0)
{
@@ -348,16 +348,13 @@ namespace vcpkg::Build
}
if (GlobalState::feature_packages)
{
- if (config.feature_list)
+ for (auto&& feature : config.feature_list)
{
- for (auto&& feature : *config.feature_list)
+ for (auto&& f_pgh : config.scf.feature_paragraphs)
{
- for (auto&& f_pgh : config.scf->feature_paragraphs)
- {
- if (f_pgh->name == feature)
- bcf->features.push_back(
- create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet));
- }
+ if (f_pgh->name == feature)
+ bcf->features.push_back(
+ create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet));
}
}
}
@@ -493,11 +490,11 @@ namespace vcpkg::Build
const fs::path ports_cmake_script_path = paths.scripts / "get_triplet_environment.cmake";
const fs::path triplet_file_path = paths.triplets / (triplet.canonical_name() + ".cmake");
- const auto cmd_launch_cmake = make_cmake_cmd(cmake_exe_path,
- ports_cmake_script_path,
- {
- {"CMAKE_TRIPLET_FILE", triplet_file_path},
- });
+ const auto cmd_launch_cmake = System::make_cmake_cmd(cmake_exe_path,
+ ports_cmake_script_path,
+ {
+ {"CMAKE_TRIPLET_FILE", triplet_file_path},
+ });
const auto ec_data = System::cmd_execute_and_capture_output(cmd_launch_cmake);
Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, ec_data.output);
@@ -555,6 +552,27 @@ namespace vcpkg::Build
continue;
}
+ if (variable_name == "VCPKG_CHAINLOAD_TOOLCHAIN_FILE")
+ {
+ pre_build_info.external_toolchain_file =
+ variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
+ continue;
+ }
+
+ if (variable_name == "VCPKG_BUILD_TYPE")
+ {
+ if (variable_value.empty())
+ pre_build_info.build_type = nullopt;
+ else if (Strings::case_insensitive_ascii_equals(variable_value, "debug"))
+ pre_build_info.build_type = ConfigurationType::DEBUG;
+ else if (Strings::case_insensitive_ascii_equals(variable_value, "release"))
+ pre_build_info.build_type = ConfigurationType::RELEASE;
+ else
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "Unknown setting for VCPKG_BUILD_TYPE: %s", variable_value);
+ continue;
+ }
+
Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown variable name %s", line);
}
diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp
index 8f79b83e1..1a2f9b47f 100644
--- a/toolsrc/src/vcpkg/commands.ci.cpp
+++ b/toolsrc/src/vcpkg/commands.ci.cpp
@@ -27,7 +27,7 @@ namespace vcpkg::Commands::CI
const std::vector<PackageSpec> specs = PackageSpec::to_package_specs(ports, triplet);
StatusParagraphs status_db = database_load_check(paths);
- const auto& paths_port_file = Dependencies::PathsPortFile(paths);
+ const auto& paths_port_file = Dependencies::PathsPortFileProvider(paths);
std::vector<InstallPlanAction> install_plan =
Dependencies::create_install_plan(paths_port_file, specs, status_db);
@@ -63,9 +63,11 @@ namespace vcpkg::Commands::CI
};
static const std::string OPTION_EXCLUDE = "--exclude";
+ static const std::string OPTION_XUNIT = "--x-xunit";
- static const std::array<CommandSetting, 1> CI_SETTINGS = {{
+ static const std::array<CommandSetting, 2> CI_SETTINGS = {{
{OPTION_EXCLUDE, "Comma separated list of ports to skip"},
+ {OPTION_XUNIT, "File to output results in XUnit format (internal)"},
}};
const CommandStructure COMMAND_STRUCTURE = {
@@ -114,6 +116,18 @@ namespace vcpkg::Commands::CI
result.summary.print();
}
+ auto it_xunit = options.settings.find(OPTION_XUNIT);
+ if (it_xunit != options.settings.end())
+ {
+ std::string xunit_doc = "<assemblies><assembly><collection>\n";
+
+ for (auto&& result : results)
+ xunit_doc += result.summary.xunit_results();
+
+ xunit_doc += "</collection></assembly></assemblies>\n";
+ paths.get_filesystem().write_contents(fs::u8path(it_xunit->second), xunit_doc);
+ }
+
Checks::exit_success(VCPKG_LINE_INFO);
}
}
diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp
index 07dcea80e..8063fe317 100644
--- a/toolsrc/src/vcpkg/commands.contact.cpp
+++ b/toolsrc/src/vcpkg/commands.contact.cpp
@@ -1,8 +1,10 @@
#include "pch.h"
+#include <vcpkg/base/chrono.h>
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
#include <vcpkg/help.h>
+#include <vcpkg/userconfig.h>
namespace vcpkg::Commands::Contact
{
@@ -28,6 +30,17 @@ namespace vcpkg::Commands::Contact
if (Util::Sets::contains(parsed_args.switches, switches[0].name))
{
+#if defined(_WIN32)
+ auto maybe_now = Chrono::CTime::get_current_date_time();
+ if (auto p_now = maybe_now.get())
+ {
+ auto& fs = Files::get_real_filesystem();
+ auto config = UserConfig::try_read_data(fs);
+ config.last_completed_survey = p_now->to_string();
+ config.try_write_data(fs);
+ }
+#endif
+
System::cmd_execute("start https://aka.ms/NPS_vcpkg");
System::println("Default browser launched to https://aka.ms/NPS_vcpkg, thank you for your feedback!");
}
diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp
index 15b10c7ea..ccf6fa729 100644
--- a/toolsrc/src/vcpkg/commands.cpp
+++ b/toolsrc/src/vcpkg/commands.cpp
@@ -13,9 +13,10 @@ namespace vcpkg::Commands
Span<const PackageNameAndFunction<CommandTypeA>> get_available_commands_type_a()
{
static std::vector<PackageNameAndFunction<CommandTypeA>> t = {
- PackageNameAndFunction<CommandTypeA>{"install", &Install::perform_and_exit},
+ {"install", &Install::perform_and_exit},
{"ci", &CI::perform_and_exit},
{"remove", &Remove::perform_and_exit},
+ {"upgrade", &Upgrade::perform_and_exit},
{"build", &Build::Command::perform_and_exit},
{"env", &Env::perform_and_exit},
{"build-external", &BuildExternal::perform_and_exit},
diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp
index c7183d257..44f5f7928 100644
--- a/toolsrc/src/vcpkg/commands.create.cpp
+++ b/toolsrc/src/vcpkg/commands.create.cpp
@@ -4,7 +4,6 @@
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
#include <vcpkg/help.h>
-#include <vcpkg/vcpkglib.h>
namespace vcpkg::Commands::Create
{
@@ -25,7 +24,7 @@ namespace vcpkg::Commands::Create
const fs::path& cmake_exe = paths.get_cmake_exe();
- std::vector<CMakeVariable> cmake_args{{"CMD", "CREATE"}, {"PORT", port_name}, {"URL", url}};
+ std::vector<System::CMakeVariable> cmake_args{{"CMD", "CREATE"}, {"PORT", port_name}, {"URL", url}};
if (args.command_arguments.size() >= 3)
{
diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp
index 98b5aced9..6e52383d8 100644
--- a/toolsrc/src/vcpkg/commands.env.cpp
+++ b/toolsrc/src/vcpkg/commands.env.cpp
@@ -20,7 +20,7 @@ namespace vcpkg::Commands::Env
args.parse_arguments(COMMAND_STRUCTURE);
const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet);
- const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path);
+ const Toolset& toolset = paths.get_toolset(pre_build_info);
System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + " && cmd");
Checks::exit_success(VCPKG_LINE_INFO);
diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp
index 31b9ec722..460e99b88 100644
--- a/toolsrc/src/vcpkg/commands.integrate.cpp
+++ b/toolsrc/src/vcpkg/commands.integrate.cpp
@@ -139,7 +139,7 @@ namespace vcpkg::Commands::Integrate
static fs::path get_appdata_targets_path()
{
static const fs::path LOCAL_APP_DATA =
- fs::path(System::get_environment_variable("LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO));
+ fs::u8path(System::get_environment_variable("LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO));
return LOCAL_APP_DATA / "vcpkg" / "vcpkg.user.targets";
}
#endif
@@ -257,7 +257,7 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")",
std::error_code ec;
const bool was_deleted = fs.remove(path, ec);
- Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %d", ec.message());
+ Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %s", ec.message());
if (was_deleted)
{
@@ -324,18 +324,20 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
" vcpkg integrate install Make installed packages available user-wide. Requires admin privileges on "
"first use\n"
" vcpkg integrate remove Remove user-wide integration\n"
- " vcpkg integrate project Generate a referencing nuget package for individual VS project use\n";
+ " vcpkg integrate project Generate a referencing nuget package for individual VS project use\n"
+ " vcpkg integrate powershell Enable PowerShell Tab-Completion\n";
namespace Subcommand
{
static const std::string INSTALL = "install";
static const std::string REMOVE = "remove";
static const std::string PROJECT = "project";
+ static const std::string POWERSHELL = "powershell";
}
static std::vector<std::string> valid_arguments(const VcpkgPaths&)
{
- return {Subcommand::INSTALL, Subcommand::REMOVE, Subcommand::PROJECT};
+ return {Subcommand::INSTALL, Subcommand::REMOVE, Subcommand::PROJECT, Subcommand::POWERSHELL};
}
const CommandStructure COMMAND_STRUCTURE = {
@@ -365,6 +367,12 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
{
return integrate_project(paths);
}
+ if (args.command_arguments[0] == Subcommand::POWERSHELL)
+ {
+ System::powershell_execute("PowerShell Tab-Completion",
+ paths.scripts / "addPoshVcpkgToPowershellProfile.ps1");
+ Checks::exit_success(VCPKG_LINE_INFO);
+ }
#endif
Checks::exit_with_message(VCPKG_LINE_INFO, "Unknown parameter %s for integrate", args.command_arguments[0]);
diff --git a/toolsrc/src/vcpkg/commands.list.cpp b/toolsrc/src/vcpkg/commands.list.cpp
index 1f2387843..960c57225 100644
--- a/toolsrc/src/vcpkg/commands.list.cpp
+++ b/toolsrc/src/vcpkg/commands.list.cpp
@@ -13,14 +13,14 @@ namespace vcpkg::Commands::List
{
if (full_desc)
{
- System::println("%-30s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description);
+ System::println("%-50s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description);
}
else
{
- System::println("%-30s %-16s %s",
- vcpkg::shorten_text(pgh.package.displayname(), 30),
+ System::println("%-50s %-16s %s",
+ vcpkg::shorten_text(pgh.package.displayname(), 50),
vcpkg::shorten_text(pgh.package.version, 16),
- vcpkg::shorten_text(pgh.package.description, 71));
+ vcpkg::shorten_text(pgh.package.description, 51));
}
}
diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp
index 0277c8bdb..dba04ce5b 100644
--- a/toolsrc/src/vcpkg/commands.portsdiff.cpp
+++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp
@@ -98,8 +98,11 @@ namespace vcpkg::Commands::PortsDiff
".vcpkg-root",
git_exe.u8string());
System::cmd_execute_clean(cmd);
- const std::map<std::string, VersionT> names_and_versions = Paragraphs::load_all_port_names_and_versions(
- paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string);
+ const auto all_ports =
+ Paragraphs::load_all_ports(paths.get_filesystem(), temp_checkout_path / ports_dir_name_as_string);
+ std::map<std::string, VersionT> names_and_versions;
+ for (auto&& port : all_ports)
+ names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version);
fs.remove_all(temp_checkout_path, ec);
return names_and_versions;
}
@@ -151,14 +154,14 @@ namespace vcpkg::Commands::PortsDiff
const std::vector<std::string>& added_ports = setp.only_left;
if (!added_ports.empty())
{
- System::println("\nThe following %d ports were added:", added_ports.size());
+ System::println("\nThe following %zd ports were added:", added_ports.size());
do_print_name_and_version(added_ports, current_names_and_versions);
}
const std::vector<std::string>& removed_ports = setp.only_right;
if (!removed_ports.empty())
{
- System::println("\nThe following %d ports were removed:", removed_ports.size());
+ System::println("\nThe following %zd ports were removed:", removed_ports.size());
do_print_name_and_version(removed_ports, previous_names_and_versions);
}
@@ -168,7 +171,7 @@ namespace vcpkg::Commands::PortsDiff
if (!updated_ports.empty())
{
- System::println("\nThe following %d ports were updated:", updated_ports.size());
+ System::println("\nThe following %zd ports were updated:", updated_ports.size());
for (const UpdatedPort& p : updated_ports)
{
System::println(" - %-14s %-16s", p.port, p.version_diff.to_string());
diff --git a/toolsrc/src/vcpkg/commands.upgrade.cpp b/toolsrc/src/vcpkg/commands.upgrade.cpp
new file mode 100644
index 000000000..d2c868870
--- /dev/null
+++ b/toolsrc/src/vcpkg/commands.upgrade.cpp
@@ -0,0 +1,180 @@
+#include "pch.h"
+
+#include <vcpkg/base/util.h>
+#include <vcpkg/commands.h>
+#include <vcpkg/dependencies.h>
+#include <vcpkg/help.h>
+#include <vcpkg/input.h>
+#include <vcpkg/install.h>
+#include <vcpkg/statusparagraphs.h>
+#include <vcpkg/update.h>
+#include <vcpkg/vcpkglib.h>
+
+namespace vcpkg::Commands::Upgrade
+{
+ using Install::KeepGoing;
+ using Install::to_keep_going;
+
+ static const std::string OPTION_NO_DRY_RUN = "--no-dry-run";
+ static const std::string OPTION_KEEP_GOING = "--keep-going";
+
+ static const std::array<CommandSwitch, 2> INSTALL_SWITCHES = {{
+ {OPTION_NO_DRY_RUN, "Actually upgrade"},
+ {OPTION_KEEP_GOING, "Continue installing packages on failure"},
+ }};
+
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string("upgrade --no-dry-run"),
+ 0,
+ SIZE_MAX,
+ {INSTALL_SWITCHES, {}},
+ nullptr,
+ };
+
+ void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
+ {
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
+
+ const bool no_dry_run = Util::Sets::contains(options.switches, OPTION_NO_DRY_RUN);
+ const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING));
+
+ StatusParagraphs status_db = database_load_check(paths);
+
+ Dependencies::PathsPortFileProvider provider(paths);
+ Dependencies::PackageGraph graph(provider, status_db);
+
+ // input sanitization
+ const std::vector<PackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
+ return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text);
+ });
+
+ for (auto&& spec : specs)
+ {
+ Input::check_triplet(spec.triplet(), paths);
+ }
+
+ if (specs.empty())
+ {
+ // If no packages specified, upgrade all outdated packages.
+ auto outdated_packages = Update::find_outdated_packages(provider, status_db);
+
+ if (outdated_packages.empty())
+ {
+ System::println("All installed packages are up-to-date with the local portfiles.");
+ Checks::exit_success(VCPKG_LINE_INFO);
+ }
+
+ for (auto&& outdated_package : outdated_packages)
+ graph.upgrade(outdated_package.spec);
+ }
+ else
+ {
+ std::vector<PackageSpec> not_installed;
+ std::vector<PackageSpec> no_portfile;
+ std::vector<PackageSpec> to_upgrade;
+ std::vector<PackageSpec> up_to_date;
+
+ for (auto&& spec : specs)
+ {
+ auto it = status_db.find_installed(spec);
+ if (it == status_db.end())
+ {
+ not_installed.push_back(spec);
+ }
+
+ auto maybe_scf = provider.get_control_file(spec.name());
+ if (auto p_scf = maybe_scf.get())
+ {
+ if (it != status_db.end())
+ {
+ if (p_scf->core_paragraph->version != (*it)->package.version)
+ {
+ to_upgrade.push_back(spec);
+ }
+ else
+ {
+ up_to_date.push_back(spec);
+ }
+ }
+ }
+ else
+ {
+ no_portfile.push_back(spec);
+ }
+ }
+
+ Util::sort(not_installed);
+ Util::sort(no_portfile);
+ Util::sort(up_to_date);
+ Util::sort(to_upgrade);
+
+ if (!up_to_date.empty())
+ {
+ System::println(System::Color::success, "The following packages are up-to-date:");
+ System::println(Strings::join(
+ "", up_to_date, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; }));
+ }
+
+ if (!not_installed.empty())
+ {
+ System::println(System::Color::error, "The following packages are not installed:");
+ System::println(Strings::join(
+ "", not_installed, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; }));
+ }
+
+ if (!no_portfile.empty())
+ {
+ System::println(System::Color::error, "The following packages do not have a valid portfile:");
+ System::println(Strings::join(
+ "", no_portfile, [](const PackageSpec& spec) { return " " + spec.to_string() + "\n"; }));
+ }
+
+ Checks::check_exit(VCPKG_LINE_INFO, not_installed.empty() && no_portfile.empty());
+
+ if (to_upgrade.empty()) Checks::exit_success(VCPKG_LINE_INFO);
+
+ for (auto&& spec : to_upgrade)
+ graph.upgrade(spec);
+ }
+
+ auto plan = graph.serialize();
+
+ Checks::check_exit(VCPKG_LINE_INFO, !plan.empty());
+
+ const Build::BuildPackageOptions install_plan_options = {
+ Build::UseHeadVersion::NO,
+ Build::AllowDownloads::YES,
+ Build::CleanBuildtrees::NO,
+ };
+
+ // Set build settings for all install actions
+ for (auto&& action : plan)
+ {
+ if (auto p_install = action.install_action.get())
+ {
+ p_install->build_options = install_plan_options;
+ }
+ }
+
+ Dependencies::print_plan(plan, true);
+
+ if (!no_dry_run)
+ {
+ System::println(System::Color::warning,
+ "If you are sure you want to rebuild the above packages, run this command with the "
+ "--no-dry-run option.");
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+
+ const Install::InstallSummary summary = Install::perform(plan, keep_going, paths, status_db);
+
+ System::println("\nTotal elapsed time: %s\n", summary.total_elapsed_time);
+
+ if (keep_going == KeepGoing::YES)
+ {
+ summary.print();
+ }
+
+ Checks::exit_success(VCPKG_LINE_INFO);
+ }
+}
diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp
index 3f44cf1a2..c21e8cafd 100644
--- a/toolsrc/src/vcpkg/commands.version.cpp
+++ b/toolsrc/src/vcpkg/commands.version.cpp
@@ -12,6 +12,13 @@
namespace vcpkg::Commands::Version
{
+ const char* base_version()
+ {
+ return
+#include "../VERSION.txt"
+ ;
+ }
+
const std::string& version()
{
static const std::string S_VERSION =
diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp
index 6f599afd4..76aeb0eaa 100644
--- a/toolsrc/src/vcpkg/dependencies.cpp
+++ b/toolsrc/src/vcpkg/dependencies.cpp
@@ -65,26 +65,19 @@ namespace vcpkg::Dependencies
struct ClusterGraph : Util::MoveOnlyBase
{
- explicit ClusterGraph(std::unordered_map<std::string, const SourceControlFile*>&& ports)
- : m_ports(std::move(ports))
- {
- }
+ explicit ClusterGraph(const PortFileProvider& provider) : m_provider(provider) {}
Cluster& get(const PackageSpec& spec)
{
auto it = m_graph.find(spec);
if (it == m_graph.end())
{
- // Load on-demand from m_ports
- auto it_ports = m_ports.find(spec.name());
- if (it_ports != m_ports.end())
- {
- auto& clust = m_graph[spec];
- clust.spec = spec;
- cluster_from_scf(*it_ports->second, clust);
- return clust;
- }
- return m_graph[spec];
+ // Load on-demand from m_provider
+ auto maybe_scf = m_provider.get_control_file(spec.name());
+ auto& clust = m_graph[spec];
+ clust.spec = spec;
+ if (auto p_scf = maybe_scf.get()) cluster_from_scf(*p_scf, clust);
+ return clust;
}
return it->second;
}
@@ -107,26 +100,27 @@ namespace vcpkg::Dependencies
}
std::unordered_map<PackageSpec, Cluster> m_graph;
- std::unordered_map<std::string, const SourceControlFile*> m_ports;
+ const PortFileProvider& m_provider;
};
std::vector<PackageSpec> AnyParagraph::dependencies(const Triplet& triplet) const
{
if (const auto p = this->status_paragraph.get())
{
- return PackageSpec::to_package_specs(p->package.depends, triplet);
+ return PackageSpec::from_dependencies_of_port(p->package.spec.name(), p->package.depends, triplet);
}
if (const auto p = this->binary_control_file.get())
{
auto deps = Util::fmap_flatten(p->features, [](const BinaryParagraph& pgh) { return pgh.depends; });
deps.insert(deps.end(), p->core_paragraph.depends.cbegin(), p->core_paragraph.depends.cend());
- return PackageSpec::to_package_specs(deps, triplet);
+ return PackageSpec::from_dependencies_of_port(p->core_paragraph.spec.name(), deps, triplet);
}
- if (const auto p = this->source_paragraph.get())
+ if (const auto p = this->source_control_file.value_or(nullptr))
{
- return PackageSpec::to_package_specs(filter_dependencies(p->depends, triplet), triplet);
+ return PackageSpec::from_dependencies_of_port(
+ p->core_paragraph->name, filter_dependencies(p->core_paragraph->depends, triplet), triplet);
}
Checks::exit_with_message(VCPKG_LINE_INFO,
@@ -192,11 +186,13 @@ namespace vcpkg::Dependencies
return;
}
- if (auto p = any_paragraph.source_paragraph.get())
+ if (auto p = any_paragraph.source_control_file.get())
{
this->plan_type = InstallPlanType::BUILD_AND_INSTALL;
return;
}
+
+ Checks::unreachable(VCPKG_LINE_INFO);
}
std::string InstallPlanAction::displayname() const
@@ -226,12 +222,12 @@ namespace vcpkg::Dependencies
const PackageSpec& AnyAction::spec() const
{
- if (const auto p = install_plan.get())
+ if (const auto p = install_action.get())
{
return p->spec;
}
- if (const auto p = remove_plan.get())
+ if (const auto p = remove_action.get())
{
return p->spec;
}
@@ -257,7 +253,7 @@ namespace vcpkg::Dependencies
return;
}
- if (auto p = any_paragraph.source_paragraph.get())
+ if (auto p = any_paragraph.source_control_file.get())
{
this->plan_type = ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT;
return;
@@ -269,21 +265,20 @@ namespace vcpkg::Dependencies
return left->spec.name() < right->spec.name();
}
- MapPortFile::MapPortFile(const std::unordered_map<std::string, SourceControlFile>& map) : ports(map) {}
+ MapPortFileProvider::MapPortFileProvider(const std::unordered_map<std::string, SourceControlFile>& map) : ports(map)
+ {
+ }
- const SourceControlFile& MapPortFile::get_control_file(const std::string& spec) const
+ Optional<const SourceControlFile&> MapPortFileProvider::get_control_file(const std::string& spec) const
{
auto scf = ports.find(spec);
- if (scf == ports.end())
- {
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
+ if (scf == ports.end()) return nullopt;
return scf->second;
}
- PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {}
+ PathsPortFileProvider::PathsPortFileProvider(const VcpkgPaths& paths) : ports(paths) {}
- const SourceControlFile& PathsPortFile::get_control_file(const std::string& spec) const
+ Optional<const SourceControlFile&> PathsPortFileProvider::get_control_file(const std::string& spec) const
{
auto cache_it = cache.find(spec);
if (cache_it != cache.end())
@@ -298,56 +293,34 @@ namespace vcpkg::Dependencies
auto it = cache.emplace(spec, std::move(*scf->get()));
return it.first->second;
}
- print_error_message(source_control_file.error());
- Checks::exit_fail(VCPKG_LINE_INFO);
+ return nullopt;
}
std::vector<InstallPlanAction> create_install_plan(const PortFileProvider& port_file_provider,
const std::vector<PackageSpec>& specs,
const StatusParagraphs& status_db)
{
- struct InstallAdjacencyProvider final : Graphs::AdjacencyProvider<PackageSpec, InstallPlanAction>
- {
- const PortFileProvider& port_file_provider;
- const StatusParagraphs& status_db;
- const std::unordered_set<PackageSpec>& specs_as_set;
+ auto fspecs = Util::fmap(specs, [](const PackageSpec& spec) { return FeatureSpec(spec, ""); });
+ auto plan = create_feature_install_plan(port_file_provider, fspecs, status_db);
- InstallAdjacencyProvider(const PortFileProvider& port_file_provider,
- const StatusParagraphs& s,
- const std::unordered_set<PackageSpec>& specs_as_set)
- : port_file_provider(port_file_provider), status_db(s), specs_as_set(specs_as_set)
- {
- }
+ std::vector<InstallPlanAction> ret;
+ ret.reserve(plan.size());
- std::vector<PackageSpec> adjacency_list(const InstallPlanAction& plan) const override
+ for (auto&& action : plan)
+ {
+ if (auto p_install = action.install_action.get())
{
- if (plan.any_paragraph.status_paragraph.get()) return std::vector<PackageSpec>{};
- return plan.any_paragraph.dependencies(plan.spec.triplet());
+ ret.push_back(std::move(*p_install));
}
-
- InstallPlanAction load_vertex_data(const PackageSpec& spec) const override
+ else
{
- const RequestType request_type = specs_as_set.find(spec) != specs_as_set.end()
- ? RequestType::USER_REQUESTED
- : RequestType::AUTO_SELECTED;
- auto it = status_db.find_installed(spec);
- if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type};
- return InstallPlanAction{
- spec,
- {nullopt, nullopt, *port_file_provider.get_control_file(spec.name()).core_paragraph},
- request_type};
+ Checks::exit_with_message(VCPKG_LINE_INFO,
+ "The installation plan requires feature packages support. Please re-run the "
+ "command with --featurepackages.");
}
- };
-
- const std::unordered_set<PackageSpec> specs_as_set(specs.cbegin(), specs.cend());
- std::vector<InstallPlanAction> toposort =
- Graphs::topological_sort(specs, InstallAdjacencyProvider{port_file_provider, status_db, specs_as_set});
- Util::erase_remove_if(toposort, [](const InstallPlanAction& plan) {
- return plan.request_type == RequestType::AUTO_SELECTED &&
- plan.plan_type == InstallPlanType::ALREADY_INSTALLED;
- });
+ }
- return toposort;
+ return ret;
}
std::vector<RemovePlanAction> create_remove_plan(const std::vector<PackageSpec>& specs,
@@ -400,6 +373,8 @@ namespace vcpkg::Dependencies
}
return RemovePlanAction{spec, RemovePlanType::REMOVE, request_type};
}
+
+ std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); }
};
const std::vector<StatusParagraph*>& installed_ports = get_installed_ports(status_db);
@@ -407,7 +382,8 @@ namespace vcpkg::Dependencies
return Graphs::topological_sort(specs, RemoveAdjacencyProvider{status_db, installed_ports, specs_as_set});
}
- std::vector<ExportPlanAction> create_export_plan(const VcpkgPaths& paths,
+ std::vector<ExportPlanAction> create_export_plan(const PortFileProvider& port_file_provider,
+ const VcpkgPaths& paths,
const std::vector<PackageSpec>& specs,
const StatusParagraphs& status_db)
{
@@ -415,12 +391,14 @@ namespace vcpkg::Dependencies
{
const VcpkgPaths& paths;
const StatusParagraphs& status_db;
+ const PortFileProvider& provider;
const std::unordered_set<PackageSpec>& specs_as_set;
ExportAdjacencyProvider(const VcpkgPaths& p,
const StatusParagraphs& s,
+ const PortFileProvider& prov,
const std::unordered_set<PackageSpec>& specs_as_set)
- : paths(p), status_db(s), specs_as_set(specs_as_set)
+ : paths(p), status_db(s), provider(prov), specs_as_set(specs_as_set)
{
}
@@ -439,19 +417,18 @@ namespace vcpkg::Dependencies
if (auto bcf = maybe_bpgh.get())
return ExportPlanAction{spec, AnyParagraph{nullopt, std::move(*bcf), nullopt}, request_type};
- auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec));
- if (auto scf = maybe_scf.get())
- return ExportPlanAction{spec, {nullopt, nullopt, *scf->get()->core_paragraph}, request_type};
- else
- print_error_message(maybe_scf.error());
+ auto maybe_scf = provider.get_control_file(spec.name());
+ if (auto scf = maybe_scf.get()) return ExportPlanAction{spec, {nullopt, nullopt, scf}, request_type};
Checks::exit_with_message(VCPKG_LINE_INFO, "Could not find package %s", spec);
}
+
+ std::string to_string(const PackageSpec& spec) const override { return spec.to_string(); }
};
const std::unordered_set<PackageSpec> specs_as_set(specs.cbegin(), specs.cend());
- std::vector<ExportPlanAction> toposort =
- Graphs::topological_sort(specs, ExportAdjacencyProvider{paths, status_db, specs_as_set});
+ std::vector<ExportPlanAction> toposort = Graphs::topological_sort(
+ specs, ExportAdjacencyProvider{paths, status_db, port_file_provider, specs_as_set});
return toposort;
}
@@ -461,11 +438,12 @@ namespace vcpkg::Dependencies
SUCCESS,
};
- MarkPlusResult mark_plus(const std::string& feature,
- Cluster& cluster,
- ClusterGraph& pkg_to_cluster,
- GraphPlan& graph_plan);
- void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan);
+ static MarkPlusResult mark_plus(const std::string& feature,
+ Cluster& cluster,
+ ClusterGraph& pkg_to_cluster,
+ GraphPlan& graph_plan);
+
+ static void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan);
MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan)
{
@@ -557,111 +535,78 @@ namespace vcpkg::Dependencies
}
}
- static ClusterGraph create_feature_install_graph(const std::unordered_map<std::string, SourceControlFile>& map,
- const StatusParagraphs& status_db)
+ std::vector<AnyAction> create_feature_install_plan(const PortFileProvider& provider,
+ const std::vector<FeatureSpec>& specs,
+ const StatusParagraphs& status_db)
{
- std::unordered_map<std::string, const SourceControlFile*> ptr_map;
- for (auto&& p : map)
- ptr_map.emplace(p.first, &p.second);
- ClusterGraph graph(std::move(ptr_map));
-
- auto installed_ports = get_installed_ports(status_db);
-
- for (auto&& status_paragraph : installed_ports)
- {
- Cluster& cluster = graph.get(status_paragraph->package.spec);
-
- cluster.transient_uninstalled = false;
-
- cluster.status_paragraphs.emplace_back(status_paragraph);
-
- auto& status_paragraph_feature = status_paragraph->package.feature;
- // In this case, empty string indicates the "core" paragraph for a package.
- if (status_paragraph_feature.empty())
- {
- cluster.original_features.insert("core");
- }
- else
- {
- cluster.original_features.insert(status_paragraph_feature);
- }
- }
-
- for (auto&& status_paragraph : installed_ports)
- {
- auto& spec = status_paragraph->package.spec;
- auto& status_paragraph_feature = status_paragraph->package.feature;
- auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends,
- status_paragraph->package.spec.triplet());
-
- for (auto&& dependency : reverse_edges)
- {
- auto& dep_cluster = graph.get(dependency.spec());
-
- auto depends_name = dependency.feature();
- if (depends_name.empty()) depends_name = "core";
+ PackageGraph pgraph(provider, status_db);
+ for (auto&& spec : specs)
+ pgraph.install(spec);
- auto& target_node = dep_cluster.edges[depends_name];
- target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature});
- }
- }
- return graph;
+ return pgraph.serialize();
}
std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<std::string, SourceControlFile>& map,
const std::vector<FeatureSpec>& specs,
const StatusParagraphs& status_db)
{
- ClusterGraph graph = create_feature_install_graph(map, status_db);
+ MapPortFileProvider provider(map);
+ return create_feature_install_plan(provider, specs, status_db);
+ }
- GraphPlan graph_plan;
- for (auto&& spec : specs)
+ void PackageGraph::install(const FeatureSpec& spec)
+ {
+ Cluster& spec_cluster = m_graph->get(spec.spec());
+ spec_cluster.request_type = RequestType::USER_REQUESTED;
+ if (spec.feature() == "*")
{
- Cluster& spec_cluster = graph.get(spec.spec());
- spec_cluster.request_type = RequestType::USER_REQUESTED;
- if (spec.feature() == "*")
+ if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr))
{
- if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr))
+ for (auto&& feature : p_scf->feature_paragraphs)
{
- for (auto&& feature : p_scf->feature_paragraphs)
- {
- auto res = mark_plus(feature->name, spec_cluster, graph, graph_plan);
-
- Checks::check_exit(VCPKG_LINE_INFO,
- res == MarkPlusResult::SUCCESS,
- "Error: Unable to locate feature %s",
- spec);
- }
-
- auto res = mark_plus("core", spec_cluster, graph, graph_plan);
+ auto res = mark_plus(feature->name, spec_cluster, *m_graph, *m_graph_plan);
Checks::check_exit(
VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec);
}
- else
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec());
- }
- }
- else
- {
- auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan);
+
+ auto res = mark_plus("core", spec_cluster, *m_graph, *m_graph_plan);
Checks::check_exit(
VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec);
}
+ else
+ {
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "Error: Unable to handle '*' because can't find CONTROL for %s", spec.spec());
+ }
+ }
+ else
+ {
+ auto res = mark_plus(spec.feature(), spec_cluster, *m_graph, *m_graph_plan);
- graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster});
+ Checks::check_exit(
+ VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec);
}
- Graphs::GraphAdjacencyProvider<ClusterPtr> adjacency_remove_graph(graph_plan.remove_graph.adjacency_list());
- auto remove_vertex_list = graph_plan.remove_graph.vertex_list();
- auto remove_toposort = Graphs::topological_sort(remove_vertex_list, adjacency_remove_graph);
+ m_graph_plan->install_graph.add_vertex(ClusterPtr{&spec_cluster});
+ }
+
+ void PackageGraph::upgrade(const PackageSpec& spec)
+ {
+ Cluster& spec_cluster = m_graph->get(spec);
+ spec_cluster.request_type = RequestType::USER_REQUESTED;
+
+ mark_minus(spec_cluster, *m_graph, *m_graph_plan);
+ }
+
+ std::vector<AnyAction> PackageGraph::serialize() const
+ {
+ auto remove_vertex_list = m_graph_plan->remove_graph.vertex_list();
+ auto remove_toposort = Graphs::topological_sort(remove_vertex_list, m_graph_plan->remove_graph);
- Graphs::GraphAdjacencyProvider<ClusterPtr> adjacency_install_graph(graph_plan.install_graph.adjacency_list());
- auto insert_vertex_list = graph_plan.install_graph.vertex_list();
- auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph);
+ auto insert_vertex_list = m_graph_plan->install_graph.vertex_list();
+ auto insert_toposort = Graphs::topological_sort(insert_vertex_list, m_graph_plan->install_graph);
std::vector<AnyAction> plan;
@@ -705,4 +650,162 @@ namespace vcpkg::Dependencies
return plan;
}
+
+ static std::unique_ptr<ClusterGraph> create_feature_install_graph(const PortFileProvider& map,
+ const StatusParagraphs& status_db)
+ {
+ std::unique_ptr<ClusterGraph> graph = std::make_unique<ClusterGraph>(map);
+
+ auto installed_ports = get_installed_ports(status_db);
+
+ for (auto&& status_paragraph : installed_ports)
+ {
+ Cluster& cluster = graph->get(status_paragraph->package.spec);
+
+ cluster.transient_uninstalled = false;
+
+ cluster.status_paragraphs.emplace_back(status_paragraph);
+
+ auto& status_paragraph_feature = status_paragraph->package.feature;
+ // In this case, empty string indicates the "core" paragraph for a package.
+ if (status_paragraph_feature.empty())
+ {
+ cluster.original_features.insert("core");
+ }
+ else
+ {
+ cluster.original_features.insert(status_paragraph_feature);
+ }
+ }
+
+ // Populate the graph with "remove edges", which are the reverse of the Build-Depends edges.
+ for (auto&& status_paragraph : installed_ports)
+ {
+ auto& spec = status_paragraph->package.spec;
+ auto& status_paragraph_feature = status_paragraph->package.feature;
+ auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends,
+ status_paragraph->package.spec.triplet());
+
+ for (auto&& dependency : reverse_edges)
+ {
+ auto& dep_cluster = graph->get(dependency.spec());
+
+ auto depends_name = dependency.feature();
+ if (depends_name.empty()) depends_name = "core";
+
+ auto& target_node = dep_cluster.edges[depends_name];
+ target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature});
+ }
+ }
+ return graph;
+ }
+
+ PackageGraph::PackageGraph(const PortFileProvider& provider, const StatusParagraphs& status_db)
+ : m_graph(create_feature_install_graph(provider, status_db)), m_graph_plan(std::make_unique<GraphPlan>())
+ {
+ }
+
+ PackageGraph::~PackageGraph() {}
+
+ void print_plan(const std::vector<AnyAction>& action_plan, const bool is_recursive)
+ {
+ std::vector<const RemovePlanAction*> remove_plans;
+ std::vector<const InstallPlanAction*> rebuilt_plans;
+ std::vector<const InstallPlanAction*> only_install_plans;
+ std::vector<const InstallPlanAction*> new_plans;
+ std::vector<const InstallPlanAction*> already_installed_plans;
+ std::vector<const InstallPlanAction*> excluded;
+
+ const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool {
+ if (auto iplan = package.install_action.get())
+ return iplan->request_type != RequestType::USER_REQUESTED;
+ else
+ return false;
+ }) != action_plan.cend();
+
+ for (auto&& action : action_plan)
+ {
+ if (auto install_action = action.install_action.get())
+ {
+ // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at
+ // all.
+ auto it = Util::find_if(
+ remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; });
+ if (it != remove_plans.end())
+ {
+ rebuilt_plans.emplace_back(install_action);
+ }
+ else
+ {
+ switch (install_action->plan_type)
+ {
+ case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break;
+ case InstallPlanType::ALREADY_INSTALLED:
+ if (install_action->request_type == RequestType::USER_REQUESTED)
+ already_installed_plans.emplace_back(install_action);
+ break;
+ case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break;
+ case InstallPlanType::EXCLUDED: excluded.emplace_back(install_action); break;
+ default: Checks::unreachable(VCPKG_LINE_INFO);
+ }
+ }
+ }
+ else if (auto remove_action = action.remove_action.get())
+ {
+ remove_plans.emplace_back(remove_action);
+ }
+ }
+
+ std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name);
+ std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name);
+ std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name);
+ std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name);
+ std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name);
+ std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name);
+
+ static auto actions_to_output_string = [](const std::vector<const InstallPlanAction*>& v) {
+ return Strings::join("\n", v, [](const InstallPlanAction* p) {
+ return to_output_string(p->request_type, p->displayname(), p->build_options);
+ });
+ };
+
+ if (excluded.size() > 0)
+ {
+ System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded));
+ }
+
+ if (already_installed_plans.size() > 0)
+ {
+ System::println("The following packages are already installed:\n%s",
+ actions_to_output_string(already_installed_plans));
+ }
+
+ if (rebuilt_plans.size() > 0)
+ {
+ System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans));
+ }
+
+ if (new_plans.size() > 0)
+ {
+ System::println("The following packages will be built and installed:\n%s",
+ actions_to_output_string(new_plans));
+ }
+
+ if (only_install_plans.size() > 0)
+ {
+ System::println("The following packages will be directly installed:\n%s",
+ actions_to_output_string(only_install_plans));
+ }
+
+ if (has_non_user_requested_packages)
+ System::println("Additional packages (*) will be modified to complete this operation.");
+
+ if (remove_plans.size() > 0 && !is_recursive)
+ {
+ System::println(System::Color::warning,
+ "If you are sure you want to rebuild the above packages, run the command with the "
+ "--recurse option");
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ }
}
diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp
index 9b86863eb..e3221a12f 100644
--- a/toolsrc/src/vcpkg/export.cpp
+++ b/toolsrc/src/vcpkg/export.cpp
@@ -290,7 +290,7 @@ namespace vcpkg::Export
{OPTION_IFW_INSTALLER_FILE_PATH, "Specify the file path for the exported installer"},
}};
- const CommandStructure vcpkg::Export::COMMAND_STRUCTURE = {
+ const CommandStructure COMMAND_STRUCTURE = {
Help::create_example_string("export zlib zlib:x64-windows boost --nuget"),
0,
SIZE_MAX,
@@ -369,7 +369,8 @@ namespace vcpkg::Export
static void print_next_step_info(const fs::path& prefix)
{
const fs::path cmake_toolchain = prefix / "scripts" / "buildsystems" / "vcpkg.cmake";
- const CMakeVariable cmake_variable = CMakeVariable("CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string());
+ const System::CMakeVariable cmake_variable =
+ System::CMakeVariable("CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string());
System::println("\n"
"To use the exported libraries in CMake projects use:"
"\n"
@@ -477,7 +478,9 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
// create the plan
const StatusParagraphs status_db = database_load_check(paths);
- std::vector<ExportPlanAction> export_plan = Dependencies::create_export_plan(paths, opts.specs, status_db);
+ Dependencies::PathsPortFileProvider provider(paths);
+ std::vector<ExportPlanAction> export_plan =
+ Dependencies::create_export_plan(provider, paths, opts.specs, status_db);
Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty");
std::map<ExportPlanType, std::vector<const ExportPlanAction*>> group_by_plan_type;
diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp
index 43230fa4b..123c77d46 100644
--- a/toolsrc/src/vcpkg/globalstate.cpp
+++ b/toolsrc/src/vcpkg/globalstate.cpp
@@ -4,7 +4,9 @@
namespace vcpkg
{
- Util::LockGuarded<Chrono::ElapsedTime> GlobalState::timer;
+ Util::LockGuarded<Chrono::ElapsedTimer> GlobalState::timer;
+ Util::LockGuarded<std::string> GlobalState::g_surveydate;
+
std::atomic<bool> GlobalState::debugging(false);
std::atomic<bool> GlobalState::feature_packages(false);
diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp
index c83f0277b..b7d355742 100644
--- a/toolsrc/src/vcpkg/help.cpp
+++ b/toolsrc/src/vcpkg/help.cpp
@@ -85,6 +85,7 @@ namespace vcpkg::Help
" vcpkg remove --outdated Uninstall all out-of-date packages\n"
" vcpkg list List installed packages\n"
" vcpkg update Display list of packages for updating\n"
+ " vcpkg upgrade Rebuild all outdated packages\n"
" vcpkg hash <file> [alg] Hash a file by specific algorithm, default SHA512\n"
" vcpkg help topics Display the list of help topics\n"
" vcpkg help <topic> Display help for a specific topic\n"
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
index f48b04d68..dcc130be3 100644
--- a/toolsrc/src/vcpkg/install.cpp
+++ b/toolsrc/src/vcpkg/install.cpp
@@ -292,25 +292,13 @@ namespace vcpkg::Install
System::println("Building package %s... ", display_name_with_features);
auto result = [&]() -> Build::ExtendedBuildResult {
- if (GlobalState::feature_packages)
- {
- const Build::BuildPackageConfig build_config{
- *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO),
- action.spec.triplet(),
- paths.port_dir(action.spec),
- action.build_options,
- action.feature_list};
- return Build::build_package(paths, build_config, status_db);
- }
- else
- {
- const Build::BuildPackageConfig build_config{
- action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO),
- action.spec.triplet(),
- paths.port_dir(action.spec),
- action.build_options};
- return Build::build_package(paths, build_config, status_db);
- }
+ const Build::BuildPackageConfig build_config{
+ *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO),
+ action.spec.triplet(),
+ paths.port_dir(action.spec),
+ action.build_options,
+ action.feature_list};
+ return Build::build_package(paths, build_config, status_db);
}();
if (result.code != Build::BuildResult::SUCCEEDED)
@@ -348,108 +336,6 @@ namespace vcpkg::Install
Checks::unreachable(VCPKG_LINE_INFO);
}
- static void print_plan(const std::vector<AnyAction>& action_plan, const bool is_recursive)
- {
- std::vector<const RemovePlanAction*> remove_plans;
- std::vector<const InstallPlanAction*> rebuilt_plans;
- std::vector<const InstallPlanAction*> only_install_plans;
- std::vector<const InstallPlanAction*> new_plans;
- std::vector<const InstallPlanAction*> already_installed_plans;
- std::vector<const InstallPlanAction*> excluded;
-
- const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool {
- if (auto iplan = package.install_plan.get())
- return iplan->request_type != RequestType::USER_REQUESTED;
- else
- return false;
- }) != action_plan.cend();
-
- for (auto&& action : action_plan)
- {
- if (auto install_action = action.install_plan.get())
- {
- // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at
- // all.
- auto it = Util::find_if(
- remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; });
- if (it != remove_plans.end())
- {
- rebuilt_plans.emplace_back(install_action);
- }
- else
- {
- switch (install_action->plan_type)
- {
- case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break;
- case InstallPlanType::ALREADY_INSTALLED:
- if (install_action->request_type == RequestType::USER_REQUESTED)
- already_installed_plans.emplace_back(install_action);
- break;
- case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break;
- case InstallPlanType::EXCLUDED: excluded.emplace_back(install_action); break;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- }
- else if (auto remove_action = action.remove_plan.get())
- {
- remove_plans.emplace_back(remove_action);
- }
- }
-
- std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name);
- std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name);
- std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name);
- std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name);
- std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name);
- std::sort(excluded.begin(), excluded.end(), &InstallPlanAction::compare_by_name);
-
- static auto actions_to_output_string = [](const std::vector<const InstallPlanAction*>& v) {
- return Strings::join("\n", v, [](const InstallPlanAction* p) {
- return to_output_string(p->request_type, p->displayname(), p->build_options);
- });
- };
-
- if (excluded.size() > 0)
- {
- System::println("The following packages are excluded:\n%s", actions_to_output_string(excluded));
- }
-
- if (already_installed_plans.size() > 0)
- {
- System::println("The following packages are already installed:\n%s",
- actions_to_output_string(already_installed_plans));
- }
-
- if (rebuilt_plans.size() > 0)
- {
- System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans));
- }
-
- if (new_plans.size() > 0)
- {
- System::println("The following packages will be built and installed:\n%s",
- actions_to_output_string(new_plans));
- }
-
- if (only_install_plans.size() > 0)
- {
- System::println("The following packages will be directly installed:\n%s",
- actions_to_output_string(only_install_plans));
- }
-
- if (has_non_user_requested_packages)
- System::println("Additional packages (*) will be installed to complete this operation.");
-
- if (remove_plans.size() > 0 && !is_recursive)
- {
- System::println(System::Color::warning,
- "If you are sure you want to rebuild the above packages, run the command with the "
- "--recurse option");
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
- }
-
void InstallSummary::print() const
{
System::println("RESULTS");
@@ -484,22 +370,22 @@ namespace vcpkg::Install
{
std::vector<SpecSummary> results;
- const auto timer = Chrono::ElapsedTime::create_started();
+ const auto timer = Chrono::ElapsedTimer::create_started();
size_t counter = 0;
const size_t package_count = action_plan.size();
for (const auto& action : action_plan)
{
- const auto build_timer = Chrono::ElapsedTime::create_started();
+ const auto build_timer = Chrono::ElapsedTimer::create_started();
counter++;
const PackageSpec& spec = action.spec();
const std::string display_name = spec.to_string();
- System::println("Starting package %d/%d: %s", counter, package_count, display_name);
+ System::println("Starting package %zd/%zd: %s", counter, package_count, display_name);
results.emplace_back(spec, &action);
- if (const auto install_action = action.install_plan.get())
+ if (const auto install_action = action.install_action.get())
{
auto result = perform_install_plan_action(paths, *install_action, status_db);
@@ -511,9 +397,8 @@ namespace vcpkg::Install
results.back().build_result = std::move(result);
}
- else if (const auto remove_action = action.remove_plan.get())
+ else if (const auto remove_action = action.remove_action.get())
{
- Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages);
Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db);
}
else
@@ -521,8 +406,8 @@ namespace vcpkg::Install
Checks::unreachable(VCPKG_LINE_INFO);
}
- results.back().timing = build_timer.to_string();
- System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string());
+ results.back().timing = build_timer.elapsed();
+ System::println("Elapsed time for package %s: %s", display_name, results.back().timing.to_string());
}
return InstallSummary{std::move(results), timer.to_string()};
@@ -533,6 +418,7 @@ namespace vcpkg::Install
static const std::string OPTION_NO_DOWNLOADS = "--no-downloads";
static const std::string OPTION_RECURSE = "--recurse";
static const std::string OPTION_KEEP_GOING = "--keep-going";
+ static const std::string OPTION_XUNIT = "--x-xunit";
static const std::array<CommandSwitch, 5> INSTALL_SWITCHES = {{
{OPTION_DRY_RUN, "Do not actually build or install"},
@@ -541,7 +427,9 @@ namespace vcpkg::Install
{OPTION_RECURSE, "Allow removal of packages as part of installation"},
{OPTION_KEEP_GOING, "Continue installing packages on failure"},
}};
- static const std::array<std::string, 0> INSTALL_SETTINGS;
+ static const std::array<CommandSetting, 1> INSTALL_SETTINGS = {{
+ {OPTION_XUNIT, "File to output results in XUnit format (Internal use)"},
+ }};
std::vector<std::string> get_all_port_names(const VcpkgPaths& paths)
{
@@ -555,13 +443,13 @@ namespace vcpkg::Install
Help::create_example_string("install zlib zlib:x64-windows curl boost"),
1,
SIZE_MAX,
- {INSTALL_SWITCHES, {}},
+ {INSTALL_SWITCHES, INSTALL_SETTINGS},
&get_all_port_names,
};
static void print_cmake_information(const BinaryParagraph& bpgh, const VcpkgPaths& paths)
{
- static const std::regex cmake_library_regex("^add_library\\(([^\\s\\$\\)]+)\\s");
+ static const std::regex cmake_library_regex(R"(\badd_library\(([^\s\)]+)\s)", std::regex_constants::ECMAScript);
auto& fs = paths.get_filesystem();
@@ -579,15 +467,17 @@ namespace vcpkg::Install
auto files = fs.read_lines(paths.listfile_path(bpgh));
if (auto p_lines = files.get())
{
+ std::map<std::string, std::vector<std::string>> library_targets;
+
for (auto&& suffix : *p_lines)
{
- if (Strings::case_insensitive_ascii_find(suffix, "/share/") != suffix.end())
+ if (Strings::case_insensitive_ascii_find(suffix, "/share/") != suffix.end() &&
+ suffix.substr(suffix.size() - 6) == ".cmake")
{
- std::vector<std::string> library_targets;
-
// File is inside the share folder
auto path = paths.installed / suffix;
auto maybe_contents = fs.read_contents(path);
+ auto find_package_name = path.parent_path().filename().u8string();
if (auto p_contents = maybe_contents.get())
{
std::sregex_iterator next(p_contents->begin(), p_contents->end(), cmake_library_regex);
@@ -596,37 +486,40 @@ namespace vcpkg::Install
while (next != last)
{
auto match = *next;
- library_targets.push_back(match[1]);
+ library_targets[find_package_name].push_back(match[1]);
++next;
}
}
+ }
+ }
- if (library_targets.empty())
- {
- }
- else if (library_targets.size() <= 4)
+ if (library_targets.empty())
+ {
+ }
+ else
+ {
+ System::println("The package %s provides CMake targets:\n", bpgh.spec);
+
+ for (auto&& library_target_pair : library_targets)
+ {
+ if (library_target_pair.second.size() <= 4)
{
- System::println("The package %s provides CMake targets:\n"
- "\n"
- " find_package(%s REQUIRED)\n"
+ System::println(" find_package(%s REQUIRED)\n"
" target_link_libraries(main PRIVATE %s)\n",
- bpgh.spec,
- path.parent_path().filename().u8string(),
- Strings::join(" ", library_targets));
+ library_target_pair.first,
+ Strings::join(" ", library_target_pair.second));
}
else
{
- auto omitted = library_targets.size() - 4;
- library_targets.erase(library_targets.begin() + 4, library_targets.end());
- System::println("The package %s provides CMake targets:\n"
- "\n"
- " find_package(%s REQUIRED)\n"
- " # Note: %d targets were omitted\n"
+ 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::println(" find_package(%s REQUIRED)\n"
+ " # Note: %zd targets were omitted\n"
" target_link_libraries(main PRIVATE %s)\n",
- bpgh.spec,
- path.parent_path().filename().u8string(),
+ library_target_pair.first,
omitted,
- Strings::join(" ", library_targets));
+ Strings::join(" ", library_target_pair.second));
}
}
}
@@ -668,31 +561,33 @@ namespace vcpkg::Install
};
// Note: action_plan will hold raw pointers to SourceControlFiles from this map
- std::unordered_map<std::string, SourceControlFile> scf_map;
std::vector<AnyAction> action_plan;
- if (GlobalState::feature_packages)
+ auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
+ std::unordered_map<std::string, SourceControlFile> scf_map;
+ for (auto&& port : all_ports)
+ scf_map[port->core_paragraph->name] = std::move(*port);
+ MapPortFileProvider provider(scf_map);
+
+ action_plan = create_feature_install_plan(provider, FullPackageSpec::to_feature_specs(specs), status_db);
+
+ if (!GlobalState::feature_packages)
{
- auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
- for (auto&& port : all_ports)
+ for (auto&& action : action_plan)
{
- scf_map[port->core_paragraph->name] = std::move(*port);
+ if (action.remove_action.has_value())
+ {
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO,
+ "The installation plan requires feature packages support. Please re-run the "
+ "command with --featurepackages.");
+ }
}
- action_plan = create_feature_install_plan(scf_map, FullPackageSpec::to_feature_specs(specs), status_db);
- }
- else
- {
- Dependencies::PathsPortFile paths_port_file(paths);
- auto install_plan = Dependencies::create_install_plan(
- paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db);
-
- action_plan = Util::fmap(
- install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); });
}
for (auto&& action : action_plan)
{
- if (auto p_install = action.install_plan.get())
+ if (auto p_install = action.install_action.get())
{
p_install->build_options = install_plan_options;
if (p_install->request_type != RequestType::USER_REQUESTED)
@@ -705,16 +600,16 @@ namespace vcpkg::Install
// log the plan
const std::string specs_string = Strings::join(",", action_plan, [](const AnyAction& action) {
- if (auto iaction = action.install_plan.get())
+ if (auto iaction = action.install_action.get())
return iaction->spec.to_string();
- else if (auto raction = action.remove_plan.get())
+ else if (auto raction = action.remove_action.get())
return "R$" + raction->spec.to_string();
Checks::unreachable(VCPKG_LINE_INFO);
});
Metrics::g_metrics.lock()->track_property("installplan", specs_string);
- print_plan(action_plan, is_recursive);
+ Dependencies::print_plan(action_plan, is_recursive);
if (dry_run)
{
@@ -730,12 +625,21 @@ namespace vcpkg::Install
summary.print();
}
- auto& fs = paths.get_filesystem();
+ auto it_xunit = options.settings.find(OPTION_XUNIT);
+ if (it_xunit != options.settings.end())
+ {
+ std::string xunit_doc = "<assemblies><assembly><collection>\n";
+
+ xunit_doc += summary.xunit_results();
+
+ xunit_doc += "</collection></assembly></assemblies>\n";
+ paths.get_filesystem().write_contents(fs::u8path(it_xunit->second), xunit_doc);
+ }
for (auto&& result : summary.results)
{
if (!result.action) continue;
- if (auto p_install_action = result.action->install_plan.get())
+ if (auto p_install_action = result.action->install_action.get())
{
if (p_install_action->request_type != RequestType::USER_REQUESTED) continue;
auto bpgh = result.get_binary_paragraph();
@@ -748,7 +652,7 @@ namespace vcpkg::Install
}
SpecSummary::SpecSummary(const PackageSpec& spec, const Dependencies::AnyAction* action)
- : spec(spec), build_result{BuildResult::NULLVALUE, nullptr}, timing("0"), action(action)
+ : spec(spec), build_result{BuildResult::NULLVALUE, nullptr}, action(action)
{
}
@@ -756,7 +660,7 @@ namespace vcpkg::Install
{
if (build_result.binary_control_file) return &build_result.binary_control_file->core_paragraph;
if (action)
- if (auto p_install_plan = action->install_plan.get())
+ if (auto p_install_plan = action->install_action.get())
{
if (auto p_bcf = p_install_plan->any_paragraph.binary_control_file.get())
return &p_bcf->core_paragraph;
@@ -767,4 +671,41 @@ namespace vcpkg::Install
}
return nullptr;
}
+
+ std::string InstallSummary::xunit_results() const
+ {
+ std::string xunit_doc;
+ for (auto&& result : results)
+ {
+ std::string inner_block;
+ const char* result_string = "";
+ switch (result.build_result.code)
+ {
+ case BuildResult::POST_BUILD_CHECKS_FAILED:
+ case BuildResult::FILE_CONFLICTS:
+ case BuildResult::BUILD_FAILED:
+ result_string = "Fail";
+ inner_block = Strings::format("<failure><message><![CDATA[%s]]></message></failure>",
+ to_string(result.build_result.code));
+ break;
+ case BuildResult::EXCLUDED:
+ case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES:
+ result_string = "Skip";
+ inner_block =
+ Strings::format("<reason><![CDATA[%s]]></reason>", to_string(result.build_result.code));
+ break;
+ case BuildResult::SUCCEEDED: result_string = "Pass"; break;
+ default: Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+
+ xunit_doc += Strings::format(R"(<test name="%s" method="%s" time="%lld" result="%s">%s</test>)"
+ "\n",
+ result.spec,
+ result.spec,
+ result.timing.as<std::chrono::seconds>().count(),
+ result_string,
+ inner_block);
+ }
+ return xunit_doc;
+ }
}
diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp
index d7e18a176..cdb21d260 100644
--- a/toolsrc/src/vcpkg/metrics.cpp
+++ b/toolsrc/src/vcpkg/metrics.cpp
@@ -1,7 +1,9 @@
#include "pch.h"
+#include <vcpkg/commands.h>
#include <vcpkg/metrics.h>
+#include <vcpkg/base/chrono.h>
#include <vcpkg/base/files.h>
#include <vcpkg/base/strings.h>
#include <vcpkg/base/system.h>
@@ -15,32 +17,13 @@ namespace vcpkg::Metrics
static std::string get_current_date_time()
{
- struct tm newtime;
- std::array<char, 80> date;
- date.fill(0);
-
-#if defined(_WIN32)
- struct _timeb timebuffer;
-
- _ftime_s(&timebuffer);
- time_t now = timebuffer.time;
- const int milli = timebuffer.millitm;
-
- const errno_t err = gmtime_s(&newtime, &now);
-
- if (err)
+ auto maybe_time = Chrono::CTime::get_current_date_time();
+ if (auto ptime = maybe_time.get())
{
- return "";
+ return ptime->to_string();
}
-#else
- time_t now;
- time(&now);
- gmtime_r(&now, &newtime);
- const int milli = 0;
-#endif
- strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S", &newtime);
- return std::string(&date[0]) + "." + std::to_string(milli) + "Z";
+ return "";
}
static std::string generate_random_UUID()
@@ -255,9 +238,10 @@ namespace vcpkg::Metrics
auto match = *next;
if (match[0] != "00-00-00-00-00-00")
{
- std::string matchstr = match[0];
+ const std::string matchstr = match[0];
+ const System::PowershellParameter value("Value", matchstr);
auto hash_result = System::powershell_execute_and_capture_output(
- "SHA256Hash", get_vcpkg_root() / "SHA256Hash.ps1", Strings::format("-Value \"%s\"", matchstr));
+ "SHA256Hash", get_vcpkg_root() / "scripts" / "SHA256Hash.ps1", {value});
Util::erase_remove_if(hash_result,
[](char ch) { return !(ch >= 'A' && ch <= 'F') && !(ch >= '0' && ch <= '9'); });
hash_result = Strings::ascii_to_lowercase(hash_result);
@@ -393,8 +377,9 @@ namespace vcpkg::Metrics
wchar_t temp_folder[MAX_PATH];
GetTempPathW(MAX_PATH, temp_folder);
- const fs::path temp_folder_path = temp_folder;
- const fs::path temp_folder_path_exe = temp_folder_path / "vcpkgmetricsuploader.exe";
+ const fs::path temp_folder_path = fs::path(temp_folder) / "vcpkg";
+ const fs::path temp_folder_path_exe =
+ temp_folder_path / Strings::format("vcpkgmetricsuploader-%s.exe", Commands::Version::base_version());
auto& fs = Files::get_real_filesystem();
@@ -412,6 +397,8 @@ namespace vcpkg::Metrics
}();
std::error_code ec;
+ fs.create_directories(temp_folder_path, ec);
+ if (ec) return;
fs.copy_file(exe_path, temp_folder_path_exe, fs::copy_options::skip_existing, ec);
if (ec) return;
}
@@ -419,8 +406,9 @@ namespace vcpkg::Metrics
const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + generate_random_UUID() + ".txt");
fs.write_contents(vcpkg_metrics_txt_path, payload);
- const std::string cmd_line =
- Strings::format("start %s %s", temp_folder_path_exe.u8string(), vcpkg_metrics_txt_path.u8string());
+ const std::string cmd_line = Strings::format("start \"vcpkgmetricsuploader.exe\" \"%s\" \"%s\"",
+ temp_folder_path_exe.u8string(),
+ vcpkg_metrics_txt_path.u8string());
System::cmd_execute_clean(cmd_line);
#endif
}
diff --git a/toolsrc/src/vcpkg/packagespec.cpp b/toolsrc/src/vcpkg/packagespec.cpp
index eeb9981af..a9e072094 100644
--- a/toolsrc/src/vcpkg/packagespec.cpp
+++ b/toolsrc/src/vcpkg/packagespec.cpp
@@ -2,6 +2,7 @@
#include <vcpkg/base/util.h>
#include <vcpkg/packagespec.h>
+#include <vcpkg/packagespecparseresult.h>
#include <vcpkg/parse.h>
using vcpkg::Parse::parse_comma_list;
@@ -95,8 +96,40 @@ namespace vcpkg
std::vector<PackageSpec> PackageSpec::to_package_specs(const std::vector<std::string>& ports,
const Triplet& triplet)
{
- return Util::fmap(ports, [&](const std::string s) {
- return PackageSpec::from_name_and_triplet(s, triplet).value_or_exit(VCPKG_LINE_INFO);
+ return Util::fmap(ports, [&](const std::string& spec_as_string) -> PackageSpec {
+ auto maybe_spec = PackageSpec::from_name_and_triplet(spec_as_string, triplet);
+ if (auto spec = maybe_spec.get())
+ {
+ return std::move(*spec);
+ }
+
+ const PackageSpecParseResult error_type = maybe_spec.error();
+ Checks::exit_with_message(VCPKG_LINE_INFO,
+ "Invalid package: %s\n"
+ "%s",
+ spec_as_string,
+ vcpkg::to_string(error_type));
+ });
+ }
+
+ std::vector<PackageSpec> PackageSpec::from_dependencies_of_port(const std::string& port,
+ const std::vector<std::string>& dependencies,
+ const Triplet& triplet)
+ {
+ return Util::fmap(dependencies, [&](const std::string& spec_as_string) -> PackageSpec {
+ auto maybe_spec = PackageSpec::from_name_and_triplet(spec_as_string, triplet);
+ if (auto spec = maybe_spec.get())
+ {
+ return std::move(*spec);
+ }
+
+ const PackageSpecParseResult error_type = maybe_spec.error();
+ Checks::exit_with_message(VCPKG_LINE_INFO,
+ "Invalid dependency [%s] in package [%s]\n"
+ "%s",
+ spec_as_string,
+ port,
+ vcpkg::to_string(error_type));
});
}
diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp
index b93de190c..b66d53994 100644
--- a/toolsrc/src/vcpkg/paragraphs.cpp
+++ b/toolsrc/src/vcpkg/paragraphs.cpp
@@ -289,16 +289,4 @@ namespace vcpkg::Paragraphs
}
return std::move(results.paragraphs);
}
-
- std::map<std::string, VersionT> load_all_port_names_and_versions(const Files::Filesystem& fs,
- const fs::path& ports_dir)
- {
- auto all_ports = load_all_ports(fs, ports_dir);
-
- std::map<std::string, VersionT> names_and_versions;
- for (auto&& port : all_ports)
- names_and_versions.emplace(port->core_paragraph->name, port->core_paragraph->version);
-
- return names_and_versions;
- }
}
diff --git a/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp b/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp
index 2baaddb5e..e966ce78a 100644
--- a/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp
+++ b/toolsrc/src/vcpkg/postbuildlint.buildtype.cpp
@@ -3,6 +3,8 @@
#include <vcpkg/base/checks.h>
#include <vcpkg/postbuildlint.buildtype.h>
+using vcpkg::Build::ConfigurationType;
+
namespace vcpkg::PostBuildLint
{
BuildType BuildType::value_of(const ConfigurationType& config, const Build::LinkageType& linkage)
diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp
index d83d656cf..2b427737a 100644
--- a/toolsrc/src/vcpkg/postbuildlint.cpp
+++ b/toolsrc/src/vcpkg/postbuildlint.cpp
@@ -38,27 +38,41 @@ namespace vcpkg::PostBuildLint
}
};
- Span<const OutdatedDynamicCrt> get_outdated_dynamic_crts(CStringView toolset)
+ Span<const OutdatedDynamicCrt> get_outdated_dynamic_crts(const Optional<std::string>& toolset_version)
{
- static const std::vector<OutdatedDynamicCrt> V_NO_MSVCRT = {
+ static const std::vector<OutdatedDynamicCrt> V_NO_120 = {
{"msvcp100.dll", R"(msvcp100\.dll)"},
{"msvcp100d.dll", R"(msvcp100d\.dll)"},
{"msvcp110.dll", R"(msvcp110\.dll)"},
{"msvcp110_win.dll", R"(msvcp110_win\.dll)"},
- {"msvcp120.dll", R"(msvcp120\.dll)"},
- {"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"},
{"msvcp60.dll", R"(msvcp60\.dll)"},
{"msvcp60.dll", R"(msvcp60\.dll)"},
+ {"msvcrt.dll", R"(msvcrt\.dll)"},
{"msvcr100.dll", R"(msvcr100\.dll)"},
{"msvcr100d.dll", R"(msvcr100d\.dll)"},
{"msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)"},
{"msvcr110.dll", R"(msvcr110\.dll)"},
- {"msvcr120.dll", R"(msvcr120\.dll)"},
- {"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"},
{"msvcrt20.dll", R"(msvcrt20\.dll)"},
- {"msvcrt40.dll", R"(msvcrt40\.dll)"}};
+ {"msvcrt40.dll", R"(msvcrt40\.dll)"},
+ };
+
+ static const std::vector<OutdatedDynamicCrt> V_NO_MSVCRT = [&]() {
+ auto ret = V_NO_120;
+ ret.push_back({"msvcp120.dll", R"(msvcp120\.dll)"});
+ ret.push_back({"msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)"});
+ ret.push_back({"msvcr120.dll", R"(msvcr120\.dll)"});
+ ret.push_back({"msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)"});
+ return ret;
+ }();
+
+ const auto tsv = toolset_version.get();
+ if (tsv && (*tsv) == "v120")
+ {
+ return V_NO_120;
+ }
+ // Default case for all version >= VS 2015.
return V_NO_MSVCRT;
}
@@ -465,7 +479,7 @@ namespace vcpkg::PostBuildLint
}
System::println(System::Color::warning,
- "Mismatching number of debug and release binaries. Found %d for debug but %d for release.",
+ "Mismatching number of debug and release binaries. Found %zd for debug but %zd for release.",
debug_count,
release_count);
System::println("Debug binaries");
@@ -639,7 +653,8 @@ namespace vcpkg::PostBuildLint
static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector<fs::path>& dlls,
const fs::path dumpbin_exe,
- const BuildInfo& build_info)
+ const BuildInfo& build_info,
+ const PreBuildInfo& pre_build_info)
{
if (build_info.policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) return LintStatus::SUCCESS;
@@ -651,7 +666,7 @@ namespace vcpkg::PostBuildLint
System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line);
Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line);
- for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts("v141"))
+ for (const OutdatedDynamicCrt& outdated_crt : get_outdated_dynamic_crts(pre_build_info.platform_toolset))
{
if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), outdated_crt.regex))
{
@@ -711,7 +726,7 @@ namespace vcpkg::PostBuildLint
const auto& fs = paths.get_filesystem();
// for dumpbin
- const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path);
+ const Toolset& toolset = paths.get_toolset(pre_build_info);
const fs::path package_dir = paths.package_dir(spec);
size_t error_count = 0;
@@ -743,7 +758,8 @@ namespace vcpkg::PostBuildLint
std::vector<fs::path> release_libs = fs.get_files_recursive(release_lib_dir);
Util::unstable_keep_if(release_libs, has_extension_pred(fs, ".lib"));
- error_count += check_matching_debug_and_release_binaries(debug_libs, release_libs);
+ if (!pre_build_info.build_type)
+ error_count += check_matching_debug_and_release_binaries(debug_libs, release_libs);
{
std::vector<fs::path> libs;
@@ -762,7 +778,8 @@ namespace vcpkg::PostBuildLint
{
case Build::LinkageType::DYNAMIC:
{
- error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls);
+ if (!pre_build_info.build_type)
+ error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls);
error_count += check_lib_files_are_available_if_dlls_are_available(
build_info.policies, debug_libs.size(), debug_dlls.size(), debug_lib_dir);
@@ -777,7 +794,7 @@ namespace vcpkg::PostBuildLint
error_count += check_uwp_bit_of_dlls(pre_build_info.cmake_system_name, dlls, toolset.dumpbin);
error_count += check_dll_architecture(pre_build_info.target_architecture, dlls);
- error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info);
+ error_count += check_outdated_crt_linkage_of_dlls(dlls, toolset.dumpbin, build_info, pre_build_info);
break;
}
case Build::LinkageType::STATIC:
@@ -790,15 +807,15 @@ namespace vcpkg::PostBuildLint
if (!build_info.policies.is_enabled(BuildPolicy::ONLY_RELEASE_CRT))
{
- error_count +=
- check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::DEBUG, build_info.crt_linkage),
- debug_libs,
- toolset.dumpbin);
+ error_count += check_crt_linkage_of_libs(
+ BuildType::value_of(Build::ConfigurationType::DEBUG, build_info.crt_linkage),
+ debug_libs,
+ toolset.dumpbin);
}
- error_count +=
- check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::RELEASE, build_info.crt_linkage),
- release_libs,
- toolset.dumpbin);
+ error_count += check_crt_linkage_of_libs(
+ BuildType::value_of(Build::ConfigurationType::RELEASE, build_info.crt_linkage),
+ release_libs,
+ toolset.dumpbin);
break;
}
default: Checks::unreachable(VCPKG_LINE_INFO);
diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp
index 8ae0bc881..4079d60c1 100644
--- a/toolsrc/src/vcpkg/remove.cpp
+++ b/toolsrc/src/vcpkg/remove.cpp
@@ -207,10 +207,11 @@ namespace vcpkg::Remove
System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'");
Checks::exit_fail(VCPKG_LINE_INFO);
}
- specs = Util::fmap(
- Update::find_outdated_packages(
- Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports), status_db),
- [](auto&& outdated) { return outdated.spec; });
+
+ Dependencies::PathsPortFileProvider provider(paths);
+
+ specs = Util::fmap(Update::find_outdated_packages(provider, status_db),
+ [](auto&& outdated) { return outdated.spec; });
if (specs.empty())
{
diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp
index 29baef91e..d6c5614ed 100644
--- a/toolsrc/src/vcpkg/update.cpp
+++ b/toolsrc/src/vcpkg/update.cpp
@@ -14,7 +14,7 @@ namespace vcpkg::Update
return left.spec.name() < right.spec.name();
}
- std::vector<OutdatedPackage> find_outdated_packages(const std::map<std::string, VersionT>& src_names_to_versions,
+ std::vector<OutdatedPackage> find_outdated_packages(const Dependencies::PortFileProvider& provider,
const StatusParagraphs& status_db)
{
const std::vector<StatusParagraph*> installed_packages = get_installed_ports(status_db);
@@ -24,19 +24,23 @@ namespace vcpkg::Update
{
if (!pgh->package.feature.empty())
{
- // Skip feature packages; only consider master packages for needing updates.
+ // Skip feature paragraphs; only consider master paragraphs for needing updates.
continue;
}
- const auto it = src_names_to_versions.find(pgh->package.spec.name());
- if (it == src_names_to_versions.end())
+ auto maybe_scf = provider.get_control_file(pgh->package.spec.name());
+ if (auto p_scf = maybe_scf.get())
{
- // Package was not installed from portfile
- continue;
+ auto&& port_version = p_scf->core_paragraph->version;
+ auto&& installed_version = pgh->package.version;
+ if (installed_version != port_version)
+ {
+ output.push_back({pgh->package.spec, VersionDiff(installed_version, port_version)});
+ }
}
- if (it->second != pgh->package.version)
+ else
{
- output.push_back({pgh->package.spec, VersionDiff(pgh->package.version, it->second)});
+ // No portfile available
}
}
@@ -58,10 +62,10 @@ namespace vcpkg::Update
const StatusParagraphs status_db = database_load_check(paths);
- const auto outdated_packages = SortedVector<OutdatedPackage>(
- find_outdated_packages(Paragraphs::load_all_port_names_and_versions(paths.get_filesystem(), paths.ports),
- status_db),
- &OutdatedPackage::compare_by_name);
+ Dependencies::PathsPortFileProvider provider(paths);
+
+ const auto outdated_packages = SortedVector<OutdatedPackage>(find_outdated_packages(provider, status_db),
+ &OutdatedPackage::compare_by_name);
if (outdated_packages.empty())
{
@@ -69,19 +73,17 @@ namespace vcpkg::Update
}
else
{
- std::string install_line;
System::println("The following packages differ from their port versions:");
for (auto&& package : outdated_packages)
{
- install_line += package.spec.to_string();
- install_line += " ";
System::println(" %-32s %s", package.spec, package.version_diff.to_string());
}
System::println("\n"
- "To update these packages, run\n"
- " .\\vcpkg remove --outdated\n"
- " .\\vcpkg install " +
- install_line);
+ "To update these packages and all dependencies, run\n"
+ " .\\vcpkg upgrade\n"
+ "\n"
+ "To only remove outdated packages, run\n"
+ " .\\vcpkg remove --outdated\n");
}
Checks::exit_success(VCPKG_LINE_INFO);
diff --git a/toolsrc/src/vcpkg/userconfig.cpp b/toolsrc/src/vcpkg/userconfig.cpp
new file mode 100644
index 000000000..906594691
--- /dev/null
+++ b/toolsrc/src/vcpkg/userconfig.cpp
@@ -0,0 +1,88 @@
+#include "pch.h"
+
+#include <vcpkg/base/files.h>
+#include <vcpkg/base/lazy.h>
+#include <vcpkg/paragraphs.h>
+#include <vcpkg/userconfig.h>
+
+#if defined(_WIN32)
+namespace
+{
+ static vcpkg::Lazy<fs::path> s_localappdata;
+
+ static const fs::path& get_localappdata()
+ {
+ return s_localappdata.get_lazy([]() {
+ fs::path localappdata;
+ {
+ // Config path in AppDataLocal
+ wchar_t* localappdatapath = nullptr;
+ if (S_OK != SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localappdatapath)) __fastfail(1);
+ localappdata = localappdatapath;
+ CoTaskMemFree(localappdatapath);
+ }
+ return localappdata;
+ });
+ }
+}
+#endif
+
+namespace vcpkg
+{
+ UserConfig UserConfig::try_read_data(const Files::Filesystem& fs)
+ {
+ UserConfig ret;
+#if defined(_WIN32)
+ try
+ {
+ auto maybe_pghs = Paragraphs::get_paragraphs(fs, get_localappdata() / "vcpkg" / "config");
+ if (const auto p_pghs = maybe_pghs.get())
+ {
+ const auto& pghs = *p_pghs;
+
+ std::unordered_map<std::string, std::string> keys;
+ if (pghs.size() > 0) keys = pghs[0];
+
+ for (size_t x = 1; x < pghs.size(); ++x)
+ {
+ for (auto&& p : pghs[x])
+ keys.insert(p);
+ }
+
+ ret.user_id = keys["User-Id"];
+ ret.user_time = keys["User-Since"];
+ ret.user_mac = keys["Mac-Hash"];
+ ret.last_completed_survey = keys["Survey-Completed"];
+ }
+ }
+ catch (...)
+ {
+ }
+#endif
+
+ return ret;
+ }
+
+ void UserConfig::try_write_data(Files::Filesystem& fs) const
+ {
+#if defined(_WIN32)
+ try
+ {
+ std::error_code ec;
+ fs.create_directory(get_localappdata() / "vcpkg", ec);
+ fs.write_contents(get_localappdata() / "vcpkg" / "config",
+ Strings::format("User-Id: %s\n"
+ "User-Since: %s\n"
+ "Mac-Hash: %s\n"
+ "Survey-Completed: %s\n",
+ user_id,
+ user_time,
+ user_mac,
+ last_completed_survey));
+ }
+ catch (...)
+ {
+ }
+#endif
+ }
+}
diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp
index 38b130f6f..5b2cec4d0 100644
--- a/toolsrc/src/vcpkg/vcpkglib.cpp
+++ b/toolsrc/src/vcpkg/vcpkglib.cpp
@@ -212,29 +212,7 @@ namespace vcpkg
return installed_files;
}
- CMakeVariable::CMakeVariable(const CStringView varname, const char* varvalue)
- : s(Strings::format(R"("-D%s=%s")", varname, varvalue))
- {
- }
- CMakeVariable::CMakeVariable(const CStringView varname, const std::string& varvalue)
- : CMakeVariable(varname, varvalue.c_str())
- {
- }
- CMakeVariable::CMakeVariable(const CStringView varname, const fs::path& path)
- : CMakeVariable(varname, path.generic_u8string())
- {
- }
-
- std::string make_cmake_cmd(const fs::path& cmake_exe,
- const fs::path& cmake_script,
- const std::vector<CMakeVariable>& pass_variables)
- {
- const std::string cmd_cmake_pass_variables = Strings::join(" ", pass_variables, [](auto&& v) { return v.s; });
- return Strings::format(
- R"("%s" %s -P "%s")", cmake_exe.u8string(), cmd_cmake_pass_variables, cmake_script.generic_u8string());
- }
-
- std::string shorten_text(const std::string& desc, size_t length)
+ std::string shorten_text(const std::string& desc, const size_t length)
{
Checks::check_exit(VCPKG_LINE_INFO, length >= 3);
auto simple_desc = std::regex_replace(desc, std::regex("\\s+"), " ");
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
index a553f4199..e64a681e2 100644
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp
@@ -4,6 +4,7 @@
#include <vcpkg/base/files.h>
#include <vcpkg/base/system.h>
#include <vcpkg/base/util.h>
+#include <vcpkg/build.h>
#include <vcpkg/metrics.h>
#include <vcpkg/packagespec.h>
#include <vcpkg/vcpkgpaths.h>
@@ -91,9 +92,10 @@ namespace vcpkg
tool_name,
version_as_string);
const fs::path script = scripts_folder / "fetchDependency.ps1";
- const std::string title = "Fetching %s version %s (No sufficient installed version was found)";
- const std::string output =
- System::powershell_execute_and_capture_output(title, script, Strings::format("-Dependency %s", tool_name));
+ const std::string title = Strings::format(
+ "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string);
+ const System::PowershellParameter dependency_param("Dependency", tool_name);
+ const std::string output = System::powershell_execute_and_capture_output(title, script, {dependency_param});
const std::vector<std::string> dependency_path = keep_data_lines(output);
Checks::check_exit(
@@ -112,14 +114,20 @@ namespace vcpkg
static fs::path get_cmake_path(const fs::path& downloads_folder, const fs::path& scripts_folder)
{
- static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 9, 5};
+#if defined(_WIN32)
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 10, 0};
+#else
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 5, 1};
+#endif
static const std::string VERSION_CHECK_ARGUMENTS = "--version";
- const fs::path downloaded_copy = downloads_folder / "cmake-3.9.5-win32-x86" / "bin" / "cmake.exe";
const std::vector<fs::path> from_path = Files::find_from_PATH("cmake");
std::vector<fs::path> candidate_paths;
+ const fs::path downloaded_copy = downloads_folder / "cmake-3.10.0-win32-x86" / "bin" / "cmake.exe";
+#if defined(_WIN32)
candidate_paths.push_back(downloaded_copy);
+#endif
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
#if defined(_WIN32)
candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe");
@@ -158,14 +166,20 @@ namespace vcpkg
fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder)
{
+#if defined(_WIN32)
static constexpr std::array<int, 3> EXPECTED_VERSION = {2, 15, 0};
+#else
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {2, 7, 4};
+#endif
static const std::string VERSION_CHECK_ARGUMENTS = "--version";
- const fs::path downloaded_copy = downloads_folder / "MinGit-2.15.0-32-bit" / "cmd" / "git.exe";
const std::vector<fs::path> from_path = Files::find_from_PATH("git");
+ const fs::path downloaded_copy = downloads_folder / "MinGit-2.15.0-32-bit" / "cmd" / "git.exe";
std::vector<fs::path> candidate_paths;
+#if defined(_WIN32)
candidate_paths.push_back(downloaded_copy);
+#endif
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
#if defined(_WIN32)
candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe");
@@ -267,7 +281,6 @@ namespace vcpkg
const std::vector<std::string>& VcpkgPaths::get_available_triplets() const
{
return this->available_triplets.get_lazy([this]() -> std::vector<std::string> {
-
std::vector<std::string> output;
for (auto&& path : this->get_filesystem().get_files_non_recursive(this->triplets))
{
@@ -371,6 +384,7 @@ namespace vcpkg
std::vector<fs::path> paths_examined;
std::vector<Toolset> found_toolsets;
+ std::vector<Toolset> excluded_toolsets;
const std::vector<VisualStudioInstance> vs_instances = get_visual_studio_instances(paths);
const bool v140_is_available = Util::find_if(vs_instances, [&](const VisualStudioInstance& vs_instance) {
@@ -427,17 +441,28 @@ namespace vcpkg
paths_examined.push_back(dumpbin_path);
if (fs.exists(dumpbin_path))
{
- found_toolsets.push_back(Toolset{
- vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures});
+ const Toolset v141toolset = Toolset{
+ vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures};
+
+ auto english_language_pack = dumpbin_path.parent_path() / "1033";
+
+ if (!fs.exists(english_language_pack))
+ {
+ excluded_toolsets.push_back(v141toolset);
+ break;
+ }
+
+ found_toolsets.push_back(v141toolset);
if (v140_is_available)
{
- found_toolsets.push_back(Toolset{vs_instance.root_path,
- dumpbin_path,
- vcvarsall_bat,
- {"-vcvars_ver=14.0"},
- V_140,
- supported_architectures});
+ const Toolset v140toolset = Toolset{vs_instance.root_path,
+ dumpbin_path,
+ vcvarsall_bat,
+ {"-vcvars_ver=14.0"},
+ V_140,
+ supported_architectures};
+ found_toolsets.push_back(v140toolset);
}
break;
@@ -447,44 +472,66 @@ namespace vcpkg
continue;
}
- if (major_version == "14")
+ if (major_version == "14" || major_version == "12")
{
const fs::path vcvarsall_bat = vs_instance.root_path / "VC" / "vcvarsall.bat";
paths_examined.push_back(vcvarsall_bat);
if (fs.exists(vcvarsall_bat))
{
- const fs::path vs2015_dumpbin_exe = vs_instance.root_path / "VC" / "bin" / "dumpbin.exe";
- paths_examined.push_back(vs2015_dumpbin_exe);
+ const fs::path vs_dumpbin_exe = vs_instance.root_path / "VC" / "bin" / "dumpbin.exe";
+ paths_examined.push_back(vs_dumpbin_exe);
- const fs::path vs2015_bin_dir = vcvarsall_bat.parent_path() / "bin";
+ const fs::path vs_bin_dir = vcvarsall_bat.parent_path() / "bin";
std::vector<ToolsetArchOption> supported_architectures;
- if (fs.exists(vs2015_bin_dir / "vcvars32.bat"))
+ if (fs.exists(vs_bin_dir / "vcvars32.bat"))
supported_architectures.push_back({"x86", CPU::X86, CPU::X86});
- if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat"))
+ if (fs.exists(vs_bin_dir / "amd64\\vcvars64.bat"))
supported_architectures.push_back({"x64", CPU::X64, CPU::X64});
- if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat"))
+ if (fs.exists(vs_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat"))
supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64});
- if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat"))
+ if (fs.exists(vs_bin_dir / "x86_arm\\vcvarsx86_arm.bat"))
supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM});
- if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat"))
+ if (fs.exists(vs_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat"))
supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86});
- if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat"))
+ if (fs.exists(vs_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat"))
supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM});
- if (fs.exists(vs2015_dumpbin_exe))
+ if (fs.exists(vs_dumpbin_exe))
{
- found_toolsets.push_back({vs_instance.root_path,
- vs2015_dumpbin_exe,
- vcvarsall_bat,
- {},
- V_140,
- supported_architectures});
+ const Toolset toolset = {vs_instance.root_path,
+ vs_dumpbin_exe,
+ vcvarsall_bat,
+ {},
+ major_version == "14" ? V_140 : V_120,
+ supported_architectures};
+
+ auto english_language_pack = vs_dumpbin_exe.parent_path() / "1033";
+
+ if (!fs.exists(english_language_pack))
+ {
+ excluded_toolsets.push_back(toolset);
+ break;
+ }
+
+ found_toolsets.push_back(toolset);
}
}
}
}
+ if (!excluded_toolsets.empty())
+ {
+ System::println(
+ System::Color::warning,
+ "Warning: The following VS instances are exluded because the English language pack is unavailable.");
+ for (const Toolset& toolset : excluded_toolsets)
+ {
+ System::println(" %s", toolset.visual_studio_root_path.u8string());
+ }
+ System::println(System::Color::warning, "Please install the English language pack.");
+ }
+
if (found_toolsets.empty())
{
System::println(System::Color::error, "Could not locate a complete toolset.");
@@ -499,16 +546,36 @@ namespace vcpkg
return found_toolsets;
}
- const Toolset& VcpkgPaths::get_toolset(const Optional<std::string>& toolset_version,
- const Optional<fs::path>& visual_studio_path) const
+ const Toolset& VcpkgPaths::get_toolset(const Build::PreBuildInfo& prebuildinfo) const
{
+ if (prebuildinfo.external_toolchain_file)
+ {
+ static Toolset external_toolset = []() -> Toolset {
+ Toolset ret;
+ ret.dumpbin = "";
+ ret.supported_architectures = {
+ ToolsetArchOption{"", System::get_host_processor(), System::get_host_processor()}};
+#if defined(_WIN32)
+ ret.vcvarsall = "cmd";
+ ret.vcvarsall_options = {"/c", "echo done"};
+#else
+ ret.vcvarsall = "true";
+ ret.vcvarsall_options = {};
+#endif
+ ret.version = "external";
+ ret.visual_studio_root_path = "";
+ return ret;
+ }();
+ return external_toolset;
+ }
+
// Invariant: toolsets are non-empty and sorted with newest at back()
const std::vector<Toolset>& vs_toolsets =
this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); });
std::vector<const Toolset*> candidates = Util::element_pointers(vs_toolsets);
- const auto tsv = toolset_version.get();
- const auto vsp = visual_studio_path.get();
+ const auto tsv = prebuildinfo.platform_toolset.get();
+ const auto vsp = prebuildinfo.visual_studio_path.get();
if (tsv && vsp)
{
@@ -542,6 +609,7 @@ namespace vcpkg
vs_root_path.generic_string());
}
+ Checks::check_exit(VCPKG_LINE_INFO, !candidates.empty(), "No suitable Visual Studio instances were found");
return *candidates.front();
}