aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authormartin-s <webmaster@macside.net>2017-11-05 19:13:16 +0100
committermartin-s <webmaster@macside.net>2017-11-05 19:13:16 +0100
commitd5a7da6bcb92b551d6f8a9a321deb063f6632dbc (patch)
tree9dfef57f1fb3611bde577cab7b9dee9411ffb041 /toolsrc/src
parentc6d69fac625706c52fc8e48615bc0c6d7b8dad25 (diff)
parent330b8d8bab6a3d07165bf7c05fea09a8e0d56348 (diff)
downloadvcpkg-d5a7da6bcb92b551d6f8a9a321deb063f6632dbc.tar.gz
vcpkg-d5a7da6bcb92b551d6f8a9a321deb063f6632dbc.zip
Merge branch 'master' of https://github.com/Microsoft/vcpkg into patch-vs2013
# Conflicts: # scripts/cmake/vcpkg_configure_cmake.cmake # toolsrc/src/vcpkg/vcpkgpaths.cpp
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/tests.arguments.cpp11
-rw-r--r--toolsrc/src/tests.installplan.cpp40
-rw-r--r--toolsrc/src/tests.packagespec.cpp34
-rw-r--r--toolsrc/src/tests.paragraph.cpp30
-rw-r--r--toolsrc/src/tests.statusparagraphs.cpp85
-rw-r--r--toolsrc/src/vcpkg.cpp56
-rw-r--r--toolsrc/src/vcpkg/base/checks.cpp12
-rw-r--r--toolsrc/src/vcpkg/base/cofffilereader.cpp7
-rw-r--r--toolsrc/src/vcpkg/base/files.cpp13
-rw-r--r--toolsrc/src/vcpkg/base/strings.cpp68
-rw-r--r--toolsrc/src/vcpkg/base/system.cpp207
-rw-r--r--toolsrc/src/vcpkg/binaryparagraph.cpp8
-rw-r--r--toolsrc/src/vcpkg/build.cpp130
-rw-r--r--toolsrc/src/vcpkg/commands.autocomplete.cpp139
-rw-r--r--toolsrc/src/vcpkg/commands.buildexternal.cpp20
-rw-r--r--toolsrc/src/vcpkg/commands.cache.cpp16
-rw-r--r--toolsrc/src/vcpkg/commands.ci.cpp95
-rw-r--r--toolsrc/src/vcpkg/commands.contact.cpp12
-rw-r--r--toolsrc/src/vcpkg/commands.cpp2
-rw-r--r--toolsrc/src/vcpkg/commands.create.cpp21
-rw-r--r--toolsrc/src/vcpkg/commands.dependinfo.cpp12
-rw-r--r--toolsrc/src/vcpkg/commands.edit.cpp49
-rw-r--r--toolsrc/src/vcpkg/commands.env.cpp14
-rw-r--r--toolsrc/src/vcpkg/commands.exportifw.cpp32
-rw-r--r--toolsrc/src/vcpkg/commands.hash.cpp38
-rw-r--r--toolsrc/src/vcpkg/commands.import.cpp14
-rw-r--r--toolsrc/src/vcpkg/commands.integrate.cpp75
-rw-r--r--toolsrc/src/vcpkg/commands.list.cpp25
-rw-r--r--toolsrc/src/vcpkg/commands.owns.cpp15
-rw-r--r--toolsrc/src/vcpkg/commands.portsdiff.cpp61
-rw-r--r--toolsrc/src/vcpkg/commands.search.cpp37
-rw-r--r--toolsrc/src/vcpkg/commands.version.cpp26
-rw-r--r--toolsrc/src/vcpkg/dependencies.cpp83
-rw-r--r--toolsrc/src/vcpkg/export.cpp136
-rw-r--r--toolsrc/src/vcpkg/globalstate.cpp8
-rw-r--r--toolsrc/src/vcpkg/help.cpp115
-rw-r--r--toolsrc/src/vcpkg/install.cpp209
-rw-r--r--toolsrc/src/vcpkg/metrics.cpp61
-rw-r--r--toolsrc/src/vcpkg/packagespec.cpp12
-rw-r--r--toolsrc/src/vcpkg/parse.cpp2
-rw-r--r--toolsrc/src/vcpkg/postbuildlint.cpp39
-rw-r--r--toolsrc/src/vcpkg/remove.cpp54
-rw-r--r--toolsrc/src/vcpkg/sourceparagraph.cpp6
-rw-r--r--toolsrc/src/vcpkg/statusparagraphs.cpp26
-rw-r--r--toolsrc/src/vcpkg/triplet.cpp14
-rw-r--r--toolsrc/src/vcpkg/update.cpp11
-rw-r--r--toolsrc/src/vcpkg/vcpkgcmdarguments.cpp145
-rw-r--r--toolsrc/src/vcpkg/vcpkglib.cpp26
-rw-r--r--toolsrc/src/vcpkg/vcpkgpaths.cpp206
49 files changed, 1605 insertions, 952 deletions
diff --git a/toolsrc/src/tests.arguments.cpp b/toolsrc/src/tests.arguments.cpp
index 25bf0f085..0f082222d 100644
--- a/toolsrc/src/tests.arguments.cpp
+++ b/toolsrc/src/tests.arguments.cpp
@@ -34,9 +34,12 @@ namespace UnitTest1
TEST_METHOD(create_from_arg_sequence_valued_options)
{
+ std::array<CommandSetting, 1> settings = { {{"--a", ""}} };
+ CommandStructure cmdstruct = { "", 0, SIZE_MAX, {{}, settings }, nullptr };
+
std::vector<std::string> t = {"--a=b", "command", "argument"};
auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- auto opts = v.check_and_get_optional_command_arguments({}, {"--a"});
+ auto opts = v.parse_arguments(cmdstruct);
Assert::AreEqual("b", opts.settings["--a"].c_str());
Assert::AreEqual(size_t{1}, v.command_arguments.size());
Assert::AreEqual("argument", v.command_arguments[0].c_str());
@@ -45,9 +48,13 @@ namespace UnitTest1
TEST_METHOD(create_from_arg_sequence_valued_options2)
{
+ std::array<CommandSwitch, 2> switches = { {{"--a", ""}, {"--c", ""}} };
+ std::array<CommandSetting, 2> settings = { { {"--b", ""}, {"--d", ""}} };
+ CommandStructure cmdstruct = {"", 0, SIZE_MAX, {switches, settings}, nullptr};
+
std::vector<std::string> t = {"--a", "--b=c"};
auto v = VcpkgCmdArguments::create_from_arg_sequence(t.data(), t.data() + t.size());
- auto opts = v.check_and_get_optional_command_arguments({"--a", "--c"}, {"--b", "--d"});
+ auto opts = v.parse_arguments(cmdstruct);
Assert::AreEqual("c", opts.settings["--b"].c_str());
Assert::IsTrue(opts.settings.find("--d") == opts.settings.end());
Assert::IsTrue(opts.switches.find("--a") != opts.switches.end());
diff --git a/toolsrc/src/tests.installplan.cpp b/toolsrc/src/tests.installplan.cpp
index 120009db5..129926317 100644
--- a/toolsrc/src/tests.installplan.cpp
+++ b/toolsrc/src/tests.installplan.cpp
@@ -17,8 +17,9 @@ namespace Microsoft::VisualStudio::CppUnitTestFramework
case Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED";
case Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL";
case Dependencies::InstallPlanType::INSTALL: return L"INSTALL";
+ case Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED";
case Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN";
- default: return ToString((int)t);
+ default: return ToString(static_cast<int>(t));
}
}
@@ -30,7 +31,7 @@ namespace Microsoft::VisualStudio::CppUnitTestFramework
case Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED";
case Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED";
case Dependencies::RequestType::UNKNOWN: return L"UNKNOWN";
- default: return ToString((int)t);
+ default: return ToString(static_cast<int>(t));
}
}
}
@@ -460,20 +461,6 @@ namespace UnitTest1
FullPackageSpec::to_feature_specs({spec_c_64, spec_a_86, spec_a_64, spec_c_86}),
StatusParagraphs(std::move(status_paragraphs)));
- /*Assert::AreEqual(size_t(8), install_plan.size());
- auto iterator_pos = [&](const PackageSpec& spec, size_t start) -> int {
- auto it = std::find_if(install_plan.begin() + start, install_plan.end(), [&](auto& action) {
- return action.spec == spec;
- });
- Assert::IsTrue(it != install_plan.end());
- return (int)(it - install_plan.begin());
- };
- int a_64_1 = iterator_pos(spec_a_64.package_spec, 0), a_86_1 = iterator_pos(spec_a_86.package_spec, 0),
- b_64 = iterator_pos(spec_b_64.package_spec, 0), b_86 = iterator_pos(spec_b_86.package_spec, 0),
- c_64 = iterator_pos(spec_c_64.package_spec, 0), c_86 = iterator_pos(spec_c_86.package_spec, 0),
- a_64_2 = iterator_pos(spec_a_64.package_spec, a_64_1 + 1),
- a_86_2 = iterator_pos(spec_a_86.package_spec, a_86_1 + 1);*/
-
remove_plan_check(&install_plan[0], "a", Triplet::X64_WINDOWS);
remove_plan_check(&install_plan[1], "a");
features_check(&install_plan[2], "b", {"core"}, Triplet::X64_WINDOWS);
@@ -483,5 +470,24 @@ namespace UnitTest1
features_check(&install_plan[6], "a", {"a1", "core"});
features_check(&install_plan[7], "c", {"core"});
}
+
+ TEST_METHOD(install_all_features_test)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
+
+ PackageSpecMap spec_map(Triplet::X64_WINDOWS);
+ auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "", {{"0", ""}, {"1", ""}}), {"core"}};
+
+ auto install_specs = FullPackageSpec::from_string("a[*]", Triplet::X64_WINDOWS);
+ Assert::IsTrue(install_specs.has_value());
+ if (!install_specs.has_value()) return;
+ auto install_plan = Dependencies::create_feature_install_plan(
+ spec_map.map,
+ FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}),
+ StatusParagraphs(std::move(status_paragraphs)));
+
+ Assert::IsTrue(install_plan.size() == 1);
+ features_check(&install_plan[0], "a", {"0", "1", "core"}, Triplet::X64_WINDOWS);
+ }
};
-} \ No newline at end of file
+}
diff --git a/toolsrc/src/tests.packagespec.cpp b/toolsrc/src/tests.packagespec.cpp
index cb5c41af0..25498a799 100644
--- a/toolsrc/src/tests.packagespec.cpp
+++ b/toolsrc/src/tests.packagespec.cpp
@@ -3,6 +3,7 @@
#include <vcpkg/paragraphs.h>
#include <vcpkg/base/strings.h>
+#include <vcpkg/base/util.h>
#pragma comment(lib, "version")
#pragma comment(lib, "winhttp")
@@ -103,6 +104,39 @@ namespace UnitTest1
Assert::AreEqual("", spec->triplet.c_str());
}
+ TEST_METHOD(parsed_specifier_wildcard_feature)
+ {
+ auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[*]");
+ Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error());
+ auto spec = maybe_spec.get();
+ Assert::AreEqual("zlib", spec->name.c_str());
+ Assert::IsTrue(spec->features.size() == 1);
+ Assert::AreEqual("*", spec->features[0].c_str());
+ Assert::AreEqual("", spec->triplet.c_str());
+ }
+
+ TEST_METHOD(expand_wildcards)
+ {
+ auto zlib =
+ vcpkg::FullPackageSpec::from_string("zlib[0,1]", Triplet::X86_UWP).value_or_exit(VCPKG_LINE_INFO);
+ auto openssl =
+ vcpkg::FullPackageSpec::from_string("openssl[*]", Triplet::X86_UWP).value_or_exit(VCPKG_LINE_INFO);
+ auto specs = FullPackageSpec::to_feature_specs({zlib, openssl});
+ Util::sort(specs);
+ auto spectargets = FeatureSpec::from_strings_and_triplet(
+ {
+ "openssl",
+ "zlib",
+ "openssl[*]",
+ "zlib[0]",
+ "zlib[1]",
+ },
+ Triplet::X86_UWP);
+ Util::sort(spectargets);
+ Assert::IsTrue(specs.size() == spectargets.size());
+ Assert::IsTrue(Util::all_equal(specs, spectargets));
+ }
+
TEST_METHOD(utf8_to_utf16)
{
auto str = vcpkg::Strings::to_utf16("abc");
diff --git a/toolsrc/src/tests.paragraph.cpp b/toolsrc/src/tests.paragraph.cpp
index d9301abd0..13052610f 100644
--- a/toolsrc/src/tests.paragraph.cpp
+++ b/toolsrc/src/tests.paragraph.cpp
@@ -190,6 +190,20 @@ namespace UnitTest1
Assert::AreEqual("c", pgh.depends[2].c_str());
}
+ TEST_METHOD(BinaryParagraph_Abi)
+ {
+ vcpkg::BinaryParagraph pgh({
+ {"Package", "zlib"},
+ {"Version", "1.2.8"},
+ {"Architecture", "x86-windows"},
+ {"Multi-Arch", "same"},
+ {"Abi", "abcd123"},
+ });
+
+ Assert::AreEqual(size_t(0), pgh.depends.size());
+ Assert::IsTrue(pgh.abi == "abcd123");
+ }
+
TEST_METHOD(parse_paragraphs_empty)
{
const char* str = "";
@@ -385,5 +399,21 @@ namespace UnitTest1
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str());
}
+
+ TEST_METHOD(BinaryParagraph_serialize_abi)
+ {
+ vcpkg::BinaryParagraph pgh({
+ {"Package", "zlib"},
+ {"Version", "1.2.8"},
+ {"Architecture", "x86-windows"},
+ {"Multi-Arch", "same"},
+ {"Depends", "a, b, c"},
+ {"Abi", "123abc"},
+ });
+ std::string ss = Strings::serialize(pgh);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO);
+ Assert::AreEqual(size_t(1), pghs.size());
+ Assert::AreEqual("123abc", pghs[0]["Abi"].c_str());
+ }
};
}
diff --git a/toolsrc/src/tests.statusparagraphs.cpp b/toolsrc/src/tests.statusparagraphs.cpp
new file mode 100644
index 000000000..4cc1130b1
--- /dev/null
+++ b/toolsrc/src/tests.statusparagraphs.cpp
@@ -0,0 +1,85 @@
+#include <CppUnitTest.h>
+
+#include <vcpkg/base/util.h>
+#include <vcpkg/paragraphs.h>
+#include <vcpkg/statusparagraph.h>
+#include <vcpkg/statusparagraphs.h>
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+
+using namespace vcpkg;
+using namespace vcpkg::Paragraphs;
+
+namespace UnitTest1
+{
+ class StatusParagraphsTests : public TestClass<StatusParagraphsTests>
+ {
+ TEST_METHOD(find_installed)
+ {
+ auto pghs = parse_paragraphs(R"(
+Package: ffmpeg
+Version: 3.3.3
+Architecture: x64-windows
+Multi-Arch: same
+Description:
+Status: install ok installed
+)");
+ Assert::IsTrue(!!pghs);
+ if (!pghs) return;
+
+ StatusParagraphs status_db(Util::fmap(
+ *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); }));
+
+ auto it = status_db.find_installed("ffmpeg", Triplet::X64_WINDOWS);
+ Assert::IsTrue(it != status_db.end());
+ }
+
+ TEST_METHOD(find_not_installed)
+ {
+ auto pghs = parse_paragraphs(R"(
+Package: ffmpeg
+Version: 3.3.3
+Architecture: x64-windows
+Multi-Arch: same
+Description:
+Status: purge ok not-installed
+)");
+ Assert::IsTrue(!!pghs);
+ if (!pghs) return;
+
+ StatusParagraphs status_db(Util::fmap(
+ *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); }));
+
+ auto it = status_db.find_installed("ffmpeg", Triplet::X64_WINDOWS);
+ Assert::IsTrue(it == status_db.end());
+ }
+
+ TEST_METHOD(find_with_feature_packages)
+ {
+ auto pghs = parse_paragraphs(R"(
+Package: ffmpeg
+Version: 3.3.3
+Architecture: x64-windows
+Multi-Arch: same
+Description:
+Status: install ok installed
+
+Package: ffmpeg
+Feature: openssl
+Depends: openssl
+Architecture: x64-windows
+Multi-Arch: same
+Description:
+Status: purge ok not-installed
+)");
+ Assert::IsTrue(!!pghs);
+ if (!pghs) return;
+
+ StatusParagraphs status_db(Util::fmap(
+ *pghs.get(), [](RawParagraph& rpgh) { return std::make_unique<StatusParagraph>(std::move(rpgh)); }));
+
+ auto it = status_db.find_installed("ffmpeg", Triplet::X64_WINDOWS);
+ Assert::IsTrue(it != status_db.end());
+ }
+ };
+} \ No newline at end of file
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp
index f1a86ae22..2a73c5b0f 100644
--- a/toolsrc/src/vcpkg.cpp
+++ b/toolsrc/src/vcpkg.cpp
@@ -1,6 +1,15 @@
+#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
+#pragma warning(push)
+#pragma warning(disable : 4768)
+#include <Shlobj.h>
+#pragma warning(pop)
+#else
+#include <unistd.h>
+#endif
+
#include <vcpkg/base/chrono.h>
#include <vcpkg/base/files.h>
#include <vcpkg/base/strings.h>
@@ -13,10 +22,6 @@
#include <vcpkg/paragraphs.h>
#include <vcpkg/vcpkglib.h>
-#pragma warning(push)
-#pragma warning(disable : 4768)
-#include <Shlobj.h>
-#pragma warning(pop)
#include <cassert>
#include <fstream>
#include <memory>
@@ -44,7 +49,7 @@ static void inner(const VcpkgCmdArguments& args)
static const auto find_command = [&](auto&& commands) {
auto it = Util::find_if(commands, [&](auto&& commandc) {
- return Strings::case_insensitive_ascii_compare(commandc.name, args.command);
+ return Strings::case_insensitive_ascii_equals(commandc.name, args.command);
});
using std::end;
if (it != end(commands))
@@ -67,7 +72,7 @@ static void inner(const VcpkgCmdArguments& args)
}
else
{
- const Optional<std::wstring> vcpkg_root_dir_env = System::get_environment_variable(L"VCPKG_ROOT");
+ const auto vcpkg_root_dir_env = System::get_environment_variable("VCPKG_ROOT");
if (const auto v = vcpkg_root_dir_env.get())
{
vcpkg_root_dir = fs::stdfs::absolute(*v);
@@ -95,9 +100,17 @@ static void inner(const VcpkgCmdArguments& args)
expected_paths.error().message());
const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO);
+#if defined(_WIN32)
const int exit_code = _wchdir(paths.root.c_str());
+#else
+ const int exit_code = chdir(paths.root.c_str());
+#endif
Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed");
- Commands::Version::warn_if_vcpkg_version_mismatch(paths);
+
+ if (args.command != "autocomplete")
+ {
+ Commands::Version::warn_if_vcpkg_version_mismatch(paths);
+ }
if (const auto command_function = find_command(Commands::get_available_commands_type_b()))
{
@@ -111,11 +124,10 @@ static void inner(const VcpkgCmdArguments& args)
}
else
{
- const Optional<std::wstring> vcpkg_default_triplet_env =
- System::get_environment_variable(L"VCPKG_DEFAULT_TRIPLET");
+ const auto vcpkg_default_triplet_env = System::get_environment_variable("VCPKG_DEFAULT_TRIPLET");
if (const auto v = vcpkg_default_triplet_env.get())
{
- default_triplet = Triplet::from_canonical_name(Strings::to_utf8(*v));
+ default_triplet = Triplet::from_canonical_name(*v);
}
else
{
@@ -135,6 +147,7 @@ static void inner(const VcpkgCmdArguments& args)
static void load_config()
{
+#if defined(_WIN32)
fs::path localappdata;
{
// Config path in AppDataLocal
@@ -194,6 +207,7 @@ static void load_config()
catch (...)
{
}
+#endif
}
static std::string trim_path_from_command_line(const std::string& full_command_line)
@@ -217,24 +231,32 @@ static std::string trim_path_from_command_line(const std::string& full_command_l
return std::string(it, full_command_line.cend());
}
+#if defined(_WIN32)
int wmain(const int argc, const wchar_t* const* const argv)
+#else
+int main(const int argc, const char* const* const argv)
+#endif
{
if (argc == 0) std::abort();
+ *GlobalState::timer.lock() = Chrono::ElapsedTime::create_started();
+
+#if defined(_WIN32)
GlobalState::g_init_console_cp = GetConsoleCP();
GlobalState::g_init_console_output_cp = GetConsoleOutputCP();
- SetConsoleCP(65001);
- SetConsoleOutputCP(65001);
-
- *GlobalState::timer.lock() = Chrono::ElapsedTime::create_started();
+ SetConsoleCP(CP_UTF8);
+ SetConsoleOutputCP(CP_UTF8);
const std::string trimmed_command_line = trim_path_from_command_line(Strings::to_utf8(GetCommandLineW()));
+#endif
{
auto locked_metrics = Metrics::g_metrics.lock();
locked_metrics->track_property("version", Commands::Version::version());
+#if defined(_WIN32)
locked_metrics->track_property("cmdline", trimmed_command_line);
+#endif
}
load_config();
Metrics::g_metrics.lock()->track_property("sqmuser", Metrics::get_SQM_user());
@@ -283,6 +305,12 @@ int wmain(const int argc, const wchar_t* const* const argv)
exc_msg);
fflush(stdout);
for (int x = 0; x < argc; ++x)
+ {
+#if defined(_WIN32)
System::println("%s|", Strings::to_utf8(argv[x]));
+#else
+ System::println("%s|", argv[x]);
+#endif
+ }
fflush(stdout);
}
diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp
index 73c7b9b1a..ed28d6e2b 100644
--- a/toolsrc/src/vcpkg/base/checks.cpp
+++ b/toolsrc/src/vcpkg/base/checks.cpp
@@ -17,14 +17,21 @@ namespace vcpkg::Checks
GlobalState::debugging = false;
metrics->flush();
+#if defined(_WIN32)
SetConsoleCP(GlobalState::g_init_console_cp);
SetConsoleOutputCP(GlobalState::g_init_console_output_cp);
+#endif
fflush(nullptr);
+#if defined(_WIN32)
::TerminateProcess(::GetCurrentProcess(), exit_code);
+#else
+ ::exit(exit_code);
+#endif
}
+#if defined(_WIN32)
static BOOL ctrl_handler(DWORD fdw_ctrl_type)
{
{
@@ -39,6 +46,9 @@ namespace vcpkg::Checks
{
SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(ctrl_handler), TRUE);
}
+#else
+ void register_console_ctrl_handler() {}
+#endif
[[noreturn]] void unreachable(const LineInfo& line_info)
{
@@ -67,7 +77,7 @@ namespace vcpkg::Checks
{
if (!expression)
{
- exit_with_message(line_info, Strings::EMPTY);
+ exit_with_message(line_info, "");
}
}
diff --git a/toolsrc/src/vcpkg/base/cofffilereader.cpp b/toolsrc/src/vcpkg/base/cofffilereader.cpp
index 5e9c86998..1927e0b5e 100644
--- a/toolsrc/src/vcpkg/base/cofffilereader.cpp
+++ b/toolsrc/src/vcpkg/base/cofffilereader.cpp
@@ -7,6 +7,7 @@ using namespace std;
namespace vcpkg::CoffFileReader
{
+#if defined(_WIN32)
template<class T>
static T reinterpret_bytes(const char* data)
{
@@ -24,7 +25,7 @@ namespace vcpkg::CoffFileReader
template<class T>
static T peek_value_from_stream(fstream& fs)
{
- const fpos_t original_pos = fs.tellg().seekpos();
+ const std::streampos original_pos = fs.tellg();
T data;
fs.read(reinterpret_cast<char*>(&data), sizeof data);
fs.seekg(original_pos);
@@ -305,4 +306,8 @@ namespace vcpkg::CoffFileReader
return {std::vector<MachineType>(machine_types.cbegin(), machine_types.cend())};
}
+#else
+ DllInfo read_dll(const fs::path& path) { exit(-1); }
+ LibInfo read_lib(const fs::path& path) { exit(-1); }
+#endif
}
diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp
index f8b239eaa..6e43debb1 100644
--- a/toolsrc/src/vcpkg/base/files.cpp
+++ b/toolsrc/src/vcpkg/base/files.cpp
@@ -163,7 +163,12 @@ namespace vcpkg::Files
virtual void write_contents(const fs::path& file_path, const std::string& data) override
{
FILE* f = nullptr;
+#if defined(_WIN32)
auto ec = _wfopen_s(&f, file_path.native().c_str(), L"wb");
+#else
+ f = fopen(file_path.native().c_str(), "wb");
+ int ec = f != nullptr ? 0 : 1;
+#endif
Checks::check_exit(
VCPKG_LINE_INFO, ec == 0, "Error: Could not open file for writing: %s", file_path.u8string().c_str());
auto count = fwrite(data.data(), sizeof(data[0]), data.size(), f);
@@ -194,9 +199,13 @@ namespace vcpkg::Files
System::println();
}
- std::vector<fs::path> find_from_PATH(const std::wstring& name)
+ std::vector<fs::path> find_from_PATH(const std::string& name)
{
- const std::wstring cmd = Strings::wformat(L"where.exe %s", name);
+#if defined(_WIN32)
+ const std::string cmd = Strings::format("where.exe %s", name);
+#else
+ const std::string cmd = Strings::format("which %s", name);
+#endif
auto out = System::cmd_execute_and_capture_output(cmd);
if (out.exit_code != 0)
{
diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp
index 2a6d3dff2..27cfcbe71 100644
--- a/toolsrc/src/vcpkg/base/strings.cpp
+++ b/toolsrc/src/vcpkg/base/strings.cpp
@@ -37,31 +37,8 @@ namespace vcpkg::Strings::details
#if defined(_WIN32)
_vsnprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args);
#else
- vsnprintf(&output.at(0), output.size() + 1, fmtstr, args);
-#endif
- va_end(args);
-
- return output;
- }
-
- std::wstring wformat_internal(const wchar_t* fmtstr, ...)
- {
- va_list args;
va_start(args, fmtstr);
-
-#if defined(_WIN32)
- const int sz = _vscwprintf_l(fmtstr, c_locale(), args);
-#else
- const int sz = vswprintf(nullptr, 0, fmtstr, args);
-#endif
- Checks::check_exit(VCPKG_LINE_INFO, sz > 0);
-
- std::wstring output(sz, L'\0');
-
-#if defined(_WIN32)
- _vsnwprintf_s_l(&output.at(0), output.size() + 1, output.size(), fmtstr, c_locale(), args);
-#else
- vswprintf(&output.at(0), output.size() + 1, fmtstr, args);
+ auto res = vsnprintf(&output.at(0), output.size() + 1, fmtstr, args);
#endif
va_end(args);
@@ -71,22 +48,30 @@ namespace vcpkg::Strings::details
namespace vcpkg::Strings
{
- std::wstring to_utf16(const CStringView s)
+ std::wstring to_utf16(const CStringView& s)
{
+#if defined(_WIN32)
const int size = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, nullptr, 0);
std::wstring output;
output.resize(size - 1);
MultiByteToWideChar(CP_UTF8, 0, s.c_str(), -1, output.data(), size - 1);
return output;
+#else
+ Checks::unreachable(VCPKG_LINE_INFO);
+#endif
}
- std::string to_utf8(const CWStringView w)
+ std::string to_utf8(const CWStringView& w)
{
+#if defined(_WIN32)
const int size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr);
std::string output;
output.resize(size - 1);
WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, output.data(), size - 1, nullptr, nullptr);
return output;
+#else
+ Checks::unreachable(VCPKG_LINE_INFO);
+#endif
}
std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern)
@@ -104,9 +89,13 @@ namespace vcpkg::Strings
return case_insensitive_ascii_find(s, pattern) != s.end();
}
- bool case_insensitive_ascii_compare(const CStringView left, const CStringView right)
+ bool case_insensitive_ascii_equals(const CStringView left, const CStringView right)
{
+#if defined(_WIN32)
return _stricmp(left.c_str(), right.c_str()) == 0;
+#else
+ return strcasecmp(left.c_str(), right.c_str()) == 0;
+#endif
}
std::string ascii_to_lowercase(const std::string& input)
@@ -118,27 +107,36 @@ namespace vcpkg::Strings
bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern)
{
+#if defined(_WIN32)
return _strnicmp(s.c_str(), pattern.c_str(), pattern.size()) == 0;
+#else
+ return strncasecmp(s.c_str(), pattern.c_str(), pattern.size()) == 0;
+#endif
}
- void trim(std::string* s)
+ std::string replace_all(std::string&& s, const std::string& search, const std::string& rep)
{
- s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end());
- s->erase(s->begin(), std::find_if_not(s->begin(), s->end(), details::isspace));
+ size_t pos = 0;
+ while ((pos = s.find(search, pos)) != std::string::npos)
+ {
+ s.replace(pos, search.size(), rep);
+ pos += rep.size();
+ }
+ return std::move(s);
}
- std::string trimmed(const std::string& s)
+ std::string trim(std::string&& s)
{
- auto whitespace_back = std::find_if_not(s.rbegin(), s.rend(), details::isspace).base();
- auto whitespace_front = std::find_if_not(s.begin(), whitespace_back, details::isspace);
- return std::string(whitespace_front, whitespace_back);
+ s.erase(std::find_if_not(s.rbegin(), s.rend(), details::isspace).base(), s.end());
+ s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), details::isspace));
+ return std::move(s);
}
void trim_all_and_remove_whitespace_strings(std::vector<std::string>* strings)
{
for (std::string& s : *strings)
{
- trim(&s);
+ s = trim(std::move(s));
}
Util::erase_remove_if(*strings, [](const std::string& s) { return s.empty(); });
diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp
index d5d39461c..47096ed63 100644
--- a/toolsrc/src/vcpkg/base/system.cpp
+++ b/toolsrc/src/vcpkg/base/system.cpp
@@ -3,6 +3,9 @@
#include <vcpkg/base/checks.h>
#include <vcpkg/base/system.h>
#include <vcpkg/globalstate.h>
+#include <vcpkg/metrics.h>
+
+#include <time.h>
#pragma comment(lib, "Advapi32")
@@ -13,35 +16,46 @@ namespace vcpkg::System
using std::chrono::system_clock;
std::time_t now_time = system_clock::to_time_t(system_clock::now());
tm parts;
+#if defined(_WIN32)
localtime_s(&parts, &now_time);
+#else
+ parts = *localtime(&now_time);
+#endif
return parts;
}
fs::path get_exe_path_of_current_process()
{
+#if defined(_WIN32)
wchar_t buf[_MAX_PATH];
const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH);
if (bytes == 0) std::abort();
return fs::path(buf, buf + bytes);
+#else
+ std::array<char, 1024 * 4> buf;
+ auto written = readlink("/proc/self/exe", buf.data(), buf.size());
+ Checks::check_exit(VCPKG_LINE_INFO, written != -1, "Could not determine current executable path.");
+ return fs::path(buf.data(), buf.data() + written);
+#endif
}
- Optional<CPUArchitecture> to_cpu_architecture(CStringView arch)
+ Optional<CPUArchitecture> to_cpu_architecture(const CStringView& arch)
{
- if (Strings::case_insensitive_ascii_compare(arch, "x86")) return CPUArchitecture::X86;
- if (Strings::case_insensitive_ascii_compare(arch, "x64")) return CPUArchitecture::X64;
- if (Strings::case_insensitive_ascii_compare(arch, "amd64")) return CPUArchitecture::X64;
- if (Strings::case_insensitive_ascii_compare(arch, "arm")) return CPUArchitecture::ARM;
- if (Strings::case_insensitive_ascii_compare(arch, "arm64")) return CPUArchitecture::ARM64;
+ if (Strings::case_insensitive_ascii_equals(arch, "x86")) return CPUArchitecture::X86;
+ if (Strings::case_insensitive_ascii_equals(arch, "x64")) return CPUArchitecture::X64;
+ if (Strings::case_insensitive_ascii_equals(arch, "amd64")) return CPUArchitecture::X64;
+ if (Strings::case_insensitive_ascii_equals(arch, "arm")) return CPUArchitecture::ARM;
+ if (Strings::case_insensitive_ascii_equals(arch, "arm64")) return CPUArchitecture::ARM64;
return nullopt;
}
CPUArchitecture get_host_processor()
{
- auto w6432 = get_environment_variable(L"PROCESSOR_ARCHITEW6432");
- if (const auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO);
+ 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(L"PROCESSOR_ARCHITECTURE").value_or_exit(VCPKG_LINE_INFO);
- return to_cpu_architecture(Strings::to_utf8(procarch)).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);
}
std::vector<CPUArchitecture> get_supported_host_architectures()
@@ -58,12 +72,13 @@ namespace vcpkg::System
return supported_architectures;
}
- int cmd_execute_clean(const CWStringView cmd_line)
+ int cmd_execute_clean(const CStringView cmd_line)
{
- static const std::wstring SYSTEM_ROOT = get_environment_variable(L"SystemRoot").value_or_exit(VCPKG_LINE_INFO);
- static const std::wstring SYSTEM_32 = SYSTEM_ROOT + LR"(\system32)";
- static const std::wstring NEW_PATH = Strings::wformat(
- LR"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32);
+#if defined(_WIN32)
+ static const std::string SYSTEM_ROOT = get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO);
+ static const std::string SYSTEM_32 = SYSTEM_ROOT + R"(\system32)";
+ static const std::string NEW_PATH = Strings::format(
+ R"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32);
std::vector<std::wstring> env_wstrings = {
L"ALLUSERSPROFILE",
@@ -118,17 +133,17 @@ namespace vcpkg::System
for (auto&& env_wstring : env_wstrings)
{
- const Optional<std::wstring> value = System::get_environment_variable(env_wstring);
+ const Optional<std::string> value = System::get_environment_variable(Strings::to_utf8(env_wstring));
const auto v = value.get();
if (!v || v->empty()) continue;
env_cstr.append(env_wstring);
env_cstr.push_back(L'=');
- env_cstr.append(*v);
+ env_cstr.append(Strings::to_utf16(*v));
env_cstr.push_back(L'\0');
}
- env_cstr.append(NEW_PATH);
+ env_cstr.append(Strings::to_utf16(NEW_PATH));
env_cstr.push_back(L'\0');
STARTUPINFOW startup_info;
@@ -139,10 +154,10 @@ namespace vcpkg::System
memset(&process_info, 0, sizeof(PROCESS_INFORMATION));
// Basically we are wrapping it in quotes
- std::wstring actual_cmd_line = Strings::wformat(LR"###(cmd.exe /c "%s")###", cmd_line);
- Debug::println("CreateProcessW(%s)", Strings::to_utf8(actual_cmd_line));
+ const std::string actual_cmd_line = Strings::format(R"###(cmd.exe /c "%s")###", cmd_line);
+ Debug::println("CreateProcessW(%s)", actual_cmd_line);
bool succeeded = TRUE == CreateProcessW(nullptr,
- actual_cmd_line.data(),
+ Strings::to_utf16(actual_cmd_line).data(),
nullptr,
nullptr,
FALSE,
@@ -164,18 +179,28 @@ namespace vcpkg::System
Debug::println("CreateProcessW() returned %lu", exit_code);
return static_cast<int>(exit_code);
+#else
+ fflush(nullptr);
+ return system(cmd_line.c_str());
+#endif
}
- int cmd_execute(const CWStringView cmd_line)
+ int cmd_execute(const CStringView cmd_line)
{
// Flush stdout before launching external process
fflush(nullptr);
// Basically we are wrapping it in quotes
- const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line);
- Debug::println("_wsystem(%s)", Strings::to_utf8(actual_cmd_line));
- const int exit_code = _wsystem(actual_cmd_line.c_str());
+ const std::string& actual_cmd_line = Strings::format(R"###("%s")###", cmd_line);
+#if defined(_WIN32)
+ Debug::println("_wsystem(%s)", actual_cmd_line);
+ const int exit_code = _wsystem(Strings::to_utf16(actual_cmd_line).c_str());
Debug::println("_wsystem() returned %d", exit_code);
+#else
+ Debug::println("_system(%s)", actual_cmd_line);
+ const int exit_code = system(actual_cmd_line.c_str());
+ Debug::println("_system() returned %d", exit_code);
+#endif
return exit_code;
}
@@ -190,17 +215,18 @@ namespace vcpkg::System
}
}
- ExitCodeAndOutput cmd_execute_and_capture_output(const CWStringView cmd_line)
+ ExitCodeAndOutput cmd_execute_and_capture_output(const CStringView cmd_line)
{
// Flush stdout before launching external process
fflush(stdout);
- const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s 2>&1")###", cmd_line);
+#if defined(_WIN32)
+ const auto actual_cmd_line = Strings::format(R"###("%s 2>&1")###", cmd_line);
- Debug::println("_wpopen(%s)", Strings::to_utf8(actual_cmd_line));
+ Debug::println("_wpopen(%s)", actual_cmd_line);
std::wstring output;
wchar_t buf[1024];
- const auto pipe = _wpopen(actual_cmd_line.c_str(), L"r");
+ const auto pipe = _wpopen(Strings::to_utf16(actual_cmd_line).c_str(), L"r");
if (pipe == nullptr)
{
return {1, Strings::to_utf8(output)};
@@ -218,27 +244,87 @@ namespace vcpkg::System
Debug::println("_pclose() returned %d", ec);
remove_byte_order_marks(&output);
return {ec, Strings::to_utf8(output)};
+#else
+ const auto actual_cmd_line = Strings::format(R"###(%s 2>&1)###", cmd_line);
+
+ Debug::println("popen(%s)", actual_cmd_line);
+ std::string output;
+ char buf[1024];
+ const auto pipe = popen(actual_cmd_line.c_str(), "r");
+ if (pipe == nullptr)
+ {
+ return {1, output};
+ }
+ while (fgets(buf, 1024, pipe))
+ {
+ output.append(buf);
+ }
+ if (!feof(pipe))
+ {
+ return {1, output};
+ }
+
+ const auto ec = pclose(pipe);
+ Debug::println("pclose() returned %d", ec);
+ return {ec, output};
+#endif
}
- std::wstring create_powershell_script_cmd(const fs::path& script_path, const CWStringView args)
+ std::string powershell_execute_and_capture_output(const std::string& title,
+ const fs::path& script_path,
+ const CStringView args)
{
// TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned
- return Strings::wformat(
- LR"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.native(), args);
+ const std::string cmd = Strings::format(
+ R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args);
+
+ auto rc = System::cmd_execute_and_capture_output(cmd);
+
+ if (rc.exit_code)
+ {
+ System::println(Color::error,
+ "%s\n"
+ "Could not run:\n"
+ " '%s'\n"
+ "Error message was:\n"
+ " %s",
+ title,
+ script_path.generic_string(),
+ rc.output);
+
+ {
+ 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.exit_code);
+ }
+
+ // Remove newline from all output.
+ // Powershell returns newlines when it hits the column count of the console.
+ // For example, this is 80 in cmd on Windows 7. If the expected output is longer than 80 lines, we get
+ // newlines in-between the data.
+ // To solve this, we design our interaction with powershell to not depend on newlines,
+ // and then strip all newlines here.
+ rc.output = Strings::replace_all(std::move(rc.output), "\n", "");
+
+ return rc.output;
}
- void println() { println(Strings::EMPTY); }
+ void println() { putchar('\n'); }
void print(const CStringView message) { fputs(message.c_str(), stdout); }
void println(const CStringView message)
{
print(message);
- putchar('\n');
+ println();
}
void print(const Color c, const CStringView message)
{
+#if defined(_WIN32)
const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info{};
@@ -248,67 +334,90 @@ namespace vcpkg::System
SetConsoleTextAttribute(console_handle, static_cast<WORD>(c) | (original_color & 0xF0));
print(message);
SetConsoleTextAttribute(console_handle, original_color);
+#else
+ print(message);
+#endif
}
void println(const Color c, const CStringView message)
{
print(c, message);
- putchar('\n');
+ println();
}
- Optional<std::wstring> get_environment_variable(const CWStringView varname) noexcept
+ Optional<std::string> get_environment_variable(const CStringView varname) noexcept
{
- const auto sz = GetEnvironmentVariableW(varname.c_str(), nullptr, 0);
+#if defined(_WIN32)
+ const auto w_varname = Strings::to_utf16(varname);
+ const auto sz = GetEnvironmentVariableW(w_varname.c_str(), nullptr, 0);
if (sz == 0) return nullopt;
std::wstring ret(sz, L'\0');
Checks::check_exit(VCPKG_LINE_INFO, MAXDWORD >= ret.size());
- const auto sz2 = GetEnvironmentVariableW(varname.c_str(), ret.data(), static_cast<DWORD>(ret.size()));
+ const auto sz2 = GetEnvironmentVariableW(w_varname.c_str(), ret.data(), static_cast<DWORD>(ret.size()));
Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz);
ret.pop_back();
- return ret;
+ return Strings::to_utf8(ret);
+#else
+ auto v = getenv(varname.c_str());
+ if (!v) return nullopt;
+ return std::string(v);
+#endif
}
- static bool is_string_keytype(DWORD hkey_type)
+#if defined(_WIN32)
+ static bool is_string_keytype(const DWORD hkey_type)
{
return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ;
}
- Optional<std::wstring> get_registry_string(HKEY base, const CWStringView sub_key, const CWStringView valuename)
+ Optional<std::string> get_registry_string(void* base_hkey, const CStringView sub_key, const CStringView valuename)
{
HKEY k = nullptr;
- const LSTATUS ec = RegOpenKeyExW(base, sub_key.c_str(), NULL, KEY_READ, &k);
+ const LSTATUS ec =
+ RegOpenKeyExW(reinterpret_cast<HKEY>(base_hkey), Strings::to_utf16(sub_key).c_str(), NULL, KEY_READ, &k);
if (ec != ERROR_SUCCESS) return nullopt;
DWORD dw_buffer_size = 0;
DWORD dw_type = 0;
- auto rc = RegQueryValueExW(k, valuename.c_str(), nullptr, &dw_type, nullptr, &dw_buffer_size);
+ auto rc =
+ RegQueryValueExW(k, Strings::to_utf16(valuename).c_str(), nullptr, &dw_type, nullptr, &dw_buffer_size);
if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size == 0 ||
dw_buffer_size % sizeof(wchar_t) != 0)
return nullopt;
std::wstring ret;
ret.resize(dw_buffer_size / sizeof(wchar_t));
- rc = RegQueryValueExW(
- k, valuename.c_str(), nullptr, &dw_type, reinterpret_cast<LPBYTE>(ret.data()), &dw_buffer_size);
+ rc = RegQueryValueExW(k,
+ Strings::to_utf16(valuename).c_str(),
+ nullptr,
+ &dw_type,
+ reinterpret_cast<LPBYTE>(ret.data()),
+ &dw_buffer_size);
if (rc != ERROR_SUCCESS || !is_string_keytype(dw_type) || dw_buffer_size != sizeof(wchar_t) * ret.size())
return nullopt;
ret.pop_back(); // remove extra trailing null byte
- return ret;
+ return Strings::to_utf8(ret);
+ }
+#else
+ Optional<std::string> get_registry_string(void* base_hkey, const CStringView sub_key, const CStringView valuename)
+ {
+ return nullopt;
}
+#endif
static const fs::path& get_program_files()
{
- static const fs::path PATH = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO);
+ static const fs::path PATH = System::get_environment_variable("PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO);
return PATH;
}
const fs::path& get_program_files_32_bit()
{
static const fs::path PATH = []() -> fs::path {
- auto value = System::get_environment_variable(L"ProgramFiles(x86)");
+ auto value = System::get_environment_variable("ProgramFiles(x86)");
if (auto v = value.get())
{
return std::move(*v);
@@ -321,7 +430,7 @@ namespace vcpkg::System
const fs::path& get_program_files_platform_bitness()
{
static const fs::path PATH = []() -> fs::path {
- auto value = System::get_environment_variable(L"ProgramW6432");
+ auto value = System::get_environment_variable("ProgramW6432");
if (auto v = value.get())
{
return std::move(*v);
diff --git a/toolsrc/src/vcpkg/binaryparagraph.cpp b/toolsrc/src/vcpkg/binaryparagraph.cpp
index ef943011f..c7136b713 100644
--- a/toolsrc/src/vcpkg/binaryparagraph.cpp
+++ b/toolsrc/src/vcpkg/binaryparagraph.cpp
@@ -16,6 +16,7 @@ namespace vcpkg
namespace Fields
{
+ static const std::string ABI = "Abi";
static const std::string FEATURE = "Feature";
static const std::string DESCRIPTION = "Description";
static const std::string MAINTAINER = "Maintainer";
@@ -47,6 +48,8 @@ namespace vcpkg
this->description = parser.optional_field(Fields::DESCRIPTION);
this->maintainer = parser.optional_field(Fields::MAINTAINER);
+ this->abi = parser.optional_field(Fields::ABI);
+
std::string multi_arch;
parser.required_field(Fields::MULTI_ARCH, multi_arch);
@@ -80,10 +83,10 @@ namespace vcpkg
BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const FeatureParagraph& fpgh, const Triplet& triplet)
{
this->spec = PackageSpec::from_name_and_triplet(spgh.name, triplet).value_or_exit(VCPKG_LINE_INFO);
- this->version = Strings::EMPTY;
+ this->version = "";
this->feature = fpgh.name;
this->description = fpgh.description;
- this->maintainer = Strings::EMPTY;
+ this->maintainer = "";
this->depends = filter_dependencies(fpgh.depends, triplet);
}
@@ -118,6 +121,7 @@ namespace vcpkg
out_str.append("Multi-Arch: same\n");
if (!pgh.maintainer.empty()) out_str.append("Maintainer: ").append(pgh.maintainer).push_back('\n');
+ if (!pgh.abi.empty()) out_str.append("Abi: ").append(pgh.abi).push_back('\n');
if (!pgh.description.empty()) out_str.append("Description: ").append(pgh.description).push_back('\n');
}
}
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
index 99ec541c1..ca0712a06 100644
--- a/toolsrc/src/vcpkg/build.cpp
+++ b/toolsrc/src/vcpkg/build.cpp
@@ -28,13 +28,13 @@ namespace vcpkg::Build::Command
static const std::string OPTION_CHECKS_ONLY = "--checks-only";
- void perform_and_exit(const FullPackageSpec& full_spec,
- const fs::path& port_dir,
- const std::unordered_set<std::string>& options,
- const VcpkgPaths& paths)
+ void perform_and_exit_ex(const FullPackageSpec& full_spec,
+ const fs::path& port_dir,
+ const ParsedArguments& options,
+ const VcpkgPaths& paths)
{
const PackageSpec& spec = full_spec.package_spec;
- if (options.find(OPTION_CHECKS_ONLY) != options.end())
+ if (Util::Sets::contains(options.switches, OPTION_CHECKS_ONLY))
{
const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet());
const auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec));
@@ -52,24 +52,25 @@ namespace vcpkg::Build::Command
Checks::exit_fail(VCPKG_LINE_INFO);
}
- for (const std::string& str : full_spec.features)
- {
- System::println("%s \n", str);
- }
const auto& scf = source_control_file.value_or_exit(VCPKG_LINE_INFO);
Checks::check_exit(VCPKG_LINE_INFO,
spec.name() == scf->core_paragraph->name,
- "The Name: field inside the CONTROL does not match the port directory: '%s' != '%s'",
+ "The Source field inside the CONTROL file does not match the port directory: '%s' != '%s'",
scf->core_paragraph->name,
spec.name());
const StatusParagraphs status_db = database_load_check(paths);
const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES};
+ const std::unordered_set<std::string> features_as_set(full_spec.features.begin(), full_spec.features.end());
+
const Build::BuildPackageConfig build_config{
- *scf->core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options};
+ *scf, spec.triplet(), fs::path{port_dir}, build_package_options, features_as_set};
+ const auto build_timer = Chrono::ElapsedTime::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());
+
if (result.code == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES)
{
System::println(System::Color::error,
@@ -84,6 +85,8 @@ namespace vcpkg::Build::Command
Checks::exit_fail(VCPKG_LINE_INFO);
}
+ Checks::check_exit(VCPKG_LINE_INFO, result.code != BuildResult::EXCLUDED);
+
if (result.code != BuildResult::SUCCEEDED)
{
System::println(System::Color::error, Build::create_error_message(result.code, spec));
@@ -94,17 +97,32 @@ namespace vcpkg::Build::Command
Checks::exit_success(VCPKG_LINE_INFO);
}
+ static const std::array<CommandSwitch, 1> BUILD_SWITCHES = {{
+ {OPTION_CHECKS_ONLY, "Only run checks, do not rebuild package"},
+ }};
+
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string("build zlib:x64-windows"),
+ 1,
+ 1,
+ {BUILD_SWITCHES, {}},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
- static const std::string EXAMPLE = Help::create_example_string("build zlib:x64-windows");
// Build only takes a single package and all dependencies must already be installed
- args.check_exact_arg_count(1, EXAMPLE);
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
const std::string command_argument = args.command_arguments.at(0);
- const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, EXAMPLE);
+ const FullPackageSpec spec =
+ Input::check_and_get_full_package_spec(command_argument, default_triplet, COMMAND_STRUCTURE.example_text);
Input::check_triplet(spec.package_spec.triplet(), paths);
- const std::unordered_set<std::string> options =
- args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY});
- perform_and_exit(spec, paths.port_dir(spec.package_spec), options, paths);
+ if (!spec.features.empty() && !GlobalState::feature_packages)
+ {
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag.");
+ }
+ perform_and_exit_ex(spec, paths.port_dir(spec.package_spec), options, paths);
}
}
@@ -155,16 +173,16 @@ namespace vcpkg::Build
static const std::string LIBRARY_LINKAGE = "LibraryLinkage";
}
- CWStringView to_vcvarsall_target(const std::string& cmake_system_name)
+ CStringView to_vcvarsall_target(const std::string& cmake_system_name)
{
- if (cmake_system_name == Strings::EMPTY) return Strings::WEMPTY;
- if (cmake_system_name == "Windows") return Strings::WEMPTY;
- if (cmake_system_name == "WindowsStore") return L"store";
+ if (cmake_system_name.empty()) return "";
+ if (cmake_system_name == "Windows") return "";
+ if (cmake_system_name == "WindowsStore") return "store";
Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported vcvarsall target %s", cmake_system_name);
}
- CWStringView to_vcvarsall_toolchain(const std::string& target_architecture, const Toolset& toolset)
+ CStringView to_vcvarsall_toolchain(const std::string& target_architecture, const Toolset& toolset)
{
auto maybe_target_arch = System::to_cpu_architecture(target_architecture);
Checks::check_exit(
@@ -183,23 +201,23 @@ namespace vcpkg::Build
Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported toolchain combination %s", target_architecture);
}
- std::wstring make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset)
+ std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset)
{
- const wchar_t* tonull = L" >nul";
+ const char* tonull = " >nul";
if (GlobalState::debugging)
{
- tonull = Strings::WEMPTY;
+ tonull = "";
}
const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset);
const auto target = to_vcvarsall_target(pre_build_info.cmake_system_name);
- return Strings::wformat(LR"("%s" %s %s %s %s 2>&1)",
- toolset.vcvarsall.native(),
- Strings::join(L" ", toolset.vcvarsall_options),
- arch,
- target,
- tonull);
+ return Strings::format(R"("%s" %s %s %s %s 2>&1)",
+ toolset.vcvarsall.u8string(),
+ Strings::join(" ", toolset.vcvarsall_options),
+ arch,
+ target,
+ tonull);
}
static void create_binary_feature_control_file(const SourceParagraph& source_paragraph,
@@ -265,8 +283,6 @@ namespace vcpkg::Build
const fs::path ports_cmake_script_path = paths.ports_cmake;
const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet);
- const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset, pre_build_info.visual_studio_path);
- const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset);
std::string features;
if (GlobalState::feature_packages)
@@ -284,22 +300,26 @@ namespace vcpkg::Build
}
}
- const std::wstring cmd_launch_cmake = make_cmake_cmd(
+ 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(
cmake_exe_path,
ports_cmake_script_path,
{
- {L"CMD", L"BUILD"},
- {L"PORT", config.src.name},
- {L"CURRENT_PORT_DIR", config.port_dir / "/."},
- {L"TARGET_TRIPLET", triplet.canonical_name()},
- {L"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()},
- {L"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? L"1" : L"0"},
- {L"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? L"1" : L"0"},
- {L"GIT", git_exe_path},
- {L"FEATURES", features},
+ {"CMD", "BUILD"},
+ {"PORT", config.src.name},
+ {"CURRENT_PORT_DIR", config.port_dir / "/."},
+ {"TARGET_TRIPLET", triplet.canonical_name()},
+ {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()},
+ {"VCPKG_USE_HEAD_VERSION", to_bool(config.build_package_options.use_head_version) ? "1" : "0"},
+ {"_VCPKG_NO_DOWNLOADS", !to_bool(config.build_package_options.allow_downloads) ? "1" : "0"},
+ {"GIT", git_exe_path},
+ {"FEATURES", features},
});
- const std::wstring command = Strings::wformat(LR"(%s && %s)", cmd_set_environment, cmd_launch_cmake);
+ std::string command;
+ const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset);
+ command = Strings::format(R"(%s && %s)", cmd_set_environment, cmd_launch_cmake);
const auto timer = Chrono::ElapsedTime::create_started();
@@ -360,6 +380,7 @@ namespace vcpkg::Build
static const std::string FILE_CONFLICTS_STRING = "FILE_CONFLICTS";
static const std::string POST_BUILD_CHECKS_FAILED_STRING = "POST_BUILD_CHECKS_FAILED";
static const std::string CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING = "CASCADED_DUE_TO_MISSING_DEPENDENCIES";
+ static const std::string EXCLUDED_STRING = "EXCLUDED";
switch (build_result)
{
@@ -367,8 +388,9 @@ namespace vcpkg::Build
case BuildResult::SUCCEEDED: return SUCCEEDED_STRING;
case BuildResult::BUILD_FAILED: return BUILD_FAILED_STRING;
case BuildResult::POST_BUILD_CHECKS_FAILED: return POST_BUILD_CHECKS_FAILED_STRING;
- case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING;
case BuildResult::FILE_CONFLICTS: return FILE_CONFLICTS_STRING;
+ case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING;
+ case BuildResult::EXCLUDED: return EXCLUDED_STRING;
default: Checks::unreachable(VCPKG_LINE_INFO);
}
}
@@ -461,15 +483,13 @@ 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 std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe_path,
- ports_cmake_script_path,
- {
- {L"CMAKE_TRIPLET_FILE", triplet_file_path},
- });
-
- const std::wstring command = Strings::wformat(LR"(%s)", cmd_launch_cmake);
- const auto ec_data = System::cmd_execute_and_capture_output(command);
- Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0);
+ const auto cmd_launch_cmake = 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);
const std::vector<std::string> lines = Strings::split(ec_data.output, "\n");
@@ -491,7 +511,7 @@ namespace vcpkg::Build
const bool variable_with_no_value = s.size() == 1;
const std::string variable_name = s.at(0);
- const std::string variable_value = variable_with_no_value ? Strings::EMPTY : s.at(1);
+ const std::string variable_value = variable_with_no_value ? "" : s.at(1);
if (variable_name == "VCPKG_TARGET_ARCHITECTURE")
{
diff --git a/toolsrc/src/vcpkg/commands.autocomplete.cpp b/toolsrc/src/vcpkg/commands.autocomplete.cpp
index 23c2c2f7e..0df7ec5eb 100644
--- a/toolsrc/src/vcpkg/commands.autocomplete.cpp
+++ b/toolsrc/src/vcpkg/commands.autocomplete.cpp
@@ -10,40 +10,6 @@
namespace vcpkg::Commands::Autocomplete
{
- std::vector<std::string> autocomplete_install(
- const std::vector<std::unique_ptr<SourceControlFile>>& source_paragraphs, const std::string& start_with)
- {
- std::vector<std::string> results;
-
- for (const auto& source_control_file : source_paragraphs)
- {
- auto&& sp = *source_control_file->core_paragraph;
-
- if (Strings::case_insensitive_ascii_starts_with(sp.name, start_with))
- {
- results.push_back(sp.name);
- }
- }
- return results;
- }
-
- std::vector<std::string> autocomplete_remove(std::vector<StatusParagraph*> installed_packages,
- const std::string& start_with)
- {
- std::vector<std::string> results;
-
- for (const auto& installed_package : installed_packages)
- {
- const auto sp = installed_package->package.displayname();
-
- if (Strings::case_insensitive_ascii_starts_with(sp, start_with))
- {
- results.push_back(sp);
- }
- }
- return results;
- }
-
[[noreturn]] static void output_sorted_results_and_exit(const LineInfo& line_info,
std::vector<std::string>&& results)
{
@@ -53,6 +19,13 @@ namespace vcpkg::Commands::Autocomplete
Checks::exit_success(line_info);
}
+ std::vector<std::string> combine_port_with_triplets(const std::string& port,
+ const std::vector<std::string>& triplets)
+ {
+ return Util::fmap(triplets,
+ [&](const std::string& triplet) { return Strings::format("%s:%s", port, triplet); });
+ }
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
Metrics::g_metrics.lock()->set_send_metrics(false);
@@ -66,7 +39,8 @@ namespace vcpkg::Commands::Autocomplete
{
const std::string requested_command = match[1].str();
- std::vector<std::string> valid_commands = {
+ // First try public commands
+ std::vector<std::string> public_commands = {
"install",
"search",
"remove",
@@ -84,43 +58,108 @@ namespace vcpkg::Commands::Autocomplete
"contact",
};
- Util::unstable_keep_if(valid_commands, [&](const std::string& s) {
+ Util::unstable_keep_if(public_commands, [&](const std::string& s) {
+ return Strings::case_insensitive_ascii_starts_with(s, requested_command);
+ });
+
+ if (!public_commands.empty())
+ {
+ output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(public_commands));
+ }
+
+ // If no public commands match, try private commands
+ std::vector<std::string> private_commands = {
+ "build",
+ "buildexternal",
+ "ci",
+ "depend-info",
+ "env",
+ "import",
+ "portsdiff",
+ };
+
+ Util::unstable_keep_if(private_commands, [&](const std::string& s) {
return Strings::case_insensitive_ascii_starts_with(s, requested_command);
});
- output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(valid_commands));
+ output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(private_commands));
+ }
+
+ // Handles vcpkg install package:<triplet>
+ if (std::regex_match(to_autocomplete, match, std::regex{R"###(^install(.*|)\s([^:]+):(\S*)$)###"}))
+ {
+ const auto port_name = match[2].str();
+ const auto triplet_prefix = match[3].str();
+
+ auto maybe_port = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(port_name));
+ if (maybe_port.error())
+ {
+ Checks::exit_success(VCPKG_LINE_INFO);
+ }
+
+ std::vector<std::string> triplets = paths.get_available_triplets();
+ Util::unstable_keep_if(triplets, [&](const std::string& s) {
+ return Strings::case_insensitive_ascii_starts_with(s, triplet_prefix);
+ });
+
+ auto result = combine_port_with_triplets(port_name, triplets);
+
+ output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(result));
}
struct CommandEntry
{
+ constexpr CommandEntry(const CStringView& name, const CStringView& regex, const CommandStructure& structure)
+ : name(name), regex(regex), structure(structure)
+ {
+ }
+
+ CStringView name;
CStringView regex;
const CommandStructure& structure;
};
- static constexpr CommandEntry commands[] = {
- {R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE},
- {R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE},
- {R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE},
+
+ static constexpr CommandEntry COMMANDS[] = {
+ CommandEntry{"install", R"###(^install\s(.*\s|)(\S*)$)###", Install::COMMAND_STRUCTURE},
+ CommandEntry{"edit", R"###(^edit\s(.*\s|)(\S*)$)###", Edit::COMMAND_STRUCTURE},
+ CommandEntry{"remove", R"###(^remove\s(.*\s|)(\S*)$)###", Remove::COMMAND_STRUCTURE},
+ CommandEntry{"integrate", R"###(^integrate(\s+)(\S*)$)###", Integrate::COMMAND_STRUCTURE},
};
- for (auto&& command : commands)
+ for (auto&& command : COMMANDS)
{
if (std::regex_match(to_autocomplete, match, std::regex{command.regex.c_str()}))
{
- auto prefix = match[2].str();
- std::vector<std::string> v;
- if (Strings::case_insensitive_ascii_starts_with(prefix, "-"))
+ const auto prefix = match[2].str();
+ std::vector<std::string> results;
+
+ const bool is_option = Strings::case_insensitive_ascii_starts_with(prefix, "-");
+ if (is_option)
{
- v = Util::fmap(command.structure.switches, [](auto&& s) -> std::string { return s; });
+ results =
+ Util::fmap(command.structure.options.switches, [](const CommandSwitch& s) { return s.name; });
+
+ auto settings = Util::fmap(command.structure.options.settings, [](auto&& s) { return s.name; });
+ results.insert(results.end(), settings.begin(), settings.end());
}
else
{
- v = command.structure.valid_arguments(paths);
+ if (command.structure.valid_arguments != nullptr)
+ results = command.structure.valid_arguments(paths);
}
- Util::unstable_keep_if(
- v, [&](const std::string& s) { return Strings::case_insensitive_ascii_starts_with(s, prefix); });
+ Util::unstable_keep_if(results, [&](const std::string& s) {
+ return Strings::case_insensitive_ascii_starts_with(s, prefix);
+ });
+
+ if (command.name == "install" && results.size() == 1 && !is_option)
+ {
+ const auto port_at_each_triplet =
+ combine_port_with_triplets(results[0], paths.get_available_triplets());
+ Util::Vectors::concatenate(&results, port_at_each_triplet);
+ }
- output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(v));
+ output_sorted_results_and_exit(VCPKG_LINE_INFO, std::move(results));
}
}
diff --git a/toolsrc/src/vcpkg/commands.buildexternal.cpp b/toolsrc/src/vcpkg/commands.buildexternal.cpp
index 3991beb62..82d03db48 100644
--- a/toolsrc/src/vcpkg/commands.buildexternal.cpp
+++ b/toolsrc/src/vcpkg/commands.buildexternal.cpp
@@ -7,17 +7,23 @@
namespace vcpkg::Commands::BuildExternal
{
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"),
+ 2,
+ 2,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
- static const std::string EXAMPLE =
- Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)");
- args.check_exact_arg_count(2, EXAMPLE);
- const FullPackageSpec spec =
- Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, EXAMPLE);
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
+
+ const FullPackageSpec spec = Input::check_and_get_full_package_spec(
+ args.command_arguments.at(0), default_triplet, COMMAND_STRUCTURE.example_text);
Input::check_triplet(spec.package_spec.triplet(), paths);
- const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({});
const fs::path port_dir = args.command_arguments.at(1);
- Build::Command::perform_and_exit(spec, port_dir, options, paths);
+ Build::Command::perform_and_exit_ex(spec, port_dir, options, paths);
}
}
diff --git a/toolsrc/src/vcpkg/commands.cache.cpp b/toolsrc/src/vcpkg/commands.cache.cpp
index 77f0a20f6..6fd123b7c 100644
--- a/toolsrc/src/vcpkg/commands.cache.cpp
+++ b/toolsrc/src/vcpkg/commands.cache.cpp
@@ -26,13 +26,19 @@ namespace vcpkg::Commands::Cache
return output;
}
+ const CommandStructure COMMAND_STRUCTURE = {
+ Strings::format(
+ "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s",
+ Help::create_example_string("cache png")),
+ 0,
+ 1,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string EXAMPLE = Strings::format(
- "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s",
- Help::create_example_string("cache png"));
- args.check_max_arg_count(1, EXAMPLE);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
const std::vector<BinaryParagraph> binary_paragraphs = read_all_binary_paragraphs(paths);
if (binary_paragraphs.empty())
diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp
index 1c98d1d83..dce294004 100644
--- a/toolsrc/src/vcpkg/commands.ci.cpp
+++ b/toolsrc/src/vcpkg/commands.ci.cpp
@@ -1,6 +1,5 @@
#include "pch.h"
-#include <vcpkg/base/chrono.h>
#include <vcpkg/base/files.h>
#include <vcpkg/base/system.h>
#include <vcpkg/base/util.h>
@@ -10,7 +9,6 @@
#include <vcpkg/help.h>
#include <vcpkg/input.h>
#include <vcpkg/install.h>
-#include <vcpkg/paragraphs.h>
#include <vcpkg/vcpkglib.h>
namespace vcpkg::Commands::CI
@@ -19,43 +17,92 @@ namespace vcpkg::Commands::CI
using Dependencies::InstallPlanAction;
using Dependencies::InstallPlanType;
- static std::vector<PackageSpec> load_all_package_specs(Files::Filesystem& fs,
- const fs::path& ports_directory,
- const Triplet& triplet)
+ static Install::InstallSummary run_ci_on_triplet(const Triplet& triplet,
+ const VcpkgPaths& paths,
+ const std::vector<std::string>& ports,
+ const std::set<std::string>& exclusions_set)
{
- auto ports = Paragraphs::load_all_ports(fs, ports_directory);
- return Util::fmap(ports, [&](auto&& control_file) -> PackageSpec {
- return PackageSpec::from_name_and_triplet(control_file->core_paragraph->name, triplet)
- .value_or_exit(VCPKG_LINE_INFO);
- });
- }
-
- void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
- {
- static const std::string EXAMPLE = Help::create_example_string("ci x64-windows");
- args.check_max_arg_count(1, EXAMPLE);
- const Triplet triplet = args.command_arguments.size() == 1
- ? Triplet::from_canonical_name(args.command_arguments.at(0))
- : default_triplet;
Input::check_triplet(triplet, paths);
- args.check_and_get_optional_command_arguments({});
- const std::vector<PackageSpec> specs = load_all_package_specs(paths.get_filesystem(), paths.ports, triplet);
+
+ 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);
std::vector<InstallPlanAction> install_plan =
Dependencies::create_install_plan(paths_port_file, specs, status_db);
+
+ for (InstallPlanAction& plan : install_plan)
+ {
+ if (Util::Sets::contains(exclusions_set, plan.spec.name()))
+ {
+ plan.plan_type = InstallPlanType::EXCLUDED;
+ }
+ }
+
Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty");
const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES};
const std::vector<Dependencies::AnyAction> action_plan =
- Util::fmap(install_plan, [](InstallPlanAction& install_action) {
+ Util::fmap(install_plan, [&install_plan_options](InstallPlanAction& install_action) {
+ install_action.build_options = install_plan_options;
return Dependencies::AnyAction(std::move(install_action));
});
- Install::perform_and_exit_ex(
- action_plan, install_plan_options, Install::KeepGoing::YES, Install::PrintSummary::YES, paths, status_db);
+ return Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db);
+ }
+
+ struct TripletAndSummary
+ {
+ Triplet triplet;
+ Install::InstallSummary summary;
+ };
+
+ static const std::string OPTION_EXCLUDE = "--exclude";
+
+ static const std::array<CommandSetting, 1> CI_SETTINGS = {{
+ {OPTION_EXCLUDE, "Comma separated list of ports to skip"},
+ }};
+
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string("ci x64-windows"),
+ 0,
+ SIZE_MAX,
+ {{}, CI_SETTINGS},
+ nullptr,
+ };
+
+ void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
+ {
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
+ const std::vector<std::string> exclusions = Strings::split(options.settings.at(OPTION_EXCLUDE), ",");
+ const std::set<std::string> exclusions_set(exclusions.cbegin(), exclusions.cend());
+
+ std::vector<Triplet> triplets;
+ for (const std::string& triplet : args.command_arguments)
+ {
+ triplets.push_back(Triplet::from_canonical_name(triplet));
+ }
+
+ if (triplets.empty())
+ {
+ triplets.push_back(default_triplet);
+ }
+
+ const std::vector<std::string> ports = Install::get_all_port_names(paths);
+ std::vector<TripletAndSummary> results;
+ for (const Triplet& triplet : triplets)
+ {
+ Install::InstallSummary summary = run_ci_on_triplet(triplet, paths, ports, exclusions_set);
+ results.push_back({triplet, std::move(summary)});
+ }
+
+ for (auto&& result : results)
+ {
+ System::println("\nTriplet: %s", result.triplet);
+ System::println("Total elapsed time: %s", result.summary.total_elapsed_time);
+ result.summary.print();
+ }
Checks::exit_success(VCPKG_LINE_INFO);
}
diff --git a/toolsrc/src/vcpkg/commands.contact.cpp b/toolsrc/src/vcpkg/commands.contact.cpp
index 421b8a230..5d62faeea 100644
--- a/toolsrc/src/vcpkg/commands.contact.cpp
+++ b/toolsrc/src/vcpkg/commands.contact.cpp
@@ -2,6 +2,7 @@
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
+#include <vcpkg/help.h>
namespace vcpkg::Commands::Contact
{
@@ -11,10 +12,17 @@ namespace vcpkg::Commands::Contact
return S_EMAIL;
}
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string("contact"),
+ 0,
+ 0,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args)
{
- args.check_exact_arg_count(0);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
System::println("Send an email to %s with any feedback.", email());
Checks::exit_success(VCPKG_LINE_INFO);
diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp
index 9d969ea28..15b10c7ea 100644
--- a/toolsrc/src/vcpkg/commands.cpp
+++ b/toolsrc/src/vcpkg/commands.cpp
@@ -13,7 +13,7 @@ namespace vcpkg::Commands
Span<const PackageNameAndFunction<CommandTypeA>> get_available_commands_type_a()
{
static std::vector<PackageNameAndFunction<CommandTypeA>> t = {
- {"install", &Install::perform_and_exit},
+ PackageNameAndFunction<CommandTypeA>{"install", &Install::perform_and_exit},
{"ci", &CI::perform_and_exit},
{"remove", &Remove::perform_and_exit},
{"build", &Build::Command::perform_and_exit},
diff --git a/toolsrc/src/vcpkg/commands.create.cpp b/toolsrc/src/vcpkg/commands.create.cpp
index d923cf555..c7183d257 100644
--- a/toolsrc/src/vcpkg/commands.create.cpp
+++ b/toolsrc/src/vcpkg/commands.create.cpp
@@ -8,19 +8,24 @@
namespace vcpkg::Commands::Create
{
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string(
+ R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###"),
+ 2,
+ 3,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string EXAMPLE = Help::create_example_string(
- R"###(create zlib2 http://zlib.net/zlib1211.zip "zlib1211-2.zip")###");
- args.check_max_arg_count(3, EXAMPLE);
- args.check_min_arg_count(2, EXAMPLE);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
const std::string port_name = args.command_arguments.at(0);
const std::string url = args.command_arguments.at(1);
const fs::path& cmake_exe = paths.get_cmake_exe();
- std::vector<CMakeVariable> cmake_args{{L"CMD", L"CREATE"}, {L"PORT", port_name}, {L"URL", url}};
+ std::vector<CMakeVariable> cmake_args{{"CMD", "CREATE"}, {"PORT", port_name}, {"URL", url}};
if (args.command_arguments.size() >= 3)
{
@@ -30,10 +35,10 @@ namespace vcpkg::Commands::Create
R"(Filename cannot contain invalid chars %s, but was %s)",
Files::FILESYSTEM_INVALID_CHARACTERS,
zip_file_name);
- cmake_args.push_back({L"FILENAME", zip_file_name});
+ cmake_args.push_back({"FILENAME", zip_file_name});
}
- const std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args);
+ const std::string cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args);
Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute_clean(cmd_launch_cmake));
}
}
diff --git a/toolsrc/src/vcpkg/commands.dependinfo.cpp b/toolsrc/src/vcpkg/commands.dependinfo.cpp
index 89c7e0c7f..bb300d96e 100644
--- a/toolsrc/src/vcpkg/commands.dependinfo.cpp
+++ b/toolsrc/src/vcpkg/commands.dependinfo.cpp
@@ -9,11 +9,17 @@
namespace vcpkg::Commands::DependInfo
{
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string(R"###(depend-info [pat])###"),
+ 0,
+ 1,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string EXAMPLE = Help::create_example_string(R"###(depend-info [pat])###");
- args.check_max_arg_count(1, EXAMPLE);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
std::vector<std::unique_ptr<SourceControlFile>> source_control_files =
Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp
index a90ae1bc3..e40e394fb 100644
--- a/toolsrc/src/vcpkg/commands.edit.cpp
+++ b/toolsrc/src/vcpkg/commands.edit.cpp
@@ -3,24 +3,24 @@
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
#include <vcpkg/help.h>
-#include <vcpkg/input.h>
#include <vcpkg/paragraphs.h>
namespace vcpkg::Commands::Edit
{
static std::vector<fs::path> find_from_registry()
{
- static const std::array<const wchar_t*, 3> REGKEYS = {
- LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)",
- LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)",
- LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)",
+ static const std::array<const char*, 3> REGKEYS = {
+ R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)",
+ R"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1287CAD5-7C8D-410D-88B9-0D1EE4A83FF2}_is1)",
+ R"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)",
};
std::vector<fs::path> output;
+#if defined(_WIN32)
for (auto&& keypath : REGKEYS)
{
- const Optional<std::wstring> code_installpath =
- System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation");
+ const Optional<std::string> code_installpath =
+ System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, "InstallLocation");
if (const auto c = code_installpath.get())
{
const fs::path install_path = fs::path(*c);
@@ -28,16 +28,12 @@ namespace vcpkg::Commands::Edit
output.push_back(install_path / "Code.exe");
}
}
+#endif
return output;
}
static const std::string OPTION_BUILDTREES = "--buildtrees";
- static const std::array<std::string, 1> SWITCHES = {
- OPTION_BUILDTREES,
- };
- static const std::array<std::string, 0> SETTINGS;
-
static std::vector<std::string> valid_arguments(const VcpkgPaths& paths)
{
auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports);
@@ -46,12 +42,15 @@ namespace vcpkg::Commands::Edit
[](auto&& pgh) -> std::string { return pgh->core_paragraph->name; });
}
+ static const std::array<CommandSwitch, 1> EDIT_SWITCHES = {{
+ {OPTION_BUILDTREES, "Open editor into the port-specific buildtree subfolder"},
+ }};
+
const CommandStructure COMMAND_STRUCTURE = {
- "edit zlib",
+ Help::create_example_string("edit zlib"),
1,
1,
- SWITCHES,
- SETTINGS,
+ {EDIT_SWITCHES, {}},
&valid_arguments,
};
@@ -62,17 +61,14 @@ namespace vcpkg::Commands::Edit
auto& fs = paths.get_filesystem();
- static const std::string EXAMPLE = Help::create_example_string("edit zlib");
- args.check_exact_arg_count(1, EXAMPLE);
- const std::unordered_set<std::string> options =
- args.check_and_get_optional_command_arguments({OPTION_BUILDTREES});
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
const std::string port_name = args.command_arguments.at(0);
const fs::path portpath = paths.ports / port_name;
Checks::check_exit(VCPKG_LINE_INFO, fs.is_directory(portpath), R"(Could not find port named "%s")", port_name);
std::vector<fs::path> candidate_paths;
- const std::vector<fs::path> from_path = Files::find_from_PATH(L"EDITOR");
+ const std::vector<fs::path> from_path = Files::find_from_PATH("EDITOR");
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE_INSIDERS);
candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE_INSIDERS);
@@ -94,17 +90,20 @@ namespace vcpkg::Commands::Edit
}
const fs::path env_editor = *it;
- if (options.find(OPTION_BUILDTREES) != options.cend())
+ if (Util::Sets::contains(options.switches, OPTION_BUILDTREES))
{
const auto buildtrees_current_dir = paths.buildtrees / port_name;
- const std::wstring cmd_line =
- Strings::wformat(LR"("%s" "%s" -n)", env_editor, buildtrees_current_dir.native());
+ const auto cmd_line =
+ Strings::format(R"("%s" "%s" -n)", env_editor.u8string(), buildtrees_current_dir.u8string());
Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line));
}
- const std::wstring cmd_line = Strings::wformat(
- LR"("%s" "%s" "%s" -n)", env_editor, portpath.native(), (portpath / "portfile.cmake").native());
+ const auto cmd_line = Strings::format(
+ R"("%s" "%s" "%s" -n)",
+ env_editor.u8string(),
+ portpath.u8string(),
+ (portpath / "portfile.cmake").u8string());
Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line));
}
}
diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp
index 089881588..98b5aced9 100644
--- a/toolsrc/src/vcpkg/commands.env.cpp
+++ b/toolsrc/src/vcpkg/commands.env.cpp
@@ -7,15 +7,21 @@
namespace vcpkg::Commands::Env
{
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string("env --triplet x64-windows"),
+ 0,
+ 0,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
- static const std::string EXAMPLE = Help::create_example_string(R"(env --triplet x64-windows)");
- args.check_exact_arg_count(0, EXAMPLE);
- args.check_and_get_optional_command_arguments({});
+ 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);
- System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, toolset) + L" && cmd");
+ 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.exportifw.cpp b/toolsrc/src/vcpkg/commands.exportifw.cpp
index fbf3beb8c..682267acb 100644
--- a/toolsrc/src/vcpkg/commands.exportifw.cpp
+++ b/toolsrc/src/vcpkg/commands.exportifw.cpp
@@ -29,7 +29,7 @@ namespace vcpkg::Export::IFW
std::string safe_rich_from_plain_text(const std::string& text)
{
- // match standalone ampersand, no HTML number or name
+ // match standalone ampersand, no HTML number or name
std::regex standalone_ampersand(R"###(&(?!(#[0-9]+|\w+);))###");
return std::regex_replace(text, standalone_ampersand, "&amp;");
@@ -350,10 +350,10 @@ namespace vcpkg::Export::IFW
Checks::check_exit(
VCPKG_LINE_INFO, !ec, "Could not remove outdated repository directory %s", repository_dir.generic_string());
- const std::wstring cmd_line = Strings::wformat(LR"("%s" --packages "%s" "%s" > nul)",
- repogen_exe.native(),
- packages_dir.native(),
- repository_dir.native());
+ const auto cmd_line = Strings::format(R"("%s" --packages "%s" "%s" > nul)",
+ repogen_exe.u8string(),
+ packages_dir.u8string(),
+ repository_dir.u8string());
const int exit_code = System::cmd_execute_clean(cmd_line);
Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: IFW repository generating failed");
@@ -371,24 +371,24 @@ namespace vcpkg::Export::IFW
System::println("Generating installer %s...", installer_file.generic_string());
- std::wstring cmd_line;
+ std::string cmd_line;
std::string ifw_repo_url = ifw_options.maybe_repository_url.value_or("");
if (!ifw_repo_url.empty())
{
- cmd_line = Strings::wformat(LR"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)",
- binarycreator_exe.native(),
- config_file.native(),
- repository_dir.native(),
- installer_file.native());
+ cmd_line = Strings::format(R"("%s" --online-only --config "%s" --repository "%s" "%s" > nul)",
+ binarycreator_exe.u8string(),
+ config_file.u8string(),
+ repository_dir.u8string(),
+ installer_file.u8string());
}
else
{
- cmd_line = Strings::wformat(LR"("%s" --config "%s" --packages "%s" "%s" > nul)",
- binarycreator_exe.native(),
- config_file.native(),
- packages_dir.native(),
- installer_file.native());
+ cmd_line = Strings::format(R"("%s" --config "%s" --packages "%s" "%s" > nul)",
+ binarycreator_exe.u8string(),
+ config_file.u8string(),
+ packages_dir.u8string(),
+ installer_file.u8string());
}
const int exit_code = System::cmd_execute_clean(cmd_line);
diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp
index 394a02e23..a5940ea1e 100644
--- a/toolsrc/src/vcpkg/commands.hash.cpp
+++ b/toolsrc/src/vcpkg/commands.hash.cpp
@@ -7,47 +7,47 @@
namespace vcpkg::Commands::Hash
{
- static void do_file_hash(fs::path const& path, std::wstring const& hash_type)
+ static void do_file_hash(fs::path const& path, std::string const& hash_type)
{
- const auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.c_str(), hash_type);
+ const auto cmd_line = Strings::format(R"(CertUtil.exe -hashfile "%s" %s)", path.u8string().c_str(), hash_type);
const auto 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", Strings::to_utf8(cmd_line));
+ Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line);
std::string const& output = ec_data.output;
const auto start = output.find_first_of("\r\n");
- Checks::check_exit(VCPKG_LINE_INFO,
- start != std::string::npos,
- "Unexpected output format from command: %s",
- Strings::to_utf8(cmd_line));
+ Checks::check_exit(
+ VCPKG_LINE_INFO, start != std::string::npos, "Unexpected output format from command: %s", cmd_line);
const auto end = output.find_first_of("\r\n", start + 1);
- Checks::check_exit(VCPKG_LINE_INFO,
- end != std::string::npos,
- "Unexpected output format from command: %s",
- Strings::to_utf8(cmd_line));
+ Checks::check_exit(
+ VCPKG_LINE_INFO, end != std::string::npos, "Unexpected output format from command: %s", cmd_line);
auto hash = output.substr(start, end - start);
Util::erase_remove_if(hash, isspace);
System::println(hash);
}
+ const CommandStructure COMMAND_STRUCTURE = {
+ Strings::format("The argument should be a file path\n%s",
+ Help::create_example_string("hash boost_1_62_0.tar.bz2")),
+ 1,
+ 2,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args)
{
- static const std::string EXAMPLE = Strings::format("The argument should be a file path\n%s",
- Help::create_example_string("hash boost_1_62_0.tar.bz2"));
- args.check_min_arg_count(1, EXAMPLE);
- args.check_max_arg_count(2, EXAMPLE);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
if (args.command_arguments.size() == 1)
{
- do_file_hash(args.command_arguments[0], L"SHA512");
+ do_file_hash(args.command_arguments[0], "SHA512");
}
if (args.command_arguments.size() == 2)
{
- do_file_hash(args.command_arguments[0], Strings::to_utf16(args.command_arguments[1]));
+ do_file_hash(args.command_arguments[0], args.command_arguments[1]);
}
Checks::exit_success(VCPKG_LINE_INFO);
diff --git a/toolsrc/src/vcpkg/commands.import.cpp b/toolsrc/src/vcpkg/commands.import.cpp
index 119aee022..24394207b 100644
--- a/toolsrc/src/vcpkg/commands.import.cpp
+++ b/toolsrc/src/vcpkg/commands.import.cpp
@@ -92,12 +92,18 @@ namespace vcpkg::Commands::Import
fs.write_contents(control_file_path, Strings::serialize(control_file_data));
}
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string(
+ R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"),
+ 3,
+ 3,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string EXAMPLE = Help::create_example_string(
- R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)");
- args.check_exact_arg_count(3, EXAMPLE);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
const fs::path control_file_path(args.command_arguments[0]);
const fs::path include_directory(args.command_arguments[1]);
diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp
index 85b567adb..31b9ec722 100644
--- a/toolsrc/src/vcpkg/commands.integrate.cpp
+++ b/toolsrc/src/vcpkg/commands.integrate.cpp
@@ -8,12 +8,6 @@
namespace vcpkg::Commands::Integrate
{
- static const std::array<fs::path, 2> OLD_SYSTEM_TARGET_FILES = {
- System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets",
- System::get_program_files_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"};
- static const fs::path SYSTEM_WIDE_TARGETS_FILE =
- System::get_program_files_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props";
-
static std::string create_appdata_targets_shortcut(const std::string& target_path) noexcept
{
return Strings::format(R"###(
@@ -99,9 +93,9 @@ namespace vcpkg::Commands::Integrate
</package>
)";
- std::string content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id);
- content = std::regex_replace(content, std::regex("@VCPKG_DIR@"), vcpkg_root_dir.string());
- content = std::regex_replace(content, std::regex("@VERSION@"), nupkg_version);
+ std::string content = Strings::replace_all(CONTENT_TEMPLATE, "@NUGET_ID@", nuget_id);
+ content = Strings::replace_all(std::move(content), "@VCPKG_DIR@", vcpkg_root_dir.string());
+ content = Strings::replace_all(std::move(content), "@VERSION@", nupkg_version);
return content;
}
@@ -111,6 +105,7 @@ namespace vcpkg::Commands::Integrate
NO
};
+#if defined(_WIN32)
static ElevationPromptChoice elevated_cmd_execute(const std::string& param)
{
SHELLEXECUTEINFOW sh_ex_info = {0};
@@ -138,16 +133,29 @@ namespace vcpkg::Commands::Integrate
CloseHandle(sh_ex_info.hProcess);
return ElevationPromptChoice::YES;
}
+#endif
+#if defined(_WIN32)
static fs::path get_appdata_targets_path()
{
static const fs::path LOCAL_APP_DATA =
- fs::path(System::get_environment_variable(L"LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO));
+ fs::path(System::get_environment_variable("LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO));
return LOCAL_APP_DATA / "vcpkg" / "vcpkg.user.targets";
}
+#endif
+#if defined(_WIN32)
static void integrate_install(const VcpkgPaths& paths)
{
+ static const std::array<fs::path, 2> OLD_SYSTEM_TARGET_FILES = {
+ System::get_program_files_32_bit() /
+ "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets",
+ System::get_program_files_32_bit() /
+ "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"};
+ static const fs::path SYSTEM_WIDE_TARGETS_FILE =
+ System::get_program_files_32_bit() /
+ "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props";
+
auto& fs = paths.get_filesystem();
// TODO: This block of code should eventually be removed
@@ -262,6 +270,7 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")",
Checks::exit_success(VCPKG_LINE_INFO);
}
+#endif
static void integrate_project(const VcpkgPaths& paths)
{
@@ -286,10 +295,10 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")",
fs.write_contents(nuspec_file_path, create_nuspec_file_contents(paths.root, nuget_id, nupkg_version));
// Using all forward slashes for the command line
- const std::wstring cmd_line = Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" > nul)",
- nuget_exe.native(),
- buildsystems_dir.native(),
- nuspec_file_path.native());
+ const std::string cmd_line = Strings::format(R"("%s" pack -OutputDirectory "%s" "%s" > nul)",
+ nuget_exe.u8string(),
+ buildsystems_dir.u8string(),
+ nuspec_file_path.u8string());
const int exit_code = System::cmd_execute_clean(cmd_line);
@@ -299,7 +308,7 @@ CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=%s")",
System::println(System::Color::success, "Created nupkg: %s", nuget_package.string());
auto source_path = buildsystems_dir.u8string();
- source_path = std::regex_replace(source_path, std::regex("`"), "``");
+ source_path = Strings::replace_all(std::move(source_path), "`", "``");
System::println(R"(
With a project open, go to Tools->NuGet Package Manager->Package Manager Console and paste:
@@ -317,26 +326,46 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
" vcpkg integrate remove Remove user-wide integration\n"
" vcpkg integrate project Generate a referencing nuget package for individual VS project use\n";
+ namespace Subcommand
+ {
+ static const std::string INSTALL = "install";
+ static const std::string REMOVE = "remove";
+ static const std::string PROJECT = "project";
+ }
+
+ static std::vector<std::string> valid_arguments(const VcpkgPaths&)
+ {
+ return {Subcommand::INSTALL, Subcommand::REMOVE, Subcommand::PROJECT};
+ }
+
+ const CommandStructure COMMAND_STRUCTURE = {
+ Strings::format("Commands:\n"
+ "%s",
+ INTEGRATE_COMMAND_HELPSTRING),
+ 1,
+ 1,
+ {},
+ &valid_arguments,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string EXAMPLE = Strings::format("Commands:\n"
- "%s",
- INTEGRATE_COMMAND_HELPSTRING);
- args.check_exact_arg_count(1, EXAMPLE);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
- if (args.command_arguments[0] == "install")
+#if defined(_WIN32)
+ if (args.command_arguments[0] == Subcommand::INSTALL)
{
return integrate_install(paths);
}
- if (args.command_arguments[0] == "remove")
+ if (args.command_arguments[0] == Subcommand::REMOVE)
{
return integrate_remove(paths.get_filesystem());
}
- if (args.command_arguments[0] == "project")
+ if (args.command_arguments[0] == Subcommand::PROJECT)
{
return integrate_project(paths);
}
+#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 d0e8e00b4..1f2387843 100644
--- a/toolsrc/src/vcpkg/commands.list.cpp
+++ b/toolsrc/src/vcpkg/commands.list.cpp
@@ -24,14 +24,23 @@ namespace vcpkg::Commands::List
}
}
+ static const std::array<CommandSwitch, 1> LIST_SWITCHES = {{
+ {OPTION_FULLDESC, "Do not truncate long text"},
+ }};
+
+ const CommandStructure COMMAND_STRUCTURE = {
+ Strings::format(
+ "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s",
+ Help::create_example_string("list png")),
+ 0,
+ 1,
+ {LIST_SWITCHES, {}},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string EXAMPLE = Strings::format(
- "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s",
- Help::create_example_string("list png"));
- args.check_max_arg_count(1, EXAMPLE);
- const std::unordered_set<std::string> options =
- args.check_and_get_optional_command_arguments({OPTION_FULLDESC});
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
const StatusParagraphs status_paragraphs = database_load_check(paths);
std::vector<StatusParagraph*> installed_packages = get_installed_ports(status_paragraphs);
@@ -52,7 +61,7 @@ namespace vcpkg::Commands::List
{
for (const StatusParagraph* status_paragraph : installed_packages)
{
- do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend());
+ do_print(*status_paragraph, Util::Sets::contains(options.switches, OPTION_FULLDESC));
}
}
else
@@ -66,7 +75,7 @@ namespace vcpkg::Commands::List
continue;
}
- do_print(*status_paragraph, options.find(OPTION_FULLDESC) != options.cend());
+ do_print(*status_paragraph, Util::Sets::contains(options.switches, OPTION_FULLDESC));
}
}
diff --git a/toolsrc/src/vcpkg/commands.owns.cpp b/toolsrc/src/vcpkg/commands.owns.cpp
index 69079e829..52249187b 100644
--- a/toolsrc/src/vcpkg/commands.owns.cpp
+++ b/toolsrc/src/vcpkg/commands.owns.cpp
@@ -23,15 +23,20 @@ namespace vcpkg::Commands::Owns
}
}
}
+ const CommandStructure COMMAND_STRUCTURE = {
+ Strings::format("The argument should be a pattern to search for. %s",
+ Help::create_example_string("owns zlib.dll")),
+ 1,
+ 1,
+ {},
+ nullptr,
+ };
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string EXAMPLE = Strings::format("The argument should be a pattern to search for. %s",
- Help::create_example_string("owns zlib.dll"));
- args.check_exact_arg_count(1, EXAMPLE);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
- StatusParagraphs status_db = database_load_check(paths);
+ const StatusParagraphs status_db = database_load_check(paths);
search_file(paths, args.command_arguments[0], status_db);
Checks::exit_success(VCPKG_LINE_INFO);
}
diff --git a/toolsrc/src/vcpkg/commands.portsdiff.cpp b/toolsrc/src/vcpkg/commands.portsdiff.cpp
index b70ad2b80..0277c8bdb 100644
--- a/toolsrc/src/vcpkg/commands.portsdiff.cpp
+++ b/toolsrc/src/vcpkg/commands.portsdiff.cpp
@@ -75,28 +75,28 @@ namespace vcpkg::Commands::PortsDiff
}
static std::map<std::string, VersionT> read_ports_from_commit(const VcpkgPaths& paths,
- const std::wstring& git_commit_id)
+ const std::string& git_commit_id)
{
std::error_code ec;
auto& fs = paths.get_filesystem();
const fs::path& git_exe = paths.get_git_exe();
const fs::path dot_git_dir = paths.root / ".git";
- const std::wstring ports_dir_name_as_string = paths.ports.filename().native();
+ const std::string ports_dir_name_as_string = paths.ports.filename().u8string();
const fs::path temp_checkout_path =
- paths.root / Strings::wformat(L"%s-%s", ports_dir_name_as_string, git_commit_id);
+ paths.root / Strings::format("%s-%s", ports_dir_name_as_string, git_commit_id);
fs.create_directory(temp_checkout_path, ec);
- const std::wstring checkout_this_dir =
- Strings::wformat(LR"(.\%s)", ports_dir_name_as_string); // Must be relative to the root of the repository
-
- const std::wstring cmd =
- Strings::wformat(LR"("%s" --git-dir="%s" --work-tree="%s" checkout %s -f -q -- %s %s & "%s" reset >NUL)",
- git_exe.native(),
- dot_git_dir.native(),
- temp_checkout_path.native(),
- git_commit_id,
- checkout_this_dir,
- L".vcpkg-root",
- git_exe.native());
+ const auto checkout_this_dir =
+ Strings::format(R"(.\%s)", ports_dir_name_as_string); // Must be relative to the root of the repository
+
+ const std::string cmd =
+ Strings::format(R"("%s" --git-dir="%s" --work-tree="%s" checkout %s -f -q -- %s %s & "%s" reset >NUL)",
+ git_exe.u8string(),
+ dot_git_dir.u8string(),
+ temp_checkout_path.u8string(),
+ git_commit_id,
+ checkout_this_dir,
+ ".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);
@@ -104,31 +104,34 @@ namespace vcpkg::Commands::PortsDiff
return names_and_versions;
}
- static void check_commit_exists(const fs::path& git_exe, const std::wstring& git_commit_id)
+ static void check_commit_exists(const fs::path& git_exe, const std::string& git_commit_id)
{
static const std::string VALID_COMMIT_OUTPUT = "commit\n";
- const std::wstring cmd = Strings::wformat(LR"("%s" cat-file -t %s)", git_exe.native(), git_commit_id);
+ const auto cmd = Strings::format(R"("%s" cat-file -t %s)", git_exe.u8string(), git_commit_id);
const System::ExitCodeAndOutput output = System::cmd_execute_and_capture_output(cmd);
- Checks::check_exit(VCPKG_LINE_INFO,
- output.output == VALID_COMMIT_OUTPUT,
- "Invalid commit id %s",
- Strings::to_utf8(git_commit_id));
+ Checks::check_exit(
+ VCPKG_LINE_INFO, output.output == VALID_COMMIT_OUTPUT, "Invalid commit id %s", git_commit_id);
}
+ const CommandStructure COMMAND_STRUCTURE = {
+ Strings::format("The argument should be a branch/tag/hash to checkout.\n%s",
+ Help::create_example_string("portsdiff mybranchname")),
+ 1,
+ 2,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string EXAMPLE = Strings::format("The argument should be a branch/tag/hash to checkout.\n%s",
- Help::create_example_string("portsdiff mybranchname"));
- args.check_min_arg_count(1, EXAMPLE);
- args.check_max_arg_count(2, EXAMPLE);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
const fs::path& git_exe = paths.get_git_exe();
- const std::wstring git_commit_id_for_previous_snapshot = Strings::to_utf16(args.command_arguments.at(0));
- const std::wstring git_commit_id_for_current_snapshot =
- args.command_arguments.size() < 2 ? L"HEAD" : Strings::to_utf16(args.command_arguments.at(1));
+ const std::string git_commit_id_for_previous_snapshot = args.command_arguments.at(0);
+ const std::string git_commit_id_for_current_snapshot =
+ args.command_arguments.size() < 2 ? "HEAD" : args.command_arguments.at(1);
check_commit_exists(git_exe, git_commit_id_for_current_snapshot);
check_commit_exists(git_exe, git_commit_id_for_previous_snapshot);
diff --git a/toolsrc/src/vcpkg/commands.search.cpp b/toolsrc/src/vcpkg/commands.search.cpp
index 3ba8707de..01291ddfb 100644
--- a/toolsrc/src/vcpkg/commands.search.cpp
+++ b/toolsrc/src/vcpkg/commands.search.cpp
@@ -79,18 +79,29 @@ namespace vcpkg::Commands::Search
}
}
+ static std::array<CommandSwitch, 2> SEARCH_SWITCHES = {{
+ {OPTION_GRAPH, "Open editor into the port-specific buildtree subfolder"},
+ {OPTION_FULLDESC, "Do not truncate long text"},
+ }};
+
+ const CommandStructure COMMAND_STRUCTURE = {
+ Strings::format(
+ "The argument should be a substring to search for, or no argument to display all libraries.\n%s",
+ Help::create_example_string("search png")),
+ 0,
+ 1,
+ {SEARCH_SWITCHES, {}},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string EXAMPLE = Strings::format(
- "The argument should be a substring to search for, or no argument to display all libraries.\n%s",
- Help::create_example_string("search png"));
- args.check_max_arg_count(1, EXAMPLE);
- const std::unordered_set<std::string> options =
- args.check_and_get_optional_command_arguments({OPTION_GRAPH, OPTION_FULLDESC});
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
+ const bool full_description = Util::Sets::contains(options.switches, OPTION_FULLDESC);
auto source_paragraphs = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
- if (options.find(OPTION_GRAPH) != options.cend())
+ if (Util::Sets::contains(options.switches, OPTION_GRAPH))
{
const std::string graph_as_string = create_graph_as_string(source_paragraphs);
System::println(graph_as_string);
@@ -101,12 +112,10 @@ namespace vcpkg::Commands::Search
{
for (const auto& source_control_file : source_paragraphs)
{
- do_print(*source_control_file->core_paragraph, options.find(OPTION_FULLDESC) != options.cend());
+ do_print(*source_control_file->core_paragraph, full_description);
for (auto&& feature_paragraph : source_control_file->feature_paragraphs)
{
- do_print(source_control_file->core_paragraph->name,
- *feature_paragraph,
- options.find(OPTION_FULLDESC) != options.cend());
+ do_print(source_control_file->core_paragraph->name, *feature_paragraph, full_description);
}
}
}
@@ -120,10 +129,10 @@ namespace vcpkg::Commands::Search
{
auto&& sp = *source_control_file->core_paragraph;
- bool contains_name = icontains(sp.name, args_zero);
+ const bool contains_name = icontains(sp.name, args_zero);
if (contains_name || icontains(sp.description, args_zero))
{
- do_print(sp, options.find(OPTION_FULLDESC) != options.cend());
+ do_print(sp, full_description);
}
for (auto&& feature_paragraph : source_control_file->feature_paragraphs)
@@ -131,7 +140,7 @@ namespace vcpkg::Commands::Search
if (contains_name || icontains(feature_paragraph->name, args_zero) ||
icontains(feature_paragraph->description, args_zero))
{
- do_print(sp.name, *feature_paragraph, options.find(OPTION_FULLDESC) != options.cend());
+ do_print(sp.name, *feature_paragraph, full_description);
}
}
}
diff --git a/toolsrc/src/vcpkg/commands.version.cpp b/toolsrc/src/vcpkg/commands.version.cpp
index c6cc82d1f..3f44cf1a2 100644
--- a/toolsrc/src/vcpkg/commands.version.cpp
+++ b/toolsrc/src/vcpkg/commands.version.cpp
@@ -2,6 +2,7 @@
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
+#include <vcpkg/help.h>
#include <vcpkg/metrics.h>
#define STRINGIFY(...) #__VA_ARGS__
@@ -20,20 +21,29 @@ namespace vcpkg::Commands::Version
#ifndef NDEBUG
+ std::string("-debug")
#endif
- + std::string(Metrics::get_compiled_metrics_enabled() ? Strings::EMPTY : "-external");
+ + std::string(Metrics::get_compiled_metrics_enabled() ? "" : "-external");
return S_VERSION;
}
+ static int scan3(const char* input, const char* pattern, int* a, int* b, int* c)
+ {
+#if defined(_WIN32)
+ return sscanf_s(input, pattern, a, b, c);
+#else
+ return sscanf(input, pattern, a, b, c);
+#endif
+ }
+
void warn_if_vcpkg_version_mismatch(const VcpkgPaths& paths)
{
auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt");
if (const auto version_contents = version_file.get())
{
int maj1, min1, rev1;
- const auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1);
+ const auto num1 = scan3(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1);
int maj2, min2, rev2;
- const auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2);
+ const auto num2 = scan3(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2);
if (num1 == 3 && num2 == 3)
{
@@ -52,11 +62,17 @@ namespace vcpkg::Commands::Version
}
}
}
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string("version"),
+ 0,
+ 0,
+ {},
+ nullptr,
+ };
void perform_and_exit(const VcpkgCmdArguments& args)
{
- args.check_exact_arg_count(0);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
System::println("Vcpkg package management program version %s\n"
"\n"
diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp
index da8f1e178..6f599afd4 100644
--- a/toolsrc/src/vcpkg/dependencies.cpp
+++ b/toolsrc/src/vcpkg/dependencies.cpp
@@ -43,14 +43,17 @@ namespace vcpkg::Dependencies
bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; }
}
-template<>
-struct std::hash<vcpkg::Dependencies::ClusterPtr>
+namespace std
{
- size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const
+ template<>
+ struct hash<vcpkg::Dependencies::ClusterPtr>
{
- return std::hash<vcpkg::PackageSpec>()(value.ptr->spec);
- }
-};
+ size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const
+ {
+ return std::hash<vcpkg::PackageSpec>()(value.ptr->spec);
+ }
+ };
+}
namespace vcpkg::Dependencies
{
@@ -109,33 +112,41 @@ namespace vcpkg::Dependencies
std::vector<PackageSpec> AnyParagraph::dependencies(const Triplet& triplet) const
{
- auto to_package_specs = [&](const std::vector<std::string>& dependencies_as_string) {
- return Util::fmap(dependencies_as_string, [&](const std::string s) {
- return PackageSpec::from_name_and_triplet(s, triplet).value_or_exit(VCPKG_LINE_INFO);
- });
- };
-
- if (auto p = this->status_paragraph.get())
+ if (const auto p = this->status_paragraph.get())
{
- return to_package_specs(p->package.depends);
+ return PackageSpec::to_package_specs(p->package.depends, triplet);
}
- if (auto p = this->binary_control_file.get())
+ 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.begin(), p->core_paragraph.depends.end());
- return to_package_specs(deps);
+ deps.insert(deps.end(), p->core_paragraph.depends.cbegin(), p->core_paragraph.depends.cend());
+ return PackageSpec::to_package_specs(deps, triplet);
}
- if (auto p = this->source_paragraph.get())
+ if (const auto p = this->source_paragraph.get())
{
- return to_package_specs(filter_dependencies(p->depends, triplet));
+ return PackageSpec::to_package_specs(filter_dependencies(p->depends, triplet), triplet);
}
Checks::exit_with_message(VCPKG_LINE_INFO,
"Cannot get dependencies because there was none of: source/binary/status paragraphs");
}
+ std::string to_output_string(RequestType request_type,
+ const CStringView s,
+ const Build::BuildPackageOptions& options)
+ {
+ const char* const from_head = options.use_head_version == Build::UseHeadVersion::YES ? " (from HEAD)" : "";
+
+ switch (request_type)
+ {
+ case RequestType::AUTO_SELECTED: return Strings::format(" * %s%s", s, from_head);
+ case RequestType::USER_REQUESTED: return Strings::format(" %s%s", s, from_head);
+ default: Checks::unreachable(VCPKG_LINE_INFO);
+ }
+ }
+
std::string to_output_string(RequestType request_type, const CStringView s)
{
switch (request_type)
@@ -608,10 +619,38 @@ namespace vcpkg::Dependencies
{
Cluster& spec_cluster = graph.get(spec.spec());
spec_cluster.request_type = RequestType::USER_REQUESTED;
- auto res = mark_plus(spec.feature(), spec_cluster, graph, graph_plan);
+ if (spec.feature() == "*")
+ {
+ if (auto p_scf = spec_cluster.source_control_file.value_or(nullptr))
+ {
+ 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);
+
+ 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);
- Checks::check_exit(
- VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec);
+ Checks::check_exit(
+ VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS, "Error: Unable to locate feature %s", spec);
+ }
graph_plan.install_graph.add_vertex(ClusterPtr{&spec_cluster});
}
diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp
index de6464c87..9b86863eb 100644
--- a/toolsrc/src/vcpkg/export.cpp
+++ b/toolsrc/src/vcpkg/export.cpp
@@ -4,6 +4,7 @@
#include <vcpkg/base/util.h>
#include <vcpkg/commands.h>
#include <vcpkg/dependencies.h>
+#include <vcpkg/export.h>
#include <vcpkg/export.ifw.h>
#include <vcpkg/help.h>
#include <vcpkg/input.h>
@@ -44,12 +45,12 @@ namespace vcpkg::Export
</package>
)";
- std::string nuspec_file_content = std::regex_replace(CONTENT_TEMPLATE, std::regex("@NUGET_ID@"), nuget_id);
- nuspec_file_content = std::regex_replace(nuspec_file_content, std::regex("@VERSION@"), nupkg_version);
+ std::string nuspec_file_content = Strings::replace_all(CONTENT_TEMPLATE, "@NUGET_ID@", nuget_id);
+ nuspec_file_content = Strings::replace_all(std::move(nuspec_file_content), "@VERSION@", nupkg_version);
nuspec_file_content =
- std::regex_replace(nuspec_file_content, std::regex("@RAW_EXPORTED_DIR@"), raw_exported_dir);
+ Strings::replace_all(std::move(nuspec_file_content), "@RAW_EXPORTED_DIR@", raw_exported_dir);
nuspec_file_content =
- std::regex_replace(nuspec_file_content, std::regex("@TARGETS_REDIRECT_PATH@"), targets_redirect_path);
+ Strings::replace_all(std::move(nuspec_file_content), "@TARGETS_REDIRECT_PATH@", targets_redirect_path);
return nuspec_file_content;
}
@@ -68,6 +69,8 @@ namespace vcpkg::Export
{
static constexpr std::array<ExportPlanType, 2> ORDER = {ExportPlanType::ALREADY_BUILT,
ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT};
+ static constexpr Build::BuildPackageOptions build_options = {Build::UseHeadVersion::NO,
+ Build::AllowDownloads::YES};
for (const ExportPlanType plan_type : ORDER)
{
@@ -80,7 +83,7 @@ namespace vcpkg::Export
std::vector<const ExportPlanAction*> cont = it->second;
std::sort(cont.begin(), cont.end(), &ExportPlanAction::compare_by_name);
const std::string as_string = Strings::join("\n", cont, [](const ExportPlanAction* p) {
- return Dependencies::to_output_string(p->request_type, p->spec.to_string());
+ return Dependencies::to_output_string(p->request_type, p->spec.to_string(), build_options);
});
switch (plan_type)
@@ -137,11 +140,10 @@ namespace vcpkg::Export
fs.write_contents(nuspec_file_path, nuspec_file_content);
// -NoDefaultExcludes is needed for ".vcpkg-root"
- const std::wstring cmd_line =
- Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" -NoDefaultExcludes > nul)",
- nuget_exe.native(),
- output_dir.native(),
- nuspec_file_path.native());
+ const auto cmd_line = Strings::format(R"("%s" pack -OutputDirectory "%s" "%s" -NoDefaultExcludes > nul)",
+ nuget_exe.u8string(),
+ output_dir.u8string(),
+ nuspec_file_path.u8string());
const int exit_code = System::cmd_execute_clean(cmd_line);
Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Error: NuGet package creation failed");
@@ -160,25 +162,25 @@ namespace vcpkg::Export
constexpr ArchiveFormat() = delete;
- constexpr ArchiveFormat(BackingEnum backing_enum, const wchar_t* extension, const wchar_t* cmake_option)
+ constexpr ArchiveFormat(BackingEnum backing_enum, const char* extension, const char* cmake_option)
: backing_enum(backing_enum), m_extension(extension), m_cmake_option(cmake_option)
{
}
constexpr operator BackingEnum() const { return backing_enum; }
- constexpr CWStringView extension() const { return this->m_extension; }
- constexpr CWStringView cmake_option() const { return this->m_cmake_option; }
+ constexpr CStringView extension() const { return this->m_extension; }
+ constexpr CStringView cmake_option() const { return this->m_cmake_option; }
private:
BackingEnum backing_enum;
- const wchar_t* m_extension;
- const wchar_t* m_cmake_option;
+ const char* m_extension;
+ const char* m_cmake_option;
};
namespace ArchiveFormatC
{
- constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, L"zip", L"zip");
- constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, L"7z", L"7zip");
+ constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, "zip", "zip");
+ constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, "7z", "7zip");
}
static fs::path do_archive_export(const VcpkgPaths& paths,
@@ -188,17 +190,17 @@ namespace vcpkg::Export
{
const fs::path& cmake_exe = paths.get_cmake_exe();
- const std::wstring exported_dir_filename = raw_exported_dir.filename().native();
- const std::wstring exported_archive_filename =
- Strings::wformat(L"%s.%s", exported_dir_filename, format.extension());
+ const std::string exported_dir_filename = raw_exported_dir.filename().u8string();
+ const std::string exported_archive_filename =
+ Strings::format("%s.%s", exported_dir_filename, format.extension());
const fs::path exported_archive_path = (output_dir / exported_archive_filename);
// -NoDefaultExcludes is needed for ".vcpkg-root"
- const std::wstring cmd_line = Strings::wformat(LR"("%s" -E tar "cf" "%s" --format=%s -- "%s")",
- cmake_exe.native(),
- exported_archive_path.native(),
- format.cmake_option(),
- raw_exported_dir.native());
+ const auto cmd_line = Strings::format(R"("%s" -E tar "cf" "%s" --format=%s -- "%s")",
+ cmake_exe.u8string(),
+ exported_archive_path.u8string(),
+ format.cmake_option(),
+ raw_exported_dir.u8string());
const int exit_code = System::cmd_execute_clean(cmd_line);
Checks::check_exit(
@@ -256,51 +258,57 @@ namespace vcpkg::Export
std::vector<PackageSpec> specs;
};
+ static const std::string OPTION_DRY_RUN = "--dry-run";
+ static const std::string OPTION_RAW = "--raw";
+ static const std::string OPTION_NUGET = "--nuget";
+ static const std::string OPTION_IFW = "--ifw";
+ static const std::string OPTION_ZIP = "--zip";
+ static const std::string OPTION_SEVEN_ZIP = "--7zip";
+ static const std::string OPTION_NUGET_ID = "--nuget-id";
+ static const std::string OPTION_NUGET_VERSION = "--nuget-version";
+ static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url";
+ static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path";
+ static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path";
+ static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path";
+ static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path";
+
+ static const std::array<CommandSwitch, 6> EXPORT_SWITCHES = {{
+ {OPTION_DRY_RUN, "Do not actually export"},
+ {OPTION_RAW, "Export to an uncompressed directory"},
+ {OPTION_NUGET, "Export a NuGet package"},
+ {OPTION_IFW, "Export to an IFW-based installer"},
+ {OPTION_ZIP, "Export to a zip file"},
+ {OPTION_SEVEN_ZIP, "Export to a 7zip (.7z) file"},
+ }};
+ static const std::array<CommandSetting, 7> EXPORT_SETTINGS = {{
+ {OPTION_NUGET_ID, "Specify the id for the exported NuGet package"},
+ {OPTION_NUGET_VERSION, "Specify the version for the exported NuGet package"},
+ {OPTION_IFW_REPOSITORY_URL, "Specify the remote repository URL for the online installer"},
+ {OPTION_IFW_PACKAGES_DIR_PATH, "Specify the temporary directory path for the repacked packages"},
+ {OPTION_IFW_REPOSITORY_DIR_PATH, "Specify the directory path for the exported repository"},
+ {OPTION_IFW_CONFIG_FILE_PATH, "Specify the temporary file path for the installer configuration"},
+ {OPTION_IFW_INSTALLER_FILE_PATH, "Specify the file path for the exported installer"},
+ }};
+
+ const CommandStructure vcpkg::Export::COMMAND_STRUCTURE = {
+ Help::create_example_string("export zlib zlib:x64-windows boost --nuget"),
+ 0,
+ SIZE_MAX,
+ {EXPORT_SWITCHES, EXPORT_SETTINGS},
+ nullptr,
+ };
+
static ExportArguments handle_export_command_arguments(const VcpkgCmdArguments& args,
const Triplet& default_triplet)
{
ExportArguments ret;
- static const std::string OPTION_DRY_RUN = "--dry-run";
- static const std::string OPTION_RAW = "--raw";
- static const std::string OPTION_NUGET = "--nuget";
- static const std::string OPTION_IFW = "--ifw";
- static const std::string OPTION_ZIP = "--zip";
- static const std::string OPTION_SEVEN_ZIP = "--7zip";
- static const std::string OPTION_NUGET_ID = "--nuget-id";
- static const std::string OPTION_NUGET_VERSION = "--nuget-version";
- static const std::string OPTION_IFW_REPOSITORY_URL = "--ifw-repository-url";
- static const std::string OPTION_IFW_PACKAGES_DIR_PATH = "--ifw-packages-directory-path";
- static const std::string OPTION_IFW_REPOSITORY_DIR_PATH = "--ifw-repository-directory-path";
- static const std::string OPTION_IFW_CONFIG_FILE_PATH = "--ifw-configuration-file-path";
- static const std::string OPTION_IFW_INSTALLER_FILE_PATH = "--ifw-installer-file-path";
+ const auto options = args.parse_arguments(COMMAND_STRUCTURE);
// input sanitization
- static const std::string EXAMPLE = Help::create_example_string("export zlib zlib:x64-windows boost --nuget");
- args.check_min_arg_count(1, EXAMPLE);
-
ret.specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE);
+ return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text);
});
-
- const auto options = args.check_and_get_optional_command_arguments(
- {
- OPTION_DRY_RUN,
- OPTION_RAW,
- OPTION_NUGET,
- OPTION_IFW,
- OPTION_ZIP,
- OPTION_SEVEN_ZIP,
- },
- {
- OPTION_NUGET_ID,
- OPTION_NUGET_VERSION,
- OPTION_IFW_REPOSITORY_URL,
- OPTION_IFW_PACKAGES_DIR_PATH,
- OPTION_IFW_REPOSITORY_DIR_PATH,
- OPTION_IFW_CONFIG_FILE_PATH,
- OPTION_IFW_INSTALLER_FILE_PATH,
- });
ret.dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend();
ret.raw = options.switches.find(OPTION_RAW) != options.switches.cend();
ret.nuget = options.switches.find(OPTION_NUGET) != options.switches.cend();
@@ -312,7 +320,7 @@ namespace vcpkg::Export
{
System::println(System::Color::error,
"Must provide at least one export type: --raw --nuget --ifw --zip --7zip");
- System::print(EXAMPLE);
+ System::print(COMMAND_STRUCTURE.example_text);
Checks::exit_fail(VCPKG_LINE_INFO);
}
@@ -361,13 +369,13 @@ 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(L"CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string());
+ const CMakeVariable cmake_variable = CMakeVariable("CMAKE_TOOLCHAIN_FILE", cmake_toolchain.generic_string());
System::println("\n"
"To use the exported libraries in CMake projects use:"
"\n"
" %s"
"\n",
- Strings::to_utf8(cmake_variable.s));
+ cmake_variable.s);
};
static void handle_raw_based_export(Span<const ExportPlanAction> export_plan,
diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp
index de564d357..43230fa4b 100644
--- a/toolsrc/src/vcpkg/globalstate.cpp
+++ b/toolsrc/src/vcpkg/globalstate.cpp
@@ -5,9 +5,9 @@
namespace vcpkg
{
Util::LockGuarded<Chrono::ElapsedTime> GlobalState::timer;
- std::atomic<bool> GlobalState::debugging = false;
- std::atomic<bool> GlobalState::feature_packages = false;
+ std::atomic<bool> GlobalState::debugging(false);
+ std::atomic<bool> GlobalState::feature_packages(false);
- std::atomic<int> GlobalState::g_init_console_cp = 0;
- std::atomic<int> GlobalState::g_init_console_output_cp = 0;
+ std::atomic<int> GlobalState::g_init_console_cp(0);
+ std::atomic<int> GlobalState::g_init_console_output_cp(0);
}
diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp
index 7867f71d2..c83f0277b 100644
--- a/toolsrc/src/vcpkg/help.cpp
+++ b/toolsrc/src/vcpkg/help.cpp
@@ -2,41 +2,79 @@
#include <vcpkg/base/system.h>
#include <vcpkg/commands.h>
+#include <vcpkg/export.h>
+#include <vcpkg/help.h>
+#include <vcpkg/install.h>
+#include <vcpkg/remove.h>
namespace vcpkg::Help
{
- void help_topics()
+ struct Topic
+ {
+ using topic_function = void (*)(const VcpkgPaths& paths);
+
+ constexpr Topic(CStringView n, topic_function fn) : name(n), print(fn) {}
+
+ CStringView name;
+ topic_function print;
+ };
+
+ template<const CommandStructure& S>
+ static void command_topic_fn(const VcpkgPaths&)
+ {
+ display_usage(S);
+ }
+
+ static void integrate_topic_fn(const VcpkgPaths&)
+ {
+ System::print("Commands:\n"
+ "%s",
+ Commands::Integrate::INTEGRATE_COMMAND_HELPSTRING);
+ }
+
+ static void help_topics(const VcpkgPaths&);
+
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string("help"),
+ 0,
+ 1,
+ {},
+ nullptr,
+ };
+
+ static constexpr std::array<Topic, 12> topics = {{
+ {"create", command_topic_fn<Commands::Create::COMMAND_STRUCTURE>},
+ {"edit", command_topic_fn<Commands::Edit::COMMAND_STRUCTURE>},
+ {"env", command_topic_fn<Commands::Env::COMMAND_STRUCTURE>},
+ {"export", command_topic_fn<Export::COMMAND_STRUCTURE>},
+ {"help", command_topic_fn<Help::COMMAND_STRUCTURE>},
+ {"install", command_topic_fn<Install::COMMAND_STRUCTURE>},
+ {"integrate", integrate_topic_fn},
+ {"list", command_topic_fn<Commands::List::COMMAND_STRUCTURE>},
+ {"owns", command_topic_fn<Commands::Owns::COMMAND_STRUCTURE>},
+ {"remove", command_topic_fn<Remove::COMMAND_STRUCTURE>},
+ {"search", command_topic_fn<Commands::Search::COMMAND_STRUCTURE>},
+ {"topics", help_topics},
+ }};
+
+ static void help_topics(const VcpkgPaths&)
{
System::println("Available help topics:\n"
" triplet\n"
- " integrate\n"
- " export");
+ " integrate"
+ "%s",
+ Strings::join("", topics, [](const Topic& topic) { return std::string("\n ") + topic.name; }));
}
void help_topic_valid_triplet(const VcpkgPaths& paths)
{
System::println("Available architecture triplets:");
- for (auto&& path : paths.get_filesystem().get_files_non_recursive(paths.triplets))
+ for (auto&& triplet : paths.get_available_triplets())
{
- System::println(" %s", path.stem().filename().string());
+ System::println(" %s", triplet);
}
}
- void help_topic_export()
- {
- System::println("Summary:\n"
- " vcpkg export [options] <pkgs>...\n"
- "\n"
- "Options:\n"
- " --7zip Export to a 7zip (.7z) file\n"
- " --dry-run Do not actually export\n"
- " --nuget Export a NuGet package\n"
- " --nuget-id=<id> Specify the id for the exported NuGet package\n"
- " --nuget-version=<ver> Specify the version for the exported NuGet package\n"
- " --raw Export to an uncompressed directory\n"
- " --zip Export to a zip file");
- }
-
void print_usage()
{
System::println(
@@ -86,15 +124,9 @@ namespace vcpkg::Help
return cs;
}
- void print_example(const std::string& command_and_arguments)
- {
- System::println(create_example_string(command_and_arguments));
- }
-
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- args.check_max_arg_count(1);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
if (args.command_arguments.empty())
{
@@ -105,27 +137,18 @@ namespace vcpkg::Help
if (topic == "triplet" || topic == "triplets" || topic == "triple")
{
help_topic_valid_triplet(paths);
+ Checks::exit_success(VCPKG_LINE_INFO);
}
- else if (topic == "export")
- {
- help_topic_export();
- }
- else if (topic == "integrate")
- {
- System::print("Commands:\n"
- "%s",
- Commands::Integrate::INTEGRATE_COMMAND_HELPSTRING);
- }
- else if (topic == "topics")
- {
- help_topics();
- }
- else
+
+ auto it_topic = Util::find_if(topics, [&](const Topic& t) { return t.name == topic; });
+ if (it_topic != topics.end())
{
- System::println(System::Color::error, "Error: unknown topic %s", topic);
- help_topics();
- Checks::exit_fail(VCPKG_LINE_INFO);
+ it_topic->print(paths);
+ Checks::exit_success(VCPKG_LINE_INFO);
}
- Checks::exit_success(VCPKG_LINE_INFO);
+
+ System::println(System::Color::error, "Error: unknown topic %s", topic);
+ help_topics(paths);
+ Checks::exit_fail(VCPKG_LINE_INFO);
}
}
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
index 26f729a57..20ffd3164 100644
--- a/toolsrc/src/vcpkg/install.cpp
+++ b/toolsrc/src/vcpkg/install.cpp
@@ -70,9 +70,8 @@ namespace vcpkg::Install
}
const std::string filename = file.filename().generic_string();
- if (fs::is_regular_file(status) &&
- (Strings::case_insensitive_ascii_compare(filename.c_str(), "CONTROL") ||
- Strings::case_insensitive_ascii_compare(filename.c_str(), "BUILD_INFO")))
+ if (fs::is_regular_file(status) && (Strings::case_insensitive_ascii_equals(filename.c_str(), "CONTROL") ||
+ Strings::case_insensitive_ascii_equals(filename.c_str(), "BUILD_INFO")))
{
// Do not copy the control file
continue;
@@ -145,7 +144,7 @@ namespace vcpkg::Install
continue;
}
- output.insert(output.end(), t.files.begin(), t.files.end());
+ Util::Vectors::concatenate(&output, t.files);
}
std::sort(output.begin(), output.end());
@@ -251,7 +250,6 @@ namespace vcpkg::Install
BuildResult perform_install_plan_action(const VcpkgPaths& paths,
const InstallPlanAction& action,
- const Build::BuildPackageOptions& build_package_options,
StatusParagraphs& status_db)
{
const InstallPlanType& plan_type = action.plan_type;
@@ -260,7 +258,7 @@ namespace vcpkg::Install
GlobalState::feature_packages ? action.displayname() : display_name;
const bool is_user_requested = action.request_type == RequestType::USER_REQUESTED;
- const bool use_head_version = to_bool(build_package_options.use_head_version);
+ const bool use_head_version = to_bool(action.build_options.use_head_version);
if (plan_type == InstallPlanType::ALREADY_INSTALLED)
{
@@ -286,7 +284,7 @@ namespace vcpkg::Install
*action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO),
action.spec.triplet(),
paths.port_dir(action.spec),
- build_package_options,
+ action.build_options,
action.feature_list};
return Build::build_package(paths, build_config, status_db);
}
@@ -296,7 +294,7 @@ namespace vcpkg::Install
action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO),
action.spec.triplet(),
paths.port_dir(action.spec),
- build_package_options};
+ action.build_options};
return Build::build_package(paths, build_config, status_db);
}
}();
@@ -343,16 +341,23 @@ namespace vcpkg::Install
}
}
+ if (plan_type == InstallPlanType::EXCLUDED)
+ {
+ System::println(System::Color::warning, "Package %s is excluded", display_name);
+ return BuildResult::EXCLUDED;
+ }
+
Checks::unreachable(VCPKG_LINE_INFO);
}
- static void print_plan(const std::vector<AnyAction>& action_plan, bool is_recursive)
+ 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())
@@ -383,6 +388,7 @@ namespace vcpkg::Install
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);
}
}
@@ -398,39 +404,40 @@ namespace vcpkg::Install
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)
{
- const std::string already_string =
- Strings::join("\n", already_installed_plans, [](const InstallPlanAction* p) {
- return to_output_string(p->request_type, p->displayname());
- });
- System::println("The following packages are already installed:\n%s", already_string);
+ System::println("The following packages are already installed:\n%s",
+ actions_to_output_string(already_installed_plans));
}
if (rebuilt_plans.size() > 0)
{
- const std::string rebuilt_string = Strings::join("\n", rebuilt_plans, [](const InstallPlanAction* p) {
- return to_output_string(p->request_type, p->displayname());
- });
- System::println("The following packages will be rebuilt:\n%s", rebuilt_string);
+ System::println("The following packages will be rebuilt:\n%s", actions_to_output_string(rebuilt_plans));
}
if (new_plans.size() > 0)
{
- const std::string new_string = Strings::join("\n", new_plans, [](const InstallPlanAction* p) {
- return to_output_string(p->request_type, p->displayname());
- });
- System::println("The following packages will be built and installed:\n%s", new_string);
+ System::println("The following packages will be built and installed:\n%s",
+ actions_to_output_string(new_plans));
}
if (only_install_plans.size() > 0)
{
- const std::string only_install_string =
- Strings::join("\n", only_install_plans, [](const InstallPlanAction* p) {
- return to_output_string(p->request_type, p->displayname());
- });
- System::println("The following packages will be directly installed:\n%s", only_install_string);
+ System::println("The following packages will be directly installed:\n%s",
+ actions_to_output_string(only_install_plans));
}
if (has_non_user_requested_packages)
@@ -445,15 +452,40 @@ namespace vcpkg::Install
}
}
- void perform_and_exit_ex(const std::vector<AnyAction>& action_plan,
- const Build::BuildPackageOptions& install_plan_options,
- const KeepGoing keep_going,
- const PrintSummary print_summary,
- const VcpkgPaths& paths,
- StatusParagraphs& status_db)
+ void InstallSummary::print() const
{
- std::vector<BuildResult> results;
- std::vector<std::string> timing;
+ System::println("RESULTS");
+
+ for (const SpecSummary& result : this->results)
+ {
+ System::println(" %s: %s: %s", result.spec, Build::to_string(result.result), result.timing);
+ }
+
+ std::map<BuildResult, int> summary;
+ for (const BuildResult& v : Build::BUILD_RESULT_VALUES)
+ {
+ summary[v] = 0;
+ }
+
+ for (const SpecSummary& r : this->results)
+ {
+ summary[r.result]++;
+ }
+
+ System::println("\nSUMMARY");
+ for (const std::pair<const BuildResult, int>& entry : summary)
+ {
+ System::println(" %s: %d", Build::to_string(entry.first), entry.second);
+ }
+ }
+
+ InstallSummary perform(const std::vector<AnyAction>& action_plan,
+ const KeepGoing keep_going,
+ const VcpkgPaths& paths,
+ StatusParagraphs& status_db)
+ {
+ std::vector<SpecSummary> results;
+
const auto timer = Chrono::ElapsedTime::create_started();
size_t counter = 0;
const size_t package_count = action_plan.size();
@@ -463,23 +495,22 @@ namespace vcpkg::Install
const auto build_timer = Chrono::ElapsedTime::create_started();
counter++;
- const std::string display_name = action.spec().to_string();
+ 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);
- timing.push_back("0");
- results.push_back(BuildResult::NULLVALUE);
+ results.push_back(SpecSummary{spec});
if (const auto install_action = action.install_plan.get())
{
- const BuildResult result =
- perform_install_plan_action(paths, *install_action, install_plan_options, status_db);
+ const BuildResult result = perform_install_plan_action(paths, *install_action, status_db);
if (result != BuildResult::SUCCEEDED && keep_going == KeepGoing::NO)
{
System::println(Build::create_user_troubleshooting_message(install_action->spec));
Checks::exit_fail(VCPKG_LINE_INFO);
}
- results.back() = result;
+ results.back().result = result;
}
else if (const auto remove_action = action.remove_plan.get())
{
@@ -491,38 +522,11 @@ namespace vcpkg::Install
Checks::unreachable(VCPKG_LINE_INFO);
}
- timing.back() = build_timer.to_string();
+ results.back().timing = build_timer.to_string();
System::println("Elapsed time for package %s: %s", display_name, build_timer.to_string());
}
- System::println("Total time taken: %s", timer.to_string());
-
- if (print_summary == PrintSummary::YES)
- {
- for (size_t i = 0; i < results.size(); i++)
- {
- System::println("%s: %s: %s", action_plan[i].spec(), Build::to_string(results[i]), timing[i]);
- }
-
- std::map<BuildResult, int> summary;
- for (const BuildResult& v : Build::BUILD_RESULT_VALUES)
- {
- summary[v] = 0;
- }
-
- for (const BuildResult& r : results)
- {
- summary[r]++;
- }
-
- System::println("\n\nSUMMARY");
- for (const std::pair<const BuildResult, int>& entry : summary)
- {
- System::println(" %s: %d", Build::to_string(entry.first), entry.second);
- }
- }
-
- Checks::exit_success(VCPKG_LINE_INFO);
+ return InstallSummary{results, timer.to_string()};
}
static const std::string OPTION_DRY_RUN = "--dry-run";
@@ -531,16 +535,16 @@ namespace vcpkg::Install
static const std::string OPTION_RECURSE = "--recurse";
static const std::string OPTION_KEEP_GOING = "--keep-going";
- static const std::array<std::string, 5> INSTALL_SWITCHES = {
- OPTION_DRY_RUN,
- OPTION_USE_HEAD_VERSION,
- OPTION_NO_DOWNLOADS,
- OPTION_RECURSE,
- OPTION_KEEP_GOING,
- };
+ static const std::array<CommandSwitch, 5> INSTALL_SWITCHES = {{
+ {OPTION_DRY_RUN, "Do not actually build or install"},
+ {OPTION_USE_HEAD_VERSION, "Install the libraries on the command line using the latest upstream sources"},
+ {OPTION_NO_DOWNLOADS, "Do not download new sources"},
+ {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 std::vector<std::string> valid_arguments(const VcpkgPaths& paths)
+ std::vector<std::string> get_all_port_names(const VcpkgPaths& paths)
{
auto sources_and_errors = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports);
@@ -549,22 +553,20 @@ namespace vcpkg::Install
}
const CommandStructure COMMAND_STRUCTURE = {
- "install zlib zlib:x64-windows curl boost",
+ Help::create_example_string("install zlib zlib:x64-windows curl boost"),
1,
SIZE_MAX,
- INSTALL_SWITCHES,
- INSTALL_SETTINGS,
- &valid_arguments,
+ {INSTALL_SWITCHES, {}},
+ &get_all_port_names,
};
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
// input sanitization
- static const std::string EXAMPLE = Help::create_example_string("install zlib zlib:x64-windows curl boost");
- args.check_min_arg_count(1, EXAMPLE);
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
const std::vector<FullPackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_full_package_spec(arg, default_triplet, EXAMPLE);
+ return Input::check_and_get_full_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text);
});
for (auto&& spec : specs)
@@ -577,14 +579,11 @@ namespace vcpkg::Install
}
}
- const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments(
- {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS, OPTION_RECURSE, OPTION_KEEP_GOING});
- const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend();
- const bool use_head_version = options.find(OPTION_USE_HEAD_VERSION) != options.cend();
- const bool no_downloads = options.find(OPTION_NO_DOWNLOADS) != options.cend();
- const bool is_recursive = options.find(OPTION_RECURSE) != options.cend();
- const KeepGoing keep_going = to_keep_going(options.find(OPTION_KEEP_GOING) != options.cend());
- const PrintSummary print_summary = to_print_summary(keep_going == KeepGoing::YES);
+ const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN);
+ const bool use_head_version = Util::Sets::contains(options.switches, (OPTION_USE_HEAD_VERSION));
+ const bool no_downloads = Util::Sets::contains(options.switches, (OPTION_NO_DOWNLOADS));
+ const bool is_recursive = Util::Sets::contains(options.switches, (OPTION_RECURSE));
+ const KeepGoing keep_going = to_keep_going(Util::Sets::contains(options.switches, OPTION_KEEP_GOING));
// create the plan
StatusParagraphs status_db = database_load_check(paths);
@@ -592,11 +591,12 @@ namespace vcpkg::Install
const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version),
Build::to_allow_downloads(!no_downloads)};
+ // 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)
{
- std::unordered_map<std::string, SourceControlFile> scf_map;
auto all_ports = Paragraphs::load_all_ports(paths.get_filesystem(), paths.ports);
for (auto&& port : all_ports)
{
@@ -614,6 +614,16 @@ namespace vcpkg::Install
install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); });
}
+ for (auto&& action : action_plan)
+ {
+ if (auto p_install = action.install_plan.get())
+ {
+ p_install->build_options = install_plan_options;
+ if (p_install->request_type != RequestType::USER_REQUESTED)
+ p_install->build_options.use_head_version = Build::UseHeadVersion::NO;
+ }
+ }
+
// install plan will be empty if it is already installed - need to change this at status paragraph part
Checks::check_exit(VCPKG_LINE_INFO, !action_plan.empty(), "Install plan cannot be empty");
@@ -635,8 +645,17 @@ namespace vcpkg::Install
Checks::exit_success(VCPKG_LINE_INFO);
}
- perform_and_exit_ex(action_plan, install_plan_options, keep_going, print_summary, paths, status_db);
+ const InstallSummary summary = perform(action_plan, keep_going, paths, status_db);
+
+ System::println("\nTotal elapsed time: %s", summary.total_elapsed_time);
+
+ if (keep_going == KeepGoing::YES)
+ {
+ summary.print();
+ }
Checks::exit_success(VCPKG_LINE_INFO);
}
+
+ SpecSummary::SpecSummary(const PackageSpec& spec) : spec(spec), result(BuildResult::NULLVALUE), timing("0") {}
}
diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp
index 84c1ee208..8f2575886 100644
--- a/toolsrc/src/vcpkg/metrics.cpp
+++ b/toolsrc/src/vcpkg/metrics.cpp
@@ -19,6 +19,7 @@ namespace vcpkg::Metrics
std::array<char, 80> date;
date.fill(0);
+#if defined(_WIN32)
struct _timeb timebuffer;
_ftime_s(&timebuffer);
@@ -26,10 +27,17 @@ namespace vcpkg::Metrics
const int milli = timebuffer.millitm;
const errno_t err = gmtime_s(&newtime, &now);
+
if (err)
{
- return Strings::EMPTY;
+ return "";
}
+#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";
@@ -121,6 +129,7 @@ namespace vcpkg::Metrics
static std::string get_os_version_string()
{
+#if defined(_WIN32)
std::wstring path;
path.resize(MAX_PATH);
const auto n = GetSystemDirectoryW(&path[0], static_cast<UINT>(path.size()));
@@ -128,16 +137,16 @@ namespace vcpkg::Metrics
path += L"\\kernel32.dll";
const auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr);
- if (versz == 0) return Strings::EMPTY;
+ if (versz == 0) return "";
std::vector<char> verbuf;
verbuf.resize(versz);
- if (!GetFileVersionInfoW(path.c_str(), 0, static_cast<DWORD>(verbuf.size()), &verbuf[0])) return Strings::EMPTY;
+ if (!GetFileVersionInfoW(path.c_str(), 0, static_cast<DWORD>(verbuf.size()), &verbuf[0])) return "";
void* rootblock;
UINT rootblocksize;
- if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return Strings::EMPTY;
+ if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return "";
auto rootblock_ffi = static_cast<VS_FIXEDFILEINFO*>(rootblock);
@@ -145,6 +154,9 @@ namespace vcpkg::Metrics
static_cast<int>(HIWORD(rootblock_ffi->dwProductVersionMS)),
static_cast<int>(LOWORD(rootblock_ffi->dwProductVersionMS)),
static_cast<int>(HIWORD(rootblock_ffi->dwProductVersionLS)));
+#else
+ return "unknown";
+#endif
}
struct MetricMessage
@@ -221,11 +233,15 @@ namespace vcpkg::Metrics
bool get_compiled_metrics_enabled() { return DISABLE_METRICS == 0; }
- std::wstring get_SQM_user()
+ std::string get_SQM_user()
{
+#if defined(_WIN32)
auto hkcu_sqmclient =
- System::get_registry_string(HKEY_CURRENT_USER, LR"(Software\Microsoft\SQMClient)", L"UserId");
- return hkcu_sqmclient.value_or(L"{}");
+ System::get_registry_string(HKEY_CURRENT_USER, R"(Software\Microsoft\SQMClient)", "UserId");
+ return hkcu_sqmclient.value_or("{}");
+#else
+ return "{}";
+#endif
}
void Metrics::set_user_information(const std::string& user_id, const std::string& first_use_time)
@@ -246,17 +262,6 @@ namespace vcpkg::Metrics
void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.track_metric(name, value); }
- void Metrics::track_property(const std::string& name, const std::wstring& value)
- {
- // Note: this is not valid UTF-16 -> UTF-8, it just yields a close enough approximation for our purposes.
- std::string converted_value;
- converted_value.resize(value.size());
- std::transform(
- value.begin(), value.end(), converted_value.begin(), [](wchar_t ch) { return static_cast<char>(ch); });
-
- g_metricmessage.track_property(name, converted_value);
- }
-
void Metrics::track_property(const std::string& name, const std::string& value)
{
g_metricmessage.track_property(name, value);
@@ -264,6 +269,7 @@ namespace vcpkg::Metrics
void Metrics::upload(const std::string& payload)
{
+#if defined(_WIN32)
HINTERNET connect = nullptr, request = nullptr;
BOOL results = FALSE;
@@ -344,18 +350,12 @@ namespace vcpkg::Metrics
if (request) WinHttpCloseHandle(request);
if (connect) WinHttpCloseHandle(connect);
if (session) WinHttpCloseHandle(session);
- }
-
- static fs::path get_bindir()
- {
- wchar_t buf[_MAX_PATH];
- const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH);
- if (bytes == 0) std::abort();
- return fs::path(buf, buf + bytes);
+#endif
}
void Metrics::flush()
{
+#if defined(_WIN32)
const std::string payload = g_metricmessage.format_event_data_template();
if (g_should_print_metrics) std::cerr << payload << "\n";
if (!g_should_send_metrics) return;
@@ -373,14 +373,14 @@ namespace vcpkg::Metrics
if (true)
{
const fs::path exe_path = [&fs]() -> fs::path {
- auto vcpkgdir = get_bindir().parent_path();
+ auto vcpkgdir = System::get_exe_path_of_current_process().parent_path();
auto path = vcpkgdir / "vcpkgmetricsuploader.exe";
if (fs.exists(path)) return path;
path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe";
if (fs.exists(path)) return path;
- return Strings::WEMPTY;
+ return "";
}();
std::error_code ec;
@@ -391,8 +391,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::wstring cmd_line =
- Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native());
+ const std::string cmd_line =
+ Strings::format("start %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 01a09618d..eeb9981af 100644
--- a/toolsrc/src/vcpkg/packagespec.cpp
+++ b/toolsrc/src/vcpkg/packagespec.cpp
@@ -38,7 +38,7 @@ namespace vcpkg
for (auto&& feature : spec->features)
f_specs.push_back(FeatureSpec{pspec, feature});
- if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, Strings::EMPTY});
+ if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, ""});
}
else
{
@@ -56,7 +56,7 @@ namespace vcpkg
std::vector<FeatureSpec> ret;
for (auto&& spec : specs)
{
- ret.emplace_back(spec.package_spec, Strings::EMPTY);
+ ret.emplace_back(spec.package_spec, "");
for (auto&& feature : spec.features)
ret.emplace_back(spec.package_spec, feature);
}
@@ -92,6 +92,14 @@ namespace vcpkg
return p;
}
+ 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);
+ });
+ }
+
const std::string& PackageSpec::name() const { return this->m_name; }
const Triplet& PackageSpec::triplet() const { return this->m_triplet; }
diff --git a/toolsrc/src/vcpkg/parse.cpp b/toolsrc/src/vcpkg/parse.cpp
index 116a7f5c8..c2670f561 100644
--- a/toolsrc/src/vcpkg/parse.cpp
+++ b/toolsrc/src/vcpkg/parse.cpp
@@ -31,7 +31,7 @@ namespace vcpkg::Parse
}
std::string ParagraphParser::optional_field(const std::string& fieldname) const
{
- return remove_field(&fields, fieldname).value_or(Strings::EMPTY);
+ return remove_field(&fields, fieldname).value_or("");
}
std::unique_ptr<ParseControlErrorInfo> ParagraphParser::error_info(const std::string& name) const
{
diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp
index 548093c6f..cc0ad0dc4 100644
--- a/toolsrc/src/vcpkg/postbuildlint.cpp
+++ b/toolsrc/src/vcpkg/postbuildlint.cpp
@@ -298,13 +298,10 @@ namespace vcpkg::PostBuildLint
std::vector<fs::path> dlls_with_no_exports;
for (const fs::path& dll : dlls)
{
- const std::wstring cmd_line =
- Strings::wformat(LR"("%s" /exports "%s")", dumpbin_exe.native(), dll.native());
+ const std::string cmd_line =
+ Strings::format(R"("%s" /exports "%s")", dumpbin_exe.u8string(), dll.u8string());
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",
- Strings::to_utf8(cmd_line));
+ Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line);
if (ec_data.output.find("ordinal hint RVA name") == std::string::npos)
{
@@ -335,13 +332,10 @@ namespace vcpkg::PostBuildLint
std::vector<fs::path> dlls_with_improper_uwp_bit;
for (const fs::path& dll : dlls)
{
- const std::wstring cmd_line =
- Strings::wformat(LR"("%s" /headers "%s")", dumpbin_exe.native(), dll.native());
+ const std::string cmd_line =
+ Strings::format(R"("%s" /headers "%s")", dumpbin_exe.u8string(), dll.u8string());
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",
- Strings::to_utf8(cmd_line));
+ Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line);
if (ec_data.output.find("App Container") == std::string::npos)
{
@@ -613,13 +607,10 @@ namespace vcpkg::PostBuildLint
for (const fs::path& lib : libs)
{
- const std::wstring cmd_line =
- Strings::wformat(LR"("%s" /directives "%s")", dumpbin_exe.native(), lib.native());
+ const std::string cmd_line =
+ Strings::format(R"("%s" /directives "%s")", dumpbin_exe.u8string(), lib.u8string());
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",
- Strings::to_utf8(cmd_line));
+ Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line);
for (const BuildType& bad_build_type : bad_build_types)
{
@@ -670,13 +661,9 @@ namespace vcpkg::PostBuildLint
for (const fs::path& dll : dlls)
{
- const std::wstring cmd_line =
- Strings::wformat(LR"("%s" /dependents "%s")", dumpbin_exe.native(), dll.native());
+ const auto cmd_line = Strings::format(R"("%s" /dependents "%s")", dumpbin_exe.u8string(), dll.u8string());
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",
- Strings::to_utf8(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(pre_build_info.platform_toolset))
{
@@ -711,8 +698,8 @@ namespace vcpkg::PostBuildLint
std::vector<fs::path> misplaced_files = fs.get_files_non_recursive(dir);
Util::unstable_keep_if(misplaced_files, [&fs](const fs::path& path) {
const std::string filename = path.filename().generic_string();
- if (Strings::case_insensitive_ascii_compare(filename.c_str(), "CONTROL") ||
- Strings::case_insensitive_ascii_compare(filename.c_str(), "BUILD_INFO"))
+ if (Strings::case_insensitive_ascii_equals(filename.c_str(), "CONTROL") ||
+ Strings::case_insensitive_ascii_equals(filename.c_str(), "BUILD_INFO"))
return false;
return !fs.is_directory(path);
});
diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp
index 04ddba1e4..7f40fb16e 100644
--- a/toolsrc/src/vcpkg/remove.cpp
+++ b/toolsrc/src/vcpkg/remove.cpp
@@ -21,7 +21,7 @@ namespace vcpkg::Remove
{
auto& fs = paths.get_filesystem();
auto spghs = status_db->find_all(spec.name(), spec.triplet());
- const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), Strings::EMPTY);
+ const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), "");
for (auto&& spgh : spghs)
{
@@ -169,14 +169,13 @@ namespace vcpkg::Remove
static const std::string OPTION_DRY_RUN = "--dry-run";
static const std::string OPTION_OUTDATED = "--outdated";
- static const std::array<std::string, 5> REMOVE_SWITCHES = {
- OPTION_PURGE,
- OPTION_NO_PURGE,
- OPTION_RECURSE,
- OPTION_DRY_RUN,
- OPTION_OUTDATED,
- };
- static const std::array<std::string, 0> REMOVE_SETTINGS;
+ static const std::array<CommandSwitch, 5> SWITCHES = {{
+ {OPTION_PURGE, "Remove the cached copy of the package (default)"},
+ {OPTION_NO_PURGE, "Do not remove the cached copy of the package"},
+ {OPTION_RECURSE, "Allow removal of packages not explicitly specified on the command line"},
+ {OPTION_DRY_RUN, "Print the packages to be removed, but do not remove them"},
+ {OPTION_OUTDATED, "Select all packages with versions that do not match the portfiles"},
+ }};
static std::vector<std::string> valid_arguments(const VcpkgPaths& paths)
{
@@ -187,25 +186,26 @@ namespace vcpkg::Remove
}
const CommandStructure COMMAND_STRUCTURE = {
- "remove zlib zlib:x64-windows curl boost",
- 1,
+ Help::create_example_string("remove zlib zlib:x64-windows curl boost"),
+ 0,
SIZE_MAX,
- REMOVE_SWITCHES,
- REMOVE_SETTINGS,
+ {SWITCHES, {}},
&valid_arguments,
};
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
- static const std::string EXAMPLE = Help::create_example_string("remove zlib zlib:x64-windows curl boost");
- const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments(
- {OPTION_PURGE, OPTION_NO_PURGE, OPTION_RECURSE, OPTION_DRY_RUN, OPTION_OUTDATED});
+ const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE);
StatusParagraphs status_db = database_load_check(paths);
std::vector<PackageSpec> specs;
- if (options.find(OPTION_OUTDATED) != options.cend())
+ if (Util::Sets::contains(options.switches, OPTION_OUTDATED))
{
- args.check_exact_arg_count(0, EXAMPLE);
+ if (args.command_arguments.size() != 0)
+ {
+ 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(paths, status_db),
[](auto&& outdated) { return outdated.spec; });
@@ -217,26 +217,30 @@ namespace vcpkg::Remove
}
else
{
- args.check_min_arg_count(1, EXAMPLE);
+ if (args.command_arguments.size() < 1)
+ {
+ System::println(System::Color::error, "Error: 'remove' accepts either libraries or '--outdated'");
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_package_spec(arg, default_triplet, EXAMPLE);
+ return Input::check_and_get_package_spec(arg, default_triplet, COMMAND_STRUCTURE.example_text);
});
for (auto&& spec : specs)
Input::check_triplet(spec.triplet(), paths);
}
- const bool no_purge_was_passed = options.find(OPTION_NO_PURGE) != options.end();
- const bool purge_was_passed = options.find(OPTION_PURGE) != options.end();
+ const bool no_purge_was_passed = Util::Sets::contains(options.switches, OPTION_NO_PURGE);
+ const bool purge_was_passed = Util::Sets::contains(options.switches, OPTION_PURGE);
if (purge_was_passed && no_purge_was_passed)
{
System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge.");
- System::print(EXAMPLE);
+ System::print(COMMAND_STRUCTURE.example_text);
Checks::exit_fail(VCPKG_LINE_INFO);
}
const Purge purge = to_purge(purge_was_passed || !no_purge_was_passed);
- const bool is_recursive = options.find(OPTION_RECURSE) != options.cend();
- const bool dry_run = options.find(OPTION_DRY_RUN) != options.cend();
+ const bool is_recursive = Util::Sets::contains(options.switches, OPTION_RECURSE);
+ const bool dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN);
const std::vector<RemovePlanAction> remove_plan = Dependencies::create_remove_plan(specs, status_db);
Checks::check_exit(VCPKG_LINE_INFO, !remove_plan.empty(), "Remove plan cannot be empty");
diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp
index d766dcb72..2a9480538 100644
--- a/toolsrc/src/vcpkg/sourceparagraph.cpp
+++ b/toolsrc/src/vcpkg/sourceparagraph.cpp
@@ -178,11 +178,11 @@ namespace vcpkg
return Strings::format("%s[%s]", this->depend.name, features);
}
- std::vector<Dependency> vcpkg::expand_qualified_dependencies(const std::vector<std::string>& depends)
+ std::vector<Dependency> expand_qualified_dependencies(const std::vector<std::string>& depends)
{
return Util::fmap(depends, [&](const std::string& depend_string) -> Dependency {
auto pos = depend_string.find(' ');
- if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, Strings::EMPTY);
+ if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, "");
// expect of the form "\w+ \[\w+\]"
Dependency dep;
@@ -190,7 +190,7 @@ namespace vcpkg
if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')')
{
// Error, but for now just slurp the entire string.
- return Dependency::parse_dependency(depend_string, Strings::EMPTY);
+ return Dependency::parse_dependency(depend_string, "");
}
dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3);
return dep;
diff --git a/toolsrc/src/vcpkg/statusparagraphs.cpp b/toolsrc/src/vcpkg/statusparagraphs.cpp
index 647ed6d3f..d4afc0427 100644
--- a/toolsrc/src/vcpkg/statusparagraphs.cpp
+++ b/toolsrc/src/vcpkg/statusparagraphs.cpp
@@ -10,22 +10,6 @@ namespace vcpkg
StatusParagraphs::StatusParagraphs(std::vector<std::unique_ptr<StatusParagraph>>&& ps)
: paragraphs(std::move(ps)){};
- StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name, const Triplet& triplet) const
- {
- return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh) {
- const PackageSpec& spec = pgh->package.spec;
- return spec.name() == name && spec.triplet() == triplet;
- });
- }
-
- StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, const Triplet& triplet)
- {
- return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh) {
- const PackageSpec& spec = pgh->package.spec;
- return spec.name() == name && spec.triplet() == triplet;
- });
- }
-
std::vector<std::unique_ptr<StatusParagraph>*> StatusParagraphs::find_all(const std::string& name,
const Triplet& triplet)
{
@@ -50,6 +34,16 @@ namespace vcpkg
});
}
+ StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name,
+ const Triplet& triplet,
+ const std::string& feature) const
+ {
+ return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh) {
+ const PackageSpec& spec = pgh->package.spec;
+ return spec.name() == name && spec.triplet() == triplet && pgh->package.feature == feature;
+ });
+ }
+
StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name,
const Triplet& triplet) const
{
diff --git a/toolsrc/src/vcpkg/triplet.cpp b/toolsrc/src/vcpkg/triplet.cpp
index 8a84ee2b2..4cba1523d 100644
--- a/toolsrc/src/vcpkg/triplet.cpp
+++ b/toolsrc/src/vcpkg/triplet.cpp
@@ -18,11 +18,14 @@ namespace vcpkg
const TripletInstance Triplet::DEFAULT_INSTANCE({});
}
-template<>
-struct std::hash<vcpkg::TripletInstance>
+namespace std
{
- size_t operator()(const vcpkg::TripletInstance& t) const { return t.hash; }
-};
+ template<>
+ struct hash<vcpkg::TripletInstance>
+ {
+ size_t operator()(const vcpkg::TripletInstance& t) const { return t.hash; }
+ };
+}
namespace vcpkg
{
@@ -41,9 +44,6 @@ namespace vcpkg
Triplet Triplet::from_canonical_name(const std::string& triplet_as_string)
{
std::string s(Strings::ascii_to_lowercase(triplet_as_string));
- const auto it = std::find(s.cbegin(), s.cend(), '-');
- Checks::check_exit(VCPKG_LINE_INFO, it != s.cend(), "Invalid triplet: %s", triplet_as_string);
-
const auto p = g_triplet_instances.emplace(std::move(s));
return &*p.first;
}
diff --git a/toolsrc/src/vcpkg/update.cpp b/toolsrc/src/vcpkg/update.cpp
index 168949bc1..61a3f89c5 100644
--- a/toolsrc/src/vcpkg/update.cpp
+++ b/toolsrc/src/vcpkg/update.cpp
@@ -38,10 +38,17 @@ namespace vcpkg::Update
return output;
}
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string("update"),
+ 0,
+ 0,
+ {},
+ nullptr,
+ };
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- args.check_exact_arg_count(0);
- args.check_and_get_optional_command_arguments({});
+ args.parse_arguments(COMMAND_STRUCTURE);
System::println("Using local portfile versions. To update the local portfiles, use `git pull`.");
const StatusParagraphs status_db = database_load_check(paths);
diff --git a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
index 522961693..671a89892 100644
--- a/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
+++ b/toolsrc/src/vcpkg/vcpkgcmdarguments.cpp
@@ -45,12 +45,17 @@ namespace vcpkg
option_field = new_setting;
}
- VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const int argc, const wchar_t* const* const argv)
+ VcpkgCmdArguments VcpkgCmdArguments::create_from_command_line(const int argc,
+ const CommandLineCharType* const* const argv)
{
std::vector<std::string> v;
for (int i = 1; i < argc; ++i)
{
+#if defined(_WIN32)
v.push_back(Strings::to_utf8(argv[i]));
+#else
+ v.push_back(argv[i]);
+#endif
}
return VcpkgCmdArguments::create_from_arg_sequence(v.data(), v.data() + v.size());
@@ -150,46 +155,83 @@ namespace vcpkg
return args;
}
- ParsedArguments VcpkgCmdArguments::check_and_get_optional_command_arguments(
- const std::vector<std::string>& valid_switches, const std::vector<std::string>& valid_settings) const
+ ParsedArguments VcpkgCmdArguments::parse_arguments(const CommandStructure& command_structure) const
{
bool failed = false;
ParsedArguments output;
+ const size_t actual_arg_count = command_arguments.size();
+
+ if (command_structure.minimum_arity == command_structure.maximum_arity)
+ {
+ if (actual_arg_count != command_structure.minimum_arity)
+ {
+ System::println(System::Color::error,
+ "Error: '%s' requires %u arguments, but %u were provided.",
+ this->command,
+ command_structure.minimum_arity,
+ actual_arg_count);
+ failed = true;
+ }
+ }
+ else
+ {
+ if (actual_arg_count < command_structure.minimum_arity)
+ {
+ System::println(System::Color::error,
+ "Error: '%s' requires at least %u arguments, but %u were provided",
+ this->command,
+ command_structure.minimum_arity,
+ actual_arg_count);
+ failed = true;
+ }
+ if (actual_arg_count > command_structure.maximum_arity)
+ {
+ System::println(System::Color::error,
+ "Error: '%s' requires at most %u arguments, but %u were provided",
+ this->command,
+ command_structure.maximum_arity,
+ actual_arg_count);
+ failed = true;
+ }
+ }
+
auto options_copy = this->optional_command_arguments;
- for (const std::string& option : valid_switches)
+ for (auto&& option : command_structure.options.switches)
{
- const auto it = options_copy.find(option);
+ const auto it = options_copy.find(option.name);
if (it != options_copy.end())
{
if (it->second.has_value())
{
// Having a string value indicates it was passed like '--a=xyz'
- System::println(System::Color::error, "The option '%s' does not accept an argument.", option);
+ System::println(
+ System::Color::error, "Error: The option '%s' does not accept an argument.", option.name);
failed = true;
}
else
{
- output.switches.insert(option);
+ output.switches.insert(option.name);
options_copy.erase(it);
}
}
}
- for (const std::string& option : valid_settings)
+ for (auto&& option : command_structure.options.settings)
{
- const auto it = options_copy.find(option);
+ const auto it = options_copy.find(option.name);
if (it != options_copy.end())
{
if (!it->second.has_value())
{
// Not having a string value indicates it was passed like '--a'
- System::println(System::Color::error, "The option '%s' must be passed an argument.", option);
+ System::println(
+ System::Color::error, "Error: The option '%s' must be passed an argument.", option.name);
failed = true;
}
else
{
- output.settings.emplace(option, it->second.value_or_exit(VCPKG_LINE_INFO));
+ output.settings.emplace(option.name, it->second.value_or_exit(VCPKG_LINE_INFO));
options_copy.erase(it);
}
}
@@ -202,83 +244,38 @@ namespace vcpkg
{
System::println(" %s", option.first);
}
- System::println("\nValid options are:", this->command);
- for (auto&& option : valid_switches)
- {
- System::println(" %s", option);
- }
- for (auto&& option : valid_settings)
- {
- System::println(" %s=...", option);
- }
- System::println(" --triplet <t>");
- System::println(" --vcpkg-root <path>");
+ System::println();
+ failed = true;
+ }
+ if (failed)
+ {
+ display_usage(command_structure);
Checks::exit_fail(VCPKG_LINE_INFO);
}
- if (failed) Checks::exit_fail(VCPKG_LINE_INFO);
return output;
}
- void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count) const
+ void display_usage(const CommandStructure& command_structure)
{
- return check_max_arg_count(expected_arg_count, Strings::EMPTY);
- }
-
- void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count) const
- {
- return check_min_arg_count(expected_arg_count, Strings::EMPTY);
- }
-
- void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count) const
- {
- return check_exact_arg_count(expected_arg_count, Strings::EMPTY);
- }
-
- void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const
- {
- const size_t actual_arg_count = command_arguments.size();
- if (actual_arg_count > expected_arg_count)
+ if (!command_structure.example_text.empty())
{
- System::println(System::Color::error,
- "Error: `%s` requires at most %u arguments, but %u were provided",
- this->command,
- expected_arg_count,
- actual_arg_count);
- System::print(example_text);
- Checks::exit_fail(VCPKG_LINE_INFO);
+ System::println("%s", command_structure.example_text);
}
- }
- void VcpkgCmdArguments::check_min_arg_count(const size_t expected_arg_count, const std::string& example_text) const
- {
- const size_t actual_arg_count = command_arguments.size();
- if (actual_arg_count < expected_arg_count)
+ System::println("Options:");
+ for (auto&& option : command_structure.options.switches)
{
- System::println(System::Color::error,
- "Error: `%s` requires at least %u arguments, but %u were provided",
- this->command,
- expected_arg_count,
- actual_arg_count);
- System::print(example_text);
- Checks::exit_fail(VCPKG_LINE_INFO);
+ System::println(" %-40s %s", option.name, option.short_help_text);
}
- }
-
- void VcpkgCmdArguments::check_exact_arg_count(const size_t expected_arg_count,
- const std::string& example_text) const
- {
- const size_t actual_arg_count = command_arguments.size();
- if (actual_arg_count != expected_arg_count)
+ for (auto&& option : command_structure.options.settings)
{
- System::println(System::Color::error,
- "Error: `%s` requires %u arguments, but %u were provided",
- this->command,
- expected_arg_count,
- actual_arg_count);
- System::print(example_text);
- Checks::exit_fail(VCPKG_LINE_INFO);
+ System::println(" %-40s %s", (option.name + "=..."), option.short_help_text);
}
+ System::println(" %-40s %s", "--triplet <t>", "Set the default triplet for unqualified packages");
+ System::println(" %-40s %s",
+ "--vcpkg-root <path>",
+ "Specify the vcpkg directory to use instead of current directory or tool directory");
}
}
diff --git a/toolsrc/src/vcpkg/vcpkglib.cpp b/toolsrc/src/vcpkg/vcpkglib.cpp
index 23c774210..38b130f6f 100644
--- a/toolsrc/src/vcpkg/vcpkglib.cpp
+++ b/toolsrc/src/vcpkg/vcpkglib.cpp
@@ -212,30 +212,26 @@ namespace vcpkg
return installed_files;
}
- CMakeVariable::CMakeVariable(const CWStringView varname, const wchar_t* varvalue)
- : s(Strings::wformat(LR"("-D%s=%s")", varname, varvalue))
+ CMakeVariable::CMakeVariable(const CStringView varname, const char* varvalue)
+ : s(Strings::format(R"("-D%s=%s")", varname, varvalue))
{
}
- CMakeVariable::CMakeVariable(const CWStringView varname, const std::string& varvalue)
- : CMakeVariable(varname, Strings::to_utf16(varvalue).c_str())
- {
- }
- CMakeVariable::CMakeVariable(const CWStringView varname, const std::wstring& varvalue)
+ CMakeVariable::CMakeVariable(const CStringView varname, const std::string& varvalue)
: CMakeVariable(varname, varvalue.c_str())
{
}
- CMakeVariable::CMakeVariable(const CWStringView varname, const fs::path& path)
- : CMakeVariable(varname, path.generic_wstring())
+ CMakeVariable::CMakeVariable(const CStringView varname, const fs::path& path)
+ : CMakeVariable(varname, path.generic_u8string())
{
}
- std::wstring make_cmake_cmd(const fs::path& cmake_exe,
- const fs::path& cmake_script,
- const std::vector<CMakeVariable>& pass_variables)
+ std::string make_cmake_cmd(const fs::path& cmake_exe,
+ const fs::path& cmake_script,
+ const std::vector<CMakeVariable>& pass_variables)
{
- const std::wstring cmd_cmake_pass_variables = Strings::join(L" ", pass_variables, [](auto&& v) { return v.s; });
- return Strings::wformat(
- LR"("%s" %s -P "%s")", cmake_exe.native(), cmd_cmake_pass_variables, cmake_script.generic_wstring());
+ 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)
diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp
index b6ec2cb52..a7012623d 100644
--- a/toolsrc/src/vcpkg/vcpkgpaths.cpp
+++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp
@@ -10,16 +10,16 @@
namespace vcpkg
{
- static constexpr CWStringView V_120 = L"v120";
- static constexpr CWStringView V_140 = L"v140";
- static constexpr CWStringView V_141 = L"v141";
+ static constexpr CStringView V_120 = "v120";
+ static constexpr CStringView V_140 = "v140";
+ static constexpr CStringView V_141 = "v141";
- static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd,
+ static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd,
const std::array<int, 3>& expected_version)
{
static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###");
- const auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd));
+ const auto rc = System::cmd_execute_and_capture_output(Strings::format(R"(%s)", version_cmd));
if (rc.exit_code != 0)
{
return false;
@@ -46,11 +46,11 @@ namespace vcpkg
}
static Optional<fs::path> find_if_has_equal_or_greater_version(const std::vector<fs::path>& candidate_paths,
- const std::wstring& version_check_arguments,
+ const std::string& version_check_arguments,
const std::array<int, 3>& expected_version)
{
auto it = Util::find_if(candidate_paths, [&](const fs::path& p) {
- const std::wstring cmd = Strings::wformat(LR"("%s" %s)", p.native(), version_check_arguments);
+ const std::string cmd = Strings::format(R"("%s" %s)", p.u8string(), version_check_arguments);
return exists_and_has_equal_or_greater_version(cmd, expected_version);
});
@@ -62,38 +62,44 @@ namespace vcpkg
return nullopt;
}
+ static std::vector<std::string> keep_data_lines(const std::string& data_blob)
+ {
+ static const std::regex DATA_LINE_REGEX(R"(<sol>::(.+?)(?=::<eol>))");
+
+ std::vector<std::string> data_lines;
+
+ const std::sregex_iterator it(data_blob.cbegin(), data_blob.cend(), DATA_LINE_REGEX);
+ const std::sregex_iterator end;
+ for (std::sregex_iterator i = it; i != end; ++i)
+ {
+ const std::smatch match = *i;
+ data_lines.push_back(match[1].str());
+ }
+
+ return data_lines;
+ }
+
static fs::path fetch_dependency(const fs::path& scripts_folder,
- const std::wstring& tool_name,
+ const std::string& tool_name,
const fs::path& expected_downloaded_path,
const std::array<int, 3>& version)
{
- const std::string tool_name_utf8 = Strings::to_utf8(tool_name);
const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]);
System::println("A suitable version of %s was not found (required v%s). Downloading portable %s v%s...",
- tool_name_utf8,
+ tool_name,
version_as_string,
- tool_name_utf8,
+ tool_name,
version_as_string);
const fs::path script = scripts_folder / "fetchDependency.ps1";
- const auto install_cmd =
- System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name));
- const System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd);
- if (rc.exit_code)
- {
- System::println(System::Color::error,
- "Launching powershell failed or was denied when trying to fetch %s version %s.\n"
- "(No sufficient installed version was found)",
- tool_name_utf8,
- version_as_string);
- {
- auto locked_metrics = Metrics::g_metrics.lock();
- locked_metrics->track_property("error", "powershell install failed");
- locked_metrics->track_property("dependency", tool_name);
- }
- Checks::exit_with_code(VCPKG_LINE_INFO, rc.exit_code);
- }
+ 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 fs::path actual_downloaded_path = Strings::trimmed(rc.output);
+ const std::vector<std::string> dependency_path = keep_data_lines(output);
+ Checks::check_exit(
+ VCPKG_LINE_INFO, dependency_path.size() == 1, "Expected dependency path, but got %s", output);
+
+ const fs::path actual_downloaded_path = Strings::trim(std::string{dependency_path.at(0)});
std::error_code ec;
const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec);
Checks::check_exit(VCPKG_LINE_INFO,
@@ -106,17 +112,19 @@ 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, 3};
- static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version";
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 9, 5};
+ static const std::string VERSION_CHECK_ARGUMENTS = "--version";
- const fs::path downloaded_copy = downloads_folder / "cmake-3.9.3-win32-x86" / "bin" / "cmake.exe";
- const std::vector<fs::path> from_path = Files::find_from_PATH(L"cmake");
+ 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;
candidate_paths.push_back(downloaded_copy);
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");
candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin");
+#endif
const Optional<fs::path> path =
find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION);
@@ -125,43 +133,44 @@ namespace vcpkg
return *p;
}
- return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, EXPECTED_VERSION);
+ return fetch_dependency(scripts_folder, "cmake", downloaded_copy, EXPECTED_VERSION);
}
fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path& scripts_folder)
{
- static constexpr std::array<int, 3> EXPECTED_VERSION = {4, 3, 0};
- static const std::wstring VERSION_CHECK_ARGUMENTS = Strings::WEMPTY;
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {4, 4, 0};
- const fs::path downloaded_copy = downloads_folder / "nuget-4.3.0" / "nuget.exe";
- const std::vector<fs::path> from_path = Files::find_from_PATH(L"nuget");
+ const fs::path downloaded_copy = downloads_folder / "nuget-4.4.0" / "nuget.exe";
+ const std::vector<fs::path> from_path = Files::find_from_PATH("nuget");
std::vector<fs::path> candidate_paths;
candidate_paths.push_back(downloaded_copy);
candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
- auto path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION);
+ auto path = find_if_has_equal_or_greater_version(candidate_paths, "", EXPECTED_VERSION);
if (const auto p = path.get())
{
return *p;
}
- return fetch_dependency(scripts_folder, L"nuget", downloaded_copy, EXPECTED_VERSION);
+ return fetch_dependency(scripts_folder, "nuget", downloaded_copy, EXPECTED_VERSION);
}
fs::path get_git_path(const fs::path& downloads_folder, const fs::path& scripts_folder)
{
- static constexpr std::array<int, 3> EXPECTED_VERSION = {2, 14, 1};
- static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version";
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {2, 15, 0};
+ static const std::string VERSION_CHECK_ARGUMENTS = "--version";
- const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe";
- const std::vector<fs::path> from_path = Files::find_from_PATH(L"git");
+ 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");
std::vector<fs::path> candidate_paths;
candidate_paths.push_back(downloaded_copy);
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");
candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe");
+#endif
const Optional<fs::path> path =
find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION);
@@ -170,13 +179,13 @@ namespace vcpkg
return *p;
}
- return fetch_dependency(scripts_folder, L"git", downloaded_copy, EXPECTED_VERSION);
+ return fetch_dependency(scripts_folder, "git", downloaded_copy, EXPECTED_VERSION);
}
static fs::path get_ifw_installerbase_path(const fs::path& downloads_folder, const fs::path& scripts_folder)
{
static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 1, 81};
- static const std::wstring VERSION_CHECK_ARGUMENTS = L"--framework-version";
+ static const std::string VERSION_CHECK_ARGUMENTS = "--framework-version";
const fs::path downloaded_copy =
downloads_folder / "QtInstallerFramework-win-x86" / "bin" / "installerbase.exe";
@@ -184,11 +193,11 @@ namespace vcpkg
std::vector<fs::path> candidate_paths;
candidate_paths.push_back(downloaded_copy);
// TODO: Uncomment later
- // const std::vector<fs::path> from_path = Files::find_from_PATH(L"installerbase");
+ // const std::vector<fs::path> from_path = Files::find_from_PATH("installerbase");
// candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend());
- // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" /
+ // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" /
// "Tools" / "QtInstallerFramework" / "3.1" / "bin" / "installerbase.exe");
- // candidate_paths.push_back(fs::path(System::get_environment_variable(L"HOMEDRIVE").value_or("C:")) / "Qt" /
+ // candidate_paths.push_back(fs::path(System::get_environment_variable("HOMEDRIVE").value_or("C:")) / "Qt" /
// "QtIFW-3.1.0" / "bin" / "installerbase.exe");
const Optional<fs::path> path =
@@ -198,7 +207,7 @@ namespace vcpkg
return *p;
}
- return fetch_dependency(scripts_folder, L"installerbase", downloaded_copy, EXPECTED_VERSION);
+ return fetch_dependency(scripts_folder, "installerbase", downloaded_copy, EXPECTED_VERSION);
}
Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir)
@@ -255,18 +264,25 @@ namespace vcpkg
return this->vcpkg_dir_info / (pgh.fullstem() + ".list");
}
- bool VcpkgPaths::is_valid_triplet(const Triplet& t) const
+ const std::vector<std::string>& VcpkgPaths::get_available_triplets() const
{
- for (auto&& path : get_filesystem().get_files_non_recursive(this->triplets))
- {
- const std::string triplet_file_name = path.stem().generic_u8string();
- if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare
+ 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))
{
- // t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare
- return true;
+ output.push_back(path.stem().filename().string());
}
- }
- return false;
+
+ return output;
+ });
+ }
+
+ bool VcpkgPaths::is_valid_triplet(const Triplet& t) const
+ {
+ auto it = Util::find_if(this->get_available_triplets(),
+ [&](auto&& available_triplet) { return t.canonical_name() == available_triplet; });
+ return it != this->get_available_triplets().cend();
}
const fs::path& VcpkgPaths::get_cmake_exe() const
@@ -315,20 +331,34 @@ namespace vcpkg
static std::vector<VisualStudioInstance> get_visual_studio_instances(const VcpkgPaths& paths)
{
const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1";
- const std::wstring cmd = System::create_powershell_script_cmd(script);
- const System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd);
- Checks::check_exit(
- VCPKG_LINE_INFO, ec_data.exit_code == 0, "Could not run script to detect Visual Studio instances");
+ const std::string output =
+ System::powershell_execute_and_capture_output("Detecting Visual Studio instances", script);
- const std::vector<std::string> instances_as_strings = Strings::split(ec_data.output, "\n");
- std::vector<VisualStudioInstance> output;
+ const std::vector<std::string> instances_as_strings = keep_data_lines(output);
+ Checks::check_exit(VCPKG_LINE_INFO,
+ !instances_as_strings.empty(),
+ "Could not detect any Visual Studio instances.\n"
+ "Powershell script:\n"
+ " %s\n"
+ "returned:\n"
+ "%s",
+ script.generic_string(),
+ output);
+
+ std::vector<VisualStudioInstance> instances;
for (const std::string& instance_as_string : instances_as_strings)
{
const std::vector<std::string> split = Strings::split(instance_as_string, "::");
- output.push_back({split.at(3), split.at(2), split.at(1), split.at(0)});
+ Checks::check_exit(VCPKG_LINE_INFO,
+ split.size() == 4,
+ "Invalid Visual Studio instance format.\n"
+ "Expected: PreferenceWeight::ReleaseType::Version::PathToVisualStudio\n"
+ "Actual : %s\n",
+ instance_as_string);
+ instances.push_back({split.at(3), split.at(2), split.at(1), split.at(0)});
}
- return output;
+ return instances;
}
static std::vector<Toolset> find_toolset_instances(const VcpkgPaths& paths)
@@ -363,21 +393,21 @@ namespace vcpkg
// Get all supported architectures
std::vector<ToolsetArchOption> supported_architectures;
if (fs.exists(vcvarsall_dir / "vcvars32.bat"))
- supported_architectures.push_back({L"x86", CPU::X86, CPU::X86});
+ supported_architectures.push_back({"x86", CPU::X86, CPU::X86});
if (fs.exists(vcvarsall_dir / "vcvars64.bat"))
- supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64});
+ supported_architectures.push_back({"amd64", CPU::X64, CPU::X64});
if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat"))
- supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64});
+ supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64});
if (fs.exists(vcvarsall_dir / "vcvarsx86_arm.bat"))
- supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM});
+ supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM});
if (fs.exists(vcvarsall_dir / "vcvarsx86_arm64.bat"))
- supported_architectures.push_back({L"x86_arm64", CPU::X86, CPU::ARM64});
+ supported_architectures.push_back({"x86_arm64", CPU::X86, CPU::ARM64});
if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat"))
- supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86});
+ supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86});
if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm.bat"))
- supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM});
+ supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM});
if (fs.exists(vcvarsall_dir / "vcvarsamd64_arm64.bat"))
- supported_architectures.push_back({L"amd64_arm64", CPU::X64, CPU::ARM64});
+ supported_architectures.push_back({"amd64_arm64", CPU::X64, CPU::ARM64});
// Locate the "best" MSVC toolchain version
const fs::path msvc_path = vc_dir / "Tools" / "MSVC";
@@ -405,7 +435,7 @@ namespace vcpkg
found_toolsets.push_back(Toolset{vs_instance.root_path,
dumpbin_path,
vcvarsall_bat,
- {L"-vcvars_ver=14.0"},
+ {"-vcvars_ver=14.0"},
V_140,
supported_architectures});
}
@@ -430,17 +460,17 @@ namespace vcpkg
const fs::path vs_bin_dir = vcvarsall_bat.parent_path() / "bin";
std::vector<ToolsetArchOption> supported_architectures;
if (fs.exists(vs_bin_dir / "vcvars32.bat"))
- supported_architectures.push_back({L"x86", CPU::X86, CPU::X86});
+ supported_architectures.push_back({"x86", CPU::X86, CPU::X86});
if (fs.exists(vs_bin_dir / "amd64\\vcvars64.bat"))
- supported_architectures.push_back({L"x64", CPU::X64, CPU::X64});
+ supported_architectures.push_back({"x64", CPU::X64, CPU::X64});
if (fs.exists(vs_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat"))
- supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64});
+ supported_architectures.push_back({"x86_amd64", CPU::X86, CPU::X64});
if (fs.exists(vs_bin_dir / "x86_arm\\vcvarsx86_arm.bat"))
- supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM});
+ supported_architectures.push_back({"x86_arm", CPU::X86, CPU::ARM});
if (fs.exists(vs_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat"))
- supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86});
+ supported_architectures.push_back({"amd64_x86", CPU::X64, CPU::X86});
if (fs.exists(vs_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat"))
- supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM});
+ supported_architectures.push_back({"amd64_arm", CPU::X64, CPU::ARM});
if (fs.exists(vs_dumpbin_exe))
{
@@ -482,15 +512,12 @@ namespace vcpkg
if (tsv && vsp)
{
- const std::wstring w_toolset_version = Strings::to_utf16(*tsv);
- const fs::path vs_root_path = *vsp;
- Util::stable_keep_if(candidates, [&](const Toolset* t) {
- return w_toolset_version == t->version && vs_root_path == t->visual_studio_root_path;
- });
+ Util::stable_keep_if(
+ candidates, [&](const Toolset* t) { return *tsv == t->version && *vsp == t->visual_studio_root_path; });
Checks::check_exit(VCPKG_LINE_INFO,
!candidates.empty(),
"Could not find Visual Studio instace at %s with %s toolset.",
- vs_root_path.generic_string(),
+ vsp->u8string(),
*tsv);
Checks::check_exit(VCPKG_LINE_INFO, candidates.size() == 1);
@@ -499,8 +526,7 @@ namespace vcpkg
if (tsv)
{
- const std::wstring w_toolset_version = Strings::to_utf16(*tsv);
- Util::stable_keep_if(candidates, [&](const Toolset* t) { return w_toolset_version == t->version; });
+ Util::stable_keep_if(candidates, [&](const Toolset* t) { return *tsv == t->version; });
Checks::check_exit(
VCPKG_LINE_INFO, !candidates.empty(), "Could not find Visual Studio instace with %s toolset.", *tsv);
}