aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorjasjuang <jasjuang@gmail.com>2017-09-22 08:16:32 -0700
committerjasjuang <jasjuang@gmail.com>2017-09-22 08:16:32 -0700
commitf643a8422f87c5a16e3cc77e3e321e34a45f7103 (patch)
tree419c9a2e74ab577aab0e868441b9a0e4c15d4919 /toolsrc/src
parent9989177fed607cdc9e20127ff7c22e3266e7c913 (diff)
parentfac96eb344a500405ab65b7e7f3755af0ad00b7e (diff)
downloadvcpkg-f643a8422f87c5a16e3cc77e3e321e34a45f7103.tar.gz
vcpkg-f643a8422f87c5a16e3cc77e3e321e34a45f7103.zip
Merge branch 'master' of https://github.com/jasjuang/vcpkg
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/BinaryParagraph.cpp12
-rw-r--r--toolsrc/src/MachineType.cpp2
-rw-r--r--toolsrc/src/PackageSpec.cpp165
-rw-r--r--toolsrc/src/Paragraphs.cpp19
-rw-r--r--toolsrc/src/PostBuildLint.cpp38
-rw-r--r--toolsrc/src/SourceParagraph.cpp85
-rw-r--r--toolsrc/src/StatusParagraph.cpp4
-rw-r--r--toolsrc/src/StatusParagraphs.cpp26
-rw-r--r--toolsrc/src/VcpkgCmdArguments.cpp23
-rw-r--r--toolsrc/src/VcpkgPaths.cpp165
-rw-r--r--toolsrc/src/coff_file_reader.cpp8
-rw-r--r--toolsrc/src/commands_build.cpp24
-rw-r--r--toolsrc/src/commands_build_external.cpp7
-rw-r--r--toolsrc/src/commands_cache.cpp6
-rw-r--r--toolsrc/src/commands_ci.cpp58
-rw-r--r--toolsrc/src/commands_contact.cpp4
-rw-r--r--toolsrc/src/commands_create.cpp7
-rw-r--r--toolsrc/src/commands_depends.cpp8
-rw-r--r--toolsrc/src/commands_edit.cpp112
-rw-r--r--toolsrc/src/commands_env.cpp9
-rw-r--r--toolsrc/src/commands_export.cpp67
-rw-r--r--toolsrc/src/commands_hash.cpp16
-rw-r--r--toolsrc/src/commands_import.cpp18
-rw-r--r--toolsrc/src/commands_install.cpp466
-rw-r--r--toolsrc/src/commands_integrate.cpp82
-rw-r--r--toolsrc/src/commands_list.cpp18
-rw-r--r--toolsrc/src/commands_owns.cpp4
-rw-r--r--toolsrc/src/commands_portsdiff.cpp11
-rw-r--r--toolsrc/src/commands_remove.cpp122
-rw-r--r--toolsrc/src/commands_search.cpp19
-rw-r--r--toolsrc/src/commands_update.cpp28
-rw-r--r--toolsrc/src/commands_version.cpp35
-rw-r--r--toolsrc/src/metrics.cpp158
-rw-r--r--toolsrc/src/test_install_plan.cpp547
-rw-r--r--toolsrc/src/tests_dependencies.cpp21
-rw-r--r--toolsrc/src/tests_package_spec.cpp119
-rw-r--r--toolsrc/src/tests_paragraph.cpp85
-rw-r--r--toolsrc/src/triplet.cpp6
-rw-r--r--toolsrc/src/vcpkg.cpp68
-rw-r--r--toolsrc/src/vcpkg_Build.cpp148
-rw-r--r--toolsrc/src/vcpkg_Checks.cpp48
-rw-r--r--toolsrc/src/vcpkg_Chrono.cpp18
-rw-r--r--toolsrc/src/vcpkg_Dependencies.cpp455
-rw-r--r--toolsrc/src/vcpkg_Files.cpp17
-rw-r--r--toolsrc/src/vcpkg_GlobalState.cpp13
-rw-r--r--toolsrc/src/vcpkg_Input.cpp6
-rw-r--r--toolsrc/src/vcpkg_Parse.cpp39
-rw-r--r--toolsrc/src/vcpkg_Strings.cpp7
-rw-r--r--toolsrc/src/vcpkg_System.cpp182
-rw-r--r--toolsrc/src/vcpkg_metrics_uploader.cpp5
-rw-r--r--toolsrc/src/vcpkglib.cpp21
51 files changed, 2133 insertions, 1498 deletions
diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp
index 49e9d58e5..1504912ab 100644
--- a/toolsrc/src/BinaryParagraph.cpp
+++ b/toolsrc/src/BinaryParagraph.cpp
@@ -56,7 +56,7 @@ namespace vcpkg
this->default_features = parse_comma_list(parser.optional_field(Fields::DEFAULTFEATURES));
}
- if (auto err = parser.error_info(this->spec.to_string()))
+ if (const auto err = parser.error_info(this->spec.to_string()))
{
System::println(
System::Color::error, "Error: while parsing the Binary Paragraph for %s", this->spec.to_string());
@@ -80,14 +80,18 @@ 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 = "";
+ this->version = Strings::EMPTY;
this->feature = fpgh.name;
this->description = fpgh.description;
- this->maintainer = "";
+ this->maintainer = Strings::EMPTY;
this->depends = filter_dependencies(fpgh.depends, triplet);
}
- std::string BinaryParagraph::displayname() const { return this->spec.to_string(); }
+ std::string BinaryParagraph::displayname() const
+ {
+ const auto f = this->feature.empty() ? "core" : this->feature;
+ return Strings::format("%s[%s]:%s", this->spec.name(), f, this->spec.triplet());
+ }
std::string BinaryParagraph::dir() const { return this->spec.dir(); }
diff --git a/toolsrc/src/MachineType.cpp b/toolsrc/src/MachineType.cpp
index 2f44ce21a..af6378c88 100644
--- a/toolsrc/src/MachineType.cpp
+++ b/toolsrc/src/MachineType.cpp
@@ -7,7 +7,7 @@ namespace vcpkg
{
MachineType to_machine_type(const uint16_t value)
{
- MachineType t = static_cast<MachineType>(value);
+ const MachineType t = static_cast<MachineType>(value);
switch (t)
{
case MachineType::UNKNOWN:
diff --git a/toolsrc/src/PackageSpec.cpp b/toolsrc/src/PackageSpec.cpp
index a7e5648cd..890de8899 100644
--- a/toolsrc/src/PackageSpec.cpp
+++ b/toolsrc/src/PackageSpec.cpp
@@ -1,8 +1,11 @@
#include "pch.h"
#include "PackageSpec.h"
+#include "vcpkg_Parse.h"
#include "vcpkg_Util.h"
+using vcpkg::Parse::parse_comma_list;
+
namespace vcpkg
{
static bool is_valid_package_spec_char(char c)
@@ -10,55 +13,69 @@ namespace vcpkg
return (c == '-') || isdigit(c) || (isalpha(c) && islower(c)) || (c == '[') || (c == ']');
}
- ExpectedT<FullPackageSpec, PackageSpecParseResult> FullPackageSpec::from_string(const std::string& spec_as_string,
- const Triplet& default_triplet)
+ std::string FeatureSpec::to_string() const
{
- auto pos = spec_as_string.find(':');
- auto pos_l_bracket = spec_as_string.find('[');
- auto pos_r_bracket = spec_as_string.find(']');
+ if (feature().empty()) return spec().to_string();
+ return Strings::format("%s[%s]:%s", name(), feature(), triplet());
+ }
- FullPackageSpec f;
- if (pos == std::string::npos && pos_l_bracket == std::string::npos)
- {
- f.package_spec =
- PackageSpec::from_name_and_triplet(spec_as_string, default_triplet).value_or_exit(VCPKG_LINE_INFO);
- return f;
- }
- else if (pos == std::string::npos)
+ std::vector<FeatureSpec> FeatureSpec::from_strings_and_triplet(const std::vector<std::string>& depends,
+ const Triplet& triplet)
+ {
+ std::vector<FeatureSpec> f_specs;
+ for (auto&& depend : depends)
{
- if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket)
+ auto maybe_spec = ParsedSpecifier::from_string(depend);
+ if (auto spec = maybe_spec.get())
{
- return PackageSpecParseResult::INVALID_CHARACTERS;
+ Checks::check_exit(VCPKG_LINE_INFO,
+ spec->triplet.empty(),
+ "error: triplets cannot currently be specified in this context: %s",
+ depend);
+ PackageSpec pspec =
+ PackageSpec::from_name_and_triplet(spec->name, triplet).value_or_exit(VCPKG_LINE_INFO);
+
+ for (auto&& feature : spec->features)
+ f_specs.push_back(FeatureSpec{pspec, feature});
+
+ if (spec->features.empty()) f_specs.push_back(FeatureSpec{pspec, Strings::EMPTY});
}
- const std::string name = spec_as_string.substr(0, pos_l_bracket);
- f.package_spec = PackageSpec::from_name_and_triplet(name, default_triplet).value_or_exit(VCPKG_LINE_INFO);
- f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1));
- return f;
- }
- else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos)
- {
- const std::string name = spec_as_string.substr(0, pos);
- const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1));
- f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO);
- }
- else
- {
- if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket)
+ else
{
- return PackageSpecParseResult::INVALID_CHARACTERS;
+ Checks::exit_with_message(VCPKG_LINE_INFO,
+ "error while parsing feature list: %s: %s",
+ vcpkg::to_string(maybe_spec.error()),
+ depend);
}
- const std::string name = spec_as_string.substr(0, pos_l_bracket);
- f.features = parse_comma_list(spec_as_string.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1));
- const Triplet triplet = Triplet::from_canonical_name(spec_as_string.substr(pos + 1));
- f.package_spec = PackageSpec::from_name_and_triplet(name, triplet).value_or_exit(VCPKG_LINE_INFO);
}
+ return f_specs;
+ }
- auto pos2 = spec_as_string.find(':', pos + 1);
- if (pos2 != std::string::npos)
+ std::vector<FeatureSpec> FullPackageSpec::to_feature_specs(const std::vector<FullPackageSpec>& specs)
+ {
+ std::vector<FeatureSpec> ret;
+ for (auto&& spec : specs)
{
- return PackageSpecParseResult::TOO_MANY_COLONS;
+ ret.emplace_back(spec.package_spec, Strings::EMPTY);
+ for (auto&& feature : spec.features)
+ ret.emplace_back(spec.package_spec, feature);
}
- return f;
+ return ret;
+ }
+
+ ExpectedT<FullPackageSpec, PackageSpecParseResult> FullPackageSpec::from_string(const std::string& spec_as_string,
+ const Triplet& default_triplet)
+ {
+ auto res = ParsedSpecifier::from_string(spec_as_string);
+ if (auto p = res.get())
+ {
+ FullPackageSpec fspec;
+ Triplet t = p->triplet.empty() ? default_triplet : Triplet::from_canonical_name(p->triplet);
+ fspec.package_spec = PackageSpec::from_name_and_triplet(p->name, t).value_or_exit(VCPKG_LINE_INFO);
+ fspec.features = std::move(p->features);
+ return fspec;
+ }
+ return res.error();
}
ExpectedT<PackageSpec, PackageSpecParseResult> PackageSpec::from_name_and_triplet(const std::string& name,
@@ -81,11 +98,7 @@ namespace vcpkg
std::string PackageSpec::dir() const { return Strings::format("%s_%s", this->m_name, this->m_triplet); }
- std::string PackageSpec::to_string(const std::string& name, const Triplet& triplet)
- {
- return Strings::format("%s:%s", name, triplet);
- }
- std::string PackageSpec::to_string() const { return to_string(this->name(), this->triplet()); }
+ std::string PackageSpec::to_string() const { return Strings::format("%s:%s", this->name(), this->triplet()); }
bool operator==(const PackageSpec& left, const PackageSpec& right)
{
@@ -93,4 +106,70 @@ namespace vcpkg
}
bool operator!=(const PackageSpec& left, const PackageSpec& right) { return !(left == right); }
+
+ ExpectedT<ParsedSpecifier, PackageSpecParseResult> ParsedSpecifier::from_string(const std::string& input)
+ {
+ auto pos = input.find(':');
+ auto pos_l_bracket = input.find('[');
+ auto pos_r_bracket = input.find(']');
+
+ ParsedSpecifier f;
+ if (pos == std::string::npos && pos_l_bracket == std::string::npos)
+ {
+ f.name = input;
+ return f;
+ }
+ else if (pos == std::string::npos)
+ {
+ if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket)
+ {
+ return PackageSpecParseResult::INVALID_CHARACTERS;
+ }
+ const std::string name = input.substr(0, pos_l_bracket);
+ f.name = name;
+ f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1));
+ return f;
+ }
+ else if (pos_l_bracket == std::string::npos && pos_r_bracket == std::string::npos)
+ {
+ const std::string name = input.substr(0, pos);
+ f.triplet = input.substr(pos + 1);
+ f.name = name;
+ }
+ else
+ {
+ if (pos_r_bracket == std::string::npos || pos_l_bracket >= pos_r_bracket)
+ {
+ return PackageSpecParseResult::INVALID_CHARACTERS;
+ }
+ const std::string name = input.substr(0, pos_l_bracket);
+ f.features = parse_comma_list(input.substr(pos_l_bracket + 1, pos_r_bracket - pos_l_bracket - 1));
+ f.triplet = input.substr(pos + 1);
+ f.name = name;
+ }
+
+ auto pos2 = input.find(':', pos + 1);
+ if (pos2 != std::string::npos)
+ {
+ return PackageSpecParseResult::TOO_MANY_COLONS;
+ }
+ return f;
+ }
+
+ ExpectedT<Features, PackageSpecParseResult> Features::from_string(const std::string& name)
+ {
+ auto maybe_spec = ParsedSpecifier::from_string(name);
+ if (auto spec = maybe_spec.get())
+ {
+ Checks::check_exit(
+ VCPKG_LINE_INFO, spec->triplet.empty(), "error: triplet not allowed in specifier: %s", name);
+
+ Features f;
+ f.name = spec->name;
+ f.features = spec->features;
+ return f;
+ }
+
+ return maybe_spec.error();
+ }
}
diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp
index 3749e919e..a7dee4fd3 100644
--- a/toolsrc/src/Paragraphs.cpp
+++ b/toolsrc/src/Paragraphs.cpp
@@ -3,6 +3,8 @@
#include "ParagraphParseResult.h"
#include "Paragraphs.h"
#include "vcpkg_Files.h"
+#include "vcpkg_GlobalState.h"
+#include "vcpkg_Util.h"
using namespace vcpkg::Parse;
@@ -209,7 +211,7 @@ namespace vcpkg::Paragraphs
if (auto vector_pghs = pghs.get())
{
auto csf = SourceControlFile::parse_control_file(std::move(*vector_pghs));
- if (!g_feature_packages)
+ if (!GlobalState::feature_packages)
{
if (auto ptr = csf.get())
{
@@ -226,14 +228,21 @@ namespace vcpkg::Paragraphs
return error_info;
}
- Expected<BinaryParagraph> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec)
+ Expected<BinaryControlFile> try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec)
{
- Expected<std::unordered_map<std::string, std::string>> pghs =
- get_single_paragraph(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL");
+ Expected<std::vector<std::unordered_map<std::string, std::string>>> pghs =
+ get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL");
if (auto p = pghs.get())
{
- return BinaryParagraph(*p);
+ BinaryControlFile bcf;
+ bcf.core_paragraph = BinaryParagraph(p->front());
+ p->erase(p->begin());
+
+ bcf.features =
+ Util::fmap(*p, [&](auto&& raw_feature) -> BinaryParagraph { return BinaryParagraph(raw_feature); });
+
+ return bcf;
}
return pghs.error();
diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp
index a5d923ad2..1fd48d3ec 100644
--- a/toolsrc/src/PostBuildLint.cpp
+++ b/toolsrc/src/PostBuildLint.cpp
@@ -10,9 +10,9 @@
#include "vcpkg_System.h"
#include "vcpkg_Util.h"
-using vcpkg::Build::PreBuildInfo;
using vcpkg::Build::BuildInfo;
using vcpkg::Build::BuildPolicy;
+using vcpkg::Build::PreBuildInfo;
namespace vcpkg::PostBuildLint
{
@@ -40,7 +40,7 @@ namespace vcpkg::PostBuildLint
const std::vector<OutdatedDynamicCrt>& get_outdated_dynamic_crts()
{
- static const std::vector<OutdatedDynamicCrt> v_no_msvcrt = {
+ static const std::vector<OutdatedDynamicCrt> V_NO_MSVCRT = {
{"msvcp100.dll", R"(msvcp100\.dll)"},
{"msvcp100d.dll", R"(msvcp100d\.dll)"},
{"msvcp110.dll", R"(msvcp110\.dll)"},
@@ -59,7 +59,7 @@ namespace vcpkg::PostBuildLint
{"msvcrt20.dll", R"(msvcrt20\.dll)"},
{"msvcrt40.dll", R"(msvcrt40\.dll)"}};
- return v_no_msvcrt;
+ return V_NO_MSVCRT;
}
static LintStatus check_for_files_in_include_directory(const Files::Filesystem& fs,
@@ -369,12 +369,12 @@ namespace vcpkg::PostBuildLint
std::vector<FileAndArch> binaries_with_invalid_architecture)
{
System::println(System::Color::warning, "The following files were built for an incorrect architecture:");
- System::println("");
+ System::println();
for (const FileAndArch& b : binaries_with_invalid_architecture)
{
System::println(" %s", b.file.generic_string());
System::println("Expected %s, but was: %s", expected_architecture, b.actual_arch);
- System::println("");
+ System::println();
}
}
@@ -389,7 +389,7 @@ namespace vcpkg::PostBuildLint
file.extension() == ".dll",
"The file extension was not .dll: %s",
file.generic_string());
- COFFFileReader::DllInfo info = COFFFileReader::read_dll(file);
+ const CoffFileReader::DllInfo info = CoffFileReader::read_dll(file);
const std::string actual_architecture = get_actual_architecture(info.machine_type);
if (expected_architecture != actual_architecture)
@@ -418,7 +418,7 @@ namespace vcpkg::PostBuildLint
file.extension() == ".lib",
"The file extension was not .lib: %s",
file.generic_string());
- COFFFileReader::LibInfo info = COFFFileReader::read_lib(file);
+ CoffFileReader::LibInfo info = CoffFileReader::read_lib(file);
// This is zero for folly's debug library
// TODO: Why?
@@ -487,7 +487,7 @@ namespace vcpkg::PostBuildLint
System::println(System::Color::warning, "Release binaries were not found");
}
- System::println("");
+ System::println();
return LintStatus::ERROR_DETECTED;
}
@@ -580,7 +580,7 @@ namespace vcpkg::PostBuildLint
return LintStatus::SUCCESS;
}
- struct BuildType_and_file
+ struct BuildTypeAndFile
{
fs::path file;
BuildType build_type;
@@ -594,7 +594,7 @@ namespace vcpkg::PostBuildLint
bad_build_types.erase(std::remove(bad_build_types.begin(), bad_build_types.end(), expected_build_type),
bad_build_types.end());
- std::vector<BuildType_and_file> libs_with_invalid_crt;
+ std::vector<BuildTypeAndFile> libs_with_invalid_crt;
for (const fs::path& lib : libs)
{
@@ -621,12 +621,12 @@ namespace vcpkg::PostBuildLint
System::println(System::Color::warning,
"Expected %s crt linkage, but the following libs had invalid crt linkage:",
expected_build_type.to_string());
- System::println("");
- for (const BuildType_and_file btf : libs_with_invalid_crt)
+ System::println();
+ for (const BuildTypeAndFile btf : libs_with_invalid_crt)
{
System::println(" %s: %s", btf.file.generic_string(), btf.build_type.to_string());
}
- System::println("");
+ System::println();
System::println(System::Color::warning,
"To inspect the lib files, use:\n dumpbin.exe /directives mylibfile.lib");
@@ -636,12 +636,12 @@ namespace vcpkg::PostBuildLint
return LintStatus::SUCCESS;
}
- struct OutdatedDynamicCrt_and_file
+ struct OutdatedDynamicCrtAndFile
{
fs::path file;
OutdatedDynamicCrt outdated_crt;
- OutdatedDynamicCrt_and_file() = delete;
+ OutdatedDynamicCrtAndFile() = delete;
};
static LintStatus check_outdated_crt_linkage_of_dlls(const std::vector<fs::path>& dlls,
@@ -650,7 +650,7 @@ namespace vcpkg::PostBuildLint
{
if (build_info.policies.is_enabled(BuildPolicy::ALLOW_OBSOLETE_MSVCRT)) return LintStatus::SUCCESS;
- std::vector<OutdatedDynamicCrt_and_file> dlls_with_outdated_crt;
+ std::vector<OutdatedDynamicCrtAndFile> dlls_with_outdated_crt;
for (const fs::path& dll : dlls)
{
@@ -675,12 +675,12 @@ namespace vcpkg::PostBuildLint
if (!dlls_with_outdated_crt.empty())
{
System::println(System::Color::warning, "Detected outdated dynamic CRT in the following files:");
- System::println("");
- for (const OutdatedDynamicCrt_and_file btf : dlls_with_outdated_crt)
+ System::println();
+ for (const OutdatedDynamicCrtAndFile btf : dlls_with_outdated_crt)
{
System::println(" %s: %s", btf.file.generic_string(), btf.outdated_crt.name);
}
- System::println("");
+ System::println();
System::println(System::Color::warning,
"To inspect the dll files, use:\n dumpbin.exe /dependents mydllfile.dll");
diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp
index a34167db7..171689ce7 100644
--- a/toolsrc/src/SourceParagraph.cpp
+++ b/toolsrc/src/SourceParagraph.cpp
@@ -1,5 +1,6 @@
#include "pch.h"
+#include "PackageSpec.h"
#include "SourceParagraph.h"
#include "Triplet.h"
#include "vcpkg_Checks.h"
@@ -12,7 +13,6 @@ namespace vcpkg
{
using namespace vcpkg::Parse;
- bool g_feature_packages = false;
namespace Fields
{
static const std::string BUILD_DEPENDS = "Build-Depends";
@@ -28,7 +28,11 @@ namespace vcpkg
static span<const std::string> get_list_of_valid_fields()
{
static const std::string valid_fields[] = {
- Fields::SOURCE, Fields::VERSION, Fields::DESCRIPTION, Fields::MAINTAINER, Fields::BUILD_DEPENDS,
+ Fields::SOURCE,
+ Fields::VERSION,
+ Fields::DESCRIPTION,
+ Fields::MAINTAINER,
+ Fields::BUILD_DEPENDS,
};
return valid_fields;
@@ -133,7 +137,7 @@ namespace vcpkg
auto control_file = std::make_unique<SourceControlFile>();
auto maybe_source = parse_source_paragraph(std::move(control_paragraphs.front()));
- if (auto source = maybe_source.get())
+ if (const auto source = maybe_source.get())
control_file->core_paragraph = std::move(*source);
else
return std::move(maybe_source).error();
@@ -143,7 +147,7 @@ namespace vcpkg
for (auto&& feature_pgh : control_paragraphs)
{
auto maybe_feature = parse_feature_paragraph(std::move(feature_pgh));
- if (auto feature = maybe_feature.get())
+ if (const auto feature = maybe_feature.get())
control_file->feature_paragraphs.emplace_back(std::move(*feature));
else
return std::move(maybe_feature).error();
@@ -152,57 +156,45 @@ namespace vcpkg
return std::move(control_file);
}
+ Dependency Dependency::parse_dependency(std::string name, std::string qualifier)
+ {
+ Dependency dep;
+ dep.qualifier = qualifier;
+ if (auto maybe_features = Features::from_string(name))
+ dep.depend = *maybe_features.get();
+ else
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "error while parsing dependency: %s: %s", to_string(maybe_features.error()), name);
+ return dep;
+ }
+
+ std::string Dependency::name() const
+ {
+ if (this->depend.features.empty()) return this->depend.name;
+
+ const std::string features = Strings::join(",", this->depend.features);
+ return Strings::format("%s[%s]", this->depend.name, features);
+ }
+
std::vector<Dependency> vcpkg::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 {depend_string, ""};
+ if (pos == std::string::npos) return Dependency::parse_dependency(depend_string, Strings::EMPTY);
// expect of the form "\w+ \[\w+\]"
Dependency dep;
- dep.name = depend_string.substr(0, pos);
- if (depend_string.c_str()[pos + 1] != '[' || depend_string[depend_string.size() - 1] != ']')
+
+ dep.depend.name = depend_string.substr(0, pos);
+ if (depend_string.c_str()[pos + 1] != '(' || depend_string[depend_string.size() - 1] != ')')
{
// Error, but for now just slurp the entire string.
- return {depend_string, ""};
+ return Dependency::parse_dependency(depend_string, Strings::EMPTY);
}
dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3);
return dep;
});
}
- std::vector<std::string> parse_comma_list(const std::string& str)
- {
- if (str.empty())
- {
- return {};
- }
-
- std::vector<std::string> out;
-
- size_t cur = 0;
- do
- {
- auto pos = str.find(',', cur);
- if (pos == std::string::npos)
- {
- out.push_back(str.substr(cur));
- break;
- }
- out.push_back(str.substr(cur, pos - cur));
-
- // skip comma and space
- ++pos;
- if (str[pos] == ' ')
- {
- ++pos;
- }
-
- cur = pos;
- } while (cur != std::string::npos);
-
- return out;
- }
-
std::vector<std::string> filter_dependencies(const std::vector<vcpkg::Dependency>& deps, const Triplet& t)
{
std::vector<std::string> ret;
@@ -210,13 +202,18 @@ namespace vcpkg
{
if (dep.qualifier.empty() || t.canonical_name().find(dep.qualifier) != std::string::npos)
{
- ret.push_back(dep.name);
+ ret.emplace_back(dep.name());
}
}
return ret;
}
- const std::string& to_string(const Dependency& dep) { return dep.name; }
+ std::vector<FeatureSpec> filter_dependencies_to_specs(const std::vector<Dependency>& deps, const Triplet& t)
+ {
+ return FeatureSpec::from_strings_and_triplet(filter_dependencies(deps, t), t);
+ }
+
+ std::string to_string(const Dependency& dep) { return dep.name(); }
ExpectedT<Supports, std::vector<std::string>> Supports::parse(const std::vector<std::string>& strs)
{
@@ -255,7 +252,7 @@ namespace vcpkg
bool Supports::is_supported(Architecture arch, Platform plat, Linkage crt, ToolsetVersion tools)
{
- auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); };
+ const auto is_in_or_empty = [](auto v, auto&& c) -> bool { return c.empty() || c.end() != Util::find(c, v); };
if (!is_in_or_empty(arch, architectures)) return false;
if (!is_in_or_empty(plat, platforms)) return false;
if (!is_in_or_empty(crt, crt_linkages)) return false;
diff --git a/toolsrc/src/StatusParagraph.cpp b/toolsrc/src/StatusParagraph.cpp
index 5b5c3978f..f8ae293c2 100644
--- a/toolsrc/src/StatusParagraph.cpp
+++ b/toolsrc/src/StatusParagraph.cpp
@@ -33,8 +33,8 @@ namespace vcpkg
this->package = BinaryParagraph(std::move(fields));
auto b = status_field.begin();
- auto mark = b;
- auto e = status_field.end();
+ const auto mark = b;
+ const auto e = status_field.end();
// Todo: improve error handling
while (b != e && *b != ' ')
diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp
index 27f3c30a2..aaba95eb9 100644
--- a/toolsrc/src/StatusParagraphs.cpp
+++ b/toolsrc/src/StatusParagraphs.cpp
@@ -27,6 +27,30 @@ namespace vcpkg
});
}
+ std::vector<std::unique_ptr<StatusParagraph>*> StatusParagraphs::find_all(const std::string& name,
+ const Triplet& triplet)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>*> spghs;
+ for (auto&& p : *this)
+ {
+ if (p->package.spec.name() == name && p->package.spec.triplet() == triplet)
+ {
+ spghs.emplace_back(&p);
+ }
+ }
+ return spghs;
+ }
+
+ StatusParagraphs::iterator StatusParagraphs::find(const std::string& name,
+ const Triplet& triplet,
+ const std::string& feature)
+ {
+ 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
{
@@ -43,7 +67,7 @@ namespace vcpkg
{
Checks::check_exit(VCPKG_LINE_INFO, pgh != nullptr, "Inserted null paragraph");
const PackageSpec& spec = pgh->package.spec;
- auto ptr = find(spec.name(), spec.triplet());
+ const auto ptr = find(spec.name(), spec.triplet(), pgh->package.feature);
if (ptr == end())
{
paragraphs.push_back(std::move(pgh));
diff --git a/toolsrc/src/VcpkgCmdArguments.cpp b/toolsrc/src/VcpkgCmdArguments.cpp
index ebf4c5fc5..cb261930e 100644
--- a/toolsrc/src/VcpkgCmdArguments.cpp
+++ b/toolsrc/src/VcpkgCmdArguments.cpp
@@ -3,6 +3,7 @@
#include "VcpkgCmdArguments.h"
#include "metrics.h"
#include "vcpkg_Commands.h"
+#include "vcpkg_GlobalState.h"
#include "vcpkg_System.h"
namespace vcpkg
@@ -15,7 +16,7 @@ namespace vcpkg
if (arg_begin == arg_end)
{
System::println(System::Color::error, "Error: expected value after %s", option_name);
- Metrics::track_property("error", "error option name");
+ Metrics::g_metrics.lock()->track_property("error", "error option name");
Commands::Help::print_usage();
Checks::exit_fail(VCPKG_LINE_INFO);
}
@@ -23,7 +24,7 @@ namespace vcpkg
if (option_field != nullptr)
{
System::println(System::Color::error, "Error: %s specified multiple times", option_name);
- Metrics::track_property("error", "error option specified multiple times");
+ Metrics::g_metrics.lock()->track_property("error", "error option specified multiple times");
Commands::Help::print_usage();
Checks::exit_fail(VCPKG_LINE_INFO);
}
@@ -36,7 +37,7 @@ namespace vcpkg
if (option_field && option_field != new_setting)
{
System::println(System::Color::error, "Error: conflicting values specified for --%s", option_name);
- Metrics::track_property("error", "error conflicting switches");
+ Metrics::g_metrics.lock()->track_property("error", "error conflicting switches");
Commands::Help::print_usage();
Checks::exit_fail(VCPKG_LINE_INFO);
}
@@ -70,7 +71,7 @@ namespace vcpkg
if (arg[0] == '-' && arg[1] != '-')
{
- Metrics::track_property("error", "error short options are not supported");
+ Metrics::g_metrics.lock()->track_property("error", "error short options are not supported");
Checks::exit_with_message(VCPKG_LINE_INFO, "Error: short options are not supported: %s", arg);
}
@@ -119,11 +120,11 @@ namespace vcpkg
}
if (arg == "--featurepackages")
{
- g_feature_packages = true;
+ GlobalState::feature_packages = true;
continue;
}
- auto eq_pos = arg.find('=');
+ const auto eq_pos = arg.find('=');
if (eq_pos != std::string::npos)
{
args.optional_command_arguments.emplace(arg.substr(0, eq_pos), arg.substr(eq_pos + 1));
@@ -157,7 +158,7 @@ namespace vcpkg
auto options_copy = this->optional_command_arguments;
for (const std::string& option : valid_switches)
{
- auto it = options_copy.find(option);
+ const auto it = options_copy.find(option);
if (it != options_copy.end())
{
if (it->second.has_value())
@@ -176,7 +177,7 @@ namespace vcpkg
for (const std::string& option : valid_settings)
{
- auto it = options_copy.find(option);
+ const auto it = options_copy.find(option);
if (it != options_copy.end())
{
if (!it->second.has_value())
@@ -221,17 +222,17 @@ namespace vcpkg
void VcpkgCmdArguments::check_max_arg_count(const size_t expected_arg_count) const
{
- return check_max_arg_count(expected_arg_count, "");
+ 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, "");
+ 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, "");
+ 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
diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp
index 60204bcdd..29edbb260 100644
--- a/toolsrc/src/VcpkgPaths.cpp
+++ b/toolsrc/src/VcpkgPaths.cpp
@@ -13,24 +13,24 @@ namespace vcpkg
static bool exists_and_has_equal_or_greater_version(const std::wstring& version_cmd,
const std::array<int, 3>& expected_version)
{
- static const std::regex re(R"###((\d+)\.(\d+)\.(\d+))###");
+ static const std::regex RE(R"###((\d+)\.(\d+)\.(\d+))###");
- auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd));
+ const auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s)", version_cmd));
if (rc.exit_code != 0)
{
return false;
}
std::match_results<std::string::const_iterator> match;
- auto found = std::regex_search(rc.output, match, re);
+ const auto found = std::regex_search(rc.output, match, RE);
if (!found)
{
return false;
}
- int d1 = atoi(match[1].str().c_str());
- int d2 = atoi(match[2].str().c_str());
- int d3 = atoi(match[3].str().c_str());
+ const int d1 = atoi(match[1].str().c_str());
+ const int d2 = atoi(match[2].str().c_str());
+ const int d3 = atoi(match[3].str().c_str());
if (d1 > expected_version[0] || (d1 == expected_version[0] && d2 > expected_version[1]) ||
(d1 == expected_version[0] && d2 == expected_version[1] && d3 >= expected_version[2]))
{
@@ -58,26 +58,15 @@ namespace vcpkg
return nullopt;
}
- static std::vector<fs::path> find_from_PATH(const std::wstring& name)
- {
- const std::wstring cmd = Strings::wformat(L"where.exe %s", name);
- auto out = System::cmd_execute_and_capture_output(cmd);
- if (out.exit_code != 0)
- {
- return {};
- }
-
- return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); });
- }
-
static fs::path fetch_dependency(const fs::path& scripts_folder,
const std::wstring& tool_name,
const fs::path& expected_downloaded_path,
const std::array<int, 3>& version)
{
const fs::path script = scripts_folder / "fetchDependency.ps1";
- auto install_cmd = System::create_powershell_script_cmd(script, Strings::wformat(L"-Dependency %s", tool_name));
- System::ExitCodeAndOutput rc = System::cmd_execute_and_capture_output(install_cmd);
+ 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)
{
const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]);
@@ -87,14 +76,17 @@ namespace vcpkg
"(No sufficient installed version was found)",
Strings::to_utf8(tool_name),
version_as_string);
- Metrics::track_property("error", "powershell install failed");
- Metrics::track_property("installcmd", install_cmd);
+ {
+ 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 fs::path actual_downloaded_path = Strings::trimmed(rc.output);
std::error_code ec;
- auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec);
+ const auto eq = fs::stdfs::equivalent(expected_downloaded_path, actual_downloaded_path, ec);
Checks::check_exit(VCPKG_LINE_INFO,
eq && !ec,
"Expected dependency downloaded path to be %s, but was %s",
@@ -105,71 +97,71 @@ 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, 1};
- static const std::wstring version_check_arguments = L"--version";
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {3, 9, 2};
+ static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version";
- const fs::path downloaded_copy = downloads_folder / "cmake-3.9.1-win32-x86" / "bin" / "cmake.exe";
- const std::vector<fs::path> from_path = find_from_PATH(L"cmake");
+ const fs::path downloaded_copy = downloads_folder / "cmake-3.9.2-win32-x86" / "bin" / "cmake.exe";
+ const std::vector<fs::path> from_path = Files::find_from_PATH(L"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());
- candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "CMake" / "bin" / "cmake.exe");
- candidate_paths.push_back(System::get_ProgramFiles_32_bit() / "CMake" / "bin");
+ 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");
const Optional<fs::path> path =
- find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version);
- if (auto p = path.get())
+ find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION);
+ if (const auto p = path.get())
{
return *p;
}
- return fetch_dependency(scripts_folder, L"cmake", downloaded_copy, expected_version);
+ return fetch_dependency(scripts_folder, L"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, 1, 0};
- static const std::wstring version_check_arguments = L"";
+ static constexpr std::array<int, 3> EXPECTED_VERSION = {4, 1, 0};
+ static const std::wstring VERSION_CHECK_ARGUMENTS = Strings::WEMPTY;
const fs::path downloaded_copy = downloads_folder / "nuget-4.1.0" / "nuget.exe";
- const std::vector<fs::path> from_path = find_from_PATH(L"nuget");
+ const std::vector<fs::path> from_path = Files::find_from_PATH(L"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);
- if (auto p = path.get())
+ auto path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, 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, L"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, 14, 1};
+ static const std::wstring VERSION_CHECK_ARGUMENTS = L"--version";
const fs::path downloaded_copy = downloads_folder / "MinGit-2.14.1-32-bit" / "cmd" / "git.exe";
- const std::vector<fs::path> from_path = find_from_PATH(L"git");
+ const std::vector<fs::path> from_path = Files::find_from_PATH(L"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());
- candidate_paths.push_back(System::get_ProgramFiles_platform_bitness() / "git" / "cmd" / "git.exe");
- candidate_paths.push_back(System::get_ProgramFiles_32_bit() / "git" / "cmd" / "git.exe");
+ 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");
const Optional<fs::path> path =
- find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version);
- if (auto p = path.get())
+ find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, EXPECTED_VERSION);
+ if (const auto p = path.get())
{
return *p;
}
- return fetch_dependency(scripts_folder, L"git", downloaded_copy, expected_version);
+ return fetch_dependency(scripts_folder, L"git", downloaded_copy, EXPECTED_VERSION);
}
Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir)
@@ -186,7 +178,7 @@ namespace vcpkg
if (paths.root.empty())
{
- Metrics::track_property("error", "Invalid vcpkg root directory");
+ Metrics::g_metrics.lock()->track_property("error", "Invalid vcpkg root directory");
Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid vcpkg root directory: %s", paths.root.string());
}
@@ -214,6 +206,7 @@ namespace vcpkg
fs::path VcpkgPaths::package_dir(const PackageSpec& spec) const { return this->packages / spec.dir(); }
fs::path VcpkgPaths::port_dir(const PackageSpec& spec) const { return this->ports / spec.name(); }
+ fs::path VcpkgPaths::port_dir(const std::string& name) const { return this->ports / name; }
fs::path VcpkgPaths::build_info_file_path(const PackageSpec& spec) const
{
@@ -229,7 +222,7 @@ namespace vcpkg
{
for (auto&& path : get_filesystem().get_files_non_recursive(this->triplets))
{
- std::string triplet_file_name = path.stem().generic_u8string();
+ const std::string triplet_file_name = path.stem().generic_u8string();
if (t.canonical_name() == triplet_file_name) // TODO: fuzzy compare
{
// t.value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare
@@ -254,19 +247,19 @@ namespace vcpkg
return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); });
}
- static std::vector<std::string> get_VS2017_installation_instances(const VcpkgPaths& paths)
+ static std::vector<std::string> get_vs2017_installation_instances(const VcpkgPaths& paths)
{
const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1";
const std::wstring cmd = System::create_powershell_script_cmd(script);
- System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd);
+ 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 VS 2017 instances");
return Strings::split(ec_data.output, "\n");
}
- static Optional<fs::path> get_VS2015_installation_instance()
+ static Optional<fs::path> get_vs2015_installation_instance()
{
const Optional<std::wstring> vs2015_cmntools_optional = System::get_environment_variable(L"VS140COMNTOOLS");
- if (auto v = vs2015_cmntools_optional.get())
+ if (const auto v = vs2015_cmntools_optional.get())
{
const fs::path vs2015_cmntools = fs::path(*v).parent_path(); // The call to parent_path() is needed because
// the env variable has a trailing backslash
@@ -278,17 +271,19 @@ namespace vcpkg
static std::vector<Toolset> find_toolset_instances(const VcpkgPaths& paths)
{
+ using CPU = System::CPUArchitecture;
+
const auto& fs = paths.get_filesystem();
- const std::vector<std::string> vs2017_installation_instances = get_VS2017_installation_instances(paths);
+ const std::vector<std::string> vs2017_installation_instances = get_vs2017_installation_instances(paths);
// Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations.
std::vector<fs::path> paths_examined;
std::vector<Toolset> found_toolsets;
// VS2015
- const Optional<fs::path> vs_2015_installation_instance = get_VS2015_installation_instance();
- if (auto v = vs_2015_installation_instance.get())
+ const Optional<fs::path> vs_2015_installation_instance = get_vs2015_installation_instance();
+ if (const auto v = vs_2015_installation_instance.get())
{
const fs::path vs2015_vcvarsall_bat = *v / "VC" / "vcvarsall.bat";
@@ -297,24 +292,57 @@ namespace vcpkg
{
const fs::path vs2015_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe";
paths_examined.push_back(vs2015_dumpbin_exe);
+
+ const fs::path vs2015_bin_dir = vs2015_vcvarsall_bat.parent_path() / "bin";
+ std::vector<ToolsetArchOption> supported_architectures;
+ if (fs.exists(vs2015_bin_dir / "vcvars32.bat"))
+ supported_architectures.push_back({L"x86", CPU::X86, CPU::X86});
+ if (fs.exists(vs2015_bin_dir / "amd64\\vcvars64.bat"))
+ supported_architectures.push_back({L"x64", CPU::X64, CPU::X64});
+ if (fs.exists(vs2015_bin_dir / "x86_amd64\\vcvarsx86_amd64.bat"))
+ supported_architectures.push_back({L"x86_amd64", CPU::X86, CPU::X64});
+ if (fs.exists(vs2015_bin_dir / "x86_arm\\vcvarsx86_arm.bat"))
+ supported_architectures.push_back({L"x86_arm", CPU::X86, CPU::ARM});
+ if (fs.exists(vs2015_bin_dir / "amd64_x86\\vcvarsamd64_x86.bat"))
+ supported_architectures.push_back({L"amd64_x86", CPU::X64, CPU::X86});
+ if (fs.exists(vs2015_bin_dir / "amd64_arm\\vcvarsamd64_arm.bat"))
+ supported_architectures.push_back({L"amd64_arm", CPU::X64, CPU::ARM});
+
if (fs.exists(vs2015_dumpbin_exe))
{
- found_toolsets.push_back({vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140"});
+ found_toolsets.push_back(
+ {vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140", supported_architectures});
}
}
}
// VS2017
Optional<Toolset> vs2017_toolset;
- for (const fs::path& instance : vs2017_installation_instances)
+ for (const std::string& instance : vs2017_installation_instances)
{
- const fs::path vc_dir = instance / "VC";
+ const fs::path vc_dir = fs::path{instance} / "VC";
// Skip any instances that do not have vcvarsall.
- const fs::path vcvarsall_bat = vc_dir / "Auxiliary" / "Build" / "vcvarsall.bat";
+ const fs::path vcvarsall_dir = vc_dir / "Auxiliary" / "Build";
+ const fs::path vcvarsall_bat = vcvarsall_dir / "vcvarsall.bat";
paths_examined.push_back(vcvarsall_bat);
if (!fs.exists(vcvarsall_bat)) continue;
+ // 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});
+ if (fs.exists(vcvarsall_dir / "vcvars64.bat"))
+ supported_architectures.push_back({L"amd64", CPU::X64, CPU::X64});
+ if (fs.exists(vcvarsall_dir / "vcvarsx86_amd64.bat"))
+ supported_architectures.push_back({L"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});
+ if (fs.exists(vcvarsall_dir / "vcvarsamd64_x86.bat"))
+ supported_architectures.push_back({L"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});
+
// Locate the "best" MSVC toolchain version
const fs::path msvc_path = vc_dir / "Tools" / "MSVC";
std::vector<fs::path> msvc_subdirectories = fs.get_files_non_recursive(msvc_path);
@@ -331,11 +359,11 @@ namespace vcpkg
paths_examined.push_back(dumpbin_path);
if (fs.exists(dumpbin_path))
{
- vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, L"v141"};
+ vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, L"v141", supported_architectures};
break;
}
}
- if (auto value = vs2017_toolset.get())
+ if (const auto value = vs2017_toolset.get())
{
found_toolsets.push_back(*value);
break;
@@ -365,15 +393,12 @@ namespace vcpkg
{
return vs_toolsets.back();
}
- else
- {
- const auto toolset = Util::find_if(vs_toolsets, [&](const Toolset& toolset) {
- return toolset_version == Strings::to_utf8(toolset.version);
- });
- Checks::check_exit(
- VCPKG_LINE_INFO, toolset != vs_toolsets.end(), "Could not find toolset '%s'", toolset_version);
- return *toolset;
- }
+
+ const auto toolset = Util::find_if(
+ vs_toolsets, [&](const Toolset& t) { return toolset_version == Strings::to_utf8(t.version); });
+ Checks::check_exit(
+ VCPKG_LINE_INFO, toolset != vs_toolsets.end(), "Could not find toolset '%s'", toolset_version);
+ return *toolset;
}
Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); }
diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp
index 6c38c452b..bb3a6cefd 100644
--- a/toolsrc/src/coff_file_reader.cpp
+++ b/toolsrc/src/coff_file_reader.cpp
@@ -5,7 +5,7 @@
using namespace std;
-namespace vcpkg::COFFFileReader
+namespace vcpkg::CoffFileReader
{
template<class T>
static T reinterpret_bytes(const char* data)
@@ -24,7 +24,7 @@ namespace vcpkg::COFFFileReader
template<class T>
static T peek_value_from_stream(fstream& fs)
{
- fpos_t original_pos = fs.tellg().seekpos();
+ const fpos_t original_pos = fs.tellg().seekpos();
T data;
fs.read(reinterpret_cast<char*>(&data), sizeof data);
fs.seekg(original_pos);
@@ -236,7 +236,7 @@ namespace vcpkg::COFFFileReader
read_and_verify_PE_signature(fs);
CoffFileHeader header = CoffFileHeader::read(fs);
- MachineType machine = header.machine_type();
+ const MachineType machine = header.machine_type();
return {machine};
}
@@ -282,7 +282,7 @@ namespace vcpkg::COFFFileReader
marker.advance_by(ArchiveMemberHeader::HEADER_SIZE + second_linker_member_header.member_size());
marker.seek_to_marker(fs);
- bool hasLongnameMemberHeader = peek_value_from_stream<uint16_t>(fs) == 0x2F2F;
+ const bool hasLongnameMemberHeader = peek_value_from_stream<uint16_t>(fs) == 0x2F2F;
if (hasLongnameMemberHeader)
{
const ArchiveMemberHeader longnames_member_header = ArchiveMemberHeader::read(fs);
diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp
index 4da9cede2..a69958058 100644
--- a/toolsrc/src/commands_build.cpp
+++ b/toolsrc/src/commands_build.cpp
@@ -29,8 +29,8 @@ namespace vcpkg::Commands::BuildCommand
const PackageSpec& spec = full_spec.package_spec;
if (options.find(OPTION_CHECKS_ONLY) != options.end())
{
- auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, spec.triplet());
- auto build_info = Build::read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec));
+ 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));
const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info);
Checks::check_exit(VCPKG_LINE_INFO, error_count == 0);
Checks::exit_success(VCPKG_LINE_INFO);
@@ -45,7 +45,7 @@ namespace vcpkg::Commands::BuildCommand
Checks::exit_fail(VCPKG_LINE_INFO);
}
- for (std::string str : full_spec.features)
+ for (const std::string& str : full_spec.features)
{
System::println("%s \n", str);
}
@@ -56,8 +56,8 @@ namespace vcpkg::Commands::BuildCommand
scf->core_paragraph->name,
spec.name());
- StatusParagraphs status_db = database_load_check(paths);
- Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES};
+ const StatusParagraphs status_db = database_load_check(paths);
+ const Build::BuildPackageOptions build_package_options{Build::UseHeadVersion::NO, Build::AllowDownloads::YES};
const Build::BuildPackageConfig build_config{
*scf->core_paragraph, spec.triplet(), paths.port_dir(spec), build_package_options};
@@ -68,12 +68,12 @@ namespace vcpkg::Commands::BuildCommand
System::println(System::Color::error,
"The build command requires all dependencies to be already installed.");
System::println("The following dependencies are missing:");
- System::println("");
+ System::println();
for (const auto& p : result.unmet_dependencies)
{
System::println(" %s", p);
}
- System::println("");
+ System::println();
Checks::exit_fail(VCPKG_LINE_INFO);
}
@@ -89,11 +89,11 @@ namespace vcpkg::Commands::BuildCommand
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
- static const std::string example = Commands::Help::create_example_string("build zlib:x64-windows");
- args.check_exact_arg_count(
- 1, example); // Build only takes a single package and all dependencies must already be installed
- std::string command_argument = args.command_arguments.at(0);
- const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, example);
+ static const std::string EXAMPLE = Commands::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 std::string command_argument = args.command_arguments.at(0);
+ const FullPackageSpec spec = Input::check_and_get_full_package_spec(command_argument, default_triplet, EXAMPLE);
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});
diff --git a/toolsrc/src/commands_build_external.cpp b/toolsrc/src/commands_build_external.cpp
index ff70e9cf2..7e85f2250 100644
--- a/toolsrc/src/commands_build_external.cpp
+++ b/toolsrc/src/commands_build_external.cpp
@@ -2,17 +2,16 @@
#include "vcpkg_Commands.h"
#include "vcpkg_Input.h"
-#include "vcpkg_System.h"
namespace vcpkg::Commands::BuildExternal
{
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
- static const std::string example =
+ static const std::string EXAMPLE =
Commands::Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)");
- args.check_exact_arg_count(2, example);
+ 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);
+ Input::check_and_get_full_package_spec(args.command_arguments.at(0), default_triplet, EXAMPLE);
Input::check_triplet(spec.package_spec.triplet(), paths);
const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({});
diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp
index 75de78461..5b65b197f 100644
--- a/toolsrc/src/commands_cache.cpp
+++ b/toolsrc/src/commands_cache.cpp
@@ -15,7 +15,7 @@ namespace vcpkg::Commands::Cache
{
const Expected<std::unordered_map<std::string, std::string>> pghs =
Paragraphs::get_single_paragraph(paths.get_filesystem(), path / "CONTROL");
- if (auto p = pghs.get())
+ if (const auto p = pghs.get())
{
const BinaryParagraph binary_paragraph = BinaryParagraph(*p);
output.push_back(binary_paragraph);
@@ -27,10 +27,10 @@ namespace vcpkg::Commands::Cache
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string example = Strings::format(
+ 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",
Commands::Help::create_example_string("cache png"));
- args.check_max_arg_count(1, example);
+ args.check_max_arg_count(1, EXAMPLE);
args.check_and_get_optional_command_arguments({});
const std::vector<BinaryParagraph> binary_paragraphs = read_all_binary_paragraphs(paths);
diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp
index f781adf69..75ff65556 100644
--- a/toolsrc/src/commands_ci.cpp
+++ b/toolsrc/src/commands_ci.cpp
@@ -13,9 +13,9 @@
namespace vcpkg::Commands::CI
{
+ using Build::BuildResult;
using Dependencies::InstallPlanAction;
using Dependencies::InstallPlanType;
- using Build::BuildResult;
static std::vector<PackageSpec> load_all_package_specs(Files::Filesystem& fs,
const fs::path& ports_directory,
@@ -30,8 +30,8 @@ namespace vcpkg::Commands::CI
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
- static const std::string example = Commands::Help::create_example_string("ci x64-windows");
- args.check_max_arg_count(1, example);
+ static const std::string EXAMPLE = Commands::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;
@@ -41,57 +41,19 @@ namespace vcpkg::Commands::CI
StatusParagraphs status_db = database_load_check(paths);
const auto& paths_port_file = Dependencies::PathsPortFile(paths);
- const std::vector<InstallPlanAction> install_plan =
+ std::vector<InstallPlanAction> install_plan =
Dependencies::create_install_plan(paths_port_file, specs, status_db);
Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty");
- std::vector<BuildResult> results;
- std::vector<std::string> timing;
- const ElapsedTime timer = ElapsedTime::create_started();
- size_t counter = 0;
- const size_t package_count = install_plan.size();
const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, Build::AllowDownloads::YES};
- for (const InstallPlanAction& action : install_plan)
- {
- const ElapsedTime build_timer = ElapsedTime::create_started();
- counter++;
- const std::string display_name = action.spec.to_string();
- System::println("Starting package %d/%d: %s", counter, package_count, display_name);
-
- timing.push_back("0");
- results.push_back(BuildResult::NULLVALUE);
-
- const BuildResult result =
- Install::perform_install_plan_action(paths, action, install_plan_options, status_db);
- timing.back() = build_timer.to_string();
- results.back() = result;
- System::println("Elapsed time for package %s: %s", action.spec, build_timer.to_string());
- }
-
- System::println("Total time taken: %s", timer.to_string());
-
- for (size_t i = 0; i < results.size(); i++)
- {
- System::println("%s: %s: %s", install_plan[i].spec, Build::to_string(results[i]), timing[i]);
- }
-
- std::map<BuildResult, int> summary;
- for (const BuildResult& v : Build::BuildResult_values)
- {
- summary[v] = 0;
- }
-
- for (const BuildResult& r : results)
- {
- summary[r]++;
- }
+ const std::vector<Dependencies::AnyAction> action_plan =
+ Util::fmap(install_plan, [](InstallPlanAction& install_action) {
+ return Dependencies::AnyAction(std::move(install_action));
+ });
- System::println("\n\nSUMMARY");
- for (const std::pair<const BuildResult, int>& entry : summary)
- {
- System::println(" %s: %d", Build::to_string(entry.first), entry.second);
- }
+ Install::perform_and_exit(
+ action_plan, install_plan_options, Install::KeepGoing::YES, Install::PrintSummary::YES, paths, status_db);
Checks::exit_success(VCPKG_LINE_INFO);
}
diff --git a/toolsrc/src/commands_contact.cpp b/toolsrc/src/commands_contact.cpp
index 7f4161802..8374350ee 100644
--- a/toolsrc/src/commands_contact.cpp
+++ b/toolsrc/src/commands_contact.cpp
@@ -7,8 +7,8 @@ namespace vcpkg::Commands::Contact
{
const std::string& email()
{
- static const std::string s_email = R"(vcpkg@microsoft.com)";
- return s_email;
+ static const std::string S_EMAIL = R"(vcpkg@microsoft.com)";
+ return S_EMAIL;
}
void perform_and_exit(const VcpkgCmdArguments& args)
diff --git a/toolsrc/src/commands_create.cpp b/toolsrc/src/commands_create.cpp
index 7f85b776a..6898f7399 100644
--- a/toolsrc/src/commands_create.cpp
+++ b/toolsrc/src/commands_create.cpp
@@ -2,7 +2,6 @@
#include "vcpkg_Commands.h"
#include "vcpkg_Files.h"
-#include "vcpkg_Input.h"
#include "vcpkg_System.h"
#include "vcpkglib.h"
@@ -10,10 +9,10 @@ namespace vcpkg::Commands::Create
{
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string example = Commands::Help::create_example_string(
+ static const std::string EXAMPLE = Commands::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_max_arg_count(3, EXAMPLE);
+ args.check_min_arg_count(2, EXAMPLE);
args.check_and_get_optional_command_arguments({});
const std::string port_name = args.command_arguments.at(0);
const std::string url = args.command_arguments.at(1);
diff --git a/toolsrc/src/commands_depends.cpp b/toolsrc/src/commands_depends.cpp
index 2d1fb658b..17cd9c881 100644
--- a/toolsrc/src/commands_depends.cpp
+++ b/toolsrc/src/commands_depends.cpp
@@ -10,8 +10,8 @@ namespace vcpkg::Commands::DependInfo
{
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string example = Commands::Help::create_example_string(R"###(depend-info [pat])###");
- args.check_max_arg_count(1, example);
+ static const std::string EXAMPLE = Commands::Help::create_example_string(R"###(depend-info [pat])###");
+ args.check_max_arg_count(1, EXAMPLE);
args.check_and_get_optional_command_arguments({});
std::vector<std::unique_ptr<SourceControlFile>> source_control_files =
@@ -33,7 +33,7 @@ namespace vcpkg::Commands::DependInfo
for (const Dependency& dependency : source_paragraph.depends)
{
- if (Strings::case_insensitive_ascii_contains(dependency.name, filter))
+ if (Strings::case_insensitive_ascii_contains(dependency.name(), filter))
{
return false;
}
@@ -46,7 +46,7 @@ namespace vcpkg::Commands::DependInfo
for (auto&& source_control_file : source_control_files)
{
const SourceParagraph& source_paragraph = *source_control_file->core_paragraph;
- auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name; });
+ const auto s = Strings::join(", ", source_paragraph.depends, [](const Dependency& d) { return d.name(); });
System::println("%s: %s", source_paragraph.name, s);
}
diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp
index 4e83fcca8..823c87534 100644
--- a/toolsrc/src/commands_edit.cpp
+++ b/toolsrc/src/commands_edit.cpp
@@ -6,77 +6,81 @@
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)",
+ };
+
+ std::vector<fs::path> output;
+ for (auto&& keypath : REGKEYS)
+ {
+ const Optional<std::wstring> code_installpath =
+ System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation");
+ if (const auto c = code_installpath.get())
+ {
+ const fs::path install_path = fs::path(*c);
+ output.push_back(install_path / "Code - Insiders.exe");
+ output.push_back(install_path / "Code.exe");
+ }
+ }
+ return output;
+ }
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
+ static const std::string OPTION_BUILDTREES = "--buildtrees";
+
+ static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe";
+ static const fs::path VS_CODE = fs::path{"Microsoft VS Code"} / "Code.exe";
+
auto& fs = paths.get_filesystem();
- static const std::string example = Commands::Help::create_example_string("edit zlib");
- args.check_exact_arg_count(1, example);
- args.check_and_get_optional_command_arguments({});
+ static const std::string EXAMPLE = Commands::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 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);
- // Find the user's selected editor
- std::wstring env_EDITOR;
+ std::vector<fs::path> candidate_paths;
+ const std::vector<fs::path> from_path = Files::find_from_PATH(L"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);
+ candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE);
+ candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE);
- if (env_EDITOR.empty())
- {
- const Optional<std::wstring> env_EDITOR_optional = System::get_environment_variable(L"EDITOR");
- if (auto e = env_EDITOR_optional.get())
- {
- env_EDITOR = *e;
- }
- }
+ const std::vector<fs::path> from_registry = find_from_registry();
+ candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend());
- if (env_EDITOR.empty())
+ auto it = Util::find_if(candidate_paths, [&](const fs::path& p) { return fs.exists(p); });
+ if (it == candidate_paths.cend())
{
- const fs::path CODE_EXE_PATH = System::get_ProgramFiles_32_bit() / "Microsoft VS Code/Code.exe";
- if (fs.exists(CODE_EXE_PATH))
- {
- env_EDITOR = CODE_EXE_PATH;
- }
+ System::println(System::Color::error,
+ "Error: Visual Studio Code was not found and the environment variable EDITOR is not set.");
+ System::println("The following paths were examined:");
+ Files::print_paths(candidate_paths);
+ System::println("You can also set the environmental variable EDITOR to your editor of choice.");
+ Checks::exit_fail(VCPKG_LINE_INFO);
}
- if (env_EDITOR.empty())
+ const fs::path env_editor = *it;
+ if (options.find(OPTION_BUILDTREES) != options.cend())
{
- static const std::array<const wchar_t*, 4> regkeys = {
- LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)",
- LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{C26E74D1-022E-4238-8B9D-1E7564A36CC9}_is1)",
- LR"(SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)",
- LR"(SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F8A2A208-72B3-4D61-95FC-8A65D340689B}_is1)",
- };
- for (auto&& keypath : regkeys)
- {
- const Optional<std::wstring> code_installpath =
- System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation");
- if (auto c = code_installpath.get())
- {
- auto p = fs::path(*c) / "Code.exe";
- if (fs.exists(p))
- {
- env_EDITOR = p.native();
- break;
- }
- auto p_insiders = fs::path(*c) / "Code - Insiders.exe";
- if (fs.exists(p_insiders))
- {
- env_EDITOR = p_insiders.native();
- break;
- }
- }
- }
- }
+ const auto buildtrees_current_dir = paths.buildtrees / port_name;
- if (env_EDITOR.empty())
- {
- Checks::exit_with_message(
- VCPKG_LINE_INFO, "Visual Studio Code was not found and the environment variable EDITOR is not set");
+ const std::wstring cmd_line =
+ Strings::wformat(LR"("%s" "%s" -n)", env_editor, buildtrees_current_dir.native());
+ Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line));
}
- std::wstring cmdLine = Strings::wformat(
- LR"("%s" "%s" "%s" -n)", env_EDITOR, portpath.native(), (portpath / "portfile.cmake").native());
- Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmdLine));
+ const std::wstring cmd_line = Strings::wformat(
+ LR"("%s" "%s" "%s" -n)", env_editor, portpath.native(), (portpath / "portfile.cmake").native());
+ Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line));
}
}
diff --git a/toolsrc/src/commands_env.cpp b/toolsrc/src/commands_env.cpp
index dd7172b89..073c501f5 100644
--- a/toolsrc/src/commands_env.cpp
+++ b/toolsrc/src/commands_env.cpp
@@ -8,12 +8,13 @@ namespace vcpkg::Commands::Env
{
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
- static const std::string example = Commands::Help::create_example_string(R"(env --Triplet x64-windows)");
- args.check_exact_arg_count(0, example);
+ static const std::string EXAMPLE = Commands::Help::create_example_string(R"(env --Triplet x64-windows)");
+ args.check_exact_arg_count(0, EXAMPLE);
args.check_and_get_optional_command_arguments({});
- auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet);
- System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, paths.get_toolset(pre_build_info.platform_toolset)) + L" && cmd");
+ const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet);
+ System::cmd_execute_clean(
+ Build::make_build_env_cmd(pre_build_info, paths.get_toolset(pre_build_info.platform_toolset)) + L" && cmd");
Checks::exit_success(VCPKG_LINE_INFO);
}
diff --git a/toolsrc/src/commands_export.cpp b/toolsrc/src/commands_export.cpp
index 4adfbc0f6..b416a6f3c 100644
--- a/toolsrc/src/commands_export.cpp
+++ b/toolsrc/src/commands_export.cpp
@@ -11,17 +11,17 @@
namespace vcpkg::Commands::Export
{
- using Install::InstallDir;
using Dependencies::ExportPlanAction;
- using Dependencies::RequestType;
using Dependencies::ExportPlanType;
+ using Dependencies::RequestType;
+ using Install::InstallDir;
static std::string create_nuspec_file_contents(const std::string& raw_exported_dir,
const std::string& targets_redirect_path,
const std::string& nuget_id,
const std::string& nupkg_version)
{
- static constexpr auto content_template = R"(
+ static constexpr auto CONTENT_TEMPLATE = R"(
<package>
<metadata>
<id>@NUGET_ID@</id>
@@ -40,7 +40,7 @@ namespace vcpkg::Commands::Export
</package>
)";
- std::string nuspec_file_content = std::regex_replace(content_template, std::regex("@NUGET_ID@"), nuget_id);
+ 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);
nuspec_file_content =
std::regex_replace(nuspec_file_content, std::regex("@RAW_EXPORTED_DIR@"), raw_exported_dir);
@@ -62,12 +62,12 @@ namespace vcpkg::Commands::Export
static void print_plan(const std::map<ExportPlanType, std::vector<const ExportPlanAction*>>& group_by_plan_type)
{
- static constexpr std::array<ExportPlanType, 2> order = {ExportPlanType::ALREADY_BUILT,
+ static constexpr std::array<ExportPlanType, 2> ORDER = {ExportPlanType::ALREADY_BUILT,
ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT};
- for (const ExportPlanType plan_type : order)
+ for (const ExportPlanType plan_type : ORDER)
{
- auto it = group_by_plan_type.find(plan_type);
+ const auto it = group_by_plan_type.find(plan_type);
if (it == group_by_plan_type.cend())
{
continue;
@@ -151,7 +151,7 @@ namespace vcpkg::Commands::Export
enum class BackingEnum
{
ZIP = 1,
- _7ZIP,
+ SEVEN_ZIP,
};
constexpr ArchiveFormat() = delete;
@@ -174,7 +174,7 @@ namespace vcpkg::Commands::Export
namespace ArchiveFormatC
{
constexpr const ArchiveFormat ZIP(ArchiveFormat::BackingEnum::ZIP, L"zip", L"zip");
- constexpr const ArchiveFormat _7ZIP(ArchiveFormat::BackingEnum::_7ZIP, L"7z", L"7zip");
+ constexpr const ArchiveFormat SEVEN_ZIP(ArchiveFormat::BackingEnum::SEVEN_ZIP, L"7z", L"7zip");
}
static fs::path do_archive_export(const VcpkgPaths& paths,
@@ -205,11 +205,9 @@ namespace vcpkg::Commands::Export
static Optional<std::string> maybe_lookup(std::unordered_map<std::string, std::string> const& m,
std::string const& key)
{
- auto it = m.find(key);
- if (it != m.end())
- return it->second;
- else
- return nullopt;
+ const auto it = m.find(key);
+ if (it != m.end()) return it->second;
+ return nullopt;
}
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
@@ -218,38 +216,43 @@ namespace vcpkg::Commands::Export
static const std::string OPTION_RAW = "--raw";
static const std::string OPTION_NUGET = "--nuget";
static const std::string OPTION_ZIP = "--zip";
- static const std::string OPTION_7ZIP = "--7zip";
+ 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";
// input sanitization
- static const std::string example =
+ static const std::string EXAMPLE =
Commands::Help::create_example_string("export zlib zlib:x64-windows boost --nuget");
- args.check_min_arg_count(1, example);
+ args.check_min_arg_count(1, EXAMPLE);
const std::vector<PackageSpec> 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, EXAMPLE);
});
for (auto&& spec : specs)
Input::check_triplet(spec.triplet(), paths);
const auto options = args.check_and_get_optional_command_arguments(
{
- OPTION_DRY_RUN, OPTION_RAW, OPTION_NUGET, OPTION_ZIP, OPTION_7ZIP,
+ OPTION_DRY_RUN,
+ OPTION_RAW,
+ OPTION_NUGET,
+ OPTION_ZIP,
+ OPTION_SEVEN_ZIP,
},
{
- OPTION_NUGET_ID, OPTION_NUGET_VERSION,
+ OPTION_NUGET_ID,
+ OPTION_NUGET_VERSION,
});
- const bool dryRun = options.switches.find(OPTION_DRY_RUN) != options.switches.cend();
+ const bool dry_run = options.switches.find(OPTION_DRY_RUN) != options.switches.cend();
const bool raw = options.switches.find(OPTION_RAW) != options.switches.cend();
const bool nuget = options.switches.find(OPTION_NUGET) != options.switches.cend();
const bool zip = options.switches.find(OPTION_ZIP) != options.switches.cend();
- const bool _7zip = options.switches.find(OPTION_7ZIP) != options.switches.cend();
+ const bool seven_zip = options.switches.find(OPTION_SEVEN_ZIP) != options.switches.cend();
- if (!raw && !nuget && !zip && !_7zip && !dryRun)
+ if (!raw && !nuget && !zip && !seven_zip && !dry_run)
{
System::println(System::Color::error, "Must provide at least one export type: --raw --nuget --zip --7zip");
- System::print(example);
+ System::print(EXAMPLE);
Checks::exit_fail(VCPKG_LINE_INFO);
}
@@ -261,7 +264,7 @@ namespace vcpkg::Commands::Export
VCPKG_LINE_INFO, !maybe_nuget_version || nuget, "--nuget-version is only valid with --nuget");
// create the plan
- StatusParagraphs status_db = database_load_check(paths);
+ const StatusParagraphs status_db = database_load_check(paths);
std::vector<ExportPlanAction> export_plan = Dependencies::create_export_plan(paths, specs, status_db);
Checks::check_exit(VCPKG_LINE_INFO, !export_plan.empty(), "Export plan cannot be empty");
@@ -280,7 +283,7 @@ namespace vcpkg::Commands::Export
"Additional packages (*) need to be exported to complete this operation.");
}
- auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT);
+ const auto it = group_by_plan_type.find(ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT);
if (it != group_by_plan_type.cend() && !it->second.empty())
{
System::println(System::Color::error, "There are packages that have not been built.");
@@ -290,14 +293,14 @@ namespace vcpkg::Commands::Export
Util::erase_remove_if(
unbuilt, [](const ExportPlanAction* a) { return a->request_type != RequestType::USER_REQUESTED; });
- auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); });
+ const auto s = Strings::join(" ", unbuilt, [](const ExportPlanAction* a) { return a->spec.to_string(); });
System::println("To build them, run:\n"
" vcpkg install %s",
s);
Checks::exit_fail(VCPKG_LINE_INFO);
}
- if (dryRun)
+ if (dry_run)
{
Checks::exit_success(VCPKG_LINE_INFO);
}
@@ -323,7 +326,7 @@ namespace vcpkg::Commands::Export
System::println("Exporting package %s... ", display_name);
const BinaryParagraph& binary_paragraph =
- action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO);
+ action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO).core_paragraph;
const InstallDir dirs = InstallDir::from_destination_root(
raw_exported_dir_path / "installed",
action.spec.triplet().to_string(),
@@ -355,7 +358,7 @@ namespace vcpkg::Commands::Export
Checks::check_exit(VCPKG_LINE_INFO, !ec);
}
- auto print_next_step_info = [](const fs::path& prefix) {
+ const auto 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());
@@ -404,11 +407,11 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
print_next_step_info("[...]");
}
- if (_7zip)
+ if (seven_zip)
{
System::println("Creating 7zip archive... ");
const fs::path output_path =
- do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::_7ZIP);
+ do_archive_export(paths, raw_exported_dir_path, export_to_path, ArchiveFormatC::SEVEN_ZIP);
System::println(System::Color::success, "Creating 7zip archive... done");
System::println(System::Color::success, "7zip archive exported at: %s", output_path.generic_string());
print_next_step_info("[...]");
diff --git a/toolsrc/src/commands_hash.cpp b/toolsrc/src/commands_hash.cpp
index 0da2b031f..b3211b9f8 100644
--- a/toolsrc/src/commands_hash.cpp
+++ b/toolsrc/src/commands_hash.cpp
@@ -6,22 +6,22 @@
namespace vcpkg::Commands::Hash
{
- static void do_file_hash(fs::path const& path, std::wstring const& hashType)
+ static void do_file_hash(fs::path const& path, std::wstring const& hash_type)
{
- auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.c_str(), hashType);
- auto ec_data = System::cmd_execute_and_capture_output(cmd_line);
+ const auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)", path.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));
std::string const& output = ec_data.output;
- auto start = output.find_first_of("\r\n");
+ 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));
- auto end = output.find_first_of("\r\n", start + 1);
+ 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",
@@ -34,11 +34,11 @@ namespace vcpkg::Commands::Hash
void perform_and_exit(const VcpkgCmdArguments& args)
{
- static const std::string example =
+ static const std::string EXAMPLE =
Strings::format("The argument should be a file path\n%s",
Commands::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_min_arg_count(1, EXAMPLE);
+ args.check_max_arg_count(2, EXAMPLE);
args.check_and_get_optional_command_arguments({});
if (args.command_arguments.size() == 1)
diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp
index 5db1885b2..412a03d7f 100644
--- a/toolsrc/src/commands_import.cpp
+++ b/toolsrc/src/commands_import.cpp
@@ -28,7 +28,7 @@ namespace vcpkg::Commands::Import
for (auto&& file : files)
{
if (fs.is_directory(file)) continue;
- auto ext = file.extension();
+ const auto ext = file.extension();
if (ext == ".dll")
binaries.dlls.push_back(std::move(file));
else if (ext == ".lib")
@@ -46,7 +46,7 @@ namespace vcpkg::Commands::Import
for (auto const& src_path : files)
{
- fs::path dest_path = destination_folder / src_path.filename();
+ const fs::path dest_path = destination_folder / src_path.filename();
fs.copy(src_path, dest_path, fs::copy_options::overwrite_existing);
}
}
@@ -59,10 +59,10 @@ namespace vcpkg::Commands::Import
check_is_directory(VCPKG_LINE_INFO, fs, include_directory);
check_is_directory(VCPKG_LINE_INFO, fs, project_directory);
check_is_directory(VCPKG_LINE_INFO, fs, destination_path);
- Binaries debug_binaries = find_binaries_in_dir(fs, project_directory / "Debug");
- Binaries release_binaries = find_binaries_in_dir(fs, project_directory / "Release");
+ const Binaries debug_binaries = find_binaries_in_dir(fs, project_directory / "Debug");
+ const Binaries release_binaries = find_binaries_in_dir(fs, project_directory / "Release");
- fs::path destination_include_directory = destination_path / "include";
+ const fs::path destination_include_directory = destination_path / "include";
fs.copy(include_directory,
destination_include_directory,
fs::copy_options::recursive | fs::copy_options::overwrite_existing);
@@ -82,20 +82,20 @@ namespace vcpkg::Commands::Import
const BinaryParagraph& control_file_data)
{
auto& fs = paths.get_filesystem();
- fs::path library_destination_path = paths.package_dir(control_file_data.spec);
+ const fs::path library_destination_path = paths.package_dir(control_file_data.spec);
std::error_code ec;
fs.create_directory(library_destination_path, ec);
place_library_files_in(paths.get_filesystem(), include_directory, project_directory, library_destination_path);
- fs::path control_file_path = library_destination_path / "CONTROL";
+ const fs::path control_file_path = library_destination_path / "CONTROL";
fs.write_contents(control_file_path, Strings::serialize(control_file_data));
}
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string example = Commands::Help::create_example_string(
+ static const std::string EXAMPLE = Commands::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_exact_arg_count(3, EXAMPLE);
args.check_and_get_optional_command_arguments({});
const fs::path control_file_path(args.command_arguments[0]);
diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp
index 2ce5b6c62..aca25996e 100644
--- a/toolsrc/src/commands_install.cpp
+++ b/toolsrc/src/commands_install.cpp
@@ -6,6 +6,7 @@
#include "vcpkg_Commands.h"
#include "vcpkg_Dependencies.h"
#include "vcpkg_Files.h"
+#include "vcpkg_GlobalState.h"
#include "vcpkg_Input.h"
#include "vcpkg_System.h"
#include "vcpkg_Util.h"
@@ -13,11 +14,7 @@
namespace vcpkg::Commands::Install
{
- using Dependencies::InstallPlanAction;
- using Dependencies::RequestType;
- using Dependencies::InstallPlanType;
- using Dependencies::RemovePlanAction;
- using Dependencies::RemovePlanType;
+ using namespace Dependencies;
InstallDir InstallDir::from_destination_root(const fs::path& destination_root,
const std::string& destination_subdirectory,
@@ -62,7 +59,7 @@ namespace vcpkg::Commands::Install
auto files = fs.get_files_recursive(source_dir);
for (auto&& file : files)
{
- auto status = fs.status(file, ec);
+ const auto status = fs.status(file, ec);
if (ec)
{
System::println(System::Color::error, "failed: %s: %s", file.u8string(), ec.message());
@@ -176,45 +173,10 @@ namespace vcpkg::Commands::Install
return SortedVector<std::string>(std::move(installed_files));
}
- static void print_plan(const std::map<InstallPlanType, std::vector<const InstallPlanAction*>>& group_by_plan_type)
+ InstallResult install_package(const VcpkgPaths& paths, const BinaryControlFile& bcf, StatusParagraphs* status_db)
{
- static constexpr std::array<InstallPlanType, 3> order = {
- InstallPlanType::ALREADY_INSTALLED, InstallPlanType::BUILD_AND_INSTALL, InstallPlanType::INSTALL};
-
- for (const InstallPlanType plan_type : order)
- {
- auto it = group_by_plan_type.find(plan_type);
- if (it == group_by_plan_type.cend())
- {
- continue;
- }
-
- std::vector<const InstallPlanAction*> cont = it->second;
- std::sort(cont.begin(), cont.end(), &InstallPlanAction::compare_by_name);
- const std::string as_string = Strings::join("\n", cont, [](const InstallPlanAction* p) {
- return Dependencies::to_output_string(p->request_type, p->spec.to_string());
- });
-
- switch (plan_type)
- {
- case InstallPlanType::ALREADY_INSTALLED:
- System::println("The following packages are already installed:\n%s", as_string);
- continue;
- case InstallPlanType::BUILD_AND_INSTALL:
- System::println("The following packages will be built and installed:\n%s", as_string);
- continue;
- case InstallPlanType::INSTALL:
- System::println("The following packages will be installed:\n%s", as_string);
- continue;
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
- }
-
- void install_package(const VcpkgPaths& paths, const BinaryParagraph& binary_paragraph, StatusParagraphs* status_db)
- {
- const fs::path package_dir = paths.package_dir(binary_paragraph.spec);
- const Triplet& triplet = binary_paragraph.spec.triplet();
+ const fs::path package_dir = paths.package_dir(bcf.core_paragraph.spec);
+ const Triplet& triplet = bcf.core_paragraph.spec.triplet();
const std::vector<StatusParagraphAndAssociatedFiles> pgh_and_files = get_installed_files(paths, *status_db);
const SortedVector<std::string> package_files =
@@ -234,35 +196,52 @@ namespace vcpkg::Commands::Install
System::println(System::Color::error,
"The following files are already installed in %s and are in conflict with %s",
triplet_install_path.generic_string(),
- binary_paragraph.spec);
+ bcf.core_paragraph.spec);
System::print("\n ");
System::println(Strings::join("\n ", intersection));
- System::println("");
- Checks::exit_fail(VCPKG_LINE_INFO);
+ System::println();
+ return InstallResult::FILE_CONFLICTS;
}
StatusParagraph source_paragraph;
- source_paragraph.package = binary_paragraph;
+ source_paragraph.package = bcf.core_paragraph;
source_paragraph.want = Want::INSTALL;
source_paragraph.state = InstallState::HALF_INSTALLED;
- for (auto&& dep : source_paragraph.package.depends)
- {
- if (status_db->find_installed(dep, source_paragraph.package.spec.triplet()) == status_db->end())
- {
- Checks::unreachable(VCPKG_LINE_INFO);
- }
- }
+
write_update(paths, source_paragraph);
status_db->insert(std::make_unique<StatusParagraph>(source_paragraph));
+ std::vector<StatusParagraph> features_spghs;
+ for (auto&& feature : bcf.features)
+ {
+ features_spghs.emplace_back();
+
+ StatusParagraph& feature_paragraph = features_spghs.back();
+ feature_paragraph.package = feature;
+ feature_paragraph.want = Want::INSTALL;
+ feature_paragraph.state = InstallState::HALF_INSTALLED;
+
+ write_update(paths, feature_paragraph);
+ status_db->insert(std::make_unique<StatusParagraph>(feature_paragraph));
+ }
+
const InstallDir install_dir = InstallDir::from_destination_root(
- paths.installed, triplet.to_string(), paths.listfile_path(binary_paragraph));
+ paths.installed, triplet.to_string(), paths.listfile_path(bcf.core_paragraph));
install_files_and_write_listfile(paths.get_filesystem(), package_dir, install_dir);
source_paragraph.state = InstallState::INSTALLED;
write_update(paths, source_paragraph);
status_db->insert(std::make_unique<StatusParagraph>(source_paragraph));
+
+ for (auto&& feature_paragraph : features_spghs)
+ {
+ feature_paragraph.state = InstallState::INSTALLED;
+ write_update(paths, feature_paragraph);
+ status_db->insert(std::make_unique<StatusParagraph>(feature_paragraph));
+ }
+
+ return InstallResult::SUCCESS;
}
using Build::BuildResult;
@@ -274,6 +253,8 @@ namespace vcpkg::Commands::Install
{
const InstallPlanType& plan_type = action.plan_type;
const std::string display_name = action.spec.to_string();
+ const std::string display_name_with_features =
+ 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);
@@ -281,75 +262,65 @@ namespace vcpkg::Commands::Install
if (plan_type == InstallPlanType::ALREADY_INSTALLED)
{
if (use_head_version && is_user_requested)
- {
System::println(
System::Color::warning, "Package %s is already installed -- not building from HEAD", display_name);
- }
else
- {
System::println(System::Color::success, "Package %s is already installed", display_name);
- }
return BuildResult::SUCCEEDED;
}
- if (plan_type == InstallPlanType::BUILD_AND_INSTALL && !g_feature_packages)
+ if (plan_type == InstallPlanType::BUILD_AND_INSTALL)
{
if (use_head_version)
- System::println("Building package %s from HEAD... ", display_name);
+ System::println("Building package %s from HEAD... ", display_name_with_features);
else
- System::println("Building package %s... ", display_name);
-
- const Build::BuildPackageConfig build_config{
- action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO),
- action.spec.triplet(),
- paths.port_dir(action.spec),
- build_package_options};
- const auto result = Build::build_package(paths, build_config, status_db);
+ System::println("Building package %s... ", display_name_with_features);
+
+ const auto result = [&]() -> Build::ExtendedBuildResult {
+ if (GlobalState::feature_packages)
+ {
+ const Build::BuildPackageConfig build_config{
+ *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO),
+ action.spec.triplet(),
+ paths.port_dir(action.spec),
+ build_package_options,
+ action.feature_list};
+ return Build::build_package(paths, build_config, status_db);
+ }
+ else
+ {
+ const Build::BuildPackageConfig build_config{
+ action.any_paragraph.source_paragraph.value_or_exit(VCPKG_LINE_INFO),
+ action.spec.triplet(),
+ paths.port_dir(action.spec),
+ build_package_options};
+ return Build::build_package(paths, build_config, status_db);
+ }
+ }();
+
if (result.code != Build::BuildResult::SUCCEEDED)
{
System::println(System::Color::error, Build::create_error_message(result.code, action.spec));
return result.code;
}
- System::println("Building package %s... done", display_name);
- const BinaryParagraph bpgh =
- Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO);
- System::println("Installing package %s... ", display_name);
- install_package(paths, bpgh, &status_db);
- System::println(System::Color::success, "Installing package %s... done", display_name);
- return BuildResult::SUCCEEDED;
- }
+ System::println("Building package %s... done", display_name_with_features);
- if (plan_type == InstallPlanType::BUILD_AND_INSTALL && g_feature_packages)
- {
- if (use_head_version)
- System::println("Building package %s from HEAD... ", display_name);
- else
- System::println("Building package %s... ", display_name);
-
- const Build::BuildPackageConfig build_config{
- *action.any_paragraph.source_control_file.value_or_exit(VCPKG_LINE_INFO),
- action.spec.triplet(),
- paths.port_dir(action.spec),
- build_package_options,
- action.feature_list};
- const auto result = Build::build_package(paths, build_config, status_db);
- if (result.code != Build::BuildResult::SUCCEEDED)
+ const BinaryControlFile bcf =
+ Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO);
+ System::println("Installing package %s... ", display_name_with_features);
+ const auto install_result = install_package(paths, bcf, &status_db);
+ switch (install_result)
{
- System::println(System::Color::error, Build::create_error_message(result.code, action.spec));
- return result.code;
+ case InstallResult::SUCCESS:
+ System::println(System::Color::success, "Installing package %s... done", display_name);
+ return BuildResult::SUCCEEDED;
+ case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS;
+ default: Checks::unreachable(VCPKG_LINE_INFO);
}
- System::println("Building package %s... done", display_name);
-
- const BinaryParagraph bpgh =
- Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO);
- System::println("Installing package %s... ", display_name);
- install_package(paths, bpgh, &status_db);
- System::println(System::Color::success, "Installing package %s... done", display_name);
- return BuildResult::SUCCEEDED;
}
- if (plan_type == InstallPlanType::INSTALL && !g_feature_packages)
+ if (plan_type == InstallPlanType::INSTALL)
{
if (use_head_version && is_user_requested)
{
@@ -357,83 +328,286 @@ namespace vcpkg::Commands::Install
System::Color::warning, "Package %s is already built -- not building from HEAD", display_name);
}
System::println("Installing package %s... ", display_name);
- install_package(paths, action.any_paragraph.binary_paragraph.value_or_exit(VCPKG_LINE_INFO), &status_db);
- System::println(System::Color::success, "Installing package %s... done", display_name);
- return BuildResult::SUCCEEDED;
+ const auto install_result = install_package(
+ paths, action.any_paragraph.binary_control_file.value_or_exit(VCPKG_LINE_INFO), &status_db);
+ switch (install_result)
+ {
+ case InstallResult::SUCCESS:
+ System::println(System::Color::success, "Installing package %s... done", display_name);
+ return BuildResult::SUCCEEDED;
+ case InstallResult::FILE_CONFLICTS: return BuildResult::FILE_CONFLICTS;
+ default: Checks::unreachable(VCPKG_LINE_INFO);
+ }
}
Checks::unreachable(VCPKG_LINE_INFO);
}
+ static void print_plan(const std::vector<AnyAction>& action_plan, 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;
+
+ const bool has_non_user_requested_packages = Util::find_if(action_plan, [](const AnyAction& package) -> bool {
+ if (auto iplan = package.install_plan.get())
+ return iplan->request_type != RequestType::USER_REQUESTED;
+ else
+ return false;
+ }) != action_plan.cend();
+
+ for (auto&& action : action_plan)
+ {
+ if (auto install_action = action.install_plan.get())
+ {
+ // remove plans are guaranteed to come before install plans, so we know the plan will be contained if at
+ // all.
+ auto it = Util::find_if(
+ remove_plans, [&](const RemovePlanAction* plan) { return plan->spec == install_action->spec; });
+ if (it != remove_plans.end())
+ {
+ rebuilt_plans.emplace_back(install_action);
+ }
+ else
+ {
+ switch (install_action->plan_type)
+ {
+ case InstallPlanType::INSTALL: only_install_plans.emplace_back(install_action); break;
+ case InstallPlanType::ALREADY_INSTALLED:
+ if (install_action->request_type == RequestType::USER_REQUESTED)
+ already_installed_plans.emplace_back(install_action);
+ break;
+ case InstallPlanType::BUILD_AND_INSTALL: new_plans.emplace_back(install_action); break;
+ default: Checks::unreachable(VCPKG_LINE_INFO);
+ }
+ }
+ }
+ else if (auto remove_action = action.remove_plan.get())
+ {
+ remove_plans.emplace_back(remove_action);
+ }
+ }
+
+ std::sort(remove_plans.begin(), remove_plans.end(), &RemovePlanAction::compare_by_name);
+ std::sort(rebuilt_plans.begin(), rebuilt_plans.end(), &InstallPlanAction::compare_by_name);
+ std::sort(only_install_plans.begin(), only_install_plans.end(), &InstallPlanAction::compare_by_name);
+ std::sort(new_plans.begin(), new_plans.end(), &InstallPlanAction::compare_by_name);
+ std::sort(already_installed_plans.begin(), already_installed_plans.end(), &InstallPlanAction::compare_by_name);
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ 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);
+ }
+
+ if (has_non_user_requested_packages)
+ System::println("Additional packages (*) will be installed to complete this operation.");
+
+ if (remove_plans.size() > 0 && !is_recursive)
+ {
+ System::println(System::Color::warning,
+ "If you are sure you want to rebuild the above packages, run the command with the "
+ "--recurse option");
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ }
+
+ void perform_and_exit(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)
+ {
+ std::vector<BuildResult> results;
+ std::vector<std::string> timing;
+ const ElapsedTime timer = ElapsedTime::create_started();
+ size_t counter = 0;
+ const size_t package_count = action_plan.size();
+
+ for (const auto& action : action_plan)
+ {
+ const ElapsedTime build_timer = ElapsedTime::create_started();
+ counter++;
+
+ const std::string display_name = action.spec().to_string();
+ System::println("Starting package %d/%d: %s", counter, package_count, display_name);
+
+ timing.push_back("0");
+ results.push_back(BuildResult::NULLVALUE);
+
+ if (const auto install_action = action.install_plan.get())
+ {
+ const BuildResult result =
+ perform_install_plan_action(paths, *install_action, install_plan_options, 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;
+ }
+ else if (const auto remove_action = action.remove_plan.get())
+ {
+ Checks::check_exit(VCPKG_LINE_INFO, GlobalState::feature_packages);
+ Remove::perform_remove_plan_action(paths, *remove_action, Remove::Purge::YES, status_db);
+ }
+ else
+ {
+ Checks::unreachable(VCPKG_LINE_INFO);
+ }
+
+ timing.back() = 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);
+ }
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
static const std::string OPTION_DRY_RUN = "--dry-run";
static const std::string OPTION_USE_HEAD_VERSION = "--head";
static const std::string OPTION_NO_DOWNLOADS = "--no-downloads";
+ static const std::string OPTION_RECURSE = "--recurse";
+ static const std::string OPTION_KEEP_GOING = "--keep-going";
// input sanitization
- static const std::string example =
+ static const std::string EXAMPLE =
Commands::Help::create_example_string("install zlib zlib:x64-windows curl boost");
- args.check_min_arg_count(1, example);
+ args.check_min_arg_count(1, EXAMPLE);
- const std::vector<PackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
- return Input::check_and_get_package_spec(arg, default_triplet, example);
+ const std::vector<FullPackageSpec> specs = Util::fmap(args.command_arguments, [&](auto&& arg) {
+ return Input::check_and_get_full_package_spec(arg, default_triplet, EXAMPLE);
});
+
for (auto&& spec : specs)
- Input::check_triplet(spec.triplet(), paths);
+ {
+ Input::check_triplet(spec.package_spec.triplet(), paths);
+ if (!spec.features.empty() && !GlobalState::feature_packages)
+ {
+ Checks::exit_with_message(
+ VCPKG_LINE_INFO, "Feature packages are experimentally available under the --featurepackages flag.");
+ }
+ }
const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments(
- {OPTION_DRY_RUN, OPTION_USE_HEAD_VERSION, OPTION_NO_DOWNLOADS});
- const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend();
+ {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());
// create the plan
StatusParagraphs status_db = database_load_check(paths);
- Dependencies::PathsPortFile paths_port_file(paths);
- std::vector<InstallPlanAction> install_plan =
- Dependencies::create_install_plan(paths_port_file, specs, status_db);
- Checks::check_exit(VCPKG_LINE_INFO, !install_plan.empty(), "Install plan cannot be empty");
-
- // log the plan
- const std::string specs_string =
- Strings::join(",", install_plan, [](const InstallPlanAction& plan) { return plan.spec.to_string(); });
- Metrics::track_property("installplan", specs_string);
-
- std::map<InstallPlanType, std::vector<const InstallPlanAction*>> group_by_plan_type;
- Util::group_by(install_plan, &group_by_plan_type, [](const InstallPlanAction& p) { return p.plan_type; });
- print_plan(group_by_plan_type);
+ const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version),
+ Build::to_allow_downloads(!no_downloads)};
- const bool has_non_user_requested_packages =
- Util::find_if(install_plan, [](const InstallPlanAction& package) -> bool {
- return package.request_type != RequestType::USER_REQUESTED;
- }) != install_plan.cend();
+ std::vector<AnyAction> action_plan;
- if (has_non_user_requested_packages)
+ if (GlobalState::feature_packages)
{
- System::println("Additional packages (*) will be installed to complete this operation.");
+ std::unordered_map<std::string, SourceControlFile> scf_map;
+ auto all_ports = Paragraphs::try_load_all_ports(paths.get_filesystem(), paths.ports);
+ for (auto&& port : all_ports.paragraphs)
+ {
+ scf_map[port->core_paragraph->name] = std::move(*port);
+ }
+ action_plan = create_feature_install_plan(scf_map, FullPackageSpec::to_feature_specs(specs), status_db);
}
-
- if (dryRun)
+ else
{
- Checks::exit_success(VCPKG_LINE_INFO);
+ Dependencies::PathsPortFile paths_port_file(paths);
+ auto install_plan = Dependencies::create_install_plan(
+ paths_port_file, Util::fmap(specs, [](auto&& spec) { return spec.package_spec; }), status_db);
+
+ action_plan = Util::fmap(
+ install_plan, [](InstallPlanAction& install_action) { return AnyAction(std::move(install_action)); });
}
- const Build::BuildPackageOptions install_plan_options = {Build::to_use_head_version(use_head_version),
- Build::to_allow_downloads(!no_downloads)};
+ // 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");
- // execute the plan
- for (const InstallPlanAction& action : install_plan)
+ // log the plan
+ const std::string specs_string = Strings::join(",", action_plan, [](const AnyAction& action) {
+ if (auto iaction = action.install_plan.get())
+ return iaction->spec.to_string();
+ else if (auto raction = action.remove_plan.get())
+ return "R$" + raction->spec.to_string();
+ Checks::unreachable(VCPKG_LINE_INFO);
+ });
+
+ Metrics::g_metrics.lock()->track_property("installplan", specs_string);
+
+ print_plan(action_plan, is_recursive);
+
+ if (dry_run)
{
- const BuildResult result = perform_install_plan_action(paths, action, install_plan_options, status_db);
- if (result != BuildResult::SUCCEEDED)
- {
- System::println(Build::create_user_troubleshooting_message(action.spec));
- Checks::exit_fail(VCPKG_LINE_INFO);
- }
+ Checks::exit_success(VCPKG_LINE_INFO);
}
+ perform_and_exit(action_plan, install_plan_options, keep_going, PrintSummary::NO, paths, status_db);
+
Checks::exit_success(VCPKG_LINE_INFO);
}
}
diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp
index c5942f9fc..1bf26910c 100644
--- a/toolsrc/src/commands_integrate.cpp
+++ b/toolsrc/src/commands_integrate.cpp
@@ -8,11 +8,11 @@
namespace vcpkg::Commands::Integrate
{
- static const std::array<fs::path, 2> old_system_target_files = {
- System::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets",
- System::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"};
- static const fs::path system_wide_targets_file =
- System::get_ProgramFiles_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props";
+ 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
{
@@ -82,7 +82,7 @@ namespace vcpkg::Commands::Integrate
const std::string& nuget_id,
const std::string& nupkg_version)
{
- static constexpr auto content_template = R"(
+ static constexpr auto CONTENT_TEMPLATE = R"(
<package>
<metadata>
<id>@NUGET_ID@</id>
@@ -99,7 +99,7 @@ namespace vcpkg::Commands::Integrate
</package>
)";
- std::string content = std::regex_replace(content_template, std::regex("@NUGET_ID@"), nuget_id);
+ 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);
return content;
@@ -113,36 +113,36 @@ namespace vcpkg::Commands::Integrate
static ElevationPromptChoice elevated_cmd_execute(const std::string& param)
{
- SHELLEXECUTEINFO shExInfo = {0};
- shExInfo.cbSize = sizeof(shExInfo);
- shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
- shExInfo.hwnd = nullptr;
- shExInfo.lpVerb = "runas";
- shExInfo.lpFile = "cmd"; // Application to start
-
- shExInfo.lpParameters = param.c_str(); // Additional parameters
- shExInfo.lpDirectory = nullptr;
- shExInfo.nShow = SW_HIDE;
- shExInfo.hInstApp = nullptr;
-
- if (!ShellExecuteExA(&shExInfo))
+ SHELLEXECUTEINFO sh_ex_info = {0};
+ sh_ex_info.cbSize = sizeof(sh_ex_info);
+ sh_ex_info.fMask = SEE_MASK_NOCLOSEPROCESS;
+ sh_ex_info.hwnd = nullptr;
+ sh_ex_info.lpVerb = "runas";
+ sh_ex_info.lpFile = "cmd"; // Application to start
+
+ sh_ex_info.lpParameters = param.c_str(); // Additional parameters
+ sh_ex_info.lpDirectory = nullptr;
+ sh_ex_info.nShow = SW_HIDE;
+ sh_ex_info.hInstApp = nullptr;
+
+ if (!ShellExecuteExA(&sh_ex_info))
{
return ElevationPromptChoice::NO;
}
- if (shExInfo.hProcess == nullptr)
+ if (sh_ex_info.hProcess == nullptr)
{
return ElevationPromptChoice::NO;
}
- WaitForSingleObject(shExInfo.hProcess, INFINITE);
- CloseHandle(shExInfo.hProcess);
+ WaitForSingleObject(sh_ex_info.hProcess, INFINITE);
+ CloseHandle(sh_ex_info.hProcess);
return ElevationPromptChoice::YES;
}
static fs::path get_appdata_targets_path()
{
- static const fs::path local_app_data =
+ static const fs::path LOCAL_APP_DATA =
fs::path(System::get_environment_variable(L"LOCALAPPDATA").value_or_exit(VCPKG_LINE_INFO));
- return local_app_data / "vcpkg" / "vcpkg.user.targets";
+ return LOCAL_APP_DATA / "vcpkg" / "vcpkg.user.targets";
}
static void integrate_install(const VcpkgPaths& paths)
@@ -150,13 +150,13 @@ namespace vcpkg::Commands::Integrate
auto& fs = paths.get_filesystem();
// TODO: This block of code should eventually be removed
- for (auto&& old_system_wide_targets_file : old_system_target_files)
+ for (auto&& old_system_wide_targets_file : OLD_SYSTEM_TARGET_FILES)
{
if (fs.exists(old_system_wide_targets_file))
{
const std::string param =
Strings::format(R"(/c DEL "%s" /Q > nul)", old_system_wide_targets_file.string());
- ElevationPromptChoice user_choice = elevated_cmd_execute(param);
+ const ElevationPromptChoice user_choice = elevated_cmd_execute(param);
switch (user_choice)
{
case ElevationPromptChoice::YES: break;
@@ -174,15 +174,15 @@ namespace vcpkg::Commands::Integrate
fs.create_directory(tmp_dir, ec);
bool should_install_system = true;
- const Expected<std::string> system_wide_file_contents = fs.read_contents(system_wide_targets_file);
- if (auto contents_data = system_wide_file_contents.get())
+ const Expected<std::string> system_wide_file_contents = fs.read_contents(SYSTEM_WIDE_TARGETS_FILE);
+ static const std::regex RE(R"###(<!-- version (\d+) -->)###");
+ if (const auto contents_data = system_wide_file_contents.get())
{
- std::regex re(R"###(<!-- version (\d+) -->)###");
std::match_results<std::string::const_iterator> match;
- auto found = std::regex_search(*contents_data, match, re);
+ const auto found = std::regex_search(*contents_data, match, RE);
if (found)
{
- int ver = atoi(match[1].str().c_str());
+ const int ver = atoi(match[1].str().c_str());
if (ver >= 1) should_install_system = false;
}
}
@@ -193,10 +193,10 @@ namespace vcpkg::Commands::Integrate
fs.write_contents(sys_src_path, create_system_targets_shortcut());
const std::string param = Strings::format(R"(/c mkdir "%s" & copy "%s" "%s" /Y > nul)",
- system_wide_targets_file.parent_path().string(),
+ SYSTEM_WIDE_TARGETS_FILE.parent_path().string(),
sys_src_path.string(),
- system_wide_targets_file.string());
- ElevationPromptChoice user_choice = elevated_cmd_execute(param);
+ SYSTEM_WIDE_TARGETS_FILE.string());
+ const ElevationPromptChoice user_choice = elevated_cmd_execute(param);
switch (user_choice)
{
case ElevationPromptChoice::YES: break;
@@ -207,9 +207,9 @@ namespace vcpkg::Commands::Integrate
}
Checks::check_exit(VCPKG_LINE_INFO,
- fs.exists(system_wide_targets_file),
+ fs.exists(SYSTEM_WIDE_TARGETS_FILE),
"Error: failed to copy targets file to %s",
- system_wide_targets_file.string());
+ SYSTEM_WIDE_TARGETS_FILE.string());
}
const fs::path appdata_src_path = tmp_dir / "vcpkg.user.targets";
@@ -217,7 +217,7 @@ namespace vcpkg::Commands::Integrate
create_appdata_targets_shortcut(paths.buildsystems_msbuild_targets.string()));
auto appdata_dst_path = get_appdata_targets_path();
- auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec);
+ const auto rc = fs.copy_file(appdata_src_path, appdata_dst_path, fs::copy_options::overwrite_existing, ec);
if (!rc || ec)
{
@@ -245,7 +245,7 @@ namespace vcpkg::Commands::Integrate
const fs::path path = get_appdata_targets_path();
std::error_code ec;
- bool was_deleted = fs.remove(path, ec);
+ const bool was_deleted = fs.remove(path, ec);
Checks::check_exit(VCPKG_LINE_INFO, !ec, "Error: Unable to remove user-wide integration: %d", ec.message());
@@ -317,10 +317,10 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string example = Strings::format("Commands:\n"
+ static const std::string EXAMPLE = Strings::format("Commands:\n"
"%s",
INTEGRATE_COMMAND_HELPSTRING);
- args.check_exact_arg_count(1, example);
+ args.check_exact_arg_count(1, EXAMPLE);
args.check_and_get_optional_command_arguments({});
if (args.command_arguments[0] == "install")
diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp
index 9bc9bcc08..640885860 100644
--- a/toolsrc/src/commands_list.cpp
+++ b/toolsrc/src/commands_list.cpp
@@ -8,27 +8,27 @@ namespace vcpkg::Commands::List
{
static const std::string OPTION_FULLDESC = "--x-full-desc"; // TODO: This should find a better home, eventually
- static void do_print(const StatusParagraph& pgh, bool FullDesc)
+ static void do_print(const StatusParagraph& pgh, bool full_desc)
{
- if (FullDesc)
+ if (full_desc)
{
- System::println("%-27s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description);
+ System::println("%-30s %-16s %s", pgh.package.displayname(), pgh.package.version, pgh.package.description);
}
else
{
- System::println("%-27s %-16s %s",
- pgh.package.displayname(),
- pgh.package.version,
- vcpkg::shorten_description(pgh.package.description));
+ System::println("%-30s %-16s %s",
+ vcpkg::shorten_text(pgh.package.displayname(), 30),
+ vcpkg::shorten_text(pgh.package.version, 16),
+ vcpkg::shorten_text(pgh.package.description, 71));
}
}
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string example = Strings::format(
+ 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",
Commands::Help::create_example_string("list png"));
- args.check_max_arg_count(1, example);
+ args.check_max_arg_count(1, EXAMPLE);
const std::unordered_set<std::string> options =
args.check_and_get_optional_command_arguments({OPTION_FULLDESC});
diff --git a/toolsrc/src/commands_owns.cpp b/toolsrc/src/commands_owns.cpp
index 757292e96..718a0277f 100644
--- a/toolsrc/src/commands_owns.cpp
+++ b/toolsrc/src/commands_owns.cpp
@@ -25,9 +25,9 @@ namespace vcpkg::Commands::Owns
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",
+ static const std::string EXAMPLE = Strings::format("The argument should be a pattern to search for. %s",
Commands::Help::create_example_string("owns zlib.dll"));
- args.check_exact_arg_count(1, example);
+ args.check_exact_arg_count(1, EXAMPLE);
args.check_and_get_optional_command_arguments({});
StatusParagraphs status_db = database_load_check(paths);
diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp
index 83d62896f..32bc3de3c 100644
--- a/toolsrc/src/commands_portsdiff.cpp
+++ b/toolsrc/src/commands_portsdiff.cpp
@@ -2,7 +2,6 @@
#include "Paragraphs.h"
#include "SortedVector.h"
-#include "SourceParagraph.h"
#include "vcpkg_Commands.h"
#include "vcpkg_Maps.h"
#include "vcpkg_System.h"
@@ -117,11 +116,11 @@ namespace vcpkg::Commands::PortsDiff
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string example =
+ static const std::string EXAMPLE =
Strings::format("The argument should be a branch/tag/hash to checkout.\n%s",
Commands::Help::create_example_string("portsdiff mybranchname"));
- args.check_min_arg_count(1, example);
- args.check_max_arg_count(2, example);
+ args.check_min_arg_count(1, EXAMPLE);
+ args.check_max_arg_count(2, EXAMPLE);
args.check_and_get_optional_command_arguments({});
const fs::path& git_exe = paths.get_git_exe();
@@ -139,8 +138,8 @@ namespace vcpkg::Commands::PortsDiff
read_ports_from_commit(paths, git_commit_id_for_previous_snapshot);
// Already sorted, so set_difference can work on std::vector too
- std::vector<std::string> current_ports = Maps::extract_keys(current_names_and_versions);
- std::vector<std::string> previous_ports = Maps::extract_keys(previous_names_and_versions);
+ const std::vector<std::string> current_ports = Maps::extract_keys(current_names_and_versions);
+ const std::vector<std::string> previous_ports = Maps::extract_keys(previous_names_and_versions);
const SetElementPresence<std::string> setp =
SetElementPresence<std::string>::create(current_ports, previous_ports);
diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp
index eabf2b9ae..a9f1b2564 100644
--- a/toolsrc/src/commands_remove.cpp
+++ b/toolsrc/src/commands_remove.cpp
@@ -17,15 +17,21 @@ namespace vcpkg::Commands::Remove
void remove_package(const VcpkgPaths& paths, const PackageSpec& spec, StatusParagraphs* status_db)
{
auto& fs = paths.get_filesystem();
- StatusParagraph& pkg = **status_db->find(spec.name(), spec.triplet());
+ auto spghs = status_db->find_all(spec.name(), spec.triplet());
+ const auto core_pkg = **status_db->find(spec.name(), spec.triplet(), Strings::EMPTY);
- pkg.want = Want::PURGE;
- pkg.state = InstallState::HALF_INSTALLED;
- write_update(paths, pkg);
+ for (auto&& spgh : spghs)
+ {
+ StatusParagraph& pkg = **spgh;
+ if (pkg.state != InstallState::INSTALLED) continue;
+ pkg.want = Want::PURGE;
+ pkg.state = InstallState::HALF_INSTALLED;
+ write_update(paths, pkg);
+ }
- auto maybe_lines = fs.read_lines(paths.listfile_path(pkg.package));
+ auto maybe_lines = fs.read_lines(paths.listfile_path(core_pkg.package));
- if (auto lines = maybe_lines.get())
+ if (const auto lines = maybe_lines.get())
{
std::vector<fs::path> dirs_touched;
for (auto&& suffix : *lines)
@@ -36,7 +42,7 @@ namespace vcpkg::Commands::Remove
auto target = paths.installed / suffix;
- auto status = fs.status(target, ec);
+ const auto status = fs.status(target, ec);
if (ec)
{
System::println(System::Color::error, "failed: %s", ec.message());
@@ -66,7 +72,7 @@ namespace vcpkg::Commands::Remove
}
auto b = dirs_touched.rbegin();
- auto e = dirs_touched.rend();
+ const auto e = dirs_touched.rend();
for (; b != e; ++b)
{
if (fs.is_empty(*b))
@@ -80,20 +86,25 @@ namespace vcpkg::Commands::Remove
}
}
- fs.remove(paths.listfile_path(pkg.package));
+ fs.remove(paths.listfile_path(core_pkg.package));
}
- pkg.state = InstallState::NOT_INSTALLED;
- write_update(paths, pkg);
+ for (auto&& spgh : spghs)
+ {
+ StatusParagraph& pkg = **spgh;
+ if (pkg.state != InstallState::HALF_INSTALLED) continue;
+ pkg.state = InstallState::NOT_INSTALLED;
+ write_update(paths, pkg);
+ }
}
static void print_plan(const std::map<RemovePlanType, std::vector<const RemovePlanAction*>>& group_by_plan_type)
{
- static constexpr std::array<RemovePlanType, 2> order = {RemovePlanType::NOT_INSTALLED, RemovePlanType::REMOVE};
+ static constexpr std::array<RemovePlanType, 2> ORDER = {RemovePlanType::NOT_INSTALLED, RemovePlanType::REMOVE};
- for (const RemovePlanType plan_type : order)
+ for (const RemovePlanType plan_type : ORDER)
{
- auto it = group_by_plan_type.find(plan_type);
+ const auto it = group_by_plan_type.find(plan_type);
if (it == group_by_plan_type.cend())
{
continue;
@@ -118,6 +129,37 @@ namespace vcpkg::Commands::Remove
}
}
+ void perform_remove_plan_action(const VcpkgPaths& paths,
+ const RemovePlanAction& action,
+ const Purge purge,
+ StatusParagraphs& status_db)
+ {
+ const std::string display_name = action.spec.to_string();
+
+ switch (action.plan_type)
+ {
+ case RemovePlanType::NOT_INSTALLED:
+ System::println(System::Color::success, "Package %s is not installed", display_name);
+ break;
+ case RemovePlanType::REMOVE:
+ System::println("Removing package %s... ", display_name);
+ remove_package(paths, action.spec, &status_db);
+ System::println(System::Color::success, "Removing package %s... done", display_name);
+ break;
+ case RemovePlanType::UNKNOWN:
+ default: Checks::unreachable(VCPKG_LINE_INFO);
+ }
+
+ if (purge == Purge::YES)
+ {
+ System::println("Purging package %s... ", display_name);
+ Files::Filesystem& fs = paths.get_filesystem();
+ std::error_code ec;
+ fs.remove_all(paths.packages / action.spec.dir(), ec);
+ System::println(System::Color::success, "Purging package %s... done", display_name);
+ }
+ }
+
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet)
{
static const std::string OPTION_PURGE = "--purge";
@@ -125,7 +167,7 @@ namespace vcpkg::Commands::Remove
static const std::string OPTION_RECURSE = "--recurse";
static const std::string OPTION_DRY_RUN = "--dry-run";
static const std::string OPTION_OUTDATED = "--outdated";
- static const std::string example =
+ static const std::string EXAMPLE =
Commands::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});
@@ -134,37 +176,38 @@ namespace vcpkg::Commands::Remove
std::vector<PackageSpec> specs;
if (options.find(OPTION_OUTDATED) != options.cend())
{
- args.check_exact_arg_count(0, example);
+ args.check_exact_arg_count(0, EXAMPLE);
specs = Util::fmap(Update::find_outdated_packages(paths, status_db),
[](auto&& outdated) { return outdated.spec; });
if (specs.empty())
{
- System::println(System::Color::success, "There are no oudated packages.");
+ System::println(System::Color::success, "There are no outdated packages.");
Checks::exit_success(VCPKG_LINE_INFO);
}
}
else
{
- args.check_min_arg_count(1, example);
+ args.check_min_arg_count(1, EXAMPLE);
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, EXAMPLE);
});
for (auto&& spec : specs)
Input::check_triplet(spec.triplet(), paths);
}
- const bool alsoRemoveFolderFromPackages = options.find(OPTION_NO_PURGE) == options.end();
- if (options.find(OPTION_PURGE) != options.end() && !alsoRemoveFolderFromPackages)
+ const bool no_purge_was_passed = options.find(OPTION_NO_PURGE) != options.end();
+ const bool purge_was_passed = options.find(OPTION_PURGE) != options.end();
+ if (purge_was_passed && no_purge_was_passed)
{
- // User specified --purge and --no-purge
System::println(System::Color::error, "Error: cannot specify both --no-purge and --purge.");
- System::print(example);
+ System::print(EXAMPLE);
Checks::exit_fail(VCPKG_LINE_INFO);
}
- const bool isRecursive = options.find(OPTION_RECURSE) != options.cend();
- const bool dryRun = options.find(OPTION_DRY_RUN) != options.cend();
+ 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 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");
@@ -183,7 +226,7 @@ namespace vcpkg::Commands::Remove
System::println(System::Color::warning,
"Additional packages (*) need to be removed to complete this operation.");
- if (!isRecursive)
+ if (!is_recursive)
{
System::println(System::Color::warning,
"If you are sure you want to remove them, run the command with the --recurse option");
@@ -191,37 +234,14 @@ namespace vcpkg::Commands::Remove
}
}
- if (dryRun)
+ if (dry_run)
{
Checks::exit_success(VCPKG_LINE_INFO);
}
for (const RemovePlanAction& action : remove_plan)
{
- const std::string display_name = action.spec.to_string();
-
- switch (action.plan_type)
- {
- case RemovePlanType::NOT_INSTALLED:
- System::println(System::Color::success, "Package %s is not installed", display_name);
- break;
- case RemovePlanType::REMOVE:
- System::println("Removing package %s... ", display_name);
- remove_package(paths, action.spec, &status_db);
- System::println(System::Color::success, "Removing package %s... done", display_name);
- break;
- case RemovePlanType::UNKNOWN:
- default: Checks::unreachable(VCPKG_LINE_INFO);
- }
-
- if (alsoRemoveFolderFromPackages)
- {
- System::println("Purging package %s... ", display_name);
- Files::Filesystem& fs = paths.get_filesystem();
- std::error_code ec;
- fs.remove_all(paths.packages / action.spec.dir(), ec);
- System::println(System::Color::success, "Purging package %s... done", display_name);
- }
+ perform_remove_plan_action(paths, action, purge, status_db);
}
Checks::exit_success(VCPKG_LINE_INFO);
diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp
index fee99a5db..1ccec9fbe 100644
--- a/toolsrc/src/commands_search.cpp
+++ b/toolsrc/src/commands_search.cpp
@@ -3,6 +3,7 @@
#include "Paragraphs.h"
#include "SourceParagraph.h"
#include "vcpkg_Commands.h"
+#include "vcpkg_GlobalState.h"
#include "vcpkg_System.h"
#include "vcpkglib.h"
@@ -39,7 +40,7 @@ namespace vcpkg::Commands::Search
s.append(Strings::format("%s;", name));
for (const Dependency& d : source_paragraph.depends)
{
- const std::string dependency_name = replace_dashes_with_underscore(d.name);
+ const std::string dependency_name = replace_dashes_with_underscore(d.name());
s.append(Strings::format("%s -> %s;", name, dependency_name));
}
}
@@ -57,9 +58,9 @@ namespace vcpkg::Commands::Search
else
{
System::println("%-20s %-16s %s",
- source_paragraph.name,
- source_paragraph.version,
- vcpkg::shorten_description(source_paragraph.description));
+ vcpkg::shorten_text(source_paragraph.name, 20),
+ vcpkg::shorten_text(source_paragraph.version, 16),
+ vcpkg::shorten_text(source_paragraph.description, 81));
}
}
@@ -72,17 +73,17 @@ namespace vcpkg::Commands::Search
else
{
System::println("%-37s %s",
- name + "[" + feature_paragraph.name + "]",
- vcpkg::shorten_description(feature_paragraph.description));
+ vcpkg::shorten_text(name + "[" + feature_paragraph.name + "]", 37),
+ vcpkg::shorten_text(feature_paragraph.description, 81));
}
}
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const std::string example = Strings::format(
+ 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",
Commands::Help::create_example_string("search png"));
- args.check_max_arg_count(1, example);
+ 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});
@@ -90,7 +91,7 @@ namespace vcpkg::Commands::Search
if (!sources_and_errors.errors.empty())
{
- if (vcpkg::g_debugging)
+ if (GlobalState::debugging)
{
print_error_message(sources_and_errors.errors);
}
diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp
index 35f24af12..71ea4b063 100644
--- a/toolsrc/src/commands_update.cpp
+++ b/toolsrc/src/commands_update.cpp
@@ -2,7 +2,6 @@
#include "Paragraphs.h"
#include "vcpkg_Commands.h"
-#include "vcpkg_Files.h"
#include "vcpkg_System.h"
#include "vcpkglib.h"
@@ -22,7 +21,7 @@ namespace vcpkg::Commands::Update
std::vector<OutdatedPackage> output;
for (const StatusParagraph* pgh : installed_packages)
{
- auto it = src_names_to_versions.find(pgh->package.spec.name());
+ const auto it = src_names_to_versions.find(pgh->package.spec.name());
if (it == src_names_to_versions.end())
{
// Package was not installed from portfile
@@ -69,31 +68,6 @@ namespace vcpkg::Commands::Update
install_line);
}
- auto version_file = paths.get_filesystem().read_contents(paths.root / "toolsrc" / "VERSION.txt");
- if (auto version_contents = version_file.get())
- {
- int maj1, min1, rev1;
- auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1);
-
- int maj2, min2, rev2;
- auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2);
-
- if (num1 == 3 && num2 == 3)
- {
- if (maj1 != maj2 || min1 != min2 || rev1 != rev2)
- {
- System::println("Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use "
- ".\\bootstrap-vcpkg.bat to update.",
- maj2,
- min2,
- rev2,
- maj1,
- min1,
- rev1);
- }
- }
- }
-
Checks::exit_success(VCPKG_LINE_INFO);
}
}
diff --git a/toolsrc/src/commands_version.cpp b/toolsrc/src/commands_version.cpp
index cd21f2561..5744ea9ef 100644
--- a/toolsrc/src/commands_version.cpp
+++ b/toolsrc/src/commands_version.cpp
@@ -13,15 +13,44 @@ namespace vcpkg::Commands::Version
{
const std::string& version()
{
- static const std::string s_version =
+ static const std::string S_VERSION =
#include "../VERSION.txt"
+std::string(VCPKG_VERSION_AS_STRING)
#ifndef NDEBUG
+ std::string("-debug")
#endif
- + std::string(Metrics::get_compiled_metrics_enabled() ? "" : "-external");
- return s_version;
+ + std::string(Metrics::get_compiled_metrics_enabled() ? Strings::EMPTY : "-external");
+ return S_VERSION;
+ }
+
+ 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);
+
+ int maj2, min2, rev2;
+ const auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2);
+
+ if (num1 == 3 && num2 == 3)
+ {
+ if (maj1 != maj2 || min1 != min2 || rev1 != rev2)
+ {
+ System::println(System::Color::warning,
+ "Warning: Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use "
+ ".\\bootstrap-vcpkg.bat to update.",
+ maj2,
+ min2,
+ rev2,
+ maj1,
+ min1,
+ rev1);
+ }
+ }
+ }
}
void perform_and_exit(const VcpkgCmdArguments& args)
diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp
index 7992f3e51..8a0050bfc 100644
--- a/toolsrc/src/metrics.cpp
+++ b/toolsrc/src/metrics.cpp
@@ -8,6 +8,8 @@
namespace vcpkg::Metrics
{
+ Util::LockGuarded<Metrics> g_metrics;
+
static std::string get_current_date_time()
{
struct tm newtime;
@@ -18,12 +20,12 @@ namespace vcpkg::Metrics
_ftime_s(&timebuffer);
time_t now = timebuffer.time;
- int milli = timebuffer.millitm;
+ const int milli = timebuffer.millitm;
- errno_t err = gmtime_s(&newtime, &now);
+ const errno_t err = gmtime_s(&newtime, &now);
if (err)
{
- return "";
+ return Strings::EMPTY;
}
strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S", &newtime);
@@ -32,7 +34,7 @@ namespace vcpkg::Metrics
static std::string generate_random_UUID()
{
- int partSizes[] = {8, 4, 4, 4, 12};
+ int part_sizes[] = {8, 4, 4, 4, 12};
char uuid[37];
memset(uuid, 0, sizeof(uuid));
int num;
@@ -48,7 +50,7 @@ namespace vcpkg::Metrics
// Generating UUID format version 4
// http://en.wikipedia.org/wiki/Universally_unique_identifier
- for (int i = 0; i < partSizes[part]; i++, index++)
+ for (int i = 0; i < part_sizes[part]; i++, index++)
{
if (part == 2 && i == 0)
{
@@ -79,8 +81,8 @@ namespace vcpkg::Metrics
static const std::string& get_session_id()
{
- static const std::string id = generate_random_UUID();
- return id;
+ static const std::string ID = generate_random_UUID();
+ return ID;
}
static std::string to_json_string(const std::string& str)
@@ -99,11 +101,11 @@ namespace vcpkg::Metrics
else if (ch < 0x20 || ch >= 0x80)
{
// Note: this treats incoming Strings as Latin-1
- static constexpr const char hex[16] = {
+ static constexpr const char HEX[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
encoded.append("\\u00");
- encoded.push_back(hex[ch / 16]);
- encoded.push_back(hex[ch % 16]);
+ encoded.push_back(HEX[ch / 16]);
+ encoded.push_back(HEX[ch % 16]);
}
else
{
@@ -118,21 +120,21 @@ namespace vcpkg::Metrics
{
std::wstring path;
path.resize(MAX_PATH);
- auto n = GetSystemDirectoryW(&path[0], static_cast<UINT>(path.size()));
+ const auto n = GetSystemDirectoryW(&path[0], static_cast<UINT>(path.size()));
path.resize(n);
path += L"\\kernel32.dll";
- auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr);
- if (versz == 0) return "";
+ const auto versz = GetFileVersionInfoSizeW(path.c_str(), nullptr);
+ if (versz == 0) return Strings::EMPTY;
std::vector<char> verbuf;
verbuf.resize(versz);
- if (!GetFileVersionInfoW(path.c_str(), 0, static_cast<DWORD>(verbuf.size()), &verbuf[0])) return "";
+ if (!GetFileVersionInfoW(path.c_str(), 0, static_cast<DWORD>(verbuf.size()), &verbuf[0])) return Strings::EMPTY;
void* rootblock;
UINT rootblocksize;
- if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return "";
+ if (!VerQueryValueW(&verbuf[0], L"\\", &rootblock, &rootblocksize)) return Strings::EMPTY;
auto rootblock_ffi = static_cast<VS_FIXEDFILEINFO*>(rootblock);
@@ -150,7 +152,7 @@ namespace vcpkg::Metrics
std::string properties;
std::string measurements;
- void TrackProperty(const std::string& name, const std::string& value)
+ void track_property(const std::string& name, const std::string& value)
{
if (properties.size() != 0) properties.push_back(',');
properties.append(to_json_string(name));
@@ -158,7 +160,7 @@ namespace vcpkg::Metrics
properties.append(to_json_string(value));
}
- void TrackMetric(const std::string& name, double value)
+ void track_metric(const std::string& name, double value)
{
if (measurements.size() != 0) measurements.push_back(',');
measurements.append(to_json_string(name));
@@ -223,25 +225,25 @@ namespace vcpkg::Metrics
return hkcu_sqmclient.value_or(L"{}");
}
- void set_user_information(const std::string& user_id, const std::string& first_use_time)
+ void Metrics::set_user_information(const std::string& user_id, const std::string& first_use_time)
{
g_metricmessage.user_id = user_id;
g_metricmessage.user_timestamp = first_use_time;
}
- void init_user_information(std::string& user_id, std::string& first_use_time)
+ void Metrics::init_user_information(std::string& user_id, std::string& first_use_time)
{
user_id = generate_random_UUID();
first_use_time = get_current_date_time();
}
- void set_send_metrics(bool should_send_metrics) { g_should_send_metrics = should_send_metrics; }
+ void Metrics::set_send_metrics(bool should_send_metrics) { g_should_send_metrics = should_send_metrics; }
- void set_print_metrics(bool should_print_metrics) { g_should_print_metrics = should_print_metrics; }
+ void Metrics::set_print_metrics(bool should_print_metrics) { g_should_print_metrics = should_print_metrics; }
- void track_metric(const std::string& name, double value) { g_metricmessage.TrackMetric(name, value); }
+ void Metrics::track_metric(const std::string& name, double value) { g_metricmessage.track_metric(name, value); }
- void track_property(const std::string& name, const std::wstring& 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;
@@ -249,85 +251,85 @@ namespace vcpkg::Metrics
std::transform(
value.begin(), value.end(), converted_value.begin(), [](wchar_t ch) { return static_cast<char>(ch); });
- g_metricmessage.TrackProperty(name, converted_value);
+ g_metricmessage.track_property(name, converted_value);
}
- void track_property(const std::string& name, const std::string& value)
+ void Metrics::track_property(const std::string& name, const std::string& value)
{
- g_metricmessage.TrackProperty(name, value);
+ g_metricmessage.track_property(name, value);
}
- void upload(const std::string& payload)
+ void Metrics::upload(const std::string& payload)
{
- HINTERNET hSession = nullptr, hConnect = nullptr, hRequest = nullptr;
- BOOL bResults = FALSE;
+ HINTERNET connect = nullptr, request = nullptr;
+ BOOL results = FALSE;
- hSession = WinHttpOpen(
+ const HINTERNET session = WinHttpOpen(
L"vcpkg/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
- if (hSession)
- hConnect = WinHttpConnect(hSession, L"dc.services.visualstudio.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
-
- if (hConnect)
- hRequest = WinHttpOpenRequest(hConnect,
- L"POST",
- L"/v2/track",
- nullptr,
- WINHTTP_NO_REFERER,
- WINHTTP_DEFAULT_ACCEPT_TYPES,
- WINHTTP_FLAG_SECURE);
-
- if (hRequest)
+ if (session) connect = WinHttpConnect(session, L"dc.services.visualstudio.com", INTERNET_DEFAULT_HTTPS_PORT, 0);
+
+ if (connect)
+ request = WinHttpOpenRequest(connect,
+ L"POST",
+ L"/v2/track",
+ nullptr,
+ WINHTTP_NO_REFERER,
+ WINHTTP_DEFAULT_ACCEPT_TYPES,
+ WINHTTP_FLAG_SECURE);
+
+ if (request)
{
if (MAXDWORD <= payload.size()) abort();
std::wstring hdrs = L"Content-Type: application/json\r\n";
- bResults = WinHttpSendRequest(hRequest,
- hdrs.c_str(),
- static_cast<DWORD>(hdrs.size()),
- (void*)&payload[0],
- static_cast<DWORD>(payload.size()),
- static_cast<DWORD>(payload.size()),
- 0);
+ std::string& p = const_cast<std::string&>(payload);
+ results = WinHttpSendRequest(request,
+ hdrs.c_str(),
+ static_cast<DWORD>(hdrs.size()),
+ static_cast<void*>(&p[0]),
+ static_cast<DWORD>(payload.size()),
+ static_cast<DWORD>(payload.size()),
+ 0);
}
- if (bResults)
+ if (results)
{
- bResults = WinHttpReceiveResponse(hRequest, nullptr);
+ results = WinHttpReceiveResponse(request, nullptr);
}
DWORD http_code = 0, junk = sizeof(DWORD);
- if (bResults)
+ if (results)
{
- bResults = WinHttpQueryHeaders(hRequest,
- WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
- nullptr,
- &http_code,
- &junk,
- WINHTTP_NO_HEADER_INDEX);
+ results = WinHttpQueryHeaders(request,
+ WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER,
+ nullptr,
+ &http_code,
+ &junk,
+ WINHTTP_NO_HEADER_INDEX);
}
- std::vector<char> responseBuffer;
- if (bResults)
+ std::vector<char> response_buffer;
+ if (results)
{
- DWORD availableData = 0, readData = 0, totalData = 0;
- while ((bResults = WinHttpQueryDataAvailable(hRequest, &availableData)) == TRUE && availableData > 0)
+ DWORD available_data = 0, read_data = 0, total_data = 0;
+ while ((results = WinHttpQueryDataAvailable(request, &available_data)) == TRUE && available_data > 0)
{
- responseBuffer.resize(responseBuffer.size() + availableData);
+ response_buffer.resize(response_buffer.size() + available_data);
- bResults = WinHttpReadData(hRequest, &responseBuffer.data()[totalData], availableData, &readData);
+ results = WinHttpReadData(request, &response_buffer.data()[total_data], available_data, &read_data);
- if (!bResults)
+ if (!results)
{
break;
}
- totalData += readData;
+ total_data += read_data;
- responseBuffer.resize(totalData);
+ response_buffer.resize(total_data);
}
}
- if (!bResults)
+ if (!results)
{
#ifndef NDEBUG
__debugbreak();
@@ -336,22 +338,22 @@ namespace vcpkg::Metrics
#endif
}
- if (hRequest) WinHttpCloseHandle(hRequest);
- if (hConnect) WinHttpCloseHandle(hConnect);
- if (hSession) WinHttpCloseHandle(hSession);
+ if (request) WinHttpCloseHandle(request);
+ if (connect) WinHttpCloseHandle(connect);
+ if (session) WinHttpCloseHandle(session);
}
static fs::path get_bindir()
{
wchar_t buf[_MAX_PATH];
- int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH);
+ const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH);
if (bytes == 0) std::abort();
return fs::path(buf, buf + bytes);
}
- void flush()
+ void Metrics::flush()
{
- std::string payload = g_metricmessage.format_event_data_template();
+ 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;
@@ -375,7 +377,7 @@ namespace vcpkg::Metrics
path = vcpkgdir / "scripts" / "vcpkgmetricsuploader.exe";
if (fs.exists(path)) return path;
- return L"";
+ return Strings::WEMPTY;
}();
std::error_code ec;
@@ -386,8 +388,8 @@ 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 cmdLine =
+ const std::wstring cmd_line =
Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native());
- System::cmd_execute_clean(cmdLine);
+ System::cmd_execute_clean(cmd_line);
}
}
diff --git a/toolsrc/src/test_install_plan.cpp b/toolsrc/src/test_install_plan.cpp
index d02af5662..6c9311264 100644
--- a/toolsrc/src/test_install_plan.cpp
+++ b/toolsrc/src/test_install_plan.cpp
@@ -6,32 +6,62 @@ using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace vcpkg;
-namespace UnitTest1
+namespace Microsoft::VisualStudio::CppUnitTestFramework
{
- class InstallPlanTests : public TestClass<InstallPlanTests>
+ template<>
+ inline std::wstring ToString<vcpkg::Dependencies::InstallPlanType>(const vcpkg::Dependencies::InstallPlanType& t)
{
- struct PackageSpecMap
+ switch (t)
{
- std::unordered_map<PackageSpec, SourceControlFile> map;
- Triplet triplet;
- PackageSpecMap(const Triplet& t) { triplet = t; }
+ 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::UNKNOWN: return L"UNKNOWN";
+ default: return ToString((int)t);
+ }
+ }
- PackageSpec get_package_spec(std::vector<std::unordered_map<std::string, std::string>>&& fields)
- {
- auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(fields));
- Assert::IsTrue(m_pgh.has_value());
- auto& scf = *m_pgh.get();
+ template<>
+ inline std::wstring ToString<vcpkg::Dependencies::RequestType>(const vcpkg::Dependencies::RequestType& t)
+ {
+ switch (t)
+ {
+ 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);
+ }
+ }
+}
- auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, triplet);
- Assert::IsTrue(spec.has_value());
- map.emplace(*spec.get(), std::move(*scf.get()));
- return PackageSpec{*spec.get()};
- }
- PackageSpec set_package_map(std::string source, std::string version, std::string build_depends)
+namespace UnitTest1
+{
+ class InstallPlanTests : public TestClass<InstallPlanTests>
+ {
+ static std::unique_ptr<SourceControlFile> make_control_file(
+ const char* name,
+ const char* depends,
+ const std::vector<std::pair<const char*, const char*>>& features = {})
+ {
+ using Pgh = std::unordered_map<std::string, std::string>;
+ std::vector<Pgh> scf_pghs;
+ scf_pghs.push_back(Pgh{
+ {"Source", name},
+ {"Version", "0"},
+ {"Build-Depends", depends},
+ });
+ for (auto&& feature : features)
{
- return get_package_spec({{{"Source", source}, {"Version", version}, {"Build-Depends", build_depends}}});
+ scf_pghs.push_back(Pgh{
+ {"Feature", feature.first},
+ {"Description", "feature"},
+ {"Build-Depends", feature.second},
+ });
}
- };
+ auto m_pgh = vcpkg::SourceControlFile::parse_control_file(std::move(scf_pghs));
+ Assert::IsTrue(m_pgh.has_value());
+ return std::move(*m_pgh.get());
+ }
static void features_check(Dependencies::AnyAction* install_action,
std::string pkg_name,
@@ -68,16 +98,60 @@ namespace UnitTest1
Assert::AreEqual(pkg_name.c_str(), plan.spec.name().c_str());
}
+ static std::unique_ptr<StatusParagraph> make_status_pgh(const char* name, const char* depends = "")
+ {
+ using Pgh = std::unordered_map<std::string, std::string>;
+ return std::make_unique<StatusParagraph>(Pgh{{"Package", name},
+ {"Version", "1"},
+ {"Architecture", "x86-windows"},
+ {"Multi-Arch", "same"},
+ {"Depends", depends},
+ {"Status", "install ok installed"}});
+ }
+ static std::unique_ptr<StatusParagraph> make_status_feature_pgh(const char* name,
+ const char* feature,
+ const char* depends = "")
+ {
+ using Pgh = std::unordered_map<std::string, std::string>;
+ return std::make_unique<StatusParagraph>(Pgh{{"Package", name},
+ {"Version", "1"},
+ {"Feature", feature},
+ {"Architecture", "x86-windows"},
+ {"Multi-Arch", "same"},
+ {"Depends", depends},
+ {"Status", "install ok installed"}});
+ }
+ struct PackageSpecMap
+ {
+ std::unordered_map<std::string, SourceControlFile> map;
+ Triplet triplet;
+ PackageSpecMap(const Triplet& t) { triplet = t; }
+
+ PackageSpec emplace(const char* name,
+ const char* depends = "",
+ const std::vector<std::pair<const char*, const char*>>& features = {})
+ {
+ return emplace(std::move(*make_control_file(name, depends, features)));
+ }
+ PackageSpec emplace(vcpkg::SourceControlFile&& scf)
+ {
+ auto spec = PackageSpec::from_name_and_triplet(scf.core_paragraph->name, triplet);
+ Assert::IsTrue(spec.has_value());
+ map.emplace(scf.core_paragraph->name, std::move(scf));
+ return PackageSpec{*spec.get()};
+ }
+ };
+
TEST_METHOD(basic_install_scheme)
{
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
PackageSpecMap spec_map(Triplet::X86_WINDOWS);
- auto spec_a = spec_map.set_package_map("a", "1.2.8", "b");
- auto spec_b = spec_map.set_package_map("b", "1.3", "c");
- auto spec_c = spec_map.set_package_map("c", "2.5.3", "");
+ auto spec_a = spec_map.emplace("a", "b");
+ auto spec_b = spec_map.emplace("b", "c");
+ auto spec_c = spec_map.emplace("c");
- auto map_port = Dependencies::MapPortFile(spec_map.map);
+ Dependencies::MapPortFile map_port(spec_map.map);
auto install_plan =
Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
@@ -92,16 +166,16 @@ namespace UnitTest1
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
PackageSpecMap spec_map(Triplet::X86_WINDOWS);
- auto spec_a = spec_map.set_package_map("a", "1.2.8", "d");
- auto spec_b = spec_map.set_package_map("b", "1.3", "d, e");
- auto spec_c = spec_map.set_package_map("c", "2.5.3", "e, h");
- auto spec_d = spec_map.set_package_map("d", "4.0", "f, g, h");
- auto spec_e = spec_map.set_package_map("e", "1.0", "g");
- auto spec_f = spec_map.set_package_map("f", "1.0", "");
- auto spec_g = spec_map.set_package_map("g", "1.0", "");
- auto spec_h = spec_map.set_package_map("h", "1.0", "");
-
- auto map_port = Dependencies::MapPortFile(spec_map.map);
+ auto spec_a = spec_map.emplace("a", "d");
+ auto spec_b = spec_map.emplace("b", "d, e");
+ auto spec_c = spec_map.emplace("c", "e, h");
+ auto spec_d = spec_map.emplace("d", "f, g, h");
+ auto spec_e = spec_map.emplace("e", "g");
+ auto spec_f = spec_map.emplace("f");
+ auto spec_g = spec_map.emplace("g");
+ auto spec_h = spec_map.emplace("h");
+
+ Dependencies::MapPortFile map_port(spec_map.map);
auto install_plan = Dependencies::create_install_plan(
map_port, {spec_a, spec_b, spec_c}, StatusParagraphs(std::move(status_paragraphs)));
@@ -127,37 +201,74 @@ namespace UnitTest1
Assert::IsTrue(e_pos > g_pos);
}
+ TEST_METHOD(existing_package_scheme)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
+ status_paragraphs.push_back(make_status_pgh("a"));
+
+ PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+ auto spec_a = FullPackageSpec{spec_map.emplace("a")};
+
+ auto install_plan =
+ Dependencies::create_feature_install_plan(spec_map.map,
+ FullPackageSpec::to_feature_specs({spec_a}),
+ StatusParagraphs(std::move(status_paragraphs)));
+
+ Assert::AreEqual(size_t(1), install_plan.size());
+ auto p = install_plan[0].install_plan.get();
+ Assert::IsNotNull(p);
+ Assert::AreEqual("a", p->spec.name().c_str());
+ Assert::AreEqual(Dependencies::InstallPlanType::ALREADY_INSTALLED, p->plan_type);
+ Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p->request_type);
+ }
+
+ TEST_METHOD(user_requested_package_scheme)
+ {
+ std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
+
+ PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+ auto spec_a = FullPackageSpec{spec_map.emplace("a", "b")};
+ auto spec_b = FullPackageSpec{spec_map.emplace("b")};
+
+ auto install_plan =
+ Dependencies::create_feature_install_plan(spec_map.map,
+ FullPackageSpec::to_feature_specs({spec_a}),
+ StatusParagraphs(std::move(status_paragraphs)));
+
+ Assert::AreEqual(size_t(2), install_plan.size());
+ auto p = install_plan[0].install_plan.get();
+ Assert::IsNotNull(p);
+ Assert::AreEqual("b", p->spec.name().c_str());
+ Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p->plan_type);
+ Assert::AreEqual(Dependencies::RequestType::AUTO_SELECTED, p->request_type);
+
+ auto p2 = install_plan[1].install_plan.get();
+ Assert::IsNotNull(p2);
+ Assert::AreEqual("a", p2->spec.name().c_str());
+ Assert::AreEqual(Dependencies::InstallPlanType::BUILD_AND_INSTALL, p2->plan_type);
+ Assert::AreEqual(Dependencies::RequestType::USER_REQUESTED, p2->request_type);
+ }
+
TEST_METHOD(long_install_scheme)
{
- using Pgh = std::unordered_map<std::string, std::string>;
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "j"},
- {"Version", "1.2.8"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", "k"},
- {"Status", "install ok installed"}}));
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "k"},
- {"Version", "1.2.8"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
+ status_paragraphs.push_back(make_status_pgh("j", "k"));
+ status_paragraphs.push_back(make_status_pgh("k"));
PackageSpecMap spec_map(Triplet::X86_WINDOWS);
- auto spec_a = spec_map.set_package_map("a", "1.2.8", "b, c, d, e, f, g, h, j, k");
- auto spec_b = spec_map.set_package_map("b", "1.2.8", "c, d, e, f, g, h, j, k");
- auto spec_c = spec_map.set_package_map("c", "1.2.8", "d, e, f, g, h, j, k");
- auto spec_d = spec_map.set_package_map("d", "1.2.8", "e, f, g, h, j, k");
- auto spec_e = spec_map.set_package_map("e", "1.2.8", "f, g, h, j, k");
- auto spec_f = spec_map.set_package_map("f", "1.2.8", "g, h, j, k");
- auto spec_g = spec_map.set_package_map("g", "1.2.8", "h, j, k");
- auto spec_h = spec_map.set_package_map("h", "1.2.8", "j, k");
- auto spec_j = spec_map.set_package_map("j", "1.2.8", "k");
- auto spec_k = spec_map.set_package_map("k", "1.2.8", "");
-
- auto map_port = Dependencies::MapPortFile(spec_map.map);
+ auto spec_a = spec_map.emplace("a", "b, c, d, e, f, g, h, j, k");
+ auto spec_b = spec_map.emplace("b", "c, d, e, f, g, h, j, k");
+ auto spec_c = spec_map.emplace("c", "d, e, f, g, h, j, k");
+ auto spec_d = spec_map.emplace("d", "e, f, g, h, j, k");
+ auto spec_e = spec_map.emplace("e", "f, g, h, j, k");
+ auto spec_f = spec_map.emplace("f", "g, h, j, k");
+ auto spec_g = spec_map.emplace("g", "h, j, k");
+ auto spec_h = spec_map.emplace("h", "j, k");
+ auto spec_j = spec_map.emplace("j", "k");
+ auto spec_k = spec_map.emplace("k");
+
+ Dependencies::MapPortFile map_port(spec_map.map);
auto install_plan =
Dependencies::create_install_plan(map_port, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
@@ -174,162 +285,85 @@ namespace UnitTest1
TEST_METHOD(basic_feature_test_1)
{
- using Pgh = std::unordered_map<std::string, std::string>;
-
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "a"},
- {"Default-Features", ""},
- {"Version", "1.3.8"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", "b, b[beefeatureone]"},
- {"Status", "install ok installed"}}));
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "b"},
- {"Feature", "beefeatureone"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "b"},
- {"Default-Features", "beefeatureone"},
- {"Version", "1.3"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
+ status_paragraphs.push_back(make_status_pgh("a", "b, b[b1]"));
+ status_paragraphs.push_back(make_status_pgh("b"));
+ status_paragraphs.push_back(make_status_feature_pgh("b", "b1"));
PackageSpecMap spec_map(Triplet::X86_WINDOWS);
- auto spec_a =
- FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b, b[beefeatureone]"}},
- {{"Feature", "featureone"},
- {"Description", "the first feature for a"},
- {"Build-Depends", "b[beefeaturetwo]"}},
- }),
- {"featureone"}};
- auto spec_b = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}},
- {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}},
- {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}},
- })};
+ auto spec_a = FullPackageSpec{spec_map.emplace("a", "b, b[b1]", {{"a1", "b[b2]"}}), {"a1"}};
+ auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})};
- auto install_plan = Dependencies::create_feature_install_plan(
- spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
+ auto install_plan =
+ Dependencies::create_feature_install_plan(spec_map.map,
+ FullPackageSpec::to_feature_specs({spec_a}),
+ StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(4), install_plan.size());
remove_plan_check(&install_plan[0], "a");
remove_plan_check(&install_plan[1], "b");
- features_check(&install_plan[2], "b", {"beefeatureone", "core", "beefeatureone"});
- features_check(&install_plan[3], "a", {"featureone", "core"});
+ features_check(&install_plan[2], "b", {"b1", "core", "b1"});
+ features_check(&install_plan[3], "a", {"a1", "core"});
}
TEST_METHOD(basic_feature_test_2)
{
- using Pgh = std::unordered_map<std::string, std::string>;
-
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
PackageSpecMap spec_map(Triplet::X86_WINDOWS);
- auto spec_a =
- FullPackageSpec{spec_map.get_package_spec(
- {{{"Source", "a"}, {"Version", "1.3.8"}, {"Build-Depends", "b[beefeatureone]"}},
- {{"Feature", "featureone"},
- {"Description", "the first feature for a"},
- {"Build-Depends", "b[beefeaturetwo]"}}
-
- }),
- {"featureone"}};
- auto spec_b = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- {{"Feature", "beefeatureone"}, {"Description", "the first feature for b"}, {"Build-Depends", ""}},
- {{"Feature", "beefeaturetwo"}, {"Description", "the second feature for b"}, {"Build-Depends", ""}},
- {{"Feature", "beefeaturethree"}, {"Description", "the third feature for b"}, {"Build-Depends", ""}},
- })};
+ auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[b1]", {{"a1", "b[b2]"}}), {"a1"}};
+ auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}, {"b3", ""}})};
- auto install_plan = Dependencies::create_feature_install_plan(
- spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
+ auto install_plan =
+ Dependencies::create_feature_install_plan(spec_map.map,
+ FullPackageSpec::to_feature_specs({spec_a}),
+ StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(2), install_plan.size());
- features_check(&install_plan[0], "b", {"beefeatureone", "beefeaturetwo", "core"});
- features_check(&install_plan[1], "a", {"featureone", "core"});
+ features_check(&install_plan[0], "b", {"b1", "b2", "core"});
+ features_check(&install_plan[1], "a", {"a1", "core"});
}
TEST_METHOD(basic_feature_test_3)
{
- using Pgh = std::unordered_map<std::string, std::string>;
-
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "a"},
- {"Default-Features", ""},
- {"Version", "1.3"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
+ status_paragraphs.push_back(make_status_pgh("a"));
PackageSpecMap spec_map(Triplet::X86_WINDOWS);
- auto spec_a = FullPackageSpec{
- spec_map.get_package_spec(
- {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}},
- {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}),
- {"core"}};
- auto spec_b = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- })};
- auto spec_c = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}},
- }),
- {"core"}};
+ auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}};
+ auto spec_b = FullPackageSpec{spec_map.emplace("b")};
+ auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}};
- auto install_plan = Dependencies::create_feature_install_plan(
- spec_map.map, {spec_c, spec_a}, StatusParagraphs(std::move(status_paragraphs)));
+ auto install_plan =
+ Dependencies::create_feature_install_plan(spec_map.map,
+ FullPackageSpec::to_feature_specs({spec_c, spec_a}),
+ StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(4), install_plan.size());
remove_plan_check(&install_plan[0], "a");
features_check(&install_plan[1], "b", {"core"});
- features_check(&install_plan[2], "a", {"one", "core"});
+ features_check(&install_plan[2], "a", {"a1", "core"});
features_check(&install_plan[3], "c", {"core"});
}
TEST_METHOD(basic_feature_test_4)
{
- using Pgh = std::unordered_map<std::string, std::string>;
-
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "a"},
- {"Default-Features", ""},
- {"Version", "1.3"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "a"},
- {"Feature", "one"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
+ status_paragraphs.push_back(make_status_pgh("a"));
+ status_paragraphs.push_back(make_status_feature_pgh("a", "a1", ""));
PackageSpecMap spec_map(Triplet::X86_WINDOWS);
- auto spec_a = FullPackageSpec{
- spec_map.get_package_spec(
- {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}},
- {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}),
- };
- auto spec_b = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- })};
- auto spec_c = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}},
- }),
- {"core"}};
+ auto spec_a = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}})};
+ auto spec_b = FullPackageSpec{spec_map.emplace("b")};
+ auto spec_c = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}};
- auto install_plan = Dependencies::create_feature_install_plan(
- spec_map.map, {spec_c}, StatusParagraphs(std::move(status_paragraphs)));
+ auto install_plan =
+ Dependencies::create_feature_install_plan(spec_map.map,
+ FullPackageSpec::to_feature_specs({spec_c}),
+ StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(1), install_plan.size());
features_check(&install_plan[0], "c", {"core"});
@@ -337,168 +371,93 @@ namespace UnitTest1
TEST_METHOD(basic_feature_test_5)
{
- using Pgh = std::unordered_map<std::string, std::string>;
-
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
PackageSpecMap spec_map(Triplet::X86_WINDOWS);
- auto spec_a = FullPackageSpec{
- spec_map.get_package_spec(
- {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[1]"}},
- {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", "b[2]"}},
- {{"Feature", "3"}, {"Description", "the first feature for a"}, {"Build-Depends", "a[2]"}}}),
- {"3"}};
- auto spec_b = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}},
- {{"Feature", "2"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}},
- })};
+ auto spec_a =
+ FullPackageSpec{spec_map.emplace("a", "", {{"a1", "b[b1]"}, {"a2", "b[b2]"}, {"a3", "a[a2]"}}), {"a3"}};
+ auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}, {"b2", ""}})};
- auto install_plan = Dependencies::create_feature_install_plan(
- spec_map.map, {spec_a}, StatusParagraphs(std::move(status_paragraphs)));
+ auto install_plan =
+ Dependencies::create_feature_install_plan(spec_map.map,
+ FullPackageSpec::to_feature_specs({spec_a}),
+ StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(2), install_plan.size());
- features_check(&install_plan[0], "b", {"core", "2"});
- features_check(&install_plan[1], "a", {"core", "3", "2"});
+ features_check(&install_plan[0], "b", {"core", "b2"});
+ features_check(&install_plan[1], "a", {"core", "a3", "a2"});
}
TEST_METHOD(basic_feature_test_6)
{
- using Pgh = std::unordered_map<std::string, std::string>;
-
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "b"},
- {"Default-Features", ""},
- {"Version", "1.3"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
- PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+ status_paragraphs.push_back(make_status_pgh("b"));
- auto spec_a = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b[core]"}},
- }),
- {"core"}};
- auto spec_b = FullPackageSpec{
- spec_map.get_package_spec({
- {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}},
- }),
- {"1"}};
+ PackageSpecMap spec_map(Triplet::X86_WINDOWS);
+ auto spec_a = FullPackageSpec{spec_map.emplace("a", "b[core]"), {"core"}};
+ auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}};
- auto install_plan = Dependencies::create_feature_install_plan(
- spec_map.map, {spec_a, spec_b}, StatusParagraphs(std::move(status_paragraphs)));
+ auto install_plan =
+ Dependencies::create_feature_install_plan(spec_map.map,
+ FullPackageSpec::to_feature_specs({spec_a, spec_b}),
+ StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(3), install_plan.size());
remove_plan_check(&install_plan[0], "b");
- features_check(&install_plan[1], "b", {"core", "1"});
+ features_check(&install_plan[1], "b", {"core", "b1"});
features_check(&install_plan[2], "a", {"core"});
}
TEST_METHOD(basic_feature_test_7)
{
- using Pgh = std::unordered_map<std::string, std::string>;
-
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "x"},
- {"Default-Features", ""},
- {"Version", "1.3"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", "b"},
- {"Status", "install ok installed"}}));
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "b"},
- {"Default-Features", ""},
- {"Version", "1.3"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
+ status_paragraphs.push_back(make_status_pgh("x", "b"));
+ status_paragraphs.push_back(make_status_pgh("b"));
+
PackageSpecMap spec_map(Triplet::X86_WINDOWS);
- auto spec_a = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- })};
- auto spec_x = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "x"}, {"Version", "1.3"}, {"Build-Depends", "a"}},
- }),
- {"core"}};
- auto spec_b = FullPackageSpec{
- spec_map.get_package_spec({
- {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}, {"Default-Features", ""}},
- {{"Feature", "1"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}},
- }),
- {"1"}};
+ auto spec_a = FullPackageSpec{spec_map.emplace("a")};
+ auto spec_x = FullPackageSpec{spec_map.emplace("x", "a"), {"core"}};
+ auto spec_b = FullPackageSpec{spec_map.emplace("b", "", {{"b1", ""}}), {"b1"}};
- auto install_plan = Dependencies::create_feature_install_plan(
- spec_map.map, {spec_b, spec_x}, StatusParagraphs(std::move(status_paragraphs)));
+ auto install_plan =
+ Dependencies::create_feature_install_plan(spec_map.map,
+ FullPackageSpec::to_feature_specs({spec_b}),
+ StatusParagraphs(std::move(status_paragraphs)));
Assert::AreEqual(size_t(5), install_plan.size());
remove_plan_check(&install_plan[0], "x");
remove_plan_check(&install_plan[1], "b");
// TODO: order here may change but A < X, and B anywhere
- features_check(&install_plan[2], "a", {"core"});
- features_check(&install_plan[3], "x", {"core"});
- features_check(&install_plan[4], "b", {"core", "1"});
+ features_check(&install_plan[2], "b", {"core", "b1"});
+ features_check(&install_plan[3], "a", {"core"});
+ features_check(&install_plan[4], "x", {"core"});
}
TEST_METHOD(basic_feature_test_8)
{
- using Pgh = std::unordered_map<std::string, std::string>;
-
std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs;
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "a"},
- {"Default-Features", ""},
- {"Version", "1.3"},
- {"Architecture", "x64-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
- status_paragraphs.push_back(std::make_unique<StatusParagraph>(Pgh{{"Package", "a"},
- {"Default-Features", ""},
- {"Version", "1.3"},
- {"Architecture", "x86-windows"},
- {"Multi-Arch", "same"},
- {"Depends", ""},
- {"Status", "install ok installed"}}));
+ status_paragraphs.push_back(make_status_pgh("a"));
+ status_paragraphs.push_back(make_status_pgh("a"));
+ status_paragraphs.back()->package.spec =
+ PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO);
PackageSpecMap spec_map(Triplet::X64_WINDOWS);
-
- auto spec_a_64 = FullPackageSpec{
- spec_map.get_package_spec(
- {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}},
- {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}),
- {"core"}};
- auto spec_b_64 = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- })};
- auto spec_c_64 = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}},
- }),
- {"core"}};
+ auto spec_a_64 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}};
+ auto spec_b_64 = FullPackageSpec{spec_map.emplace("b")};
+ auto spec_c_64 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}};
spec_map.triplet = Triplet::X86_WINDOWS;
- auto spec_a_86 = FullPackageSpec{
- spec_map.get_package_spec(
- {{{"Source", "a"}, {"Version", "1.3"}, {"Build-Depends", "b"}},
- {{"Feature", "one"}, {"Description", "the first feature for a"}, {"Build-Depends", ""}}}),
- {"core"}};
- auto spec_b_86 = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "b"}, {"Version", "1.3"}, {"Build-Depends", ""}},
- })};
- auto spec_c_86 = FullPackageSpec{spec_map.get_package_spec({
- {{"Source", "c"}, {"Version", "1.3"}, {"Build-Depends", "a[one]"}},
- }),
- {"core"}};
+ auto spec_a_86 = FullPackageSpec{spec_map.emplace("a", "b", {{"a1", ""}}), {"core"}};
+ auto spec_b_86 = FullPackageSpec{spec_map.emplace("b")};
+ auto spec_c_86 = FullPackageSpec{spec_map.emplace("c", "a[a1]"), {"core"}};
- auto install_plan =
- Dependencies::create_feature_install_plan(spec_map.map,
- {spec_c_64, spec_a_86, spec_a_64, spec_c_86},
- StatusParagraphs(std::move(status_paragraphs)));
+ auto install_plan = Dependencies::create_feature_install_plan(
+ spec_map.map,
+ 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 {
@@ -517,10 +476,10 @@ namespace UnitTest1
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);
- features_check(&install_plan[3], "a", {"one", "core"}, Triplet::X64_WINDOWS);
+ features_check(&install_plan[3], "a", {"a1", "core"}, Triplet::X64_WINDOWS);
features_check(&install_plan[4], "c", {"core"}, Triplet::X64_WINDOWS);
features_check(&install_plan[5], "b", {"core"});
- features_check(&install_plan[6], "a", {"one", "core"});
+ features_check(&install_plan[6], "a", {"a1", "core"});
features_check(&install_plan[7], "c", {"core"});
}
};
diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp
index 995d46873..6a6981d73 100644
--- a/toolsrc/src/tests_dependencies.cpp
+++ b/toolsrc/src/tests_dependencies.cpp
@@ -8,6 +8,7 @@
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace vcpkg;
+using Parse::parse_comma_list;
namespace UnitTest1
{
@@ -15,15 +16,15 @@ namespace UnitTest1
{
TEST_METHOD(parse_depends_one)
{
- auto v = expand_qualified_dependencies(parse_comma_list("libA [windows]"));
+ auto v = expand_qualified_dependencies(parse_comma_list("libA (windows)"));
Assert::AreEqual(size_t(1), v.size());
- Assert::AreEqual("libA", v[0].name.c_str());
+ Assert::AreEqual("libA", v[0].depend.name.c_str());
Assert::AreEqual("windows", v[0].qualifier.c_str());
}
TEST_METHOD(filter_depends)
{
- auto deps = expand_qualified_dependencies(parse_comma_list("libA [windows], libB, libC [uwp]"));
+ auto deps = expand_qualified_dependencies(parse_comma_list("libA (windows), libB, libC (uwp)"));
auto v = filter_dependencies(deps, Triplet::X64_WINDOWS);
Assert::AreEqual(size_t(2), v.size());
Assert::AreEqual("libA", v[0].c_str());
@@ -41,7 +42,15 @@ namespace UnitTest1
TEST_METHOD(parse_supports_all)
{
auto v = Supports::parse({
- "x64", "x86", "arm", "windows", "uwp", "v140", "v141", "crt-static", "crt-dynamic",
+ "x64",
+ "x86",
+ "arm",
+ "windows",
+ "uwp",
+ "v140",
+ "v141",
+ "crt-static",
+ "crt-dynamic",
});
Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get()));
@@ -74,7 +83,9 @@ namespace UnitTest1
TEST_METHOD(parse_supports_some)
{
auto v = Supports::parse({
- "x64", "x86", "windows",
+ "x64",
+ "x86",
+ "windows",
});
Assert::AreNotEqual(uintptr_t(0), uintptr_t(v.get()));
diff --git a/toolsrc/src/tests_package_spec.cpp b/toolsrc/src/tests_package_spec.cpp
new file mode 100644
index 000000000..fa201b372
--- /dev/null
+++ b/toolsrc/src/tests_package_spec.cpp
@@ -0,0 +1,119 @@
+#include "BinaryParagraph.h"
+#include "CppUnitTest.h"
+#include "Paragraphs.h"
+#include "vcpkg_Strings.h"
+
+#pragma comment(lib, "version")
+#pragma comment(lib, "winhttp")
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+
+namespace Microsoft::VisualStudio::CppUnitTestFramework
+{
+ template<>
+ inline std::wstring ToString<vcpkg::PackageSpecParseResult>(const vcpkg::PackageSpecParseResult& t)
+ {
+ return ToString(static_cast<uint32_t>(t));
+ }
+
+ template<>
+ inline std::wstring ToString<vcpkg::PackageSpec>(const vcpkg::PackageSpec& t)
+ {
+ return ToString(t.to_string());
+ }
+}
+
+namespace Strings = vcpkg::Strings;
+
+namespace UnitTest1
+{
+ using namespace vcpkg;
+
+ class SpecifierConversion : public TestClass<SpecifierConversion>
+ {
+ TEST_METHOD(full_package_spec_to_feature_specs)
+ {
+ auto a_spec = PackageSpec::from_name_and_triplet("a", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO);
+ auto b_spec = PackageSpec::from_name_and_triplet("b", Triplet::X64_WINDOWS).value_or_exit(VCPKG_LINE_INFO);
+
+ auto fspecs = FullPackageSpec::to_feature_specs({{a_spec, {"0", "1"}}, {b_spec, {"2", "3"}}});
+
+ Assert::AreEqual(size_t(6), fspecs.size());
+
+ std::array<const char*, 6> features = {"", "0", "1", "", "2", "3"};
+ std::array<PackageSpec*, 6> specs = {&a_spec, &a_spec, &a_spec, &b_spec, &b_spec, &b_spec};
+
+ for (int i = 0; i < features.size(); ++i)
+ {
+ Assert::AreEqual(features[i], fspecs[i].feature().c_str());
+ Assert::AreEqual(*specs[i], fspecs[i].spec());
+ }
+ }
+ };
+
+ class SpecifierParsing : public TestClass<SpecifierParsing>
+ {
+ TEST_METHOD(parsed_specifier_from_string)
+ {
+ 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::AreEqual(size_t(0), spec->features.size());
+ Assert::AreEqual("", spec->triplet.c_str());
+ }
+
+ TEST_METHOD(parsed_specifier_from_string_with_triplet)
+ {
+ auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib:x64-uwp");
+ Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, maybe_spec.error());
+ auto spec = maybe_spec.get();
+ Assert::AreEqual("zlib", spec->name.c_str());
+ Assert::AreEqual("x64-uwp", spec->triplet.c_str());
+ }
+
+ TEST_METHOD(parsed_specifier_from_string_with_colons)
+ {
+ auto ec = vcpkg::ParsedSpecifier::from_string("zlib:x86-uwp:").error();
+ Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec);
+ }
+
+ TEST_METHOD(parsed_specifier_from_string_with_feature)
+ {
+ auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[feature]:x64-uwp");
+ 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("feature", spec->features.front().c_str());
+ Assert::AreEqual("x64-uwp", spec->triplet.c_str());
+ }
+
+ TEST_METHOD(parsed_specifier_from_string_with_many_features)
+ {
+ auto maybe_spec = vcpkg::ParsedSpecifier::from_string("zlib[0, 1,2]");
+ 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() == 3);
+ Assert::AreEqual("0", spec->features[0].c_str());
+ Assert::AreEqual("1", spec->features[1].c_str());
+ Assert::AreEqual("2", spec->features[2].c_str());
+ Assert::AreEqual("", spec->triplet.c_str());
+ }
+
+ TEST_METHOD(utf8_to_utf16)
+ {
+ auto str = vcpkg::Strings::to_utf16("abc");
+ Assert::AreEqual(L"abc", str.c_str());
+ }
+
+ TEST_METHOD(utf8_to_utf16_with_whitespace)
+ {
+ auto str = vcpkg::Strings::to_utf16("abc -x86-windows");
+ Assert::AreEqual(L"abc -x86-windows", str.c_str());
+ }
+ };
+
+ TEST_CLASS(Metrics){};
+}
diff --git a/toolsrc/src/tests_paragraph.cpp b/toolsrc/src/tests_paragraph.cpp
index dd9a40160..47a07e12d 100644
--- a/toolsrc/src/tests_paragraph.cpp
+++ b/toolsrc/src/tests_paragraph.cpp
@@ -27,7 +27,8 @@ namespace UnitTest1
{
auto m_pgh =
vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
- {"Source", "zlib"}, {"Version", "1.2.8"},
+ {"Source", "zlib"},
+ {"Version", "1.2.8"},
}});
Assert::IsTrue(m_pgh.has_value());
@@ -59,7 +60,7 @@ namespace UnitTest1
Assert::AreEqual("m", pgh->core_paragraph->maintainer.c_str());
Assert::AreEqual("d", pgh->core_paragraph->description.c_str());
Assert::AreEqual(size_t(1), pgh->core_paragraph->depends.size());
- Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name.c_str());
+ Assert::AreEqual("bd", pgh->core_paragraph->depends[0].name().c_str());
Assert::AreEqual(size_t(1), pgh->core_paragraph->supports.size());
Assert::AreEqual("x64", pgh->core_paragraph->supports[0].c_str());
}
@@ -68,36 +69,42 @@ namespace UnitTest1
{
auto m_pgh =
vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
- {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl"},
+ {"Source", "zlib"},
+ {"Version", "1.2.8"},
+ {"Build-Depends", "z, openssl"},
}});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size());
- Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str());
- Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str());
+ Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str());
+ Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str());
}
TEST_METHOD(SourceParagraph_Three_Depends)
{
auto m_pgh =
vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
- {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "z, openssl, xyz"},
+ {"Source", "zlib"},
+ {"Version", "1.2.8"},
+ {"Build-Depends", "z, openssl, xyz"},
}});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
Assert::AreEqual(size_t(3), pgh->core_paragraph->depends.size());
- Assert::AreEqual("z", pgh->core_paragraph->depends[0].name.c_str());
- Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name.c_str());
- Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name.c_str());
+ Assert::AreEqual("z", pgh->core_paragraph->depends[0].name().c_str());
+ Assert::AreEqual("openssl", pgh->core_paragraph->depends[1].name().c_str());
+ Assert::AreEqual("xyz", pgh->core_paragraph->depends[2].name().c_str());
}
TEST_METHOD(SourceParagraph_Three_Supports)
{
auto m_pgh =
vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
- {"Source", "zlib"}, {"Version", "1.2.8"}, {"Supports", "x64, windows, uwp"},
+ {"Source", "zlib"},
+ {"Version", "1.2.8"},
+ {"Supports", "x64, windows, uwp"},
}});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
@@ -112,7 +119,9 @@ namespace UnitTest1
{
auto m_pgh =
vcpkg::SourceControlFile::parse_control_file(std::vector<std::unordered_map<std::string, std::string>>{{
- {"Source", "zlib"}, {"Version", "1.2.8"}, {"Build-Depends", "libA [windows], libB [uwp]"},
+ {"Source", "zlib"},
+ {"Version", "1.2.8"},
+ {"Build-Depends", "libA (windows), libB (uwp)"},
}});
Assert::IsTrue(m_pgh.has_value());
auto& pgh = *m_pgh.get();
@@ -122,16 +131,19 @@ namespace UnitTest1
Assert::AreEqual("", pgh->core_paragraph->maintainer.c_str());
Assert::AreEqual("", pgh->core_paragraph->description.c_str());
Assert::AreEqual(size_t(2), pgh->core_paragraph->depends.size());
- Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name.c_str());
+ Assert::AreEqual("libA", pgh->core_paragraph->depends[0].name().c_str());
Assert::AreEqual("windows", pgh->core_paragraph->depends[0].qualifier.c_str());
- Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name.c_str());
+ Assert::AreEqual("libB", pgh->core_paragraph->depends[1].name().c_str());
Assert::AreEqual("uwp", pgh->core_paragraph->depends[1].qualifier.c_str());
}
TEST_METHOD(BinaryParagraph_Construct_Minimum)
{
vcpkg::BinaryParagraph pgh({
- {"Package", "zlib"}, {"Version", "1.2.8"}, {"Architecture", "x86-windows"}, {"Multi-Arch", "same"},
+ {"Package", "zlib"},
+ {"Version", "1.2.8"},
+ {"Architecture", "x86-windows"},
+ {"Multi-Arch", "same"},
});
Assert::AreEqual("zlib", pgh.spec.name().c_str());
@@ -320,7 +332,10 @@ namespace UnitTest1
TEST_METHOD(BinaryParagraph_serialize_min)
{
vcpkg::BinaryParagraph pgh({
- {"Package", "zlib"}, {"Version", "1.2.8"}, {"Architecture", "x86-windows"}, {"Multi-Arch", "same"},
+ {"Package", "zlib"},
+ {"Version", "1.2.8"},
+ {"Architecture", "x86-windows"},
+ {"Multi-Arch", "same"},
});
std::string ss = Strings::serialize(pgh);
auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss).value_or_exit(VCPKG_LINE_INFO);
@@ -369,45 +384,5 @@ namespace UnitTest1
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str());
}
-
- TEST_METHOD(package_spec_parse)
- {
- vcpkg::ExpectedT<vcpkg::FullPackageSpec, vcpkg::PackageSpecParseResult> spec =
- vcpkg::FullPackageSpec::from_string("zlib", vcpkg::Triplet::X86_WINDOWS);
- Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error());
- Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str());
- Assert::AreEqual(vcpkg::Triplet::X86_WINDOWS.canonical_name(),
- spec.get()->package_spec.triplet().canonical_name());
- }
-
- TEST_METHOD(package_spec_parse_with_arch)
- {
- vcpkg::ExpectedT<vcpkg::FullPackageSpec, vcpkg::PackageSpecParseResult> spec =
- vcpkg::FullPackageSpec::from_string("zlib:x64-uwp", vcpkg::Triplet::X86_WINDOWS);
- Assert::AreEqual(vcpkg::PackageSpecParseResult::SUCCESS, spec.error());
- Assert::AreEqual("zlib", spec.get()->package_spec.name().c_str());
- Assert::AreEqual(vcpkg::Triplet::X64_UWP.canonical_name(),
- spec.get()->package_spec.triplet().canonical_name());
- }
-
- TEST_METHOD(package_spec_parse_with_multiple_colon)
- {
- auto ec = vcpkg::FullPackageSpec::from_string("zlib:x86-uwp:", vcpkg::Triplet::X86_WINDOWS).error();
- Assert::AreEqual(vcpkg::PackageSpecParseResult::TOO_MANY_COLONS, ec);
- }
-
- TEST_METHOD(utf8_to_utf16)
- {
- auto str = vcpkg::Strings::to_utf16("abc");
- Assert::AreEqual(L"abc", str.c_str());
- }
-
- TEST_METHOD(utf8_to_utf16_with_whitespace)
- {
- auto str = vcpkg::Strings::to_utf16("abc -x86-windows");
- Assert::AreEqual(L"abc -x86-windows", str.c_str());
- }
};
-
- TEST_CLASS(Metrics){};
}
diff --git a/toolsrc/src/triplet.cpp b/toolsrc/src/triplet.cpp
index 451deb040..3b56da02a 100644
--- a/toolsrc/src/triplet.cpp
+++ b/toolsrc/src/triplet.cpp
@@ -15,7 +15,7 @@ namespace vcpkg
bool operator==(const TripletInstance& o) const { return o.value == value; }
};
- const TripletInstance Triplet::default_instance({});
+ const TripletInstance Triplet::DEFAULT_INSTANCE({});
}
template<>
@@ -41,10 +41,10 @@ namespace vcpkg
Triplet Triplet::from_canonical_name(const std::string& triplet_as_string)
{
std::string s(Strings::ascii_to_lowercase(triplet_as_string));
- auto it = std::find(s.cbegin(), s.cend(), '-');
+ const auto it = std::find(s.cbegin(), s.cend(), '-');
Checks::check_exit(VCPKG_LINE_INFO, it != s.cend(), "Invalid triplet: %s", triplet_as_string);
- auto p = g_triplet_instances.emplace(std::move(s));
+ const auto p = g_triplet_instances.emplace(std::move(s));
return &*p.first;
}
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp
index 738b7b284..f4300a73c 100644
--- a/toolsrc/src/vcpkg.cpp
+++ b/toolsrc/src/vcpkg.cpp
@@ -6,6 +6,7 @@
#include "vcpkg_Chrono.h"
#include "vcpkg_Commands.h"
#include "vcpkg_Files.h"
+#include "vcpkg_GlobalState.h"
#include "vcpkg_Input.h"
#include "vcpkg_Strings.h"
#include "vcpkg_System.h"
@@ -26,14 +27,14 @@ void invalid_command(const std::string& cmd)
static void inner(const VcpkgCmdArguments& args)
{
- Metrics::track_property("command", args.command);
+ Metrics::g_metrics.lock()->track_property("command", args.command);
if (args.command.empty())
{
Commands::Help::print_usage();
Checks::exit_fail(VCPKG_LINE_INFO);
}
- if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_c()))
+ if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_c()))
{
return command_function(args);
}
@@ -46,7 +47,7 @@ static void inner(const VcpkgCmdArguments& args)
else
{
const Optional<std::wstring> vcpkg_root_dir_env = System::get_environment_variable(L"VCPKG_ROOT");
- if (auto v = vcpkg_root_dir_env.get())
+ if (const auto v = vcpkg_root_dir_env.get())
{
vcpkg_root_dir = fs::stdfs::absolute(*v);
}
@@ -66,10 +67,11 @@ static void inner(const VcpkgCmdArguments& args)
vcpkg_root_dir.string(),
expected_paths.error().message());
const VcpkgPaths paths = expected_paths.value_or_exit(VCPKG_LINE_INFO);
- int exit_code = _wchdir(paths.root.c_str());
+ const int exit_code = _wchdir(paths.root.c_str());
Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed");
+ Commands::Version::warn_if_vcpkg_version_mismatch(paths);
- if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b()))
+ if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b()))
{
return command_function(args, paths);
}
@@ -83,7 +85,7 @@ static void inner(const VcpkgCmdArguments& args)
{
const Optional<std::wstring> vcpkg_default_triplet_env =
System::get_environment_variable(L"VCPKG_DEFAULT_TRIPLET");
- if (auto v = vcpkg_default_triplet_env.get())
+ if (const auto v = vcpkg_default_triplet_env.get())
{
default_triplet = Triplet::from_canonical_name(Strings::to_utf8(*v));
}
@@ -95,7 +97,7 @@ static void inner(const VcpkgCmdArguments& args)
Input::check_triplet(default_triplet, paths);
- if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_a()))
+ if (const auto command_function = Commands::find(args.command, Commands::get_available_commands_type_a()))
{
return command_function(args, paths, default_triplet);
}
@@ -103,7 +105,7 @@ static void inner(const VcpkgCmdArguments& args)
return invalid_command(args.command);
}
-static void loadConfig()
+static void load_config()
{
fs::path localappdata;
{
@@ -117,7 +119,7 @@ static void loadConfig()
try
{
auto maybe_pghs = Paragraphs::get_paragraphs(Files::get_real_filesystem(), localappdata / "vcpkg" / "config");
- if (auto p_pghs = maybe_pghs.get())
+ if (const auto p_pghs = maybe_pghs.get())
{
const auto& pghs = *p_pghs;
@@ -134,7 +136,7 @@ static void loadConfig()
auto user_time = keys["User-Since"];
if (!user_id.empty() && !user_time.empty())
{
- Metrics::set_user_information(user_id, user_time);
+ Metrics::g_metrics.lock()->set_user_information(user_id, user_time);
return;
}
}
@@ -145,8 +147,11 @@ static void loadConfig()
// config file not found, could not be read, or invalid
std::string user_id, user_time;
- Metrics::init_user_information(user_id, user_time);
- Metrics::set_user_information(user_id, user_time);
+ {
+ auto locked_metrics = Metrics::g_metrics.lock();
+ locked_metrics->init_user_information(user_id, user_time);
+ locked_metrics->set_user_information(user_id, user_time);
+ }
try
{
std::error_code ec;
@@ -184,34 +189,37 @@ static std::string trim_path_from_command_line(const std::string& full_command_l
return std::string(it, full_command_line.cend());
}
-static ElapsedTime g_timer;
-
int wmain(const int argc, const wchar_t* const* const argv)
{
if (argc == 0) std::abort();
- g_timer = ElapsedTime::create_started();
- atexit([]() {
- auto elapsed_us = g_timer.microseconds();
- Metrics::track_metric("elapsed_us", elapsed_us);
- g_debugging = false;
- Metrics::flush();
- });
+ GlobalState::g_init_console_cp = GetConsoleCP();
+ GlobalState::g_init_console_output_cp = GetConsoleOutputCP();
+
+ SetConsoleCP(65001);
+ SetConsoleOutputCP(65001);
- Metrics::track_property("version", Commands::Version::version());
+ *GlobalState::timer.lock() = ElapsedTime::create_started();
const std::string trimmed_command_line = trim_path_from_command_line(Strings::to_utf8(GetCommandLineW()));
- Metrics::track_property("cmdline", trimmed_command_line);
- loadConfig();
- Metrics::track_property("sqmuser", Metrics::get_SQM_user());
+
+ {
+ auto locked_metrics = Metrics::g_metrics.lock();
+ locked_metrics->track_property("version", Commands::Version::version());
+ locked_metrics->track_property("cmdline", trimmed_command_line);
+ }
+ load_config();
+ Metrics::g_metrics.lock()->track_property("sqmuser", Metrics::get_SQM_user());
const VcpkgCmdArguments args = VcpkgCmdArguments::create_from_command_line(argc, argv);
- if (auto p = args.printmetrics.get()) Metrics::set_print_metrics(*p);
- if (auto p = args.sendmetrics.get()) Metrics::set_send_metrics(*p);
- if (auto p = args.debug.get()) g_debugging = *p;
+ if (const auto p = args.printmetrics.get()) Metrics::g_metrics.lock()->set_print_metrics(*p);
+ if (const auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p);
+ if (const auto p = args.debug.get()) GlobalState::debugging = *p;
+
+ Checks::register_console_ctrl_handler();
- if (g_debugging)
+ if (GlobalState::debugging)
{
inner(args);
Checks::exit_fail(VCPKG_LINE_INFO);
@@ -231,7 +239,7 @@ int wmain(const int argc, const wchar_t* const* const argv)
{
exc_msg = "unknown error(...)";
}
- Metrics::track_property("error", exc_msg);
+ Metrics::g_metrics.lock()->track_property("error", exc_msg);
fflush(stdout);
System::print("vcpkg.exe has crashed.\n"
diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp
index a0d690f37..d40140aca 100644
--- a/toolsrc/src/vcpkg_Build.cpp
+++ b/toolsrc/src/vcpkg_Build.cpp
@@ -8,6 +8,7 @@
#include "vcpkg_Chrono.h"
#include "vcpkg_Commands.h"
#include "vcpkg_Enums.h"
+#include "vcpkg_GlobalState.h"
#include "vcpkg_System.h"
#include "vcpkg_optional.h"
#include "vcpkglib.h"
@@ -29,46 +30,27 @@ namespace vcpkg::Build
CWStringView to_vcvarsall_target(const std::string& cmake_system_name)
{
- if (cmake_system_name == "") return L"";
- if (cmake_system_name == "Windows") return L"";
+ 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";
Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported vcvarsall target %s", cmake_system_name);
}
- CWStringView to_vcvarsall_toolchain(const std::string& target_architecture)
+ CWStringView to_vcvarsall_toolchain(const std::string& target_architecture, const Toolset& toolset)
{
- using CPU = System::CPUArchitecture;
+ auto maybe_target_arch = System::to_cpu_architecture(target_architecture);
+ Checks::check_exit(
+ VCPKG_LINE_INFO, maybe_target_arch.has_value(), "Invalid architecture string: %s", target_architecture);
+ auto target_arch = maybe_target_arch.value_or_exit(VCPKG_LINE_INFO);
+ auto host_architectures = System::get_supported_host_architectures();
- struct ArchOption
+ for (auto&& host : host_architectures)
{
- CWStringView name;
- CPU host_arch;
- CPU target_arch;
- };
-
- static constexpr ArchOption X86 = {L"x86", CPU::X86, CPU::X86};
- static constexpr ArchOption X86_X64 = {L"x86_x64", CPU::X86, CPU::X64};
- static constexpr ArchOption X86_ARM = {L"x86_arm", CPU::X86, CPU::ARM};
- static constexpr ArchOption X86_ARM64 = {L"x86_arm64", CPU::X86, CPU::ARM64};
-
- static constexpr ArchOption X64 = {L"amd64", CPU::X64, CPU::X64};
- static constexpr ArchOption X64_X86 = {L"amd64_x86", CPU::X64, CPU::X86};
- static constexpr ArchOption X64_ARM = {L"amd64_arm", CPU::X64, CPU::ARM};
- static constexpr ArchOption X64_ARM64 = {L"amd64_arm64", CPU::X64, CPU::ARM64};
-
- static constexpr std::array<ArchOption, 8> VALUES = {
- X86, X86_X64, X86_ARM, X86_ARM64, X64, X64_X86, X64_ARM, X64_ARM64};
-
- auto target_arch = System::to_cpu_architecture(target_architecture);
- auto host_arch = System::get_host_processor();
-
- for (auto&& value : VALUES)
- {
- if (target_arch == value.target_arch && host_arch == value.host_arch)
- {
- return value.name;
- }
+ auto it = Util::find_if(toolset.supported_architectures, [&](const ToolsetArchOption& opt) {
+ return host == opt.host_arch && target_arch == opt.target_arch;
+ });
+ if (it != toolset.supported_architectures.end()) return it->name;
}
Checks::exit_with_message(VCPKG_LINE_INFO, "Unsupported toolchain combination %s", target_architecture);
@@ -77,40 +59,48 @@ namespace vcpkg::Build
std::wstring make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset)
{
const wchar_t* tonull = L" >nul";
- if (g_debugging)
+ if (GlobalState::debugging)
{
- tonull = L"";
+ tonull = Strings::WEMPTY;
}
- auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture);
- auto target = to_vcvarsall_target(pre_build_info.cmake_system_name);
+ 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 2>&1)", toolset.vcvarsall.native(), arch, target, tonull);
}
- static void create_binary_control_file(const VcpkgPaths& paths,
- const SourceParagraph& source_paragraph,
+ static void create_binary_feature_control_file(const SourceParagraph& source_paragraph,
+ const FeatureParagraph& feature_paragraph,
+ const Triplet& triplet,
+ BinaryControlFile& bcf)
+ {
+ BinaryParagraph bpgh(source_paragraph, feature_paragraph, triplet);
+ bcf.features.emplace_back(std::move(bpgh));
+ }
+
+ static void create_binary_control_file(const SourceParagraph& source_paragraph,
const Triplet& triplet,
- const BuildInfo& build_info)
+ const BuildInfo& build_info,
+ BinaryControlFile& bcf)
{
- BinaryParagraph bpgh = BinaryParagraph(source_paragraph, triplet);
- if (auto p_ver = build_info.version.get())
+ BinaryParagraph bpgh(source_paragraph, triplet);
+ if (const auto p_ver = build_info.version.get())
{
bpgh.version = *p_ver;
}
- const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL";
- paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh));
+ bcf.core_paragraph = std::move(bpgh);
}
- static void create_binary_feature_control_file(const VcpkgPaths& paths,
- const SourceParagraph& source_paragraph,
- const FeatureParagraph& feature_paragraph,
- const Triplet& triplet,
- const BuildInfo& build_info)
+ static void write_binary_control_file(const VcpkgPaths& paths, BinaryControlFile bcf)
{
- BinaryParagraph bpgh = BinaryParagraph(source_paragraph, feature_paragraph, triplet);
- const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL";
- paths.get_filesystem().write_contents(binary_control_file, Strings::serialize(bpgh));
+ std::string start = Strings::serialize(bcf.core_paragraph);
+ for (auto&& feature : bcf.features)
+ {
+ start += "\n" + Strings::serialize(feature);
+ }
+ const fs::path binary_control_file = paths.packages / bcf.core_paragraph.dir() / "CONTROL";
+ paths.get_filesystem().write_contents(binary_control_file, start);
}
ExtendedBuildResult build_package(const VcpkgPaths& paths,
@@ -142,12 +132,12 @@ namespace vcpkg::Build
const fs::path& git_exe_path = paths.get_git_exe();
const fs::path ports_cmake_script_path = paths.ports_cmake;
- auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet);
+ const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet);
const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset);
const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset);
std::string features;
- if (g_feature_packages)
+ if (GlobalState::feature_packages)
{
if (config.feature_list)
{
@@ -181,26 +171,33 @@ namespace vcpkg::Build
const ElapsedTime timer = ElapsedTime::create_started();
- int return_code = System::cmd_execute_clean(command);
- auto buildtimeus = timer.microseconds();
+ const int return_code = System::cmd_execute_clean(command);
+ const auto buildtimeus = timer.microseconds();
const auto spec_string = spec.to_string();
- Metrics::track_metric("buildtimeus-" + spec_string, buildtimeus);
- if (return_code != 0)
{
- Metrics::track_property("error", "build failed");
- Metrics::track_property("build_error", spec_string);
- return {BuildResult::BUILD_FAILED, {}};
+ auto locked_metrics = Metrics::g_metrics.lock();
+ locked_metrics->track_metric("buildtimeus-" + spec_string, buildtimeus);
+ if (return_code != 0)
+ {
+ locked_metrics->track_property("error", "build failed");
+ locked_metrics->track_property("build_error", spec_string);
+ return {BuildResult::BUILD_FAILED, {}};
+ }
}
- auto build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec));
+ const BuildInfo build_info = read_build_info(paths.get_filesystem(), paths.build_info_file_path(spec));
const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info);
+ BinaryControlFile bcf;
+
+ create_binary_control_file(config.src, triplet, build_info, bcf);
+
if (error_count != 0)
{
return {BuildResult::POST_BUILD_CHECKS_FAILED, {}};
}
- if (g_feature_packages)
+ if (GlobalState::feature_packages)
{
if (config.feature_list)
{
@@ -209,13 +206,13 @@ namespace vcpkg::Build
for (auto&& f_pgh : config.scf->feature_paragraphs)
{
if (f_pgh->name == feature)
- create_binary_feature_control_file(
- paths, *config.scf->core_paragraph, *f_pgh, triplet, build_info);
+ create_binary_feature_control_file(*config.scf->core_paragraph, *f_pgh, triplet, bcf);
}
}
}
}
- create_binary_control_file(paths, config.src, triplet, build_info);
+
+ write_binary_control_file(paths, bcf);
// const fs::path port_buildtrees_dir = paths.buildtrees / spec.name;
// delete_directory(port_buildtrees_dir);
@@ -228,6 +225,7 @@ namespace vcpkg::Build
static const std::string NULLVALUE_STRING = Enums::nullvalue_to_string("vcpkg::Commands::Build::BuildResult");
static const std::string SUCCEEDED_STRING = "SUCCEEDED";
static const std::string BUILD_FAILED_STRING = "BUILD_FAILED";
+ 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";
@@ -238,6 +236,7 @@ namespace vcpkg::Build
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;
default: Checks::unreachable(VCPKG_LINE_INFO);
}
}
@@ -270,7 +269,7 @@ namespace vcpkg::Build
parser.required_field(BuildInfoRequiredField::CRT_LINKAGE, crt_linkage_as_string);
auto crtlinkage = to_linkage_type(crt_linkage_as_string);
- if (auto p = crtlinkage.get())
+ if (const auto p = crtlinkage.get())
build_info.crt_linkage = *p;
else
Checks::exit_with_message(VCPKG_LINE_INFO, "Invalid crt linkage type: [%s]", crt_linkage_as_string);
@@ -280,7 +279,7 @@ namespace vcpkg::Build
std::string library_linkage_as_string;
parser.required_field(BuildInfoRequiredField::LIBRARY_LINKAGE, library_linkage_as_string);
auto liblinkage = to_linkage_type(library_linkage_as_string);
- if (auto p = liblinkage.get())
+ if (const auto p = liblinkage.get())
build_info.library_linkage = *p;
else
Checks::exit_with_message(
@@ -290,12 +289,11 @@ namespace vcpkg::Build
if (!version.empty()) build_info.version = std::move(version);
std::map<BuildPolicy, bool> policies;
- for (auto policy : g_all_policies)
+ for (auto policy : G_ALL_POLICIES)
{
const auto setting = parser.optional_field(to_string(policy));
- if (setting.empty())
- continue;
- else if (setting == "enabled")
+ if (setting.empty()) continue;
+ if (setting == "enabled")
policies.emplace(policy, true);
else if (setting == "disabled")
policies.emplace(policy, false);
@@ -304,7 +302,7 @@ namespace vcpkg::Build
VCPKG_LINE_INFO, "Unknown setting for policy '%s': %s", to_string(policy), setting);
}
- if (auto err = parser.error_info("PostBuildInformation"))
+ if (const auto err = parser.error_info("PostBuildInformation"))
{
print_error_message(err);
Checks::exit_fail(VCPKG_LINE_INFO);
@@ -338,14 +336,14 @@ namespace vcpkg::Build
});
const std::wstring command = Strings::wformat(LR"(%s)", cmd_launch_cmake);
- auto ec_data = System::cmd_execute_and_capture_output(command);
+ const auto ec_data = System::cmd_execute_and_capture_output(command);
Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0);
const std::vector<std::string> lines = Strings::split(ec_data.output, "\n");
PreBuildInfo pre_build_info;
- auto e = lines.cend();
+ const auto e = lines.cend();
auto cur = std::find(lines.cbegin(), e, FLAG_GUID);
if (cur != e) ++cur;
@@ -361,7 +359,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 ? "" : s.at(1);
+ const std::string variable_value = variable_with_no_value ? Strings::EMPTY : s.at(1);
if (variable_name == "VCPKG_TARGET_ARCHITECTURE")
{
diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp
index 2674b889a..e7c9046a4 100644
--- a/toolsrc/src/vcpkg_Checks.cpp
+++ b/toolsrc/src/vcpkg_Checks.cpp
@@ -1,11 +1,45 @@
#include "pch.h"
+#include "metrics.h"
#include "vcpkg_Checks.h"
+#include "vcpkg_GlobalState.h"
#include "vcpkg_System.h"
#include "vcpkglib.h"
namespace vcpkg::Checks
{
+ [[noreturn]] static void cleanup_and_exit(const int exit_code)
+ {
+ const auto elapsed_us = GlobalState::timer.lock()->microseconds();
+
+ auto metrics = Metrics::g_metrics.lock();
+ metrics->track_metric("elapsed_us", elapsed_us);
+ GlobalState::debugging = false;
+ metrics->flush();
+
+ SetConsoleCP(GlobalState::g_init_console_cp);
+ SetConsoleOutputCP(GlobalState::g_init_console_output_cp);
+
+ fflush(nullptr);
+
+ ::TerminateProcess(::GetCurrentProcess(), exit_code);
+ }
+
+ static BOOL ctrl_handler(DWORD fdw_ctrl_type)
+ {
+ {
+ auto locked_metrics = Metrics::g_metrics.lock();
+ locked_metrics->track_property("CtrlHandler", std::to_string(fdw_ctrl_type));
+ locked_metrics->track_property("error", "CtrlHandler was fired.");
+ }
+ cleanup_and_exit(EXIT_FAILURE);
+ }
+
+ void register_console_ctrl_handler()
+ {
+ SetConsoleCtrlHandler(reinterpret_cast<PHANDLER_ROUTINE>(ctrl_handler), TRUE);
+ }
+
[[noreturn]] void unreachable(const LineInfo& line_info)
{
System::println(System::Color::error, "Error: Unreachable code was reached");
@@ -13,19 +47,19 @@ namespace vcpkg::Checks
#ifndef NDEBUG
std::abort();
#else
- ::exit(EXIT_FAILURE);
+ cleanup_and_exit(EXIT_FAILURE);
#endif
}
[[noreturn]] void exit_with_code(const LineInfo& line_info, const int exit_code)
{
Debug::println(System::Color::error, line_info.to_string());
- ::exit(exit_code);
+ cleanup_and_exit(exit_code);
}
- [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView errorMessage)
+ [[noreturn]] void exit_with_message(const LineInfo& line_info, const CStringView error_message)
{
- System::println(System::Color::error, errorMessage);
+ System::println(System::Color::error, error_message);
exit_fail(line_info);
}
@@ -33,15 +67,15 @@ namespace vcpkg::Checks
{
if (!expression)
{
- exit_with_message(line_info, "");
+ exit_with_message(line_info, Strings::EMPTY);
}
}
- void check_exit(const LineInfo& line_info, bool expression, const CStringView errorMessage)
+ void check_exit(const LineInfo& line_info, bool expression, const CStringView error_message)
{
if (!expression)
{
- exit_with_message(line_info, errorMessage);
+ exit_with_message(line_info, error_message);
}
}
}
diff --git a/toolsrc/src/vcpkg_Chrono.cpp b/toolsrc/src/vcpkg_Chrono.cpp
index d70f4a054..d96f30987 100644
--- a/toolsrc/src/vcpkg_Chrono.cpp
+++ b/toolsrc/src/vcpkg_Chrono.cpp
@@ -7,43 +7,43 @@ namespace vcpkg
{
static std::string format_time_userfriendly(const std::chrono::nanoseconds& nanos)
{
+ using std::chrono::duration_cast;
using std::chrono::hours;
- using std::chrono::minutes;
- using std::chrono::seconds;
- using std::chrono::milliseconds;
using std::chrono::microseconds;
+ using std::chrono::milliseconds;
+ using std::chrono::minutes;
using std::chrono::nanoseconds;
- using std::chrono::duration_cast;
+ using std::chrono::seconds;
const double nanos_as_double = static_cast<double>(nanos.count());
if (duration_cast<hours>(nanos) > hours())
{
- auto t = nanos_as_double / duration_cast<nanoseconds>(hours(1)).count();
+ const auto t = nanos_as_double / duration_cast<nanoseconds>(hours(1)).count();
return Strings::format("%.4g h", t);
}
if (duration_cast<minutes>(nanos) > minutes())
{
- auto t = nanos_as_double / duration_cast<nanoseconds>(minutes(1)).count();
+ const auto t = nanos_as_double / duration_cast<nanoseconds>(minutes(1)).count();
return Strings::format("%.4g min", t);
}
if (duration_cast<seconds>(nanos) > seconds())
{
- auto t = nanos_as_double / duration_cast<nanoseconds>(seconds(1)).count();
+ const auto t = nanos_as_double / duration_cast<nanoseconds>(seconds(1)).count();
return Strings::format("%.4g s", t);
}
if (duration_cast<milliseconds>(nanos) > milliseconds())
{
- auto t = nanos_as_double / duration_cast<nanoseconds>(milliseconds(1)).count();
+ const auto t = nanos_as_double / duration_cast<nanoseconds>(milliseconds(1)).count();
return Strings::format("%.4g ms", t);
}
if (duration_cast<microseconds>(nanos) > microseconds())
{
- auto t = nanos_as_double / duration_cast<nanoseconds>(microseconds(1)).count();
+ const auto t = nanos_as_double / duration_cast<nanoseconds>(microseconds(1)).count();
return Strings::format("%.4g us", t);
}
diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp
index 820e51b33..8dd60a2eb 100644
--- a/toolsrc/src/vcpkg_Dependencies.cpp
+++ b/toolsrc/src/vcpkg_Dependencies.cpp
@@ -7,12 +7,105 @@
#include "vcpkg_Dependencies.h"
#include "vcpkg_Files.h"
#include "vcpkg_Graphs.h"
+#include "vcpkg_Strings.h"
#include "vcpkg_Util.h"
#include "vcpkglib.h"
namespace vcpkg::Dependencies
{
+ struct FeatureNodeEdges
+ {
+ std::vector<FeatureSpec> remove_edges;
+ std::vector<FeatureSpec> build_edges;
+ bool plus = false;
+ };
+
+ struct Cluster : Util::MoveOnlyBase
+ {
+ std::vector<StatusParagraph*> status_paragraphs;
+ Optional<const SourceControlFile*> source_control_file;
+ PackageSpec spec;
+ std::unordered_map<std::string, FeatureNodeEdges> edges;
+ std::unordered_set<std::string> to_install_features;
+ std::unordered_set<std::string> original_features;
+ bool will_remove = false;
+ bool transient_uninstalled = true;
+ RequestType request_type = RequestType::AUTO_SELECTED;
+ };
+
+ struct ClusterPtr
+ {
+ Cluster* ptr;
+
+ Cluster* operator->() const { return ptr; }
+ };
+
bool operator==(const ClusterPtr& l, const ClusterPtr& r) { return l.ptr == r.ptr; }
+}
+
+template<>
+struct std::hash<vcpkg::Dependencies::ClusterPtr>
+{
+ size_t operator()(const vcpkg::Dependencies::ClusterPtr& value) const
+ {
+ return std::hash<vcpkg::PackageSpec>()(value.ptr->spec);
+ }
+};
+
+namespace vcpkg::Dependencies
+{
+ struct GraphPlan
+ {
+ Graphs::Graph<ClusterPtr> remove_graph;
+ Graphs::Graph<ClusterPtr> install_graph;
+ };
+
+ struct ClusterGraph : Util::MoveOnlyBase
+ {
+ explicit ClusterGraph(std::unordered_map<std::string, const SourceControlFile*>&& ports)
+ : m_ports(std::move(ports))
+ {
+ }
+
+ Cluster& get(const PackageSpec& spec)
+ {
+ auto it = m_graph.find(spec);
+ if (it == m_graph.end())
+ {
+ // Load on-demand from m_ports
+ auto it_ports = m_ports.find(spec.name());
+ if (it_ports != m_ports.end())
+ {
+ auto& clust = m_graph[spec];
+ clust.spec = spec;
+ cluster_from_scf(*it_ports->second, clust);
+ return clust;
+ }
+ return m_graph[spec];
+ }
+ return it->second;
+ }
+
+ private:
+ void cluster_from_scf(const SourceControlFile& scf, Cluster& out_cluster) const
+ {
+ FeatureNodeEdges core_dependencies;
+ core_dependencies.build_edges =
+ filter_dependencies_to_specs(scf.core_paragraph->depends, out_cluster.spec.triplet());
+ out_cluster.edges.emplace("core", std::move(core_dependencies));
+
+ for (const auto& feature : scf.feature_paragraphs)
+ {
+ FeatureNodeEdges added_edges;
+ added_edges.build_edges = filter_dependencies_to_specs(feature->depends, out_cluster.spec.triplet());
+ out_cluster.edges.emplace(feature->name, std::move(added_edges));
+ }
+ out_cluster.source_control_file = &scf;
+ }
+
+ std::unordered_map<PackageSpec, Cluster> m_graph;
+ std::unordered_map<std::string, const SourceControlFile*> m_ports;
+ };
std::vector<PackageSpec> AnyParagraph::dependencies(const Triplet& triplet) const
{
@@ -27,9 +120,11 @@ namespace vcpkg::Dependencies
return to_package_specs(p->package.depends);
}
- if (auto p = this->binary_paragraph.get())
+ if (auto p = this->binary_control_file.get())
{
- return to_package_specs(p->depends);
+ 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);
}
if (auto p = this->source_paragraph.get())
@@ -51,54 +146,57 @@ namespace vcpkg::Dependencies
}
}
- InstallPlanAction::InstallPlanAction()
- : spec(), any_paragraph(), plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN)
- {
- }
+ InstallPlanAction::InstallPlanAction() : plan_type(InstallPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {}
InstallPlanAction::InstallPlanAction(const PackageSpec& spec,
const SourceControlFile& any_paragraph,
const std::unordered_set<std::string>& features,
const RequestType& request_type)
- : InstallPlanAction()
+ : spec(spec), plan_type(InstallPlanType::BUILD_AND_INSTALL), request_type(request_type), feature_list(features)
{
- this->spec = spec;
- this->request_type = request_type;
-
- this->plan_type = InstallPlanType::BUILD_AND_INSTALL;
this->any_paragraph.source_control_file = &any_paragraph;
- this->feature_list = features;
+ }
+
+ InstallPlanAction::InstallPlanAction(const PackageSpec& spec,
+ const std::unordered_set<std::string>& features,
+ const RequestType& request_type)
+ : spec(spec), plan_type(InstallPlanType::ALREADY_INSTALLED), request_type(request_type), feature_list(features)
+ {
}
InstallPlanAction::InstallPlanAction(const PackageSpec& spec,
const AnyParagraph& any_paragraph,
const RequestType& request_type)
- : InstallPlanAction()
+ : spec(spec), any_paragraph(any_paragraph), plan_type(InstallPlanType::UNKNOWN), request_type(request_type)
{
- this->spec = spec;
- this->request_type = request_type;
if (auto p = any_paragraph.status_paragraph.get())
{
this->plan_type = InstallPlanType::ALREADY_INSTALLED;
- this->any_paragraph.status_paragraph = *p;
return;
}
- if (auto p = any_paragraph.binary_paragraph.get())
+ if (auto p = any_paragraph.binary_control_file.get())
{
this->plan_type = InstallPlanType::INSTALL;
- this->any_paragraph.binary_paragraph = *p;
return;
}
if (auto p = any_paragraph.source_paragraph.get())
{
this->plan_type = InstallPlanType::BUILD_AND_INSTALL;
- this->any_paragraph.source_paragraph = *p;
return;
}
+ }
+
+ std::string InstallPlanAction::displayname() const
+ {
+ if (this->feature_list.empty())
+ {
+ return this->spec.to_string();
+ }
- this->plan_type = InstallPlanType::UNKNOWN;
+ const std::string features = Strings::join(",", this->feature_list);
+ return Strings::format("%s[%s]:%s", this->spec.name(), features, this->spec.triplet());
}
bool InstallPlanAction::compare_by_name(const InstallPlanAction* left, const InstallPlanAction* right)
@@ -115,39 +213,44 @@ namespace vcpkg::Dependencies
{
}
- bool ExportPlanAction::compare_by_name(const ExportPlanAction* left, const ExportPlanAction* right)
+ const PackageSpec& AnyAction::spec() const
{
- return left->spec.name() < right->spec.name();
+ if (const auto p = install_plan.get())
+ {
+ return p->spec;
+ }
+
+ if (const auto p = remove_plan.get())
+ {
+ return p->spec;
+ }
+
+ Checks::exit_with_message(VCPKG_LINE_INFO, "Null action");
}
- ExportPlanAction::ExportPlanAction()
- : spec(), any_paragraph(), plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN)
+ bool ExportPlanAction::compare_by_name(const ExportPlanAction* left, const ExportPlanAction* right)
{
+ return left->spec.name() < right->spec.name();
}
+ ExportPlanAction::ExportPlanAction() : plan_type(ExportPlanType::UNKNOWN), request_type(RequestType::UNKNOWN) {}
+
ExportPlanAction::ExportPlanAction(const PackageSpec& spec,
const AnyParagraph& any_paragraph,
const RequestType& request_type)
- : ExportPlanAction()
+ : spec(spec), any_paragraph(any_paragraph), plan_type(ExportPlanType::UNKNOWN), request_type(request_type)
{
- this->spec = spec;
- this->request_type = request_type;
-
- if (auto p = any_paragraph.binary_paragraph.get())
+ if (auto p = any_paragraph.binary_control_file.get())
{
this->plan_type = ExportPlanType::ALREADY_BUILT;
- this->any_paragraph.binary_paragraph = *p;
return;
}
if (auto p = any_paragraph.source_paragraph.get())
{
this->plan_type = ExportPlanType::PORT_AVAILABLE_BUT_NOT_BUILT;
- this->any_paragraph.source_paragraph = *p;
return;
}
-
- this->plan_type = ExportPlanType::UNKNOWN;
}
bool RemovePlanAction::compare_by_name(const RemovePlanAction* left, const RemovePlanAction* right)
@@ -155,9 +258,9 @@ namespace vcpkg::Dependencies
return left->spec.name() < right->spec.name();
}
- MapPortFile::MapPortFile(const std::unordered_map<PackageSpec, SourceControlFile>& map) : ports(map) {}
+ MapPortFile::MapPortFile(const std::unordered_map<std::string, SourceControlFile>& map) : ports(map) {}
- const SourceControlFile& MapPortFile::get_control_file(const PackageSpec& spec) const
+ const SourceControlFile& MapPortFile::get_control_file(const std::string& spec) const
{
auto scf = ports.find(spec);
if (scf == ports.end())
@@ -169,9 +272,9 @@ namespace vcpkg::Dependencies
PathsPortFile::PathsPortFile(const VcpkgPaths& paths) : ports(paths) {}
- const SourceControlFile& PathsPortFile::get_control_file(const PackageSpec& spec) const
+ const SourceControlFile& PathsPortFile::get_control_file(const std::string& spec) const
{
- std::unordered_map<PackageSpec, SourceControlFile>::iterator cache_it = cache.find(spec);
+ auto cache_it = cache.find(spec);
if (cache_it != cache.end())
{
return cache_it->second;
@@ -219,7 +322,9 @@ namespace vcpkg::Dependencies
auto it = status_db.find_installed(spec);
if (it != status_db.end()) return InstallPlanAction{spec, {*it->get(), nullopt, nullopt}, request_type};
return InstallPlanAction{
- spec, {nullopt, nullopt, *port_file_provider.get_control_file(spec).core_paragraph}, request_type};
+ spec,
+ {nullopt, nullopt, *port_file_provider.get_control_file(spec.name()).core_paragraph},
+ request_type};
}
};
@@ -319,9 +424,9 @@ namespace vcpkg::Dependencies
? RequestType::USER_REQUESTED
: RequestType::AUTO_SELECTED;
- Expected<BinaryParagraph> maybe_bpgh = Paragraphs::try_load_cached_package(paths, spec);
- if (auto bpgh = maybe_bpgh.get())
- return ExportPlanAction{spec, {nullopt, *bpgh, nullopt}, request_type};
+ Expected<BinaryControlFile> maybe_bpgh = Paragraphs::try_load_cached_control_package(paths, spec);
+ if (auto bcf = maybe_bpgh.get())
+ return ExportPlanAction{spec, AnyParagraph{nullopt, std::move(*bcf), nullopt}, request_type};
auto maybe_scf = Paragraphs::try_load_port(paths.get_filesystem(), paths.port_dir(spec));
if (auto scf = maybe_scf.get())
@@ -339,93 +444,79 @@ namespace vcpkg::Dependencies
return toposort;
}
- std::vector<FeatureSpec> to_feature_specs(const std::vector<std::string>& depends, const Triplet& triplet)
+ enum class MarkPlusResult
{
- std::vector<FeatureSpec> f_specs;
- for (auto&& depend : depends)
- {
- int end = (int)depend.find(']');
- if (end != std::string::npos)
- {
- int start = (int)depend.find('[');
-
- auto feature_name = depend.substr(start + 1, end - start - 1);
- auto package_name = depend.substr(0, start);
- auto p_spec = PackageSpec::from_name_and_triplet(package_name, triplet).value_or_exit(VCPKG_LINE_INFO);
- auto feature_spec = FeatureSpec{p_spec, feature_name};
- f_specs.emplace_back(std::move(feature_spec));
- }
- else
- {
- auto p_spec = PackageSpec::from_name_and_triplet(depend, triplet).value_or_exit(VCPKG_LINE_INFO);
+ FEATURE_NOT_FOUND,
+ SUCCESS,
+ };
- auto feature_spec = FeatureSpec{p_spec, ""};
- f_specs.emplace_back(std::move(feature_spec));
- }
- }
- return f_specs;
- }
+ MarkPlusResult mark_plus(const std::string& feature,
+ Cluster& cluster,
+ ClusterGraph& pkg_to_cluster,
+ GraphPlan& graph_plan);
+ void mark_minus(Cluster& cluster, ClusterGraph& pkg_to_cluster, GraphPlan& graph_plan);
- bool mark_plus(const std::string& feature,
- Cluster& cluster,
- std::unordered_map<PackageSpec, Cluster>& pkg_to_cluster,
- GraphPlan& graph_plan)
+ MarkPlusResult mark_plus(const std::string& feature, Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan)
{
- auto it = cluster.edges.find(feature);
- std::string updated_feature = feature;
- if (updated_feature == "")
- {
- updated_feature = "core";
- it = cluster.edges.find("core");
- }
- if (it == cluster.edges.end())
+ if (feature.empty())
{
- Checks::unreachable(VCPKG_LINE_INFO);
+ // Indicates that core was not specified in the reference
+ return mark_plus("core", cluster, graph, graph_plan);
}
- if (cluster.edges[updated_feature].plus) return true;
+ auto it = cluster.edges.find(feature);
+ if (it == cluster.edges.end()) return MarkPlusResult::FEATURE_NOT_FOUND;
- if (cluster.original_features.find(updated_feature) == cluster.original_features.end())
+ if (cluster.edges[feature].plus) return MarkPlusResult::SUCCESS;
+
+ if (cluster.original_features.find(feature) == cluster.original_features.end())
{
cluster.transient_uninstalled = true;
}
if (!cluster.transient_uninstalled)
{
- return false;
+ return MarkPlusResult::SUCCESS;
}
- cluster.edges[updated_feature].plus = true;
+ cluster.edges[feature].plus = true;
if (!cluster.original_features.empty())
{
- mark_minus(cluster, pkg_to_cluster, graph_plan);
+ mark_minus(cluster, graph, graph_plan);
}
graph_plan.install_graph.add_vertex({&cluster});
auto& tracked = cluster.to_install_features;
- tracked.insert(updated_feature);
- if (tracked.find("core") == tracked.end() && tracked.find("") == tracked.end())
+ tracked.insert(feature);
+
+ if (feature != "core")
{
- cluster.to_install_features.insert("core");
- for (auto&& depend : cluster.edges["core"].build_edges)
- {
- auto& depend_cluster = pkg_to_cluster[depend.spec];
- mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan);
- graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster});
- }
+ // All features implicitly depend on core
+ auto res = mark_plus("core", cluster, graph, graph_plan);
+
+ // Should be impossible for "core" to not exist
+ Checks::check_exit(VCPKG_LINE_INFO, res == MarkPlusResult::SUCCESS);
}
- for (auto&& depend : cluster.edges[updated_feature].build_edges)
+ for (auto&& depend : cluster.edges[feature].build_edges)
{
- auto& depend_cluster = pkg_to_cluster[depend.spec];
- mark_plus(depend.feature_name, depend_cluster, pkg_to_cluster, graph_plan);
+ auto& depend_cluster = graph.get(depend.spec());
+ auto res = mark_plus(depend.feature(), depend_cluster, graph, graph_plan);
+
+ Checks::check_exit(VCPKG_LINE_INFO,
+ res == MarkPlusResult::SUCCESS,
+ "Error: Unable to satisfy dependency %s of %s",
+ depend,
+ FeatureSpec(cluster.spec, feature));
+
if (&depend_cluster == &cluster) continue;
graph_plan.install_graph.add_edge({&cluster}, {&depend_cluster});
}
- return true;
+
+ return MarkPlusResult::SUCCESS;
}
- void mark_minus(Cluster& cluster, std::unordered_map<PackageSpec, Cluster>& pkg_to_cluster, GraphPlan& graph_plan)
+ void mark_minus(Cluster& cluster, ClusterGraph& graph, GraphPlan& graph_plan)
{
if (cluster.will_remove) return;
cluster.will_remove = true;
@@ -436,89 +527,93 @@ namespace vcpkg::Dependencies
auto& remove_edges_edges = pair.second.remove_edges;
for (auto&& depend : remove_edges_edges)
{
- auto& depend_cluster = pkg_to_cluster[depend.spec];
+ auto& depend_cluster = graph.get(depend.spec());
graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster});
- depend_cluster.transient_uninstalled = true;
- mark_minus(depend_cluster, pkg_to_cluster, graph_plan);
+ mark_minus(depend_cluster, graph, graph_plan);
}
}
+
+ cluster.transient_uninstalled = true;
for (auto&& original_feature : cluster.original_features)
{
- cluster.transient_uninstalled = true;
- mark_plus(original_feature, cluster, pkg_to_cluster, graph_plan);
+ auto res = mark_plus(original_feature, cluster, graph, graph_plan);
+ if (res != MarkPlusResult::SUCCESS)
+ {
+ System::println(System::Color::warning,
+ "Warning: could not reinstall feature %s",
+ FeatureSpec{cluster.spec, original_feature});
+ }
}
}
- std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<PackageSpec, SourceControlFile>& map,
- const std::vector<FullPackageSpec>& specs,
- const StatusParagraphs& status_db)
+
+ static ClusterGraph create_feature_install_graph(const std::unordered_map<std::string, SourceControlFile>& map,
+ const StatusParagraphs& status_db)
{
- std::unordered_map<PackageSpec, Cluster> pkg_spec_to_package_node;
+ std::unordered_map<std::string, const SourceControlFile*> ptr_map;
+ for (auto&& p : map)
+ ptr_map.emplace(p.first, &p.second);
+ ClusterGraph graph(std::move(ptr_map));
+
+ auto installed_ports = get_installed_ports(status_db);
- for (const auto& it : map)
+ for (auto&& status_paragraph : installed_ports)
{
- Cluster& node = pkg_spec_to_package_node[it.first];
+ Cluster& cluster = graph.get(status_paragraph->package.spec);
- node.spec = it.first;
- FeatureNodeEdges core_dependencies;
- auto core_depends = filter_dependencies(it.second.core_paragraph->depends, node.spec.triplet());
- core_dependencies.build_edges = to_feature_specs(core_depends, node.spec.triplet());
- node.edges["core"] = std::move(core_dependencies);
+ cluster.transient_uninstalled = false;
- for (const auto& feature : it.second.feature_paragraphs)
+ cluster.status_paragraphs.emplace_back(status_paragraph);
+
+ auto& status_paragraph_feature = status_paragraph->package.feature;
+ // In this case, empty string indicates the "core" paragraph for a package.
+ if (status_paragraph_feature.empty())
{
- FeatureNodeEdges added_edges;
- auto depends = filter_dependencies(feature->depends, node.spec.triplet());
- added_edges.build_edges = to_feature_specs(depends, node.spec.triplet());
- node.edges.emplace(feature->name, std::move(added_edges));
+ cluster.original_features.insert("core");
+ }
+ else
+ {
+ cluster.original_features.insert(status_paragraph_feature);
}
- node.source_control_file = &it.second;
}
- for (auto&& status_paragraph : get_installed_ports(status_db))
+ for (auto&& status_paragraph : installed_ports)
{
auto& spec = status_paragraph->package.spec;
auto& status_paragraph_feature = status_paragraph->package.feature;
- Cluster& cluster = pkg_spec_to_package_node[spec];
-
- cluster.transient_uninstalled = false;
- auto reverse_edges =
- to_feature_specs(status_paragraph->package.depends, status_paragraph->package.spec.triplet());
+ auto reverse_edges = FeatureSpec::from_strings_and_triplet(status_paragraph->package.depends,
+ status_paragraph->package.spec.triplet());
for (auto&& dependency : reverse_edges)
{
- auto pkg_node = pkg_spec_to_package_node.find(dependency.spec);
- auto depends_name = dependency.feature_name;
- if (depends_name == "")
- {
- for (auto&& default_feature : status_paragraph->package.default_features)
- {
- auto& target_node = pkg_node->second.edges[default_feature];
- target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature});
- }
- depends_name = "core";
- }
- auto& target_node = pkg_node->second.edges[depends_name];
+ auto& dep_cluster = graph.get(dependency.spec());
+
+ auto depends_name = dependency.feature();
+ if (depends_name.empty()) depends_name = "core";
+
+ auto& target_node = dep_cluster.edges[depends_name];
target_node.remove_edges.emplace_back(FeatureSpec{spec, status_paragraph_feature});
}
- cluster.status_paragraphs.emplace_back(*status_paragraph);
- if (status_paragraph_feature == "")
- {
- cluster.original_features.insert("core");
- }
- else
- {
- cluster.original_features.insert(status_paragraph_feature);
- }
}
+ return graph;
+ }
+
+ std::vector<AnyAction> create_feature_install_plan(const std::unordered_map<std::string, SourceControlFile>& map,
+ const std::vector<FeatureSpec>& specs,
+ const StatusParagraphs& status_db)
+ {
+ ClusterGraph graph = create_feature_install_graph(map, status_db);
GraphPlan graph_plan;
for (auto&& spec : specs)
{
- Cluster& spec_cluster = pkg_spec_to_package_node[spec.package_spec];
- for (auto&& feature : spec.features)
- {
- mark_plus(feature, spec_cluster, pkg_spec_to_package_node, graph_plan);
- }
+ 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);
+
+ 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});
}
Graphs::GraphAdjacencyProvider<ClusterPtr> adjacency_remove_graph(graph_plan.remove_graph.adjacency_list());
@@ -529,38 +624,46 @@ namespace vcpkg::Dependencies
auto insert_vertex_list = graph_plan.install_graph.vertex_list();
auto insert_toposort = Graphs::topological_sort(insert_vertex_list, adjacency_install_graph);
- std::vector<AnyAction> install_plan;
+ std::vector<AnyAction> plan;
- for (auto&& like_cluster : remove_toposort)
+ for (auto&& p_cluster : remove_toposort)
{
- auto scf = *like_cluster.ptr->source_control_file.get();
-
- AnyAction any_plan;
- any_plan.remove_plan = RemovePlanAction{
- PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet())
- .value_or_exit(VCPKG_LINE_INFO),
+ auto scf = *p_cluster->source_control_file.get();
+ auto spec = PackageSpec::from_name_and_triplet(scf->core_paragraph->name, p_cluster->spec.triplet())
+ .value_or_exit(VCPKG_LINE_INFO);
+ plan.emplace_back(RemovePlanAction{
+ std::move(spec),
RemovePlanType::REMOVE,
- RequestType::AUTO_SELECTED};
-
- install_plan.emplace_back(std::move(any_plan));
+ p_cluster->request_type,
+ });
}
- for (auto&& like_cluster : insert_toposort)
+ for (auto&& p_cluster : insert_toposort)
{
- if (!like_cluster.ptr->transient_uninstalled) continue;
-
- auto scf = *like_cluster.ptr->source_control_file.get();
- auto pkg_spec =
- PackageSpec::from_name_and_triplet(scf->core_paragraph->name, like_cluster.ptr->spec.triplet())
- .value_or_exit(VCPKG_LINE_INFO);
- auto action =
- InstallPlanAction{pkg_spec, *scf, like_cluster.ptr->to_install_features, RequestType::AUTO_SELECTED};
-
- AnyAction any_plan;
- any_plan.install_plan = std::move(action);
- install_plan.emplace_back(std::move(any_plan));
+ if (p_cluster->transient_uninstalled)
+ {
+ // If it will be transiently uninstalled, we need to issue a full installation command
+ auto pscf = p_cluster->source_control_file.value_or_exit(VCPKG_LINE_INFO);
+ Checks::check_exit(VCPKG_LINE_INFO, pscf != nullptr);
+ plan.emplace_back(InstallPlanAction{
+ p_cluster->spec,
+ *pscf,
+ p_cluster->to_install_features,
+ p_cluster->request_type,
+ });
+ }
+ else
+ {
+ // If the package isn't transitively installed, still include it if the user explicitly requested it
+ if (p_cluster->request_type != RequestType::USER_REQUESTED) continue;
+ plan.emplace_back(InstallPlanAction{
+ p_cluster->spec,
+ p_cluster->original_features,
+ p_cluster->request_type,
+ });
+ }
}
- return install_plan;
+ return plan;
}
}
diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp
index 29da7e684..ad1fcebc6 100644
--- a/toolsrc/src/vcpkg_Files.cpp
+++ b/toolsrc/src/vcpkg_Files.cpp
@@ -2,6 +2,7 @@
#include "vcpkg_Files.h"
#include "vcpkg_System.h"
+#include "vcpkg_Util.h"
#include <thread>
namespace vcpkg::Files
@@ -186,11 +187,23 @@ namespace vcpkg::Files
void print_paths(const std::vector<fs::path>& paths)
{
- System::println("");
+ System::println();
for (const fs::path& p : paths)
{
System::println(" %s", p.generic_string());
}
- System::println("");
+ System::println();
+ }
+
+ std::vector<fs::path> find_from_PATH(const std::wstring& name)
+ {
+ const std::wstring cmd = Strings::wformat(L"where.exe %s", name);
+ auto out = System::cmd_execute_and_capture_output(cmd);
+ if (out.exit_code != 0)
+ {
+ return {};
+ }
+
+ return Util::fmap(Strings::split(out.output, "\n"), [](auto&& s) { return fs::path(s); });
}
}
diff --git a/toolsrc/src/vcpkg_GlobalState.cpp b/toolsrc/src/vcpkg_GlobalState.cpp
new file mode 100644
index 000000000..2221222c0
--- /dev/null
+++ b/toolsrc/src/vcpkg_GlobalState.cpp
@@ -0,0 +1,13 @@
+#include "pch.h"
+
+#include "vcpkg_GlobalState.h"
+
+namespace vcpkg
+{
+ Util::LockGuarded<ElapsedTime> GlobalState::timer;
+ 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;
+}
diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp
index f4e9a07c2..f1cac9632 100644
--- a/toolsrc/src/vcpkg_Input.cpp
+++ b/toolsrc/src/vcpkg_Input.cpp
@@ -13,7 +13,7 @@ namespace vcpkg::Input
{
const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string);
auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet);
- if (auto spec = expected_spec.get())
+ if (const auto spec = expected_spec.get())
{
return PackageSpec{spec->package_spec};
}
@@ -29,7 +29,7 @@ namespace vcpkg::Input
if (!paths.is_valid_triplet(t))
{
System::println(System::Color::error, "Error: invalid triplet: %s", t);
- Metrics::track_property("error", "invalid triplet: " + t.to_string());
+ Metrics::g_metrics.lock()->track_property("error", "invalid triplet: " + t.to_string());
Commands::Help::help_topic_valid_triplet(paths);
Checks::exit_fail(VCPKG_LINE_INFO);
}
@@ -41,7 +41,7 @@ namespace vcpkg::Input
{
const std::string as_lowercase = Strings::ascii_to_lowercase(full_package_spec_as_string);
auto expected_spec = FullPackageSpec::from_string(as_lowercase, default_triplet);
- if (auto spec = expected_spec.get())
+ if (const auto spec = expected_spec.get())
{
return *spec;
}
diff --git a/toolsrc/src/vcpkg_Parse.cpp b/toolsrc/src/vcpkg_Parse.cpp
index 659af2939..e671a1a05 100644
--- a/toolsrc/src/vcpkg_Parse.cpp
+++ b/toolsrc/src/vcpkg_Parse.cpp
@@ -23,14 +23,14 @@ namespace vcpkg::Parse
void ParagraphParser::required_field(const std::string& fieldname, std::string& out)
{
auto maybe_field = remove_field(&fields, fieldname);
- if (auto field = maybe_field.get())
+ if (const auto field = maybe_field.get())
out = std::move(*field);
else
missing_fields.push_back(fieldname);
}
- std::string ParagraphParser::optional_field(const std::string& fieldname)
+ std::string ParagraphParser::optional_field(const std::string& fieldname) const
{
- return remove_field(&fields, fieldname).value_or("");
+ return remove_field(&fields, fieldname).value_or(Strings::EMPTY);
}
std::unique_ptr<ParseControlErrorInfo> ParagraphParser::error_info(const std::string& name) const
{
@@ -44,4 +44,37 @@ namespace vcpkg::Parse
}
return nullptr;
}
+
+ std::vector<std::string> parse_comma_list(const std::string& str)
+ {
+ if (str.empty())
+ {
+ return {};
+ }
+
+ std::vector<std::string> out;
+
+ size_t cur = 0;
+ do
+ {
+ auto pos = str.find(',', cur);
+ if (pos == std::string::npos)
+ {
+ out.push_back(str.substr(cur));
+ break;
+ }
+ out.push_back(str.substr(cur, pos - cur));
+
+ // skip comma and space
+ ++pos;
+ if (str[pos] == ' ')
+ {
+ ++pos;
+ }
+
+ cur = pos;
+ } while (cur != std::string::npos);
+
+ return out;
+ }
}
diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp
index 0c1c1f9f9..5ad951399 100644
--- a/toolsrc/src/vcpkg_Strings.cpp
+++ b/toolsrc/src/vcpkg_Strings.cpp
@@ -130,12 +130,17 @@ namespace vcpkg::Strings
trim(&s);
}
- Util::erase_remove_if(*strings, [](const std::string& s) { return s == ""; });
+ Util::erase_remove_if(*strings, [](const std::string& s) { return s.empty(); });
}
std::vector<std::string> split(const std::string& s, const std::string& delimiter)
{
std::vector<std::string> output;
+
+ if(delimiter.empty()){
+ output.push_back(s);
+ return output;
+ }
size_t i = 0;
for (size_t pos = s.find(delimiter); pos != std::string::npos; pos = s.find(delimiter, pos))
diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp
index 883fe6612..40e335117 100644
--- a/toolsrc/src/vcpkg_System.cpp
+++ b/toolsrc/src/vcpkg_System.cpp
@@ -1,6 +1,7 @@
#include "pch.h"
#include "vcpkg_Checks.h"
+#include "vcpkg_GlobalState.h"
#include "vcpkg_System.h"
#include "vcpkglib.h"
@@ -18,7 +19,7 @@ namespace vcpkg::System
fs::path get_exe_path_of_current_process()
{
wchar_t buf[_MAX_PATH];
- int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH);
+ const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH);
if (bytes == 0) std::abort();
return fs::path(buf, buf + bytes);
}
@@ -36,18 +37,32 @@ namespace vcpkg::System
CPUArchitecture get_host_processor()
{
auto w6432 = get_environment_variable(L"PROCESSOR_ARCHITEW6432");
- if (auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO);
+ if (const auto p = w6432.get()) return to_cpu_architecture(Strings::to_utf8(*p)).value_or_exit(VCPKG_LINE_INFO);
- auto procarch = get_environment_variable(L"PROCESSOR_ARCHITECTURE").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);
}
+ std::vector<CPUArchitecture> get_supported_host_architectures()
+ {
+ std::vector<CPUArchitecture> supported_architectures;
+ supported_architectures.push_back(get_host_processor());
+
+ // AMD64 machines support to run x86 applications
+ if (supported_architectures.back() == CPUArchitecture::X64)
+ {
+ supported_architectures.push_back(CPUArchitecture::X86);
+ }
+
+ return supported_architectures;
+ }
+
int cmd_execute_clean(const CWStringView 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);
+ 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);
std::vector<std::wstring> env_wstrings = {
L"ALLUSERSPROFILE",
@@ -94,47 +109,84 @@ namespace vcpkg::System
};
// Flush stdout before launching external process
- fflush(nullptr);
+ fflush(nullptr);
- std::vector<const wchar_t*> env_cstr;
- env_cstr.reserve(env_wstrings.size() + 2);
+ std::wstring env_cstr;
for (auto&& env_wstring : env_wstrings)
{
const Optional<std::wstring> value = System::get_environment_variable(env_wstring);
- auto v = value.get();
+ const auto v = value.get();
if (!v || v->empty()) continue;
- env_wstring.push_back(L'=');
- env_wstring.append(*v);
- env_cstr.push_back(env_wstring.c_str());
+ env_cstr.append(env_wstring);
+ env_cstr.push_back(L'=');
+ env_cstr.append(*v);
+ env_cstr.push_back(L'\0');
}
- env_cstr.push_back(new_PATH.c_str());
- env_cstr.push_back(nullptr);
+ env_cstr.append(NEW_PATH);
+ env_cstr.push_back(L'\0');
+
+ STARTUPINFOW startup_info;
+ memset(&startup_info, 0, sizeof(STARTUPINFOW));
+ startup_info.cb = sizeof(STARTUPINFOW);
+
+ PROCESS_INFORMATION process_info;
+ memset(&process_info, 0, sizeof(PROCESS_INFORMATION));
// Basically we are wrapping it in quotes
- const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line);
- Debug::println("_wspawnlpe(cmd.exe /c %s)", Strings::to_utf8(actual_cmd_line));
- auto exit_code =
- _wspawnlpe(_P_WAIT, L"cmd.exe", L"cmd.exe", L"/c", actual_cmd_line.c_str(), nullptr, env_cstr.data());
- Debug::println("_wspawnlpe() returned %d", exit_code);
+ std::wstring actual_cmd_line = Strings::wformat(LR"###(cmd.exe /c "%s")###", cmd_line);
+ Debug::println("CreateProcessW(%s)", Strings::to_utf8(actual_cmd_line));
+ bool succeeded = TRUE == CreateProcessW(nullptr,
+ actual_cmd_line.data(),
+ nullptr,
+ nullptr,
+ FALSE,
+ BELOW_NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT,
+ env_cstr.data(),
+ nullptr,
+ &startup_info,
+ &process_info);
+
+ Checks::check_exit(VCPKG_LINE_INFO, succeeded, "Process creation failed with error code: %lu", GetLastError());
+
+ CloseHandle(process_info.hThread);
+
+ const DWORD result = WaitForSingleObject(process_info.hProcess, INFINITE);
+ Checks::check_exit(VCPKG_LINE_INFO, result != WAIT_FAILED, "WaitForSingleObject failed");
+
+ DWORD exit_code = 0;
+ GetExitCodeProcess(process_info.hProcess, &exit_code);
+
+ Debug::println("CreateProcessW() returned %lu", exit_code);
return static_cast<int>(exit_code);
}
int cmd_execute(const CWStringView cmd_line)
{
// Flush stdout before launching external process
- fflush(nullptr);
+ 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));
- int exit_code = _wsystem(actual_cmd_line.c_str());
+ const int exit_code = _wsystem(actual_cmd_line.c_str());
Debug::println("_wsystem() returned %d", exit_code);
return exit_code;
}
+ // On Win7, output from powershell calls contain a byte order mark, so we strip it out if it is present
+ static void remove_byte_order_mark(std::wstring* s)
+ {
+ const wchar_t* a = s->c_str();
+ // This is the UTF-8 byte-order mark
+ if (a[0] == 0xEF && a[1] == 0xBB && a[2] == 0xBF)
+ {
+ s->erase(0, 3);
+ }
+ }
+
ExitCodeAndOutput cmd_execute_and_capture_output(const CWStringView cmd_line)
{
// Flush stdout before launching external process
@@ -143,24 +195,26 @@ namespace vcpkg::System
const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s 2>&1")###", cmd_line);
Debug::println("_wpopen(%s)", Strings::to_utf8(actual_cmd_line));
- std::string output;
- char buf[1024];
- auto pipe = _wpopen(actual_cmd_line.c_str(), L"r");
+ std::wstring output;
+ wchar_t buf[1024];
+ const auto pipe = _wpopen(actual_cmd_line.c_str(), L"r");
if (pipe == nullptr)
{
- return {1, output};
+ return {1, Strings::to_utf8(output)};
}
- while (fgets(buf, 1024, pipe))
+ while (fgetws(buf, 1024, pipe))
{
output.append(buf);
}
if (!feof(pipe))
{
- return {1, output};
+ return {1, Strings::to_utf8(output)};
}
- auto ec = _pclose(pipe);
- Debug::println("_wpopen() returned %d", ec);
- return {ec, output};
+
+ const auto ec = _pclose(pipe);
+ Debug::println("_pclose() returned %d", ec);
+ remove_byte_order_mark(&output);
+ return {ec, Strings::to_utf8(output)};
}
std::wstring create_powershell_script_cmd(const fs::path& script_path, const CWStringView args)
@@ -170,6 +224,8 @@ namespace vcpkg::System
LR"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.native(), args);
}
+ void println() { println(Strings::EMPTY); }
+
void print(const CStringView message) { fputs(message, stdout); }
void println(const CStringView message)
@@ -180,15 +236,15 @@ namespace vcpkg::System
void print(const Color c, const CStringView message)
{
- HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
+ const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo{};
- GetConsoleScreenBufferInfo(hConsole, &consoleScreenBufferInfo);
- auto original_color = consoleScreenBufferInfo.wAttributes;
+ CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info{};
+ GetConsoleScreenBufferInfo(console_handle, &console_screen_buffer_info);
+ const auto original_color = console_screen_buffer_info.wAttributes;
- SetConsoleTextAttribute(hConsole, static_cast<WORD>(c) | (original_color & 0xF0));
+ SetConsoleTextAttribute(console_handle, static_cast<WORD>(c) | (original_color & 0xF0));
print(message);
- SetConsoleTextAttribute(hConsole, original_color);
+ SetConsoleTextAttribute(console_handle, original_color);
}
void println(const Color c, const CStringView message)
@@ -199,13 +255,13 @@ namespace vcpkg::System
Optional<std::wstring> get_environment_variable(const CWStringView varname) noexcept
{
- auto sz = GetEnvironmentVariableW(varname, nullptr, 0);
+ const auto sz = GetEnvironmentVariableW(varname, nullptr, 0);
if (sz == 0) return nullopt;
std::wstring ret(sz, L'\0');
Checks::check_exit(VCPKG_LINE_INFO, MAXDWORD >= ret.size());
- auto sz2 = GetEnvironmentVariableW(varname, ret.data(), static_cast<DWORD>(ret.size()));
+ const auto sz2 = GetEnvironmentVariableW(varname, ret.data(), static_cast<DWORD>(ret.size()));
Checks::check_exit(VCPKG_LINE_INFO, sz2 + 1 == sz);
ret.pop_back();
return ret;
@@ -216,59 +272,59 @@ namespace vcpkg::System
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 subKey, const CWStringView valuename)
+ Optional<std::wstring> get_registry_string(HKEY base, const CWStringView sub_key, const CWStringView valuename)
{
HKEY k = nullptr;
- LSTATUS ec = RegOpenKeyExW(base, subKey, NULL, KEY_READ, &k);
+ const LSTATUS ec = RegOpenKeyExW(base, sub_key, NULL, KEY_READ, &k);
if (ec != ERROR_SUCCESS) return nullopt;
- DWORD dwBufferSize = 0;
- DWORD dwType = 0;
- auto rc = RegQueryValueExW(k, valuename, nullptr, &dwType, nullptr, &dwBufferSize);
- if (rc != ERROR_SUCCESS || !is_string_keytype(dwType) || dwBufferSize == 0 ||
- dwBufferSize % sizeof(wchar_t) != 0)
+ DWORD dw_buffer_size = 0;
+ DWORD dw_type = 0;
+ auto rc = RegQueryValueExW(k, valuename, 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(dwBufferSize / sizeof(wchar_t));
+ ret.resize(dw_buffer_size / sizeof(wchar_t));
- rc = RegQueryValueExW(k, valuename, nullptr, &dwType, reinterpret_cast<LPBYTE>(ret.data()), &dwBufferSize);
- if (rc != ERROR_SUCCESS || !is_string_keytype(dwType) || dwBufferSize != sizeof(wchar_t) * ret.size())
+ rc = RegQueryValueExW(k, valuename, 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;
}
- static const fs::path& get_ProgramFiles()
+ static const fs::path& get_program_files()
{
- static const fs::path p = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO);
- return p;
+ static const fs::path PATH = System::get_environment_variable(L"PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO);
+ return PATH;
}
- const fs::path& get_ProgramFiles_32_bit()
+ const fs::path& get_program_files_32_bit()
{
- static const fs::path p = []() -> fs::path {
+ static const fs::path PATH = []() -> fs::path {
auto value = System::get_environment_variable(L"ProgramFiles(x86)");
if (auto v = value.get())
{
return std::move(*v);
}
- return get_ProgramFiles();
+ return get_program_files();
}();
- return p;
+ return PATH;
}
- const fs::path& get_ProgramFiles_platform_bitness()
+ const fs::path& get_program_files_platform_bitness()
{
- static const fs::path p = []() -> fs::path {
+ static const fs::path PATH = []() -> fs::path {
auto value = System::get_environment_variable(L"ProgramW6432");
if (auto v = value.get())
{
return std::move(*v);
}
- return get_ProgramFiles();
+ return get_program_files();
}();
- return p;
+ return PATH;
}
}
@@ -276,7 +332,7 @@ namespace vcpkg::Debug
{
void println(const CStringView message)
{
- if (g_debugging)
+ if (GlobalState::debugging)
{
System::println("[DEBUG] %s", message);
}
@@ -284,7 +340,7 @@ namespace vcpkg::Debug
void println(const System::Color c, const CStringView message)
{
- if (g_debugging)
+ if (GlobalState::debugging)
{
System::println(c, "[DEBUG] %s", message);
}
diff --git a/toolsrc/src/vcpkg_metrics_uploader.cpp b/toolsrc/src/vcpkg_metrics_uploader.cpp
index 38bf7ff9c..cef4f4756 100644
--- a/toolsrc/src/vcpkg_metrics_uploader.cpp
+++ b/toolsrc/src/vcpkg_metrics_uploader.cpp
@@ -11,5 +11,8 @@ int WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int)
LPWSTR* szArgList = CommandLineToArgvW(GetCommandLineW(), &argCount);
Checks::check_exit(VCPKG_LINE_INFO, argCount == 2, "Requires exactly one argument, the path to the payload file");
- Metrics::upload(Files::get_real_filesystem().read_contents(szArgList[1]).value_or_exit(VCPKG_LINE_INFO));
+ auto v = Files::get_real_filesystem().read_contents(szArgList[1]).value_or_exit(VCPKG_LINE_INFO);
+ Metrics::g_metrics.lock()->upload(v);
+ LocalFree(szArgList);
+ return 0;
}
diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp
index 6b180b532..5cdafdbc8 100644
--- a/toolsrc/src/vcpkglib.cpp
+++ b/toolsrc/src/vcpkglib.cpp
@@ -9,8 +9,6 @@
namespace vcpkg
{
- bool g_debugging = false;
-
static StatusParagraphs load_current_database(Files::Filesystem& fs,
const fs::path& vcpkg_dir_status_file,
const fs::path& vcpkg_dir_status_file_old)
@@ -41,7 +39,7 @@ namespace vcpkg
{
auto& fs = paths.get_filesystem();
- auto updates_dir = paths.vcpkg_dir_updates;
+ const auto updates_dir = paths.vcpkg_dir_updates;
std::error_code ec;
fs.create_directory(paths.installed, ec);
@@ -92,9 +90,9 @@ namespace vcpkg
static int update_id = 0;
auto& fs = paths.get_filesystem();
- auto my_update_id = update_id++;
- auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete";
- auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id);
+ const auto my_update_id = update_id++;
+ const auto tmp_update_filename = paths.vcpkg_dir_updates / "incomplete";
+ const auto update_filename = paths.vcpkg_dir_updates / std::to_string(my_update_id);
fs.write_contents(tmp_update_filename, Strings::serialize(p));
fs.rename(tmp_update_filename, update_filename);
@@ -119,7 +117,7 @@ namespace vcpkg
if (!was_tracked)
{
was_tracked = true;
- Metrics::track_property("listfile", "update to new format");
+ Metrics::g_metrics.lock()->track_property("listfile", "update to new format");
}
// The files are sorted such that directories are placed just before the files they contain
@@ -191,7 +189,7 @@ namespace vcpkg
for (const std::unique_ptr<StatusParagraph>& pgh : status_db)
{
- if (pgh->state != InstallState::INSTALLED)
+ if (pgh->state != InstallState::INSTALLED || !pgh->package.feature.empty())
{
continue;
}
@@ -235,14 +233,15 @@ namespace vcpkg
const fs::path& cmake_script,
const std::vector<CMakeVariable>& pass_variables)
{
- std::wstring cmd_cmake_pass_variables = Strings::join(L" ", pass_variables, [](auto&& v) { return v.s; });
+ 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());
}
- std::string shorten_description(const std::string& desc)
+ std::string shorten_text(const std::string& desc, size_t length)
{
+ Checks::check_exit(VCPKG_LINE_INFO, length >= 3);
auto simple_desc = std::regex_replace(desc, std::regex("\\s+"), " ");
- return simple_desc.size() <= 52 ? simple_desc : simple_desc.substr(0, 49) + "...";
+ return simple_desc.size() <= length ? simple_desc : simple_desc.substr(0, length - 3) + "...";
}
}