aboutsummaryrefslogtreecommitdiff
path: root/toolsrc
diff options
context:
space:
mode:
authorJan Hrubý <jhruby.web@gmail.com>2017-03-13 08:56:05 +0100
committerGitHub <noreply@github.com>2017-03-13 08:56:05 +0100
commit665f4118f603c5858217ed7a2f2f824b18ff4fc5 (patch)
treef0167041edf71e90f2331b5025f603392a8de67a /toolsrc
parent1bec0fcb73073b5b1719f454c368a63f1bff625e (diff)
parent1c9873a0daf625f67474aaf3e163c592c27ecb65 (diff)
downloadvcpkg-665f4118f603c5858217ed7a2f2f824b18ff4fc5.tar.gz
vcpkg-665f4118f603c5858217ed7a2f2f824b18ff4fc5.zip
Merge pull request #1 from Microsoft/master
pull
Diffstat (limited to 'toolsrc')
-rw-r--r--toolsrc/VERSION.txt2
-rw-r--r--toolsrc/dirs.proj20
-rw-r--r--toolsrc/include/BinaryParagraph.h7
-rw-r--r--toolsrc/include/ImmutableSortedVector.h48
-rw-r--r--toolsrc/include/MachineType.h36
-rw-r--r--toolsrc/include/Paragraphs.h21
-rw-r--r--toolsrc/include/PostBuildLint.h8
-rw-r--r--toolsrc/include/PostBuildLint_BuildInfo.h21
-rw-r--r--toolsrc/include/PostBuildLint_BuildPolicies.h38
-rw-r--r--toolsrc/include/PostBuildLint_BuildType.h47
-rw-r--r--toolsrc/include/PostBuildLint_ConfigurationType.h33
-rw-r--r--toolsrc/include/PostBuildLint_LinkageType.h34
-rw-r--r--toolsrc/include/SourceParagraph.h19
-rw-r--r--toolsrc/include/StatusParagraphs.h15
-rw-r--r--toolsrc/include/coff_file_reader.h21
-rw-r--r--toolsrc/include/expected.h1
-rw-r--r--toolsrc/include/filesystem_fs.h5
-rw-r--r--toolsrc/include/lazy.h26
-rw-r--r--toolsrc/include/metrics.h1
-rw-r--r--toolsrc/include/opt_bool.h32
-rw-r--r--toolsrc/include/package_spec.h24
-rw-r--r--toolsrc/include/package_spec_parse_result.h8
-rw-r--r--toolsrc/include/pch.h43
-rw-r--r--toolsrc/include/post_build_lint.h8
-rw-r--r--toolsrc/include/triplet.h11
-rw-r--r--toolsrc/include/vcpkg.h33
-rw-r--r--toolsrc/include/vcpkg_Checks.h8
-rw-r--r--toolsrc/include/vcpkg_Chrono.h31
-rw-r--r--toolsrc/include/vcpkg_Commands.h149
-rw-r--r--toolsrc/include/vcpkg_Dependencies.h76
-rw-r--r--toolsrc/include/vcpkg_Enums.h11
-rw-r--r--toolsrc/include/vcpkg_Environment.h22
-rw-r--r--toolsrc/include/vcpkg_Files.h53
-rw-r--r--toolsrc/include/vcpkg_Graphs.h13
-rw-r--r--toolsrc/include/vcpkg_Input.h15
-rw-r--r--toolsrc/include/vcpkg_Maps.h27
-rw-r--r--toolsrc/include/vcpkg_Sets.h6
-rw-r--r--toolsrc/include/vcpkg_Strings.h92
-rw-r--r--toolsrc/include/vcpkg_System.h63
-rw-r--r--toolsrc/include/vcpkg_cmd_arguments.h18
-rw-r--r--toolsrc/include/vcpkg_optional.h5
-rw-r--r--toolsrc/include/vcpkg_paths.h50
-rw-r--r--toolsrc/include/vcpkglib.h34
-rw-r--r--toolsrc/include/vcpkglib_helpers.h12
-rw-r--r--toolsrc/src/BinaryParagraph.cpp66
-rw-r--r--toolsrc/src/MachineType.cpp42
-rw-r--r--toolsrc/src/Paragraphs.cpp227
-rw-r--r--toolsrc/src/PostBuildLint.cpp719
-rw-r--r--toolsrc/src/PostBuildLint_BuildInfo.cpp48
-rw-r--r--toolsrc/src/PostBuildLint_BuildPolicies.cpp70
-rw-r--r--toolsrc/src/PostBuildLint_BuildType.cpp85
-rw-r--r--toolsrc/src/PostBuildLint_ConfigurationType.cpp26
-rw-r--r--toolsrc/src/PostBuildLint_LinkageType.cpp41
-rw-r--r--toolsrc/src/SourceParagraph.cpp150
-rw-r--r--toolsrc/src/StatusParagraph.cpp10
-rw-r--r--toolsrc/src/StatusParagraphs.cpp31
-rw-r--r--toolsrc/src/coff_file_reader.cpp307
-rw-r--r--toolsrc/src/commands_available_commands.cpp46
-rw-r--r--toolsrc/src/commands_build.cpp183
-rw-r--r--toolsrc/src/commands_build_external.cpp20
-rw-r--r--toolsrc/src/commands_cache.cpp70
-rw-r--r--toolsrc/src/commands_ci.cpp120
-rw-r--r--toolsrc/src/commands_contact.cpp21
-rw-r--r--toolsrc/src/commands_create.cpp63
-rw-r--r--toolsrc/src/commands_edit.cpp70
-rw-r--r--toolsrc/src/commands_hash.cpp46
-rw-r--r--toolsrc/src/commands_help.cpp91
-rw-r--r--toolsrc/src/commands_helpers.cpp7
-rw-r--r--toolsrc/src/commands_import.cpp77
-rw-r--r--toolsrc/src/commands_install.cpp247
-rw-r--r--toolsrc/src/commands_installation.cpp164
-rw-r--r--toolsrc/src/commands_integrate.cpp (renamed from toolsrc/src/commands_integration.cpp)104
-rw-r--r--toolsrc/src/commands_list.cpp67
-rw-r--r--toolsrc/src/commands_other.cpp94
-rw-r--r--toolsrc/src/commands_owns.cpp31
-rw-r--r--toolsrc/src/commands_portsdiff.cpp138
-rw-r--r--toolsrc/src/commands_remove.cpp201
-rw-r--r--toolsrc/src/commands_search.cpp108
-rw-r--r--toolsrc/src/commands_update.cpp43
-rw-r--r--toolsrc/src/commands_version.cpp37
-rw-r--r--toolsrc/src/lib.cpp509
-rw-r--r--toolsrc/src/main.cpp251
-rw-r--r--toolsrc/src/metrics.cpp37
-rw-r--r--toolsrc/src/opt_bool.cpp29
-rw-r--r--toolsrc/src/package_spec.cpp60
-rw-r--r--toolsrc/src/package_spec_parse_result.cpp10
-rw-r--r--toolsrc/src/pch.cpp1
-rw-r--r--toolsrc/src/post_build_lint.cpp356
-rw-r--r--toolsrc/src/tests_dependencies.cpp39
-rw-r--r--toolsrc/src/tests_paragraph.cpp (renamed from toolsrc/src/test.cpp)98
-rw-r--r--toolsrc/src/triplet.cpp61
-rw-r--r--toolsrc/src/vcpkg.cpp346
-rw-r--r--toolsrc/src/vcpkg_Checks.cpp28
-rw-r--r--toolsrc/src/vcpkg_Chrono.cpp63
-rw-r--r--toolsrc/src/vcpkg_Dependencies.cpp159
-rw-r--r--toolsrc/src/vcpkg_Enums.cpp21
-rw-r--r--toolsrc/src/vcpkg_Environment.cpp220
-rw-r--r--toolsrc/src/vcpkg_Files.cpp101
-rw-r--r--toolsrc/src/vcpkg_Input.cpp53
-rw-r--r--toolsrc/src/vcpkg_Strings.cpp114
-rw-r--r--toolsrc/src/vcpkg_System.cpp181
-rw-r--r--toolsrc/src/vcpkg_cmd_arguments.cpp94
-rw-r--r--toolsrc/src/vcpkg_metrics_uploader.cpp12
-rw-r--r--toolsrc/src/vcpkg_paths.cpp196
-rw-r--r--toolsrc/src/vcpkg_version.cpp25
-rw-r--r--toolsrc/src/vcpkglib.cpp215
-rw-r--r--toolsrc/src/vcpkglib_helpers.cpp69
-rw-r--r--toolsrc/vcpkg.sln20
-rw-r--r--toolsrc/vcpkg/vcpkg.vcxproj47
-rw-r--r--toolsrc/vcpkg/vcpkg.vcxproj.filters70
-rw-r--r--toolsrc/vcpkgcommon/vcpkgcommon.vcxproj142
-rw-r--r--toolsrc/vcpkgcommon/vcpkgcommon.vcxproj.filters60
-rw-r--r--toolsrc/vcpkglib/vcpkglib.vcxproj116
-rw-r--r--toolsrc/vcpkglib/vcpkglib.vcxproj.filters237
-rw-r--r--toolsrc/vcpkgmetrics/vcpkgmetrics.vcxproj140
-rw-r--r--toolsrc/vcpkgmetrics/vcpkgmetrics.vcxproj.filters27
-rw-r--r--toolsrc/vcpkgmetricsuploader/vcpkgmetricsuploader.vcxproj20
-rw-r--r--toolsrc/vcpkgtest/vcpkgtest.vcxproj24
-rw-r--r--toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters5
119 files changed, 6409 insertions, 2964 deletions
diff --git a/toolsrc/VERSION.txt b/toolsrc/VERSION.txt
index f723d10e0..efe1fb7ee 100644
--- a/toolsrc/VERSION.txt
+++ b/toolsrc/VERSION.txt
@@ -1 +1 @@
-"0.0.30" \ No newline at end of file
+"0.0.76" \ No newline at end of file
diff --git a/toolsrc/dirs.proj b/toolsrc/dirs.proj
new file mode 100644
index 000000000..17d9fa1b0
--- /dev/null
+++ b/toolsrc/dirs.proj
@@ -0,0 +1,20 @@
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <SolutionDir>$(MSBuildThisFileDirectory)</SolutionDir>
+ </PropertyGroup>
+ <ItemGroup>
+ <ProjectFile Include="vcpkg\vcpkg.vcxproj"/>
+ <ProjectFile Include="vcpkglib\vcpkglib.vcxproj"/>
+ <ProjectFile Include="vcpkgmetricsuploader\vcpkgmetricsuploader.vcxproj"/>
+ </ItemGroup>
+
+ <Target Name="Rebuild" DependsOnTargets="Clean;Build" />
+
+ <Target Name="Build">
+ <MSBuild Projects="@(ProjectFile)" Properties="SolutionDir=$(SolutionDir)" Targets="Build"/>
+ </Target>
+
+ <Target Name="Clean">
+ <MSBuild Projects="@(ProjectFile)" Properties="SolutionDir=$(SolutionDir)" Targets="Clean"/>
+ </Target>
+</Project> \ No newline at end of file
diff --git a/toolsrc/include/BinaryParagraph.h b/toolsrc/include/BinaryParagraph.h
index 88d6e84b1..3d9cfb9fb 100644
--- a/toolsrc/include/BinaryParagraph.h
+++ b/toolsrc/include/BinaryParagraph.h
@@ -2,14 +2,14 @@
#include <unordered_map>
#include "SourceParagraph.h"
-#include "triplet.h"
+#include "package_spec.h"
namespace vcpkg
{
struct BinaryParagraph
{
BinaryParagraph();
- explicit BinaryParagraph(const std::unordered_map<std::string, std::string>& fields);
+ explicit BinaryParagraph(std::unordered_map<std::string, std::string> fields);
BinaryParagraph(const SourceParagraph& spgh, const triplet& target_triplet);
std::string displayname() const;
@@ -18,11 +18,10 @@ namespace vcpkg
std::string dir() const;
- std::string name;
+ package_spec spec;
std::string version;
std::string description;
std::string maintainer;
- triplet target_triplet;
std::vector<std::string> depends;
};
diff --git a/toolsrc/include/ImmutableSortedVector.h b/toolsrc/include/ImmutableSortedVector.h
new file mode 100644
index 000000000..681f9fd4d
--- /dev/null
+++ b/toolsrc/include/ImmutableSortedVector.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <vector>
+#include <algorithm>
+
+// Add more forwarding functions to the delegate std::vector as needed.
+namespace vcpkg
+{
+ template <class T>
+ class ImmutableSortedVector
+ {
+ public:
+ static ImmutableSortedVector<T> create(std::vector<T> vector)
+ {
+ ImmutableSortedVector out;
+ out.delegate = std::move(vector);
+ if (!std::is_sorted(out.delegate.cbegin(), out.delegate.cend()))
+ {
+ std::sort(out.delegate.begin(), out.delegate.end());
+ }
+
+ return out;
+ }
+
+ typename std::vector<T>::const_iterator begin() const
+ {
+ return this->delegate.cbegin();
+ }
+
+ typename std::vector<T>::const_iterator end() const
+ {
+ return this->delegate.cend();
+ }
+
+ typename std::vector<T>::const_iterator cbegin() const
+ {
+ return this->delegate.cbegin();
+ }
+
+ typename std::vector<T>::const_iterator cend() const
+ {
+ return this->delegate.cend();
+ }
+
+ private:
+ std::vector<T> delegate;
+ };
+}
diff --git a/toolsrc/include/MachineType.h b/toolsrc/include/MachineType.h
new file mode 100644
index 000000000..86efb85c5
--- /dev/null
+++ b/toolsrc/include/MachineType.h
@@ -0,0 +1,36 @@
+#pragma once
+#include <cstdint>
+
+namespace vcpkg
+{
+ enum class MachineType : uint16_t
+ {
+ UNKNOWN = 0x0, // The contents of this field are assumed to be applicable to any machine type
+ AM33=0x1d3,//Matsushita AM33
+ AMD64=0x8664,//x64
+ ARM=0x1c0,//ARM little endian
+ ARM64=0xaa64,//ARM64 little endian
+ ARMNT=0x1c4,//ARM Thumb-2 little endian
+ EBC=0xebc,//EFI byte code
+ I386=0x14c,//Intel 386 or later processors and compatible processors
+ IA64=0x200,//Intel Itanium processor family
+ M32R=0x9041,//Mitsubishi M32R little endian
+ MIPS16=0x266,//MIPS16
+ MIPSFPU=0x366,//MIPS with FPU
+ MIPSFPU16=0x466,//MIPS16 with FPU
+ POWERPC=0x1f0,//Power PC little endian
+ POWERPCFP=0x1f1,//Power PC with floating point support
+ R4000=0x166,//MIPS little endian
+ RISCV32=0x5032,//RISC-V 32-bit address space
+ RISCV64=0x5064,//RISC-V 64-bit address space
+ RISCV128=0x5128,//RISC-V 128-bit address space
+ SH3=0x1a2,//Hitachi SH3
+ SH3DSP=0x1a3,//Hitachi SH3 DSP
+ SH4=0x1a6,//Hitachi SH4
+ SH5=0x1a8,//Hitachi SH5
+ THUMB=0x1c2,//Thumb
+ WCEMIPSV2=0x169,//MIPS little-endian WCE v2
+ };
+
+ MachineType getMachineType(const uint16_t value);
+}
diff --git a/toolsrc/include/Paragraphs.h b/toolsrc/include/Paragraphs.h
new file mode 100644
index 000000000..79b66a67f
--- /dev/null
+++ b/toolsrc/include/Paragraphs.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "filesystem_fs.h"
+#include <map>
+#include "expected.h"
+#include "BinaryParagraph.h"
+#include "vcpkg_paths.h"
+
+namespace vcpkg::Paragraphs
+{
+ std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path);
+ std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str);
+
+ expected<SourceParagraph> try_load_port(const fs::path& control_path);
+
+ expected<BinaryParagraph> try_load_cached_package(const vcpkg_paths& paths, const package_spec& spec);
+
+ std::vector<SourceParagraph> load_all_ports(const fs::path& ports_dir);
+
+ std::map<std::string, std::string> extract_port_names_and_versions(const std::vector<SourceParagraph>& source_paragraphs);
+}
diff --git a/toolsrc/include/PostBuildLint.h b/toolsrc/include/PostBuildLint.h
new file mode 100644
index 000000000..73c8ec54b
--- /dev/null
+++ b/toolsrc/include/PostBuildLint.h
@@ -0,0 +1,8 @@
+#pragma once
+#include "package_spec.h"
+#include "vcpkg_paths.h"
+
+namespace vcpkg::PostBuildLint
+{
+ size_t perform_all_checks(const package_spec& spec, const vcpkg_paths& paths);
+}
diff --git a/toolsrc/include/PostBuildLint_BuildInfo.h b/toolsrc/include/PostBuildLint_BuildInfo.h
new file mode 100644
index 000000000..bac024e01
--- /dev/null
+++ b/toolsrc/include/PostBuildLint_BuildInfo.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include "filesystem_fs.h"
+#include "PostBuildLint_BuildPolicies.h"
+#include "opt_bool.h"
+#include "PostBuildLint_LinkageType.h"
+
+namespace vcpkg::PostBuildLint
+{
+ struct BuildInfo
+ {
+ static BuildInfo create(std::unordered_map<std::string, std::string> pgh);
+
+ LinkageType::type crt_linkage;
+ LinkageType::type library_linkage;
+
+ std::map<BuildPolicies::type, opt_bool_t> policies;
+ };
+
+ BuildInfo read_build_info(const fs::path& filepath);
+}
diff --git a/toolsrc/include/PostBuildLint_BuildPolicies.h b/toolsrc/include/PostBuildLint_BuildPolicies.h
new file mode 100644
index 000000000..d815c6d27
--- /dev/null
+++ b/toolsrc/include/PostBuildLint_BuildPolicies.h
@@ -0,0 +1,38 @@
+#pragma once
+#include <string>
+#include <array>
+
+namespace vcpkg::PostBuildLint::BuildPolicies
+{
+ enum class backing_enum_t
+ {
+ NULLVALUE = 0,
+ EMPTY_PACKAGE,
+ DLLS_WITHOUT_LIBS,
+ ONLY_RELEASE_CRT
+ };
+
+ struct type
+ {
+ constexpr type() : backing_enum(backing_enum_t::NULLVALUE) {}
+ constexpr explicit type(backing_enum_t backing_enum) : backing_enum(backing_enum) { }
+ constexpr operator backing_enum_t() const { return backing_enum; }
+
+ const std::string& toString() const;
+ const std::string& cmake_variable() const;
+
+ private:
+ backing_enum_t backing_enum;
+ };
+
+ static const std::string ENUM_NAME = "vcpkg::PostBuildLint::BuildPolicies";
+
+ static constexpr type NULLVALUE(backing_enum_t::NULLVALUE);
+ static constexpr type EMPTY_PACKAGE(backing_enum_t::EMPTY_PACKAGE);
+ static constexpr type DLLS_WITHOUT_LIBS(backing_enum_t::DLLS_WITHOUT_LIBS);
+ static constexpr type ONLY_RELEASE_CRT(backing_enum_t::ONLY_RELEASE_CRT);
+
+ static constexpr std::array<type, 3> values = { EMPTY_PACKAGE, DLLS_WITHOUT_LIBS, ONLY_RELEASE_CRT };
+
+ type parse(const std::string& s);
+}
diff --git a/toolsrc/include/PostBuildLint_BuildType.h b/toolsrc/include/PostBuildLint_BuildType.h
new file mode 100644
index 000000000..31fbb11c9
--- /dev/null
+++ b/toolsrc/include/PostBuildLint_BuildType.h
@@ -0,0 +1,47 @@
+#pragma once
+#include "PostBuildLint_ConfigurationType.h"
+#include "PostBuildLint_LinkageType.h"
+#include <array>
+#include <regex>
+
+namespace vcpkg::PostBuildLint::BuildType
+{
+ enum class backing_enum_t
+ {
+ DEBUG_STATIC = 1,
+ DEBUG_DYNAMIC,
+ RELEASE_STATIC,
+ RELEASE_DYNAMIC
+ };
+
+ struct type
+ {
+ type() = delete;
+
+ constexpr explicit type(const backing_enum_t backing_enum, const ConfigurationType::type config, const LinkageType::type linkage) :
+ backing_enum(backing_enum), m_config(config), m_linkage(linkage) { }
+
+ constexpr operator backing_enum_t() const { return backing_enum; }
+
+ const ConfigurationType::type& config() const;
+ const LinkageType::type& linkage() const;
+ const std::regex& crt_regex() const;
+ const std::string& toString() const;
+
+ private:
+ backing_enum_t backing_enum;
+ ConfigurationType::type m_config;
+ LinkageType::type m_linkage;
+ };
+
+ static const std::string ENUM_NAME = "vcpkg::PostBuildLint::BuildType";
+
+ static constexpr type DEBUG_STATIC = type(backing_enum_t::DEBUG_STATIC, ConfigurationType::DEBUG, LinkageType::STATIC);
+ static constexpr type DEBUG_DYNAMIC = type(backing_enum_t::DEBUG_DYNAMIC, ConfigurationType::DEBUG, LinkageType::DYNAMIC);
+ static constexpr type RELEASE_STATIC = type(backing_enum_t::RELEASE_STATIC, ConfigurationType::RELEASE, LinkageType::STATIC);
+ static constexpr type RELEASE_DYNAMIC = type(backing_enum_t::RELEASE_DYNAMIC, ConfigurationType::RELEASE, LinkageType::DYNAMIC);
+
+ static constexpr std::array<type, 4> values = { DEBUG_STATIC, DEBUG_DYNAMIC, RELEASE_STATIC, RELEASE_DYNAMIC };
+
+ type value_of(const ConfigurationType::type& config, const LinkageType::type& linkage);
+}
diff --git a/toolsrc/include/PostBuildLint_ConfigurationType.h b/toolsrc/include/PostBuildLint_ConfigurationType.h
new file mode 100644
index 000000000..7245d2932
--- /dev/null
+++ b/toolsrc/include/PostBuildLint_ConfigurationType.h
@@ -0,0 +1,33 @@
+#pragma once
+#pragma once
+#include <string>
+
+namespace vcpkg::PostBuildLint::ConfigurationType
+{
+ enum class backing_enum_t
+ {
+ NULLVALUE = 0,
+ DEBUG = 1,
+ RELEASE = 2
+ };
+
+ struct type
+ {
+ constexpr type() : backing_enum(backing_enum_t::NULLVALUE) {}
+ constexpr explicit type(backing_enum_t backing_enum) : backing_enum(backing_enum) { }
+ constexpr operator backing_enum_t() const { return backing_enum; }
+
+ const std::string& toString() const;
+
+ private:
+ backing_enum_t backing_enum;
+ };
+
+ static const std::string ENUM_NAME = "vcpkg::PostBuildLint::ConfigurationType";
+
+ static constexpr type NULLVALUE(backing_enum_t::NULLVALUE);
+ static constexpr type DEBUG(backing_enum_t::DEBUG);
+ static constexpr type RELEASE(backing_enum_t::RELEASE);
+
+ static constexpr std::array<type, 2> values = { DEBUG, RELEASE };
+}
diff --git a/toolsrc/include/PostBuildLint_LinkageType.h b/toolsrc/include/PostBuildLint_LinkageType.h
new file mode 100644
index 000000000..0cecc8c9f
--- /dev/null
+++ b/toolsrc/include/PostBuildLint_LinkageType.h
@@ -0,0 +1,34 @@
+#pragma once
+#include <string>
+
+namespace vcpkg::PostBuildLint::LinkageType
+{
+ enum class backing_enum_t
+ {
+ NULLVALUE = 0,
+ DYNAMIC,
+ STATIC
+ };
+
+ struct type
+ {
+ constexpr type() : backing_enum(backing_enum_t::NULLVALUE) {}
+ constexpr explicit type(backing_enum_t backing_enum) : backing_enum(backing_enum) { }
+ constexpr operator backing_enum_t() const { return backing_enum; }
+
+ const std::string& toString() const;
+
+ private:
+ backing_enum_t backing_enum;
+ };
+
+ static const std::string ENUM_NAME = "vcpkg::PostBuildLint::LinkageType";
+
+ static constexpr type NULLVALUE(backing_enum_t::NULLVALUE);
+ static constexpr type DYNAMIC(backing_enum_t::DYNAMIC);
+ static constexpr type STATIC(backing_enum_t::STATIC);
+
+ static constexpr std::array<type, 2> values = { DYNAMIC, STATIC };
+
+ type value_of(const std::string& as_string);
+}
diff --git a/toolsrc/include/SourceParagraph.h b/toolsrc/include/SourceParagraph.h
index 72dca8324..5ae9b38b8 100644
--- a/toolsrc/include/SourceParagraph.h
+++ b/toolsrc/include/SourceParagraph.h
@@ -5,16 +5,31 @@
namespace vcpkg
{
+ struct triplet;
+
+ struct dependency
+ {
+ std::string name;
+ std::string qualifier;
+ };
+
+ std::ostream& operator<<(std::ostream& os, const dependency& p);
+
struct SourceParagraph
{
SourceParagraph();
- explicit SourceParagraph(const std::unordered_map<std::string, std::string>& fields);
+ explicit SourceParagraph(std::unordered_map<std::string, std::string> fields);
std::string name;
std::string version;
std::string description;
std::string maintainer;
- std::vector<std::string> depends;
+ std::vector<dependency> depends;
};
+
+ std::vector<std::string> filter_dependencies(const std::vector<vcpkg::dependency>& deps, const triplet& t);
+
+ std::vector<vcpkg::dependency> expand_qualified_dependencies(const std::vector<std::string>& depends);
+ std::vector<std::string> parse_depends(const std::string& depends_string);
}
diff --git a/toolsrc/include/StatusParagraphs.h b/toolsrc/include/StatusParagraphs.h
index 9446d432c..3c5d35183 100644
--- a/toolsrc/include/StatusParagraphs.h
+++ b/toolsrc/include/StatusParagraphs.h
@@ -1,6 +1,7 @@
#pragma once
#include "StatusParagraph.h"
#include <memory>
+#include <iterator>
namespace vcpkg
{
@@ -13,30 +14,34 @@ namespace vcpkg
using iterator = container::reverse_iterator;
using const_iterator = container::const_reverse_iterator;
+ const_iterator find(const package_spec& spec) const
+ {
+ return find(spec.name(), spec.target_triplet());
+ }
const_iterator find(const std::string& name, const triplet& target_triplet) const;
iterator find(const std::string& name, const triplet& target_triplet);
- iterator find_installed(const std::string& name, const triplet& target_triplet);
+ const_iterator find_installed(const std::string& name, const triplet& target_triplet) const;
iterator insert(std::unique_ptr<StatusParagraph>);
friend std::ostream& operator<<(std::ostream&, const StatusParagraphs&);
- auto end()
+ iterator end()
{
return paragraphs.rend();
}
- auto end() const
+ const_iterator end() const
{
return paragraphs.rend();
}
- auto begin()
+ iterator begin()
{
return paragraphs.rbegin();
}
- auto begin() const
+ const_iterator begin() const
{
return paragraphs.rbegin();
}
diff --git a/toolsrc/include/coff_file_reader.h b/toolsrc/include/coff_file_reader.h
new file mode 100644
index 000000000..24fbf4576
--- /dev/null
+++ b/toolsrc/include/coff_file_reader.h
@@ -0,0 +1,21 @@
+#pragma once
+#include <vector>
+#include "MachineType.h"
+#include "filesystem_fs.h"
+
+namespace vcpkg::COFFFileReader
+{
+ struct dll_info
+ {
+ MachineType machine_type;
+ };
+
+ struct lib_info
+ {
+ std::vector<MachineType> machine_types;
+ };
+
+ dll_info read_dll(const fs::path& path);
+
+ lib_info read_lib(const fs::path& path);
+}
diff --git a/toolsrc/include/expected.h b/toolsrc/include/expected.h
index affabcc02..cbb513b22 100644
--- a/toolsrc/include/expected.h
+++ b/toolsrc/include/expected.h
@@ -1,5 +1,6 @@
#pragma once
+#include <system_error>
#include "vcpkg_Checks.h"
namespace vcpkg
diff --git a/toolsrc/include/filesystem_fs.h b/toolsrc/include/filesystem_fs.h
new file mode 100644
index 000000000..ece485c23
--- /dev/null
+++ b/toolsrc/include/filesystem_fs.h
@@ -0,0 +1,5 @@
+#pragma once
+
+#include <filesystem>
+
+namespace fs = std::tr2::sys; \ No newline at end of file
diff --git a/toolsrc/include/lazy.h b/toolsrc/include/lazy.h
new file mode 100644
index 000000000..f9dbd8dc7
--- /dev/null
+++ b/toolsrc/include/lazy.h
@@ -0,0 +1,26 @@
+#pragma once
+
+namespace vcpkg
+{
+ template <typename T>
+ class lazy
+ {
+ public:
+ lazy() : value(T()), initialized(false) {}
+
+ template <class F>
+ T const& get_lazy(F& f) const
+ {
+ if (!initialized)
+ {
+ value = f();
+ initialized = true;
+ }
+ return value;
+ }
+
+ private:
+ mutable T value;
+ mutable bool initialized;
+ };
+}
diff --git a/toolsrc/include/metrics.h b/toolsrc/include/metrics.h
index 52662cd97..a0f4fc61d 100644
--- a/toolsrc/include/metrics.h
+++ b/toolsrc/include/metrics.h
@@ -13,6 +13,7 @@ namespace vcpkg
void TrackProperty(const std::string& name, const std::string& value);
void TrackProperty(const std::string& name, const std::wstring& value);
bool GetCompiledMetricsEnabled();
+ std::wstring GetSQMUser();
void Upload(const std::string& payload);
void Flush();
diff --git a/toolsrc/include/opt_bool.h b/toolsrc/include/opt_bool.h
index 3856366c8..06642a399 100644
--- a/toolsrc/include/opt_bool.h
+++ b/toolsrc/include/opt_bool.h
@@ -1,11 +1,33 @@
#pragma once
-namespace vcpkg
+#include <string>
+#include <map>
+
+namespace vcpkg::opt_bool
{
- enum class opt_bool
+ enum class type
{
- unspecified,
- enabled,
- disabled
+ UNSPECIFIED = 0,
+ ENABLED,
+ DISABLED
};
+
+ type parse(const std::string& s);
+
+ template <class T>
+ type from_map(const std::map<T, std::string>& map, const T& key)
+ {
+ auto it = map.find(key);
+ if (it == map.cend())
+ {
+ return type::UNSPECIFIED;
+ }
+
+ return parse(*it);
+ }
}
+
+namespace vcpkg
+{
+ using opt_bool_t = opt_bool::type;
+} \ No newline at end of file
diff --git a/toolsrc/include/package_spec.h b/toolsrc/include/package_spec.h
index 942b34adc..1bc493756 100644
--- a/toolsrc/include/package_spec.h
+++ b/toolsrc/include/package_spec.h
@@ -1,5 +1,4 @@
#pragma once
-#include <string>
#include "package_spec_parse_result.h"
#include "triplet.h"
#include "expected.h"
@@ -8,15 +7,24 @@ namespace vcpkg
{
struct package_spec
{
- static expected<package_spec> from_string(const std::string& spec, const triplet& default_target_triplet);
+ static expected<package_spec> from_string(const std::string& spec_as_string, const triplet& default_target_triplet);
- std::string name;
- triplet target_triplet;
+ static expected<package_spec> from_name_and_triplet(const std::string& name, const triplet& target_triplet);
+
+ const std::string& name() const;
+
+ const triplet& target_triplet() const;
+
+ std::string display_name() const;
std::string dir() const;
- };
- std::string to_string(const package_spec& spec);
+ std::string toString() const;
+
+ private:
+ std::string m_name;
+ triplet m_target_triplet;
+ };
std::string to_printf_arg(const package_spec& spec);
@@ -33,8 +41,8 @@ namespace std
size_t operator()(const vcpkg::package_spec& value) const
{
size_t hash = 17;
- hash = hash * 31 + std::hash<std::string>()(value.name);
- hash = hash * 31 + std::hash<vcpkg::triplet>()(value.target_triplet);
+ hash = hash * 31 + std::hash<std::string>()(value.name());
+ hash = hash * 31 + std::hash<vcpkg::triplet>()(value.target_triplet());
return hash;
}
};
diff --git a/toolsrc/include/package_spec_parse_result.h b/toolsrc/include/package_spec_parse_result.h
index e59622951..5735c4f4c 100644
--- a/toolsrc/include/package_spec_parse_result.h
+++ b/toolsrc/include/package_spec_parse_result.h
@@ -5,8 +5,9 @@ namespace vcpkg
{
enum class package_spec_parse_result
{
- success = 0,
- too_many_colons
+ SUCCESS = 0,
+ TOO_MANY_COLONS,
+ INVALID_CHARACTERS
};
struct package_spec_parse_result_category_impl final : std::error_category
@@ -30,5 +31,6 @@ namespace std
{
template <>
struct is_error_code_enum<vcpkg::package_spec_parse_result> : ::std::true_type
- {};
+ {
+ };
}
diff --git a/toolsrc/include/pch.h b/toolsrc/include/pch.h
new file mode 100644
index 000000000..e78f17237
--- /dev/null
+++ b/toolsrc/include/pch.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include <Windows.h>
+#include <shellapi.h>
+#include <Shlobj.h>
+#include <winhttp.h>
+#include <process.h>
+
+#include <cassert>
+#include <stdexcept>
+#include <system_error>
+
+#include <array>
+#include <vector>
+#include <set>
+#include <map>
+#include <unordered_set>
+#include <unordered_map>
+
+#include <string>
+#include <regex>
+
+#include <filesystem>
+#include <iostream>
+#include <fstream>
+#include <memory>
+#include <iomanip>
+
+#include <algorithm>
+#include <functional>
+#include <iterator>
+#include <utility>
+
+#include <cstdarg>
+#include <codecvt>
+#include <cctype>
+#include <cstdint>
+
+#include <sys/timeb.h>
+#include <time.h>
+#include <chrono>
diff --git a/toolsrc/include/post_build_lint.h b/toolsrc/include/post_build_lint.h
deleted file mode 100644
index bc916a7af..000000000
--- a/toolsrc/include/post_build_lint.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#pragma once
-#include "package_spec.h"
-#include "vcpkg_paths.h"
-
-namespace vcpkg
-{
- void perform_all_checks(const package_spec& spec, const vcpkg_paths& paths);
-}
diff --git a/toolsrc/include/triplet.h b/toolsrc/include/triplet.h
index 0c42f2ec7..32ea2e711 100644
--- a/toolsrc/include/triplet.h
+++ b/toolsrc/include/triplet.h
@@ -4,23 +4,24 @@
namespace vcpkg
{
- struct vcpkg_paths;
-
struct triplet
{
+ static triplet from_canonical_name(const std::string& triplet_as_string);
+
static const triplet X86_WINDOWS;
static const triplet X64_WINDOWS;
static const triplet X86_UWP;
static const triplet X64_UWP;
static const triplet ARM_UWP;
- std::string value;
+ const std::string& canonical_name() const;
std::string architecture() const;
std::string system() const;
- bool validate(const vcpkg_paths& paths);
+ private:
+ std::string m_canonical_name;
};
bool operator==(const triplet& left, const triplet& right);
@@ -43,7 +44,7 @@ namespace std
{
std::hash<std::string> hasher;
size_t hash = 17;
- hash = hash * 31 + hasher(t.value);
+ hash = hash * 31 + hasher(t.canonical_name());
return hash;
}
};
diff --git a/toolsrc/include/vcpkg.h b/toolsrc/include/vcpkg.h
deleted file mode 100644
index a4a0682cf..000000000
--- a/toolsrc/include/vcpkg.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#pragma once
-
-#include <filesystem>
-#include <vector>
-#include <unordered_map>
-#include "package_spec.h"
-#include "BinaryParagraph.h"
-#include "StatusParagraphs.h"
-#include "vcpkg_paths.h"
-
-namespace vcpkg
-{
- namespace fs = std::tr2::sys;
-
- extern bool g_do_dry_run;
-
- std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path);
- std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str);
- std::string shorten_description(const std::string& desc);
-
- StatusParagraphs database_load_check(const vcpkg_paths& paths);
-
- std::vector<std::string> get_unmet_package_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db);
-
- void install_package(const vcpkg_paths& paths, const BinaryParagraph& binary_paragraph, StatusParagraphs& status_db);
- void deinstall_package(const vcpkg_paths& paths, const package_spec& spec, StatusParagraphs& status_db);
-
- void search_file(const vcpkg_paths& paths, const std::string& file_substr, const StatusParagraphs& status_db);
-
- void binary_import(const vcpkg_paths& paths, const fs::path& include_directory, const fs::path& project_directory, const BinaryParagraph& control_file_data);
-
- const std::string& version();
-} // namespace vcpkg
diff --git a/toolsrc/include/vcpkg_Checks.h b/toolsrc/include/vcpkg_Checks.h
index 05bd0e729..23869f35f 100644
--- a/toolsrc/include/vcpkg_Checks.h
+++ b/toolsrc/include/vcpkg_Checks.h
@@ -2,7 +2,7 @@
#include "vcpkg_Strings.h"
-namespace vcpkg {namespace Checks
+namespace vcpkg::Checks
{
__declspec(noreturn) void unreachable();
@@ -20,7 +20,7 @@ namespace vcpkg {namespace Checks
template <class...Args>
_declspec(noreturn) void throw_with_message(const char* errorMessageTemplate, const Args&... errorMessageArgs)
{
- throw_with_message(Strings::format(errorMessageTemplate, errorMessageArgs...));
+ throw_with_message(Strings::format(errorMessageTemplate, errorMessageArgs...).c_str());
}
void check_throw(bool expression, const char* errorMessage);
@@ -35,6 +35,8 @@ namespace vcpkg {namespace Checks
}
}
+ void check_exit(bool expression);
+
void check_exit(bool expression, const char* errorMessage);
template <class...Args>
@@ -46,4 +48,4 @@ namespace vcpkg {namespace Checks
exit_with_message(Strings::format(errorMessageTemplate, errorMessageArgs...).c_str());
}
}
-}}
+}
diff --git a/toolsrc/include/vcpkg_Chrono.h b/toolsrc/include/vcpkg_Chrono.h
new file mode 100644
index 000000000..a9d1bbbed
--- /dev/null
+++ b/toolsrc/include/vcpkg_Chrono.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <chrono>
+#include <string>
+
+namespace vcpkg
+{
+ class ElapsedTime
+ {
+ public:
+ static ElapsedTime createStarted();
+
+ constexpr ElapsedTime() : m_startTick() {}
+
+ template <class TimeUnit>
+ TimeUnit elapsed() const
+ {
+ return std::chrono::duration_cast<TimeUnit>(std::chrono::high_resolution_clock::now() - this->m_startTick);
+ }
+
+ double microseconds() const
+ {
+ return elapsed<std::chrono::duration<double, std::micro>>().count();
+ }
+
+ std::string toString() const;
+
+ private:
+ std::chrono::high_resolution_clock::time_point m_startTick;
+ };
+}
diff --git a/toolsrc/include/vcpkg_Commands.h b/toolsrc/include/vcpkg_Commands.h
index c706c131c..544dffe72 100644
--- a/toolsrc/include/vcpkg_Commands.h
+++ b/toolsrc/include/vcpkg_Commands.h
@@ -2,42 +2,139 @@
#include "vcpkg_cmd_arguments.h"
#include "vcpkg_paths.h"
+#include "StatusParagraphs.h"
+#include <array>
-namespace vcpkg
+namespace vcpkg::Commands
{
- extern const char*const INTEGRATE_COMMAND_HELPSTRING;
+ using command_type_a = void(*)(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ using command_type_b = void(*)(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ using command_type_c = void(*)(const vcpkg_cmd_arguments& args);
- void print_usage();
- void print_example(const char* command_and_arguments);
- void update_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ namespace Build
+ {
+ enum class BuildResult
+ {
+ NULLVALUE = 0,
+ SUCCEEDED,
+ BUILD_FAILED,
+ POST_BUILD_CHECKS_FAILED,
+ CASCADED_DUE_TO_MISSING_DEPENDENCIES
+ };
- void build_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
- void build_external_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
- void install_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
- void remove_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ static constexpr std::array<BuildResult, 4> BuildResult_values = { BuildResult::SUCCEEDED, BuildResult::BUILD_FAILED, BuildResult::POST_BUILD_CHECKS_FAILED, BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES };
- void edit_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
- void create_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ const std::string& to_string(const BuildResult build_result);
+ std::string create_error_message(const BuildResult build_result, const package_spec& spec);
+ std::string create_user_troubleshooting_message(const package_spec& spec);
- void search_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
- void list_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
- void import_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
- void owns_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
- void internal_test_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ BuildResult build_package(const SourceParagraph& source_paragraph, const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir, const StatusParagraphs& status_db);
+ void perform_and_exit(const package_spec& spec, const fs::path& port_dir, const std::unordered_set<std::string>& options, const vcpkg_paths& paths);
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ }
- void cache_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ namespace BuildExternal
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ }
- void integrate_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ namespace Install
+ {
+ void install_package(const vcpkg_paths& paths, const BinaryParagraph& binary_paragraph, StatusParagraphs* status_db);
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ }
- void help_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
- void help_topic_valid_triplet(const vcpkg_paths& paths);
+ namespace CI
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ }
- void version_command(const vcpkg_cmd_arguments& args);
- void contact_command(const vcpkg_cmd_arguments& args);
+ namespace Remove
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
+ }
- using command_type_a = void(*)(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet);
- using command_type_b = void(*)(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
- using command_type_c = void(*)(const vcpkg_cmd_arguments& args);
+ namespace Update
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace Create
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace Edit
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace Search
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace List
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace Owns
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace Cache
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace Import
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace Integrate
+ {
+ extern const char*const INTEGRATE_COMMAND_HELPSTRING;
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace PortsDiff
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+ }
+
+ namespace Help
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths);
+
+ void help_topic_valid_triplet(const vcpkg_paths& paths);
+
+ void print_usage();
+
+ void print_example(const std::string& command_and_arguments);
+
+ std::string create_example_string(const std::string& command_and_arguments);
+ }
+
+ namespace Version
+ {
+ const std::string& version();
+ void perform_and_exit(const vcpkg_cmd_arguments& args);
+ }
+
+ namespace Contact
+ {
+ const std::string& email();
+ void perform_and_exit(const vcpkg_cmd_arguments& args);
+ }
+
+ namespace Hash
+ {
+ void perform_and_exit(const vcpkg_cmd_arguments& args);
+ }
template <class T>
struct package_name_and_function
@@ -51,7 +148,7 @@ namespace vcpkg
const std::vector<package_name_and_function<command_type_c>>& get_available_commands_type_c();
template <typename T>
- T find_command(const std::string& command_name, const std::vector<package_name_and_function<T>> available_commands)
+ T find(const std::string& command_name, const std::vector<package_name_and_function<T>> available_commands)
{
for (const package_name_and_function<T>& cmd : available_commands)
{
diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h
index 9dc32fc41..dca824ee9 100644
--- a/toolsrc/include/vcpkg_Dependencies.h
+++ b/toolsrc/include/vcpkg_Dependencies.h
@@ -2,12 +2,78 @@
#include <vector>
#include "package_spec.h"
#include "StatusParagraphs.h"
-#include <unordered_set>
#include "vcpkg_paths.h"
+#include "vcpkg_optional.h"
-namespace vcpkg {namespace Dependencies
+namespace vcpkg::Dependencies
{
- std::vector<package_spec> create_dependency_ordered_install_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db);
+ enum class request_type
+ {
+ UNKNOWN,
+ USER_REQUESTED,
+ AUTO_SELECTED
+ };
- std::unordered_set<package_spec> find_unmet_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db);
-}}
+ enum class install_plan_type
+ {
+ UNKNOWN,
+ BUILD_AND_INSTALL,
+ INSTALL,
+ ALREADY_INSTALLED
+ };
+
+ struct install_plan_action
+ {
+ install_plan_action();
+ install_plan_action(const install_plan_type& plan_type, optional<BinaryParagraph> binary_pgh, optional<SourceParagraph> source_pgh);
+ install_plan_action(const install_plan_action&) = delete;
+ install_plan_action(install_plan_action&&) = default;
+ install_plan_action& operator=(const install_plan_action&) = delete;
+ install_plan_action& operator=(install_plan_action&&) = default;
+
+ install_plan_type plan_type;
+ optional<BinaryParagraph> binary_pgh;
+ optional<SourceParagraph> source_pgh;
+ };
+
+ struct package_spec_with_install_plan
+ {
+ package_spec_with_install_plan(const package_spec& spec, install_plan_action&& plan);
+
+ package_spec spec;
+ install_plan_action plan;
+ };
+
+ enum class remove_plan_type
+ {
+ UNKNOWN,
+ NOT_INSTALLED,
+ REMOVE
+ };
+
+ struct remove_plan_action
+ {
+ remove_plan_action();
+ remove_plan_action(const remove_plan_type& plan_type, const request_type& request_type);
+ remove_plan_action(const remove_plan_action&) = delete;
+ remove_plan_action(remove_plan_action&&) = default;
+ remove_plan_action& operator=(const remove_plan_action&) = delete;
+ remove_plan_action& operator=(remove_plan_action&&) = default;
+
+
+ remove_plan_type plan_type;
+ request_type request_type;
+ };
+
+ struct package_spec_with_remove_plan
+ {
+ package_spec_with_remove_plan(const package_spec& spec, remove_plan_action&& plan);
+
+ package_spec spec;
+ remove_plan_action plan;
+ };
+
+ std::vector<package_spec_with_install_plan> create_install_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db);
+
+ std::vector<package_spec_with_remove_plan> create_remove_plan(const std::vector<package_spec>& specs, const StatusParagraphs& status_db);
+}
diff --git a/toolsrc/include/vcpkg_Enums.h b/toolsrc/include/vcpkg_Enums.h
new file mode 100644
index 000000000..5c4dc8b06
--- /dev/null
+++ b/toolsrc/include/vcpkg_Enums.h
@@ -0,0 +1,11 @@
+#pragma once
+#include <string>
+
+namespace vcpkg::Enums
+{
+ std::string nullvalue_toString(const std::string& enum_name);
+
+ __declspec(noreturn) void nullvalue_used(const std::string& enum_name);
+
+ __declspec(noreturn) void unreachable(const std::string& enum_name);
+}
diff --git a/toolsrc/include/vcpkg_Environment.h b/toolsrc/include/vcpkg_Environment.h
index 877ac7deb..5d12c8f6c 100644
--- a/toolsrc/include/vcpkg_Environment.h
+++ b/toolsrc/include/vcpkg_Environment.h
@@ -1,17 +1,19 @@
#pragma once
#include "vcpkg_paths.h"
-namespace vcpkg {namespace Environment
+namespace vcpkg::Environment
{
- void ensure_nuget_on_path(const vcpkg_paths& paths);
+ const fs::path& get_dumpbin_exe(const vcpkg_paths& paths);
- void ensure_git_on_path(const vcpkg_paths& paths);
+ struct vcvarsall_and_platform_toolset
+ {
+ fs::path path;
+ std::wstring platform_toolset;
+ };
- void ensure_cmake_on_path(const vcpkg_paths& paths);
+ const vcvarsall_and_platform_toolset& get_vcvarsall_bat(const vcpkg_paths& paths);
- inline void ensure_utilities_on_path(const vcpkg_paths& paths)
- {
- ensure_cmake_on_path(paths);
- ensure_git_on_path(paths);
- }
-}}
+ const fs::path& get_ProgramFiles_32_bit();
+
+ const fs::path& get_ProgramFiles_platform_bitness();
+}
diff --git a/toolsrc/include/vcpkg_Files.h b/toolsrc/include/vcpkg_Files.h
index 445713965..3f9570946 100644
--- a/toolsrc/include/vcpkg_Files.h
+++ b/toolsrc/include/vcpkg_Files.h
@@ -1,17 +1,56 @@
#pragma once
#include "expected.h"
-#include <filesystem>
+#include "filesystem_fs.h"
+#include <iterator>
-namespace vcpkg {namespace Files
+namespace vcpkg::Files
{
static const char* FILESYSTEM_INVALID_CHARACTERS = R"(\/:*?"<>|)";
- void check_is_directory(const std::tr2::sys::path& dirpath);
+ void check_is_directory(const fs::path& dirpath);
- bool has_invalid_chars_for_filesystem(const std::string s);
+ bool has_invalid_chars_for_filesystem(const std::string& s);
- expected<std::string> get_contents(const std::tr2::sys::path& file_path) noexcept;
+ expected<std::string> read_contents(const fs::path& file_path) noexcept;
- std::tr2::sys::path find_file_recursively_up(const std::tr2::sys::path& starting_dir, const std::string& filename);
-}}
+ expected<std::vector<std::string>> read_all_lines(const fs::path& file_path);
+
+ void write_all_lines(const fs::path& file_path, const std::vector<std::string>& lines);
+
+ fs::path find_file_recursively_up(const fs::path& starting_dir, const std::string& filename);
+
+ template <class Pred>
+ void non_recursive_find_matching_paths_in_dir(const fs::path& dir, const Pred predicate, std::vector<fs::path>* output)
+ {
+ std::copy_if(fs::directory_iterator(dir), fs::directory_iterator(), std::back_inserter(*output), predicate);
+ }
+
+ template <class Pred>
+ void recursive_find_matching_paths_in_dir(const fs::path& dir, const Pred predicate, std::vector<fs::path>* output)
+ {
+ std::copy_if(fs::recursive_directory_iterator(dir), fs::recursive_directory_iterator(), std::back_inserter(*output), predicate);
+ }
+
+ template <class Pred>
+ std::vector<fs::path> recursive_find_matching_paths_in_dir(const fs::path& dir, const Pred predicate)
+ {
+ std::vector<fs::path> v;
+ recursive_find_matching_paths_in_dir(dir, predicate, &v);
+ return v;
+ }
+
+ void recursive_find_files_with_extension_in_dir(const fs::path& dir, const std::string& extension, std::vector<fs::path>* output);
+
+ std::vector<fs::path> recursive_find_files_with_extension_in_dir(const fs::path& dir, const std::string& extension);
+
+ void recursive_find_all_files_in_dir(const fs::path& dir, std::vector<fs::path>* output);
+
+ std::vector<fs::path> recursive_find_all_files_in_dir(const fs::path& dir);
+
+ void non_recursive_find_all_files_in_dir(const fs::path& dir, std::vector<fs::path>* output);
+
+ std::vector<fs::path> non_recursive_find_all_files_in_dir(const fs::path& dir);
+
+ void print_paths(const std::vector<fs::path>& paths);
+}
diff --git a/toolsrc/include/vcpkg_Graphs.h b/toolsrc/include/vcpkg_Graphs.h
index 81b189f0e..933d9ac67 100644
--- a/toolsrc/include/vcpkg_Graphs.h
+++ b/toolsrc/include/vcpkg_Graphs.h
@@ -1,8 +1,9 @@
#pragma once
#include <unordered_map>
+#include <unordered_set>
-namespace vcpkg { namespace Graphs
+namespace vcpkg::Graphs
{
enum class ExplorationStatus
{
@@ -21,7 +22,7 @@ namespace vcpkg { namespace Graphs
{
static void find_topological_sort_internal(V vertex,
ExplorationStatus& status,
- const std::unordered_map<V, std::vector<V>>& adjacency_list,
+ const std::unordered_map<V, std::unordered_set<V>>& adjacency_list,
std::unordered_map<V, ExplorationStatus>& exploration_status,
std::vector<V>& sorted)
{
@@ -63,7 +64,7 @@ namespace vcpkg { namespace Graphs
void add_edge(V u, V v)
{
this->vertices[v];
- this->vertices[u].push_back(v);
+ this->vertices[u].insert(v);
}
std::vector<V> find_topological_sort() const
@@ -108,12 +109,12 @@ namespace vcpkg { namespace Graphs
return indegrees;
}
- const std::unordered_map<V, std::vector<V>>& adjacency_list() const
+ const std::unordered_map<V, std::unordered_set<V>>& adjacency_list() const
{
return this->vertices;
}
private:
- std::unordered_map<V, std::vector<V>> vertices;
+ std::unordered_map<V, std::unordered_set<V>> vertices;
};
-}}
+}
diff --git a/toolsrc/include/vcpkg_Input.h b/toolsrc/include/vcpkg_Input.h
new file mode 100644
index 000000000..96cbeecc3
--- /dev/null
+++ b/toolsrc/include/vcpkg_Input.h
@@ -0,0 +1,15 @@
+#pragma once
+#include <vector>
+#include "package_spec.h"
+#include "vcpkg_paths.h"
+
+namespace vcpkg::Input
+{
+ package_spec check_and_get_package_spec(const std::string& package_spec_as_string, const triplet& default_target_triplet, const std::string& example_text);
+
+ std::vector<package_spec> check_and_get_package_specs(const std::vector<std::string>& package_specs_as_strings, const triplet& default_target_triplet, const std::string& example_text);
+
+ void check_triplet(const triplet& t, const vcpkg_paths& paths);
+
+ void check_triplets(const std::vector<package_spec>& triplets, const vcpkg_paths& paths);
+}
diff --git a/toolsrc/include/vcpkg_Maps.h b/toolsrc/include/vcpkg_Maps.h
index 5b7b8ed46..5e2f92f55 100644
--- a/toolsrc/include/vcpkg_Maps.h
+++ b/toolsrc/include/vcpkg_Maps.h
@@ -2,8 +2,9 @@
#include <unordered_map>
#include <unordered_set>
+#include <map>
-namespace vcpkg { namespace Maps
+namespace vcpkg::Maps
{
template <typename K, typename V>
std::unordered_set<K> extract_key_set(const std::unordered_map<K, V>& input_map)
@@ -15,4 +16,26 @@ namespace vcpkg { namespace Maps
}
return key_set;
}
-}}
+
+ template <typename K, typename V>
+ std::vector<K> extract_keys(const std::unordered_map<K, V>& input_map)
+ {
+ std::vector<K> key_set;
+ for (auto const& element : input_map)
+ {
+ key_set.push_back(element.first);
+ }
+ return key_set;
+ }
+
+ template <typename K, typename V>
+ std::vector<K> extract_keys(const std::map<K, V>& input_map)
+ {
+ std::vector<K> key_set;
+ for (auto const& element : input_map)
+ {
+ key_set.push_back(element.first);
+ }
+ return key_set;
+ }
+}
diff --git a/toolsrc/include/vcpkg_Sets.h b/toolsrc/include/vcpkg_Sets.h
index 7b330f31c..ec4800864 100644
--- a/toolsrc/include/vcpkg_Sets.h
+++ b/toolsrc/include/vcpkg_Sets.h
@@ -3,15 +3,15 @@
#include "vcpkg_Checks.h"
#include <unordered_set>
-namespace vcpkg { namespace Sets
+namespace vcpkg::Sets
{
template <typename T, typename Container>
void remove_all(std::unordered_set<T>* input_set, Container remove_these)
{
- Checks::check_throw(input_set != nullptr, "Input set cannot be null");
+ Checks::check_exit(input_set != nullptr, "Input set cannot be null");
for (const T& r : remove_these)
{
input_set->erase(r);
}
}
-}}
+}
diff --git a/toolsrc/include/vcpkg_Strings.h b/toolsrc/include/vcpkg_Strings.h
index f4b989292..abf3651e5 100644
--- a/toolsrc/include/vcpkg_Strings.h
+++ b/toolsrc/include/vcpkg_Strings.h
@@ -1,8 +1,8 @@
#pragma once
-#include <string>
+#include <vector>
-namespace vcpkg {namespace Strings {namespace details
+namespace vcpkg::Strings::details
{
inline const char* to_printf_arg(const std::string& s)
{
@@ -19,6 +19,21 @@ namespace vcpkg {namespace Strings {namespace details
return s;
}
+ inline long long to_printf_arg(const long long s)
+ {
+ return s;
+ }
+
+ inline double to_printf_arg(const double s)
+ {
+ return s;
+ }
+
+ inline size_t to_printf_arg(const size_t s)
+ {
+ return s;
+ }
+
std::string format_internal(const char* fmtstr, ...);
inline const wchar_t* to_wprintf_arg(const std::wstring& s)
@@ -31,10 +46,10 @@ namespace vcpkg {namespace Strings {namespace details
return s;
}
- std::wstring format_internal(const wchar_t* fmtstr, ...);
-}}}
+ std::wstring wformat_internal(const wchar_t* fmtstr, ...);
+}
-namespace vcpkg {namespace Strings
+namespace vcpkg::Strings
{
template <class...Args>
std::string format(const char* fmtstr, const Args&...args)
@@ -44,15 +59,74 @@ namespace vcpkg {namespace Strings
}
template <class...Args>
- std::wstring format(const wchar_t* fmtstr, const Args&...args)
+ std::wstring wformat(const wchar_t* fmtstr, const Args&...args)
{
using vcpkg::Strings::details::to_wprintf_arg;
- return details::format_internal(fmtstr, to_wprintf_arg(to_wprintf_arg(args))...);
+ return details::wformat_internal(fmtstr, to_wprintf_arg(to_wprintf_arg(args))...);
}
std::wstring utf8_to_utf16(const std::string& s);
std::string utf16_to_utf8(const std::wstring& w);
- std::string::const_iterator case_insensitive_find(const std::string& s, const std::string& pattern);
-}}
+ std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern);
+
+ std::string ascii_to_lowercase(const std::string& input);
+
+ template <class T, class Transformer>
+ std::string join(const std::string& delimiter, const std::vector<T>& v, Transformer transformer)
+ {
+ if (v.empty())
+ {
+ return std::string();
+ }
+
+ std::string output;
+ size_t size = v.size();
+
+ output.append(transformer(v.at(0)));
+
+ for (size_t i = 1; i < size; ++i)
+ {
+ output.append(delimiter);
+ output.append(transformer(v.at(i)));
+ }
+
+ return output;
+ }
+
+ std::string join(const std::string& delimiter, const std::vector<std::string>& v);
+
+ template <class T, class Transformer>
+ std::wstring wjoin(const std::wstring& delimiter, const std::vector<T>& v, Transformer transformer)
+ {
+ if (v.empty())
+ {
+ return std::wstring();
+ }
+
+ std::wstring output;
+ size_t size = v.size();
+
+ output.append(transformer(v.at(0)));
+
+ for (size_t i = 1; i < size; ++i)
+ {
+ output.append(delimiter);
+ output.append(transformer(v.at(i)));
+ }
+
+ return output;
+ }
+
+ std::wstring wjoin(const std::wstring& delimiter, const std::vector<std::wstring>& v);
+
+
+ void trim(std::string* s);
+
+ std::string trimmed(const std::string& s);
+
+ void trim_all_and_remove_whitespace_strings(std::vector<std::string>* strings);
+
+ std::vector<std::string> split(const std::string& s, const std::string& delimiter);
+}
diff --git a/toolsrc/include/vcpkg_System.h b/toolsrc/include/vcpkg_System.h
index f47fc9aab..71caeed5e 100644
--- a/toolsrc/include/vcpkg_System.h
+++ b/toolsrc/include/vcpkg_System.h
@@ -1,12 +1,15 @@
#pragma once
+#include <Windows.h>
#include "vcpkg_Strings.h"
+#include "filesystem_fs.h"
+#include "vcpkg_optional.h"
-#include <filesystem>
-
-namespace vcpkg {namespace System
+namespace vcpkg::System
{
- std::tr2::sys::path get_exe_path_of_current_process();
+ optional<std::wstring> get_registry_string(HKEY base, const wchar_t* subkey, const wchar_t* valuename);
+
+ fs::path get_exe_path_of_current_process();
struct exit_code_and_output
{
@@ -14,6 +17,13 @@ namespace vcpkg {namespace System
std::string output;
};
+ int cmd_execute_clean(const wchar_t* cmd_line);
+
+ inline int cmd_execute_clean(const std::wstring& cmd_line)
+ {
+ return cmd_execute_clean(cmd_line.c_str());
+ }
+
int cmd_execute(const wchar_t* cmd_line);
inline int cmd_execute(const std::wstring& cmd_line)
@@ -28,6 +38,10 @@ namespace vcpkg {namespace System
return cmd_execute_and_capture_output(cmd_line.c_str());
}
+ std::wstring create_powershell_script_cmd(const fs::path& script_path);
+
+ std::wstring create_powershell_script_cmd(const fs::path& script_path, const std::wstring& args);
+
enum class color
{
success = 10,
@@ -37,8 +51,28 @@ namespace vcpkg {namespace System
void print(const char* message);
void println(const char* message);
- void print(color c, const char* message);
- void println(color c, const char* message);
+ void print(const color c, const char* message);
+ void println(const color c, const char* message);
+
+ inline void print(const std::string& message)
+ {
+ return print(message.c_str());
+ }
+
+ inline void println(const std::string& message)
+ {
+ return println(message.c_str());
+ }
+
+ inline void print(const color c, const std::string& message)
+ {
+ return print(c, message.c_str());
+ }
+
+ inline void println(const color c, const std::string& message)
+ {
+ return println(c, message.c_str());
+ }
template <class...Args>
void print(const char* messageTemplate, const Args&... messageArgs)
@@ -47,7 +81,7 @@ namespace vcpkg {namespace System
}
template <class...Args>
- void print(color c, const char* messageTemplate, const Args&... messageArgs)
+ void print(const color c, const char* messageTemplate, const Args&... messageArgs)
{
return print(c, Strings::format(messageTemplate, messageArgs...).c_str());
}
@@ -59,19 +93,12 @@ namespace vcpkg {namespace System
}
template <class...Args>
- void println(color c, const char* messageTemplate, const Args&... messageArgs)
+ void println(const color c, const char* messageTemplate, const Args&... messageArgs)
{
return println(c, Strings::format(messageTemplate, messageArgs...).c_str());
}
- struct Stopwatch
- {
- int64_t start_time, end_time, freq;
-
- void start();
- void stop();
- double microseconds() const;
- };
+ optional<std::wstring> get_environmental_variable(const wchar_t* varname) noexcept;
- std::wstring wdupenv_str(const wchar_t* varname) noexcept;
-}}
+ void set_environmental_variable(const wchar_t* varname, const wchar_t* varvalue) noexcept;
+}
diff --git a/toolsrc/include/vcpkg_cmd_arguments.h b/toolsrc/include/vcpkg_cmd_arguments.h
index 7df3d64b1..91f7de8ac 100644
--- a/toolsrc/include/vcpkg_cmd_arguments.h
+++ b/toolsrc/include/vcpkg_cmd_arguments.h
@@ -4,30 +4,30 @@
#include <vector>
#include <unordered_set>
#include "opt_bool.h"
-#include "package_spec.h"
-#include "vcpkg_paths.h"
-#include "StatusParagraphs.h"
namespace vcpkg
{
struct vcpkg_cmd_arguments
{
static vcpkg_cmd_arguments create_from_command_line(const int argc, const wchar_t* const* const argv);
-
static vcpkg_cmd_arguments create_from_arg_sequence(const std::string* arg_begin, const std::string* arg_end);
std::unique_ptr<std::string> vcpkg_root_dir;
std::unique_ptr<std::string> target_triplet;
- opt_bool debug = opt_bool::unspecified;
- opt_bool sendmetrics = opt_bool::unspecified;
- opt_bool printmetrics = opt_bool::unspecified;
+ opt_bool_t debug = opt_bool_t::UNSPECIFIED;
+ opt_bool_t sendmetrics = opt_bool_t::UNSPECIFIED;
+ opt_bool_t printmetrics = opt_bool_t::UNSPECIFIED;
std::string command;
std::vector<std::string> command_arguments;
std::unordered_set<std::string> check_and_get_optional_command_arguments(const std::vector<std::string>& valid_options) const;
- void check_max_args(size_t arg_count, const char* example_text = nullptr) const;
- std::vector<package_spec> parse_all_arguments_as_package_specs(const triplet& default_target_triplet, const char* example_text = nullptr) const;
+ void check_max_arg_count(const size_t expected_arg_count) const;
+ void check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const;
+ void check_min_arg_count(const size_t expected_arg_count) const;
+ void check_min_arg_count(const size_t expected_arg_count, const std::string& example_text) const;
+ void check_exact_arg_count(const size_t expected_arg_count) const;
+ void check_exact_arg_count(const size_t expected_arg_count, const std::string& example_text) const;
private:
std::unordered_set<std::string> optional_command_arguments;
diff --git a/toolsrc/include/vcpkg_optional.h b/toolsrc/include/vcpkg_optional.h
new file mode 100644
index 000000000..7b935bea9
--- /dev/null
+++ b/toolsrc/include/vcpkg_optional.h
@@ -0,0 +1,5 @@
+#pragma once
+#include <memory>
+
+template<class T>
+using optional = std::unique_ptr<T>;
diff --git a/toolsrc/include/vcpkg_paths.h b/toolsrc/include/vcpkg_paths.h
index 72cba01b7..99fd14905 100644
--- a/toolsrc/include/vcpkg_paths.h
+++ b/toolsrc/include/vcpkg_paths.h
@@ -1,35 +1,49 @@
#pragma once
-#include <filesystem>
+#include "filesystem_fs.h"
#include "expected.h"
#include "package_spec.h"
+#include "BinaryParagraph.h"
+#include "lazy.h"
namespace vcpkg
{
- namespace fs = std::tr2::sys;
-
struct vcpkg_paths
{
- static expected<vcpkg_paths> create(const std::tr2::sys::path& vcpkg_root_dir);
+ static expected<vcpkg_paths> create(const fs::path& vcpkg_root_dir);
fs::path package_dir(const package_spec& spec) const;
fs::path port_dir(const package_spec& spec) const;
+ fs::path build_info_file_path(const package_spec& spec) const;
+ fs::path listfile_path(const BinaryParagraph& pgh) const;
+
+ bool is_valid_triplet(const triplet& t) const;
+
+ fs::path root;
+ fs::path packages;
+ fs::path buildtrees;
+ fs::path downloads;
+ fs::path ports;
+ fs::path installed;
+ fs::path triplets;
+ fs::path scripts;
+
+ fs::path buildsystems;
+ fs::path buildsystems_msbuild_targets;
- std::tr2::sys::path root;
- std::tr2::sys::path packages;
- std::tr2::sys::path buildtrees;
- std::tr2::sys::path downloads;
- std::tr2::sys::path ports;
- std::tr2::sys::path installed;
- std::tr2::sys::path triplets;
+ fs::path vcpkg_dir;
+ fs::path vcpkg_dir_status_file;
+ fs::path vcpkg_dir_info;
+ fs::path vcpkg_dir_updates;
- std::tr2::sys::path buildsystems;
- std::tr2::sys::path buildsystems_msbuild_targets;
+ fs::path ports_cmake;
- std::tr2::sys::path vcpkg_dir;
- std::tr2::sys::path vcpkg_dir_status_file;
- std::tr2::sys::path vcpkg_dir_info;
- std::tr2::sys::path vcpkg_dir_updates;
+ const fs::path& get_cmake_exe() const;
+ const fs::path& get_git_exe() const;
+ const fs::path& get_nuget_exe() const;
- std::tr2::sys::path ports_cmake;
+ private:
+ lazy<fs::path> cmake_exe;
+ lazy<fs::path> git_exe;
+ lazy<fs::path> nuget_exe;
};
}
diff --git a/toolsrc/include/vcpkglib.h b/toolsrc/include/vcpkglib.h
new file mode 100644
index 000000000..353bfb0a0
--- /dev/null
+++ b/toolsrc/include/vcpkglib.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "StatusParagraphs.h"
+#include "vcpkg_paths.h"
+#include "ImmutableSortedVector.h"
+
+namespace vcpkg
+{
+ StatusParagraphs database_load_check(const vcpkg_paths& paths);
+
+ void write_update(const vcpkg_paths& paths, const StatusParagraph& p);
+
+ struct StatusParagraph_and_associated_files
+ {
+ StatusParagraph pgh;
+ ImmutableSortedVector<std::string> files;
+ };
+
+ std::vector<StatusParagraph_and_associated_files> get_installed_files(const vcpkg_paths& paths, const StatusParagraphs& status_db);
+
+
+ struct CMakeVariable
+ {
+ CMakeVariable(const std::wstring& varname, const wchar_t* varvalue);
+ CMakeVariable(const std::wstring& varname, const std::string& varvalue);
+ CMakeVariable(const std::wstring& varname, const std::wstring& varvalue);
+ CMakeVariable(const std::wstring& varname, const fs::path& path);
+
+ std::wstring s;
+ };
+
+ std::wstring make_cmake_cmd(const fs::path& cmake_exe, const fs::path& cmake_script, const std::vector<CMakeVariable>& pass_variables);
+
+} // namespace vcpkg
diff --git a/toolsrc/include/vcpkglib_helpers.h b/toolsrc/include/vcpkglib_helpers.h
index e15b59b0b..8a08513f3 100644
--- a/toolsrc/include/vcpkglib_helpers.h
+++ b/toolsrc/include/vcpkglib_helpers.h
@@ -2,11 +2,13 @@
#include <unordered_map>
-namespace vcpkg {namespace details
+namespace vcpkg::details
{
- void optional_field(const std::unordered_map<std::string, std::string>& fields, std::string& out, const std::string& fieldname);
+ std::string optional_field(const std::unordered_map<std::string, std::string>& fields, const std::string& fieldname);
+ std::string remove_optional_field(std::unordered_map<std::string, std::string>* fields, const std::string& fieldname);
- void required_field(const std::unordered_map<std::string, std::string>& fields, std::string& out, const std::string& fieldname);
+ std::string required_field(const std::unordered_map<std::string, std::string>& fields, const std::string& fieldname);
+ std::string remove_required_field(std::unordered_map<std::string, std::string>* fields, const std::string& fieldname);
- void parse_depends(const std::string& depends_string, std::vector<std::string>& out);
-}}
+ std::string shorten_description(const std::string& desc);
+}
diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp
index 274bd879e..8605cd276 100644
--- a/toolsrc/src/BinaryParagraph.cpp
+++ b/toolsrc/src/BinaryParagraph.cpp
@@ -1,3 +1,4 @@
+#include "pch.h"
#include "BinaryParagraph.h"
#include "vcpkglib_helpers.h"
#include "vcpkg_Checks.h"
@@ -6,57 +7,70 @@ using namespace vcpkg::details;
namespace vcpkg
{
+ //
+ namespace BinaryParagraphRequiredField
+ {
+ static const std::string PACKAGE = "Package";
+ static const std::string VERSION = "Version";
+ static const std::string ARCHITECTURE = "Architecture";
+ static const std::string MULTI_ARCH = "Multi-Arch";
+ }
+
+ namespace BinaryParagraphOptionalField
+ {
+ static const std::string DESCRIPTION = "Description";
+ static const std::string MAINTAINER = "Maintainer";
+ static const std::string DEPENDS = "Depends";
+ }
+
BinaryParagraph::BinaryParagraph() = default;
- BinaryParagraph::BinaryParagraph(const std::unordered_map<std::string, std::string>& fields)
+ BinaryParagraph::BinaryParagraph(std::unordered_map<std::string, std::string> fields)
{
- details::required_field(fields, name, "Package");
- required_field(fields, version, "Version");
- required_field(fields, target_triplet.value, "Architecture");
- {
- std::string multi_arch;
- required_field(fields, multi_arch, "Multi-Arch");
- Checks::check_throw(multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch);
- }
- optional_field(fields, description, "Description");
- std::string deps;
- optional_field(fields, deps, "Depends");
- if (!deps.empty())
- {
- depends.clear();
- parse_depends(deps, depends);
- }
- optional_field(fields, maintainer, "Maintainer");
+ const std::string name = details::remove_required_field(&fields, BinaryParagraphRequiredField::PACKAGE);
+ const std::string architecture = details::remove_required_field(&fields, BinaryParagraphRequiredField::ARCHITECTURE);
+ const triplet target_triplet = triplet::from_canonical_name(architecture);
+
+ this->spec = package_spec::from_name_and_triplet(name, target_triplet).get_or_throw();
+ this->version = details::remove_required_field(&fields, BinaryParagraphRequiredField::VERSION);
+
+ this->description = details::remove_optional_field(&fields, BinaryParagraphOptionalField::DESCRIPTION);
+ this->maintainer = details::remove_optional_field(&fields, BinaryParagraphOptionalField::MAINTAINER);
+
+ std::string multi_arch = details::remove_required_field(&fields, BinaryParagraphRequiredField::MULTI_ARCH);
+ Checks::check_exit(multi_arch == "same", "Multi-Arch must be 'same' but was %s", multi_arch);
+
+ std::string deps = details::remove_optional_field(&fields, BinaryParagraphOptionalField::DEPENDS);
+ this->depends = parse_depends(deps);
}
BinaryParagraph::BinaryParagraph(const SourceParagraph& spgh, const triplet& target_triplet)
{
- this->name = spgh.name;
+ this->spec = package_spec::from_name_and_triplet(spgh.name, target_triplet).get_or_throw();
this->version = spgh.version;
this->description = spgh.description;
this->maintainer = spgh.maintainer;
- this->depends = spgh.depends;
- this->target_triplet = target_triplet;
+ this->depends = filter_dependencies(spgh.depends, target_triplet);
}
std::string BinaryParagraph::displayname() const
{
- return Strings::format("%s:%s", this->name, this->target_triplet);
+ return this->spec.display_name();
}
std::string BinaryParagraph::dir() const
{
- return Strings::format("%s_%s", this->name, this->target_triplet);
+ return this->spec.dir();
}
std::string BinaryParagraph::fullstem() const
{
- return Strings::format("%s_%s_%s", this->name, this->version, this->target_triplet);
+ return Strings::format("%s_%s_%s", this->spec.name(), this->version, this->spec.target_triplet());
}
std::ostream& operator<<(std::ostream& os, const BinaryParagraph& p)
{
- os << "Package: " << p.name << "\n";
+ os << "Package: " << p.spec.name() << "\n";
os << "Version: " << p.version << "\n";
if (!p.depends.empty())
{
@@ -71,7 +85,7 @@ namespace vcpkg
os << "\n";
}
- os << "Architecture: " << p.target_triplet << "\n";
+ os << "Architecture: " << p.spec.target_triplet() << "\n";
os << "Multi-Arch: same\n";
if (!p.maintainer.empty())
os << "Maintainer: " << p.maintainer << "\n";
diff --git a/toolsrc/src/MachineType.cpp b/toolsrc/src/MachineType.cpp
new file mode 100644
index 000000000..81012234d
--- /dev/null
+++ b/toolsrc/src/MachineType.cpp
@@ -0,0 +1,42 @@
+#include "pch.h"
+#include "MachineType.h"
+#include "vcpkg_Checks.h"
+
+namespace vcpkg
+{
+ MachineType getMachineType(const uint16_t value)
+ {
+ MachineType t = static_cast<MachineType>(value);
+ switch (t)
+ {
+ case MachineType::UNKNOWN:
+ case MachineType::AM33:
+ case MachineType::AMD64:
+ case MachineType::ARM:
+ case MachineType::ARM64:
+ case MachineType::ARMNT:
+ case MachineType::EBC:
+ case MachineType::I386:
+ case MachineType::IA64:
+ case MachineType::M32R:
+ case MachineType::MIPS16:
+ case MachineType::MIPSFPU:
+ case MachineType::MIPSFPU16:
+ case MachineType::POWERPC:
+ case MachineType::POWERPCFP:
+ case MachineType::R4000:
+ case MachineType::RISCV32:
+ case MachineType::RISCV64:
+ case MachineType::RISCV128:
+ case MachineType::SH3:
+ case MachineType::SH3DSP:
+ case MachineType::SH4:
+ case MachineType::SH5:
+ case MachineType::THUMB:
+ case MachineType::WCEMIPSV2:
+ return t;
+ default:
+ Checks::exit_with_message("Unknown machine type code 0x%x", value);
+ }
+ }
+}
diff --git a/toolsrc/src/Paragraphs.cpp b/toolsrc/src/Paragraphs.cpp
new file mode 100644
index 000000000..cb90ed1ec
--- /dev/null
+++ b/toolsrc/src/Paragraphs.cpp
@@ -0,0 +1,227 @@
+#include "pch.h"
+#include "Paragraphs.h"
+#include "vcpkg_Files.h"
+
+namespace vcpkg::Paragraphs
+{
+ struct Parser
+ {
+ Parser(const char* c, const char* e) : cur(c), end(e) { }
+
+ private:
+ const char* cur;
+ const char* const end;
+
+ void peek(char& ch) const
+ {
+ if (cur == end)
+ ch = 0;
+ else
+ ch = *cur;
+ }
+
+ void next(char& ch)
+ {
+ if (cur == end)
+ ch = 0;
+ else
+ {
+ ++cur;
+ peek(ch);
+ }
+ }
+
+ void skip_spaces(char& ch)
+ {
+ while (ch == ' ' || ch == '\t')
+ next(ch);
+ }
+
+ static bool is_alphanum(char ch)
+ {
+ return (ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')
+ || (ch >= '0' && ch <= '9');
+ }
+
+ static bool is_lineend(char ch)
+ {
+ return ch == '\r' || ch == '\n' || ch == 0;
+ }
+
+ void get_fieldvalue(char& ch, std::string& fieldvalue)
+ {
+ fieldvalue.clear();
+
+ auto beginning_of_line = cur;
+ do
+ {
+ // scan to end of current line (it is part of the field value)
+ while (!is_lineend(ch))
+ next(ch);
+
+ fieldvalue.append(beginning_of_line, cur);
+
+ if (ch == '\r')
+ next(ch);
+ if (ch == '\n')
+ next(ch);
+
+ if (is_alphanum(ch))
+ {
+ // Line begins a new field.
+ return;
+ }
+
+ beginning_of_line = cur;
+
+ // Line may continue the current field with data or terminate the paragraph,
+ // depending on first nonspace character.
+ skip_spaces(ch);
+
+ if (is_lineend(ch))
+ {
+ // Line was whitespace or empty.
+ // This terminates the field and the paragraph.
+ // We leave the blank line's whitespace consumed, because it doesn't matter.
+ return;
+ }
+
+ // First nonspace is not a newline. This continues the current field value.
+ // We forcibly convert all newlines into single '\n' for ease of text handling later on.
+ fieldvalue.push_back('\n');
+ }
+ while (true);
+ }
+
+ void get_fieldname(char& ch, std::string& fieldname)
+ {
+ auto begin_fieldname = cur;
+ while (is_alphanum(ch) || ch == '-')
+ next(ch);
+ Checks::check_exit(ch == ':', "Expected ':'");
+ fieldname = std::string(begin_fieldname, cur);
+
+ // skip ': '
+ next(ch);
+ skip_spaces(ch);
+ }
+
+ void get_paragraph(char& ch, std::unordered_map<std::string, std::string>& fields)
+ {
+ fields.clear();
+ std::string fieldname;
+ std::string fieldvalue;
+ do
+ {
+ get_fieldname(ch, fieldname);
+
+ auto it = fields.find(fieldname);
+ Checks::check_exit(it == fields.end(), "Duplicate field");
+
+ get_fieldvalue(ch, fieldvalue);
+
+ fields.emplace(fieldname, fieldvalue);
+ }
+ while (!is_lineend(ch));
+ }
+
+ public:
+ std::vector<std::unordered_map<std::string, std::string>> get_paragraphs()
+ {
+ std::vector<std::unordered_map<std::string, std::string>> paragraphs;
+
+ char ch;
+ peek(ch);
+
+ while (ch != 0)
+ {
+ if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t')
+ {
+ next(ch);
+ continue;
+ }
+
+ paragraphs.emplace_back();
+ get_paragraph(ch, paragraphs.back());
+ }
+
+ return paragraphs;
+ }
+ };
+
+ std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path)
+ {
+ const expected<std::string> contents = Files::read_contents(control_path);
+ if (auto spgh = contents.get())
+ {
+ return parse_paragraphs(*spgh);
+ }
+
+ Checks::exit_with_message("Error while reading %s: %s", control_path.generic_string(), contents.error_code().message());
+ }
+
+ std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str)
+ {
+ return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs();
+ }
+
+ expected<SourceParagraph> try_load_port(const fs::path& path)
+ {
+ try
+ {
+ auto pghs = get_paragraphs(path / "CONTROL");
+ Checks::check_exit(pghs.size() == 1, "Invalid control file at %s\\CONTROL", path.string());
+ return SourceParagraph(pghs[0]);
+ }
+ catch (std::runtime_error const&) {}
+
+ return std::errc::no_such_file_or_directory;
+ }
+
+ expected<BinaryParagraph> try_load_cached_package(const vcpkg_paths& paths, const package_spec& spec)
+ {
+ const fs::path path = paths.package_dir(spec) / "CONTROL";
+
+ auto control_contents_maybe = Files::read_contents(path);
+ if (auto control_contents = control_contents_maybe.get())
+ {
+ std::vector<std::unordered_map<std::string, std::string>> pghs;
+ try
+ {
+ pghs = parse_paragraphs(*control_contents);
+ }
+ catch (std::runtime_error) {}
+ Checks::check_exit(pghs.size() == 1, "Invalid control file at %s", path.string());
+ return BinaryParagraph(pghs[0]);
+ }
+ return control_contents_maybe.error_code();
+ }
+
+ std::vector<SourceParagraph> load_all_ports(const fs::path& ports_dir)
+ {
+ std::vector<SourceParagraph> output;
+ for (auto it = fs::directory_iterator(ports_dir); it != fs::directory_iterator(); ++it)
+ {
+ const fs::path& path = it->path();
+ expected<SourceParagraph> source_paragraph = try_load_port(path);
+ if (auto srcpgh = source_paragraph.get())
+ {
+ output.emplace_back(std::move(*srcpgh));
+ }
+ }
+
+ return output;
+ }
+
+ std::map<std::string, std::string> extract_port_names_and_versions(const std::vector<SourceParagraph>& source_paragraphs)
+ {
+ std::map<std::string, std::string> names_and_versions;
+ for (const SourceParagraph& port : source_paragraphs)
+ {
+ names_and_versions.emplace(port.name, port.version);
+ }
+
+ return names_and_versions;
+ }
+}
diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp
new file mode 100644
index 000000000..8abf71bb3
--- /dev/null
+++ b/toolsrc/src/PostBuildLint.cpp
@@ -0,0 +1,719 @@
+#include "pch.h"
+#include "vcpkg_paths.h"
+#include "package_spec.h"
+#include "vcpkg_Files.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Environment.h"
+#include "coff_file_reader.h"
+#include "PostBuildLint_BuildInfo.h"
+#include "PostBuildLint_BuildType.h"
+
+namespace vcpkg::PostBuildLint
+{
+ enum class lint_status
+ {
+ SUCCESS = 0,
+ ERROR_DETECTED = 1
+ };
+
+ struct OutdatedDynamicCrt
+ {
+ std::string name;
+ std::regex regex;
+
+ OutdatedDynamicCrt(const std::string& name, const std::string& regex_as_string)
+ : name(name),
+ regex(std::regex(regex_as_string, std::regex_constants::icase)) {}
+ };
+
+ const std::vector<OutdatedDynamicCrt>& get_outdated_dynamic_crts()
+ {
+ static const std::vector<OutdatedDynamicCrt> v = {
+ { "msvcp100.dll", R"(msvcp100\.dll)" },
+ { "msvcp100d.dll", R"(msvcp100d\.dll)" },
+ { "msvcp110.dll", R"(msvcp110\.dll)" },
+ { "msvcp110_win.dll", R"(msvcp110_win\.dll)" },
+ { "msvcp120.dll", R"(msvcp120\.dll)" },
+ { "msvcp120_clr0400.dll", R"(msvcp120_clr0400\.dll)" },
+ { "msvcp60.dll", R"(msvcp60\.dll)" },
+ { "msvcp60.dll", R"(msvcp60\.dll)" },
+
+ { "msvcr100.dll", R"(msvcr100\.dll)" },
+ { "msvcr100d.dll", R"(msvcr100d\.dll)" },
+ { "msvcr100_clr0400.dll", R"(msvcr100_clr0400\.dll)" },
+ { "msvcr110.dll", R"(msvcr110\.dll)" },
+ { "msvcr120.dll", R"(msvcr120\.dll)" },
+ { "msvcr120_clr0400.dll", R"(msvcr120_clr0400\.dll)" },
+ { "msvcrt.dll", R"(msvcrt\.dll)" },
+ { "msvcrt20.dll", R"(msvcrt20\.dll)" },
+ { "msvcrt40.dll", R"(msvcrt40\.dll)" }
+ };
+
+ return v;
+ }
+
+ static lint_status check_for_files_in_include_directory(const fs::path& package_dir)
+ {
+ const fs::path include_dir = package_dir / "include";
+ if (!fs::exists(include_dir) || fs::is_empty(include_dir))
+ {
+ System::println(System::color::warning, "The folder /include is empty. This indicates the library was not correctly installed.");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_for_files_in_debug_include_directory(const fs::path& package_dir)
+ {
+ const fs::path debug_include_dir = package_dir / "debug" / "include";
+ std::vector<fs::path> files_found;
+
+ Files::recursive_find_matching_paths_in_dir(debug_include_dir, [&](const fs::path& current)
+ {
+ return !fs::is_directory(current) && current.extension() != ".ifc";
+ }, &files_found);
+
+ if (!files_found.empty())
+ {
+ System::println(System::color::warning, "Include files should not be duplicated into the /debug/include directory. If this cannot be disabled in the project cmake, use\n"
+ " file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include)"
+ );
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_for_files_in_debug_share_directory(const fs::path& package_dir)
+ {
+ const fs::path debug_share = package_dir / "debug" / "share";
+
+ if (fs::exists(debug_share) && !fs::is_empty(debug_share))
+ {
+ System::println(System::color::warning, "No files should be present in /debug/share");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_folder_lib_cmake(const fs::path& package_dir)
+ {
+ const fs::path lib_cmake = package_dir / "lib" / "cmake";
+ if (fs::exists(lib_cmake))
+ {
+ System::println(System::color::warning, "The /lib/cmake folder should be moved to just /cmake");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_for_misplaced_cmake_files(const fs::path& package_dir, const package_spec& spec)
+ {
+ std::vector<fs::path> misplaced_cmake_files;
+ Files::recursive_find_files_with_extension_in_dir(package_dir / "cmake", ".cmake", &misplaced_cmake_files);
+ Files::recursive_find_files_with_extension_in_dir(package_dir / "debug" / "cmake", ".cmake", &misplaced_cmake_files);
+ Files::recursive_find_files_with_extension_in_dir(package_dir / "lib" / "cmake", ".cmake", &misplaced_cmake_files);
+ Files::recursive_find_files_with_extension_in_dir(package_dir / "debug" / "lib" / "cmake", ".cmake", &misplaced_cmake_files);
+
+ if (!misplaced_cmake_files.empty())
+ {
+ System::println(System::color::warning, "The following cmake files were found outside /share/%s. Please place cmake files in /share/%s.", spec.name(), spec.name());
+ Files::print_paths(misplaced_cmake_files);
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_folder_debug_lib_cmake(const fs::path& package_dir)
+ {
+ const fs::path lib_cmake_debug = package_dir / "debug" / "lib" / "cmake";
+ if (fs::exists(lib_cmake_debug))
+ {
+ System::println(System::color::warning, "The /debug/lib/cmake folder should be moved to just /debug/cmake");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_for_dlls_in_lib_dirs(const fs::path& package_dir)
+ {
+ std::vector<fs::path> dlls;
+ Files::recursive_find_files_with_extension_in_dir(package_dir / "lib", ".dll", &dlls);
+ Files::recursive_find_files_with_extension_in_dir(package_dir / "debug" / "lib", ".dll", &dlls);
+
+ if (!dlls.empty())
+ {
+ System::println(System::color::warning, "\nThe following dlls were found in /lib and /debug/lib. Please move them to /bin or /debug/bin, respectively.");
+ Files::print_paths(dlls);
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_for_copyright_file(const package_spec& spec, const vcpkg_paths& paths)
+ {
+ const fs::path packages_dir = paths.packages / spec.dir();
+ const fs::path copyright_file = packages_dir / "share" / spec.name() / "copyright";
+ if (fs::exists(copyright_file))
+ {
+ return lint_status::SUCCESS;
+ }
+ const fs::path current_buildtrees_dir = paths.buildtrees / spec.name();
+ const fs::path current_buildtrees_dir_src = current_buildtrees_dir / "src";
+
+ std::vector<fs::path> potential_copyright_files;
+ // Only searching one level deep
+ for (auto it = fs::recursive_directory_iterator(current_buildtrees_dir_src); it != fs::recursive_directory_iterator(); ++it)
+ {
+ if (it.depth() > 1)
+ {
+ continue;
+ }
+
+ const std::string filename = it->path().filename().string();
+ if (filename == "LICENSE" || filename == "LICENSE.txt" || filename == "COPYING")
+ {
+ potential_copyright_files.push_back(it->path());
+ }
+ }
+
+ System::println(System::color::warning, "The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright .", spec.name());
+ if (potential_copyright_files.size() == 1) // if there is only one candidate, provide the cmake lines needed to place it in the proper location
+ {
+ const fs::path found_file = potential_copyright_files[0];
+ const fs::path relative_path = found_file.string().erase(0, current_buildtrees_dir.string().size() + 1); // The +1 is needed to remove the "/"
+ System::println("\n file(COPY ${CURRENT_BUILDTREES_DIR}/%s DESTINATION ${CURRENT_PACKAGES_DIR}/share/%s)\n"
+ " file(RENAME ${CURRENT_PACKAGES_DIR}/share/%s/%s ${CURRENT_PACKAGES_DIR}/share/%s/copyright)",
+ relative_path.generic_string(), spec.name(), spec.name(), found_file.filename().generic_string(), spec.name());
+ return lint_status::ERROR_DETECTED;
+ }
+
+ if (potential_copyright_files.size() > 1)
+ {
+ System::println(System::color::warning, "The following files are potential copyright files:");
+ Files::print_paths(potential_copyright_files);
+ }
+
+ System::println(" %s/share/%s/copyright", packages_dir.generic_string(), spec.name());
+ return lint_status::ERROR_DETECTED;
+ }
+
+ static lint_status check_for_exes(const fs::path& package_dir)
+ {
+ std::vector<fs::path> exes;
+ Files::recursive_find_files_with_extension_in_dir(package_dir / "bin", ".exe", &exes);
+ Files::recursive_find_files_with_extension_in_dir(package_dir / "debug" / "bin", ".exe", &exes);
+
+ if (!exes.empty())
+ {
+ System::println(System::color::warning, "The following EXEs were found in /bin and /debug/bin. EXEs are not valid distribution targets.");
+ Files::print_paths(exes);
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_exports_of_dlls(const std::vector<fs::path>& dlls, const fs::path& dumpbin_exe)
+ {
+ std::vector<fs::path> dlls_with_no_exports;
+ for (const fs::path& dll : dlls)
+ {
+ const std::wstring cmd_line = Strings::wformat(LR"("%s" /exports "%s")", dumpbin_exe.native(), dll.native());
+ System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
+ Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
+
+ if (ec_data.output.find("ordinal hint RVA name") == std::string::npos)
+ {
+ dlls_with_no_exports.push_back(dll);
+ }
+ }
+
+ if (!dlls_with_no_exports.empty())
+ {
+ System::println(System::color::warning, "The following DLLs have no exports:");
+ Files::print_paths(dlls_with_no_exports);
+ System::println(System::color::warning, "DLLs without any exports are likely a bug in the build script.");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_uwp_bit_of_dlls(const std::string& expected_system_name, const std::vector<fs::path>& dlls, const fs::path dumpbin_exe)
+ {
+ if (expected_system_name != "uwp")
+ {
+ return lint_status::SUCCESS;
+ }
+
+ std::vector<fs::path> dlls_with_improper_uwp_bit;
+ for (const fs::path& dll : dlls)
+ {
+ const std::wstring cmd_line = Strings::wformat(LR"("%s" /headers "%s")", dumpbin_exe.native(), dll.native());
+ System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
+ Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
+
+ if (ec_data.output.find("App Container") == std::string::npos)
+ {
+ dlls_with_improper_uwp_bit.push_back(dll);
+ }
+ }
+
+ if (!dlls_with_improper_uwp_bit.empty())
+ {
+ System::println(System::color::warning, "The following DLLs do not have the App Container bit set:");
+ Files::print_paths(dlls_with_improper_uwp_bit);
+ System::println(System::color::warning, "This bit is required for Windows Store apps.");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ struct file_and_arch
+ {
+ fs::path file;
+ std::string actual_arch;
+ };
+
+ static std::string get_actual_architecture(const MachineType& machine_type)
+ {
+ switch (machine_type)
+ {
+ case MachineType::AMD64:
+ case MachineType::IA64:
+ return "x64";
+ case MachineType::I386:
+ return "x86";
+ case MachineType::ARM:
+ case MachineType::ARMNT:
+ return "arm";
+ default:
+ return "Machine Type Code = " + std::to_string(static_cast<uint16_t>(machine_type));
+ }
+ }
+
+ static void print_invalid_architecture_files(const std::string& expected_architecture, std::vector<file_and_arch> binaries_with_invalid_architecture)
+ {
+ System::println(System::color::warning, "The following files were built for an incorrect architecture:");
+ System::println("");
+ for (const file_and_arch& 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("");
+ }
+ }
+
+ static lint_status check_dll_architecture(const std::string& expected_architecture, const std::vector<fs::path>& files)
+ {
+ std::vector<file_and_arch> binaries_with_invalid_architecture;
+
+ for (const fs::path& file : files)
+ {
+ Checks::check_exit(file.extension() == ".dll", "The file extension was not .dll: %s", file.generic_string());
+ COFFFileReader::dll_info info = COFFFileReader::read_dll(file);
+ const std::string actual_architecture = get_actual_architecture(info.machine_type);
+
+ if (expected_architecture != actual_architecture)
+ {
+ binaries_with_invalid_architecture.push_back({ file, actual_architecture });
+ }
+ }
+
+ if (!binaries_with_invalid_architecture.empty())
+ {
+ print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture);
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_lib_architecture(const std::string& expected_architecture, const std::vector<fs::path>& files)
+ {
+ std::vector<file_and_arch> binaries_with_invalid_architecture;
+
+ for (const fs::path& file : files)
+ {
+ Checks::check_exit(file.extension() == ".lib", "The file extension was not .lib: %s", file.generic_string());
+ COFFFileReader::lib_info info = COFFFileReader::read_lib(file);
+ Checks::check_exit(info.machine_types.size() == 1, "Found more than 1 architecture in file %s", file.generic_string());
+
+ const std::string actual_architecture = get_actual_architecture(info.machine_types.at(0));
+ if (expected_architecture != actual_architecture)
+ {
+ binaries_with_invalid_architecture.push_back({ file, actual_architecture });
+ }
+ }
+
+ if (!binaries_with_invalid_architecture.empty())
+ {
+ print_invalid_architecture_files(expected_architecture, binaries_with_invalid_architecture);
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_no_dlls_present(const std::vector<fs::path>& dlls)
+ {
+ if (dlls.empty())
+ {
+ return lint_status::SUCCESS;
+ }
+
+ System::println(System::color::warning, "DLLs should not be present in a static build, but the following DLLs were found:");
+ Files::print_paths(dlls);
+ return lint_status::ERROR_DETECTED;
+ }
+
+ static lint_status check_matching_debug_and_release_binaries(const std::vector<fs::path>& debug_binaries, const std::vector<fs::path>& release_binaries)
+ {
+ const size_t debug_count = debug_binaries.size();
+ const size_t release_count = release_binaries.size();
+ if (debug_count == release_count)
+ {
+ return lint_status::SUCCESS;
+ }
+
+ System::println(System::color::warning, "Mismatching number of debug and release binaries. Found %d for debug but %d for release.", debug_count, release_count);
+ System::println("Debug binaries");
+ Files::print_paths(debug_binaries);
+
+ System::println("Release binaries");
+ Files::print_paths(release_binaries);
+
+ if (debug_count == 0)
+ {
+ System::println(System::color::warning, "Debug binaries were not found");
+ }
+ if (release_count == 0)
+ {
+ System::println(System::color::warning, "Release binaries were not found");
+ }
+
+ System::println("");
+
+ return lint_status::ERROR_DETECTED;
+ }
+
+ static lint_status check_lib_files_are_available_if_dlls_are_available(const std::map<BuildPolicies::type, opt_bool_t>& policies, const size_t lib_count, const size_t dll_count, const fs::path& lib_dir)
+ {
+ auto it = policies.find(BuildPolicies::DLLS_WITHOUT_LIBS);
+ if (it != policies.cend() && it->second == opt_bool_t::DISABLED)
+ {
+ return lint_status::SUCCESS;
+ }
+
+ if (lib_count == 0 && dll_count != 0)
+ {
+ System::println(System::color::warning, "Import libs were not present in %s", lib_dir.generic_string());
+ System::println(System::color::warning,
+ "If this is intended, add the following line in the portfile:\n"
+ " SET(%s disabled)", BuildPolicies::DLLS_WITHOUT_LIBS.cmake_variable());
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_bin_folders_are_not_present_in_static_build(const fs::path& package_dir)
+ {
+ const fs::path bin = package_dir / "bin";
+ const fs::path debug_bin = package_dir / "debug" / "bin";
+
+ if (!fs::exists(bin) && !fs::exists(debug_bin))
+ {
+ return lint_status::SUCCESS;
+ }
+
+ if (fs::exists(bin))
+ {
+ System::println(System::color::warning, R"(There should be no bin\ directory in a static build, but %s is present.)", bin.generic_string());
+ }
+
+ if (fs::exists(debug_bin))
+ {
+ System::println(System::color::warning, R"(There should be no debug\bin\ directory in a static build, but %s is present.)", debug_bin.generic_string());
+ }
+
+ System::println(System::color::warning, R"(If the creation of bin\ and/or debug\bin\ cannot be disabled, use this in the portfile to remove them)" "\n"
+ "\n"
+ R"###( if(VCPKG_LIBRARY_LINKAGE STREQUAL static))###""\n"
+ R"###( file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/bin ${CURRENT_PACKAGES_DIR}/debug/bin))###""\n"
+ R"###( endif())###"
+ "\n"
+ );
+
+ return lint_status::ERROR_DETECTED;
+ }
+
+ static lint_status check_no_empty_folders(const fs::path& dir)
+ {
+ const std::vector<fs::path> empty_directories = Files::recursive_find_matching_paths_in_dir(dir, [](const fs::path& current)
+ {
+ return fs::is_directory(current) && fs::is_empty(current);
+ });
+
+ if (!empty_directories.empty())
+ {
+ System::println(System::color::warning, "There should be no empty directories in %s", dir.generic_string());
+ System::println("The following empty directories were found: ");
+ Files::print_paths(empty_directories);
+ System::println(System::color::warning, "If a directory should be populated but is not, this might indicate an error in the portfile.\n"
+ "If the directories are not needed and their creation cannot be disabled, use something like this in the portfile to remove them:\n"
+ "\n"
+ R"###( file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/a/dir ${CURRENT_PACKAGES_DIR}/some/other/dir))###""\n"
+ "\n");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ struct BuildType_and_file
+ {
+ fs::path file;
+ BuildType::type build_type;
+ };
+
+ static lint_status check_crt_linkage_of_libs(const BuildType::type& expected_build_type, const std::vector<fs::path>& libs, const fs::path dumpbin_exe)
+ {
+ std::vector<BuildType::type> bad_build_types(BuildType::values.cbegin(), BuildType::values.cend());
+ 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;
+
+ for (const fs::path& lib : libs)
+ {
+ const std::wstring cmd_line = Strings::wformat(LR"("%s" /directives "%s")", dumpbin_exe.native(), lib.native());
+ System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
+ Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
+
+ for (const BuildType::type& bad_build_type : bad_build_types)
+ {
+ if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), bad_build_type.crt_regex()))
+ {
+ libs_with_invalid_crt.push_back({ lib, bad_build_type });
+ break;
+ }
+ }
+ }
+
+ if (!libs_with_invalid_crt.empty())
+ {
+ System::println(System::color::warning, "Expected %s crt linkage, but the following libs had invalid crt linkage:", expected_build_type.toString());
+ System::println("");
+ for (const BuildType_and_file btf : libs_with_invalid_crt)
+ {
+ System::println(" %s: %s", btf.file.generic_string(), btf.build_type.toString());
+ }
+ System::println("");
+
+ System::println(System::color::warning, "To inspect the lib files, use:\n dumpbin.exe /directives mylibfile.lib");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ struct OutdatedDynamicCrt_and_file
+ {
+ fs::path file;
+ OutdatedDynamicCrt outdated_crt;
+
+ OutdatedDynamicCrt_and_file() = delete;
+ };
+
+ static lint_status check_outdated_crt_linkage_of_dlls(const std::vector<fs::path>& dlls, const fs::path dumpbin_exe)
+ {
+ const std::vector<OutdatedDynamicCrt>& outdated_crts = get_outdated_dynamic_crts();
+
+ std::vector<OutdatedDynamicCrt_and_file> dlls_with_outdated_crt;
+
+ for (const fs::path& dll : dlls)
+ {
+ const std::wstring cmd_line = Strings::wformat(LR"("%s" /dependents "%s")", dumpbin_exe.native(), dll.native());
+ System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
+ Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
+
+ for (const OutdatedDynamicCrt& outdated_crt : outdated_crts)
+ {
+ if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), outdated_crt.regex))
+ {
+ dlls_with_outdated_crt.push_back({ dll, outdated_crt });
+ break;
+ }
+ }
+ }
+
+ 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(" %s: %s", btf.file.generic_string(), btf.outdated_crt.name);
+ }
+ System::println("");
+
+ System::println(System::color::warning, "To inspect the dll files, use:\n dumpbin.exe /dependents mydllfile.dll");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static lint_status check_no_files_in_package_dir_and_debug_dir(const fs::path& package_dir)
+ {
+ std::vector<fs::path> misplaced_files;
+
+ Files::non_recursive_find_matching_paths_in_dir(package_dir, [](const fs::path& current)
+ {
+ const std::string filename = current.filename().generic_string();
+ return !fs::is_directory(current) && !((_stricmp(filename.c_str(), "CONTROL") == 0 || _stricmp(filename.c_str(), "BUILD_INFO") == 0));
+ }, &misplaced_files);
+
+ const fs::path debug_dir = package_dir / "debug";
+ Files::non_recursive_find_all_files_in_dir(debug_dir, &misplaced_files);
+
+ if (!misplaced_files.empty())
+ {
+ System::println(System::color::warning, "The following files are placed in\n%s and\n%s: ", package_dir.generic_string(), debug_dir.generic_string());
+ Files::print_paths(misplaced_files);
+ System::println(System::color::warning, "Files cannot be present in those directories.\n");
+ return lint_status::ERROR_DETECTED;
+ }
+
+ return lint_status::SUCCESS;
+ }
+
+ static void operator +=(size_t& left, const lint_status& right)
+ {
+ left += static_cast<size_t>(right);
+ }
+
+ template <class T>
+ static bool contains_and_enabled(const std::map<T, opt_bool_t> map, const T& key)
+ {
+ auto it = map.find(key);
+ if (it != map.cend() && it->second == opt_bool_t::ENABLED)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ static size_t perform_all_checks_and_return_error_count(const package_spec& spec, const vcpkg_paths& paths)
+ {
+ const fs::path dumpbin_exe = Environment::get_dumpbin_exe(paths);
+
+ BuildInfo build_info = read_build_info(paths.build_info_file_path(spec));
+ const fs::path package_dir = paths.package_dir(spec);
+
+ size_t error_count = 0;
+
+ if (contains_and_enabled(build_info.policies, BuildPolicies::EMPTY_PACKAGE))
+ {
+ return error_count;
+ }
+
+ error_count += check_for_files_in_include_directory(package_dir);
+ error_count += check_for_files_in_debug_include_directory(package_dir);
+ error_count += check_for_files_in_debug_share_directory(package_dir);
+ error_count += check_folder_lib_cmake(package_dir);
+ error_count += check_for_misplaced_cmake_files(package_dir, spec);
+ error_count += check_folder_debug_lib_cmake(package_dir);
+ error_count += check_for_dlls_in_lib_dirs(package_dir);
+ error_count += check_for_copyright_file(spec, paths);
+ error_count += check_for_exes(package_dir);
+
+ const fs::path debug_lib_dir = package_dir / "debug" / "lib";
+ const fs::path release_lib_dir = package_dir / "lib";
+ const fs::path debug_bin_dir = package_dir / "debug" / "bin";
+ const fs::path release_bin_dir = package_dir / "bin";
+
+ const std::vector<fs::path> debug_libs = Files::recursive_find_files_with_extension_in_dir(debug_lib_dir, ".lib");
+ const std::vector<fs::path> release_libs = Files::recursive_find_files_with_extension_in_dir(release_lib_dir, ".lib");
+
+ error_count += check_matching_debug_and_release_binaries(debug_libs, release_libs);
+
+ std::vector<fs::path> libs;
+ libs.insert(libs.cend(), debug_libs.cbegin(), debug_libs.cend());
+ libs.insert(libs.cend(), release_libs.cbegin(), release_libs.cend());
+
+ error_count += check_lib_architecture(spec.target_triplet().architecture(), libs);
+
+ switch (build_info.library_linkage)
+ {
+ case LinkageType::backing_enum_t::DYNAMIC:
+ {
+ const std::vector<fs::path> debug_dlls = Files::recursive_find_files_with_extension_in_dir(debug_bin_dir, ".dll");
+ const std::vector<fs::path> release_dlls = Files::recursive_find_files_with_extension_in_dir(release_bin_dir, ".dll");
+
+ error_count += check_matching_debug_and_release_binaries(debug_dlls, release_dlls);
+
+ error_count += check_lib_files_are_available_if_dlls_are_available(build_info.policies, debug_libs.size(), debug_dlls.size(), debug_lib_dir);
+ error_count += check_lib_files_are_available_if_dlls_are_available(build_info.policies, release_libs.size(), release_dlls.size(), release_lib_dir);
+
+ std::vector<fs::path> dlls;
+ dlls.insert(dlls.cend(), debug_dlls.cbegin(), debug_dlls.cend());
+ dlls.insert(dlls.cend(), release_dlls.cbegin(), release_dlls.cend());
+
+ error_count += check_exports_of_dlls(dlls, dumpbin_exe);
+ error_count += check_uwp_bit_of_dlls(spec.target_triplet().system(), dlls, dumpbin_exe);
+ error_count += check_dll_architecture(spec.target_triplet().architecture(), dlls);
+
+ error_count += check_outdated_crt_linkage_of_dlls(dlls, dumpbin_exe);
+ break;
+ }
+ case LinkageType::backing_enum_t::STATIC:
+ {
+ std::vector<fs::path> dlls;
+ Files::recursive_find_files_with_extension_in_dir(package_dir, ".dll", &dlls);
+ error_count += check_no_dlls_present(dlls);
+
+ error_count += check_bin_folders_are_not_present_in_static_build(package_dir);
+
+ if (!contains_and_enabled(build_info.policies, BuildPolicies::ONLY_RELEASE_CRT))
+ {
+ error_count += check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::DEBUG, build_info.crt_linkage), debug_libs, dumpbin_exe);
+ }
+ error_count += check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::RELEASE, build_info.crt_linkage), release_libs, dumpbin_exe);
+ break;
+ }
+ case LinkageType::backing_enum_t::NULLVALUE:
+ default:
+ Checks::unreachable();
+ }
+
+ error_count += check_no_empty_folders(package_dir);
+ error_count += check_no_files_in_package_dir_and_debug_dir(package_dir);
+
+ return error_count;
+ }
+
+ size_t perform_all_checks(const package_spec& spec, const vcpkg_paths& paths)
+ {
+ System::println("-- Performing post-build validation");
+ const size_t error_count = perform_all_checks_and_return_error_count(spec, paths);
+ System::println("-- Performing post-build validation done");
+
+ if (error_count != 0)
+ {
+ const fs::path portfile = paths.ports / spec.name() / "portfile.cmake";
+ System::println(System::color::error, "Found %u error(s). Please correct the portfile:\n %s", error_count, portfile.string());
+ }
+
+ return error_count;
+ }
+}
diff --git a/toolsrc/src/PostBuildLint_BuildInfo.cpp b/toolsrc/src/PostBuildLint_BuildInfo.cpp
new file mode 100644
index 000000000..0d1d480b8
--- /dev/null
+++ b/toolsrc/src/PostBuildLint_BuildInfo.cpp
@@ -0,0 +1,48 @@
+#include "pch.h"
+#include "PostBuildLint_BuildInfo.h"
+#include "vcpkg_Checks.h"
+#include "opt_bool.h"
+#include "vcpkglib_helpers.h"
+#include "Paragraphs.h"
+
+namespace vcpkg::PostBuildLint
+{
+ //
+ namespace BuildInfoRequiredField
+ {
+ static const std::string CRT_LINKAGE = "CRTLinkage";
+ static const std::string LIBRARY_LINKAGE = "LibraryLinkage";
+ }
+
+ BuildInfo BuildInfo::create(std::unordered_map<std::string, std::string> pgh)
+ {
+ BuildInfo build_info;
+ const std::string crt_linkage_as_string = details::remove_required_field(&pgh, BuildInfoRequiredField::CRT_LINKAGE);
+ build_info.crt_linkage = LinkageType::value_of(crt_linkage_as_string);
+ Checks::check_exit(build_info.crt_linkage != LinkageType::NULLVALUE, "Invalid crt linkage type: [%s]", crt_linkage_as_string);
+
+ const std::string library_linkage_as_string = details::remove_required_field(&pgh, BuildInfoRequiredField::LIBRARY_LINKAGE);
+ build_info.library_linkage = LinkageType::value_of(library_linkage_as_string);
+ Checks::check_exit(build_info.library_linkage != LinkageType::NULLVALUE, "Invalid library linkage type: [%s]", library_linkage_as_string);
+
+ // The remaining entries are policies
+ for (const std::unordered_map<std::string, std::string>::value_type& p : pgh)
+ {
+ const BuildPolicies::type policy = BuildPolicies::parse(p.first);
+ Checks::check_exit(policy != BuildPolicies::NULLVALUE, "Unknown policy found: %s", p.first);
+ const opt_bool_t status = opt_bool::parse(p.second);
+ build_info.policies.emplace(policy, status);
+ }
+
+ return build_info;
+ }
+
+ BuildInfo read_build_info(const fs::path& filepath)
+ {
+ const std::vector<std::unordered_map<std::string, std::string>> pghs = Paragraphs::get_paragraphs(filepath);
+ Checks::check_exit(pghs.size() == 1, "Invalid BUILD_INFO file for package");
+
+ return BuildInfo::create(pghs[0]);
+ }
+
+}
diff --git a/toolsrc/src/PostBuildLint_BuildPolicies.cpp b/toolsrc/src/PostBuildLint_BuildPolicies.cpp
new file mode 100644
index 000000000..f070a2a42
--- /dev/null
+++ b/toolsrc/src/PostBuildLint_BuildPolicies.cpp
@@ -0,0 +1,70 @@
+#include "pch.h"
+#include "PostBuildLint_BuildPolicies.h"
+#include "vcpkg_Enums.h"
+
+namespace vcpkg::PostBuildLint::BuildPolicies
+{
+ static const std::string NULLVALUE_STRING = Enums::nullvalue_toString(ENUM_NAME);
+
+ static const std::string NAME_EMPTY_PACKAGE = "PolicyEmptyPackage";
+ static const std::string NAME_DLLS_WITHOUT_LIBS = "PolicyDLLsWithoutLIBs";
+ static const std::string NAME_ONLY_RELEASE_CRT = "PolicyOnlyReleaseCRT";
+
+ const std::string& type::toString() const
+ {
+ switch (this->backing_enum)
+ {
+ case EMPTY_PACKAGE:
+ return NAME_EMPTY_PACKAGE;
+ case DLLS_WITHOUT_LIBS:
+ return NAME_DLLS_WITHOUT_LIBS;
+ case ONLY_RELEASE_CRT:
+ return NAME_ONLY_RELEASE_CRT;
+ case NULLVALUE:
+ return NULLVALUE_STRING;
+ default:
+ Enums::unreachable(ENUM_NAME);
+ }
+ }
+
+ const std::string& type::cmake_variable() const
+ {
+ static const std::string CMAKE_VARIABLE_EMPTY_PACKAGE = "VCPKG_POLICY_EMPTY_PACKAGE";
+ static const std::string CMAKE_VARIABLE_DLLS_WITHOUT_LIBS = "VCPKG_POLICY_DLLS_WITHOUT_LIBS";
+ static const std::string CMAKE_VARIABLE_ONLY_RELEASE_CRT = "VCPKG_POLICY_ONLY_RELEASE_CRT";
+
+ switch (this->backing_enum)
+ {
+ case EMPTY_PACKAGE:
+ return CMAKE_VARIABLE_EMPTY_PACKAGE;
+ case DLLS_WITHOUT_LIBS:
+ return CMAKE_VARIABLE_DLLS_WITHOUT_LIBS;
+ case ONLY_RELEASE_CRT:
+ return CMAKE_VARIABLE_ONLY_RELEASE_CRT;
+ case NULLVALUE:
+ Enums::nullvalue_used(ENUM_NAME);
+ default:
+ Enums::unreachable(ENUM_NAME);
+ }
+ }
+
+ type parse(const std::string& s)
+ {
+ if (s == NAME_EMPTY_PACKAGE)
+ {
+ return BuildPolicies::EMPTY_PACKAGE;
+ }
+
+ if (s == NAME_DLLS_WITHOUT_LIBS)
+ {
+ return BuildPolicies::DLLS_WITHOUT_LIBS;
+ }
+
+ if (s == NAME_ONLY_RELEASE_CRT)
+ {
+ return BuildPolicies::ONLY_RELEASE_CRT;
+ }
+
+ return BuildPolicies::NULLVALUE;
+ }
+}
diff --git a/toolsrc/src/PostBuildLint_BuildType.cpp b/toolsrc/src/PostBuildLint_BuildType.cpp
new file mode 100644
index 000000000..f2fb292d7
--- /dev/null
+++ b/toolsrc/src/PostBuildLint_BuildType.cpp
@@ -0,0 +1,85 @@
+#include "pch.h"
+#include "PostBuildLint_BuildType.h"
+#include "vcpkg_Enums.h"
+
+namespace vcpkg::PostBuildLint::BuildType
+{
+ type value_of(const ConfigurationType::type& config, const LinkageType::type& linkage)
+ {
+ if (config == ConfigurationType::DEBUG && linkage == LinkageType::STATIC)
+ {
+ return DEBUG_STATIC;
+ }
+
+ if (config == ConfigurationType::DEBUG && linkage == LinkageType::DYNAMIC)
+ {
+ return DEBUG_DYNAMIC;
+ }
+
+ if (config == ConfigurationType::RELEASE && linkage == LinkageType::STATIC)
+ {
+ return RELEASE_STATIC;
+ }
+
+ if (config == ConfigurationType::RELEASE && linkage == LinkageType::DYNAMIC)
+ {
+ return RELEASE_DYNAMIC;
+ }
+
+ Enums::unreachable(ENUM_NAME);
+ }
+
+ const ConfigurationType::type& type::config() const
+ {
+ return this->m_config;
+ }
+
+ const LinkageType::type& type::linkage() const
+ {
+ return this->m_linkage;
+ }
+
+ const std::regex& type::crt_regex() const
+ {
+ static const std::regex REGEX_DEBUG_STATIC(R"(/DEFAULTLIB:LIBCMTD)", std::regex_constants::icase);
+ static const std::regex REGEX_DEBUG_DYNAMIC(R"(/DEFAULTLIB:MSVCRTD)", std::regex_constants::icase);
+ static const std::regex REGEX_RELEASE_STATIC(R"(/DEFAULTLIB:LIBCMT[^D])", std::regex_constants::icase);
+ static const std::regex REGEX_RELEASE_DYNAMIC(R"(/DEFAULTLIB:MSVCRT[^D])", std::regex_constants::icase);
+
+ switch (backing_enum)
+ {
+ case BuildType::DEBUG_STATIC:
+ return REGEX_DEBUG_STATIC;
+ case BuildType::DEBUG_DYNAMIC:
+ return REGEX_DEBUG_DYNAMIC;
+ case BuildType::RELEASE_STATIC:
+ return REGEX_RELEASE_STATIC;
+ case BuildType::RELEASE_DYNAMIC:
+ return REGEX_RELEASE_DYNAMIC;
+ default:
+ Enums::unreachable(ENUM_NAME);
+ }
+ }
+
+ const std::string& type::toString() const
+ {
+ static const std::string NAME_DEBUG_STATIC("Debug,Static");
+ static const std::string NAME_DEBUG_DYNAMIC("Debug,Dynamic");
+ static const std::string NAME_RELEASE_STATIC("Release,Static");
+ static const std::string NAME_RELEASE_DYNAMIC("Release,Dynamic");
+
+ switch (backing_enum)
+ {
+ case BuildType::DEBUG_STATIC:
+ return NAME_DEBUG_STATIC;
+ case BuildType::DEBUG_DYNAMIC:
+ return NAME_DEBUG_DYNAMIC;
+ case BuildType::RELEASE_STATIC:
+ return NAME_RELEASE_STATIC;
+ case BuildType::RELEASE_DYNAMIC:
+ return NAME_RELEASE_DYNAMIC;
+ default:
+ Enums::unreachable(ENUM_NAME);
+ }
+ }
+}
diff --git a/toolsrc/src/PostBuildLint_ConfigurationType.cpp b/toolsrc/src/PostBuildLint_ConfigurationType.cpp
new file mode 100644
index 000000000..990b10a37
--- /dev/null
+++ b/toolsrc/src/PostBuildLint_ConfigurationType.cpp
@@ -0,0 +1,26 @@
+#include "pch.h"
+#include "PostBuildLint_ConfigurationType.h"
+#include "vcpkg_Enums.h"
+
+namespace vcpkg::PostBuildLint::ConfigurationType
+{
+ static const std::string NULLVALUE_STRING = Enums::nullvalue_toString(ENUM_NAME);
+
+ static const std::string NAME_DEBUG = "Debug";
+ static const std::string NAME_RELEASE = "Release";
+
+ const std::string& type::toString() const
+ {
+ switch (this->backing_enum)
+ {
+ case ConfigurationType::DEBUG:
+ return NAME_DEBUG;
+ case ConfigurationType::RELEASE:
+ return NAME_RELEASE;
+ case ConfigurationType::NULLVALUE:
+ return NULLVALUE_STRING;
+ default:
+ Enums::unreachable(ENUM_NAME);
+ }
+ }
+}
diff --git a/toolsrc/src/PostBuildLint_LinkageType.cpp b/toolsrc/src/PostBuildLint_LinkageType.cpp
new file mode 100644
index 000000000..6d2c2c935
--- /dev/null
+++ b/toolsrc/src/PostBuildLint_LinkageType.cpp
@@ -0,0 +1,41 @@
+#include "pch.h"
+#include "PostBuildLint_LinkageType.h"
+#include "vcpkg_Enums.h"
+
+namespace vcpkg::PostBuildLint::LinkageType
+{
+ static const std::string NULLVALUE_STRING = Enums::nullvalue_toString(ENUM_NAME);
+
+ static const std::string NAME_DYNAMIC = "dynamic";
+ static const std::string NAME_STATIC = "static";
+
+ const std::string& type::toString() const
+ {
+ switch (this->backing_enum)
+ {
+ case LinkageType::DYNAMIC:
+ return NAME_DYNAMIC;
+ case LinkageType::STATIC:
+ return NAME_STATIC;
+ case LinkageType::NULLVALUE:
+ return NULLVALUE_STRING;
+ default:
+ Enums::unreachable(ENUM_NAME);
+ }
+ }
+
+ type value_of(const std::string& as_string)
+ {
+ if (as_string == NAME_DYNAMIC)
+ {
+ return LinkageType::DYNAMIC;
+ }
+
+ if (as_string == NAME_STATIC)
+ {
+ return LinkageType::STATIC;
+ }
+
+ return LinkageType::NULLVALUE;
+ }
+}
diff --git a/toolsrc/src/SourceParagraph.cpp b/toolsrc/src/SourceParagraph.cpp
index 7e3b0403e..4d144191f 100644
--- a/toolsrc/src/SourceParagraph.cpp
+++ b/toolsrc/src/SourceParagraph.cpp
@@ -1,21 +1,145 @@
+#include "pch.h"
#include "SourceParagraph.h"
#include "vcpkglib_helpers.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Maps.h"
+#include "triplet.h"
-using namespace vcpkg::details;
+namespace vcpkg
+{
+ //
+ namespace SourceParagraphRequiredField
+ {
+ static const std::string SOURCE = "Source";
+ static const std::string VERSION = "Version";
+ }
-vcpkg::SourceParagraph::SourceParagraph() = default;
+ namespace SourceParagraphOptionalField
+ {
+ static const std::string DESCRIPTION = "Description";
+ static const std::string MAINTAINER = "Maintainer";
+ static const std::string BUILD_DEPENDS = "Build-Depends";
+ }
-vcpkg::SourceParagraph::SourceParagraph(const std::unordered_map<std::string, std::string>& fields)
-{
- required_field(fields, name, "Source");
- required_field(fields, version, "Version");
- optional_field(fields, description, "Description");
- std::string deps;
- optional_field(fields, deps, "Build-Depends");
- if (!deps.empty())
+ static const std::vector<std::string>& get_list_of_valid_fields()
+ {
+ static const std::vector<std::string> valid_fields =
+ {
+ SourceParagraphRequiredField::SOURCE,
+ SourceParagraphRequiredField::VERSION,
+
+ SourceParagraphOptionalField::DESCRIPTION,
+ SourceParagraphOptionalField::MAINTAINER,
+ SourceParagraphOptionalField::BUILD_DEPENDS
+ };
+
+ return valid_fields;
+ }
+
+ SourceParagraph::SourceParagraph() = default;
+
+ SourceParagraph::SourceParagraph(std::unordered_map<std::string, std::string> fields)
+ {
+ this->name = details::remove_required_field(&fields, SourceParagraphRequiredField::SOURCE);
+ this->version = details::remove_required_field(&fields, SourceParagraphRequiredField::VERSION);
+ this->description = details::remove_optional_field(&fields, SourceParagraphOptionalField::DESCRIPTION);
+ this->maintainer = details::remove_optional_field(&fields, SourceParagraphOptionalField::MAINTAINER);
+
+ std::string deps = details::remove_optional_field(&fields, SourceParagraphOptionalField::BUILD_DEPENDS);
+ this->depends = expand_qualified_dependencies(parse_depends(deps));
+
+ if (!fields.empty())
+ {
+ const std::vector<std::string> remaining_fields = Maps::extract_keys(fields);
+ const std::vector<std::string>& valid_fields = get_list_of_valid_fields();
+
+ const std::string remaining_fields_as_string = Strings::join("\n ", remaining_fields);
+ const std::string valid_fields_as_string = Strings::join("\n ", valid_fields);
+
+ System::println(System::color::error, "Error: There are invalid fields in the Source Paragraph of %s", this->name);
+ System::println("The following fields were not expected:\n\n %s\n\n", remaining_fields_as_string);
+ System::println("This is the list of valid fields (case-sensitive): \n\n %s\n", valid_fields_as_string);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ std::vector<dependency> vcpkg::expand_qualified_dependencies(const std::vector<std::string>& depends)
+ {
+ auto convert = [&](const std::string& depend_string) -> dependency {
+ auto pos = depend_string.find(' ');
+ if (pos == std::string::npos)
+ return{ depend_string, "" };
+ // 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] != ']')
+ {
+ // Error, but for now just slurp the entire string.
+ return{ depend_string, "" };
+ }
+ dep.qualifier = depend_string.substr(pos + 2, depend_string.size() - pos - 3);
+ return dep;
+ };
+
+ std::vector<vcpkg::dependency> ret;
+
+ for (auto&& depend_string : depends)
+ {
+ ret.push_back(convert(depend_string));
+ }
+
+ return ret;
+ }
+
+ std::vector<std::string> parse_depends(const std::string& depends_string)
+ {
+ if (depends_string.empty())
+ {
+ return{};
+ }
+
+ std::vector<std::string> out;
+
+ size_t cur = 0;
+ do
+ {
+ auto pos = depends_string.find(',', cur);
+ if (pos == std::string::npos)
+ {
+ out.push_back(depends_string.substr(cur));
+ break;
+ }
+ out.push_back(depends_string.substr(cur, pos - cur));
+
+ // skip comma and space
+ ++pos;
+ if (depends_string[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;
+ for (auto&& dep : deps)
+ {
+ if (dep.qualifier.empty() || t.canonical_name().find(dep.qualifier) != std::string::npos)
+ {
+ ret.push_back(dep.name);
+ }
+ }
+ return ret;
+ }
+
+ std::ostream & operator<<(std::ostream & os, const dependency & p)
{
- depends.clear();
- parse_depends(deps, depends);
+ os << p.name;
+ return os;
}
- optional_field(fields, maintainer, "Maintainer");
}
diff --git a/toolsrc/src/StatusParagraph.cpp b/toolsrc/src/StatusParagraph.cpp
index 09a3b4d45..3f07689ca 100644
--- a/toolsrc/src/StatusParagraph.cpp
+++ b/toolsrc/src/StatusParagraph.cpp
@@ -1,3 +1,4 @@
+#include "pch.h"
#include "StatusParagraph.h"
#include "vcpkglib_helpers.h"
@@ -5,6 +6,12 @@ using namespace vcpkg::details;
namespace vcpkg
{
+ //
+ namespace BinaryParagraphRequiredField
+ {
+ static const std::string STATUS = "Status";
+ }
+
StatusParagraph::StatusParagraph() : want(want_t::error), state(install_state_t::error)
{
}
@@ -19,8 +26,7 @@ namespace vcpkg
StatusParagraph::StatusParagraph(const std::unordered_map<std::string, std::string>& fields)
: package(fields)
{
- std::string status_field;
- required_field(fields, status_field, "Status");
+ std::string status_field = required_field(fields, BinaryParagraphRequiredField::STATUS);
auto b = status_field.begin();
auto mark = b;
diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp
index 463e3e3b8..9a440fbb8 100644
--- a/toolsrc/src/StatusParagraphs.cpp
+++ b/toolsrc/src/StatusParagraphs.cpp
@@ -1,5 +1,5 @@
+#include "pch.h"
#include "StatusParagraphs.h"
-#include <algorithm>
#include "vcpkg_Checks.h"
namespace vcpkg
@@ -13,23 +13,25 @@ namespace vcpkg
StatusParagraphs::const_iterator StatusParagraphs::find(const std::string& name, const triplet& target_triplet) const
{
- return std::find_if(begin(), end(), [&](const auto& pgh)
+ return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh)
{
- return pgh->package.name == name && pgh->package.target_triplet == target_triplet;
+ const package_spec& spec = pgh->package.spec;
+ return spec.name() == name && spec.target_triplet() == target_triplet;
});
}
StatusParagraphs::iterator StatusParagraphs::find(const std::string& name, const triplet& target_triplet)
{
- return std::find_if(begin(), end(), [&](const auto& pgh)
+ return std::find_if(begin(), end(), [&](const std::unique_ptr<StatusParagraph>& pgh)
{
- return pgh->package.name == name && pgh->package.target_triplet == target_triplet;
+ const package_spec& spec = pgh->package.spec;
+ return spec.name() == name && spec.target_triplet() == target_triplet;
});
}
- StatusParagraphs::iterator StatusParagraphs::find_installed(const std::string& name, const triplet& target_triplet)
+ StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, const triplet& target_triplet) const
{
- auto it = find(name, target_triplet);
+ const const_iterator it = find(name, target_triplet);
if (it != end() && (*it)->want == want_t::install)
{
return it;
@@ -40,19 +42,18 @@ namespace vcpkg
StatusParagraphs::iterator StatusParagraphs::insert(std::unique_ptr<StatusParagraph> pgh)
{
- Checks::check_throw(pgh != nullptr, "Inserted null paragraph");
- auto ptr = find(pgh->package.name, pgh->package.target_triplet);
+ Checks::check_exit(pgh != nullptr, "Inserted null paragraph");
+ const package_spec& spec = pgh->package.spec;
+ auto ptr = find(spec.name(), spec.target_triplet());
if (ptr == end())
{
paragraphs.push_back(std::move(pgh));
return paragraphs.rbegin();
}
- else
- {
- // consume data from provided pgh.
- **ptr = std::move(*pgh);
- return ptr;
- }
+
+ // consume data from provided pgh.
+ **ptr = std::move(*pgh);
+ return ptr;
}
std::ostream& vcpkg::operator<<(std::ostream& os, const StatusParagraphs& l)
diff --git a/toolsrc/src/coff_file_reader.cpp b/toolsrc/src/coff_file_reader.cpp
new file mode 100644
index 000000000..f48f912c1
--- /dev/null
+++ b/toolsrc/src/coff_file_reader.cpp
@@ -0,0 +1,307 @@
+#include "pch.h"
+#include "coff_file_reader.h"
+#include "vcpkg_Checks.h"
+
+using namespace std;
+
+namespace vcpkg::COFFFileReader
+{
+ template <class T>
+ static T reinterpret_bytes(const char* data)
+ {
+ return (*reinterpret_cast<const T *>(&data[0]));
+ }
+
+ template <class T>
+ static T read_value_from_stream(fstream& fs)
+ {
+ T data;
+ fs.read(reinterpret_cast<char*>(&data), sizeof data);
+ return data;
+ }
+
+ template <class T>
+ static T peek_value_from_stream(fstream& fs)
+ {
+ fpos_t original_pos = fs.tellg().seekpos();
+ T data;
+ fs.read(reinterpret_cast<char*>(&data), sizeof data);
+ fs.seekg(original_pos);
+ return data;
+ }
+
+ static void verify_equal_strings(const char* expected, const char* actual, int size, const char* label)
+ {
+ Checks::check_exit(memcmp(expected, actual, size) == 0, "Incorrect string (%s) found. Expected: (%s) but found (%s)", label, expected, actual);
+ }
+
+ static void read_and_verify_PE_signature(fstream& fs)
+ {
+ static const size_t OFFSET_TO_PE_SIGNATURE_OFFSET = 0x3c;
+
+ static const char* PE_SIGNATURE = "PE\0\0";
+ static const size_t PE_SIGNATURE_SIZE = 4;
+
+ fs.seekg(OFFSET_TO_PE_SIGNATURE_OFFSET, ios_base::beg);
+ const int32_t offset_to_PE_signature = read_value_from_stream<int32_t>(fs);
+
+ fs.seekg(offset_to_PE_signature);
+ char signature[PE_SIGNATURE_SIZE];
+ fs.read(signature, PE_SIGNATURE_SIZE);
+ verify_equal_strings(PE_SIGNATURE, signature, PE_SIGNATURE_SIZE, "PE_SIGNATURE");
+ fs.seekg(offset_to_PE_signature + PE_SIGNATURE_SIZE, ios_base::beg);
+ }
+
+ static fpos_t align_to_size(const uint64_t unaligned, const uint64_t alignment_size)
+ {
+ fpos_t aligned = unaligned - 1;
+ aligned /= alignment_size;
+ aligned += 1;
+ aligned *= alignment_size;
+ return aligned;
+ }
+
+ struct coff_file_header
+ {
+ static const size_t HEADER_SIZE = 20;
+
+ static coff_file_header read(fstream& fs)
+ {
+ coff_file_header ret;
+ ret.data.resize(HEADER_SIZE);
+ fs.read(&ret.data[0], HEADER_SIZE);
+ return ret;
+ }
+
+ MachineType machineType() const
+ {
+ static const size_t MACHINE_TYPE_OFFSET = 0;
+ static const size_t MACHINE_TYPE_SIZE = 2;
+
+ std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE);
+ const uint16_t machine = reinterpret_bytes<uint16_t>(machine_field_as_string.c_str());
+ return getMachineType(machine);
+ }
+
+ private:
+ std::string data;
+ };
+
+ struct archive_member_header
+ {
+ static const size_t HEADER_SIZE = 60;
+
+ static archive_member_header read(fstream& fs)
+ {
+ static const size_t HEADER_END_OFFSET = 58;
+ static const char* HEADER_END = "`\n";
+ static const size_t HEADER_END_SIZE = 2;
+
+ archive_member_header ret;
+ ret.data.resize(HEADER_SIZE);
+ fs.read(&ret.data[0], HEADER_SIZE);
+
+ if (ret.data[0] != '\0') // Due to freeglut. github issue #223
+ {
+ const std::string header_end = ret.data.substr(HEADER_END_OFFSET, HEADER_END_SIZE);
+ verify_equal_strings(HEADER_END, header_end.c_str(), HEADER_END_SIZE, "LIB HEADER_END");
+ }
+
+ return ret;
+ }
+
+ std::string name() const
+ {
+ static const size_t HEADER_NAME_OFFSET = 0;
+ static const size_t HEADER_NAME_SIZE = 16;
+ return data.substr(HEADER_NAME_OFFSET, HEADER_NAME_SIZE);
+ }
+
+ uint64_t member_size() const
+ {
+ static const size_t ALIGNMENT_SIZE = 2;
+
+ static const size_t HEADER_SIZE_OFFSET = 48;
+ static const size_t HEADER_SIZE_FIELD_SIZE = 10;
+ const std::string as_string = data.substr(HEADER_SIZE_OFFSET, HEADER_SIZE_FIELD_SIZE);
+ // This is in ASCII decimal representation
+ const uint64_t value = std::strtoull(as_string.c_str(), nullptr, 10);
+
+ const uint64_t aligned = align_to_size(value, ALIGNMENT_SIZE);
+ return aligned;
+ }
+
+ std::string data;
+ };
+
+ struct offsets_array
+ {
+ static offsets_array read(fstream& fs, const uint32_t offset_count)
+ {
+ static const size_t OFFSET_WIDTH = 4;
+
+ std::string raw_offsets;
+ const size_t raw_offset_size = offset_count * OFFSET_WIDTH;
+ raw_offsets.resize(raw_offset_size);
+ fs.read(&raw_offsets[0], raw_offset_size);
+
+ offsets_array ret;
+ for (uint32_t i = 0; i < offset_count; ++i)
+ {
+ const std::string value_as_string = raw_offsets.substr(OFFSET_WIDTH * i, OFFSET_WIDTH * (i + 1));
+ const uint32_t value = reinterpret_bytes<uint32_t>(value_as_string.c_str());
+
+ // Ignore offsets that point to offset 0. See vcpkg github #223 #288 #292
+ if (value != 0)
+ {
+ ret.data.push_back(value);
+ }
+ }
+
+ // Sort the offsets, because it is possible for them to be unsorted. See vcpkg github #292
+ std::sort(ret.data.begin(), ret.data.end());
+ return ret;
+ }
+
+ std::vector<uint32_t> data;
+ };
+
+ struct import_header
+ {
+ static const size_t HEADER_SIZE = 20;
+
+ static import_header read(fstream& fs)
+ {
+ static const size_t SIG1_OFFSET = 0;
+ static const uint16_t SIG1 = static_cast<uint16_t>(MachineType::UNKNOWN);
+ static const size_t SIG1_SIZE = 2;
+
+ static const size_t SIG2_OFFSET = 2;
+ static const uint16_t SIG2 = 0xFFFF;
+ static const size_t SIG2_SIZE = 2;
+
+ import_header ret;
+ ret.data.resize(HEADER_SIZE);
+ fs.read(&ret.data[0], HEADER_SIZE);
+
+ const std::string sig1_as_string = ret.data.substr(SIG1_OFFSET, SIG1_SIZE);
+ const uint16_t sig1 = reinterpret_bytes<uint16_t>(sig1_as_string.c_str());
+ Checks::check_exit(sig1 == SIG1, "Sig1 was incorrect. Expected %s but got %s", SIG1, sig1);
+
+ const std::string sig2_as_string = ret.data.substr(SIG2_OFFSET, SIG2_SIZE);
+ const uint16_t sig2 = reinterpret_bytes<uint16_t>(sig2_as_string.c_str());
+ Checks::check_exit(sig2 == SIG2, "Sig2 was incorrect. Expected %s but got %s", SIG2, sig2);
+
+ return ret;
+ }
+
+ MachineType machineType() const
+ {
+ static const size_t MACHINE_TYPE_OFFSET = 6;
+ static const size_t MACHINE_TYPE_SIZE = 2;
+
+ std::string machine_field_as_string = data.substr(MACHINE_TYPE_OFFSET, MACHINE_TYPE_SIZE);
+ const uint16_t machine = reinterpret_bytes<uint16_t>(machine_field_as_string.c_str());
+ return getMachineType(machine);
+ }
+
+ private:
+ std::string data;
+ };
+
+ static void read_and_verify_archive_file_signature(fstream& fs)
+ {
+ static const char* FILE_START = "!<arch>\n";
+ static const size_t FILE_START_SIZE = 8;
+
+ fs.seekg(fs.beg);
+
+ char file_start[FILE_START_SIZE];
+ fs.read(file_start, FILE_START_SIZE);
+ verify_equal_strings(FILE_START, file_start, FILE_START_SIZE, "LIB FILE_START");
+ }
+
+ dll_info read_dll(const fs::path& path)
+ {
+ std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate);
+ Checks::check_exit(fs.is_open(), "Could not open file %s for reading", path.generic_string());
+
+ read_and_verify_PE_signature(fs);
+ coff_file_header header = coff_file_header::read(fs);
+ MachineType machine = header.machineType();
+ return {machine};
+ }
+
+ struct marker_t
+ {
+ void set_to_offset(const fpos_t position)
+ {
+ this->m_absolute_position = position;
+ }
+
+ void set_to_current_pos(fstream& fs)
+ {
+ this->m_absolute_position = fs.tellg().seekpos();
+ }
+
+ void seek_to_marker(fstream& fs) const
+ {
+ fs.seekg(this->m_absolute_position, ios_base::beg);
+ }
+
+ void advance_by(const uint64_t offset)
+ {
+ this->m_absolute_position += offset;
+ }
+
+ private:
+ fpos_t m_absolute_position = 0;
+ };
+
+ lib_info read_lib(const fs::path& path)
+ {
+ std::fstream fs(path, std::ios::in | std::ios::binary | std::ios::ate);
+ Checks::check_exit(fs.is_open(), "Could not open file %s for reading", path.generic_string());
+
+ read_and_verify_archive_file_signature(fs);
+
+ marker_t marker;
+ marker.set_to_current_pos(fs);
+
+ // First Linker Member
+ const archive_member_header first_linker_member_header = archive_member_header::read(fs);
+ Checks::check_exit(first_linker_member_header.name().substr(0, 2) == "/ ", "Could not find proper first linker member");
+ marker.advance_by(archive_member_header::HEADER_SIZE + first_linker_member_header.member_size());
+ marker.seek_to_marker(fs);
+
+ const archive_member_header second_linker_member_header = archive_member_header::read(fs);
+ Checks::check_exit(second_linker_member_header.name().substr(0, 2) == "/ ", "Could not find proper second linker member");
+ // The first 4 bytes contains the number of archive members
+ const uint32_t archive_member_count = read_value_from_stream<uint32_t>(fs);
+ const offsets_array offsets = offsets_array::read(fs, archive_member_count);
+ marker.advance_by(archive_member_header::HEADER_SIZE + second_linker_member_header.member_size());
+ marker.seek_to_marker(fs);
+
+ bool hasLongnameMemberHeader = peek_value_from_stream<uint16_t>(fs) == 0x2F2F;
+ if (hasLongnameMemberHeader)
+ {
+ const archive_member_header longnames_member_header = archive_member_header::read(fs);
+ marker.advance_by(archive_member_header::HEADER_SIZE + longnames_member_header.member_size());
+ marker.seek_to_marker(fs);
+ }
+
+ std::set<MachineType> machine_types;
+ // Next we have the obj and pseudo-object files
+ for (const uint32_t offset : offsets.data)
+ {
+ marker.set_to_offset(offset + archive_member_header::HEADER_SIZE); // Skip the header, no need to read it.
+ marker.seek_to_marker(fs);
+ const uint16_t first_two_bytes = peek_value_from_stream<uint16_t>(fs);
+ const bool isImportHeader = getMachineType(first_two_bytes) == MachineType::UNKNOWN;
+ const MachineType machine = isImportHeader ? import_header::read(fs).machineType() : coff_file_header::read(fs).machineType();
+ machine_types.insert(machine);
+ }
+
+ return {std::vector<MachineType>(machine_types.cbegin(), machine_types.cend())};
+ }
+}
diff --git a/toolsrc/src/commands_available_commands.cpp b/toolsrc/src/commands_available_commands.cpp
new file mode 100644
index 000000000..4c7e0df2c
--- /dev/null
+++ b/toolsrc/src/commands_available_commands.cpp
@@ -0,0 +1,46 @@
+#include "pch.h"
+#include "vcpkg_Commands.h"
+
+namespace vcpkg::Commands
+{
+ const std::vector<package_name_and_function<command_type_a>>& get_available_commands_type_a()
+ {
+ static std::vector<package_name_and_function<command_type_a>> t = {
+ {"install", &Install::perform_and_exit},
+ { "ci", &CI::perform_and_exit },
+ {"remove", &Remove::perform_and_exit},
+ {"build", &Build::perform_and_exit},
+ {"build_external", &BuildExternal::perform_and_exit}
+ };
+ return t;
+ }
+
+ const std::vector<package_name_and_function<command_type_b>>& get_available_commands_type_b()
+ {
+ static std::vector<package_name_and_function<command_type_b>> t = {
+ {"/?", &Help::perform_and_exit},
+ {"help", &Help::perform_and_exit},
+ {"search", &Search::perform_and_exit},
+ {"list", &List::perform_and_exit},
+ {"integrate", &Integrate::perform_and_exit},
+ {"owns", &Owns::perform_and_exit},
+ {"update", &Update::perform_and_exit},
+ {"edit", &Edit::perform_and_exit},
+ {"create", &Create::perform_and_exit},
+ {"import", &Import::perform_and_exit},
+ {"cache", &Cache::perform_and_exit},
+ {"portsdiff", &PortsDiff::perform_and_exit}
+ };
+ return t;
+ }
+
+ const std::vector<package_name_and_function<command_type_c>>& get_available_commands_type_c()
+ {
+ static std::vector<package_name_and_function<command_type_c>> t = {
+ {"version", &Version::perform_and_exit},
+ {"contact", &Contact::perform_and_exit},
+ {"hash", &Hash::perform_and_exit},
+ };
+ return t;
+ }
+}
diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp
new file mode 100644
index 000000000..a47083cbd
--- /dev/null
+++ b/toolsrc/src/commands_build.cpp
@@ -0,0 +1,183 @@
+#include "pch.h"
+#include "vcpkg_Commands.h"
+#include "StatusParagraphs.h"
+#include "vcpkglib.h"
+#include "vcpkg_Input.h"
+#include "PostBuildLint.h"
+#include "vcpkg_Dependencies.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Chrono.h"
+#include "vcpkg_Environment.h"
+#include "metrics.h"
+#include "vcpkg_Enums.h"
+#include "Paragraphs.h"
+
+namespace vcpkg::Commands::Build
+{
+ using Dependencies::package_spec_with_install_plan;
+ using Dependencies::install_plan_type;
+
+ static const std::string OPTION_CHECKS_ONLY = "--checks-only";
+
+ static void create_binary_control_file(const vcpkg_paths& paths, const SourceParagraph& source_paragraph, const triplet& target_triplet)
+ {
+ const BinaryParagraph bpgh = BinaryParagraph(source_paragraph, target_triplet);
+ const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL";
+ std::ofstream(binary_control_file) << bpgh;
+ }
+
+ BuildResult build_package(const SourceParagraph& source_paragraph, const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir, const StatusParagraphs& status_db)
+ {
+ Checks::check_exit(spec.name() == source_paragraph.name, "inconsistent arguments to build_package()");
+
+ const triplet& target_triplet = spec.target_triplet();
+ for (auto&& dep : source_paragraph.depends)
+ {
+ if (status_db.find_installed(dep.name, target_triplet) == status_db.end())
+ {
+ return BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES;
+ }
+ }
+
+ const fs::path& cmake_exe_path = paths.get_cmake_exe();
+ const fs::path& git_exe_path = paths.get_git_exe();
+
+ const fs::path ports_cmake_script_path = paths.ports_cmake;
+ const Environment::vcvarsall_and_platform_toolset vcvarsall_bat = Environment::get_vcvarsall_bat(paths);
+ const std::wstring cmd_set_environment = Strings::wformat(LR"("%s" %s >nul 2>&1)", vcvarsall_bat.path.native(), Strings::utf8_to_utf16(target_triplet.architecture()));
+
+ const std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe_path, ports_cmake_script_path,
+ {
+ { L"CMD", L"BUILD" },
+ { L"PORT", source_paragraph.name },
+ { L"CURRENT_PORT_DIR", port_dir / "/." },
+ { L"TARGET_TRIPLET", target_triplet.canonical_name() },
+ { L"VCPKG_PLATFORM_TOOLSET", vcvarsall_bat.platform_toolset },
+ { L"GIT", git_exe_path }
+ });
+
+ const std::wstring command = Strings::wformat(LR"(%s && %s)", cmd_set_environment, cmd_launch_cmake);
+
+ const ElapsedTime timer = ElapsedTime::createStarted();
+
+ int return_code = System::cmd_execute_clean(command);
+ auto buildtimeus = timer.microseconds();
+ TrackMetric("buildtimeus-" + spec.toString(), buildtimeus);
+
+ if (return_code != 0)
+ {
+ TrackProperty("error", "build failed");
+ TrackProperty("build_error", spec.toString());
+ return BuildResult::BUILD_FAILED;
+ }
+
+ const size_t error_count = PostBuildLint::perform_all_checks(spec, paths);
+
+ if (error_count != 0)
+ {
+ return BuildResult::POST_BUILD_CHECKS_FAILED;
+ }
+
+ create_binary_control_file(paths, source_paragraph, target_triplet);
+
+ // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name;
+ // delete_directory(port_buildtrees_dir);
+
+ return BuildResult::SUCCEEDED;
+ }
+
+ const std::string& to_string(const BuildResult build_result)
+ {
+ static const std::string NULLVALUE_STRING = Enums::nullvalue_toString("vcpkg::Commands::Build::BuildResult");
+ static const std::string SUCCEEDED_STRING = "SUCCEEDED";
+ static const std::string BUILD_FAILED_STRING = "BUILD_FAILED";
+ 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";
+
+ switch (build_result)
+ {
+ case BuildResult::NULLVALUE: return NULLVALUE_STRING;
+ case BuildResult::SUCCEEDED: return SUCCEEDED_STRING;
+ case BuildResult::BUILD_FAILED: return BUILD_FAILED_STRING;
+ case BuildResult::POST_BUILD_CHECKS_FAILED: return POST_BUILD_CHECKS_FAILED_STRING;
+ case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING;
+ default: Checks::unreachable();
+ }
+ }
+
+ std::string create_error_message(const BuildResult build_result, const package_spec& spec)
+ {
+ return Strings::format("Error: Building package %s failed with: %s", spec.toString(), Build::to_string(build_result));
+ }
+
+ std::string create_user_troubleshooting_message(const package_spec& spec)
+ {
+ return Strings::format("Please ensure sure you're using the latest portfiles with `.\\vcpkg update`, then\n"
+ "submit an issue at https://github.com/Microsoft/vcpkg/issues including:\n"
+ " Package: %s\n"
+ " Vcpkg version: %s\n"
+ "\n"
+ "Additionally, attach any relevant sections from the log files above."
+ , spec.toString(), Version::version());
+ }
+
+ void perform_and_exit(const package_spec& spec, const fs::path& port_dir, const std::unordered_set<std::string>& options, const vcpkg_paths& paths)
+ {
+ if (options.find(OPTION_CHECKS_ONLY) != options.end())
+ {
+ const size_t error_count = PostBuildLint::perform_all_checks(spec, paths);
+ if (error_count > 0)
+ {
+ exit(EXIT_FAILURE);
+ }
+ exit(EXIT_SUCCESS);
+ }
+
+ const expected<SourceParagraph> maybe_spgh = Paragraphs::try_load_port(port_dir);
+ Checks::check_exit(!maybe_spgh.error_code(), "Could not find package named %s: %s", spec, maybe_spgh.error_code().message());
+ const SourceParagraph& spgh = *maybe_spgh.get();
+
+ StatusParagraphs status_db = database_load_check(paths);
+ const BuildResult result = build_package(spgh, spec, paths, paths.port_dir(spec), status_db);
+ if (result == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES)
+ {
+ std::vector<package_spec_with_install_plan> unmet_dependencies = Dependencies::create_install_plan(paths, { spec }, status_db);
+ unmet_dependencies.erase(
+ std::remove_if(unmet_dependencies.begin(), unmet_dependencies.end(), [&spec](const package_spec_with_install_plan& p)
+ {
+ return (p.spec == spec) || (p.plan.plan_type == install_plan_type::ALREADY_INSTALLED);
+ }),
+ unmet_dependencies.end());
+
+ Checks::check_exit(!unmet_dependencies.empty());
+ System::println(System::color::error, "The build command requires all dependencies to be already installed.");
+ System::println("The following dependencies are missing:");
+ System::println("");
+ for (const package_spec_with_install_plan& p : unmet_dependencies)
+ {
+ System::println(" %s", p.spec.toString());
+ }
+ System::println("");
+ exit(EXIT_FAILURE);
+ }
+
+ if (result != BuildResult::SUCCEEDED)
+ {
+ System::println(System::color::error, Build::create_error_message(result, spec));
+ System::println(Build::create_user_troubleshooting_message(spec));
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_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
+ const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example);
+ Input::check_triplet(spec.target_triplet(), paths);
+ const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({ OPTION_CHECKS_ONLY });
+ perform_and_exit(spec, paths.port_dir(spec), options, paths);
+ }
+}
diff --git a/toolsrc/src/commands_build_external.cpp b/toolsrc/src/commands_build_external.cpp
new file mode 100644
index 000000000..06bd1374c
--- /dev/null
+++ b/toolsrc/src/commands_build_external.cpp
@@ -0,0 +1,20 @@
+#include "pch.h"
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Environment.h"
+#include "vcpkg_Input.h"
+
+namespace vcpkg::Commands::BuildExternal
+{
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
+ {
+ 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);
+ const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example);
+ Input::check_triplet(spec.target_triplet(), paths);
+ const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({});
+
+ const fs::path port_dir = args.command_arguments.at(1);
+ Build::perform_and_exit(spec, port_dir, options, paths);
+ }
+}
diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp
index 3a08c4a64..e255b5dff 100644
--- a/toolsrc/src/commands_cache.cpp
+++ b/toolsrc/src/commands_cache.cpp
@@ -1,36 +1,74 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
#include "vcpkg_System.h"
#include "vcpkg_Files.h"
-#include "vcpkg.h"
+#include "Paragraphs.h"
+#include "BinaryParagraph.h"
-namespace vcpkg
+namespace vcpkg::Commands::Cache
{
- void cache_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ static std::vector<BinaryParagraph> read_all_binary_paragraphs(const vcpkg_paths& paths)
{
- args.check_max_args(0);
+ std::vector<BinaryParagraph> output;
+ for (auto it = fs::directory_iterator(paths.packages); it != fs::directory_iterator(); ++it)
+ {
+ const fs::path& path = it->path();
+
+ try
+ {
+ auto file_contents = Files::read_contents(path / "CONTROL");
+ if (auto text = file_contents.get())
+ {
+ auto pghs = Paragraphs::parse_paragraphs(*text);
+ if (pghs.size() != 1)
+ continue;
+
+ const BinaryParagraph binary_paragraph = BinaryParagraph(pghs[0]);
+ output.push_back(binary_paragraph);
+ }
+ }
+ catch (std::runtime_error const&)
+ {
+ }
+ }
- auto begin_it = fs::directory_iterator(paths.packages);
- auto end_it = fs::directory_iterator();
+ return output;
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ static const std::string example = Strings::format(
+ "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", Commands::Help::create_example_string("cache png"));
+ args.check_max_arg_count(1, example);
+ args.check_and_get_optional_command_arguments({});
- if (begin_it == end_it)
+ const std::vector<BinaryParagraph> binary_paragraphs = read_all_binary_paragraphs(paths);
+ if (binary_paragraphs.empty())
{
System::println("No packages are cached.");
exit(EXIT_SUCCESS);
}
- for (; begin_it != end_it; ++begin_it)
+ if (args.command_arguments.size() == 0)
{
- const auto& path = begin_it->path();
-
- auto file_contents = Files::get_contents(path / "CONTROL");
- if (auto text = file_contents.get())
+ for (const BinaryParagraph& binary_paragraph : binary_paragraphs)
+ {
+ const std::string displayname = binary_paragraph.displayname();
+ System::println(displayname);
+ }
+ }
+ else
+ {
+ // At this point there is 1 argument
+ for (const BinaryParagraph& binary_paragraph : binary_paragraphs)
{
- auto pghs = parse_paragraphs(*text);
- if (pghs.size() != 1)
+ const std::string displayname = binary_paragraph.displayname();
+ if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end())
+ {
continue;
+ }
- auto src = BinaryParagraph(pghs[0]);
- System::println(src.displayname().c_str());
+ System::println(displayname);
}
}
diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp
new file mode 100644
index 000000000..315308a62
--- /dev/null
+++ b/toolsrc/src/commands_ci.cpp
@@ -0,0 +1,120 @@
+#include "pch.h"
+#include "vcpkg_Commands.h"
+#include "vcpkglib.h"
+#include "vcpkg_Files.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Dependencies.h"
+#include "vcpkg_Input.h"
+#include "vcpkg_Chrono.h"
+#include "Paragraphs.h"
+
+namespace vcpkg::Commands::CI
+{
+ using Dependencies::package_spec_with_install_plan;
+ using Dependencies::install_plan_type;
+ using Build::BuildResult;
+
+ static std::vector<package_spec> load_all_package_specs(const fs::path& ports_directory, const triplet& target_triplet)
+ {
+ std::vector<SourceParagraph> ports = Paragraphs::load_all_ports(ports_directory);
+ std::vector<package_spec> specs;
+ for (const SourceParagraph& p : ports)
+ {
+ specs.push_back(package_spec::from_name_and_triplet(p.name, target_triplet).get_or_throw());
+ }
+
+ return specs;
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
+ {
+ static const std::string example = Commands::Help::create_example_string("ci x64-windows");
+ args.check_max_arg_count(1, example);
+ const triplet target_triplet = args.command_arguments.size() == 1 ? triplet::from_canonical_name(args.command_arguments.at(0)) : default_target_triplet;
+ Input::check_triplet(target_triplet, paths);
+ args.check_and_get_optional_command_arguments({});
+ const std::vector<package_spec> specs = load_all_package_specs(paths.ports, target_triplet);
+
+ StatusParagraphs status_db = database_load_check(paths);
+ const std::vector<package_spec_with_install_plan> install_plan = Dependencies::create_install_plan(paths, specs, status_db);
+ Checks::check_exit(!install_plan.empty(), "Install plan cannot be empty");
+
+ std::vector<BuildResult> results;
+ std::vector<std::chrono::milliseconds::rep> timing;
+ const ElapsedTime timer = ElapsedTime::createStarted();
+ size_t counter = 0;
+ const size_t package_count = install_plan.size();
+ for (const package_spec_with_install_plan& action : install_plan)
+ {
+ const ElapsedTime build_timer = ElapsedTime::createStarted();
+ counter++;
+ System::println("Starting package %d/%d: %s", counter, package_count, action.spec.toString());
+
+ timing.push_back(-1);
+ results.push_back(BuildResult::NULLVALUE);
+
+ try
+ {
+ if (action.plan.plan_type == install_plan_type::ALREADY_INSTALLED)
+ {
+ results.back() = BuildResult::SUCCEEDED;
+ System::println(System::color::success, "Package %s is already installed", action.spec);
+ }
+ else if (action.plan.plan_type == install_plan_type::BUILD_AND_INSTALL)
+ {
+ const BuildResult result = Commands::Build::build_package(*action.plan.source_pgh, action.spec, paths, paths.port_dir(action.spec), status_db);
+ timing.back() = build_timer.elapsed<std::chrono::milliseconds>().count();
+ results.back() = result;
+ if (result != BuildResult::SUCCEEDED)
+ {
+ System::println(System::color::error, Build::create_error_message(result, action.spec));
+ continue;
+ }
+ const BinaryParagraph bpgh = Paragraphs::try_load_cached_package(paths, action.spec).get_or_throw();
+ Install::install_package(paths, bpgh, &status_db);
+ System::println(System::color::success, "Package %s is installed", action.spec);
+ }
+ else if (action.plan.plan_type == install_plan_type::INSTALL)
+ {
+ results.back() = BuildResult::SUCCEEDED;
+ Install::install_package(paths, *action.plan.binary_pgh, &status_db);
+ System::println(System::color::success, "Package %s is installed from cache", action.spec);
+ }
+ else
+ Checks::unreachable();
+ }
+ catch (const std::exception& e)
+ {
+ System::println(System::color::error, "Error: Could not install package %s: %s", action.spec, e.what());
+ results.back() = BuildResult::NULLVALUE;
+ }
+ System::println("Elapsed time for package %s: %s", action.spec, build_timer.toString());
+ }
+
+ System::println("Total time taken: %s", timer.toString());
+
+ for (size_t i = 0; i < results.size(); i++)
+ {
+ System::println("%s: %s: %dms", install_plan[i].spec.toString(), 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]++;
+ }
+
+ System::println("\n\nSUMMARY");
+ for (const std::pair<const BuildResult, int>& entry : summary)
+ {
+ System::println(" %s: %d", Build::to_string(entry.first), entry.second);
+ }
+
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_contact.cpp b/toolsrc/src/commands_contact.cpp
new file mode 100644
index 000000000..29f0d4d27
--- /dev/null
+++ b/toolsrc/src/commands_contact.cpp
@@ -0,0 +1,21 @@
+#include "pch.h"
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+
+namespace vcpkg::Commands::Contact
+{
+ const std::string& email()
+ {
+ static const std::string s_email = R"(vcpkg@microsoft.com)";
+ return s_email;
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args)
+ {
+ args.check_exact_arg_count(0);
+ args.check_and_get_optional_command_arguments({});
+
+ System::println("Send an email to %s with any feedback.", email());
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_create.cpp b/toolsrc/src/commands_create.cpp
index 76ba644e4..b74693ed5 100644
--- a/toolsrc/src/commands_create.cpp
+++ b/toolsrc/src/commands_create.cpp
@@ -1,50 +1,41 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
#include "vcpkg_System.h"
#include "vcpkg_Environment.h"
#include "vcpkg_Files.h"
+#include "vcpkg_Input.h"
+#include "vcpkglib.h"
-namespace vcpkg
+namespace vcpkg::Commands::Create
{
- void create_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
{
- args.check_max_args(3);
- if (args.command_arguments.size() < 2)
- {
- System::println(System::color::error, "Error: create requires the archive's URL as the second argument.");
- print_usage();
- exit(EXIT_FAILURE);
- }
-
- expected<package_spec> current_spec = package_spec::from_string(args.command_arguments[0], default_target_triplet);
- if (const package_spec* spec = current_spec.get())
- {
- Environment::ensure_utilities_on_path(paths);
+ 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_and_get_optional_command_arguments({});
+ const std::string port_name = args.command_arguments.at(0);
+ const std::string url = args.command_arguments.at(1);
- // Space OR define the FILENAME with proper spacing
- std::wstring custom_filename = L" ";
- if (args.command_arguments.size() >= 3)
- {
- const std::string& zip_file_name = args.command_arguments.at(2);
- Checks::check_exit(!Files::has_invalid_chars_for_filesystem(zip_file_name),
- R"(Filename cannot contain invalid chars %s, but was %s)",
- Files::FILESYSTEM_INVALID_CHARACTERS, zip_file_name);
- custom_filename = Strings::format(LR"( -DFILENAME="%s" )", Strings::utf8_to_utf16(zip_file_name));
- }
+ const fs::path& cmake_exe = paths.get_cmake_exe();
- const std::wstring cmdline = Strings::format(LR"(cmake -DCMD=SCAFFOLD -DPORT=%s -DTARGET_TRIPLET=%s -DURL=%s%s-P "%s")",
- Strings::utf8_to_utf16(spec->name),
- Strings::utf8_to_utf16(spec->target_triplet.value),
- Strings::utf8_to_utf16(args.command_arguments.at(1)),
- custom_filename,
- paths.ports_cmake.generic_wstring());
+ std::vector<CMakeVariable> cmake_args
+ {
+ { L"CMD", L"CREATE" },
+ { L"PORT", port_name },
+ { L"URL", url }
+ };
- exit(System::cmd_execute(cmdline));
- }
- else
+ if (args.command_arguments.size() >= 3)
{
- System::println(System::color::error, "Error: %s: %s", current_spec.error_code().message(), args.command_arguments[0]);
- print_example(Strings::format("%s zlib:x64-windows", args.command).c_str());
- exit(EXIT_FAILURE);
+ const std::string& zip_file_name = args.command_arguments.at(2);
+ Checks::check_exit(!Files::has_invalid_chars_for_filesystem(zip_file_name),
+ R"(Filename cannot contain invalid chars %s, but was %s)",
+ Files::FILESYSTEM_INVALID_CHARACTERS, zip_file_name);
+ cmake_args.push_back({ L"FILENAME", zip_file_name });
}
+
+ const std::wstring cmd_launch_cmake = make_cmake_cmd(cmake_exe, paths.ports_cmake, cmake_args);
+ exit(System::cmd_execute_clean(cmd_launch_cmake));
}
}
diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp
index 71ae8b2c8..ce0557e09 100644
--- a/toolsrc/src/commands_edit.cpp
+++ b/toolsrc/src/commands_edit.cpp
@@ -1,21 +1,71 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
#include "vcpkg_System.h"
+#include "vcpkg_Input.h"
+#include "vcpkg_Environment.h"
-namespace vcpkg
+namespace vcpkg::Commands::Edit
{
- void edit_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
{
- static auto example = "edit zlib";
- args.check_max_args(1, example);
- package_spec spec = args.parse_all_arguments_as_package_specs(default_target_triplet, example).at(0);
+ 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({});
+ const std::string port_name = args.command_arguments.at(0);
+
+ const fs::path portpath = paths.ports / port_name;
+ Checks::check_exit(fs::is_directory(portpath), R"(Could not find port named "%s")", port_name);
+
+ // Find the user's selected editor
+ std::wstring env_EDITOR;
+
+ if (env_EDITOR.empty())
+ {
+ const optional<std::wstring> env_EDITOR_optional = System::get_environmental_variable(L"EDITOR");
+ if (env_EDITOR_optional)
+ {
+ env_EDITOR = *env_EDITOR_optional;
+ }
+ }
+
+ if (env_EDITOR.empty())
+ {
+ const fs::path CODE_EXE_PATH = Environment::get_ProgramFiles_32_bit() / "Microsoft VS Code/Code.exe";
+ if (fs::exists(CODE_EXE_PATH))
+ {
+ env_EDITOR = CODE_EXE_PATH;
+ }
+ }
+
+ if (env_EDITOR.empty())
+ {
+ 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)
+ {
+ auto code_installpath = System::get_registry_string(HKEY_LOCAL_MACHINE, keypath, L"InstallLocation");
+ if (code_installpath)
+ {
+ auto p = fs::path(*code_installpath) / "Code.exe";
+ if (fs::exists(p))
+ {
+ env_EDITOR = p.native();
+ break;
+ }
+ }
+ }
+ }
- // Find editor
- std::wstring env_EDITOR = System::wdupenv_str(L"EDITOR");
if (env_EDITOR.empty())
- env_EDITOR = LR"(C:\Program Files (x86)\Microsoft VS Code\Code.exe)";
+ {
+ Checks::exit_with_message("Visual Studio Code was not found and the environment variable EDITOR is not set");
+ }
- auto portpath = paths.ports / spec.name;
- std::wstring cmdLine = Strings::format(LR"("%s" "%s" "%s")", env_EDITOR, portpath.native(), (portpath / "portfile.cmake").native());
+ std::wstring cmdLine = Strings::wformat(LR"("%s" "%s" "%s" -n)", env_EDITOR, portpath.native(), (portpath / "portfile.cmake").native());
exit(System::cmd_execute(cmdLine));
}
}
diff --git a/toolsrc/src/commands_hash.cpp b/toolsrc/src/commands_hash.cpp
new file mode 100644
index 000000000..805da4153
--- /dev/null
+++ b/toolsrc/src/commands_hash.cpp
@@ -0,0 +1,46 @@
+#include "pch.h"
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+
+namespace vcpkg::Commands::Hash
+{
+ static void do_file_hash(fs::path const& path, std::wstring const& hashType)
+ {
+ auto cmd_line = Strings::wformat(LR"(CertUtil.exe -hashfile "%s" %s)",
+ path.c_str(), hashType.c_str());
+ auto ec_data = System::cmd_execute_and_capture_output(cmd_line);
+ Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
+
+ std::string const& output = ec_data.output;
+
+ auto start = output.find_first_of("\r\n");
+ Checks::check_exit(start != std::string::npos, "Unexpected output format from command: %s", Strings::utf16_to_utf8(cmd_line));
+
+ auto end = output.find_first_of("\r\n", start + 1);
+ Checks::check_exit(end != std::string::npos, "Unexpected output format from command: %s", Strings::utf16_to_utf8(cmd_line));
+
+ auto hash = output.substr(start, end - start);
+ hash.erase(std::remove_if(hash.begin(), hash.end(), isspace), hash.end());
+ System::println(hash);
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args)
+ {
+ 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_and_get_optional_command_arguments({});
+
+ if (args.command_arguments.size() == 1)
+ {
+ do_file_hash(args.command_arguments[0], L"SHA512");
+ }
+ if (args.command_arguments.size() == 2)
+ {
+ do_file_hash(args.command_arguments[0], Strings::utf8_to_utf16(args.command_arguments[1]));
+ }
+
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_help.cpp b/toolsrc/src/commands_help.cpp
index 4e1ae9c49..49b5697c3 100644
--- a/toolsrc/src/commands_help.cpp
+++ b/toolsrc/src/commands_help.cpp
@@ -1,23 +1,74 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
-#include "vcpkg.h"
#include "vcpkg_System.h"
-namespace vcpkg
+namespace vcpkg::Commands::Help
{
- void version_command(const vcpkg_cmd_arguments& args)
+ void help_topic_valid_triplet(const vcpkg_paths& paths)
{
- args.check_max_args(0);
- System::println("Vcpkg package management program version %s\n"
- "\n"
- "Vcpkg is provided \"as-is\" without warranty of any kind, express or implied.\n"
- "All rights reserved.", vcpkg::version()
- );
- exit(EXIT_SUCCESS);
+ System::println("Available architecture triplets:");
+ auto it = fs::directory_iterator(paths.triplets);
+ for (; it != fs::directory_iterator(); ++it)
+ {
+ System::println(" %s", it->path().stem().filename().string());
+ }
+ }
+
+ void print_usage()
+ {
+ System::println(
+ "Commands:\n"
+ " vcpkg search [pat] Search for packages available to be built\n"
+ " vcpkg install <pkg> Install a package\n"
+ " vcpkg remove <pkg> Uninstall a package. \n"
+ " vcpkg remove --purge <pkg> Uninstall and delete a package. \n"
+ " vcpkg list List installed packages\n"
+ " vcpkg update Display list of packages for updating\n"
+ " vcpkg hash <file> [alg] Hash a file by specific algorithm, default SHA512\n"
+ "\n"
+ "%s" // Integration help
+ "\n"
+ " vcpkg edit <pkg> Open up a port for editing (uses %%EDITOR%%, default 'code')\n"
+ " vcpkg import <pkg> Import a pre-built library\n"
+ " vcpkg create <pkg> <url>\n"
+ " [archivename] Create a new package\n"
+ " vcpkg owns <pat> Search for files in installed packages\n"
+ " vcpkg cache List cached compiled packages\n"
+ " vcpkg version Display version information\n"
+ " vcpkg contact Display contact information to send feedback\n"
+ "\n"
+ //"internal commands:\n"
+ //" --check-build-deps <controlfile>\n"
+ //" --create-binary-control <controlfile>\n"
+ //"\n"
+ "Options:\n"
+ " --triplet <t> Specify the target architecture triplet.\n"
+ " (default: %%VCPKG_DEFAULT_TRIPLET%%, see 'vcpkg help triplet')\n"
+ "\n"
+ " --vcpkg-root <path> Specify the vcpkg root directory\n"
+ " (default: %%VCPKG_ROOT%%)\n"
+ "\n"
+ "For more help (including examples) see the accompanying README.md."
+ , Integrate::INTEGRATE_COMMAND_HELPSTRING);
+ }
+
+ std::string create_example_string(const std::string& command_and_arguments)
+ {
+ std::string cs = Strings::format("Example:\n"
+ " vcpkg %s", command_and_arguments);
+ return cs;
+ }
+
+ void print_example(const std::string& command_and_arguments)
+ {
+ System::println(create_example_string(command_and_arguments));
}
- void help_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
{
- args.check_max_args(1);
+ args.check_max_arg_count(1);
+ args.check_and_get_optional_command_arguments({});
+
if (args.command_arguments.empty())
{
print_usage();
@@ -36,20 +87,4 @@ namespace vcpkg
}
exit(EXIT_SUCCESS);
}
-
- void contact_command(const vcpkg_cmd_arguments& /*args*/)
- {
- System::println("Send an email to vcpkg@microsoft.com with any feedback.");
- exit(EXIT_SUCCESS);
- }
-
- void help_topic_valid_triplet(const vcpkg_paths& paths)
- {
- System::println("Available architecture triplets:");
- auto it = fs::directory_iterator(paths.triplets);
- for (; it != fs::directory_iterator(); ++it)
- {
- System::println(" %s", it->path().stem().filename().string());
- }
- }
}
diff --git a/toolsrc/src/commands_helpers.cpp b/toolsrc/src/commands_helpers.cpp
new file mode 100644
index 000000000..0c7ce15bb
--- /dev/null
+++ b/toolsrc/src/commands_helpers.cpp
@@ -0,0 +1,7 @@
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+
+namespace vcpkg::Commands::Helpers
+{
+
+}
diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp
index b1eae277c..11924b4b2 100644
--- a/toolsrc/src/commands_import.cpp
+++ b/toolsrc/src/commands_import.cpp
@@ -1,30 +1,85 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
-#include "vcpkg.h"
-#include "vcpkg_System.h"
+#include "Paragraphs.h"
+#include "StatusParagraph.h"
+#include "vcpkg_Files.h"
-namespace vcpkg
+namespace vcpkg::Commands::Import
{
- void import_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ struct Binaries
{
- if (args.command_arguments.size() != 3)
+ std::vector<fs::path> dlls;
+ std::vector<fs::path> libs;
+ };
+
+ static Binaries find_binaries_in_dir(const fs::path& path)
+ {
+ Files::check_is_directory(path);
+
+ Binaries binaries;
+ binaries.dlls = Files::recursive_find_files_with_extension_in_dir(path, ".dll");
+ binaries.libs = Files::recursive_find_files_with_extension_in_dir(path, ".lib");
+ return binaries;
+ }
+
+ static void copy_files_into_directory(const std::vector<fs::path>& files, const fs::path& destination_folder)
+ {
+ fs::create_directory(destination_folder);
+
+ for (auto const& src_path : files)
{
- System::println(System::color::error, "Error: %s requires 3 parameters", args.command);
- print_example(Strings::format(R"(%s C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)", args.command).c_str());
- exit(EXIT_FAILURE);
+ fs::path dest_path = destination_folder / src_path.filename();
+ fs::copy(src_path, dest_path, fs::copy_options::overwrite_existing);
}
+ }
+
+ static void place_library_files_in(const fs::path& include_directory, const fs::path& project_directory, const fs::path& destination_path)
+ {
+ Files::check_is_directory(include_directory);
+ Files::check_is_directory(project_directory);
+ Files::check_is_directory(destination_path);
+ Binaries debug_binaries = find_binaries_in_dir(project_directory / "Debug");
+ Binaries release_binaries = find_binaries_in_dir(project_directory / "Release");
+
+ fs::path destination_include_directory = destination_path / "include";
+ fs::copy(include_directory, destination_include_directory, fs::copy_options::recursive | fs::copy_options::overwrite_existing);
+
+ copy_files_into_directory(release_binaries.dlls, destination_path / "bin");
+ copy_files_into_directory(release_binaries.libs, destination_path / "lib");
+
+ fs::create_directory(destination_path / "debug");
+ copy_files_into_directory(debug_binaries.dlls, destination_path / "debug" / "bin");
+ copy_files_into_directory(debug_binaries.libs, destination_path / "debug" / "lib");
+ }
+
+ static void do_import(const vcpkg_paths& paths, const fs::path& include_directory, const fs::path& project_directory, const BinaryParagraph& control_file_data)
+ {
+ fs::path library_destination_path = paths.package_dir(control_file_data.spec);
+ fs::create_directory(library_destination_path);
+ place_library_files_in(include_directory, project_directory, library_destination_path);
+
+ fs::path control_file_path = library_destination_path / "CONTROL";
+ std::ofstream(control_file_path) << control_file_data;
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ 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_and_get_optional_command_arguments({});
const fs::path control_file_path(args.command_arguments[0]);
const fs::path include_directory(args.command_arguments[1]);
const fs::path project_directory(args.command_arguments[2]);
- auto pghs = get_paragraphs(control_file_path);
- Checks::check_throw(pghs.size() == 1, "Invalid control file for package");
+ auto pghs = Paragraphs::get_paragraphs(control_file_path);
+ Checks::check_exit(pghs.size() == 1, "Invalid control file %s for package", control_file_path.generic_string());
StatusParagraph spgh;
spgh.package = BinaryParagraph(pghs[0]);
auto& control_file_data = spgh.package;
- vcpkg::binary_import(paths, include_directory, project_directory, control_file_data);
+ do_import(paths, include_directory, project_directory, control_file_data);
exit(EXIT_SUCCESS);
}
}
diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp
new file mode 100644
index 000000000..bb3df943c
--- /dev/null
+++ b/toolsrc/src/commands_install.cpp
@@ -0,0 +1,247 @@
+#include "pch.h"
+#include "vcpkg_Commands.h"
+#include "vcpkglib.h"
+#include "metrics.h"
+#include "vcpkg_Files.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Dependencies.h"
+#include "vcpkg_Input.h"
+#include "Paragraphs.h"
+
+namespace vcpkg::Commands::Install
+{
+ using Dependencies::package_spec_with_install_plan;
+ using Dependencies::install_plan_type;
+
+ static void install_and_write_listfile(const vcpkg_paths& paths, const BinaryParagraph& bpgh)
+ {
+ std::vector<std::string> output;
+
+ const fs::path package_prefix_path = paths.package_dir(bpgh.spec);
+ const size_t prefix_length = package_prefix_path.native().size();
+
+ const triplet& target_triplet = bpgh.spec.target_triplet();
+ const std::string& target_triplet_as_string = target_triplet.canonical_name();
+ std::error_code ec;
+ fs::create_directory(paths.installed / target_triplet_as_string, ec);
+ output.push_back(Strings::format(R"(%s/)", target_triplet_as_string));
+
+ for (auto it = fs::recursive_directory_iterator(package_prefix_path); it != fs::recursive_directory_iterator(); ++it)
+ {
+ const std::string filename = it->path().filename().generic_string();
+ if (fs::is_regular_file(it->status()) && (_stricmp(filename.c_str(), "CONTROL") == 0 || _stricmp(filename.c_str(), "BUILD_INFO") == 0))
+ {
+ // Do not copy the control file
+ continue;
+ }
+
+ const std::string suffix = it->path().generic_u8string().substr(prefix_length + 1);
+ const fs::path target = paths.installed / target_triplet_as_string / suffix;
+
+ auto status = it->status(ec);
+ if (ec)
+ {
+ System::println(System::color::error, "failed: %s: %s", it->path().u8string(), ec.message());
+ continue;
+ }
+
+ if (fs::is_directory(status))
+ {
+ fs::create_directory(target, ec);
+ if (ec)
+ {
+ System::println(System::color::error, "failed: %s: %s", target.u8string(), ec.message());
+ }
+
+ // Trailing backslash for directories
+ output.push_back(Strings::format(R"(%s/%s/)", target_triplet_as_string, suffix));
+ continue;
+ }
+
+ if (fs::is_regular_file(status))
+ {
+ if (fs::exists(target))
+ {
+ System::println(System::color::warning, "File %s was already present and will be overwritten", target.u8string(), ec.message());
+ }
+ fs::copy_file(*it, target, fs::copy_options::overwrite_existing, ec);
+ if (ec)
+ {
+ System::println(System::color::error, "failed: %s: %s", target.u8string(), ec.message());
+ }
+ output.push_back(Strings::format(R"(%s/%s)", target_triplet_as_string, suffix));
+ continue;
+ }
+
+ if (!fs::status_known(status))
+ {
+ System::println(System::color::error, "failed: %s: unknown status", it->path().u8string());
+ continue;
+ }
+
+ System::println(System::color::error, "failed: %s: cannot handle file type", it->path().u8string());
+ }
+
+ std::sort(output.begin(), output.end());
+
+ Files::write_all_lines(paths.listfile_path(bpgh), output);
+ }
+
+ static void remove_first_n_chars(std::vector<std::string>* strings, const size_t n)
+ {
+ for (std::string& s : *strings)
+ {
+ s.erase(0, n);
+ }
+ };
+
+ static std::vector<std::string> extract_files_in_triplet(const std::vector<StatusParagraph_and_associated_files>& pgh_and_files, const triplet& triplet)
+ {
+ std::vector<std::string> output;
+ for (const StatusParagraph_and_associated_files& t : pgh_and_files)
+ {
+ if (t.pgh.package.spec.target_triplet() != triplet)
+ {
+ continue;
+ }
+
+ output.insert(output.end(), t.files.cbegin(), t.files.cend());
+ }
+
+ std::sort(output.begin(), output.end());
+ return output;
+ }
+
+ static ImmutableSortedVector<std::string> build_list_of_package_files(const fs::path& package_dir)
+ {
+ const std::vector<fs::path> package_file_paths = Files::recursive_find_all_files_in_dir(package_dir);
+ std::vector<std::string> package_files;
+ const size_t package_remove_char_count = package_dir.generic_string().size() + 1; // +1 for the slash
+ std::transform(package_file_paths.cbegin(), package_file_paths.cend(), std::back_inserter(package_files), [package_remove_char_count](const fs::path& path)
+ {
+ std::string as_string = path.generic_string();
+ as_string.erase(0, package_remove_char_count);
+ return std::move(as_string);
+ });
+
+ return ImmutableSortedVector<std::string>::create(std::move(package_files));
+ }
+
+ static ImmutableSortedVector<std::string> build_list_of_installed_files(const std::vector<StatusParagraph_and_associated_files>& pgh_and_files, const triplet& triplet)
+ {
+ std::vector<std::string> installed_files = extract_files_in_triplet(pgh_and_files, triplet);
+ const size_t installed_remove_char_count = triplet.canonical_name().size() + 1; // +1 for the slash
+ remove_first_n_chars(&installed_files, installed_remove_char_count);
+
+ return ImmutableSortedVector<std::string>::create(std::move(installed_files));
+ }
+
+ void install_package(const vcpkg_paths& 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.target_triplet();
+ const std::vector<StatusParagraph_and_associated_files> pgh_and_files = get_installed_files(paths, *status_db);
+
+ const ImmutableSortedVector<std::string> package_files = build_list_of_package_files(package_dir);
+ const ImmutableSortedVector<std::string> installed_files = build_list_of_installed_files(pgh_and_files, triplet);
+
+ std::vector<std::string> intersection;
+ std::set_intersection(package_files.cbegin(), package_files.cend(),
+ installed_files.cbegin(), installed_files.cend(),
+ std::back_inserter(intersection));
+
+ if (!intersection.empty())
+ {
+ const fs::path triplet_install_path = paths.installed / triplet.canonical_name();
+ 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);
+ System::print("\n ");
+ System::println(Strings::join("\n ", intersection));
+ System::println("");
+ exit(EXIT_FAILURE);
+ }
+
+ StatusParagraph spgh;
+ spgh.package = binary_paragraph;
+ spgh.want = want_t::install;
+ spgh.state = install_state_t::half_installed;
+ for (auto&& dep : spgh.package.depends)
+ {
+ if (status_db->find_installed(dep, spgh.package.spec.target_triplet()) == status_db->end())
+ {
+ Checks::unreachable();
+ }
+ }
+ write_update(paths, spgh);
+ status_db->insert(std::make_unique<StatusParagraph>(spgh));
+
+ install_and_write_listfile(paths, spgh.package);
+
+ spgh.state = install_state_t::installed;
+ write_update(paths, spgh);
+ status_db->insert(std::make_unique<StatusParagraph>(spgh));
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
+ {
+ static const std::string example = Commands::Help::create_example_string("install zlib zlib:x64-windows curl boost");
+ args.check_min_arg_count(1, example);
+ std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example);
+ Input::check_triplets(specs, paths);
+ args.check_and_get_optional_command_arguments({});
+
+ StatusParagraphs status_db = database_load_check(paths);
+ std::vector<package_spec_with_install_plan> install_plan = Dependencies::create_install_plan(paths, specs, status_db);
+ Checks::check_exit(!install_plan.empty(), "Install plan cannot be empty");
+
+ std::string specs_string = install_plan[0].spec.toString();
+ for (size_t i = 1; i < install_plan.size(); ++i)
+ {
+ specs_string.push_back(',');
+ specs_string.append(install_plan[i].spec.toString());
+ }
+ TrackProperty("installplan", specs_string);
+
+ for (const package_spec_with_install_plan& action : install_plan)
+ {
+ try
+ {
+ if (action.plan.plan_type == install_plan_type::ALREADY_INSTALLED)
+ {
+ if (std::find(specs.begin(), specs.end(), action.spec) != specs.end())
+ {
+ System::println(System::color::success, "Package %s is already installed", action.spec);
+ }
+ }
+ else if (action.plan.plan_type == install_plan_type::BUILD_AND_INSTALL)
+ {
+ const Build::BuildResult result = Commands::Build::build_package(*action.plan.source_pgh, action.spec, paths, paths.port_dir(action.spec), status_db);
+ if (result != Build::BuildResult::SUCCEEDED)
+ {
+ System::println(System::color::error, Build::create_error_message(result, action.spec));
+ System::println(Build::create_user_troubleshooting_message(action.spec));
+ exit(EXIT_FAILURE);
+ }
+ const BinaryParagraph bpgh = Paragraphs::try_load_cached_package(paths, action.spec).get_or_throw();
+ install_package(paths, bpgh, &status_db);
+ System::println(System::color::success, "Package %s is installed", action.spec);
+ }
+ else if (action.plan.plan_type == install_plan_type::INSTALL)
+ {
+ install_package(paths, *action.plan.binary_pgh, &status_db);
+ System::println(System::color::success, "Package %s is installed", action.spec);
+ }
+ else
+ Checks::unreachable();
+ }
+ catch (const std::exception& e)
+ {
+ System::println(System::color::error, "Error: Could not install package %s: %s", action.spec, e.what());
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_installation.cpp b/toolsrc/src/commands_installation.cpp
deleted file mode 100644
index 24ea7480b..000000000
--- a/toolsrc/src/commands_installation.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-#include "vcpkg_Commands.h"
-#include "vcpkg.h"
-#include <fstream>
-#include "vcpkg_Environment.h"
-#include "metrics.h"
-#include "vcpkg_Files.h"
-#include "post_build_lint.h"
-#include "vcpkg_System.h"
-#include "vcpkg_Dependencies.h"
-
-namespace vcpkg
-{
- static void create_binary_control_file(const vcpkg_paths& paths, const fs::path& port_dir, const triplet& target_triplet)
- {
- auto pghs = get_paragraphs(port_dir / "CONTROL");
- Checks::check_exit(pghs.size() == 1, "Error: invalid control file");
- auto bpgh = BinaryParagraph(SourceParagraph(pghs[0]), target_triplet);
- const fs::path binary_control_file = paths.packages / bpgh.dir() / "CONTROL";
- std::ofstream(binary_control_file) << bpgh;
- }
-
- static void build_internal(const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir)
- {
- const fs::path ports_cmake_script_path = paths.ports_cmake;
- const std::wstring command = Strings::format(LR"("%%VS140COMNTOOLS%%..\..\VC\vcvarsall.bat" %s && cmake -DCMD=BUILD -DPORT=%s -DTARGET_TRIPLET=%s "-DCURRENT_PORT_DIR=%s/." -P "%s")",
- Strings::utf8_to_utf16(spec.target_triplet.architecture()),
- Strings::utf8_to_utf16(spec.name),
- Strings::utf8_to_utf16(spec.target_triplet.value),
- port_dir.generic_wstring(),
- ports_cmake_script_path.generic_wstring());
-
- System::Stopwatch timer;
- timer.start();
- int return_code = System::cmd_execute(command);
- timer.stop();
- TrackMetric("buildtimeus-" + to_string(spec), timer.microseconds());
-
- if (return_code != 0)
- {
- System::println(System::color::error, "Error: build command failed");
- TrackProperty("error", "build failed");
- TrackProperty("build_error", std::to_string(return_code));
- exit(EXIT_FAILURE);
- }
-
- perform_all_checks(spec, paths);
-
- create_binary_control_file(paths, port_dir, spec.target_triplet);
-
- // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name;
- // delete_directory(port_buildtrees_dir);
- }
-
- static void build_internal(const package_spec& spec, const vcpkg_paths& paths)
- {
- return build_internal(spec, paths, paths.ports / spec.name);
- }
-
- void install_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
- {
- StatusParagraphs status_db = database_load_check(paths);
-
- std::vector<package_spec> specs = args.parse_all_arguments_as_package_specs(default_target_triplet);
- std::vector<package_spec> install_plan = Dependencies::create_dependency_ordered_install_plan(paths, specs, status_db);
- Checks::check_exit(!install_plan.empty(), "Install plan cannot be empty");
- std::string specs_string = to_string(install_plan[0]);
- for (size_t i = 1; i < install_plan.size(); ++i)
- {
- specs_string.push_back(',');
- specs_string.append(to_string(install_plan[i]));
- }
- TrackProperty("installplan", specs_string);
- Environment::ensure_utilities_on_path(paths);
-
- for (const package_spec& spec : install_plan)
- {
- if (status_db.find_installed(spec.name, spec.target_triplet) != status_db.end())
- {
- System::println(System::color::success, "Package %s is already installed", spec);
- continue;
- }
-
- fs::path package_path = paths.package_dir(spec);
-
- expected<std::string> file_contents = Files::get_contents(package_path / "CONTROL");
-
- try
- {
- if (file_contents.error_code())
- {
- build_internal(spec, paths);
- file_contents = Files::get_contents(package_path / "CONTROL");
- if (file_contents.error_code())
- {
- file_contents.get_or_throw();
- }
- }
-
- auto pghs = parse_paragraphs(file_contents.get_or_throw());
- Checks::check_throw(pghs.size() == 1, "multiple paragraphs in control file");
- install_package(paths, BinaryParagraph(pghs[0]), status_db);
- System::println(System::color::success, "Package %s is installed", spec);
- }
- catch (const std::exception& e)
- {
- System::println(System::color::error, "Error: Could not install package %s: %s", spec, e.what());
- exit(EXIT_FAILURE);
- }
- }
-
- exit(EXIT_SUCCESS);
- }
-
- void build_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
- {
- // Installing multiple packages leads to unintuitive behavior if one of them depends on another.
- // Allowing only 1 package for now.
- args.check_max_args(1);
-
- StatusParagraphs status_db = database_load_check(paths);
-
- const package_spec spec = args.parse_all_arguments_as_package_specs(default_target_triplet).at(0);
- std::unordered_set<package_spec> unmet_dependencies = Dependencies::find_unmet_dependencies(paths, spec, status_db);
- if (!unmet_dependencies.empty())
- {
- System::println(System::color::error, "The build command requires all dependencies to be already installed.");
- System::println("The following dependencies are missing:");
- System::println("");
- for (const package_spec& p : unmet_dependencies)
- {
- System::println(" %s", to_string(p));
- }
- System::println("");
- exit(EXIT_FAILURE);
- }
-
- Environment::ensure_utilities_on_path(paths);
- build_internal(spec, paths);
- exit(EXIT_SUCCESS);
- }
-
- void build_external_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
- {
- if (args.command_arguments.size() != 2)
- {
- System::println(System::color::error, "Error: buildexternal requires the package name and the directory containing the CONTROL file");
- print_example(R"(buildexternal mylib C:\path\to\mylib\)");
- exit(EXIT_FAILURE);
- }
-
- expected<package_spec> current_spec = package_spec::from_string(args.command_arguments[0], default_target_triplet);
- if (auto spec = current_spec.get())
- {
- Environment::ensure_utilities_on_path(paths);
- const fs::path port_dir = args.command_arguments.at(1);
- build_internal(*spec, paths, port_dir);
- exit(EXIT_SUCCESS);
- }
-
- System::println(System::color::error, "Error: %s: %s", current_spec.error_code().message(), args.command_arguments[0]);
- print_example(Strings::format("%s zlib:x64-windows", args.command).c_str());
- exit(EXIT_FAILURE);
- }
-}
diff --git a/toolsrc/src/commands_integration.cpp b/toolsrc/src/commands_integrate.cpp
index 4f3fdd20b..f98b9f77c 100644
--- a/toolsrc/src/commands_integration.cpp
+++ b/toolsrc/src/commands_integrate.cpp
@@ -1,24 +1,17 @@
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#include <shellapi.h>
+#include "pch.h"
#include "vcpkg_Commands.h"
-#include "vcpkg.h"
-#include <fstream>
-#include <iostream>
-#include <regex>
-#include <array>
#include "vcpkg_Environment.h"
#include "vcpkg_Checks.h"
#include "vcpkg_System.h"
#include "vcpkg_Files.h"
-namespace vcpkg
+namespace vcpkg::Commands::Integrate
{
static const std::array<fs::path, 2> old_system_target_files = {
- "C:/Program Files (x86)/MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets",
- "C:/Program Files (x86)/MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"
+ Environment::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets",
+ Environment::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"
};
- static const fs::path system_wide_targets_file = "C:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props";
+ static const fs::path system_wide_targets_file = Environment::get_ProgramFiles_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
{
@@ -116,7 +109,7 @@ namespace vcpkg
static elevation_prompt_user_choice elevated_cmd_execute(const std::string& param)
{
- SHELLEXECUTEINFO shExInfo = {0};
+ SHELLEXECUTEINFO shExInfo = { 0 };
shExInfo.cbSize = sizeof(shExInfo);
shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
shExInfo.hwnd = nullptr;
@@ -143,7 +136,7 @@ namespace vcpkg
static fs::path get_appdata_targets_path()
{
- return fs::path(System::wdupenv_str(L"LOCALAPPDATA")) / "vcpkg" / "vcpkg.user.targets";
+ return fs::path(*System::get_environmental_variable(L"LOCALAPPDATA")) / "vcpkg" / "vcpkg.user.targets";
}
static void integrate_install(const vcpkg_paths& paths)
@@ -173,20 +166,17 @@ namespace vcpkg
fs::create_directory(tmp_dir);
bool should_install_system = true;
- if (fs::exists(system_wide_targets_file))
+ const expected<std::string> system_wide_file_contents = Files::read_contents(system_wide_targets_file);
+ if (auto contents_data = system_wide_file_contents.get())
{
- auto system_wide_file_contents = Files::get_contents(system_wide_targets_file);
- if (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);
+ if (found)
{
- std::regex re(R"###(<!-- version (\d+) -->)###");
- std::match_results<std::string::const_iterator> match;
- auto found = std::regex_search(*contents_data, match, re);
- if (found)
- {
- int ver = atoi(match[1].str().c_str());
- if (ver >= 1)
- should_install_system = false;
- }
+ int ver = atoi(match[1].str().c_str());
+ if (ver >= 1)
+ should_install_system = false;
}
}
@@ -195,7 +185,7 @@ namespace vcpkg
const fs::path sys_src_path = tmp_dir / "vcpkg.system.targets";
std::ofstream(sys_src_path) << create_system_targets_shortcut();
- const std::string param = Strings::format(R"(/c echo f | XCOPY "%s" "%s" /Y > nul)", sys_src_path.string(), system_wide_targets_file.string());
+ const std::string param = Strings::format(R"(/c mkdir "%s" & copy "%s" "%s" /Y > nul)", system_wide_targets_file.parent_path().string(), sys_src_path.string(), system_wide_targets_file.string());
elevation_prompt_user_choice user_choice = elevated_cmd_execute(param);
switch (user_choice)
{
@@ -221,37 +211,45 @@ namespace vcpkg
exit(EXIT_FAILURE);
}
System::println(System::color::success, "Applied user-wide integration for this vcpkg root.");
+ const fs::path cmake_toolchain = paths.buildsystems / "vcpkg.cmake";
System::println("\n"
- "All C++ projects can now #include any installed libraries.\n"
- "Linking will be handled automatically.\n"
- "Installing new libraries will make them instantly available.");
+ "All MSBuild C++ projects can now #include any installed libraries.\n"
+ "Linking will be handled automatically.\n"
+ "Installing new libraries will make them instantly available.\n"
+ "\n"
+ "CMake projects should use -DCMAKE_TOOLCHAIN_FILE=%s", cmake_toolchain.generic_string());
exit(EXIT_SUCCESS);
}
static void integrate_remove()
{
- auto path = get_appdata_targets_path();
- if (!fs::exists(path))
+ const fs::path path = get_appdata_targets_path();
+
+ std::error_code ec;
+ bool was_deleted = fs::remove(path, ec);
+
+ if (ec)
{
- System::println(System::color::success, "User-wide integration is not installed");
- exit(EXIT_SUCCESS);
+ System::println(System::color::error, "Error: Unable to remove user-wide integration: %d", ec.message());
+ exit(EXIT_FAILURE);
}
- const std::wstring cmd_line = Strings::format(LR"(DEL "%s")", get_appdata_targets_path().native());
- const int exit_code = System::cmd_execute(cmd_line);
- if (exit_code)
+ if (was_deleted)
+ {
+ System::println(System::color::success, "User-wide integration was removed");
+ }
+ else
{
- System::println(System::color::error, "Error: Unable to remove user-wide integration: %d", exit_code);
- exit(exit_code);
+ System::println(System::color::success, "User-wide integration is not installed");
}
- System::println(System::color::success, "User-wide integration was removed");
+
exit(EXIT_SUCCESS);
}
static void integrate_project(const vcpkg_paths& paths)
{
- Environment::ensure_nuget_on_path(paths);
+ const fs::path& nuget_exe = paths.get_nuget_exe();
const fs::path& buildsystems_dir = paths.buildsystems;
const fs::path tmp_dir = buildsystems_dir / "tmp";
@@ -269,17 +267,12 @@ namespace vcpkg
std::ofstream(nuspec_file_path) << create_nuspec_file(paths.root, nuget_id, nupkg_version);
// Using all forward slashes for the command line
- const std::wstring cmd_line = Strings::format(LR"(nuget.exe pack -OutputDirectory "%s" "%s" > nul)", buildsystems_dir.native(), nuspec_file_path.native());
+ const std::wstring cmd_line = Strings::wformat(LR"("%s" pack -OutputDirectory "%s" "%s" > nul)", nuget_exe.native(), buildsystems_dir.native(), nuspec_file_path.native());
- const int exit_code = System::cmd_execute(cmd_line);
+ const int exit_code = System::cmd_execute_clean(cmd_line);
const fs::path nuget_package = buildsystems_dir / Strings::format("%s.%s.nupkg", nuget_id, nupkg_version);
- if (exit_code != 0 || !fs::exists(nuget_package))
- {
- System::println(System::color::error, "Error: NuGet package creation failed");
- exit(EXIT_FAILURE);
- }
-
+ Checks::check_exit(exit_code == 0 && fs::exists(nuget_package), "Error: NuGet package creation failed");
System::println(System::color::success, "Created nupkg: %s", nuget_package.string());
System::println(R"(
@@ -295,15 +288,12 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console
" vcpkg integrate remove Remove user-wide integration\n"
" vcpkg integrate project Generate a referencing nuget package for individual VS project use\n";
- void integrate_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
{
- if (args.command_arguments.size() != 1)
- {
- std::cout << "Commands:\n" <<
- INTEGRATE_COMMAND_HELPSTRING <<
- "\n";
- exit(EXIT_FAILURE);
- }
+ static const std::string example = Strings::format("Commands:\n"
+ "%s", INTEGRATE_COMMAND_HELPSTRING);
+ args.check_exact_arg_count(1, example);
+ args.check_and_get_optional_command_arguments({});
if (args.command_arguments[0] == "install")
{
diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp
index 2969ea953..7bfc11f1b 100644
--- a/toolsrc/src/commands_list.cpp
+++ b/toolsrc/src/commands_list.cpp
@@ -1,32 +1,69 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
-#include "vcpkg.h"
+#include "vcpkglib.h"
#include "vcpkg_System.h"
+#include "vcpkglib_helpers.h"
-namespace vcpkg
+namespace vcpkg::Commands::List
{
- void list_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ static void do_print(const StatusParagraph& pgh)
{
- args.check_max_args(0);
+ System::println("%-27s %-16s %s",
+ pgh.package.displayname(),
+ pgh.package.version,
+ details::shorten_description(pgh.package.description));
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ static const std::string example = Strings::format(
+ "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", Commands::Help::create_example_string("list png"));
+ args.check_max_arg_count(1, example);
+ args.check_and_get_optional_command_arguments({});
- std::vector<std::string> packages_output;
- for (auto&& pgh : database_load_check(paths))
+ const StatusParagraphs status_paragraphs = database_load_check(paths);
+ std::vector<StatusParagraph> installed_packages;
+ for (auto&& pgh : status_paragraphs)
{
if (pgh->state == install_state_t::not_installed && pgh->want == want_t::purge)
continue;
- packages_output.push_back(Strings::format("%-27s %-16s %s",
- pgh->package.displayname(),
- pgh->package.version,
- shorten_description(pgh->package.description)));
+ installed_packages.push_back(*pgh);
+ }
+
+ if (installed_packages.empty())
+ {
+ System::println("No packages are installed. Did you mean `search`?");
+ exit(EXIT_SUCCESS);
}
- std::sort(packages_output.begin(), packages_output.end());
- for (auto&& package : packages_output)
+
+ std::sort(installed_packages.begin(), installed_packages.end(),
+ [ ]( const StatusParagraph& lhs, const StatusParagraph& rhs ) -> bool
+ {
+ return lhs.package.displayname() < rhs.package.displayname();
+ });
+
+ if (args.command_arguments.size() == 0)
{
- System::println(package.c_str());
+ for (const StatusParagraph& status_paragraph : installed_packages)
+ {
+ do_print(status_paragraph);
+ }
}
- if (packages_output.empty())
+ else
{
- System::println("No packages are installed. Did you mean `search`?");
+ // At this point there is 1 argument
+ for (const StatusParagraph& status_paragraph : installed_packages)
+ {
+ const std::string displayname = status_paragraph.package.displayname();
+ if (Strings::case_insensitive_ascii_find(displayname, args.command_arguments[0]) == displayname.end())
+ {
+ continue;
+ }
+
+ do_print(status_paragraph);
+ }
}
+
exit(EXIT_SUCCESS);
}
}
diff --git a/toolsrc/src/commands_other.cpp b/toolsrc/src/commands_other.cpp
deleted file mode 100644
index f4fad6690..000000000
--- a/toolsrc/src/commands_other.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "vcpkg_Commands.h"
-#include "vcpkg_System.h"
-#include "vcpkg.h"
-
-namespace vcpkg
-{
- void print_usage()
- {
- System::println(
- "Commands:\n"
- " vcpkg search [pat] Search for packages available to be built\n"
- " vcpkg install <pkg> Install a package\n"
- " vcpkg remove <pkg> Uninstall a package. \n"
- " vcpkg remove --purge <pkg> Uninstall and delete a package. \n"
- " vcpkg list List installed packages\n"
- " vcpkg update Display list of packages for updating\n"
- "\n"
- "%s" // Integration help
- "\n"
- " vcpkg edit <pkg> Open up a port for editing (uses %%EDITOR%%, default 'code')\n"
- " vcpkg import <pkg> Import a pre-built library\n"
- " vcpkg create <pkg> <url>\n"
- " [archivename] Create a new package\n"
- " vcpkg owns <pat> Search for files in installed packages\n"
- " vcpkg cache List cached compiled packages\n"
- " vcpkg version Display version information\n"
- " vcpkg contact Display contact information to send feedback\n"
- "\n"
- //"internal commands:\n"
- //" --check-build-deps <controlfile>\n"
- //" --create-binary-control <controlfile>\n"
- //"\n"
- "Options:\n"
- " --triplet <t> Specify the target architecture triplet.\n"
- " (default: %%VCPKG_DEFAULT_TRIPLET%%, see 'vcpkg help triplet')\n"
- "\n"
- " --vcpkg-root <path> Specify the vcpkg root directory\n"
- " (default: %%VCPKG_ROOT%%)\n"
- "\n"
- "For more help (including examples) see the accompanying README.md."
- , INTEGRATE_COMMAND_HELPSTRING);
- }
-
- void print_example(const char* command_and_arguments)
- {
- System::println("Example:\n"
- " vcpkg %s", command_and_arguments);
- }
-
- void internal_test_command(const vcpkg_cmd_arguments& /*args*/, const vcpkg_paths& /*paths*/)
- {
- // auto data = FormatEventData("test");
- // Track(data);
- exit(EXIT_SUCCESS);
- }
-
- const std::vector<package_name_and_function<command_type_a>>& get_available_commands_type_a()
- {
- static std::vector<package_name_and_function<command_type_a>> t = {
- {"install", install_command},
- {"remove", remove_command},
- {"build", build_command},
- {"edit", edit_command},
- {"create", create_command},
- {"build_external", build_external_command}
- };
- return t;
- }
-
- const std::vector<package_name_and_function<command_type_b>>& get_available_commands_type_b()
- {
- static std::vector<package_name_and_function<command_type_b>> t = {
- {"help", help_command},
- {"search", search_command},
- {"list", list_command},
- {"integrate", integrate_command},
- {"owns", owns_command},
- {"update", update_command},
- {"import", import_command},
- {"cache", cache_command},
- {"internal_test", internal_test_command},
- };
- return t;
- }
-
- const std::vector<package_name_and_function<command_type_c>>& get_available_commands_type_c()
- {
- static std::vector<package_name_and_function<command_type_c>> t = {
- {"version", &version_command},
- {"contact", &contact_command}
- };
- return t;
- }
-}
diff --git a/toolsrc/src/commands_owns.cpp b/toolsrc/src/commands_owns.cpp
index 19c0a8dc6..16bb986e2 100644
--- a/toolsrc/src/commands_owns.cpp
+++ b/toolsrc/src/commands_owns.cpp
@@ -1,18 +1,33 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
#include "vcpkg_System.h"
-#include "vcpkg.h"
+#include "vcpkglib.h"
-namespace vcpkg
+namespace vcpkg::Commands::Owns
{
- void owns_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ static void search_file(const vcpkg_paths& paths, const std::string& file_substr, const StatusParagraphs& status_db)
{
- args.check_max_args(1);
- if (args.command_arguments.size() == 0)
+ const std::vector<StatusParagraph_and_associated_files> installed_files = get_installed_files(paths, status_db);
+ for (const StatusParagraph_and_associated_files& pgh_and_file : installed_files)
{
- System::println(System::color::error, "Error: owns requires a pattern to search for as the first argument.");
- print_example("owns .dll");
- exit(EXIT_FAILURE);
+ const StatusParagraph& pgh = pgh_and_file.pgh;
+
+ for (const std::string& file : pgh_and_file.files)
+ {
+ if (file.find(file_substr) != std::string::npos)
+ {
+ System::println("%s: %s", pgh.package.displayname(), file);
+ }
+ }
}
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ 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_and_get_optional_command_arguments({});
+
StatusParagraphs status_db = database_load_check(paths);
search_file(paths, args.command_arguments[0], status_db);
exit(EXIT_SUCCESS);
diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp
new file mode 100644
index 000000000..4d5a589f6
--- /dev/null
+++ b/toolsrc/src/commands_portsdiff.cpp
@@ -0,0 +1,138 @@
+#include "pch.h"
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Maps.h"
+#include "SourceParagraph.h"
+#include "vcpkg_Environment.h"
+#include "Paragraphs.h"
+
+namespace vcpkg::Commands::PortsDiff
+{
+ static void do_print_name_and_version(const std::vector<std::string>& ports_to_print, const std::map<std::string, std::string>& names_and_versions)
+ {
+ for (const std::string& name : ports_to_print)
+ {
+ const std::string& version = names_and_versions.at(name);
+ System::println("%-20s %-16s", name, version);
+ }
+ }
+
+ static void do_print_name_and_previous_version_and_current_version(const std::vector<std::string>& ports_to_print,
+ const std::map<std::string, std::string>& previous_names_and_versions,
+ const std::map<std::string, std::string>& current_names_and_versions)
+ {
+ for (const std::string& name : ports_to_print)
+ {
+ const std::string& previous_version = previous_names_and_versions.at(name);
+ const std::string& current_version = current_names_and_versions.at(name);
+ System::println("%-20s %-16s -> %s", name, previous_version, current_version);
+ }
+ }
+
+ static std::map<std::string, std::string> read_ports_from_commit(const vcpkg_paths& paths, const std::wstring& git_commit_id)
+ {
+ const fs::path& git_exe = paths.get_git_exe();
+ const fs::path dot_git_dir = paths.root / ".git";
+ const std::wstring ports_dir_name_as_string = paths.ports.filename().native();
+ const fs::path temp_checkout_path = paths.root / Strings::wformat(L"%s-%s", ports_dir_name_as_string, git_commit_id);
+ fs::create_directory(temp_checkout_path);
+ const std::wstring checkout_this_dir = Strings::wformat(LR"(.\%s)", ports_dir_name_as_string); // Must be relative to the root of the repository
+
+ const std::wstring cmd = Strings::wformat(LR"("%s" --git-dir="%s" --work-tree="%s" checkout %s -f -q -- %s %s & "%s" reset >NUL)",
+ git_exe.native(),
+ dot_git_dir.native(),
+ temp_checkout_path.native(),
+ git_commit_id,
+ checkout_this_dir,
+ L".vcpkg-root",
+ git_exe.native());
+ System::cmd_execute_clean(cmd);
+ const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(temp_checkout_path / ports_dir_name_as_string);
+ const std::map<std::string, std::string> names_and_versions = Paragraphs::extract_port_names_and_versions(source_paragraphs);
+ fs::remove_all(temp_checkout_path);
+ return names_and_versions;
+ }
+
+ static void check_commit_exists(const fs::path& git_exe, const std::wstring& git_commit_id)
+ {
+ static const std::string VALID_COMMIT_OUTPUT = "commit\n";
+
+ const std::wstring cmd = Strings::wformat(LR"("%s" cat-file -t %s 2>NUL)", git_exe.native(), git_commit_id);
+ const System::exit_code_and_output output = System::cmd_execute_and_capture_output(cmd);
+ Checks::check_exit(output.output == VALID_COMMIT_OUTPUT, "Invalid commit id %s", Strings::utf16_to_utf8(git_commit_id));
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ {
+ 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_and_get_optional_command_arguments({});
+
+ const fs::path& git_exe = paths.get_git_exe();
+
+ const std::wstring git_commit_id_for_previous_snapshot = Strings::utf8_to_utf16(args.command_arguments.at(0));
+ const std::wstring git_commit_id_for_current_snapshot = args.command_arguments.size() < 2 ? L"HEAD" : Strings::utf8_to_utf16(args.command_arguments.at(1));
+
+ check_commit_exists(git_exe, git_commit_id_for_current_snapshot);
+ check_commit_exists(git_exe, git_commit_id_for_previous_snapshot);
+
+ const std::map<std::string, std::string> current_names_and_versions = read_ports_from_commit(paths, git_commit_id_for_current_snapshot);
+ const std::map<std::string, std::string> previous_names_and_versions = 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);
+
+ std::vector<std::string> added_ports;
+ std::set_difference(
+ current_ports.cbegin(), current_ports.cend(),
+ previous_ports.cbegin(), previous_ports.cend(),
+ std::back_inserter(added_ports));
+
+ if (!added_ports.empty())
+ {
+ System::println("\nThe following %d ports were added:\n", added_ports.size());
+ do_print_name_and_version(added_ports, current_names_and_versions);
+ }
+
+ std::vector<std::string> removed_ports;
+ std::set_difference(
+ previous_ports.cbegin(), previous_ports.cend(),
+ current_ports.cbegin(), current_ports.cend(),
+ std::back_inserter(removed_ports));
+
+ if (!removed_ports.empty())
+ {
+ System::println("\nThe following %d ports were removed:\n", removed_ports.size());
+ do_print_name_and_version(removed_ports, previous_names_and_versions);
+ }
+
+ std::vector<std::string> potentially_updated_ports;
+ std::set_intersection(
+ current_ports.cbegin(), current_ports.cend(),
+ previous_ports.cbegin(), previous_ports.cend(),
+ std::back_inserter(potentially_updated_ports));
+
+ std::vector<std::string> updated_ports;
+ std::copy_if(potentially_updated_ports.cbegin(), potentially_updated_ports.cend(), std::back_inserter(updated_ports),
+ [&](const std::string& port) -> bool
+ {
+ return current_names_and_versions.at(port) != previous_names_and_versions.at(port);
+ }
+ );
+
+ if (!updated_ports.empty())
+ {
+ System::println("\nThe following %d ports were updated:\n", updated_ports.size());
+ do_print_name_and_previous_version_and_current_version(updated_ports, previous_names_and_versions, current_names_and_versions);
+ }
+
+ if (added_ports.empty() && removed_ports.empty() && updated_ports.empty())
+ {
+ System::println("There were no changes in the ports between the two commits.");
+ }
+
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp
index f5315ccb1..1b7b7923a 100644
--- a/toolsrc/src/commands_remove.cpp
+++ b/toolsrc/src/commands_remove.cpp
@@ -1,10 +1,18 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
-#include "vcpkg.h"
+#include "vcpkglib.h"
#include "vcpkg_System.h"
+#include "vcpkg_Input.h"
+#include "vcpkg_Dependencies.h"
-namespace vcpkg
+namespace vcpkg::Commands::Remove
{
+ using Dependencies::package_spec_with_remove_plan;
+ using Dependencies::remove_plan_type;
+ using Dependencies::request_type;
+
static const std::string OPTION_PURGE = "--purge";
+ static const std::string OPTION_RECURSE = "--recurse";
static void delete_directory(const fs::path& directory)
{
@@ -20,24 +28,197 @@ namespace vcpkg
}
}
- void remove_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
+ static void remove_package(const vcpkg_paths& paths, const package_spec& spec, StatusParagraphs* status_db)
+ {
+ StatusParagraph& pkg = **status_db->find(spec.name(), spec.target_triplet());
+
+ pkg.want = want_t::purge;
+ pkg.state = install_state_t::half_installed;
+ write_update(paths, pkg);
+
+ std::fstream listfile(paths.listfile_path(pkg.package), std::ios_base::in | std::ios_base::binary);
+ if (listfile)
+ {
+ std::vector<fs::path> dirs_touched;
+ std::string suffix;
+ while (std::getline(listfile, suffix))
+ {
+ if (!suffix.empty() && suffix.back() == '\r')
+ suffix.pop_back();
+
+ std::error_code ec;
+
+ auto target = paths.installed / suffix;
+
+ auto status = fs::status(target, ec);
+ if (ec)
+ {
+ System::println(System::color::error, "failed: %s", ec.message());
+ continue;
+ }
+
+ if (fs::is_directory(status))
+ {
+ dirs_touched.push_back(target);
+ }
+ else if (fs::is_regular_file(status))
+ {
+ fs::remove(target, ec);
+ if (ec)
+ {
+ System::println(System::color::error, "failed: %s: %s", target.u8string(), ec.message());
+ }
+ }
+ else if (!fs::status_known(status))
+ {
+ System::println(System::color::warning, "Warning: unknown status: %s", target.u8string());
+ }
+ else
+ {
+ System::println(System::color::warning, "Warning: %s: cannot handle file type", target.u8string());
+ }
+ }
+
+ auto b = dirs_touched.rbegin();
+ auto e = dirs_touched.rend();
+ for (; b != e; ++b)
+ {
+ if (fs::directory_iterator(*b) == fs::directory_iterator())
+ {
+ std::error_code ec;
+ fs::remove(*b, ec);
+ if (ec)
+ {
+ System::println(System::color::error, "failed: %s", ec.message());
+ }
+ }
+ }
+
+ listfile.close();
+ fs::remove(paths.listfile_path(pkg.package));
+ }
+
+ pkg.state = install_state_t::not_installed;
+ write_update(paths, pkg);
+ }
+
+ static void sort_packages_by_name(std::vector<const package_spec_with_remove_plan*>* packages)
{
- const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_PURGE});
+ std::sort(packages->begin(), packages->end(), [](const package_spec_with_remove_plan* left, const package_spec_with_remove_plan* right) -> bool
+ {
+ return left->spec.name() < right->spec.name();
+ });
+ }
+
+ static void print_plan(const std::vector<package_spec_with_remove_plan>& plan)
+ {
+ std::vector<const package_spec_with_remove_plan*> not_installed;
+ std::vector<const package_spec_with_remove_plan*> remove;
+
+ for (const package_spec_with_remove_plan& i : plan)
+ {
+ if (i.plan.plan_type == remove_plan_type::NOT_INSTALLED)
+ {
+ not_installed.push_back(&i);
+ continue;
+ }
+
+ if (i.plan.plan_type == remove_plan_type::REMOVE)
+ {
+ remove.push_back(&i);
+ continue;
+ }
+
+ Checks::unreachable();
+ }
+
+ if (!not_installed.empty())
+ {
+ sort_packages_by_name(&not_installed);
+ System::println("The following packages are not installed, so not removed:\n%s",
+ Strings::join("\n ", not_installed, [](const package_spec_with_remove_plan* p)
+ {
+ return " " + p->spec.toString();
+ }));
+ }
+
+ if (!remove.empty())
+ {
+ sort_packages_by_name(&remove);
+ System::println("The following packages will be removed:\n%s",
+ Strings::join("\n", remove, [](const package_spec_with_remove_plan* p)
+ {
+ if (p->plan.request_type == Dependencies::request_type::AUTO_SELECTED)
+ {
+ return " * " + p->spec.toString();
+ }
+
+ if (p->plan.request_type == Dependencies::request_type::USER_REQUESTED)
+ {
+ return " " + p->spec.toString();
+ }
+
+ Checks::unreachable();
+ }));
+ }
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet)
+ {
+ static const std::string example = Commands::Help::create_example_string("remove zlib zlib:x64-windows curl boost");
+ args.check_min_arg_count(1, example);
+ std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example);
+ Input::check_triplets(specs, paths);
+ const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({ OPTION_PURGE, OPTION_RECURSE });
+ const bool alsoRemoveFolderFromPackages = options.find(OPTION_PURGE) != options.end();
+ const bool isRecursive = options.find(OPTION_RECURSE) != options.end();
+
auto status_db = database_load_check(paths);
+ const std::vector<package_spec_with_remove_plan> remove_plan = Dependencies::create_remove_plan(specs, status_db);
+ Checks::check_exit(!remove_plan.empty(), "Remove plan cannot be empty");
+
+ print_plan(remove_plan);
+
+ const bool has_non_user_requested_packages = std::find_if(remove_plan.cbegin(), remove_plan.cend(), [](const package_spec_with_remove_plan& package)-> bool
+ {
+ return package.plan.request_type != request_type::USER_REQUESTED;
+ }) != remove_plan.cend();
- std::vector<package_spec> specs = args.parse_all_arguments_as_package_specs(default_target_triplet);
- bool alsoRemoveFolderFromPackages = options.find(OPTION_PURGE) != options.end();
+ if (has_non_user_requested_packages && !isRecursive)
+ {
+ System::println(System::color::warning,
+ "Additional packages (*) need to be removed to complete this operation.\n"
+ "If you are sure you want to remove them, run the command with the --recurse option");
+ exit(EXIT_FAILURE);
+ }
- for (const package_spec& spec : specs)
+ for (const package_spec_with_remove_plan& action : remove_plan)
{
- deinstall_package(paths, spec, status_db);
+ const std::string display_name = action.spec.display_name();
+
+ switch (action.plan.plan_type)
+ {
+ case remove_plan_type::NOT_INSTALLED:
+ System::println(System::color::success, "Package %s is not installed", display_name);
+ break;
+ case remove_plan_type::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 remove_plan_type::UNKNOWN:
+ default:
+ Checks::unreachable();
+ }
if (alsoRemoveFolderFromPackages)
{
- const fs::path spec_package_dir = paths.packages / spec.dir();
- delete_directory(spec_package_dir);
+ System::println("Purging package %s... ", display_name);
+ delete_directory(paths.packages / action.spec.dir());
+ System::println(System::color::success, "Purging package %s... done", display_name);
}
}
+
exit(EXIT_SUCCESS);
}
}
diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp
index ce02e9c3b..8bac858f1 100644
--- a/toolsrc/src/commands_search.cpp
+++ b/toolsrc/src/commands_search.cpp
@@ -1,58 +1,92 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
#include "vcpkg_System.h"
-#include "vcpkg.h"
-#include <iostream>
-#include <iomanip>
+#include "Paragraphs.h"
+#include "vcpkglib_helpers.h"
+#include "SourceParagraph.h"
-namespace fs = std::tr2::sys;
-
-namespace vcpkg
+namespace vcpkg::Commands::Search
{
- template <class Pred>
- static void do_print(const vcpkg_paths& paths, Pred predicate)
+ static const std::string OPTION_GRAPH = "--graph"; //TODO: This should find a better home, eventually
+
+ static std::string replace_dashes_with_underscore(const std::string& input)
{
- for (auto it = fs::directory_iterator(paths.ports); it != fs::directory_iterator(); ++it)
- {
- const fs::path& path = it->path();
+ std::string output = input;
+ std::replace(output.begin(), output.end(), '-', '_');
+ return output;
+ }
- try
- {
- auto pghs = get_paragraphs(path / "CONTROL");
- if (pghs.empty())
- continue;
- auto srcpgh = SourceParagraph(pghs[0]);
+ static std::string create_graph_as_string(const std::vector<SourceParagraph>& source_paragraphs)
+ {
+ int empty_node_count = 0;
- if (predicate(srcpgh.name))
- {
- std::cout << std::left
- << std::setw(20) << srcpgh.name << ' '
- << std::setw(16) << srcpgh.version << ' '
- << shorten_description(srcpgh.description) << '\n';
- }
+ std::string s;
+ s.append("digraph G{ rankdir=LR; edge [minlen=3]; overlap=false;");
+
+ for (const SourceParagraph& source_paragraph : source_paragraphs)
+ {
+ if (source_paragraph.depends.empty())
+ {
+ empty_node_count++;
+ continue;
}
- catch (std::runtime_error const&)
+
+ const std::string name = replace_dashes_with_underscore(source_paragraph.name);
+ s.append(Strings::format("%s;", name));
+ for (const dependency& d : source_paragraph.depends)
{
+ const std::string dependency_name = replace_dashes_with_underscore(d.name);
+ s.append(Strings::format("%s -> %s;", name, dependency_name));
}
}
+
+ s.append(Strings::format("empty [label=\"%d singletons...\"]; }", empty_node_count));
+ return s;
+ }
+
+ static void do_print(const SourceParagraph& source_paragraph)
+ {
+ System::println("%-20s %-16s %s",
+ source_paragraph.name,
+ source_paragraph.version,
+ details::shorten_description(source_paragraph.description));
}
- void search_command(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
{
- args.check_max_args(1);
- if (args.command_arguments.size() == 0)
+ 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);
+ const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({ OPTION_GRAPH });
+
+ const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(paths.ports);
+ if (options.find(OPTION_GRAPH) != options.cend())
{
- do_print(paths, [](std::string&) -> bool
- {
- return true;
- });
+ const std::string graph_as_string = create_graph_as_string(source_paragraphs);
+ System::println(graph_as_string);
exit(EXIT_SUCCESS);
}
- // At this point there is 1 argument
- do_print(paths, [&](std::string& port_name) -> bool
- {
- return Strings::case_insensitive_find(port_name, args.command_arguments[0]) != port_name.end();
- });
+ if (args.command_arguments.empty())
+ {
+ for (const SourceParagraph& source_paragraph : source_paragraphs)
+ {
+ do_print(source_paragraph);
+ }
+ }
+ else
+ {
+ // At this point there is 1 argument
+ for (const SourceParagraph& source_paragraph : source_paragraphs)
+ {
+ if (Strings::case_insensitive_ascii_find(source_paragraph.name, args.command_arguments[0]) == source_paragraph.name.end())
+ {
+ continue;
+ }
+
+ do_print(source_paragraph);
+ }
+ }
System::println("\nIf your library is not listed, please open an issue at:\n"
" https://github.com/Microsoft/vcpkg/issues");
diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp
index eec3e46a7..8131d9a73 100644
--- a/toolsrc/src/commands_update.cpp
+++ b/toolsrc/src/commands_update.cpp
@@ -1,42 +1,31 @@
+#include "pch.h"
#include "vcpkg_Commands.h"
-#include "vcpkg.h"
+#include "vcpkglib.h"
#include "vcpkg_System.h"
#include "vcpkg_Files.h"
+#include "Paragraphs.h"
-namespace vcpkg
+namespace vcpkg::Commands::Update
{
- void update_command(const vcpkg_cmd_arguments& /*args*/, const vcpkg_paths& paths)
+ void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths)
{
- auto status_db = database_load_check(paths);
+ args.check_exact_arg_count(0);
+ args.check_and_get_optional_command_arguments({});
+ System::println("Using local portfile versions. To update the local portfiles, use `git pull`.");
- std::unordered_map<std::string, std::string> src_names_to_versions;
+ auto status_db = database_load_check(paths);
- auto begin_it = fs::directory_iterator(paths.ports);
- auto end_it = fs::directory_iterator();
- for (; begin_it != end_it; ++begin_it)
- {
- const auto& path = begin_it->path();
- try
- {
- auto pghs = get_paragraphs(path / "CONTROL");
- if (pghs.empty())
- continue;
- auto srcpgh = SourceParagraph(pghs[0]);
- src_names_to_versions.emplace(srcpgh.name, srcpgh.version);
- }
- catch (std::runtime_error const&)
- {
- }
- }
+ const std::vector<SourceParagraph> source_paragraphs = Paragraphs::load_all_ports(paths.ports);
+ const std::map<std::string, std::string> src_names_to_versions = Paragraphs::extract_port_names_and_versions(source_paragraphs);
std::string packages_list;
std::vector<std::string> packages_output;
- for (auto&& pgh : database_load_check(paths))
+ for (auto&& pgh : status_db)
{
if (pgh->state == install_state_t::not_installed && pgh->want == want_t::purge)
continue;
- auto it = src_names_to_versions.find(pgh->package.name);
+ auto it = src_names_to_versions.find(pgh->package.spec.name());
if (it == src_names_to_versions.end())
{
// Package was not installed from portfile
@@ -66,20 +55,20 @@ namespace vcpkg
System::println("\nTo update these packages, run\n vcpkg remove --purge <pkgs>...\n vcpkg install <pkgs>...");
}
- auto version_file = Files::get_contents(paths.root / "toolsrc" / "VERSION.txt");
+ auto version_file = Files::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().c_str(), "%d.%d.%d-", &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 scripts\\bootstrap.ps1 to update.",
+ System::println("Different source is available for vcpkg (%d.%d.%d -> %d.%d.%d). Use powershell -exec bypass scripts/bootstrap.ps1 to update.",
maj2, min2, rev2,
maj1, min1, rev1);
}
diff --git a/toolsrc/src/commands_version.cpp b/toolsrc/src/commands_version.cpp
new file mode 100644
index 000000000..4789e2409
--- /dev/null
+++ b/toolsrc/src/commands_version.cpp
@@ -0,0 +1,37 @@
+#include "pch.h"
+#include "vcpkg_Commands.h"
+#include "vcpkg_System.h"
+#include "metrics.h"
+
+#define STRINGIFY(...) #__VA_ARGS__
+#define MACRO_TO_STRING(X) STRINGIFY(X)
+
+#define VCPKG_VERSION_AS_STRING MACRO_TO_STRING(VCPKG_VERSION)
+
+namespace vcpkg::Commands::Version
+{
+ const std::string& version()
+ {
+ static const std::string s_version =
+#include "../VERSION.txt"
+
+ + std::string(VCPKG_VERSION_AS_STRING)
+#ifndef NDEBUG
+ + std::string("-debug")
+#endif
+ + std::string(GetCompiledMetricsEnabled() ? "" : "-external");
+ return s_version;
+ }
+
+ void perform_and_exit(const vcpkg_cmd_arguments& args)
+ {
+ args.check_exact_arg_count(0);
+ args.check_and_get_optional_command_arguments({});
+
+ System::println("Vcpkg package management program version %s\n"
+ "\n"
+ "See LICENSE.txt for license information.", version()
+ );
+ exit(EXIT_SUCCESS);
+ }
+}
diff --git a/toolsrc/src/lib.cpp b/toolsrc/src/lib.cpp
deleted file mode 100644
index a717344a4..000000000
--- a/toolsrc/src/lib.cpp
+++ /dev/null
@@ -1,509 +0,0 @@
-#include "vcpkg.h"
-#include <iostream>
-#include <iomanip>
-#include <fstream>
-#include <functional>
-#include <string>
-#include <unordered_map>
-#include <memory>
-#include <filesystem>
-#include <vector>
-#include <cassert>
-#include "vcpkg_Files.h"
-#include "vcpkg_System.h"
-
-using namespace vcpkg;
-
-bool vcpkg::g_do_dry_run = false;
-
-namespace
-{
- template <class M, class K, class V>
- auto find_or_default(const M& map, const K& key, const V& val)
- {
- auto it = map.find(key);
- if (it == map.end())
- return decltype(it->second)(val);
- else
- return it->second;
- }
-}
-
-namespace
-{
- std::fstream open_status_file(const vcpkg_paths& paths, std::ios_base::openmode mode = std::ios_base::app | std::ios_base::in | std::ios_base::out | std::ios_base::binary)
- {
- return std::fstream(paths.vcpkg_dir_status_file, mode);
- }
-}
-
-static StatusParagraphs load_current_database(const fs::path& vcpkg_dir_status_file, const fs::path& vcpkg_dir_status_file_old)
-{
- if (!fs::exists(vcpkg_dir_status_file))
- {
- if (!fs::exists(vcpkg_dir_status_file_old))
- {
- // no status file, use empty db
- return StatusParagraphs();
- }
-
- fs::rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file);
- }
-
- auto text = Files::get_contents(vcpkg_dir_status_file).get_or_throw();
- auto pghs = parse_paragraphs(text);
-
- std::vector<std::unique_ptr<StatusParagraph>> status_pghs;
- for (auto&& p : pghs)
- {
- status_pghs.push_back(std::make_unique<StatusParagraph>(p));
- }
-
- return StatusParagraphs(std::move(status_pghs));
-}
-
-StatusParagraphs vcpkg::database_load_check(const vcpkg_paths& paths)
-{
- auto updates_dir = paths.vcpkg_dir_updates;
-
- std::error_code ec;
- fs::create_directory(paths.installed, ec);
- fs::create_directory(paths.vcpkg_dir, ec);
- fs::create_directory(paths.vcpkg_dir_info, ec);
- fs::create_directory(updates_dir, ec);
-
- const fs::path& status_file = paths.vcpkg_dir_status_file;
- const fs::path status_file_old = status_file.parent_path() / "status-old";
- const fs::path status_file_new = status_file.parent_path() / "status-new";
-
- StatusParagraphs current_status_db = load_current_database(status_file, status_file_old);
-
- auto b = fs::directory_iterator(updates_dir);
- auto e = fs::directory_iterator();
- if (b == e)
- {
- // updates directory is empty, control file is up-to-date.
- return current_status_db;
- }
-
- for (; b != e; ++b)
- {
- if (!fs::is_regular_file(b->status()))
- continue;
- if (b->path().filename() == "incomplete")
- continue;
-
- auto text = Files::get_contents(b->path()).get_or_throw();
- auto pghs = parse_paragraphs(text);
- for (auto&& p : pghs)
- {
- current_status_db.insert(std::make_unique<StatusParagraph>(p));
- }
- }
-
- std::fstream(status_file_new, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc) << current_status_db;
-
- if (fs::exists(status_file_old))
- fs::remove(status_file_old);
- if (fs::exists(status_file))
- fs::rename(status_file, status_file_old);
- fs::rename(status_file_new, status_file);
- fs::remove(status_file_old);
-
- b = fs::directory_iterator(updates_dir);
- for (; b != e; ++b)
- {
- if (!fs::is_regular_file(b->status()))
- continue;
- fs::remove(b->path());
- }
-
- return current_status_db;
-}
-
-static fs::path listfile_path(const vcpkg_paths& paths, const BinaryParagraph& pgh)
-{
- return paths.vcpkg_dir_info / (pgh.fullstem() + ".list");
-}
-
-static std::string get_fullpkgname_from_listfile(const fs::path& path)
-{
- auto ret = path.stem().generic_u8string();
- std::replace(ret.begin(), ret.end(), '_', ':');
- return ret;
-}
-
-static fs::path prefix_path_for_package(const vcpkg_paths& paths, const BinaryParagraph& pgh)
-{
- return paths.package_dir({pgh.name, pgh.target_triplet});
-}
-
-static void write_update(const vcpkg_paths& paths, const StatusParagraph& p)
-{
- static int update_id = 0;
- 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);
- std::fstream fs(tmp_update_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
- fs << p;
- fs.close();
- fs::rename(tmp_update_filename, update_filename);
-}
-
-static void install_and_write_listfile(const vcpkg_paths& paths, const BinaryParagraph& bpgh)
-{
- std::fstream listfile(listfile_path(paths, bpgh), std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
-
- auto package_prefix_path = prefix_path_for_package(paths, bpgh);
- auto prefix_length = package_prefix_path.native().size();
-
- std::error_code ec;
- fs::create_directory(paths.installed / bpgh.target_triplet.value, ec);
- listfile << bpgh.target_triplet << "\n";
-
- for (auto it = fs::recursive_directory_iterator(package_prefix_path); it != fs::recursive_directory_iterator(); ++it)
- {
- const auto& filename = it->path().filename();
- if (fs::is_regular_file(it->status()) && (filename == "CONTROL" || filename == "control"))
- {
- // Do not copy the control file
- continue;
- }
-
- auto suffix = it->path().generic_u8string().substr(prefix_length + 1);
- auto target = paths.installed / bpgh.target_triplet.value / suffix;
-
- auto status = it->status(ec);
- if (ec)
- {
- System::println(System::color::error, "failed: %s", ec.message());
- continue;
- }
- if (fs::is_directory(status))
- {
- fs::create_directory(target, ec);
- if (ec)
- {
- System::println(System::color::error, "failed: %s", ec.message());
- }
-
- listfile << bpgh.target_triplet << "/" << suffix << "\n";
- }
- else if (fs::is_regular_file(status))
- {
- fs::copy_file(*it, target, ec);
- if (ec)
- {
- System::println(System::color::error, "failed: %s", ec.message());
- }
- listfile << bpgh.target_triplet << "/" << suffix << "\n";
- }
- else if (!fs::status_known(status))
- {
- std::cout << "unknown status: " << *it << "\n";
- }
- else
- std::cout << "warning: file does not exist: " << *it << "\n";
- }
-
- listfile.close();
-}
-
-// TODO: Refactoring between this function and install_package
-std::vector<std::string> vcpkg::get_unmet_package_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db)
-{
- std::vector<std::unordered_map<std::string, std::string>> pghs;
- const fs::path packages_dir_control_file_path = paths.package_dir(spec) / "CONTROL";
-
- if (fs::exists(packages_dir_control_file_path))
- {
- try
- {
- pghs = get_paragraphs(packages_dir_control_file_path);
- }
- catch (std::runtime_error)
- {
- // ??
- }
-
- Checks::check_throw(pghs.size() == 1, "Invalid control file for package");
- return BinaryParagraph(pghs[0]).depends;
- }
-
- const fs::path ports_dir_control_file_path = paths.port_dir(spec) / "CONTROL";
- try
- {
- pghs = get_paragraphs(ports_dir_control_file_path);
- }
- catch (std::runtime_error)
- {
- // ??
- }
-
- Checks::check_exit(pghs.size() == 1, "Invalid control file for package %s", spec);
- return SourceParagraph(pghs[0]).depends;
-}
-
-void vcpkg::install_package(const vcpkg_paths& paths, const BinaryParagraph& binary_paragraph, StatusParagraphs& status_db)
-{
- StatusParagraph spgh;
- spgh.package = binary_paragraph;
- spgh.want = want_t::install;
- spgh.state = install_state_t::half_installed;
- for (const std::string& dependency : spgh.package.depends)
- {
- if (status_db.find_installed(dependency, spgh.package.target_triplet) == status_db.end())
- {
- std::abort();
- }
- }
- write_update(paths, spgh);
- status_db.insert(std::make_unique<StatusParagraph>(spgh));
-
- install_and_write_listfile(paths, spgh.package);
-
- spgh.state = install_state_t::installed;
- write_update(paths, spgh);
- status_db.insert(std::make_unique<StatusParagraph>(spgh));
-}
-
-enum class deinstall_plan
-{
- not_installed,
- dependencies_not_satisfied,
- should_deinstall
-};
-
-static deinstall_plan deinstall_package_plan(
- const StatusParagraphs::iterator package_it,
- const StatusParagraphs& status_db,
- std::vector<const StatusParagraph*>& dependencies_out)
-{
- dependencies_out.clear();
-
- if (package_it == status_db.end() || (*package_it)->state == install_state_t::not_installed)
- {
- return deinstall_plan::not_installed;
- }
-
- auto& pkg = (*package_it)->package;
-
- for (auto&& inst_pkg : status_db)
- {
- if (inst_pkg->want != want_t::install)
- continue;
- if (inst_pkg->package.target_triplet != pkg.target_triplet)
- continue;
-
- const auto& deps = inst_pkg->package.depends;
-
- if (std::find(deps.begin(), deps.end(), pkg.name) != deps.end())
- {
- dependencies_out.push_back(inst_pkg.get());
- }
- }
-
- if (!dependencies_out.empty())
- return deinstall_plan::dependencies_not_satisfied;
-
- return deinstall_plan::should_deinstall;
-}
-
-void vcpkg::deinstall_package(const vcpkg_paths& paths, const package_spec& spec, StatusParagraphs& status_db)
-{
- auto package_it = status_db.find(spec.name, spec.target_triplet);
- if (package_it == status_db.end())
- {
- System::println(System::color::success, "Package %s is not installed", spec);
- return;
- }
-
- auto& pkg = **package_it;
-
- std::vector<const StatusParagraph*> deps;
- auto plan = deinstall_package_plan(package_it, status_db, deps);
- switch (plan)
- {
- case deinstall_plan::not_installed:
- System::println(System::color::success, "Package %s is not installed", spec);
- return;
- case deinstall_plan::dependencies_not_satisfied:
- System::println(System::color::error, "Error: Cannot remove package %s:", spec);
- for (auto&& dep : deps)
- {
- System::println(" %s depends on %s", dep->package.displayname(), pkg.package.displayname());
- }
- exit(EXIT_FAILURE);
- case deinstall_plan::should_deinstall:
- break;
- default:
- Checks::unreachable();
- }
-
- pkg.want = want_t::purge;
- pkg.state = install_state_t::half_installed;
- write_update(paths, pkg);
-
- std::fstream listfile(listfile_path(paths, pkg.package), std::ios_base::in | std::ios_base::binary);
- if (listfile)
- {
- std::vector<fs::path> dirs_touched;
- std::string suffix;
- while (std::getline(listfile, suffix))
- {
- if (!suffix.empty() && suffix.back() == '\r')
- suffix.pop_back();
-
- std::error_code ec;
-
- auto target = paths.installed / suffix;
-
- auto status = fs::status(target, ec);
- if (ec)
- {
- System::println(System::color::error, "failed: %s", ec.message());
- continue;
- }
-
- if (fs::is_directory(status))
- {
- dirs_touched.push_back(target);
- }
- else if (fs::is_regular_file(status))
- {
- fs::remove(target, ec);
- if (ec)
- {
- System::println(System::color::error, "failed: %s", ec.message());
- }
- }
- else if (!fs::status_known(status))
- {
- System::println(System::color::warning, "Warning: unknown status: %s", target.string());
- }
- else
- {
- System::println(System::color::warning, "Warning: ???: %s", target.string());
- }
- }
-
- auto b = dirs_touched.rbegin();
- auto e = dirs_touched.rend();
- for (; b != e; ++b)
- {
- if (fs::directory_iterator(*b) == fs::directory_iterator())
- {
- std::error_code ec;
- fs::remove(*b, ec);
- if (ec)
- {
- System::println(System::color::error, "failed: %s", ec.message());
- }
- }
- }
-
- listfile.close();
- fs::remove(listfile_path(paths, pkg.package));
- }
-
- pkg.state = install_state_t::not_installed;
- write_update(paths, pkg);
- System::println(System::color::success, "Package %s was successfully removed", pkg.package.displayname());
-}
-
-void vcpkg::search_file(const vcpkg_paths& paths, const std::string& file_substr, const StatusParagraphs& status_db)
-{
- std::string line;
-
- for (auto&& pgh : status_db)
- {
- if (pgh->state != install_state_t::installed)
- continue;
-
- std::fstream listfile(listfile_path(paths, pgh->package));
- while (std::getline(listfile, line))
- {
- if (line.empty())
- {
- continue;
- }
-
- if (line.find(file_substr) != std::string::npos)
- {
- System::println("%s: %s", pgh->package.displayname(), line);
- }
- }
- }
-}
-
-namespace
-{
- struct Binaries
- {
- std::vector<fs::path> dlls;
- std::vector<fs::path> libs;
- };
-
- Binaries detect_files_in_directory_ending_with(const fs::path& path)
- {
- Files::check_is_directory(path);
-
- Binaries binaries;
-
- for (auto it = fs::recursive_directory_iterator(path); it != fs::recursive_directory_iterator(); ++it)
- {
- fs::path file = *it;
- // Skip if directory ?????
- if (file.extension() == ".dll")
- {
- binaries.dlls.push_back(file);
- }
- else if (file.extension() == ".lib")
- {
- binaries.libs.push_back(file);
- }
- }
-
- return binaries;
- }
-
- void copy_files_into_directory(const std::vector<fs::path>& files, const fs::path& destination_folder)
- {
- fs::create_directory(destination_folder);
-
- for (auto const& src_path : files)
- {
- fs::path dest_path = destination_folder / src_path.filename();
- fs::copy(src_path, dest_path, fs::copy_options::overwrite_existing);
- }
- }
-
- void place_library_files_in(const fs::path& include_directory, const fs::path& project_directory, const fs::path& destination_path)
- {
- Files::check_is_directory(include_directory);
- Files::check_is_directory(project_directory);
- Files::check_is_directory(destination_path);
- Binaries debug_binaries = detect_files_in_directory_ending_with(project_directory / "Debug");
- Binaries release_binaries = detect_files_in_directory_ending_with(project_directory / "Release");
-
- fs::path destination_include_directory = destination_path / "include";
- fs::copy(include_directory, destination_include_directory, fs::copy_options::recursive | fs::copy_options::overwrite_existing);
-
- copy_files_into_directory(release_binaries.dlls, destination_path / "bin");
- copy_files_into_directory(release_binaries.libs, destination_path / "lib");
-
- fs::create_directory(destination_path / "debug");
- copy_files_into_directory(debug_binaries.dlls, destination_path / "debug" / "bin");
- copy_files_into_directory(debug_binaries.libs, destination_path / "debug" / "lib");
- }
-}
-
-void vcpkg::binary_import(const vcpkg_paths& paths, const fs::path& include_directory, const fs::path& project_directory, const BinaryParagraph& control_file_data)
-{
- fs::path library_destination_path = prefix_path_for_package(paths, control_file_data);
- fs::create_directory(library_destination_path);
- place_library_files_in(include_directory, project_directory, library_destination_path);
-
- fs::path control_file_path = library_destination_path / "CONTROL";
- std::ofstream(control_file_path) << control_file_data;
-}
diff --git a/toolsrc/src/main.cpp b/toolsrc/src/main.cpp
deleted file mode 100644
index a2f6fa10f..000000000
--- a/toolsrc/src/main.cpp
+++ /dev/null
@@ -1,251 +0,0 @@
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-
-#include <iostream>
-#include <fstream>
-#include <memory>
-#include <cassert>
-#include "vcpkg.h"
-#include "vcpkg_Commands.h"
-#include "metrics.h"
-#include <Shlobj.h>
-#include "vcpkg_Files.h"
-#include "vcpkg_System.h"
-
-using namespace vcpkg;
-
-bool g_debugging = false;
-
-void invalid_command(const std::string& cmd)
-{
- System::println(System::color::error, "invalid command: %s", cmd);
- print_usage();
- exit(EXIT_FAILURE);
-}
-
-static void inner(const vcpkg_cmd_arguments& args)
-{
- TrackProperty("command", args.command);
- if (args.command.empty())
- {
- print_usage();
- exit(EXIT_FAILURE);
- }
-
- if (auto command_function = find_command(args.command, get_available_commands_type_c()))
- {
- return command_function(args);
- }
-
- fs::path vcpkg_root_dir;
- if (args.vcpkg_root_dir != nullptr)
- {
- vcpkg_root_dir = fs::absolute(Strings::utf8_to_utf16(*args.vcpkg_root_dir));
- }
- else
- {
- auto vcpkg_root_dir_env = System::wdupenv_str(L"VCPKG_ROOT");
-
- if (!vcpkg_root_dir_env.empty())
- {
- vcpkg_root_dir = fs::absolute(vcpkg_root_dir_env);
- }
- else
- {
- vcpkg_root_dir = Files::find_file_recursively_up(fs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root");
- }
- }
-
- Checks::check_exit(!vcpkg_root_dir.empty(), "Error: Could not detect vcpkg-root.");
-
- const expected<vcpkg_paths> expected_paths = vcpkg_paths::create(vcpkg_root_dir);
- Checks::check_exit(!expected_paths.error_code(), "Error: Invalid vcpkg root directory %s: %s", vcpkg_root_dir.string(), expected_paths.error_code().message());
- const vcpkg_paths paths = expected_paths.get_or_throw();
- int exit_code = _wchdir(paths.root.c_str());
- Checks::check_exit(exit_code == 0, "Changing the working dir failed");
-
- if (auto command_function = find_command(args.command, get_available_commands_type_b()))
- {
- return command_function(args, paths);
- }
-
- triplet default_target_triplet;
- if(args.target_triplet != nullptr)
- {
- default_target_triplet = {*args.target_triplet};
- }
- else
- {
- const auto vcpkg_default_triplet_env = System::wdupenv_str(L"VCPKG_DEFAULT_TRIPLET");
- if(!vcpkg_default_triplet_env.empty())
- {
- default_target_triplet = {Strings::utf16_to_utf8(vcpkg_default_triplet_env)};
- }
- else
- {
- default_target_triplet = triplet::X86_WINDOWS;
- }
- }
-
- if(!default_target_triplet.validate(paths))
- {
- System::println(System::color::error, "Error: invalid triplet: %s", default_target_triplet.value);
- TrackProperty("error", "invalid triplet: " + default_target_triplet.value);
- help_topic_valid_triplet(paths);
- exit(EXIT_FAILURE);
- }
-
- if (auto command_function = find_command(args.command, get_available_commands_type_a()))
- {
- return command_function(args, paths, default_target_triplet);
- }
-
- return invalid_command(args.command);
-}
-
-static void loadConfig()
-{
- fs::path localappdata;
- {
- // Config path in AppDataLocal
- wchar_t* localappdatapath = nullptr;
- if (S_OK != SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localappdatapath))
- __fastfail(1);
- localappdata = localappdatapath;
- CoTaskMemFree(localappdatapath);
- }
-
- try
- {
- std::string config_contents = Files::get_contents(localappdata / "vcpkg" / "config").get_or_throw();
-
- std::unordered_map<std::string, std::string> keys;
- auto pghs = parse_paragraphs(config_contents);
- if (pghs.size() > 0)
- keys = pghs[0];
-
- for (size_t x = 1; x < pghs.size(); ++x)
- {
- for (auto&& p : pghs[x])
- keys.insert(p);
- }
-
- auto user_id = keys["User-Id"];
- auto user_time = keys["User-Since"];
- Checks::check_throw(!user_id.empty() && !user_time.empty(), ""); // Use as goto to the catch statement
-
- SetUserInformation(user_id, user_time);
- return;
- }
- catch (...)
- {
- }
-
- // config file not found, could not be read, or invalid
- std::string user_id, user_time;
- InitUserInformation(user_id, user_time);
- SetUserInformation(user_id, user_time);
- try
- {
- std::error_code ec;
- fs::create_directory(localappdata / "vcpkg", ec);
- std::ofstream(localappdata / "vcpkg" / "config", std::ios_base::out | std::ios_base::trunc)
- << "User-Id: " << user_id << "\n"
- << "User-Since: " << user_time << "\n";
- }
- catch (...)
- {
- }
-}
-
-static System::Stopwatch g_timer;
-
-static std::string trim_path_from_command_line(const std::string& full_command_line)
-{
- Checks::check_exit(full_command_line.size() > 0, "Internal failure - cannot have empty command line");
-
- if (full_command_line[0] == '"')
- {
- auto it = std::find(full_command_line.cbegin() + 1, full_command_line.cend(), '"');
- if (it != full_command_line.cend()) // Skip over the quote
- ++it;
- while (it != full_command_line.cend() && *it == ' ') // Skip over a space
- ++it;
- return std::string(it, full_command_line.cend());
- }
-
- auto it = std::find(full_command_line.cbegin(), full_command_line.cend(), ' ');
- while (it != full_command_line.cend() && *it == ' ')
- ++it;
- return std::string(it, full_command_line.cend());
-}
-
-int wmain(const int argc, const wchar_t* const* const argv)
-{
- if (argc == 0)
- std::abort();
-
- std::cout.sync_with_stdio(false);
- std::cout.imbue(std::locale::classic());
-
- g_timer.start();
- atexit([]()
- {
- g_timer.stop();
- TrackMetric("elapsed_us", g_timer.microseconds());
- Flush();
- });
-
- TrackProperty("version", version());
-
- const std::string trimmed_command_line = trim_path_from_command_line(Strings::utf16_to_utf8(GetCommandLineW()));
- TrackProperty("cmdline", trimmed_command_line);
- loadConfig();
-
- const vcpkg_cmd_arguments args = vcpkg_cmd_arguments::create_from_command_line(argc, argv);
-
- if (args.printmetrics != opt_bool::unspecified)
- SetPrintMetrics(args.printmetrics == opt_bool::enabled);
- if (args.sendmetrics != opt_bool::unspecified)
- SetSendMetrics(args.sendmetrics == opt_bool::enabled);
-
- if (args.debug != opt_bool::unspecified)
- {
- g_debugging = (args.debug == opt_bool::enabled);
- }
-
- if (g_debugging)
- {
- inner(args);
- exit(EXIT_FAILURE);
- }
-
- std::string exc_msg;
- try
- {
- inner(args);
- exit(EXIT_FAILURE);
- }
- catch (std::exception& e)
- {
- exc_msg = e.what();
- }
- catch (...)
- {
- exc_msg = "unknown error(...)";
- }
- TrackProperty("error", exc_msg);
- std::cerr
- << "vcpkg.exe has crashed.\n"
- << "Please send an email to:\n"
- << " vcpkg@microsoft.com\n"
- << "containing a brief summary of what you were trying to do and the following data blob:\n"
- << "\n"
- << "Version=" << version() << "\n"
- << "EXCEPTION='" << exc_msg << "'\n"
- << "CMD=\n";
- for (int x = 0; x < argc; ++x)
- std::cerr << argv[x] << "|\n";
- std::cerr
- << "\n";
-}
diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp
index 610c71ed1..d0e20fe2d 100644
--- a/toolsrc/src/metrics.cpp
+++ b/toolsrc/src/metrics.cpp
@@ -1,21 +1,9 @@
+#include "pch.h"
#include "metrics.h"
-#include <utility>
-#include <array>
-#include <string>
-#include <iostream>
-#include <vector>
-#include <sys/timeb.h>
-#include <time.h>
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-#include <winhttp.h>
-#include <fstream>
-#include <filesystem>
+#include "filesystem_fs.h"
#include "vcpkg_Strings.h"
#include "vcpkg_System.h"
-namespace fs = std::tr2::sys;
-
namespace vcpkg
{
static std::string GetCurrentDateTime()
@@ -44,7 +32,7 @@ namespace vcpkg
static std::string GenerateRandomUUID()
{
- int partSizes[] = {8, 4, 4, 4, 12};
+ int partSizes[] = { 8, 4, 4, 4, 12 };
char uuid[37];
memset(uuid, 0, sizeof(uuid));
int num;
@@ -113,7 +101,7 @@ namespace vcpkg
// Note: this treats incoming Strings as Latin-1
static constexpr const char hex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
encoded.append("\\u00");
encoded.push_back(hex[ch / 16]);
encoded.push_back(hex[ch % 16]);
@@ -237,6 +225,16 @@ true
return DISABLE_METRICS == 0;
}
+ std::wstring GetSQMUser()
+ {
+ auto hkcu_sqmclient = System::get_registry_string(HKEY_CURRENT_USER, LR"(Software\Microsoft\SQMClient)", L"UserId");
+
+ if (hkcu_sqmclient)
+ return std::move(*hkcu_sqmclient);
+ else
+ return L"{}";
+ }
+
void SetUserInformation(const std::string& user_id, const std::string& first_use_time)
{
g_metricmessage.user_id = user_id;
@@ -334,8 +332,7 @@ true
if (bResults)
{
DWORD availableData = 0, readData = 0, totalData = 0;
-
- while ((bResults = WinHttpQueryDataAvailable(hRequest, &availableData)) && availableData > 0)
+ while ((bResults = WinHttpQueryDataAvailable(hRequest, &availableData)) == TRUE && availableData > 0)
{
responseBuffer.resize(responseBuffer.size() + availableData);
@@ -419,7 +416,7 @@ true
const fs::path vcpkg_metrics_txt_path = temp_folder_path / ("vcpkg" + GenerateRandomUUID() + ".txt");
std::ofstream(vcpkg_metrics_txt_path) << payload;
- const std::wstring cmdLine = Strings::format(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native());
- System::cmd_execute(cmdLine);
+ const std::wstring cmdLine = Strings::wformat(L"start %s %s", temp_folder_path_exe.native(), vcpkg_metrics_txt_path.native());
+ System::cmd_execute_clean(cmdLine);
}
}
diff --git a/toolsrc/src/opt_bool.cpp b/toolsrc/src/opt_bool.cpp
new file mode 100644
index 000000000..324936fb4
--- /dev/null
+++ b/toolsrc/src/opt_bool.cpp
@@ -0,0 +1,29 @@
+#include "pch.h"
+#include "opt_bool.h"
+#include "vcpkg_Checks.h"
+
+namespace vcpkg::opt_bool
+{
+ static const std::string UNSPECIFIED_NAME = "unspecified";
+ static const std::string ENABLED_NAME = "enabled";
+ static const std::string DISABLED_NAME = "disabled";
+ type parse(const std::string& s)
+ {
+ if (s == UNSPECIFIED_NAME)
+ {
+ return opt_bool_t::UNSPECIFIED;
+ }
+
+ if (s == ENABLED_NAME)
+ {
+ return opt_bool_t::ENABLED;
+ }
+
+ if (s == DISABLED_NAME)
+ {
+ return opt_bool_t::DISABLED;
+ }
+
+ Checks::exit_with_message("Could not convert string [%s] to opt_bool", s);
+ }
+}
diff --git a/toolsrc/src/package_spec.cpp b/toolsrc/src/package_spec.cpp
index efa54734e..2713e219f 100644
--- a/toolsrc/src/package_spec.cpp
+++ b/toolsrc/src/package_spec.cpp
@@ -1,46 +1,82 @@
+#include "pch.h"
#include "package_spec.h"
namespace vcpkg
{
- expected<package_spec> package_spec::from_string(const std::string& spec, const triplet& default_target_triplet)
+ static bool is_valid_package_spec_char(char c)
{
- auto pos = spec.find(':');
+ return (c == '-') || isdigit(c) || (isalpha(c) && islower(c));
+ }
+
+ expected<package_spec> package_spec::from_string(const std::string& spec_as_string, const triplet& default_target_triplet)
+ {
+ auto pos = spec_as_string.find(':');
if (pos == std::string::npos)
{
- return package_spec{spec, default_target_triplet};
+ return from_name_and_triplet(spec_as_string, default_target_triplet);
}
- auto pos2 = spec.find(':', pos + 1);
+ auto pos2 = spec_as_string.find(':', pos + 1);
if (pos2 != std::string::npos)
{
- return std::error_code(package_spec_parse_result::too_many_colons);
+ return std::error_code(package_spec_parse_result::TOO_MANY_COLONS);
+ }
+
+ const std::string name = spec_as_string.substr(0, pos);
+ const triplet target_triplet = triplet::from_canonical_name(spec_as_string.substr(pos + 1));
+ return from_name_and_triplet(name, target_triplet);
+ }
+
+ expected<package_spec> package_spec::from_name_and_triplet(const std::string& name, const triplet& target_triplet)
+ {
+ if (std::find_if_not(name.cbegin(), name.cend(), is_valid_package_spec_char) != name.end())
+ {
+ return std::error_code(package_spec_parse_result::INVALID_CHARACTERS);
}
- return package_spec{spec.substr(0, pos), spec.substr(pos + 1)};
+ package_spec p;
+ p.m_name = name;
+ p.m_target_triplet = target_triplet;
+ return p;
+ }
+
+ const std::string& package_spec::name() const
+ {
+ return this->m_name;
+ }
+
+ const triplet& package_spec::target_triplet() const
+ {
+ return this->m_target_triplet;
+ }
+
+ std::string package_spec::display_name() const
+ {
+ return Strings::format("%s:%s", this->name(), this->target_triplet());
}
std::string package_spec::dir() const
{
- return Strings::format("%s_%s", this->name, this->target_triplet);
+ return Strings::format("%s_%s", this->m_name, this->m_target_triplet);
}
- std::string to_string(const package_spec& spec)
+ std::string package_spec::toString() const
{
- return Strings::format("%s:%s", spec.name, spec.target_triplet);
+ return this->display_name();
}
std::string to_printf_arg(const package_spec& spec)
{
- return to_string(spec);
+ return spec.toString();
}
bool operator==(const package_spec& left, const package_spec& right)
{
- return left.name == right.name && left.target_triplet == right.target_triplet;
+ return left.name() == right.name() && left.target_triplet() == right.target_triplet();
}
std::ostream& operator<<(std::ostream& os, const package_spec& spec)
{
- return os << to_string(spec);
+ return os << spec.toString();
}
}
diff --git a/toolsrc/src/package_spec_parse_result.cpp b/toolsrc/src/package_spec_parse_result.cpp
index 757b6df53..892232c2e 100644
--- a/toolsrc/src/package_spec_parse_result.cpp
+++ b/toolsrc/src/package_spec_parse_result.cpp
@@ -1,5 +1,5 @@
-#include <package_spec.h>
-#include <system_error>
+#include "pch.h"
+#include "package_spec.h"
#include "package_spec_parse_result.h"
namespace vcpkg
@@ -13,10 +13,12 @@ namespace vcpkg
{
switch (static_cast<package_spec_parse_result>(ev))
{
- case package_spec_parse_result::success:
+ case package_spec_parse_result::SUCCESS:
return "OK";
- case package_spec_parse_result::too_many_colons:
+ case package_spec_parse_result::TOO_MANY_COLONS:
return "Too many colons";
+ case package_spec_parse_result::INVALID_CHARACTERS:
+ return "Contains invalid characters. Only alphanumeric lowercase ASCII characters and dashes are allowed";
default:
Checks::unreachable();
}
diff --git a/toolsrc/src/pch.cpp b/toolsrc/src/pch.cpp
new file mode 100644
index 000000000..17305716a
--- /dev/null
+++ b/toolsrc/src/pch.cpp
@@ -0,0 +1 @@
+#include "pch.h" \ No newline at end of file
diff --git a/toolsrc/src/post_build_lint.cpp b/toolsrc/src/post_build_lint.cpp
deleted file mode 100644
index 1d4ca0f67..000000000
--- a/toolsrc/src/post_build_lint.cpp
+++ /dev/null
@@ -1,356 +0,0 @@
-#include <filesystem>
-#include "vcpkg_paths.h"
-#include "package_spec.h"
-#include <iterator>
-#include <functional>
-#include "vcpkg_System.h"
-
-namespace fs = std::tr2::sys;
-
-namespace vcpkg
-{
- enum class lint_status
- {
- SUCCESS = 0,
- ERROR = 1
- };
-
- static const fs::path DUMPBIN_EXE = R"(%VS140COMNTOOLS%\..\..\VC\bin\dumpbin.exe)";
-
- namespace
- {
- void print_vector_of_files(const std::vector<fs::path>& paths)
- {
- System::println("");
- for (const fs::path& p : paths)
- {
- System::println(" %s", p.generic_string());
- }
- System::println("");
- }
-
- template <class Pred>
- void recursive_find_matching_paths_in_dir(const fs::path& dir, const Pred predicate, std::vector<fs::path>& output)
- {
- std::copy_if(fs::recursive_directory_iterator(dir), fs::recursive_directory_iterator(), std::back_inserter(output), predicate);
- }
-
- void recursive_find_files_with_extension_in_dir(const fs::path& dir, const std::string& extension, std::vector<fs::path>& output)
- {
- recursive_find_matching_paths_in_dir(dir, [&extension](const fs::path& current)
- {
- return !fs::is_directory(current) && current.extension() == extension;
- }, output);
- }
- }
-
- static lint_status check_for_files_in_include_directory(const package_spec& spec, const vcpkg_paths& paths)
- {
- const fs::path include_dir = paths.packages / spec.dir() / "include";
- if (!fs::exists(include_dir) || fs::is_empty(include_dir))
- {
- System::println(System::color::warning, "The folder /include is empty. This indicates the library was not correctly installed.");
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- static lint_status check_for_files_in_debug_include_directory(const package_spec& spec, const vcpkg_paths& paths)
- {
- const fs::path debug_include_dir = paths.packages / spec.dir() / "debug" / "include";
- std::vector<fs::path> files_found;
-
- recursive_find_matching_paths_in_dir(debug_include_dir, [&](const fs::path& current)
- {
- return !fs::is_directory(current) && current.extension() != ".ifc";
- }, files_found);
-
- if (!files_found.empty())
- {
- System::println(System::color::warning, "Include files should not be duplicated into the /debug/include directory. If this cannot be disabled in the project cmake, use\n"
- " file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include)"
- );
- return
- lint_status::ERROR;
- }
-
- return
- lint_status::SUCCESS;
- }
-
- static lint_status check_for_files_in_debug_share_directory(const package_spec& spec, const vcpkg_paths& paths)
- {
- const fs::path debug_share = paths.packages / spec.dir() / "debug" / "share";
-
- if (fs::exists(debug_share) && !fs::is_empty(debug_share))
- {
- System::println(System::color::warning, "No files should be present in /debug/share");
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- static lint_status check_folder_lib_cmake(const package_spec& spec, const vcpkg_paths& paths)
- {
- const fs::path lib_cmake = paths.packages / spec.dir() / "lib" / "cmake";
- if (fs::exists(lib_cmake))
- {
- System::println(System::color::warning, "The /lib/cmake folder should be moved to just /cmake");
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- static lint_status check_for_misplaced_cmake_files(const package_spec& spec, const vcpkg_paths& paths)
- {
- const fs::path current_packages_dir = paths.packages / spec.dir();
- std::vector<fs::path> misplaced_cmake_files;
- recursive_find_files_with_extension_in_dir(current_packages_dir / "cmake", ".cmake", misplaced_cmake_files);
- recursive_find_files_with_extension_in_dir(current_packages_dir / "debug" / "cmake", ".cmake", misplaced_cmake_files);
- recursive_find_files_with_extension_in_dir(current_packages_dir / "lib" / "cmake", ".cmake", misplaced_cmake_files);
- recursive_find_files_with_extension_in_dir(current_packages_dir / "debug" / "lib" / "cmake", ".cmake", misplaced_cmake_files);
-
- if (!misplaced_cmake_files.empty())
- {
- System::println(System::color::warning, "The following cmake files were found outside /share/%s. Please place cmake files in /share/%s.", spec.name, spec.name);
- print_vector_of_files(misplaced_cmake_files);
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- static lint_status check_folder_debug_lib_cmake(const package_spec& spec, const vcpkg_paths& paths)
- {
- const fs::path lib_cmake_debug = paths.packages / spec.dir() / "debug" / "lib" / "cmake";
- if (fs::exists(lib_cmake_debug))
- {
- System::println(System::color::warning, "The /debug/lib/cmake folder should be moved to just /debug/cmake");
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- static lint_status check_for_dlls_in_lib_dirs(const package_spec& spec, const vcpkg_paths& paths)
- {
- std::vector<fs::path> dlls;
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "lib", ".dll", dlls);
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "debug" / "lib", ".dll", dlls);
-
- if (!dlls.empty())
- {
- System::println(System::color::warning, "\nThe following dlls were found in /lib and /debug/lib. Please move them to /bin or /debug/bin, respectively.");
- print_vector_of_files(dlls);
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- static lint_status check_for_copyright_file(const package_spec& spec, const vcpkg_paths& paths)
- {
- const fs::path copyright_file = paths.packages / spec.dir() / "share" / spec.name / "copyright";
- if (fs::exists(copyright_file))
- {
- return lint_status::SUCCESS;
- }
- const fs::path current_buildtrees_dir = paths.buildtrees / spec.name;
- const fs::path current_buildtrees_dir_src = current_buildtrees_dir / "src";
-
- std::vector<fs::path> potential_copyright_files;
- // Only searching one level deep
- for (auto it = fs::recursive_directory_iterator(current_buildtrees_dir_src); it != fs::recursive_directory_iterator(); ++it)
- {
- if (it.depth() > 1)
- {
- continue;
- }
-
- const std::string filename = it->path().filename().string();
- if (filename == "LICENSE" || filename == "LICENSE.txt" || filename == "COPYING")
- {
- potential_copyright_files.push_back(it->path());
- }
- }
-
- System::println(System::color::warning, "The software license must be available at ${CURRENT_PACKAGES_DIR}/share/%s/copyright .", spec.name);
- if (potential_copyright_files.size() == 1) // if there is only one candidate, provide the cmake lines needed to place it in the proper location
- {
- const fs::path found_file = potential_copyright_files[0];
- const fs::path relative_path = found_file.string().erase(0, current_buildtrees_dir.string().size() + 1); // The +1 is needed to remove the "/"
- System::println("\n file(COPY ${CURRENT_BUILDTREES_DIR}/%s DESTINATION ${CURRENT_PACKAGES_DIR}/share/%s)\n"
- " file(RENAME ${CURRENT_PACKAGES_DIR}/share/%s/%s ${CURRENT_PACKAGES_DIR}/share/%s/copyright)",
- relative_path.generic_string(), spec.name, spec.name, found_file.filename().generic_string(), spec.name);
- return lint_status::ERROR;
- }
-
- if (potential_copyright_files.size() > 1)
- {
- System::println(System::color::warning, "The following files are potential copyright files:");
- print_vector_of_files(potential_copyright_files);
- }
-
- const fs::path current_packages_dir = paths.packages / spec.dir();
- System::println(" %s/share/%s/copyright", current_packages_dir.generic_string(), spec.name);
-
- return lint_status::ERROR;
- }
-
- static lint_status check_for_exes(const package_spec& spec, const vcpkg_paths& paths)
- {
- std::vector<fs::path> exes;
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "bin", ".exe", exes);
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "debug" / "bin", ".exe", exes);
-
- if (!exes.empty())
- {
- System::println(System::color::warning, "The following EXEs were found in /bin and /debug/bin. EXEs are not valid distribution targets.");
- print_vector_of_files(exes);
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- static lint_status check_exports_of_dlls(const std::vector<fs::path>& dlls)
- {
- std::vector<fs::path> dlls_with_no_exports;
- for (const fs::path& dll : dlls)
- {
- const std::wstring cmd_line = Strings::format(LR"("%s" /exports "%s")", DUMPBIN_EXE.native(), dll.native());
- System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
- Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
-
- if (ec_data.output.find("ordinal hint RVA name") == std::string::npos)
- {
- dlls_with_no_exports.push_back(dll);
- }
- }
-
- if (!dlls_with_no_exports.empty())
- {
- System::println(System::color::warning, "The following DLLs have no exports:");
- print_vector_of_files(dlls_with_no_exports);
- System::println(System::color::warning, "DLLs without any exports are likely a bug in the build script.");
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- static lint_status check_uwp_bit_of_dlls(const std::string& expected_system_name, const std::vector<fs::path>& dlls)
- {
- if (expected_system_name != "uwp")
- {
- return lint_status::SUCCESS;
- }
-
- std::vector<fs::path> dlls_with_improper_uwp_bit;
- for (const fs::path& dll : dlls)
- {
- const std::wstring cmd_line = Strings::format(LR"("%s" /headers "%s")", DUMPBIN_EXE.native(), dll.native());
- System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
- Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
-
- if (ec_data.output.find("App Container") == std::string::npos)
- {
- dlls_with_improper_uwp_bit.push_back(dll);
- }
- }
-
- if (!dlls_with_improper_uwp_bit.empty())
- {
- System::println(System::color::warning, "The following DLLs do not have the App Container bit set:");
- print_vector_of_files(dlls_with_improper_uwp_bit);
- System::println(System::color::warning, "This bit is required for Windows Store apps.");
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- struct file_and_arch
- {
- fs::path file;
- std::string actual_arch;
- };
-
- static lint_status check_architecture(const std::string& expected_architecture, const std::vector<fs::path>& files)
- {
- std::vector<file_and_arch> binaries_with_invalid_architecture;
- for (const fs::path& f : files)
- {
- const std::wstring cmd_line = Strings::format(LR"("%s" /headers "%s" | findstr machine)", DUMPBIN_EXE.native(), f.native());
- System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line);
- Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line));
-
- if (Strings::case_insensitive_find(ec_data.output, expected_architecture) == ec_data.output.end())
- {
- binaries_with_invalid_architecture.push_back({f, ec_data.output});
- }
- }
-
- if (!binaries_with_invalid_architecture.empty())
- {
- System::println(System::color::warning, "The following files were built for an incorrect architecture:");
- System::println("");
- for (const file_and_arch& b : binaries_with_invalid_architecture)
- {
- System::println(" %s", b.file.generic_string());
- System::println("Expected %s, but was:\n %s", expected_architecture, b.actual_arch);
- }
- System::println("");
-
- return lint_status::ERROR;
- }
-
- return lint_status::SUCCESS;
- }
-
- static void operator +=(unsigned int& left, const lint_status& right)
- {
- left += static_cast<unsigned int>(right);
- }
-
- void perform_all_checks(const package_spec& spec, const vcpkg_paths& paths)
- {
- System::println("-- Performing post-build validation");
- unsigned int error_count = 0;
- error_count += check_for_files_in_include_directory(spec, paths);
- error_count += check_for_files_in_debug_include_directory(spec, paths);
- error_count += check_for_files_in_debug_share_directory(spec, paths);
- error_count += check_folder_lib_cmake(spec, paths);
- error_count += check_for_misplaced_cmake_files(spec, paths);
- error_count += check_folder_debug_lib_cmake(spec, paths);
- error_count += check_for_dlls_in_lib_dirs(spec, paths);
- error_count += check_for_copyright_file(spec, paths);
- error_count += check_for_exes(spec, paths);
-
- std::vector<fs::path> dlls;
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "bin", ".dll", dlls);
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "debug" / "bin", ".dll", dlls);
-
- error_count += check_exports_of_dlls(dlls);
- error_count += check_uwp_bit_of_dlls(spec.target_triplet.system(), dlls);
- error_count += check_architecture(spec.target_triplet.architecture(), dlls);
-
- std::vector<fs::path> libs;
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "lib", ".lib", libs);
- recursive_find_files_with_extension_in_dir(paths.packages / spec.dir() / "debug" / "lib", ".lib", libs);
-
- error_count += check_architecture(spec.target_triplet.architecture(), libs);
-
- if (error_count != 0)
- {
- const fs::path portfile = paths.ports / spec.name / "portfile.cmake";
- System::println(System::color::error, "Found %d error(s). Please correct the portfile:\n %s", error_count, portfile.string());
- exit(EXIT_FAILURE);
- }
-
- System::println("-- Performing post-build validation done");
- }
-}
diff --git a/toolsrc/src/tests_dependencies.cpp b/toolsrc/src/tests_dependencies.cpp
new file mode 100644
index 000000000..bce1cab0e
--- /dev/null
+++ b/toolsrc/src/tests_dependencies.cpp
@@ -0,0 +1,39 @@
+#include "CppUnitTest.h"
+#include "SourceParagraph.h"
+#include "triplet.h"
+
+#pragma comment(lib,"version")
+#pragma comment(lib,"winhttp")
+
+using namespace Microsoft::VisualStudio::CppUnitTestFramework;
+
+using namespace vcpkg;
+
+namespace UnitTest1
+{
+ TEST_CLASS(DependencyTests)
+ {
+ public:
+ TEST_METHOD(parse_depends_one)
+ {
+ auto v = expand_qualified_dependencies(parse_depends("libA [windows]"));
+ Assert::AreEqual(size_t(1), v.size());
+ Assert::AreEqual("libA", v[0].name.c_str());
+ Assert::AreEqual("windows", v[0].qualifier.c_str());
+ }
+
+ TEST_METHOD(filter_depends)
+ {
+ auto deps = expand_qualified_dependencies(parse_depends("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());
+ Assert::AreEqual("libB", v[1].c_str());
+
+ auto v2 = filter_dependencies(deps, triplet::ARM_UWP);
+ Assert::AreEqual(size_t(2), v.size());
+ Assert::AreEqual("libB", v2[0].c_str());
+ Assert::AreEqual("libC", v2[1].c_str());
+ }
+ };
+}
diff --git a/toolsrc/src/test.cpp b/toolsrc/src/tests_paragraph.cpp
index 9c5f1dc87..fb20eee82 100644
--- a/toolsrc/src/test.cpp
+++ b/toolsrc/src/tests_paragraph.cpp
@@ -1,19 +1,20 @@
#include "CppUnitTest.h"
-#include "vcpkg.h"
+#include "Paragraphs.h"
+#include "BinaryParagraph.h"
#pragma comment(lib,"version")
#pragma comment(lib,"winhttp")
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
-namespace Microsoft { namespace VisualStudio { namespace CppUnitTestFramework
+namespace Microsoft::VisualStudio::CppUnitTestFramework
{
template <>
inline std::wstring ToString<vcpkg::package_spec_parse_result>(const vcpkg::package_spec_parse_result& t)
{
return ToString(static_cast<uint32_t>(t));
}
-}}}
+}
namespace UnitTest1
{
@@ -48,7 +49,7 @@ namespace UnitTest1
Assert::AreEqual("m", pgh.maintainer.c_str());
Assert::AreEqual("d", pgh.description.c_str());
Assert::AreEqual(size_t(1), pgh.depends.size());
- Assert::AreEqual("bd", pgh.depends[0].c_str());
+ Assert::AreEqual("bd", pgh.depends[0].name.c_str());
}
TEST_METHOD(SourceParagraph_Two_Depends)
@@ -60,8 +61,8 @@ namespace UnitTest1
});
Assert::AreEqual(size_t(2), pgh.depends.size());
- Assert::AreEqual("z", pgh.depends[0].c_str());
- Assert::AreEqual("openssl", pgh.depends[1].c_str());
+ Assert::AreEqual("z", pgh.depends[0].name.c_str());
+ Assert::AreEqual("openssl", pgh.depends[1].name.c_str());
}
TEST_METHOD(SourceParagraph_Three_Depends)
@@ -73,9 +74,28 @@ namespace UnitTest1
});
Assert::AreEqual(size_t(3), pgh.depends.size());
- Assert::AreEqual("z", pgh.depends[0].c_str());
- Assert::AreEqual("openssl", pgh.depends[1].c_str());
- Assert::AreEqual("xyz", pgh.depends[2].c_str());
+ Assert::AreEqual("z", pgh.depends[0].name.c_str());
+ Assert::AreEqual("openssl", pgh.depends[1].name.c_str());
+ Assert::AreEqual("xyz", pgh.depends[2].name.c_str());
+ }
+
+ TEST_METHOD(SourceParagraph_Construct_Qualified_Depends)
+ {
+ vcpkg::SourceParagraph pgh({
+ {"Source", "zlib"},
+ {"Version", "1.2.8"},
+ {"Build-Depends", "libA [windows], libB [uwp]"}
+ });
+
+ Assert::AreEqual("zlib", pgh.name.c_str());
+ Assert::AreEqual("1.2.8", pgh.version.c_str());
+ Assert::AreEqual("", pgh.maintainer.c_str());
+ Assert::AreEqual("", pgh.description.c_str());
+ Assert::AreEqual(size_t(2), pgh.depends.size());
+ Assert::AreEqual("libA", pgh.depends[0].name.c_str());
+ Assert::AreEqual("windows", pgh.depends[0].qualifier.c_str());
+ Assert::AreEqual("libB", pgh.depends[1].name.c_str());
+ Assert::AreEqual("uwp", pgh.depends[1].qualifier.c_str());
}
TEST_METHOD(BinaryParagraph_Construct_Minimum)
@@ -83,15 +103,15 @@ namespace UnitTest1
vcpkg::BinaryParagraph pgh({
{"Package", "zlib"},
{"Version", "1.2.8"},
- {"Architecture", "a"},
+ {"Architecture", "x86-windows"},
{"Multi-Arch", "same"},
});
- Assert::AreEqual("zlib", pgh.name.c_str());
+ Assert::AreEqual("zlib", pgh.spec.name().c_str());
Assert::AreEqual("1.2.8", pgh.version.c_str());
Assert::AreEqual("", pgh.maintainer.c_str());
Assert::AreEqual("", pgh.description.c_str());
- Assert::AreEqual("a", pgh.target_triplet.value.c_str());
+ Assert::AreEqual("x86-windows", pgh.spec.target_triplet().canonical_name().c_str());
Assert::AreEqual(size_t(0), pgh.depends.size());
}
@@ -100,13 +120,13 @@ namespace UnitTest1
vcpkg::BinaryParagraph pgh({
{"Package", "s"},
{"Version", "v"},
- {"Architecture", "a"},
+ {"Architecture", "x86-windows"},
{"Multi-Arch", "same"},
{"Maintainer", "m"},
{"Description", "d"},
{"Depends", "bd"}
});
- Assert::AreEqual("s", pgh.name.c_str());
+ Assert::AreEqual("s", pgh.spec.name().c_str());
Assert::AreEqual("v", pgh.version.c_str());
Assert::AreEqual("m", pgh.maintainer.c_str());
Assert::AreEqual("d", pgh.description.c_str());
@@ -119,7 +139,7 @@ namespace UnitTest1
vcpkg::BinaryParagraph pgh({
{"Package", "zlib"},
{"Version", "1.2.8"},
- {"Architecture", "a"},
+ {"Architecture", "x86-windows"},
{"Multi-Arch", "same"},
{"Depends", "a, b, c"},
});
@@ -133,14 +153,14 @@ namespace UnitTest1
TEST_METHOD(parse_paragraphs_empty)
{
const char* str = "";
- auto pghs = vcpkg::parse_paragraphs(str);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(str);
Assert::IsTrue(pghs.empty());
}
TEST_METHOD(parse_paragraphs_one_field)
{
const char* str = "f1: v1";
- auto pghs = vcpkg::parse_paragraphs(str);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(str);
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual(size_t(1), pghs[0].size());
Assert::AreEqual("v1", pghs[0]["f1"].c_str());
@@ -151,7 +171,7 @@ namespace UnitTest1
const char* str =
"f1: v1\n"
"f2: v2";
- auto pghs = vcpkg::parse_paragraphs(str);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(str);
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual(size_t(2), pghs[0].size());
Assert::AreEqual("v1", pghs[0]["f1"].c_str());
@@ -166,7 +186,7 @@ namespace UnitTest1
"\n"
"f3: v3\n"
"f4: v4";
- auto pghs = vcpkg::parse_paragraphs(str);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(str);
Assert::AreEqual(size_t(2), pghs.size());
Assert::AreEqual(size_t(2), pghs[0].size());
Assert::AreEqual("v1", pghs[0]["f1"].c_str());
@@ -184,7 +204,7 @@ namespace UnitTest1
"F:\n"
"0:\n"
"F-2:\n";
- auto pghs = vcpkg::parse_paragraphs(str);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(str);
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual(size_t(5), pghs[0].size());
}
@@ -198,7 +218,7 @@ namespace UnitTest1
"\n"
"f3: v3\n"
"f4: v4";
- auto pghs = vcpkg::parse_paragraphs(str);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(str);
Assert::AreEqual(size_t(2), pghs.size());
}
@@ -207,7 +227,7 @@ namespace UnitTest1
const char* str =
"f1:\n"
"f2: ";
- auto pghs = vcpkg::parse_paragraphs(str);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(str);
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual(size_t(2), pghs[0].size());
Assert::AreEqual("", pghs[0]["f1"].c_str());
@@ -223,7 +243,7 @@ namespace UnitTest1
"f2:\r\n"
" f2\r\n"
" continue\r\n";
- auto pghs = vcpkg::parse_paragraphs(str);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(str);
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual("simple\n f1", pghs[0]["f1"].c_str());
Assert::AreEqual("\n f2\n continue", pghs[0]["f2"].c_str());
@@ -237,7 +257,7 @@ namespace UnitTest1
"\r\n"
"f3: v3\r\n"
"f4: v4";
- auto pghs = vcpkg::parse_paragraphs(str);
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(str);
Assert::AreEqual(size_t(2), pghs.size());
Assert::AreEqual(size_t(2), pghs[0].size());
Assert::AreEqual("v1", pghs[0]["f1"].c_str());
@@ -253,16 +273,16 @@ namespace UnitTest1
vcpkg::BinaryParagraph pgh({
{"Package", "zlib"},
{"Version", "1.2.8"},
- {"Architecture", "a"},
+ {"Architecture", "x86-windows"},
{"Multi-Arch", "same"},
});
ss << pgh;
- auto pghs = vcpkg::parse_paragraphs(ss.str());
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str());
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual(size_t(4), pghs[0].size());
Assert::AreEqual("zlib", pghs[0]["Package"].c_str());
Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str());
- Assert::AreEqual("a", pghs[0]["Architecture"].c_str());
+ Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str());
Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str());
}
@@ -272,19 +292,19 @@ namespace UnitTest1
vcpkg::BinaryParagraph pgh({
{"Package", "zlib"},
{"Version", "1.2.8"},
- {"Architecture", "a"},
+ {"Architecture", "x86-windows"},
{"Description", "first line\n second line"},
{"Maintainer", "abc <abc@abc.abc>"},
{"Depends", "dep"},
{"Multi-Arch", "same"},
});
ss << pgh;
- auto pghs = vcpkg::parse_paragraphs(ss.str());
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str());
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual(size_t(7), pghs[0].size());
Assert::AreEqual("zlib", pghs[0]["Package"].c_str());
Assert::AreEqual("1.2.8", pghs[0]["Version"].c_str());
- Assert::AreEqual("a", pghs[0]["Architecture"].c_str());
+ Assert::AreEqual("x86-windows", pghs[0]["Architecture"].c_str());
Assert::AreEqual("same", pghs[0]["Multi-Arch"].c_str());
Assert::AreEqual("first line\n second line", pghs[0]["Description"].c_str());
Assert::AreEqual("dep", pghs[0]["Depends"].c_str());
@@ -296,12 +316,12 @@ namespace UnitTest1
vcpkg::BinaryParagraph pgh({
{"Package", "zlib"},
{"Version", "1.2.8"},
- {"Architecture", "a"},
+ {"Architecture", "x86-windows"},
{"Multi-Arch", "same"},
{"Depends", "a, b, c"},
});
ss << pgh;
- auto pghs = vcpkg::parse_paragraphs(ss.str());
+ auto pghs = vcpkg::Paragraphs::parse_paragraphs(ss.str());
Assert::AreEqual(size_t(1), pghs.size());
Assert::AreEqual("a, b, c", pghs[0]["Depends"].c_str());
}
@@ -309,23 +329,23 @@ namespace UnitTest1
TEST_METHOD(package_spec_parse)
{
vcpkg::expected<vcpkg::package_spec> spec = vcpkg::package_spec::from_string("zlib", vcpkg::triplet::X86_WINDOWS);
- Assert::AreEqual(vcpkg::package_spec_parse_result::success, vcpkg::to_package_spec_parse_result(spec.error_code()));
- Assert::AreEqual("zlib", spec.get()->name.c_str());
- Assert::AreEqual(vcpkg::triplet::X86_WINDOWS.value, spec.get()->target_triplet.value);
+ Assert::AreEqual(vcpkg::package_spec_parse_result::SUCCESS, vcpkg::to_package_spec_parse_result(spec.error_code()));
+ Assert::AreEqual("zlib", spec.get()->name().c_str());
+ Assert::AreEqual(vcpkg::triplet::X86_WINDOWS.canonical_name(), spec.get()->target_triplet().canonical_name());
}
TEST_METHOD(package_spec_parse_with_arch)
{
vcpkg::expected<vcpkg::package_spec> spec = vcpkg::package_spec::from_string("zlib:x64-uwp", vcpkg::triplet::X86_WINDOWS);
- Assert::AreEqual(vcpkg::package_spec_parse_result::success, vcpkg::to_package_spec_parse_result(spec.error_code()));
- Assert::AreEqual("zlib", spec.get()->name.c_str());
- Assert::AreEqual(vcpkg::triplet::X64_UWP.value, spec.get()->target_triplet.value);
+ Assert::AreEqual(vcpkg::package_spec_parse_result::SUCCESS, vcpkg::to_package_spec_parse_result(spec.error_code()));
+ Assert::AreEqual("zlib", spec.get()->name().c_str());
+ Assert::AreEqual(vcpkg::triplet::X64_UWP.canonical_name(), spec.get()->target_triplet().canonical_name());
}
TEST_METHOD(package_spec_parse_with_multiple_colon)
{
auto ec = vcpkg::package_spec::from_string("zlib:x86-uwp:", vcpkg::triplet::X86_WINDOWS).error_code();
- Assert::AreEqual(vcpkg::package_spec_parse_result::too_many_colons, vcpkg::to_package_spec_parse_result(ec));
+ Assert::AreEqual(vcpkg::package_spec_parse_result::TOO_MANY_COLONS, vcpkg::to_package_spec_parse_result(ec));
}
TEST_METHOD(utf8_to_utf16)
diff --git a/toolsrc/src/triplet.cpp b/toolsrc/src/triplet.cpp
index 14f19d5cd..d91e0e68f 100644
--- a/toolsrc/src/triplet.cpp
+++ b/toolsrc/src/triplet.cpp
@@ -1,19 +1,19 @@
+#include "pch.h"
#include "triplet.h"
-#include "vcpkg.h"
-#include "vcpkg_System.h"
#include "vcpkg_Checks.h"
+#include "vcpkg_Strings.h"
namespace vcpkg
{
- const triplet triplet::X86_WINDOWS = {"x86-windows"};
- const triplet triplet::X64_WINDOWS = {"x64-windows"};
- const triplet triplet::X86_UWP = {"x86-uwp"};
- const triplet triplet::X64_UWP = {"x64-uwp"};
- const triplet triplet::ARM_UWP = {"arm-uwp"};
+ const triplet triplet::X86_WINDOWS = from_canonical_name("x86-windows");
+ const triplet triplet::X64_WINDOWS = from_canonical_name("x64-windows");
+ const triplet triplet::X86_UWP = from_canonical_name("x86-uwp");
+ const triplet triplet::X64_UWP = from_canonical_name("x64-uwp");
+ const triplet triplet::ARM_UWP = from_canonical_name("arm-uwp");
std::string to_string(const triplet& t)
{
- return t.value;
+ return t.canonical_name();
}
std::string to_printf_arg(const triplet& t)
@@ -23,7 +23,7 @@ namespace vcpkg
bool operator==(const triplet& left, const triplet& right)
{
- return left.value == right.value;
+ return left.canonical_name() == right.canonical_name();
}
bool operator!=(const triplet& left, const triplet& right)
@@ -36,40 +36,31 @@ namespace vcpkg
return os << to_string(t);
}
- std::string triplet::architecture() const
+ triplet triplet::from_canonical_name(const std::string& triplet_as_string)
{
- if (*this == X86_WINDOWS || *this == X86_UWP)
- return "x86";
- if (*this == X64_WINDOWS || *this == X64_UWP)
- return "x64";
- if (*this == ARM_UWP)
- return "arm";
+ const std::string s(Strings::ascii_to_lowercase(triplet_as_string));
+ auto it = std::find(s.cbegin(), s.cend(), '-');
+ Checks::check_exit(it != s.cend(), "Invalid triplet: %s", triplet_as_string);
- Checks::exit_with_message("Unknown architecture: %s", value);
+ triplet t;
+ t.m_canonical_name = s;
+ return t;
}
- std::string triplet::system() const
+ const std::string& triplet::canonical_name() const
{
- if (*this == X86_WINDOWS || *this == X64_WINDOWS)
- return "windows";
- if (*this == X86_UWP || *this == X64_UWP || *this == ARM_UWP)
- return "uwp";
+ return this->m_canonical_name;
+ }
- Checks::exit_with_message("Unknown system: %s", value);
+ std::string triplet::architecture() const
+ {
+ auto it = std::find(this->m_canonical_name.cbegin(), this->m_canonical_name.cend(), '-');
+ return std::string(this->m_canonical_name.cbegin(), it);
}
- bool triplet::validate(const vcpkg_paths & paths)
+ std::string triplet::system() const
{
- auto it = fs::directory_iterator(paths.triplets);
- for(; it != fs::directory_iterator(); ++it)
- {
- std::string triplet_file_name = it->path().stem().generic_u8string();
- if(value == triplet_file_name) // TODO: fuzzy compare
- {
- //value = triplet_file_name; // NOTE: uncomment when implementing fuzzy compare
- return true;
- }
- }
- return false;
+ auto it = std::find(this->m_canonical_name.cbegin(), this->m_canonical_name.cend(), '-');
+ return std::string(it + 1, this->m_canonical_name.cend());
}
}
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp
index f705858cc..e94d2538b 100644
--- a/toolsrc/src/vcpkg.cpp
+++ b/toolsrc/src/vcpkg.cpp
@@ -1,178 +1,250 @@
-#include "vcpkg.h"
-#include <regex>
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+
+#include <iostream>
+#include <fstream>
+#include <memory>
+#include <cassert>
+#include "vcpkg_Commands.h"
+#include "metrics.h"
+#include <Shlobj.h>
#include "vcpkg_Files.h"
-#include "vcpkglib_helpers.h"
+#include "vcpkg_System.h"
+#include "vcpkg_Input.h"
+#include "Paragraphs.h"
+#include "vcpkg_Strings.h"
+#include "vcpkg_Chrono.h"
-namespace
+using namespace vcpkg;
+
+bool g_debugging = false;
+
+void invalid_command(const std::string& cmd)
{
- using namespace vcpkg;
+ System::println(System::color::error, "invalid command: %s", cmd);
+ Commands::Help::print_usage();
+ exit(EXIT_FAILURE);
+}
- struct Parser
+static void inner(const vcpkg_cmd_arguments& args)
+{
+ TrackProperty("command", args.command);
+ if (args.command.empty())
{
- Parser(const char* c, const char* e) : cur(c), end(e)
- {
- }
+ Commands::Help::print_usage();
+ exit(EXIT_FAILURE);
+ }
- private:
- const char* cur;
- const char* const end;
+ if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_c()))
+ {
+ return command_function(args);
+ }
- void peek(char& ch) const
+ fs::path vcpkg_root_dir;
+ if (args.vcpkg_root_dir != nullptr)
+ {
+ vcpkg_root_dir = fs::absolute(Strings::utf8_to_utf16(*args.vcpkg_root_dir));
+ }
+ else
+ {
+ const optional<std::wstring> vcpkg_root_dir_env = System::get_environmental_variable(L"VCPKG_ROOT");
+ if (vcpkg_root_dir_env)
{
- if (cur == end)
- ch = 0;
- else
- ch = *cur;
+ vcpkg_root_dir = fs::absolute(*vcpkg_root_dir_env);
}
-
- void next(char& ch)
+ else
{
- if (cur == end)
- ch = 0;
- else
- {
- ++cur;
- peek(ch);
- }
+ vcpkg_root_dir = Files::find_file_recursively_up(fs::absolute(System::get_exe_path_of_current_process()), ".vcpkg-root");
}
+ }
- void skip_spaces(char& ch)
- {
- while (ch == ' ' || ch == '\t')
- next(ch);
- }
+ Checks::check_exit(!vcpkg_root_dir.empty(), "Error: Could not detect vcpkg-root.");
- static bool is_alphanum(char ch)
- {
- return (ch >= 'A' && ch <= 'Z')
- || (ch >= 'a' && ch <= 'z')
- || (ch >= '0' && ch <= '9');
- }
+ const expected<vcpkg_paths> expected_paths = vcpkg_paths::create(vcpkg_root_dir);
+ Checks::check_exit(!expected_paths.error_code(), "Error: Invalid vcpkg root directory %s: %s", vcpkg_root_dir.string(), expected_paths.error_code().message());
+ const vcpkg_paths paths = expected_paths.get_or_throw();
+ int exit_code = _wchdir(paths.root.c_str());
+ Checks::check_exit(exit_code == 0, "Changing the working dir failed");
- static bool is_lineend(char ch)
- {
- return ch == '\r' || ch == '\n' || ch == 0;
- }
+ if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_b()))
+ {
+ return command_function(args, paths);
+ }
- void get_fieldvalue(char& ch, std::string& fieldvalue)
+ triplet default_target_triplet;
+ if (args.target_triplet != nullptr)
+ {
+ default_target_triplet = triplet::from_canonical_name(*args.target_triplet);
+ }
+ else
+ {
+ const optional<std::wstring> vcpkg_default_triplet_env = System::get_environmental_variable(L"VCPKG_DEFAULT_TRIPLET");
+ if (vcpkg_default_triplet_env)
{
- fieldvalue.clear();
-
- auto beginning_of_line = cur;
- do
- {
- // scan to end of current line (it is part of the field value)
- while (!is_lineend(ch))
- next(ch);
-
- fieldvalue.append(beginning_of_line, cur);
-
- if (ch == '\r')
- next(ch);
- if (ch == '\n')
- next(ch);
-
- if (is_alphanum(ch))
- {
- // Line begins a new field.
- return;
- }
-
- beginning_of_line = cur;
-
- // Line may continue the current field with data or terminate the paragraph,
- // depending on first nonspace character.
- skip_spaces(ch);
-
- if (is_lineend(ch))
- {
- // Line was whitespace or empty.
- // This terminates the field and the paragraph.
- // We leave the blank line's whitespace consumed, because it doesn't matter.
- return;
- }
-
- // First nonspace is not a newline. This continues the current field value.
- // We forcibly convert all newlines into single '\n' for ease of text handling later on.
- fieldvalue.push_back('\n');
- }
- while (true);
+ default_target_triplet = triplet::from_canonical_name(Strings::utf16_to_utf8(*vcpkg_default_triplet_env));
}
-
- void get_fieldname(char& ch, std::string& fieldname)
+ else
{
- auto begin_fieldname = cur;
- while (is_alphanum(ch) || ch == '-')
- next(ch);
- Checks::check_throw(ch == ':', "Expected ':'");
- fieldname = std::string(begin_fieldname, cur);
-
- // skip ': '
- next(ch);
- skip_spaces(ch);
+ default_target_triplet = triplet::X86_WINDOWS;
}
+ }
- void get_paragraph(char& ch, std::unordered_map<std::string, std::string>& fields)
- {
- fields.clear();
- std::string fieldname;
- std::string fieldvalue;
- do
- {
- get_fieldname(ch, fieldname);
+ Input::check_triplet(default_target_triplet, paths);
- auto it = fields.find(fieldname);
- Checks::check_throw(it == fields.end(), "Duplicate field");
+ if (auto command_function = Commands::find(args.command, Commands::get_available_commands_type_a()))
+ {
+ return command_function(args, paths, default_target_triplet);
+ }
- get_fieldvalue(ch, fieldvalue);
+ return invalid_command(args.command);
+}
- fields.emplace(fieldname, fieldvalue);
- }
- while (!is_lineend(ch));
- }
+static void loadConfig()
+{
+ fs::path localappdata;
+ {
+ // Config path in AppDataLocal
+ wchar_t* localappdatapath = nullptr;
+ if (S_OK != SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &localappdatapath))
+ __fastfail(1);
+ localappdata = localappdatapath;
+ CoTaskMemFree(localappdatapath);
+ }
+
+ try
+ {
+ std::string config_contents = Files::read_contents(localappdata / "vcpkg" / "config").get_or_throw();
- public:
- std::vector<std::unordered_map<std::string, std::string>> get_paragraphs()
+ std::unordered_map<std::string, std::string> keys;
+ auto pghs = Paragraphs::parse_paragraphs(config_contents);
+ if (pghs.size() > 0)
+ keys = pghs[0];
+
+ for (size_t x = 1; x < pghs.size(); ++x)
{
- std::vector<std::unordered_map<std::string, std::string>> paragraphs;
+ for (auto&& p : pghs[x])
+ keys.insert(p);
+ }
- char ch;
- peek(ch);
+ auto user_id = keys["User-Id"];
+ auto user_time = keys["User-Since"];
+ Checks::check_throw(!user_id.empty() && !user_time.empty(), ""); // Use as goto to the catch statement
- while (ch != 0)
- {
- if (ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t')
- {
- next(ch);
- continue;
- }
+ SetUserInformation(user_id, user_time);
+ return;
+ }
+ catch (...)
+ {
+ }
- paragraphs.emplace_back();
- get_paragraph(ch, paragraphs.back());
- }
+ // config file not found, could not be read, or invalid
+ std::string user_id, user_time;
+ InitUserInformation(user_id, user_time);
+ SetUserInformation(user_id, user_time);
+ try
+ {
+ std::error_code ec;
+ fs::create_directory(localappdata / "vcpkg", ec);
+ std::ofstream(localappdata / "vcpkg" / "config", std::ios_base::out | std::ios_base::trunc)
+ << "User-Id: " << user_id << "\n"
+ << "User-Since: " << user_time << "\n";
+ }
+ catch (...)
+ {
+ }
+}
- return paragraphs;
- }
- };
+static std::string trim_path_from_command_line(const std::string& full_command_line)
+{
+ Checks::check_exit(full_command_line.size() > 0, "Internal failure - cannot have empty command line");
+
+ if (full_command_line[0] == '"')
+ {
+ auto it = std::find(full_command_line.cbegin() + 1, full_command_line.cend(), '"');
+ if (it != full_command_line.cend()) // Skip over the quote
+ ++it;
+ while (it != full_command_line.cend() && *it == ' ') // Skip over a space
+ ++it;
+ return std::string(it, full_command_line.cend());
+ }
+
+ auto it = std::find(full_command_line.cbegin(), full_command_line.cend(), ' ');
+ while (it != full_command_line.cend() && *it == ' ')
+ ++it;
+ return std::string(it, full_command_line.cend());
}
-namespace vcpkg
+static ElapsedTime g_timer;
+
+int wmain(const int argc, const wchar_t* const* const argv)
{
- std::string shorten_description(const std::string& desc)
+ if (argc == 0)
+ std::abort();
+
+ g_timer = ElapsedTime::createStarted();
+ atexit([]()
+ {
+ auto elapsed_us = g_timer.microseconds();
+ TrackMetric("elapsed_us", elapsed_us);
+ Flush();
+ });
+
+ TrackProperty("version", Commands::Version::version());
+
+ const std::string trimmed_command_line = trim_path_from_command_line(Strings::utf16_to_utf8(GetCommandLineW()));
+ TrackProperty("cmdline", trimmed_command_line);
+ loadConfig();
+ TrackProperty("sqmuser", GetSQMUser());
+
+ const vcpkg_cmd_arguments args = vcpkg_cmd_arguments::create_from_command_line(argc, argv);
+
+ if (args.printmetrics != opt_bool_t::UNSPECIFIED)
+ SetPrintMetrics(args.printmetrics == opt_bool_t::ENABLED);
+ if (args.sendmetrics != opt_bool_t::UNSPECIFIED)
+ SetSendMetrics(args.sendmetrics == opt_bool_t::ENABLED);
+
+ if (args.debug != opt_bool_t::UNSPECIFIED)
{
- auto simple_desc = std::regex_replace(desc.substr(0, 49), std::regex("\\n( |\\t)?"), "");
- if (desc.size() > 49)
- simple_desc.append("...");
- return simple_desc;
+ g_debugging = (args.debug == opt_bool_t::ENABLED);
}
- std::vector<std::unordered_map<std::string, std::string>> get_paragraphs(const fs::path& control_path)
+ if (g_debugging)
{
- return parse_paragraphs(Files::get_contents(control_path).get_or_throw());
+ inner(args);
+ exit(EXIT_FAILURE);
}
- std::vector<std::unordered_map<std::string, std::string>> parse_paragraphs(const std::string& str)
+ std::string exc_msg;
+ try
+ {
+ inner(args);
+ exit(EXIT_FAILURE);
+ }
+ catch (std::exception& e)
+ {
+ exc_msg = e.what();
+ }
+ catch (...)
{
- return Parser(str.c_str(), str.c_str() + str.size()).get_paragraphs();
+ exc_msg = "unknown error(...)";
}
+ TrackProperty("error", exc_msg);
+
+ fflush(stdout);
+ System::print(
+ "vcpkg.exe has crashed.\n"
+ "Please send an email to:\n"
+ " %s\n"
+ "containing a brief summary of what you were trying to do and the following data blob:\n"
+ "\n"
+ "Version=%s\n"
+ "EXCEPTION='%s'\n"
+ "CMD=\n",
+ Commands::Contact::email(),
+ Commands::Version::version(),
+ exc_msg);
+ fflush(stdout);
+ for (int x = 0; x < argc; ++x)
+ System::println("%s|", Strings::utf16_to_utf8(argv[x]));
+ fflush(stdout);
}
diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp
index d5433b1f5..02d3480a2 100644
--- a/toolsrc/src/vcpkg_Checks.cpp
+++ b/toolsrc/src/vcpkg_Checks.cpp
@@ -1,23 +1,26 @@
+#include "pch.h"
#include "vcpkg_Checks.h"
-
-#include <stdexcept>
#include "vcpkg_System.h"
-namespace vcpkg {namespace Checks
+namespace vcpkg::Checks
{
- void unreachable()
+ __declspec(noreturn) void unreachable()
{
System::println(System::color::error, "Error: Unreachable code was reached");
+#ifndef NDEBUG
+ std::abort();
+#else
exit(EXIT_FAILURE);
+#endif
}
- void exit_with_message(const char* errorMessage)
+ __declspec(noreturn) void exit_with_message(const char* errorMessage)
{
System::println(System::color::error, errorMessage);
exit(EXIT_FAILURE);
}
- void throw_with_message(const char* errorMessage)
+ __declspec(noreturn) void throw_with_message(const char* errorMessage)
{
throw std::runtime_error(errorMessage);
}
@@ -30,12 +33,19 @@ namespace vcpkg {namespace Checks
}
}
- void check_exit(bool expression, const char* errorMessage)
+ void check_exit(bool expression)
{
if (!expression)
{
- System::println(System::color::error, errorMessage);
exit(EXIT_FAILURE);
}
}
-}}
+
+ void check_exit(bool expression, const char* errorMessage)
+ {
+ if (!expression)
+ {
+ exit_with_message(errorMessage);
+ }
+ }
+}
diff --git a/toolsrc/src/vcpkg_Chrono.cpp b/toolsrc/src/vcpkg_Chrono.cpp
new file mode 100644
index 000000000..e39842df9
--- /dev/null
+++ b/toolsrc/src/vcpkg_Chrono.cpp
@@ -0,0 +1,63 @@
+#include "pch.h"
+#include "vcpkg_Chrono.h"
+#include "vcpkg_Checks.h"
+
+namespace vcpkg
+{
+ static std::string format_time_userfriendly(const std::chrono::nanoseconds& nanos)
+ {
+ using std::chrono::hours;
+ using std::chrono::minutes;
+ using std::chrono::seconds;
+ using std::chrono::milliseconds;
+ using std::chrono::microseconds;
+ using std::chrono::nanoseconds;
+ using std::chrono::duration_cast;
+
+ 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();
+ return Strings::format("%.4g h", t);
+ }
+
+ if (duration_cast<minutes>(nanos) > minutes())
+ {
+ 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();
+ return Strings::format("%.4g s", t);
+ }
+
+ if (duration_cast<milliseconds>(nanos) > milliseconds())
+ {
+ 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();
+ return Strings::format("%.4g us", t);
+ }
+
+ return Strings::format("%.4g ns", nanos_as_double);
+ }
+
+ ElapsedTime ElapsedTime::createStarted()
+ {
+ ElapsedTime t;
+ t.m_startTick = std::chrono::high_resolution_clock::now();
+ return t;
+ }
+
+ std::string ElapsedTime::toString() const
+ {
+ return format_time_userfriendly(elapsed<std::chrono::nanoseconds>());
+ }
+}
diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp
index 6ffb4959d..e8bf10617 100644
--- a/toolsrc/src/vcpkg_Dependencies.cpp
+++ b/toolsrc/src/vcpkg_Dependencies.cpp
@@ -1,26 +1,114 @@
+#include "pch.h"
#include "vcpkg_Dependencies.h"
-#include <vector>
#include "vcpkg_Graphs.h"
#include "vcpkg_paths.h"
#include "package_spec.h"
#include "StatusParagraphs.h"
-#include <unordered_set>
-#include "vcpkg.h"
-#include "vcpkg_Maps.h"
-#include "vcpkg_Sets.h"
+#include "vcpkg_Files.h"
+#include "Paragraphs.h"
-namespace vcpkg { namespace Dependencies
+namespace vcpkg::Dependencies
{
- static Graphs::Graph<package_spec> build_dependency_graph(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
+ install_plan_action::install_plan_action() : plan_type(install_plan_type::UNKNOWN), binary_pgh(nullptr), source_pgh(nullptr)
{
+ }
+
+ install_plan_action::install_plan_action(const install_plan_type& plan_type, optional<BinaryParagraph> binary_pgh, optional<SourceParagraph> source_pgh)
+ : plan_type(std::move(plan_type)), binary_pgh(std::move(binary_pgh)), source_pgh(std::move(source_pgh))
+ {
+ }
+
+ package_spec_with_install_plan::package_spec_with_install_plan(const package_spec& spec, install_plan_action&& plan) : spec(spec), plan(std::move(plan))
+ {
+ }
+
+ remove_plan_action::remove_plan_action() : plan_type(remove_plan_type::UNKNOWN), request_type(request_type::UNKNOWN)
+ {
+ }
+
+ remove_plan_action::remove_plan_action(const remove_plan_type& plan_type, const Dependencies::request_type& request_type) : plan_type(plan_type), request_type(request_type)
+ {
+ }
+
+ package_spec_with_remove_plan::package_spec_with_remove_plan(const package_spec& spec, remove_plan_action&& plan)
+ : spec(spec), plan(std::move(plan))
+ {
+ }
+
+ std::vector<package_spec_with_install_plan> create_install_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
+ {
+ std::unordered_map<package_spec, install_plan_action> was_examined; // Examine = we have checked its immediate (non-recursive) dependencies
+ Graphs::Graph<package_spec> graph;
+ graph.add_vertices(specs);
+
std::vector<package_spec> examine_stack(specs);
- std::unordered_set<package_spec> was_examined; // Examine = we have checked its immediate (non-recursive) dependencies
+ while (!examine_stack.empty())
+ {
+ const package_spec spec = examine_stack.back();
+ examine_stack.pop_back();
+
+ if (was_examined.find(spec) != was_examined.end())
+ {
+ continue;
+ }
+
+ auto process_dependencies = [&](const std::vector<std::string>& dependencies_as_string)
+ {
+ for (const std::string& dep_as_string : dependencies_as_string)
+ {
+ const package_spec current_dep = package_spec::from_name_and_triplet(dep_as_string, spec.target_triplet()).get_or_throw();
+ graph.add_edge(spec, current_dep);
+ if (was_examined.find(current_dep) == was_examined.end())
+ {
+ examine_stack.push_back(std::move(current_dep));
+ }
+ }
+ };
+
+ auto it = status_db.find(spec);
+ if (it != status_db.end() && (*it)->want == want_t::install)
+ {
+ was_examined.emplace(spec, install_plan_action{install_plan_type::ALREADY_INSTALLED, nullptr, nullptr});
+ continue;
+ }
+
+ expected<BinaryParagraph> maybe_bpgh = Paragraphs::try_load_cached_package(paths, spec);
+ if (BinaryParagraph* bpgh = maybe_bpgh.get())
+ {
+ process_dependencies(bpgh->depends);
+ was_examined.emplace(spec, install_plan_action{install_plan_type::INSTALL, std::make_unique<BinaryParagraph>(std::move(*bpgh)), nullptr});
+ continue;
+ }
+
+ expected<SourceParagraph> maybe_spgh = Paragraphs::try_load_port(paths.port_dir(spec));
+ SourceParagraph* spgh = maybe_spgh.get();
+ Checks::check_exit(spgh != nullptr, "Cannot find package %s", spec.name());
+ process_dependencies(filter_dependencies(spgh->depends, spec.target_triplet()));
+ was_examined.emplace(spec, install_plan_action{install_plan_type::BUILD_AND_INSTALL, nullptr, std::make_unique<SourceParagraph>(std::move(*spgh))});
+ }
+
+ std::vector<package_spec_with_install_plan> ret;
+
+ const std::vector<package_spec> pkgs = graph.find_topological_sort();
+ for (const package_spec& pkg : pkgs)
+ {
+ ret.push_back(package_spec_with_install_plan(pkg, std::move(was_examined[pkg])));
+ }
+ return ret;
+ }
+
+ std::vector<package_spec_with_remove_plan> create_remove_plan(const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
+ {
+ std::unordered_set<package_spec> specs_as_set(specs.cbegin(), specs.cend());
+
+ std::unordered_map<package_spec, remove_plan_action> was_examined; // Examine = we have checked its immediate (non-recursive) dependencies
Graphs::Graph<package_spec> graph;
- graph.add_vertices(examine_stack);
+ graph.add_vertices(specs);
+ std::vector<package_spec> examine_stack(specs);
while (!examine_stack.empty())
{
- package_spec spec = examine_stack.back();
+ const package_spec spec = examine_stack.back();
examine_stack.pop_back();
if (was_examined.find(spec) != was_examined.end())
@@ -28,40 +116,41 @@ namespace vcpkg { namespace Dependencies
continue;
}
- std::vector<std::string> dependencies_as_string = get_unmet_package_dependencies(paths, spec, status_db);
+ const StatusParagraphs::const_iterator it = status_db.find(spec);
+ if (it == status_db.end() || (*it)->state == install_state_t::not_installed)
+ {
+ was_examined.emplace(spec, remove_plan_action(remove_plan_type::NOT_INSTALLED, request_type::USER_REQUESTED));
+ continue;
+ }
- for (const std::string& dep_as_string : dependencies_as_string)
+ for (const std::unique_ptr<StatusParagraph>& an_installed_package : status_db)
{
- package_spec current_dep = {dep_as_string, spec.target_triplet};
- auto it = status_db.find(current_dep.name, current_dep.target_triplet);
- if (it != status_db.end() && (*it)->want == want_t::install)
- {
+ if (an_installed_package->want != want_t::install)
+ continue;
+ if (an_installed_package->package.spec.target_triplet() != spec.target_triplet())
continue;
- }
- graph.add_edge(spec, current_dep);
- if (was_examined.find(current_dep) == was_examined.end())
+ const std::vector<std::string>& deps = an_installed_package->package.depends;
+ if (std::find(deps.begin(), deps.end(), spec.name()) == deps.end())
{
- examine_stack.push_back(std::move(current_dep));
+ continue;
}
+
+ graph.add_edge(spec, an_installed_package.get()->package.spec);
+ examine_stack.push_back(an_installed_package.get()->package.spec);
}
- was_examined.insert(spec);
+ const request_type request_type = specs_as_set.find(spec) != specs_as_set.end() ? request_type::USER_REQUESTED : request_type::AUTO_SELECTED;
+ was_examined.emplace(spec, remove_plan_action(remove_plan_type::REMOVE, request_type));
}
- return graph;
- }
-
- std::vector<package_spec> create_dependency_ordered_install_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db)
- {
- return build_dependency_graph(paths, specs, status_db).find_topological_sort();
- }
+ std::vector<package_spec_with_remove_plan> ret;
- std::unordered_set<package_spec> find_unmet_dependencies(const vcpkg_paths& paths, const package_spec& spec, const StatusParagraphs& status_db)
- {
- const Graphs::Graph<package_spec> dependency_graph = build_dependency_graph(paths, {spec}, status_db);
- std::unordered_set<package_spec> key_set = Maps::extract_key_set(dependency_graph.adjacency_list());
- key_set.erase(spec);
- return key_set;
+ const std::vector<package_spec> pkgs = graph.find_topological_sort();
+ for (const package_spec& pkg : pkgs)
+ {
+ ret.push_back(package_spec_with_remove_plan(pkg, std::move(was_examined[pkg])));
+ }
+ return ret;
}
-}}
+}
diff --git a/toolsrc/src/vcpkg_Enums.cpp b/toolsrc/src/vcpkg_Enums.cpp
new file mode 100644
index 000000000..5e698659d
--- /dev/null
+++ b/toolsrc/src/vcpkg_Enums.cpp
@@ -0,0 +1,21 @@
+#include "pch.h"
+#include "vcpkg_Enums.h"
+#include "vcpkg_Checks.h"
+
+namespace vcpkg::Enums
+{
+ std::string nullvalue_toString(const std::string& enum_name)
+ {
+ return Strings::format("%s_NULLVALUE", enum_name);
+ }
+
+ void nullvalue_used(const std::string& enum_name)
+ {
+ Checks::exit_with_message("NULLVALUE of enum %s was used", enum_name);
+ }
+
+ void unreachable(const std::string& enum_name)
+ {
+ Checks::exit_with_message("Unreachable code for enum, %s", enum_name);
+ }
+}
diff --git a/toolsrc/src/vcpkg_Environment.cpp b/toolsrc/src/vcpkg_Environment.cpp
index f70f2b893..8aaaba8a8 100644
--- a/toolsrc/src/vcpkg_Environment.cpp
+++ b/toolsrc/src/vcpkg_Environment.cpp
@@ -1,87 +1,187 @@
-#include <regex>
-#include <array>
+#include "pch.h"
#include "vcpkg_Environment.h"
#include "vcpkg_Commands.h"
-#include "vcpkg.h"
-#include "metrics.h"
#include "vcpkg_System.h"
+#include "vcpkg_Strings.h"
+#include "vcpkg_Files.h"
-namespace vcpkg {namespace Environment
+namespace vcpkg::Environment
{
- static const fs::path default_cmake_installation_dir = "C:/Program Files/CMake/bin";
- static const fs::path default_cmake_installation_dir_x86 = "C:/Program Files (x86)/CMake/bin";
- static const fs::path default_git_installation_dir = "C:/Program Files/git/cmd";
- static const fs::path default_git_installation_dir_x86 = "C:/Program Files (x86)/git/cmd";
+ static std::vector<std::string> get_VS2017_installation_instances(const vcpkg_paths& paths)
+ {
+ const fs::path script = paths.scripts / "findVisualStudioInstallationInstances.ps1";
+ const std::wstring cmd = System::create_powershell_script_cmd(script);
+ System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd);
+ Checks::check_exit(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> find_vs2015_installation_instance()
+ {
+ const optional<std::wstring> vs2015_cmntools_optional = System::get_environmental_variable(L"VS140COMNTOOLS");
+ if (!vs2015_cmntools_optional)
+ {
+ return nullptr;
+ }
+
+ static const fs::path vs2015_cmntools = fs::path(*vs2015_cmntools_optional).parent_path(); // The call to parent_path() is needed because the env variable has a trailing backslash
+ static const fs::path vs2015_path = vs2015_cmntools.parent_path().parent_path();
+ return std::make_unique<fs::path>(vs2015_path);
+ }
+
+ static const optional<fs::path>& get_VS2015_installation_instance()
+ {
+ static const optional<fs::path> vs2015_path = find_vs2015_installation_instance();
+ return vs2015_path;
+ }
- static void ensure_on_path(const std::array<int, 3>& version, const wchar_t* version_check_cmd, const wchar_t* install_cmd)
+ static fs::path find_dumpbin_exe(const vcpkg_paths& paths)
{
- System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(version_check_cmd);
- if (ec_data.exit_code == 0)
+ const std::vector<std::string> vs2017_installation_instances = get_VS2017_installation_instances(paths);
+ std::vector<fs::path> paths_examined;
+
+ // VS2017
+ for (const std::string& instance : vs2017_installation_instances)
{
- // version check
- std::regex re(R"###((\d+)\.(\d+)\.(\d+))###");
- std::match_results<std::string::const_iterator> match;
- auto found = std::regex_search(ec_data.output, match, re);
- if (found)
+ const fs::path msvc_path = Strings::format(R"(%s\VC\Tools\MSVC)", instance);
+ std::vector<fs::path> msvc_subdirectories;
+ Files::non_recursive_find_matching_paths_in_dir(msvc_path, [&](const fs::path& current)
+ {
+ return fs::is_directory(current);
+ }, &msvc_subdirectories);
+
+ // Sort them so that latest comes first
+ std::sort(msvc_subdirectories.begin(), msvc_subdirectories.end(), [&](const fs::path& left, const fs::path& right)
+ {
+ return left.filename() > right.filename();
+ });
+
+ for (const fs::path& subdir : msvc_subdirectories)
{
- int d1 = atoi(match[1].str().c_str());
- int d2 = atoi(match[2].str().c_str());
- int d3 = atoi(match[3].str().c_str());
- if (d1 > version[0] || (d1 == version[0] && d2 > version[1]) || (d1 == version[0] && d2 == version[1] && d3 >= version[2]))
+ const fs::path dumpbin_path = subdir / "bin" / "HostX86" / "x86" / "dumpbin.exe";
+ paths_examined.push_back(dumpbin_path);
+ if (fs::exists(dumpbin_path))
{
- // satisfactory version found
- return;
+ return dumpbin_path;
}
}
}
- auto rc = System::cmd_execute(install_cmd);
- if (rc)
+ // VS2015
+ const optional<fs::path>& vs_2015_installation_instance = get_VS2015_installation_instance();
+ if (vs_2015_installation_instance)
+ {
+ const fs::path vs2015_dumpbin_exe = *vs_2015_installation_instance / "VC" / "bin" / "dumpbin.exe";
+ paths_examined.push_back(vs2015_dumpbin_exe);
+ if (fs::exists(vs2015_dumpbin_exe))
+ {
+ return vs2015_dumpbin_exe;
+ }
+ }
+
+ System::println(System::color::error, "Could not detect dumpbin.exe.");
+ System::println("The following paths were examined:");
+ for (const fs::path& path : paths_examined)
+ {
+ System::println(" %s", path.generic_string());
+ }
+ exit(EXIT_FAILURE);
+ }
+
+ const fs::path& get_dumpbin_exe(const vcpkg_paths& paths)
+ {
+ static const fs::path dumpbin_exe = find_dumpbin_exe(paths);
+ return dumpbin_exe;
+ }
+
+ static vcvarsall_and_platform_toolset find_vcvarsall_bat(const vcpkg_paths& paths)
+ {
+ const std::vector<std::string> vs2017_installation_instances = get_VS2017_installation_instances(paths);
+ std::vector<fs::path> paths_examined;
+
+ // VS2017
+ for (const fs::path& instance : vs2017_installation_instances)
+ {
+ const fs::path vcvarsall_bat = instance / "VC" / "Auxiliary" / "Build" / "vcvarsall.bat";
+ paths_examined.push_back(vcvarsall_bat);
+ if (fs::exists(vcvarsall_bat))
+ {
+ return { vcvarsall_bat , L"v141" };
+ }
+ }
+
+ // VS2015
+ const optional<fs::path>& vs_2015_installation_instance = get_VS2015_installation_instance();
+ if (vs_2015_installation_instance)
+ {
+ const fs::path vs2015_vcvarsall_bat = *vs_2015_installation_instance / "VC" / "vcvarsall.bat";
+
+ paths_examined.push_back(vs2015_vcvarsall_bat);
+ if (fs::exists(vs2015_vcvarsall_bat))
+ {
+ return { vs2015_vcvarsall_bat, L"v140" };
+ }
+ }
+
+ System::println(System::color::error, "Could not detect vcvarsall.bat.");
+ System::println("The following paths were examined:");
+ for (const fs::path& path : paths_examined)
{
- System::println(System::color::error, "Launching powershell failed or was denied");
- TrackProperty("error", "powershell install failed");
- TrackProperty("installcmd", install_cmd);
- exit(rc);
+ System::println(" %s", path.generic_string());
}
+ exit(EXIT_FAILURE);
+ }
+
+ const vcvarsall_and_platform_toolset& get_vcvarsall_bat(const vcpkg_paths& paths)
+ {
+ static const vcvarsall_and_platform_toolset vcvarsall_bat = find_vcvarsall_bat(paths);
+ return vcvarsall_bat;
}
- void ensure_git_on_path(const vcpkg_paths& paths)
+ static fs::path find_ProgramFiles()
{
- const fs::path downloaded_git = paths.downloads / "PortableGit" / "cmd";
- const std::wstring path_buf = Strings::format(L"%s;%s;%s;%s",
- downloaded_git.native(),
- System::wdupenv_str(L"PATH"),
- default_git_installation_dir.native(),
- default_git_installation_dir_x86.native());
- _wputenv_s(L"PATH", path_buf.c_str());
-
- static constexpr std::array<int, 3> git_version = {2,0,0};
- // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned
- ensure_on_path(git_version, L"git --version 2>&1", L"powershell -ExecutionPolicy Bypass scripts\\fetchDependency.ps1 -Dependency git");
+ const optional<std::wstring> program_files = System::get_environmental_variable(L"PROGRAMFILES");
+ Checks::check_exit(program_files.get() != nullptr, "Could not detect the PROGRAMFILES environmental variable");
+ return *program_files;
}
- void ensure_cmake_on_path(const vcpkg_paths& paths)
+ static const fs::path& get_ProgramFiles()
{
- const fs::path downloaded_cmake = paths.downloads / "cmake-3.5.2-win32-x86" / "bin";
- const std::wstring path_buf = Strings::format(L"%s;%s;%s;%s",
- downloaded_cmake.native(),
- System::wdupenv_str(L"PATH"),
- default_cmake_installation_dir.native(),
- default_cmake_installation_dir_x86.native());
- _wputenv_s(L"PATH", path_buf.c_str());
-
- static constexpr std::array<int, 3> cmake_version = {3,5,0};
- // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned
- ensure_on_path(cmake_version, L"cmake --version 2>&1", L"powershell -ExecutionPolicy Bypass scripts\\fetchDependency.ps1 -Dependency cmake");
+ static const fs::path p = find_ProgramFiles();
+ return p;
}
- void ensure_nuget_on_path(const vcpkg_paths& paths)
+ static fs::path find_ProgramFiles_32_bit()
{
- const std::wstring path_buf = Strings::format(L"%s;%s", paths.downloads.native(), System::wdupenv_str(L"PATH"));
- _wputenv_s(L"PATH", path_buf.c_str());
+ const optional<std::wstring> program_files_X86 = System::get_environmental_variable(L"ProgramFiles(x86)");
+ if (program_files_X86)
+ {
+ return *program_files_X86;
+ }
+
+ return get_ProgramFiles();
+ }
+
+ const fs::path& get_ProgramFiles_32_bit()
+ {
+ static const fs::path p = find_ProgramFiles_32_bit();
+ return p;
+ }
- static constexpr std::array<int, 3> nuget_version = {1,0,0};
- // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned
- ensure_on_path(nuget_version, L"nuget 2>&1", L"powershell -ExecutionPolicy Bypass scripts\\fetchDependency.ps1 -Dependency nuget");
+ static fs::path find_ProgramFiles_platform_bitness()
+ {
+ const optional<std::wstring> program_files_W6432 = System::get_environmental_variable(L"ProgramW6432");
+ if (program_files_W6432)
+ {
+ return *program_files_W6432;
+ }
+
+ return get_ProgramFiles();
+ }
+
+ const fs::path& get_ProgramFiles_platform_bitness()
+ {
+ static const fs::path p = find_ProgramFiles_platform_bitness();
+ return p;
}
-}}
+}
diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp
index 611aa7450..57d4c665c 100644
--- a/toolsrc/src/vcpkg_Files.cpp
+++ b/toolsrc/src/vcpkg_Files.cpp
@@ -1,25 +1,22 @@
+#include "pch.h"
#include "vcpkg_Files.h"
-#include <fstream>
-#include <filesystem>
-#include <regex>
+#include "vcpkg_System.h"
-namespace fs = std::tr2::sys;
-
-namespace vcpkg {namespace Files
+namespace vcpkg::Files
{
static const std::regex FILESYSTEM_INVALID_CHARACTERS_REGEX = std::regex(R"([\/:*?"<>|])");
void check_is_directory(const fs::path& dirpath)
{
- Checks::check_throw(fs::is_directory(dirpath), "The path %s is not a directory", dirpath.string());
+ Checks::check_exit(fs::is_directory(dirpath), "The path %s is not a directory", dirpath.string());
}
- bool has_invalid_chars_for_filesystem(const std::string s)
+ bool has_invalid_chars_for_filesystem(const std::string& s)
{
return std::regex_search(s, FILESYSTEM_INVALID_CHARACTERS_REGEX);
}
- expected<std::string> get_contents(const fs::path& file_path) noexcept
+ expected<std::string> read_contents(const fs::path& file_path) noexcept
{
std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary);
if (file_stream.fail())
@@ -44,6 +41,35 @@ namespace vcpkg {namespace Files
return std::move(output);
}
+ expected<std::vector<std::string>> read_all_lines(const fs::path& file_path)
+ {
+ std::fstream file_stream(file_path, std::ios_base::in | std::ios_base::binary);
+ if (file_stream.fail())
+ {
+ return std::errc::no_such_file_or_directory;
+ }
+
+ std::vector<std::string> output;
+ std::string line;
+ while (std::getline(file_stream, line))
+ {
+ output.push_back(line);
+ }
+ file_stream.close();
+
+ return std::move(output);
+ }
+
+ void write_all_lines(const fs::path& file_path, const std::vector<std::string>& lines)
+ {
+ std::fstream output(file_path, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
+ for (const std::string& line : lines)
+ {
+ output << line << "\n";
+ }
+ output.close();
+ }
+
fs::path find_file_recursively_up(const fs::path& starting_dir, const std::string& filename)
{
fs::path current_dir = starting_dir;
@@ -58,4 +84,59 @@ namespace vcpkg {namespace Files
return current_dir;
}
-}}
+
+ void recursive_find_files_with_extension_in_dir(const fs::path& dir, const std::string& extension, std::vector<fs::path>* output)
+ {
+ recursive_find_matching_paths_in_dir(dir, [&extension](const fs::path& current)
+ {
+ return !fs::is_directory(current) && current.extension() == extension;
+ }, output);
+ }
+
+ std::vector<fs::path> recursive_find_files_with_extension_in_dir(const fs::path& dir, const std::string& extension)
+ {
+ std::vector<fs::path> v;
+ recursive_find_files_with_extension_in_dir(dir, extension, &v);
+ return v;
+ }
+
+ void recursive_find_all_files_in_dir(const fs::path& dir, std::vector<fs::path>* output)
+ {
+ recursive_find_matching_paths_in_dir(dir, [](const fs::path& current)
+ {
+ return !fs::is_directory(current);
+ }, output);
+ }
+
+ std::vector<fs::path> recursive_find_all_files_in_dir(const fs::path& dir)
+ {
+ std::vector<fs::path> v;
+ recursive_find_all_files_in_dir(dir, &v);
+ return v;
+ }
+
+ void non_recursive_find_all_files_in_dir(const fs::path& dir, std::vector<fs::path>* output)
+ {
+ non_recursive_find_matching_paths_in_dir(dir, [](const fs::path& current)
+ {
+ return !fs::is_directory(current);
+ }, output);
+ }
+
+ std::vector<fs::path> non_recursive_find_all_files_in_dir(const fs::path& dir)
+ {
+ std::vector<fs::path> v;
+ non_recursive_find_all_files_in_dir(dir, &v);
+ return v;
+ }
+
+ void print_paths(const std::vector<fs::path>& paths)
+ {
+ System::println("");
+ for (const fs::path& p : paths)
+ {
+ System::println(" %s", p.generic_string());
+ }
+ System::println("");
+ }
+}
diff --git a/toolsrc/src/vcpkg_Input.cpp b/toolsrc/src/vcpkg_Input.cpp
new file mode 100644
index 000000000..5720cadc0
--- /dev/null
+++ b/toolsrc/src/vcpkg_Input.cpp
@@ -0,0 +1,53 @@
+#include "pch.h"
+#include "vcpkg_Input.h"
+#include "vcpkg_System.h"
+#include "metrics.h"
+#include "vcpkg_Commands.h"
+
+namespace vcpkg::Input
+{
+ package_spec check_and_get_package_spec(const std::string& package_spec_as_string, const triplet& default_target_triplet, const std::string& example_text)
+ {
+ const std::string as_lowercase = Strings::ascii_to_lowercase(package_spec_as_string);
+ expected<package_spec> expected_spec = package_spec::from_string(as_lowercase, default_target_triplet);
+ if (auto spec = expected_spec.get())
+ {
+ return *spec;
+ }
+
+ // Intentionally show the lowercased string
+ System::println(System::color::error, "Error: %s: %s", expected_spec.error_code().message(), as_lowercase);
+ System::print(example_text);
+ exit(EXIT_FAILURE);
+ }
+
+ std::vector<package_spec> check_and_get_package_specs(const std::vector<std::string>& package_specs_as_strings, const triplet& default_target_triplet, const std::string& example_text)
+ {
+ std::vector<package_spec> specs;
+ for (const std::string& spec : package_specs_as_strings)
+ {
+ specs.push_back(check_and_get_package_spec(spec, default_target_triplet, example_text));
+ }
+
+ return specs;
+ }
+
+ void check_triplet(const triplet& t, const vcpkg_paths& paths)
+ {
+ if (!paths.is_valid_triplet(t))
+ {
+ System::println(System::color::error, "Error: invalid triplet: %s", t.canonical_name());
+ TrackProperty("error", "invalid triplet: " + t.canonical_name());
+ Commands::Help::help_topic_valid_triplet(paths);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ void check_triplets(const std::vector<package_spec>& triplets, const vcpkg_paths& paths)
+ {
+ for (const package_spec& spec : triplets)
+ {
+ check_triplet(spec.target_triplet(), paths);
+ }
+ }
+}
diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp
index b0312536a..044fd3c05 100644
--- a/toolsrc/src/vcpkg_Strings.cpp
+++ b/toolsrc/src/vcpkg_Strings.cpp
@@ -1,40 +1,54 @@
+#include "pch.h"
#include "vcpkg_Strings.h"
-#include <cstdarg>
-#include <algorithm>
-#include <codecvt>
-#include <iterator>
-
-namespace vcpkg {namespace Strings {namespace details
+namespace vcpkg::Strings::details
{
+ // To disambiguate between two overloads
+ static const auto isspace = [](const char c)
+ {
+ return std::isspace(c);
+ };
+
+ // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower()
+ static char tolower_char(const char c)
+ {
+ return static_cast<char>(std::tolower(c));
+ }
+
+ static _locale_t& c_locale()
+ {
+ static _locale_t c_locale_impl = _create_locale(LC_ALL, "C");
+ return c_locale_impl;
+ }
+
std::string format_internal(const char* fmtstr, ...)
{
va_list lst;
va_start(lst, fmtstr);
- auto sz = _vscprintf(fmtstr, lst);
+ const int sz = _vscprintf_l(fmtstr, c_locale(), lst);
std::string output(sz, '\0');
- _vsnprintf_s(&output[0], output.size() + 1, output.size() + 1, fmtstr, lst);
+ _vsnprintf_s_l(&output[0], output.size() + 1, output.size() + 1, fmtstr, c_locale(), lst);
va_end(lst);
return output;
}
- std::wstring format_internal(const wchar_t* fmtstr, ...)
+ std::wstring wformat_internal(const wchar_t* fmtstr, ...)
{
va_list lst;
va_start(lst, fmtstr);
- auto sz = _vscwprintf(fmtstr, lst);
+ const int sz = _vscwprintf_l(fmtstr, c_locale(), lst);
std::wstring output(sz, '\0');
- _vsnwprintf_s(&output[0], output.size() + 1, output.size() + 1, fmtstr, lst);
+ _vsnwprintf_s_l(&output[0], output.size() + 1, output.size() + 1, fmtstr, c_locale(), lst);
va_end(lst);
return output;
}
-}}}
+}
-namespace vcpkg {namespace Strings
+namespace vcpkg::Strings
{
std::wstring utf8_to_utf16(const std::string& s)
{
@@ -48,13 +62,75 @@ namespace vcpkg {namespace Strings
return conversion.to_bytes(w);
}
- std::string::const_iterator case_insensitive_find(const std::string& s, const std::string& pattern)
+ std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern)
{
- std::string patter_as_lower_case;
- std::transform(pattern.begin(), pattern.end(), back_inserter(patter_as_lower_case), tolower);
- return search(s.begin(), s.end(), patter_as_lower_case.begin(), patter_as_lower_case.end(), [](const char a, const char b)
+ const std::string pattern_as_lower_case(ascii_to_lowercase(pattern));
+ return search(s.begin(), s.end(), pattern_as_lower_case.begin(), pattern_as_lower_case.end(), [](const char a, const char b)
{
- return (tolower(a) == b);
+ return details::tolower_char(a) == b;
});
}
-}}
+
+ std::string ascii_to_lowercase(const std::string& input)
+ {
+ std::string output(input);
+ std::transform(output.begin(), output.end(), output.begin(), &details::tolower_char);
+ return output;
+ }
+
+ std::string join(const std::string& delimiter, const std::vector<std::string>& v)
+ {
+ return join(delimiter, v, [](const std::string& p) -> const std::string& { return p; });
+ }
+
+ std::wstring wjoin(const std::wstring& delimiter, const std::vector<std::wstring>& v)
+ {
+ return wjoin(delimiter, v, [](const std::wstring& p) -> const std::wstring&{ return p; });
+ }
+
+ void trim(std::string* s)
+ {
+ s->erase(std::find_if_not(s->rbegin(), s->rend(), details::isspace).base(), s->end());
+ s->erase(s->begin(), std::find_if_not(s->begin(), s->end(), details::isspace));
+ }
+
+ std::string trimmed(const std::string& s)
+ {
+ auto whitespace_back = std::find_if_not(s.rbegin(), s.rend(), details::isspace).base();
+ auto whitespace_front = std::find_if_not(s.begin(), whitespace_back, details::isspace);
+ return std::string(whitespace_front, whitespace_back);
+ }
+
+ void trim_all_and_remove_whitespace_strings(std::vector<std::string>* strings)
+ {
+ for (std::string& s : *strings)
+ {
+ trim(&s);
+ }
+
+ strings->erase(std::remove_if(strings->begin(), strings->end(), [](const std::string& s)-> bool
+ {
+ return s == "";
+ }), strings->end());
+ }
+
+ std::vector<std::string> split(const std::string& s, const std::string& delimiter)
+ {
+ std::vector<std::string> output;
+
+ size_t i = 0;
+ for (size_t pos = s.find(delimiter); pos != std::string::npos; pos = s.find(delimiter, pos))
+ {
+ output.push_back(s.substr(i, pos - i));
+ i = ++pos;
+ }
+
+ // Add the rest of the string after the last delimiter, unless there is nothing after it
+ if (i != s.length())
+ {
+ output.push_back(s.substr(i, s.length()));
+ }
+
+ return output;
+ }
+}
diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp
index 71b4087d2..472f8450f 100644
--- a/toolsrc/src/vcpkg_System.cpp
+++ b/toolsrc/src/vcpkg_System.cpp
@@ -1,39 +1,116 @@
+#include "pch.h"
#include "vcpkg_System.h"
-#include <iostream>
-#include <Windows.h>
-#include <regex>
+#include "vcpkg_Checks.h"
-namespace fs = std::tr2::sys;
-
-namespace vcpkg {namespace System
+namespace vcpkg::System
{
fs::path get_exe_path_of_current_process()
{
- wchar_t buf[_MAX_PATH ];
+ wchar_t buf[_MAX_PATH];
int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH);
if (bytes == 0)
std::abort();
return fs::path(buf, buf + bytes);
}
+ int cmd_execute_clean(const wchar_t* cmd_line)
+ {
+ static const std::wstring system_root = *get_environmental_variable(L"SystemRoot");
+ static const std::wstring system_32 = system_root + LR"(\system32)";
+ static const std::wstring new_PATH = Strings::wformat(LR"(Path=%s;%s;%s\WindowsPowerShell\v1.0\)", system_32, system_root, system_32);
+
+ std::vector<std::wstring> env_wstrings =
+ {
+ L"ALLUSERSPROFILE",
+ L"APPDATA",
+ L"CommonProgramFiles",
+ L"CommonProgramFiles(x86)",
+ L"CommonProgramW6432",
+ L"COMPUTERNAME",
+ L"ComSpec",
+ L"HOMEDRIVE",
+ L"HOMEPATH",
+ L"LOCALAPPDATA",
+ L"LOGONSERVER",
+ L"NUMBER_OF_PROCESSORS",
+ L"OS",
+ L"PATHEXT",
+ L"PROCESSOR_ARCHITECTURE",
+ L"PROCESSOR_IDENTIFIER",
+ L"PROCESSOR_LEVEL",
+ L"PROCESSOR_REVISION",
+ L"ProgramData",
+ L"ProgramFiles",
+ L"ProgramFiles(x86)",
+ L"ProgramW6432",
+ L"PROMPT",
+ L"PSModulePath",
+ L"PUBLIC",
+ L"SystemDrive",
+ L"SystemRoot",
+ L"TEMP",
+ L"TMP",
+ L"USERDNSDOMAIN",
+ L"USERDOMAIN",
+ L"USERDOMAIN_ROAMINGPROFILE",
+ L"USERNAME",
+ L"USERPROFILE",
+ L"windir",
+ // Enables proxy information to be passed to Curl, the underlying download library in cmake.exe
+ L"HTTP_PROXY",
+ L"HTTPS_PROXY",
+ };
+
+ // Flush stdout before launching external process
+ _flushall();
+
+ std::vector<const wchar_t*> env_cstr;
+ env_cstr.reserve(env_wstrings.size() + 2);
+
+ for (auto&& env_wstring : env_wstrings)
+ {
+ auto v = System::get_environmental_variable(env_wstring.c_str());
+ if (v == nullptr || v->empty())
+ continue;
+
+ env_wstring.push_back(L'=');
+ env_wstring.append(*v);
+ env_cstr.push_back(env_wstring.c_str());
+ }
+
+ env_cstr.push_back(new_PATH.c_str());
+ env_cstr.push_back(nullptr);
+
+ // Basically we are wrapping it in quotes
+ const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", 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());
+ return static_cast<int>(exit_code);
+ }
+
int cmd_execute(const wchar_t* cmd_line)
{
+ // Flush stdout before launching external process
+ _flushall();
+
// Basically we are wrapping it in quotes
- const std::wstring& actual_cmd_line = Strings::format(LR"###("%s")###", cmd_line);
+ const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line);
int exit_code = _wsystem(actual_cmd_line.c_str());
return exit_code;
}
exit_code_and_output cmd_execute_and_capture_output(const wchar_t* cmd_line)
{
- const std::wstring& actual_cmd_line = Strings::format(LR"###("%s")###", cmd_line);
+ // Flush stdout before launching external process
+ fflush(stdout);
+
+ const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line);
std::string output;
char buf[1024];
auto pipe = _wpopen(actual_cmd_line.c_str(), L"r");
if (pipe == nullptr)
{
- return {1, output};
+ return { 1, output };
}
while (fgets(buf, 1024, pipe))
{
@@ -41,24 +118,35 @@ namespace vcpkg {namespace System
}
if (!feof(pipe))
{
- return {1, output};
+ return { 1, output };
}
auto ec = _pclose(pipe);
- return {ec, output};
+ return { ec, output };
+ }
+
+ std::wstring create_powershell_script_cmd(const fs::path& script_path)
+ {
+ return create_powershell_script_cmd(script_path, L"");
+ }
+
+ std::wstring create_powershell_script_cmd(const fs::path& script_path, const std::wstring& args)
+ {
+ // TODO: switch out ExecutionPolicy Bypass with "Remove Mark Of The Web" code and restore RemoteSigned
+ return Strings::wformat(LR"(powershell -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.native(), args);
}
void print(const char* message)
{
- std::cout << message;
+ fputs(message, stdout);
}
void println(const char* message)
{
print(message);
- std::cout << "\n";
+ putchar('\n');
}
- void print(color c, const char* message)
+ void print(const color c, const char* message)
{
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
@@ -66,46 +154,61 @@ namespace vcpkg {namespace System
GetConsoleScreenBufferInfo(hConsole, &consoleScreenBufferInfo);
auto original_color = consoleScreenBufferInfo.wAttributes;
- SetConsoleTextAttribute(hConsole, static_cast<int>(c) | (original_color & 0xF0));
- std::cout << message;
+ SetConsoleTextAttribute(hConsole, static_cast<WORD>(c) | (original_color & 0xF0));
+ print(message);
SetConsoleTextAttribute(hConsole, original_color);
}
- void println(color c, const char* message)
+ void println(const color c, const char* message)
{
print(c, message);
- std::cout << "\n";
+ putchar('\n');
}
- std::wstring wdupenv_str(const wchar_t* varname) noexcept
+ optional<std::wstring> get_environmental_variable(const wchar_t* varname) noexcept
{
- std::wstring ret;
- wchar_t* buffer;
- _wdupenv_s(&buffer, nullptr, varname);
- if (buffer != nullptr)
- {
- ret = buffer;
- free(buffer);
- }
+ auto sz = GetEnvironmentVariableW(varname, nullptr, 0);
+ if (sz == 0)
+ return nullptr;
+
+ auto ret = std::make_unique<std::wstring>(sz, L'\0');
+ Checks::check_exit(MAXDWORD >= ret->size());
+ auto sz2 = GetEnvironmentVariableW(varname, ret->data(), static_cast<DWORD>(ret->size()));
+ Checks::check_exit(sz2 + 1 == sz);
+ ret->pop_back();
return ret;
}
- void Stopwatch::start()
+ void set_environmental_variable(const wchar_t* varname, const wchar_t* varvalue) noexcept
{
- static_assert(sizeof(start_time) == sizeof(LARGE_INTEGER), "");
-
- QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&start_time));
+ _wputenv_s(varname, varvalue);
}
- void Stopwatch::stop()
+ static bool is_string_keytype(DWORD hkey_type)
{
- QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER*>(&end_time));
- QueryPerformanceFrequency(reinterpret_cast<LARGE_INTEGER*>(&freq));
+ return hkey_type == REG_SZ || hkey_type == REG_MULTI_SZ || hkey_type == REG_EXPAND_SZ;
}
- double Stopwatch::microseconds() const
+ optional<std::wstring> get_registry_string(HKEY base, const wchar_t* subKey, const wchar_t* valuename)
{
- return (reinterpret_cast<const LARGE_INTEGER*>(&end_time)->QuadPart -
- reinterpret_cast<const LARGE_INTEGER*>(&start_time)->QuadPart) * 1000000.0 / reinterpret_cast<const LARGE_INTEGER*>(&freq)->QuadPart;
+ HKEY k = nullptr;
+ LSTATUS ec = RegOpenKeyExW(base, subKey, NULL, KEY_READ, &k);
+ if (ec != ERROR_SUCCESS)
+ return nullptr;
+
+ 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)
+ return nullptr;
+ std::wstring ret;
+ ret.resize(dwBufferSize / 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())
+ return nullptr;
+
+ ret.pop_back(); // remove extra trailing null byte
+ return std::make_unique<std::wstring>(std::move(ret));
}
-}}
+}
diff --git a/toolsrc/src/vcpkg_cmd_arguments.cpp b/toolsrc/src/vcpkg_cmd_arguments.cpp
index ec6946b98..fdeb6e877 100644
--- a/toolsrc/src/vcpkg_cmd_arguments.cpp
+++ b/toolsrc/src/vcpkg_cmd_arguments.cpp
@@ -1,11 +1,7 @@
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
+#include "pch.h"
#include "vcpkg_cmd_arguments.h"
#include "vcpkg_Commands.h"
-#include "vcpkg_Graphs.h"
-#include <unordered_set>
#include "metrics.h"
-#include "vcpkg.h"
#include "vcpkg_System.h"
namespace vcpkg
@@ -20,7 +16,7 @@ namespace vcpkg
{
System::println(System::color::error, "Error: expected value after %s", option_name);
TrackProperty("error", "error option name");
- print_usage();
+ Commands::Help::print_usage();
exit(EXIT_FAILURE);
}
@@ -28,7 +24,7 @@ namespace vcpkg
{
System::println(System::color::error, "Error: %s specified multiple times", option_name);
TrackProperty("error", "error option specified multiple times");
- print_usage();
+ Commands::Help::print_usage();
exit(EXIT_FAILURE);
}
@@ -36,15 +32,15 @@ namespace vcpkg
}
static void parse_switch(
- opt_bool new_setting,
+ opt_bool_t new_setting,
const std::string& option_name,
- opt_bool& option_field)
+ opt_bool_t& option_field)
{
- if (option_field != opt_bool::unspecified && option_field != new_setting)
+ if (option_field != opt_bool_t::UNSPECIFIED && option_field != new_setting)
{
System::println(System::color::error, "Error: conflicting values specified for --%s", option_name);
TrackProperty("error", "error conflicting switches");
- print_usage();
+ Commands::Help::print_usage();
exit(EXIT_FAILURE);
}
option_field = new_setting;
@@ -98,27 +94,27 @@ namespace vcpkg
}
if (arg == "--debug")
{
- parse_switch(opt_bool::enabled, "debug", args.debug);
+ parse_switch(opt_bool_t::ENABLED, "debug", args.debug);
continue;
}
if (arg == "--sendmetrics")
{
- parse_switch(opt_bool::enabled, "sendmetrics", args.sendmetrics);
+ parse_switch(opt_bool_t::ENABLED, "sendmetrics", args.sendmetrics);
continue;
}
if (arg == "--printmetrics")
{
- parse_switch(opt_bool::enabled, "printmetrics", args.printmetrics);
+ parse_switch(opt_bool_t::ENABLED, "printmetrics", args.printmetrics);
continue;
}
if (arg == "--no-sendmetrics")
{
- parse_switch(opt_bool::disabled, "sendmetrics", args.sendmetrics);
+ parse_switch(opt_bool_t::DISABLED, "sendmetrics", args.sendmetrics);
continue;
}
if (arg == "--no-printmetrics")
{
- parse_switch(opt_bool::disabled, "printmetrics", args.printmetrics);
+ parse_switch(opt_bool_t::DISABLED, "printmetrics", args.printmetrics);
continue;
}
@@ -158,7 +154,7 @@ namespace vcpkg
System::println(System::color::error, "Unknown option(s) for command '%s':", this->command);
for (const std::string& option : options_copy)
{
- System::println(option.c_str());
+ System::println(option);
}
exit(EXIT_FAILURE);
}
@@ -166,49 +162,51 @@ namespace vcpkg
return output;
}
- void vcpkg_cmd_arguments::check_max_args(size_t arg_count, const char* example_text) const
+ void vcpkg_cmd_arguments::check_max_arg_count(const size_t expected_arg_count) const
{
- if (command_arguments.size() > arg_count)
+ return check_max_arg_count(expected_arg_count, "");
+ }
+
+ void vcpkg_cmd_arguments::check_min_arg_count(const size_t expected_arg_count) const
+ {
+ return check_min_arg_count(expected_arg_count, "");
+ }
+
+ void vcpkg_cmd_arguments::check_exact_arg_count(const size_t expected_arg_count) const
+ {
+ return check_exact_arg_count(expected_arg_count, "");
+ }
+
+ void vcpkg_cmd_arguments::check_max_arg_count(const size_t expected_arg_count, const std::string& example_text) const
+ {
+ const size_t actual_arg_count = command_arguments.size();
+ if (actual_arg_count > expected_arg_count)
{
- System::println(System::color::error, "Error: too many arguments to command %s", command);
- if (example_text != nullptr)
- print_example(example_text);
- else
- print_usage();
+ System::println(System::color::error, "Error: `%s` requires at most %u arguments, but %u were provided", this->command, expected_arg_count, actual_arg_count);
+ System::print(example_text);
exit(EXIT_FAILURE);
}
}
- std::vector<package_spec> vcpkg_cmd_arguments::parse_all_arguments_as_package_specs(const triplet& default_target_triplet, const char* example_text) const
+ void vcpkg_cmd_arguments::check_min_arg_count(const size_t expected_arg_count, const std::string& example_text) const
{
- size_t arg_count = command_arguments.size();
- if (arg_count < 1)
+ const size_t actual_arg_count = command_arguments.size();
+ if (actual_arg_count < expected_arg_count)
{
- System::println(System::color::error, "Error: %s requires one or more package specifiers", this->command);
- if (example_text == nullptr)
- print_example(Strings::format("%s zlib zlib:x64-windows curl boost", this->command).c_str());
- else
- print_example(example_text);
+ System::println(System::color::error, "Error: `%s` requires at least %u arguments, but %u were provided", this->command, expected_arg_count, actual_arg_count);
+ System::print(example_text);
exit(EXIT_FAILURE);
}
- std::vector<package_spec> specs;
- specs.reserve(arg_count);
+ }
- for (const std::string& command_argument : command_arguments)
+ void vcpkg_cmd_arguments::check_exact_arg_count(const size_t expected_arg_count, const std::string& example_text) const
+ {
+ const size_t actual_arg_count = command_arguments.size();
+ if (actual_arg_count != expected_arg_count)
{
- expected<package_spec> current_spec = package_spec::from_string(command_argument, default_target_triplet);
- if (auto spec = current_spec.get())
- {
- specs.push_back(std::move(*spec));
- }
- else
- {
- System::println(System::color::error, "Error: %s: %s", current_spec.error_code().message(), command_argument);
- print_example(Strings::format("%s zlib:x64-windows", this->command).c_str());
- exit(EXIT_FAILURE);
- }
+ System::println(System::color::error, "Error: `%s` requires %u arguments, but %u were provided", this->command, expected_arg_count, actual_arg_count);
+ System::print(example_text);
+ exit(EXIT_FAILURE);
}
-
- return specs;
}
}
diff --git a/toolsrc/src/vcpkg_metrics_uploader.cpp b/toolsrc/src/vcpkg_metrics_uploader.cpp
index f1f4a52ed..82dcd4b03 100644
--- a/toolsrc/src/vcpkg_metrics_uploader.cpp
+++ b/toolsrc/src/vcpkg_metrics_uploader.cpp
@@ -1,19 +1,11 @@
#include "metrics.h"
-#include <filesystem>
#include "vcpkg_Checks.h"
#include "vcpkg_Files.h"
#include <Windows.h>
-namespace fs = std::tr2::sys;
using namespace vcpkg;
-int WINAPI
-WinMain(
- _In_ HINSTANCE hInstance,
- _In_opt_ HINSTANCE hPrevInstance,
- _In_ LPSTR lpCmdLine,
- _In_ int nShowCmd
-)
+int WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int)
{
LPWSTR* szArgList;
int argCount;
@@ -21,5 +13,5 @@ WinMain(
szArgList = CommandLineToArgvW(GetCommandLineW(), &argCount);
Checks::check_exit(argCount == 2, "Requires exactly one argument, the path to the payload file");
- Upload(Files::get_contents(szArgList[1]).get_or_throw());
+ Upload(Files::read_contents(szArgList[1]).get_or_throw());
}
diff --git a/toolsrc/src/vcpkg_paths.cpp b/toolsrc/src/vcpkg_paths.cpp
index 30d32a99b..fa6fca370 100644
--- a/toolsrc/src/vcpkg_paths.cpp
+++ b/toolsrc/src/vcpkg_paths.cpp
@@ -1,14 +1,156 @@
-#include <filesystem>
+#include "pch.h"
#include "expected.h"
#include "vcpkg_paths.h"
#include "metrics.h"
#include "vcpkg_System.h"
#include "package_spec.h"
-
-namespace fs = std::tr2::sys;
+#include "vcpkg_Environment.h"
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+))###");
+
+ auto rc = System::cmd_execute_and_capture_output(Strings::wformat(LR"(%s 2>&1)", 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);
+ 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());
+ 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]))
+ {
+ // satisfactory version found
+ return true;
+ }
+
+ return false;
+ }
+
+ static optional<fs::path> find_if_has_equal_or_greater_version(const std::vector<fs::path>& candidate_paths, const std::wstring& version_check_arguments, const std::array<int, 3>& expected_version)
+ {
+ auto it = std::find_if(candidate_paths.cbegin(), candidate_paths.cend(), [&](const fs::path& p)
+ {
+ const std::wstring cmd = Strings::wformat(LR"("%s" %s)", p.native(), version_check_arguments);
+ return exists_and_has_equal_or_greater_version(cmd, expected_version);
+ });
+
+ if (it != candidate_paths.cend())
+ {
+ return std::make_unique<fs::path>(std::move(*it));
+ }
+
+ return nullptr;
+ }
+
+ 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 {};
+ }
+
+ const std::vector<std::string> paths_to_add = Strings::split(out.output, "\n");
+ std::vector<fs::path> v;
+ v.insert(v.end(), paths_to_add.cbegin(), paths_to_add.cend());
+ return v;
+ }
+
+ static fs::path fetch_dependency(const fs::path scripts_folder, const std::wstring& tool_name, const fs::path& expected_downloaded_path)
+ {
+ 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::exit_code_and_output rc = System::cmd_execute_and_capture_output(install_cmd);
+ if (rc.exit_code)
+ {
+ System::println(System::color::error, "Launching powershell failed or was denied");
+ TrackProperty("error", "powershell install failed");
+ TrackProperty("installcmd", install_cmd);
+ exit(rc.exit_code);
+ }
+
+ const fs::path actual_downloaded_path = rc.output;
+ Checks::check_exit(expected_downloaded_path == actual_downloaded_path, "Expected dependency downloaded path to be %s, but was %s",
+ expected_downloaded_path.generic_string(), actual_downloaded_path.generic_string());
+ return actual_downloaded_path;
+ }
+
+ 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,8,0 };
+ static const std::wstring version_check_arguments = L"--version";
+
+ const fs::path downloaded_copy = downloads_folder / "cmake-3.8.0-rc1-win32-x86" / "bin" / "cmake.exe";
+ const std::vector<fs::path> from_path = 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(Environment::get_ProgramFiles_platform_bitness() / "CMake" / "bin" / "cmake.exe");
+ candidate_paths.push_back(Environment::get_ProgramFiles_32_bit() / "CMake" / "bin");
+
+ if (auto ret = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version))
+ {
+ return *ret;
+ }
+
+ return fetch_dependency(scripts_folder, L"cmake", downloaded_copy);
+ }
+
+ fs::path get_nuget_path(const fs::path& downloads_folder, const fs::path scripts_folder)
+ {
+ static constexpr std::array<int, 3> expected_version = { 3,3,0 };
+ static const std::wstring version_check_arguments = L"";
+
+ const fs::path downloaded_copy = downloads_folder / "nuget-3.5.0" / "nuget.exe";
+ const std::vector<fs::path> from_path = 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());
+
+ if (auto ret = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version))
+ {
+ return *ret;
+ }
+
+ return fetch_dependency(scripts_folder, L"nuget", downloaded_copy);
+ }
+
+ fs::path get_git_path(const fs::path& downloads_folder, const fs::path scripts_folder)
+ {
+ static constexpr std::array<int, 3> expected_version = { 2,0,0 };
+ static const std::wstring version_check_arguments = L"--version";
+
+ const fs::path downloaded_copy = downloads_folder / "MinGit-2.11.1-32-bit" / "cmd" / "git.exe";
+ const std::vector<fs::path> from_path = 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(Environment::get_ProgramFiles_platform_bitness() / "git" / "cmd" / "git.exe");
+ candidate_paths.push_back(Environment::get_ProgramFiles_32_bit() / "git" / "cmd" / "git.exe");
+
+ if (auto ret = find_if_has_equal_or_greater_version(candidate_paths, version_check_arguments, expected_version))
+ {
+ return *ret;
+ }
+
+ return fetch_dependency(scripts_folder, L"git", downloaded_copy);
+ }
+
expected<vcpkg_paths> vcpkg_paths::create(const fs::path& vcpkg_root_dir)
{
std::error_code ec;
@@ -34,8 +176,9 @@ namespace vcpkg
paths.ports = paths.root / "ports";
paths.installed = paths.root / "installed";
paths.triplets = paths.root / "triplets";
+ paths.scripts = paths.root / "scripts";
- paths.buildsystems = paths.root / "scripts" / "buildsystems";
+ paths.buildsystems = paths.scripts / "buildsystems";
paths.buildsystems_msbuild_targets = paths.buildsystems / "msbuild" / "vcpkg.targets";
paths.vcpkg_dir = paths.installed / "vcpkg";
@@ -43,7 +186,8 @@ namespace vcpkg
paths.vcpkg_dir_info = paths.vcpkg_dir / "info";
paths.vcpkg_dir_updates = paths.vcpkg_dir / "updates";
- paths.ports_cmake = paths.root / "scripts" / "ports.cmake";
+ paths.ports_cmake = paths.scripts / "ports.cmake";
+
return paths;
}
@@ -54,6 +198,46 @@ namespace vcpkg
fs::path vcpkg_paths::port_dir(const package_spec& spec) const
{
- return this->ports / spec.name;
+ return this->ports / spec.name();
+ }
+
+ fs::path vcpkg_paths::build_info_file_path(const package_spec& spec) const
+ {
+ return this->package_dir(spec) / "BUILD_INFO";
+ }
+
+ fs::path vcpkg_paths::listfile_path(const BinaryParagraph& pgh) const
+ {
+ return this->vcpkg_dir_info / (pgh.fullstem() + ".list");
+ }
+
+ bool vcpkg_paths::is_valid_triplet(const triplet& t) const
+ {
+ auto it = fs::directory_iterator(this->triplets);
+ for (; it != fs::directory_iterator(); ++it)
+ {
+ std::string triplet_file_name = it->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
+ return true;
+ }
+ }
+ return false;
+ }
+
+ const fs::path& vcpkg_paths::get_cmake_exe() const
+ {
+ return this->cmake_exe.get_lazy([this]() { return get_cmake_path(this->downloads, this->scripts); });
+ }
+
+ const fs::path& vcpkg_paths::get_git_exe() const
+ {
+ return this->git_exe.get_lazy([this]() { return get_git_path(this->downloads, this->scripts); });
+ }
+
+ const fs::path& vcpkg_paths::get_nuget_exe() const
+ {
+ return this->nuget_exe.get_lazy([this]() { return get_nuget_path(this->downloads, this->scripts); });
}
}
diff --git a/toolsrc/src/vcpkg_version.cpp b/toolsrc/src/vcpkg_version.cpp
deleted file mode 100644
index da52b7cab..000000000
--- a/toolsrc/src/vcpkg_version.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#include "vcpkg.h"
-#include "metrics.h"
-
-#define STRINGIFY(X) #X
-#define MACRO_TO_STRING(X) STRINGIFY(X)
-
-#define VCPKG_VERSION_AS_STRING MACRO_TO_STRING(VCPKG_VERSION)"" // Double quotes needed at the end to prevent blank token
-
-const std::string& vcpkg::version()
-{
- static const std::string s_version =
-#include "../VERSION.txt"
-
-
-#pragma warning( push )
-#pragma warning( disable : 4003)
- // VCPKG_VERSION can be defined but have no value, which yields C4003.
- + std::string(VCPKG_VERSION_AS_STRING)
-#pragma warning( pop )
-#ifndef NDEBUG
- + std::string("-debug")
-#endif
- + std::string(GetCompiledMetricsEnabled() ? "" : "-external");
- return s_version;
-}
diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp
new file mode 100644
index 000000000..7ea33da0a
--- /dev/null
+++ b/toolsrc/src/vcpkglib.cpp
@@ -0,0 +1,215 @@
+#include "pch.h"
+#include "vcpkglib.h"
+#include "vcpkg_Files.h"
+#include "Paragraphs.h"
+#include "metrics.h"
+#include "vcpkg_Strings.h"
+
+namespace vcpkg
+{
+ static StatusParagraphs load_current_database(const fs::path& vcpkg_dir_status_file, const fs::path& vcpkg_dir_status_file_old)
+ {
+ if (!fs::exists(vcpkg_dir_status_file))
+ {
+ if (!fs::exists(vcpkg_dir_status_file_old))
+ {
+ // no status file, use empty db
+ return StatusParagraphs();
+ }
+
+ fs::rename(vcpkg_dir_status_file_old, vcpkg_dir_status_file);
+ }
+
+ auto text = Files::read_contents(vcpkg_dir_status_file).get_or_throw();
+ auto pghs = Paragraphs::parse_paragraphs(text);
+
+ std::vector<std::unique_ptr<StatusParagraph>> status_pghs;
+ for (auto&& p : pghs)
+ {
+ status_pghs.push_back(std::make_unique<StatusParagraph>(p));
+ }
+
+ return StatusParagraphs(std::move(status_pghs));
+ }
+
+ StatusParagraphs database_load_check(const vcpkg_paths& paths)
+ {
+ auto updates_dir = paths.vcpkg_dir_updates;
+
+ std::error_code ec;
+ fs::create_directory(paths.installed, ec);
+ fs::create_directory(paths.vcpkg_dir, ec);
+ fs::create_directory(paths.vcpkg_dir_info, ec);
+ fs::create_directory(updates_dir, ec);
+
+ const fs::path& status_file = paths.vcpkg_dir_status_file;
+ const fs::path status_file_old = status_file.parent_path() / "status-old";
+ const fs::path status_file_new = status_file.parent_path() / "status-new";
+
+ StatusParagraphs current_status_db = load_current_database(status_file, status_file_old);
+
+ auto b = fs::directory_iterator(updates_dir);
+ auto e = fs::directory_iterator();
+ if (b == e)
+ {
+ // updates directory is empty, control file is up-to-date.
+ return current_status_db;
+ }
+
+ for (; b != e; ++b)
+ {
+ if (!fs::is_regular_file(b->status()))
+ continue;
+ if (b->path().filename() == "incomplete")
+ continue;
+
+ auto text = Files::read_contents(b->path()).get_or_throw();
+ auto pghs = Paragraphs::parse_paragraphs(text);
+ for (auto&& p : pghs)
+ {
+ current_status_db.insert(std::make_unique<StatusParagraph>(p));
+ }
+ }
+
+ std::fstream(status_file_new, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc) << current_status_db;
+
+ if (fs::exists(status_file_old))
+ fs::remove(status_file_old);
+ if (fs::exists(status_file))
+ fs::rename(status_file, status_file_old);
+ fs::rename(status_file_new, status_file);
+ fs::remove(status_file_old);
+
+ b = fs::directory_iterator(updates_dir);
+ for (; b != e; ++b)
+ {
+ if (!fs::is_regular_file(b->status()))
+ continue;
+ fs::remove(b->path());
+ }
+
+ return current_status_db;
+ }
+
+ void write_update(const vcpkg_paths& paths, const StatusParagraph& p)
+ {
+ static int update_id = 0;
+ 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);
+ std::fstream fs(tmp_update_filename, std::ios_base::out | std::ios_base::binary | std::ios_base::trunc);
+ fs << p;
+ fs.close();
+ fs::rename(tmp_update_filename, update_filename);
+ }
+
+ static void upgrade_to_slash_terminated_sorted_format(std::vector<std::string>* lines, const fs::path& listfile_path)
+ {
+ static bool was_tracked = false;
+
+ if (lines->empty())
+ {
+ return;
+ }
+
+ if (lines->at(0).back() == '/')
+ {
+ return; // File already in the new format
+ }
+
+ if (!was_tracked)
+ {
+ was_tracked = true;
+ TrackProperty("listfile", "update to new format");
+ }
+
+ // The files are sorted such that directories are placed just before the files they contain
+ // (They are not necessarily sorted alphabetically, e.g. libflac)
+ // Therefore we can detect the entries that represent directories by comparing every element with the next one
+ // and checking if the next has a slash immediately after the current one's length
+ for (size_t i = 0; i < lines->size() - 1; i++)
+ {
+ std::string& current_string = lines->at(i);
+ const std::string& next_string = lines->at(i + 1);
+
+ const size_t potential_slash_char_index = current_string.length();
+ // Make sure the index exists first
+ if (next_string.size() > potential_slash_char_index && next_string.at(potential_slash_char_index) == '/')
+ {
+ current_string += '/'; // Mark as a directory
+ }
+ }
+
+ // After suffixing the directories with a slash, we can now sort.
+ // We cannot sort before adding the suffixes because the following (actual example):
+ /*
+ x86-windows/include/FLAC <<<<<< This would be separated from its group due to sorting
+ x86-windows/include/FLAC/all.h
+ x86-windows/include/FLAC/assert.h
+ x86-windows/include/FLAC/callback.h
+ x86-windows/include/FLAC++
+ x86-windows/include/FLAC++/all.h
+ x86-windows/include/FLAC++/decoder.h
+ x86-windows/include/FLAC++/encoder.h
+ *
+ x86-windows/include/FLAC/ <<<<<< This will now be kept with its group when sorting
+ x86-windows/include/FLAC/all.h
+ x86-windows/include/FLAC/assert.h
+ x86-windows/include/FLAC/callback.h
+ x86-windows/include/FLAC++/
+ x86-windows/include/FLAC++/all.h
+ x86-windows/include/FLAC++/decoder.h
+ x86-windows/include/FLAC++/encoder.h
+ */
+ // Note that after sorting, the FLAC++/ group will be placed before the FLAC/ group
+ // The new format is lexicographically sorted
+ std::sort(lines->begin(), lines->end());
+
+ // Replace the listfile on disk
+ const fs::path updated_listfile_path = listfile_path.generic_string() + "_updated";
+ Files::write_all_lines(updated_listfile_path, *lines);
+ fs::rename(updated_listfile_path, listfile_path);
+ }
+
+ std::vector<StatusParagraph_and_associated_files> get_installed_files(const vcpkg_paths& paths, const StatusParagraphs& status_db)
+ {
+ std::vector<StatusParagraph_and_associated_files> installed_files;
+
+ for (const std::unique_ptr<StatusParagraph>& pgh : status_db)
+ {
+ if (pgh->state != install_state_t::installed)
+ {
+ continue;
+ }
+
+ const fs::path listfile_path = paths.listfile_path(pgh->package);
+ std::vector<std::string> installed_files_of_current_pgh = Files::read_all_lines(listfile_path).get_or_throw();
+ Strings::trim_all_and_remove_whitespace_strings(&installed_files_of_current_pgh);
+ upgrade_to_slash_terminated_sorted_format(&installed_files_of_current_pgh, listfile_path);
+
+ // Remove the directories
+ installed_files_of_current_pgh.erase(
+ std::remove_if(installed_files_of_current_pgh.begin(), installed_files_of_current_pgh.end(), [](const std::string& file) -> bool
+ {
+ return file.back() == '/';
+ }
+ ), installed_files_of_current_pgh.end());
+
+ StatusParagraph_and_associated_files pgh_and_files = { *pgh, ImmutableSortedVector<std::string>::create(std::move(installed_files_of_current_pgh)) };
+ installed_files.push_back(std::move(pgh_and_files));
+ }
+
+ return installed_files;
+ }
+
+ CMakeVariable::CMakeVariable(const std::wstring& varname, const wchar_t* varvalue) : s(Strings::wformat(LR"("-D%s=%s")", varname, varvalue)) { }
+ CMakeVariable::CMakeVariable(const std::wstring& varname, const std::string& varvalue) : CMakeVariable(varname, Strings::utf8_to_utf16(varvalue).c_str()) { }
+ CMakeVariable::CMakeVariable(const std::wstring& varname, const std::wstring& varvalue) : CMakeVariable(varname, varvalue.c_str()) {}
+ CMakeVariable::CMakeVariable(const std::wstring& varname, const fs::path& path) : CMakeVariable(varname, path.generic_wstring()) {}
+
+ std::wstring make_cmake_cmd(const fs::path& cmake_exe, const fs::path& cmake_script, const std::vector<CMakeVariable>& pass_variables)
+ {
+ std::wstring cmd_cmake_pass_variables = Strings::wjoin(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());
+ }
+}
diff --git a/toolsrc/src/vcpkglib_helpers.cpp b/toolsrc/src/vcpkglib_helpers.cpp
index e947dc647..6b96c25cb 100644
--- a/toolsrc/src/vcpkglib_helpers.cpp
+++ b/toolsrc/src/vcpkglib_helpers.cpp
@@ -1,50 +1,55 @@
+#include "pch.h"
#include "vcpkg_Checks.h"
#include "vcpkglib_helpers.h"
-#include <unordered_map>
-namespace vcpkg {namespace details
+namespace vcpkg::details
{
- void optional_field(const std::unordered_map<std::string, std::string>& fields, std::string& out, const std::string& fieldname)
+ std::string optional_field(const std::unordered_map<std::string, std::string>& fields, const std::string& fieldname)
{
auto it = fields.find(fieldname);
if (it == fields.end())
{
- out.clear();
+ return std::string();
}
- else
+ return it->second;
+ }
+
+ std::string remove_optional_field(std::unordered_map<std::string, std::string>* fields, const std::string& fieldname)
+ {
+ auto it = fields->find(fieldname);
+ if (it == fields->end())
{
- out = it->second;
+ return std::string();
}
- };
- void required_field(const std::unordered_map<std::string, std::string>& fields, std::string& out, const std::string& fieldname)
+ const std::string value = std::move(it->second);
+ fields->erase(it);
+ return value;
+ }
+
+ std::string required_field(const std::unordered_map<std::string, std::string>& fields, const std::string& fieldname)
{
auto it = fields.find(fieldname);
- vcpkg::Checks::check_throw(it != fields.end(), "Required field not present: %s", fieldname);
- out = it->second;
- };
+ Checks::check_exit(it != fields.end(), "Required field not present: %s", fieldname);
+ return it->second;
+ }
- void parse_depends(const std::string& depends_string, std::vector<std::string>& out)
+ std::string remove_required_field(std::unordered_map<std::string, std::string>* fields, const std::string& fieldname)
{
- size_t cur = 0;
- do
- {
- auto pos = depends_string.find(',', cur);
- if (pos == std::string::npos)
- {
- out.push_back(depends_string.substr(cur));
- return;
- }
- out.push_back(depends_string.substr(cur, pos - cur));
-
- // skip comma and space
- ++pos;
- if (depends_string[pos] == ' ')
- ++pos;
-
- cur = pos;
- }
- while (cur != std::string::npos);
+ auto it = fields->find(fieldname);
+ Checks::check_exit(it != fields->end(), "Required field not present: %s", fieldname);
+
+ const std::string value = std::move(it->second);
+ fields->erase(it);
+ return value;
+ }
+
+ std::string shorten_description(const std::string& desc)
+ {
+ auto simple_desc = std::regex_replace(desc.substr(0, 49), std::regex("\\n( |\\t)?"), "");
+ if (desc.size() > 49)
+ simple_desc.append("...");
+ return simple_desc;
}
-}}
+}
diff --git a/toolsrc/vcpkg.sln b/toolsrc/vcpkg.sln
index 83051670a..c97756c21 100644
--- a/toolsrc/vcpkg.sln
+++ b/toolsrc/vcpkg.sln
@@ -5,12 +5,8 @@ VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vcpkg", "vcpkg\vcpkg.vcxproj", "{34671B80-54F9-46F5-8310-AC429C11D4FB}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vcpkgcommon", "vcpkgcommon\vcpkgcommon.vcxproj", "{7129F242-F20C-43E7-BBEC-4E15B71890B2}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vcpkglib", "vcpkglib\vcpkglib.vcxproj", "{B98C92B7-2874-4537-9D46-D14E5C237F04}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vcpkgmetrics", "vcpkgmetrics\vcpkgmetrics.vcxproj", "{7226078C-1D2A-4123-9EF1-8DF2B722B8F1}"
-EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vcpkgmetricsuploader", "vcpkgmetricsuploader\vcpkgmetricsuploader.vcxproj", "{7D6FDEEB-B299-4A23-85EE-F67C4DED47BE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vcpkgtest", "vcpkgtest\vcpkgtest.vcxproj", "{F27B8DB0-1279-4AF8-A2E3-1D49C4F0220D}"
@@ -31,14 +27,6 @@ Global
{34671B80-54F9-46F5-8310-AC429C11D4FB}.Release|x64.Build.0 = Release|x64
{34671B80-54F9-46F5-8310-AC429C11D4FB}.Release|x86.ActiveCfg = Release|Win32
{34671B80-54F9-46F5-8310-AC429C11D4FB}.Release|x86.Build.0 = Release|Win32
- {7129F242-F20C-43E7-BBEC-4E15B71890B2}.Debug|x64.ActiveCfg = Debug|x64
- {7129F242-F20C-43E7-BBEC-4E15B71890B2}.Debug|x64.Build.0 = Debug|x64
- {7129F242-F20C-43E7-BBEC-4E15B71890B2}.Debug|x86.ActiveCfg = Debug|Win32
- {7129F242-F20C-43E7-BBEC-4E15B71890B2}.Debug|x86.Build.0 = Debug|Win32
- {7129F242-F20C-43E7-BBEC-4E15B71890B2}.Release|x64.ActiveCfg = Release|x64
- {7129F242-F20C-43E7-BBEC-4E15B71890B2}.Release|x64.Build.0 = Release|x64
- {7129F242-F20C-43E7-BBEC-4E15B71890B2}.Release|x86.ActiveCfg = Release|Win32
- {7129F242-F20C-43E7-BBEC-4E15B71890B2}.Release|x86.Build.0 = Release|Win32
{B98C92B7-2874-4537-9D46-D14E5C237F04}.Debug|x64.ActiveCfg = Debug|x64
{B98C92B7-2874-4537-9D46-D14E5C237F04}.Debug|x64.Build.0 = Debug|x64
{B98C92B7-2874-4537-9D46-D14E5C237F04}.Debug|x86.ActiveCfg = Debug|Win32
@@ -47,14 +35,6 @@ Global
{B98C92B7-2874-4537-9D46-D14E5C237F04}.Release|x64.Build.0 = Release|x64
{B98C92B7-2874-4537-9D46-D14E5C237F04}.Release|x86.ActiveCfg = Release|Win32
{B98C92B7-2874-4537-9D46-D14E5C237F04}.Release|x86.Build.0 = Release|Win32
- {7226078C-1D2A-4123-9EF1-8DF2B722B8F1}.Debug|x64.ActiveCfg = Debug|x64
- {7226078C-1D2A-4123-9EF1-8DF2B722B8F1}.Debug|x64.Build.0 = Debug|x64
- {7226078C-1D2A-4123-9EF1-8DF2B722B8F1}.Debug|x86.ActiveCfg = Debug|Win32
- {7226078C-1D2A-4123-9EF1-8DF2B722B8F1}.Debug|x86.Build.0 = Debug|Win32
- {7226078C-1D2A-4123-9EF1-8DF2B722B8F1}.Release|x64.ActiveCfg = Release|x64
- {7226078C-1D2A-4123-9EF1-8DF2B722B8F1}.Release|x64.Build.0 = Release|x64
- {7226078C-1D2A-4123-9EF1-8DF2B722B8F1}.Release|x86.ActiveCfg = Release|Win32
- {7226078C-1D2A-4123-9EF1-8DF2B722B8F1}.Release|x86.Build.0 = Release|Win32
{7D6FDEEB-B299-4A23-85EE-F67C4DED47BE}.Debug|x64.ActiveCfg = Debug|x64
{7D6FDEEB-B299-4A23-85EE-F67C4DED47BE}.Debug|x64.Build.0 = Debug|x64
{7D6FDEEB-B299-4A23-85EE-F67C4DED47BE}.Debug|x86.ActiveCfg = Debug|Win32
diff --git a/toolsrc/vcpkg/vcpkg.vcxproj b/toolsrc/vcpkg/vcpkg.vcxproj
index a59683470..fd8e5d33e 100644
--- a/toolsrc/vcpkg/vcpkg.vcxproj
+++ b/toolsrc/vcpkg/vcpkg.vcxproj
@@ -22,31 +22,28 @@
<ProjectGuid>{34671B80-54F9-46F5-8310-AC429C11D4FB}</ProjectGuid>
<RootNamespace>vcpkg</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@@ -76,6 +73,8 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -88,6 +87,8 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -103,6 +104,7 @@
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -120,6 +122,7 @@
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -128,42 +131,12 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
- <ClCompile Include="..\src\commands_cache.cpp" />
- <ClCompile Include="..\src\commands_create.cpp" />
- <ClCompile Include="..\src\commands_edit.cpp" />
- <ClCompile Include="..\src\commands_import.cpp" />
- <ClCompile Include="..\src\commands_list.cpp" />
- <ClCompile Include="..\src\commands_owns.cpp" />
- <ClCompile Include="..\src\commands_remove.cpp" />
- <ClCompile Include="..\src\commands_search.cpp" />
- <ClCompile Include="..\src\commands_update.cpp" />
- <ClCompile Include="..\src\vcpkg_cmd_arguments.cpp" />
- <ClCompile Include="..\src\commands_other.cpp" />
- <ClCompile Include="..\src\vcpkg_Dependencies.cpp" />
- <ClCompile Include="..\src\vcpkg_Environment.cpp" />
- <ClCompile Include="..\src\commands_installation.cpp" />
- <ClCompile Include="..\src\commands_integration.cpp" />
- <ClCompile Include="..\src\main.cpp" />
- <ClCompile Include="..\src\commands_help.cpp" />
- <ClCompile Include="..\src\post_build_lint.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\include\vcpkg_cmd_arguments.h" />
- <ClInclude Include="..\include\vcpkg_Commands.h" />
- <ClInclude Include="..\include\vcpkg_Dependencies.h" />
- <ClInclude Include="..\include\vcpkg_Environment.h" />
- <ClInclude Include="..\include\post_build_lint.h" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\vcpkgcommon\vcpkgcommon.vcxproj">
- <Project>{7129f242-f20c-43e7-bbec-4e15b71890b2}</Project>
- </ProjectReference>
<ProjectReference Include="..\vcpkglib\vcpkglib.vcxproj">
<Project>{b98c92b7-2874-4537-9d46-d14e5c237f04}</Project>
</ProjectReference>
- <ProjectReference Include="..\vcpkgmetrics\vcpkgmetrics.vcxproj">
- <Project>{7226078c-1d2a-4123-9ef1-8df2b722b8f1}</Project>
- </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\vcpkg.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/toolsrc/vcpkg/vcpkg.vcxproj.filters b/toolsrc/vcpkg/vcpkg.vcxproj.filters
index 2e8a343fc..ca9723bbf 100644
--- a/toolsrc/vcpkg/vcpkg.vcxproj.filters
+++ b/toolsrc/vcpkg/vcpkg.vcxproj.filters
@@ -15,76 +15,8 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\src\main.cpp">
+ <ClCompile Include="..\src\vcpkg.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="..\src\commands_other.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_help.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_integration.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_installation.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\post_build_lint.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\vcpkg_cmd_arguments.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\vcpkg_Environment.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_remove.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_search.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_cache.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_update.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_list.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_edit.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_create.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_owns.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\commands_import.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\vcpkg_Dependencies.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\include\post_build_lint.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_cmd_arguments.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_Commands.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_Environment.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_Dependencies.h">
- <Filter>Header Files</Filter>
- </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/toolsrc/vcpkgcommon/vcpkgcommon.vcxproj b/toolsrc/vcpkgcommon/vcpkgcommon.vcxproj
deleted file mode 100644
index d5e68fde3..000000000
--- a/toolsrc/vcpkgcommon/vcpkgcommon.vcxproj
+++ /dev/null
@@ -1,142 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{7129F242-F20C-43E7-BBEC-4E15B71890B2}</ProjectGuid>
- <RootNamespace>vcpkgcommon</RootNamespace>
- <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="Shared">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup />
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>Disabled</Optimization>
- <SDLCheck>true</SDLCheck>
- <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>Disabled</Optimization>
- <SDLCheck>true</SDLCheck>
- <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <SDLCheck>true</SDLCheck>
- <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <SDLCheck>true</SDLCheck>
- <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClCompile Include="..\src\vcpkg_Checks.cpp" />
- <ClCompile Include="..\src\vcpkg_Files.cpp" />
- <ClCompile Include="..\src\vcpkg_Strings.cpp" />
- <ClCompile Include="..\src\vcpkg_System.cpp" />
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\include\expected.h" />
- <ClInclude Include="..\include\opt_bool.h" />
- <ClInclude Include="..\include\vcpkg_Checks.h" />
- <ClInclude Include="..\include\vcpkg_Files.h" />
- <ClInclude Include="..\include\vcpkg_Graphs.h" />
- <ClInclude Include="..\include\vcpkg_Maps.h" />
- <ClInclude Include="..\include\vcpkg_Sets.h" />
- <ClInclude Include="..\include\vcpkg_Strings.h" />
- <ClInclude Include="..\include\vcpkg_System.h" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/toolsrc/vcpkgcommon/vcpkgcommon.vcxproj.filters b/toolsrc/vcpkgcommon/vcpkgcommon.vcxproj.filters
deleted file mode 100644
index ae747d687..000000000
--- a/toolsrc/vcpkgcommon/vcpkgcommon.vcxproj.filters
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
- <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="..\src\vcpkg_Checks.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\vcpkg_Strings.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\vcpkg_System.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\vcpkg_Files.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\include\vcpkg_Checks.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_Strings.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_System.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\expected.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_Files.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_Graphs.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\opt_bool.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_Maps.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- <ClInclude Include="..\include\vcpkg_Sets.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj b/toolsrc/vcpkglib/vcpkglib.vcxproj
index 99e16e431..dd5dd124a 100644
--- a/toolsrc/vcpkglib/vcpkglib.vcxproj
+++ b/toolsrc/vcpkglib/vcpkglib.vcxproj
@@ -22,34 +22,34 @@
<ProjectGuid>{B98C92B7-2874-4537-9D46-D14E5C237F04}</ProjectGuid>
<RootNamespace>vcpkglib</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
+ <PropertyGroup>
+ <DISABLE_METRICS Condition="'$(DISABLE_METRICS)' == ''">0</DISABLE_METRICS>
+ </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
@@ -75,18 +75,26 @@
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>VCPKG_VERSION=$(VCPKG_VERSION);_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>DISABLE_METRICS=$(DISABLE_METRICS);VCPKG_VERSION=$(VCPKG_VERSION);_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
- <WarningLevel>Level3</WarningLevel>
+ <WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>VCPKG_VERSION=$(VCPKG_VERSION);_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>DISABLE_METRICS=$(DISABLE_METRICS);VCPKG_VERSION=$(VCPKG_VERSION);_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -97,8 +105,11 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>VCPKG_VERSION=$(VCPKG_VERSION);_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>DISABLE_METRICS=$(DISABLE_METRICS);VCPKG_VERSION=$(VCPKG_VERSION);_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -113,8 +124,11 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>VCPKG_VERSION=$(VCPKG_VERSION);_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions>DISABLE_METRICS=$(DISABLE_METRICS);VCPKG_VERSION=$(VCPKG_VERSION);_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -123,29 +137,105 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\include\BinaryParagraph.h" />
+ <ClInclude Include="..\include\lazy.h" />
+ <ClInclude Include="..\include\PostBuildLint_BuildInfo.h" />
+ <ClInclude Include="..\include\PostBuildLint_BuildPolicies.h" />
+ <ClInclude Include="..\include\coff_file_reader.h" />
+ <ClInclude Include="..\include\expected.h" />
+ <ClInclude Include="..\include\filesystem_fs.h" />
+ <ClInclude Include="..\include\ImmutableSortedVector.h" />
+ <ClInclude Include="..\include\MachineType.h" />
+ <ClInclude Include="..\include\metrics.h" />
+ <ClInclude Include="..\include\opt_bool.h" />
<ClInclude Include="..\include\package_spec.h" />
<ClInclude Include="..\include\package_spec_parse_result.h" />
+ <ClInclude Include="..\include\Paragraphs.h" />
+ <ClInclude Include="..\include\pch.h" />
+ <ClInclude Include="..\include\PostBuildLint.h" />
+ <ClInclude Include="..\include\PostBuildLint_BuildType.h" />
+ <ClInclude Include="..\include\PostBuildLint_ConfigurationType.h" />
+ <ClInclude Include="..\include\PostBuildLint_LinkageType.h" />
<ClInclude Include="..\include\SourceParagraph.h" />
<ClInclude Include="..\include\StatusParagraph.h" />
<ClInclude Include="..\include\StatusParagraphs.h" />
+ <ClInclude Include="..\include\vcpkg_Chrono.h" />
<ClInclude Include="..\include\triplet.h" />
- <ClInclude Include="..\include\vcpkg.h" />
+ <ClInclude Include="..\include\vcpkglib.h" />
<ClInclude Include="..\include\vcpkglib_helpers.h" />
+ <ClInclude Include="..\include\vcpkg_Checks.h" />
+ <ClInclude Include="..\include\vcpkg_cmd_arguments.h" />
+ <ClInclude Include="..\include\vcpkg_Commands.h" />
+ <ClInclude Include="..\include\vcpkg_Dependencies.h" />
+ <ClInclude Include="..\include\vcpkg_Enums.h" />
+ <ClInclude Include="..\include\vcpkg_Environment.h" />
+ <ClInclude Include="..\include\vcpkg_Files.h" />
+ <ClInclude Include="..\include\vcpkg_Graphs.h" />
+ <ClInclude Include="..\include\vcpkg_Input.h" />
+ <ClInclude Include="..\include\vcpkg_Maps.h" />
+ <ClInclude Include="..\include\vcpkg_optional.h" />
<ClInclude Include="..\include\vcpkg_paths.h" />
+ <ClInclude Include="..\include\vcpkg_Sets.h" />
+ <ClInclude Include="..\include\vcpkg_Strings.h" />
+ <ClInclude Include="..\include\vcpkg_System.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\BinaryParagraph.cpp" />
- <ClCompile Include="..\src\lib.cpp" />
+ <ClCompile Include="..\src\commands_ci.cpp" />
+ <ClCompile Include="..\src\PostBuildLint_BuildInfo.cpp" />
+ <ClCompile Include="..\src\PostBuildLint_BuildPolicies.cpp" />
+ <ClCompile Include="..\src\coff_file_reader.cpp" />
+ <ClCompile Include="..\src\commands_available_commands.cpp" />
+ <ClCompile Include="..\src\commands_build.cpp" />
+ <ClCompile Include="..\src\commands_build_external.cpp" />
+ <ClCompile Include="..\src\commands_cache.cpp" />
+ <ClCompile Include="..\src\commands_contact.cpp" />
+ <ClCompile Include="..\src\commands_create.cpp" />
+ <ClCompile Include="..\src\commands_edit.cpp" />
+ <ClCompile Include="..\src\commands_hash.cpp" />
+ <ClCompile Include="..\src\commands_help.cpp" />
+ <ClCompile Include="..\src\commands_import.cpp" />
+ <ClCompile Include="..\src\commands_install.cpp" />
+ <ClCompile Include="..\src\commands_integrate.cpp" />
+ <ClCompile Include="..\src\commands_list.cpp" />
+ <ClCompile Include="..\src\commands_owns.cpp" />
+ <ClCompile Include="..\src\commands_portsdiff.cpp" />
+ <ClCompile Include="..\src\commands_remove.cpp" />
+ <ClCompile Include="..\src\commands_search.cpp" />
+ <ClCompile Include="..\src\commands_update.cpp" />
+ <ClCompile Include="..\src\commands_version.cpp" />
+ <ClCompile Include="..\src\MachineType.cpp" />
+ <ClCompile Include="..\src\metrics.cpp" />
+ <ClCompile Include="..\src\opt_bool.cpp" />
+ <ClCompile Include="..\src\pch.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="..\src\PostBuildLint.cpp" />
+ <ClCompile Include="..\src\PostBuildLint_ConfigurationType.cpp" />
+ <ClCompile Include="..\src\PostBuildLint_LinkageType.cpp" />
+ <ClCompile Include="..\src\PostBuildLint_BuildType.cpp" />
+ <ClCompile Include="..\src\vcpkg_Chrono.cpp" />
+ <ClCompile Include="..\src\vcpkglib.cpp" />
<ClCompile Include="..\src\package_spec.cpp" />
<ClCompile Include="..\src\package_spec_parse_result.cpp" />
+ <ClCompile Include="..\src\Paragraphs.cpp" />
<ClCompile Include="..\src\SourceParagraph.cpp" />
<ClCompile Include="..\src\StatusParagraph.cpp" />
<ClCompile Include="..\src\StatusParagraphs.cpp" />
<ClCompile Include="..\src\triplet.cpp" />
- <ClCompile Include="..\src\vcpkg.cpp" />
<ClCompile Include="..\src\vcpkglib_helpers.cpp" />
+ <ClCompile Include="..\src\vcpkg_Checks.cpp" />
+ <ClCompile Include="..\src\vcpkg_cmd_arguments.cpp" />
+ <ClCompile Include="..\src\vcpkg_Dependencies.cpp" />
+ <ClCompile Include="..\src\vcpkg_Enums.cpp" />
+ <ClCompile Include="..\src\vcpkg_Environment.cpp" />
+ <ClCompile Include="..\src\vcpkg_Files.cpp" />
+ <ClCompile Include="..\src\vcpkg_Input.cpp" />
<ClCompile Include="..\src\vcpkg_paths.cpp" />
- <ClCompile Include="..\src\vcpkg_version.cpp" />
+ <ClCompile Include="..\src\vcpkg_Strings.cpp" />
+ <ClCompile Include="..\src\vcpkg_System.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
diff --git a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters
index eec73a445..d701321be 100644
--- a/toolsrc/vcpkglib/vcpkglib.vcxproj.filters
+++ b/toolsrc/vcpkglib/vcpkglib.vcxproj.filters
@@ -15,15 +15,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\src\vcpkg.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\lib.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- <ClCompile Include="..\src\vcpkg_version.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
<ClCompile Include="..\src\package_spec.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -51,11 +42,137 @@
<ClCompile Include="..\src\vcpkg_paths.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="..\src\Paragraphs.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\metrics.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_Input.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_Environment.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coff_file_reader.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_available_commands.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_build.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_build_external.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_cache.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_contact.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_create.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_edit.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_hash.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_help.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_import.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_install.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_integrate.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_list.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_owns.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_portsdiff.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_remove.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_search.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_update.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_version.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\MachineType.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_cmd_arguments.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_Dependencies.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkglib.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_System.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_Checks.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_Files.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_Strings.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\pch.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\opt_bool.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\PostBuildLint.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\PostBuildLint_BuildInfo.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\PostBuildLint_BuildPolicies.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\PostBuildLint_LinkageType.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\PostBuildLint_ConfigurationType.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\PostBuildLint_BuildType.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_Enums.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\commands_ci.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vcpkg_Chrono.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
- <ClInclude Include="..\include\vcpkg.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="..\include\package_spec.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -83,5 +200,101 @@
<ClInclude Include="..\include\vcpkg_paths.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="..\include\Paragraphs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\metrics.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Input.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\coff_file_reader.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\filesystem_fs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\MachineType.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_cmd_arguments.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Commands.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Dependencies.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Environment.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkglib.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\expected.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\ImmutableSortedVector.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\opt_bool.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Checks.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Files.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Graphs.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Maps.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Sets.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Strings.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_System.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\pch.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_optional.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\PostBuildLint.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\PostBuildLint_BuildInfo.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\PostBuildLint_BuildPolicies.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\PostBuildLint_LinkageType.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\PostBuildLint_ConfigurationType.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\PostBuildLint_BuildType.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Enums.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\vcpkg_Chrono.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\include\lazy.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file
diff --git a/toolsrc/vcpkgmetrics/vcpkgmetrics.vcxproj b/toolsrc/vcpkgmetrics/vcpkgmetrics.vcxproj
deleted file mode 100644
index 7b7fe89ed..000000000
--- a/toolsrc/vcpkgmetrics/vcpkgmetrics.vcxproj
+++ /dev/null
@@ -1,140 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Debug|x64">
- <Configuration>Debug</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|x64">
- <Configuration>Release</Configuration>
- <Platform>x64</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectGuid>{7226078C-1D2A-4123-9EF1-8DF2B722B8F1}</ProjectGuid>
- <RootNamespace>vcpkgmetrics</RootNamespace>
- <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
- <ConfigurationType>StaticLibrary</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
- <WholeProgramOptimization>true</WholeProgramOptimization>
- <CharacterSet>MultiByte</CharacterSet>
- </PropertyGroup>
- <PropertyGroup>
- <DISABLE_METRICS Condition="'$(DISABLE_METRICS)' == ''">0</DISABLE_METRICS>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Label="Shared">
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup />
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>Disabled</Optimization>
- <SDLCheck>true</SDLCheck>
- <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>Disabled</Optimization>
- <SDLCheck>true</SDLCheck>
- <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <SDLCheck>true</SDLCheck>
- <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>DISABLE_METRICS=$(DISABLE_METRICS);_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
- <ClCompile>
- <WarningLevel>Level3</WarningLevel>
- <Optimization>MaxSpeed</Optimization>
- <FunctionLevelLinking>true</FunctionLevelLinking>
- <IntrinsicFunctions>true</IntrinsicFunctions>
- <SDLCheck>true</SDLCheck>
- <AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>DISABLE_METRICS=$(DISABLE_METRICS);_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- <Link>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <OptimizeReferences>true</OptimizeReferences>
- </Link>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup>
- <ClCompile>
- <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">DISABLE_METRICS=$(DISABLE_METRICS);_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">DISABLE_METRICS=$(DISABLE_METRICS);_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">/std:c++latest %(AdditionalOptions)</AdditionalOptions>
- <AdditionalOptions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">/std:c++latest %(AdditionalOptions)</AdditionalOptions>
- </ClCompile>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClInclude Include="..\include\metrics.h" />
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="..\src\metrics.cpp" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project> \ No newline at end of file
diff --git a/toolsrc/vcpkgmetrics/vcpkgmetrics.vcxproj.filters b/toolsrc/vcpkgmetrics/vcpkgmetrics.vcxproj.filters
deleted file mode 100644
index 7116a4247..000000000
--- a/toolsrc/vcpkgmetrics/vcpkgmetrics.vcxproj.filters
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup>
- <Filter Include="Source Files">
- <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
- <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
- </Filter>
- <Filter Include="Header Files">
- <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
- <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
- </Filter>
- <Filter Include="Resource Files">
- <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
- <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
- </Filter>
- </ItemGroup>
- <ItemGroup>
- <ClInclude Include="..\include\metrics.h">
- <Filter>Header Files</Filter>
- </ClInclude>
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="..\src\metrics.cpp">
- <Filter>Source Files</Filter>
- </ClCompile>
- </ItemGroup>
-</Project> \ No newline at end of file
diff --git a/toolsrc/vcpkgmetricsuploader/vcpkgmetricsuploader.vcxproj b/toolsrc/vcpkgmetricsuploader/vcpkgmetricsuploader.vcxproj
index 1e2a85087..472d74e30 100644
--- a/toolsrc/vcpkgmetricsuploader/vcpkgmetricsuploader.vcxproj
+++ b/toolsrc/vcpkgmetricsuploader/vcpkgmetricsuploader.vcxproj
@@ -22,31 +22,28 @@
<ProjectGuid>{7D6FDEEB-B299-4A23-85EE-F67C4DED47BE}</ProjectGuid>
<RootNamespace>vcpkgmetricsuploader</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
@@ -76,6 +73,8 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -83,11 +82,13 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
- <WarningLevel>Level3</WarningLevel>
+ <WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
@@ -103,6 +104,7 @@
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -120,6 +122,7 @@
<AdditionalIncludeDirectories>..\include</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_MBCS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -131,11 +134,8 @@
<ClCompile Include="..\src\vcpkg_metrics_uploader.cpp" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\vcpkgcommon\vcpkgcommon.vcxproj">
- <Project>{7129f242-f20c-43e7-bbec-4e15b71890b2}</Project>
- </ProjectReference>
- <ProjectReference Include="..\vcpkgmetrics\vcpkgmetrics.vcxproj">
- <Project>{7226078c-1d2a-4123-9ef1-8df2b722b8f1}</Project>
+ <ProjectReference Include="..\vcpkglib\vcpkglib.vcxproj">
+ <Project>{b98c92b7-2874-4537-9d46-d14e5c237f04}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
diff --git a/toolsrc/vcpkgtest/vcpkgtest.vcxproj b/toolsrc/vcpkgtest/vcpkgtest.vcxproj
index 3d9503374..c12c2dd31 100644
--- a/toolsrc/vcpkgtest/vcpkgtest.vcxproj
+++ b/toolsrc/vcpkgtest/vcpkgtest.vcxproj
@@ -19,37 +19,31 @@
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\src\test.cpp" />
+ <ClCompile Include="..\src\tests_dependencies.cpp" />
+ <ClCompile Include="..\src\tests_paragraph.cpp" />
</ItemGroup>
<ItemGroup>
- <ProjectReference Include="..\vcpkgcommon\vcpkgcommon.vcxproj">
- <Project>{7129f242-f20c-43e7-bbec-4e15b71890b2}</Project>
- </ProjectReference>
<ProjectReference Include="..\vcpkglib\vcpkglib.vcxproj">
<Project>{b98c92b7-2874-4537-9d46-d14e5c237f04}</Project>
</ProjectReference>
- <ProjectReference Include="..\vcpkgmetrics\vcpkgmetrics.vcxproj">
- <Project>{7226078c-1d2a-4123-9ef1-8df2b722b8f1}</Project>
- </ProjectReference>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{F27B8DB0-1279-4AF8-A2E3-1D49C4F0220D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>vcpkgtest</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
+ <PlatformToolset>v140</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
@@ -57,14 +51,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
@@ -105,6 +97,8 @@
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile />
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -114,13 +108,15 @@
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
+ <WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>..\include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <AdditionalIncludeDirectories>..\include;$(VCInstallDir)UnitTest\include;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile />
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
+ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -139,6 +135,7 @@
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile />
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -159,6 +156,7 @@
<UseFullPaths>true</UseFullPaths>
<PrecompiledHeaderFile />
<AdditionalOptions>/std:c++latest %(AdditionalOptions)</AdditionalOptions>
+ <MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
diff --git a/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters b/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters
index 9db7e6ef8..bbbc6bd40 100644
--- a/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters
+++ b/toolsrc/vcpkgtest/vcpkgtest.vcxproj.filters
@@ -15,7 +15,10 @@
</Filter>
</ItemGroup>
<ItemGroup>
- <ClCompile Include="..\src\test.cpp">
+ <ClCompile Include="..\src\tests_paragraph.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\tests_dependencies.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>