From f0902b35370fbebcf257de88e43ee47379185a10 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 20 Jun 2019 11:46:55 -0700 Subject: VS 2019 16.3 deprecates . (#6968) VS 2019 16.3 will contain a couple of source-breaking changes: * will be deprecated via an impossible-to-miss preprocessor "#error The header providing std::experimental::filesystem is deprecated by Microsoft and will be REMOVED. It is superseded by the C++17 header providing std::filesystem. You can define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING to acknowledge that you have received this warning." * will no longer include . In the long term, I believe that vcpkg should detect when it's being built with VS 2017 15.7 or newer, compile in C++17 mode, include , and use std::filesystem. (Activating this for VS 2019 16.0 or newer would also be reasonable.) Similarly for other toolsets supporting std::filesystem. In the short term, this commit makes vcpkg compatible with the upcoming deprecation. First, we need to define the silencing macro before including the appropriate header. I've chosen to define it unconditionally (without checking for platform or version), since it has no effect for other platforms or versions. Second, we need to deal with no longer including . I verified that VS 2015 Update 3 contained (back then, it simply included the header, where the experimental implementation was defined; this was later reorganized). Therefore, all of vcpkg's supported MSVC toolsets have , so we can simply always include it. I've verified that this builds with both VS 2015 Update 3 and VS 2019 16.1.3 (the current production version). --- toolsrc/include/pch.h | 5 +---- toolsrc/include/vcpkg/base/files.h | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/pch.h b/toolsrc/include/pch.h index fa2c2bb72..15ec25e76 100644 --- a/toolsrc/include/pch.h +++ b/toolsrc/include/pch.h @@ -37,11 +37,8 @@ #include #include #include -#if defined(_WIN32) -#include -#else +#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING #include -#endif #include #include #include diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h index 02e2b8db8..3ea0d6036 100644 --- a/toolsrc/include/vcpkg/base/files.h +++ b/toolsrc/include/vcpkg/base/files.h @@ -2,11 +2,8 @@ #include -#if defined(_WIN32) -#include -#else +#define _SILENCE_EXPERIMENTAL_FILESYSTEM_DEPRECATION_WARNING #include -#endif namespace fs { -- cgit v1.2.3 From f3db66b403840b24ea2612d09cca30a5285f5ea3 Mon Sep 17 00:00:00 2001 From: Victor Romero Date: Fri, 21 Jun 2019 23:50:05 -0700 Subject: Ports Overlay partial implementation (#6981) * Ports Overlay feature spec * Ports Overlay implementation * [--overlay-ports] Refactor handling of additional paths * Code cleanup * [--overlay-ports] Add help * [depend-info] Support --overlay-ports * Add method to load all ports using PathsPortFileProvider * Make PortFileProvider::load_all_control_files() const * Remove unused code * [vcpkg] Avoid double-load of source control file between Build::perform_and_exit and Build::perform_and_exit_ex * [vcpkg] Clang format * [vcpkg] Fixup build failure introduced in b069ceb2f231 * Report errors from Paragraphs::try_load_port() --- toolsrc/include/vcpkg/build.h | 2 +- toolsrc/include/vcpkg/dependencies.h | 27 ++++++++++++++++----------- toolsrc/include/vcpkg/postbuildlint.h | 3 ++- toolsrc/include/vcpkg/sourceparagraph.h | 9 +++++++++ toolsrc/include/vcpkg/vcpkgcmdarguments.h | 16 +++++++++++++++- toolsrc/include/vcpkg/vcpkgpaths.h | 2 -- 6 files changed, 43 insertions(+), 16 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index 9044cb556..04cd7cf87 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -20,7 +20,7 @@ namespace vcpkg::Build namespace Command { void perform_and_exit_ex(const FullPackageSpec& full_spec, - const fs::path& port_dir, + const SourceControlFileLocation& scfl, const ParsedArguments& options, const VcpkgPaths& paths); diff --git a/toolsrc/include/vcpkg/dependencies.h b/toolsrc/include/vcpkg/dependencies.h index 16fdb3f73..8c2050b3d 100644 --- a/toolsrc/include/vcpkg/dependencies.h +++ b/toolsrc/include/vcpkg/dependencies.h @@ -48,7 +48,7 @@ namespace vcpkg::Dependencies const RequestType& request_type); InstallPlanAction(const PackageSpec& spec, - const SourceControlFile& scf, + const SourceControlFileLocation& scfl, const std::set& features, const RequestType& request_type, std::vector&& dependencies); @@ -57,7 +57,7 @@ namespace vcpkg::Dependencies PackageSpec spec; - Optional source_control_file; + Optional source_control_file_location; Optional installed_package; InstallPlanType plan_type; @@ -129,26 +129,31 @@ namespace vcpkg::Dependencies struct PortFileProvider { - virtual Optional get_control_file(const std::string& src_name) const = 0; + virtual Optional get_control_file(const std::string& src_name) const = 0; + virtual std::vector load_all_control_files() const = 0; }; struct MapPortFileProvider : Util::ResourceBase, PortFileProvider { - explicit MapPortFileProvider(const std::unordered_map& map); - Optional get_control_file(const std::string& src_name) const override; + explicit MapPortFileProvider(const std::unordered_map& map); + Optional get_control_file(const std::string& src_name) const override; + std::vector load_all_control_files() const override; private: - const std::unordered_map& ports; + const std::unordered_map& ports; }; struct PathsPortFileProvider : Util::ResourceBase, PortFileProvider { - explicit PathsPortFileProvider(const VcpkgPaths& paths); - Optional get_control_file(const std::string& src_name) const override; + explicit PathsPortFileProvider(const vcpkg::VcpkgPaths& paths, + const std::vector* ports_dirs_paths); + Optional get_control_file(const std::string& src_name) const override; + std::vector load_all_control_files() const override; private: - const VcpkgPaths& ports; - mutable std::unordered_map cache; + Files::Filesystem& filesystem; + std::vector ports_dirs; + mutable std::unordered_map cache; }; struct ClusterGraph; @@ -181,7 +186,7 @@ namespace vcpkg::Dependencies std::vector create_export_plan(const std::vector& specs, const StatusParagraphs& status_db); - std::vector create_feature_install_plan(const std::unordered_map& map, + std::vector create_feature_install_plan(const std::unordered_map& map, const std::vector& specs, const StatusParagraphs& status_db); diff --git a/toolsrc/include/vcpkg/postbuildlint.h b/toolsrc/include/vcpkg/postbuildlint.h index 5dcfeb8df..027619eb8 100644 --- a/toolsrc/include/vcpkg/postbuildlint.h +++ b/toolsrc/include/vcpkg/postbuildlint.h @@ -9,5 +9,6 @@ namespace vcpkg::PostBuildLint size_t perform_all_checks(const PackageSpec& spec, const VcpkgPaths& paths, const Build::PreBuildInfo& pre_build_info, - const Build::BuildInfo& build_info); + const Build::BuildInfo& build_info, + const fs::path& port_dir); } diff --git a/toolsrc/include/vcpkg/sourceparagraph.h b/toolsrc/include/vcpkg/sourceparagraph.h index d70fd4337..6232a3fd2 100644 --- a/toolsrc/include/vcpkg/sourceparagraph.h +++ b/toolsrc/include/vcpkg/sourceparagraph.h @@ -68,6 +68,15 @@ namespace vcpkg Optional find_feature(const std::string& featurename) const; }; + /// + /// Full metadata of a package: core and other features. As well as the location the SourceControlFile was loaded from. + /// + struct SourceControlFileLocation + { + std::unique_ptr source_control_file; + fs::path source_location; + }; + void print_error_message(Span> error_info_list); inline void print_error_message(const std::unique_ptr& error_info_list) { diff --git a/toolsrc/include/vcpkg/vcpkgcmdarguments.h b/toolsrc/include/vcpkg/vcpkgcmdarguments.h index de65eec28..cad013eb8 100644 --- a/toolsrc/include/vcpkg/vcpkgcmdarguments.h +++ b/toolsrc/include/vcpkg/vcpkgcmdarguments.h @@ -15,6 +15,7 @@ namespace vcpkg { std::unordered_set switches; std::unordered_map settings; + std::unordered_map> multisettings; }; struct VcpkgPaths; @@ -41,10 +42,22 @@ namespace vcpkg StringLiteral short_help_text; }; + struct CommandMultiSetting + { + constexpr CommandMultiSetting(const StringLiteral& name, const StringLiteral& short_help_text) + : name(name), short_help_text(short_help_text) + { + } + + StringLiteral name; + StringLiteral short_help_text; + }; + struct CommandOptionsStructure { Span switches; Span settings; + Span multisettings; }; struct CommandStructure @@ -74,6 +87,7 @@ namespace vcpkg std::unique_ptr vcpkg_root_dir; std::unique_ptr triplet; + std::unique_ptr> overlay_ports; Optional debug = nullopt; Optional sendmetrics = nullopt; Optional printmetrics = nullopt; @@ -88,6 +102,6 @@ namespace vcpkg ParsedArguments parse_arguments(const CommandStructure& command_structure) const; private: - std::unordered_map> optional_command_arguments; + std::unordered_map>> optional_command_arguments; }; } diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h index 42de40d9c..b09169b02 100644 --- a/toolsrc/include/vcpkg/vcpkgpaths.h +++ b/toolsrc/include/vcpkg/vcpkgpaths.h @@ -50,8 +50,6 @@ namespace vcpkg static Expected create(const fs::path& vcpkg_root_dir, const std::string& default_vs_path); fs::path package_dir(const PackageSpec& spec) const; - fs::path port_dir(const PackageSpec& spec) const; - fs::path port_dir(const std::string& name) const; fs::path build_info_file_path(const PackageSpec& spec) const; fs::path listfile_path(const BinaryParagraph& pgh) const; -- cgit v1.2.3 From 9e565e986789cf273de12fe1b07ce31800d10417 Mon Sep 17 00:00:00 2001 From: Victor Romero Date: Mon, 24 Jun 2019 12:09:48 -0700 Subject: [--overlay-ports] Show location of overriden ports during install plan (#7002) * [--overlay-ports] Show source location of overlayed ports during install plan * Code cleanup * Code cleanup --- toolsrc/include/vcpkg/dependencies.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/dependencies.h b/toolsrc/include/vcpkg/dependencies.h index 8c2050b3d..964158026 100644 --- a/toolsrc/include/vcpkg/dependencies.h +++ b/toolsrc/include/vcpkg/dependencies.h @@ -199,5 +199,7 @@ namespace vcpkg::Dependencies const StatusParagraphs& status_db, const CreateInstallPlanOptions& options = {}); - void print_plan(const std::vector& action_plan, const bool is_recursive = true); + void print_plan(const std::vector& action_plan, + const bool is_recursive = true, + const fs::path& default_ports_dir = ""); } -- cgit v1.2.3 From 35e985d3ccf60235bc4881df4d934610cd507090 Mon Sep 17 00:00:00 2001 From: Victor Romero Date: Thu, 27 Jun 2019 12:20:12 -0700 Subject: Triplets Overlay Implementation (#7053) * Triplets Overlay Implementation * Use cache for get_triplet_file_path() * Code cleanup --- toolsrc/include/vcpkg/vcpkgcmdarguments.h | 1 + toolsrc/include/vcpkg/vcpkgpaths.h | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/vcpkgcmdarguments.h b/toolsrc/include/vcpkg/vcpkgcmdarguments.h index cad013eb8..ff13ae6bf 100644 --- a/toolsrc/include/vcpkg/vcpkgcmdarguments.h +++ b/toolsrc/include/vcpkg/vcpkgcmdarguments.h @@ -88,6 +88,7 @@ namespace vcpkg std::unique_ptr vcpkg_root_dir; std::unique_ptr triplet; std::unique_ptr> overlay_ports; + std::unique_ptr> overlay_triplets; Optional debug = nullopt; Optional sendmetrics = nullopt; Optional printmetrics = nullopt; diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h index b09169b02..a30e0c653 100644 --- a/toolsrc/include/vcpkg/vcpkgpaths.h +++ b/toolsrc/include/vcpkg/vcpkgpaths.h @@ -47,14 +47,17 @@ namespace vcpkg struct VcpkgPaths { - static Expected create(const fs::path& vcpkg_root_dir, const std::string& default_vs_path); + static Expected create(const fs::path& vcpkg_root_dir, + const std::string& default_vs_path, + const std::vector* triplets_dirs); fs::path package_dir(const PackageSpec& spec) const; fs::path build_info_file_path(const PackageSpec& spec) const; fs::path listfile_path(const BinaryParagraph& pgh) const; - - const std::vector& get_available_triplets() const; + bool is_valid_triplet(const Triplet& t) const; + const std::vector& get_available_triplets() const; + const fs::path get_triplet_file_path(const Triplet& triplet) const; fs::path root; fs::path packages; @@ -93,7 +96,9 @@ namespace vcpkg Lazy> toolsets_vs2013; fs::path default_vs_path; + std::vector triplets_dirs; mutable std::unique_ptr m_tool_cache; + mutable vcpkg::Cache m_triplets_cache; }; } -- cgit v1.2.3 From 91da4aab4c74af1d30c68896a058100257910e8d Mon Sep 17 00:00:00 2001 From: martin-s Date: Tue, 2 Jul 2019 05:51:07 +0000 Subject: Allow redirection of the scripts folder. (#6552) * Allow redirection of the scripts folder with an environment variable. * - Updated feature from environment variable to argument. * Fix crash when no scripts override is given and use --scripts-root= format * Update help messages to use --scripts-root= format --- toolsrc/include/vcpkg/vcpkgcmdarguments.h | 1 + toolsrc/include/vcpkg/vcpkgpaths.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/vcpkgcmdarguments.h b/toolsrc/include/vcpkg/vcpkgcmdarguments.h index ff13ae6bf..fe7911ae3 100644 --- a/toolsrc/include/vcpkg/vcpkgcmdarguments.h +++ b/toolsrc/include/vcpkg/vcpkgcmdarguments.h @@ -86,6 +86,7 @@ namespace vcpkg static VcpkgCmdArguments create_from_arg_sequence(const std::string* arg_begin, const std::string* arg_end); std::unique_ptr vcpkg_root_dir; + std::unique_ptr scripts_root_dir; std::unique_ptr triplet; std::unique_ptr> overlay_ports; std::unique_ptr> overlay_triplets; diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h index a30e0c653..ce442858b 100644 --- a/toolsrc/include/vcpkg/vcpkgpaths.h +++ b/toolsrc/include/vcpkg/vcpkgpaths.h @@ -47,7 +47,8 @@ namespace vcpkg struct VcpkgPaths { - static Expected create(const fs::path& vcpkg_root_dir, + static Expected create(const fs::path& vcpkg_root_dir, + const Optional& vcpkg_scripts_root_dir, const std::string& default_vs_path, const std::vector* triplets_dirs); -- cgit v1.2.3 From 2b8e225b2ea83a3138d4b7345f104c1bd9a129dd Mon Sep 17 00:00:00 2001 From: Robert Schumacher Date: Sat, 6 Jul 2019 13:29:46 -0700 Subject: [vcpkg] Fix powershell font corruption bug (#7094) * [vcpkg] Fix font corruption bug on Windows by downloading Powershell Core * [vcpkg] Rename subtool to powershell-core * [vcpkg] Add missing includes to project files --- toolsrc/include/vcpkg/base/system.process.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/system.process.h b/toolsrc/include/vcpkg/base/system.process.h index e409ff950..14e2eb109 100644 --- a/toolsrc/include/vcpkg/base/system.process.h +++ b/toolsrc/include/vcpkg/base/system.process.h @@ -31,7 +31,8 @@ namespace vcpkg::System }; int cmd_execute_clean(const ZStringView cmd_line, - const std::unordered_map& extra_env = {}); + const std::unordered_map& extra_env = {}, + const std::string& prepend_to_path = {}); int cmd_execute(const ZStringView cmd_line); -- cgit v1.2.3 From 7f80c0e2d311c7ff2453bdd558e4e7fd91cea872 Mon Sep 17 00:00:00 2001 From: gnaggnoyil Date: Wed, 10 Jul 2019 04:02:48 +0800 Subject: Make handle features (#6797) --- toolsrc/include/vcpkg/base/util.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/util.h b/toolsrc/include/vcpkg/base/util.h index 213adb67c..e629ef0b2 100644 --- a/toolsrc/include/vcpkg/base/util.h +++ b/toolsrc/include/vcpkg/base/util.h @@ -6,9 +6,18 @@ #include #include #include +#include namespace vcpkg::Util { + template + constexpr std::add_const_t& as_const(T& t) noexcept + { + return t; + } + template + void as_const(const T&&) = delete; + template using ElementT = std::remove_reference_t::iterator>())>; -- cgit v1.2.3 From 5857e2c680fde9e37abc8f799f8d5509dd47ed62 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Mon, 8 Jul 2019 16:45:27 -0700 Subject: initial remove-in-parallel doesn't actually do parallel remove yet --- toolsrc/include/vcpkg/base/rng.h | 96 ++++++++++++++++++++++++++++++++++++ toolsrc/include/vcpkg/base/strings.h | 32 ++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 toolsrc/include/vcpkg/base/rng.h (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/rng.h b/toolsrc/include/vcpkg/base/rng.h new file mode 100644 index 000000000..1bcab05b3 --- /dev/null +++ b/toolsrc/include/vcpkg/base/rng.h @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include + +namespace vcpkg { + + /* + NOTE(ubsan): taken from the xoshiro paper + initialized from random_device by default + actual code is copied from wikipedia, since I wrote that code + */ + struct splitmix64_engine { + splitmix64_engine() noexcept; + + constexpr splitmix64_engine(std::uint64_t seed) noexcept + : state(seed) {} + + constexpr std::uint64_t operator()() noexcept { + state += 0x9E3779B97F4A7C15; + + std::uint64_t result = state; + result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9; + result = (result ^ (result >> 27)) * 0x94D049BB133111EB; + + return result ^ (result >> 31); + } + + constexpr std::uint64_t max() const noexcept { + return std::numeric_limits::max(); + } + + constexpr std::uint64_t min() const noexcept { + return std::numeric_limits::min(); + } + + private: + std::uint64_t state; + }; + + // Sebastian Vigna's xorshift-based xoshiro xoshiro256** engine + // fast and really good + // uses the splitmix64_engine to initialize state + struct xoshiro256ss_engine { + // splitmix64_engine will be initialized with random_device + xoshiro256ss_engine() noexcept { + splitmix64_engine sm64{}; + + for (std::uint64_t& s : this->state) { + s = sm64(); + } + } + + constexpr xoshiro256ss_engine(std::uint64_t seed) noexcept : state() { + splitmix64_engine sm64{seed}; + + for (std::uint64_t& s : this->state) { + s = sm64(); + } + } + + constexpr std::uint64_t operator()() noexcept { + std::uint64_t const result = rol(state[1] * 5, 7) * 9; + + std::uint64_t const t = state[1] << 17; + + // state[i] = state[i] ^ state[i + 4 mod 4] + state[2] ^= state[0]; + state[3] ^= state[1]; + state[1] ^= state[2]; + state[0] ^= state[3]; + + state[2] ^= t; + state[3] ^= rol(state[3], 45); + + return result; + } + + constexpr std::uint64_t max() const noexcept { + return std::numeric_limits::max(); + } + + constexpr std::uint64_t min() const noexcept { + return std::numeric_limits::min(); + } + private: + // rotate left + constexpr std::uint64_t rol(std::uint64_t x, int k) { + return (x << k) | (x >> (64 - k)); + } + + std::uint64_t state[4]; + }; + +} diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h index d553d1d41..423ea2096 100644 --- a/toolsrc/include/vcpkg/base/strings.h +++ b/toolsrc/include/vcpkg/base/strings.h @@ -184,4 +184,36 @@ namespace vcpkg::Strings const char* search(StringView haystack, StringView needle); bool contains(StringView haystack, StringView needle); + + // base 64 encoding with URL and filesafe alphabet (base64url) + // based on IETF RFC 4648 + // ignores padding, since one implicitly knows the length from the size of x + template + std::string b64url_encode(Integral x) { + static_assert(std::is_integral_v); + auto value = static_cast>(x); + + // 64 values, plus the implicit \0 + constexpr static char map[0x41] = + /* 0123456789ABCDEF */ + /*0*/ "ABCDEFGHIJKLMNOP" + /*1*/ "QRSTUVWXYZabcdef" + /*2*/ "ghijklmnopqrstuv" + /*3*/ "wxyz0123456789-_" + ; + + constexpr static std::make_unsigned_t mask = 0x3F; + constexpr static int shift = 5; + + std::string result; + // reserve ceiling(number of bits / 3) + result.reserve((sizeof(value) * 8 + 2) / 3); + + while (value != 0) { + char mapped_value = map[value & mask]; + result.push_back(mapped_value); + } + + return result; + } } -- cgit v1.2.3 From 2d6df16849ebcf237d17c919727756d90974daba Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Wed, 10 Jul 2019 14:35:10 -0700 Subject: remove_all parallelized, and fix the issues with symlink --- toolsrc/include/vcpkg/base/files.h | 38 ++++++- toolsrc/include/vcpkg/base/rng.h | 167 +++++++++++++++++++++++------ toolsrc/include/vcpkg/base/work_queue.h | 183 ++++++++++++++++++++++++++++++++ 3 files changed, 355 insertions(+), 33 deletions(-) create mode 100644 toolsrc/include/vcpkg/base/work_queue.h (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h index 3ea0d6036..178fae541 100644 --- a/toolsrc/include/vcpkg/base/files.h +++ b/toolsrc/include/vcpkg/base/files.h @@ -12,14 +12,50 @@ namespace fs using stdfs::copy_options; using stdfs::file_status; using stdfs::file_type; + using stdfs::perms; using stdfs::path; using stdfs::u8path; + /* + std::experimental::filesystem's file_status and file_type are broken in + the presence of symlinks -- a symlink is treated as the object it points + to for `symlink_status` and `symlink_type` + */ + + using stdfs::status; + + // we want to poison ADL with these niebloids + constexpr struct { + file_status operator()(const path& p, std::error_code& ec) const noexcept; + file_status operator()(const path& p) const noexcept; + } symlink_status{}; + + constexpr struct { + inline bool operator()(file_status s) const { + return stdfs::is_symlink(s); + } + + inline bool operator()(const path& p) const { + return stdfs::is_symlink(symlink_status(p)); + } + inline bool operator()(const path& p, std::error_code& ec) const { + return stdfs::is_symlink(symlink_status(p, ec)); + } + } is_symlink{}; + inline bool is_regular_file(file_status s) { return stdfs::is_regular_file(s); } inline bool is_directory(file_status s) { return stdfs::is_directory(s); } - inline bool is_symlink(file_status s) { return stdfs::is_symlink(s); } } +/* + if someone attempts to use unqualified `symlink_status` or `is_symlink`, + they might get the ADL version, which is broken. + Therefore, put `symlink_status` in the global namespace, so that they get + our symlink_status. +*/ +using fs::symlink_status; +using fs::is_symlink; + namespace vcpkg::Files { struct Filesystem diff --git a/toolsrc/include/vcpkg/base/rng.h b/toolsrc/include/vcpkg/base/rng.h index 1bcab05b3..4a0411f64 100644 --- a/toolsrc/include/vcpkg/base/rng.h +++ b/toolsrc/include/vcpkg/base/rng.h @@ -4,17 +4,56 @@ #include #include -namespace vcpkg { +namespace vcpkg::Rng { + + namespace detail { + template + constexpr std::size_t bitsize = sizeof(T) * CHAR_BITS; + + template + constexpr bool is_valid_shift(int k) { + return 0 <= k && k <= bitsize; + } + + // precondition: 0 <= k < bitsize + template + constexpr T ror(T x, int k) { + if (k == 0) { + return x; + } + return (x >> k) | (x << (bitsize - k)); + } + + // precondition: 0 <= k < bitsize + template + constexpr T rol(T x, int k) { + if (k == 0) { + return x; + } + return (x << k) | (x >> (bitsize - k)); + } + + // there _is_ a way to do this generally, but I don't know how to + template + struct XoshiroJumpTable; + + template <> + struct XoshiroJumpTable { + constexpr static std::uint64_t value[4] = { + 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c + }; + }; + } /* NOTE(ubsan): taken from the xoshiro paper initialized from random_device by default actual code is copied from wikipedia, since I wrote that code */ - struct splitmix64_engine { - splitmix64_engine() noexcept; + struct splitmix { + splitmix() noexcept; - constexpr splitmix64_engine(std::uint64_t seed) noexcept + constexpr splitmix(std::uint64_t seed) noexcept : state(seed) {} constexpr std::uint64_t operator()() noexcept { @@ -35,62 +74,126 @@ namespace vcpkg { return std::numeric_limits::min(); } + template + constexpr void fill(T* first, T* last) { + constexpr auto mask = + static_cast(std::numeric_limits::max()); + + const auto remaining = + (last - first) % (sizeof(std::uint64_t) / sizeof(T)); + + for (auto it = first; it != last - remaining;) { + const auto item = (*this)(); + for ( + int shift = 0; + shift < 64; + shift += detail::bitsize, ++it + ) { + *it = static_cast((item >> shift) & mask); + } + } + + if (remaining == 0) return; + + int shift = 0; + const auto item = (*this)(); + for (auto it = last - remaining; + it != last; + shift += detail::bitsize, ++it + ) { + *it = static_cast((item >> shift) & mask); + } + } + private: std::uint64_t state; }; - // Sebastian Vigna's xorshift-based xoshiro xoshiro256** engine + template + struct starstar_scrambler { + constexpr static UIntType scramble(UIntType n) noexcept { + return detail::rol(n * S, R) * T; + } + }; + + // Sebastian Vigna's xorshift-based xoshiro engine // fast and really good - // uses the splitmix64_engine to initialize state - struct xoshiro256ss_engine { - // splitmix64_engine will be initialized with random_device - xoshiro256ss_engine() noexcept { - splitmix64_engine sm64{}; - - for (std::uint64_t& s : this->state) { - s = sm64(); - } + // uses the splitmix to initialize state + template + struct xoshiro_engine { + static_assert(detail::is_valid_shift(A)); + static_assert(detail::is_valid_shift(B)); + static_assert(std::is_unsigned_v); + + // splitmix will be initialized with random_device + xoshiro_engine() noexcept { + splitmix sm{}; + + sm.fill(&state[0], &state[4]); } - constexpr xoshiro256ss_engine(std::uint64_t seed) noexcept : state() { - splitmix64_engine sm64{seed}; + constexpr xoshiro_engine(std::uint64_t seed) noexcept : state() { + splitmix sm{seed}; - for (std::uint64_t& s : this->state) { - s = sm64(); - } + sm.fill(&state[0], &state[4]); } - constexpr std::uint64_t operator()() noexcept { - std::uint64_t const result = rol(state[1] * 5, 7) * 9; + constexpr UIntType operator()() noexcept { + const UIntType result = Scrambler::scramble(state[0]); - std::uint64_t const t = state[1] << 17; + const UIntType t = state[1] << A; - // state[i] = state[i] ^ state[i + 4 mod 4] state[2] ^= state[0]; state[3] ^= state[1]; state[1] ^= state[2]; state[0] ^= state[3]; state[2] ^= t; - state[3] ^= rol(state[3], 45); + state[3] ^= detail::rol(state[3], B); return result; } - constexpr std::uint64_t max() const noexcept { - return std::numeric_limits::max(); + constexpr UIntType max() const noexcept { + return std::numeric_limits::max(); } constexpr std::uint64_t min() const noexcept { - return std::numeric_limits::min(); + return std::numeric_limits::min(); + } + + // quickly jump ahead 2^e steps + // takes 4 * bitsize rng next operations + template + constexpr void discard_e() noexcept { + using JT = detail::XoshiroJumpTable; + + UIntType s[4] = {}; + for (const auto& jump : JT::value) { + for (std::size_t i = 0; i < bitsize; ++i) { + if ((jump >> i) & 1) { + s[0] ^= state[0]; + s[1] ^= state[1]; + s[2] ^= state[2]; + s[3] ^= state[3]; + } + (*this)(); + } + } + + state[0] = s[0]; + state[1] = s[1]; + state[2] = s[2]; + state[3] = s[3]; } private: // rotate left - constexpr std::uint64_t rol(std::uint64_t x, int k) { - return (x << k) | (x >> (64 - k)); - } - - std::uint64_t state[4]; + UIntType state[4]; }; + using xoshiro256ss = xoshiro_engine< + std::uint64_t, + starstar_scrambler, + 17, + 45>; } diff --git a/toolsrc/include/vcpkg/base/work_queue.h b/toolsrc/include/vcpkg/base/work_queue.h new file mode 100644 index 000000000..4db167fa6 --- /dev/null +++ b/toolsrc/include/vcpkg/base/work_queue.h @@ -0,0 +1,183 @@ +#pragma once + +#include +#include + +namespace vcpkg { + namespace detail { + template + auto call_action( + Action& action, + const WorkQueue& work_queue, + ThreadLocalData& tld + ) -> decltype(static_cast(std::move(action)(tld, work_queue))) + { + std::move(action)(tld, work_queue); + } + + template + auto call_action( + Action& action, + const WorkQueue&, + ThreadLocalData& tld + ) -> decltype(static_cast(std::move(action)(tld))) + { + std::move(action)(tld); + } + } + + template + struct WorkQueue { + template + explicit WorkQueue(const F& initializer) noexcept { + state = State::Joining; + + std::size_t num_threads = std::thread::hardware_concurrency(); + if (num_threads == 0) { + num_threads = 4; + } + + m_threads.reserve(num_threads); + for (std::size_t i = 0; i < num_threads; ++i) { + m_threads.emplace_back(this, initializer); + } + } + + WorkQueue(WorkQueue const&) = delete; + WorkQueue(WorkQueue&&) = delete; + + ~WorkQueue() = default; + + // runs all remaining tasks, and blocks on their finishing + // if this is called in an existing task, _will block forever_ + // DO NOT DO THAT + // thread-unsafe + void join() { + { + auto lck = std::unique_lock(m_mutex); + if (m_state == State::Running) { + m_state = State::Joining; + } else if (m_state == State::Joining) { + Checks::exit_with_message(VCPKG_LINE_INFO, "Attempted to join more than once"); + } + } + for (auto& thrd : m_threads) { + thrd.join(); + } + } + + // useful in the case of errors + // doesn't stop any existing running tasks + // returns immediately, so that one can call this in a task + void terminate() const { + { + auto lck = std::unique_lock(m_mutex); + m_state = State::Terminated; + } + m_cv.notify_all(); + } + + void enqueue_action(Action a) const { + { + auto lck = std::unique_lock(m_mutex); + m_actions.push_back(std::move(a)); + } + m_cv.notify_one(); + } + + template + void enqueue_all_actions_by_move(Rng&& rng) const { + { + using std::begin; + using std::end; + + auto lck = std::unique_lock(m_mutex); + + auto first = begin(rng); + auto last = end(rng); + + m_actions.reserve(m_actions.size() + (end - begin)); + + std::move(first, last, std::back_insert_iterator(rng)); + } + + m_cv.notify_all(); + } + + template + void enqueue_all_actions(Rng&& rng) const { + { + using std::begin; + using std::end; + + auto lck = std::unique_lock(m_mutex); + + auto first = begin(rng); + auto last = end(rng); + + m_actions.reserve(m_actions.size() + (end - begin)); + + std::copy(first, last, std::back_insert_iterator(rng)); + } + + m_cv.notify_all(); + } + + private: + friend struct WorkQueueWorker { + const WorkQueue* work_queue; + ThreadLocalData tld; + + template + WorkQueueWorker(const WorkQueue* work_queue, const F& initializer) + : work_queue(work_queue), tld(initializer()) + { } + + void operator()() { + for (;;) { + auto lck = std::unique_lock(work_queue->m_mutex); + ++work_queue->running_workers; + + const auto state = work_queue->m_state; + + if (state == State::Terminated) { + --work_queue->running_workers; + return; + } + + if (work_queue->m_actions.empty()) { + --work_queue->running_workers; + if (state == State::Running || work_queue->running_workers > 0) { + work_queue->m_cv.wait(lck); + continue; + } + + // state == State::Joining and we are the only worker + // no more work! + return; + } + + Action action = work_queue->m_actions.pop_back(); + lck.unlock(); + + detail::call_action(action, *work_queue, tld); + } + } + }; + + enum class State : std::uint16_t { + Running, + Joining, + Terminated, + }; + + mutable std::mutex m_mutex; + // these four are under m_mutex + mutable State m_state; + mutable std::uint16_t running_workers; + mutable std::vector m_actions; + mutable std::condition_variable condition_variable; + + std::vector m_threads; + }; +} -- cgit v1.2.3 From 43493b56df7c8f7aab02256ab7f65135d4dd1d4c Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Wed, 10 Jul 2019 15:18:44 -0700 Subject: delete the random number generator --- toolsrc/include/vcpkg/base/rng.h | 199 --------------------------------------- 1 file changed, 199 deletions(-) delete mode 100644 toolsrc/include/vcpkg/base/rng.h (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/rng.h b/toolsrc/include/vcpkg/base/rng.h deleted file mode 100644 index 4a0411f64..000000000 --- a/toolsrc/include/vcpkg/base/rng.h +++ /dev/null @@ -1,199 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace vcpkg::Rng { - - namespace detail { - template - constexpr std::size_t bitsize = sizeof(T) * CHAR_BITS; - - template - constexpr bool is_valid_shift(int k) { - return 0 <= k && k <= bitsize; - } - - // precondition: 0 <= k < bitsize - template - constexpr T ror(T x, int k) { - if (k == 0) { - return x; - } - return (x >> k) | (x << (bitsize - k)); - } - - // precondition: 0 <= k < bitsize - template - constexpr T rol(T x, int k) { - if (k == 0) { - return x; - } - return (x << k) | (x >> (bitsize - k)); - } - - // there _is_ a way to do this generally, but I don't know how to - template - struct XoshiroJumpTable; - - template <> - struct XoshiroJumpTable { - constexpr static std::uint64_t value[4] = { - 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c - }; - }; - } - - /* - NOTE(ubsan): taken from the xoshiro paper - initialized from random_device by default - actual code is copied from wikipedia, since I wrote that code - */ - struct splitmix { - splitmix() noexcept; - - constexpr splitmix(std::uint64_t seed) noexcept - : state(seed) {} - - constexpr std::uint64_t operator()() noexcept { - state += 0x9E3779B97F4A7C15; - - std::uint64_t result = state; - result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9; - result = (result ^ (result >> 27)) * 0x94D049BB133111EB; - - return result ^ (result >> 31); - } - - constexpr std::uint64_t max() const noexcept { - return std::numeric_limits::max(); - } - - constexpr std::uint64_t min() const noexcept { - return std::numeric_limits::min(); - } - - template - constexpr void fill(T* first, T* last) { - constexpr auto mask = - static_cast(std::numeric_limits::max()); - - const auto remaining = - (last - first) % (sizeof(std::uint64_t) / sizeof(T)); - - for (auto it = first; it != last - remaining;) { - const auto item = (*this)(); - for ( - int shift = 0; - shift < 64; - shift += detail::bitsize, ++it - ) { - *it = static_cast((item >> shift) & mask); - } - } - - if (remaining == 0) return; - - int shift = 0; - const auto item = (*this)(); - for (auto it = last - remaining; - it != last; - shift += detail::bitsize, ++it - ) { - *it = static_cast((item >> shift) & mask); - } - } - - private: - std::uint64_t state; - }; - - template - struct starstar_scrambler { - constexpr static UIntType scramble(UIntType n) noexcept { - return detail::rol(n * S, R) * T; - } - }; - - // Sebastian Vigna's xorshift-based xoshiro engine - // fast and really good - // uses the splitmix to initialize state - template - struct xoshiro_engine { - static_assert(detail::is_valid_shift(A)); - static_assert(detail::is_valid_shift(B)); - static_assert(std::is_unsigned_v); - - // splitmix will be initialized with random_device - xoshiro_engine() noexcept { - splitmix sm{}; - - sm.fill(&state[0], &state[4]); - } - - constexpr xoshiro_engine(std::uint64_t seed) noexcept : state() { - splitmix sm{seed}; - - sm.fill(&state[0], &state[4]); - } - - constexpr UIntType operator()() noexcept { - const UIntType result = Scrambler::scramble(state[0]); - - const UIntType t = state[1] << A; - - state[2] ^= state[0]; - state[3] ^= state[1]; - state[1] ^= state[2]; - state[0] ^= state[3]; - - state[2] ^= t; - state[3] ^= detail::rol(state[3], B); - - return result; - } - - constexpr UIntType max() const noexcept { - return std::numeric_limits::max(); - } - - constexpr std::uint64_t min() const noexcept { - return std::numeric_limits::min(); - } - - // quickly jump ahead 2^e steps - // takes 4 * bitsize rng next operations - template - constexpr void discard_e() noexcept { - using JT = detail::XoshiroJumpTable; - - UIntType s[4] = {}; - for (const auto& jump : JT::value) { - for (std::size_t i = 0; i < bitsize; ++i) { - if ((jump >> i) & 1) { - s[0] ^= state[0]; - s[1] ^= state[1]; - s[2] ^= state[2]; - s[3] ^= state[3]; - } - (*this)(); - } - } - - state[0] = s[0]; - state[1] = s[1]; - state[2] = s[2]; - state[3] = s[3]; - } - private: - // rotate left - UIntType state[4]; - }; - - using xoshiro256ss = xoshiro_engine< - std::uint64_t, - starstar_scrambler, - 17, - 45>; -} -- cgit v1.2.3 From 3b6d6b3465e0e79999e5995f0104a6e8c021088c Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Wed, 10 Jul 2019 15:42:13 -0700 Subject: actually get the code compiling --- toolsrc/include/vcpkg/base/work_queue.h | 42 ++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/work_queue.h b/toolsrc/include/vcpkg/base/work_queue.h index 4db167fa6..71e00a2ab 100644 --- a/toolsrc/include/vcpkg/base/work_queue.h +++ b/toolsrc/include/vcpkg/base/work_queue.h @@ -1,10 +1,15 @@ #pragma once +#include #include #include namespace vcpkg { + template + struct WorkQueue; + namespace detail { + // for SFINAE purposes, keep out of the class template auto call_action( Action& action, @@ -29,8 +34,8 @@ namespace vcpkg { template struct WorkQueue { template - explicit WorkQueue(const F& initializer) noexcept { - state = State::Joining; + explicit WorkQueue(const F& tld_init) noexcept { + m_state = State::Running; std::size_t num_threads = std::thread::hardware_concurrency(); if (num_threads == 0) { @@ -39,7 +44,7 @@ namespace vcpkg { m_threads.reserve(num_threads); for (std::size_t i = 0; i < num_threads; ++i) { - m_threads.emplace_back(this, initializer); + m_threads.push_back(std::thread(Worker{this, tld_init()})); } } @@ -93,10 +98,10 @@ namespace vcpkg { auto lck = std::unique_lock(m_mutex); - auto first = begin(rng); - auto last = end(rng); + const auto first = begin(rng); + const auto last = end(rng); - m_actions.reserve(m_actions.size() + (end - begin)); + m_actions.reserve(m_actions.size() + (last - first)); std::move(first, last, std::back_insert_iterator(rng)); } @@ -112,10 +117,10 @@ namespace vcpkg { auto lck = std::unique_lock(m_mutex); - auto first = begin(rng); - auto last = end(rng); + const auto first = begin(rng); + const auto last = end(rng); - m_actions.reserve(m_actions.size() + (end - begin)); + m_actions.reserve(m_actions.size() + (last - first)); std::copy(first, last, std::back_insert_iterator(rng)); } @@ -124,18 +129,15 @@ namespace vcpkg { } private: - friend struct WorkQueueWorker { + struct Worker { const WorkQueue* work_queue; ThreadLocalData tld; - template - WorkQueueWorker(const WorkQueue* work_queue, const F& initializer) - : work_queue(work_queue), tld(initializer()) - { } - void operator()() { + // unlocked when waiting, or when in the `call_action` block + // locked otherwise + auto lck = std::unique_lock(work_queue->m_mutex); for (;;) { - auto lck = std::unique_lock(work_queue->m_mutex); ++work_queue->running_workers; const auto state = work_queue->m_state; @@ -157,10 +159,12 @@ namespace vcpkg { return; } - Action action = work_queue->m_actions.pop_back(); - lck.unlock(); + Action action = std::move(work_queue->m_actions.back()); + work_queue->m_actions.pop_back(); + lck.unlock(); detail::call_action(action, *work_queue, tld); + lck.lock(); } } }; @@ -176,7 +180,7 @@ namespace vcpkg { mutable State m_state; mutable std::uint16_t running_workers; mutable std::vector m_actions; - mutable std::condition_variable condition_variable; + mutable std::condition_variable m_cv; std::vector m_threads; }; -- cgit v1.2.3 From 5b76f24f35976739991941d3b6289fb78fd93648 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Wed, 10 Jul 2019 16:28:56 -0700 Subject: make this compile on macos --- toolsrc/include/vcpkg/base/files.h | 39 ++++++++++++++++++++---------------- toolsrc/include/vcpkg/base/strings.h | 2 +- 2 files changed, 23 insertions(+), 18 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h index 178fae541..33f464779 100644 --- a/toolsrc/include/vcpkg/base/files.h +++ b/toolsrc/include/vcpkg/base/files.h @@ -25,23 +25,28 @@ namespace fs using stdfs::status; // we want to poison ADL with these niebloids - constexpr struct { - file_status operator()(const path& p, std::error_code& ec) const noexcept; - file_status operator()(const path& p) const noexcept; - } symlink_status{}; - - constexpr struct { - inline bool operator()(file_status s) const { - return stdfs::is_symlink(s); - } - - inline bool operator()(const path& p) const { - return stdfs::is_symlink(symlink_status(p)); - } - inline bool operator()(const path& p, std::error_code& ec) const { - return stdfs::is_symlink(symlink_status(p, ec)); - } - } is_symlink{}; + + namespace detail { + struct symlink_status_t { + file_status operator()(const path& p, std::error_code& ec) const noexcept; + file_status operator()(const path& p) const noexcept; + }; + struct is_symlink_t { + inline bool operator()(file_status s) const { + return stdfs::is_symlink(s); + } + + inline bool operator()(const path& p) const { + return stdfs::is_symlink(symlink_status(p)); + } + inline bool operator()(const path& p, std::error_code& ec) const { + return stdfs::is_symlink(symlink_status(p, ec)); + } + }; + } + + constexpr detail::symlink_status_t symlink_status{}; + constexpr detail::is_symlink_t is_symlink{}; inline bool is_regular_file(file_status s) { return stdfs::is_regular_file(s); } inline bool is_directory(file_status s) { return stdfs::is_directory(s); } diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h index 423ea2096..82145b826 100644 --- a/toolsrc/include/vcpkg/base/strings.h +++ b/toolsrc/include/vcpkg/base/strings.h @@ -190,7 +190,7 @@ namespace vcpkg::Strings // ignores padding, since one implicitly knows the length from the size of x template std::string b64url_encode(Integral x) { - static_assert(std::is_integral_v); + static_assert(std::is_integral::value, "b64url_encode must take an integer type"); auto value = static_cast>(x); // 64 values, plus the implicit \0 -- cgit v1.2.3 From bb579072077153fabfa74acec852bce222265357 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Wed, 10 Jul 2019 17:39:04 -0700 Subject: make it compile on macos under g++6 --- toolsrc/include/vcpkg/base/strings.h | 6 ++++-- toolsrc/include/vcpkg/base/work_queue.h | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h index 82145b826..9890bedbc 100644 --- a/toolsrc/include/vcpkg/base/strings.h +++ b/toolsrc/include/vcpkg/base/strings.h @@ -191,7 +191,8 @@ namespace vcpkg::Strings template std::string b64url_encode(Integral x) { static_assert(std::is_integral::value, "b64url_encode must take an integer type"); - auto value = static_cast>(x); + using Unsigned = std::make_unsigned_t; + auto value = static_cast(x); // 64 values, plus the implicit \0 constexpr static char map[0x41] = @@ -202,8 +203,8 @@ namespace vcpkg::Strings /*3*/ "wxyz0123456789-_" ; - constexpr static std::make_unsigned_t mask = 0x3F; constexpr static int shift = 5; + constexpr static auto mask = (static_cast(1) << shift) - 1; std::string result; // reserve ceiling(number of bits / 3) @@ -212,6 +213,7 @@ namespace vcpkg::Strings while (value != 0) { char mapped_value = map[value & mask]; result.push_back(mapped_value); + value >>= shift; } return result; diff --git a/toolsrc/include/vcpkg/base/work_queue.h b/toolsrc/include/vcpkg/base/work_queue.h index 71e00a2ab..8a3d27538 100644 --- a/toolsrc/include/vcpkg/base/work_queue.h +++ b/toolsrc/include/vcpkg/base/work_queue.h @@ -103,7 +103,7 @@ namespace vcpkg { m_actions.reserve(m_actions.size() + (last - first)); - std::move(first, last, std::back_insert_iterator(rng)); + std::move(first, last, std::back_inserter(rng)); } m_cv.notify_all(); @@ -122,7 +122,7 @@ namespace vcpkg { m_actions.reserve(m_actions.size() + (last - first)); - std::copy(first, last, std::back_insert_iterator(rng)); + std::copy(first, last, std::back_inserter(rng)); } m_cv.notify_all(); -- cgit v1.2.3 From 319023587558a9f8de9d7eabeb7441ef2e7ee277 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Thu, 11 Jul 2019 10:53:32 -0700 Subject: fix some comments from code reviewers --- toolsrc/include/vcpkg/base/strings.h | 10 ++++++---- toolsrc/include/vcpkg/base/work_queue.h | 15 +++++++-------- 2 files changed, 13 insertions(+), 12 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h index 9890bedbc..25cd302b0 100644 --- a/toolsrc/include/vcpkg/base/strings.h +++ b/toolsrc/include/vcpkg/base/strings.h @@ -208,11 +208,13 @@ namespace vcpkg::Strings std::string result; // reserve ceiling(number of bits / 3) - result.reserve((sizeof(value) * 8 + 2) / 3); + result.resize((sizeof(value) * 8 + 2) / 3, map[0]); - while (value != 0) { - char mapped_value = map[value & mask]; - result.push_back(mapped_value); + for (char& c: result) { + if (value == 0) { + break; + } + c = map[value & mask]; value >>= shift; } diff --git a/toolsrc/include/vcpkg/base/work_queue.h b/toolsrc/include/vcpkg/base/work_queue.h index 8a3d27538..b6f070cd8 100644 --- a/toolsrc/include/vcpkg/base/work_queue.h +++ b/toolsrc/include/vcpkg/base/work_queue.h @@ -11,7 +11,7 @@ namespace vcpkg { namespace detail { // for SFINAE purposes, keep out of the class template - auto call_action( + auto call_moved_action( Action& action, const WorkQueue& work_queue, ThreadLocalData& tld @@ -21,7 +21,7 @@ namespace vcpkg { } template - auto call_action( + auto call_moved_action( Action& action, const WorkQueue&, ThreadLocalData& tld @@ -134,21 +134,18 @@ namespace vcpkg { ThreadLocalData tld; void operator()() { - // unlocked when waiting, or when in the `call_action` block + // unlocked when waiting, or when in the `call_moved_action` + // block // locked otherwise auto lck = std::unique_lock(work_queue->m_mutex); for (;;) { - ++work_queue->running_workers; - const auto state = work_queue->m_state; if (state == State::Terminated) { - --work_queue->running_workers; return; } if (work_queue->m_actions.empty()) { - --work_queue->running_workers; if (state == State::Running || work_queue->running_workers > 0) { work_queue->m_cv.wait(lck); continue; @@ -162,9 +159,11 @@ namespace vcpkg { Action action = std::move(work_queue->m_actions.back()); work_queue->m_actions.pop_back(); + ++work_queue->running_workers; lck.unlock(); - detail::call_action(action, *work_queue, tld); + detail::call_moved_action(action, *work_queue, tld); lck.lock(); + --work_queue->running_workers; } } }; -- cgit v1.2.3 From 510b0c5cc0233311b6993b89cd5ce488218ed78d Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Thu, 11 Jul 2019 15:01:29 -0700 Subject: fix more comments --- toolsrc/include/vcpkg/base/files.h | 29 +++++---- toolsrc/include/vcpkg/base/strings.h | 37 +++--------- toolsrc/include/vcpkg/base/work_queue.h | 102 +++++++++++++++++++++++++------- 3 files changed, 106 insertions(+), 62 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h index 33f464779..6cad3d461 100644 --- a/toolsrc/include/vcpkg/base/files.h +++ b/toolsrc/include/vcpkg/base/files.h @@ -29,27 +29,29 @@ namespace fs namespace detail { struct symlink_status_t { file_status operator()(const path& p, std::error_code& ec) const noexcept; - file_status operator()(const path& p) const noexcept; + file_status operator()(const path& p, vcpkg::LineInfo li) const noexcept; }; struct is_symlink_t { inline bool operator()(file_status s) const { return stdfs::is_symlink(s); } - - inline bool operator()(const path& p) const { - return stdfs::is_symlink(symlink_status(p)); + }; + struct is_regular_file_t { + inline bool operator()(file_status s) const { + return stdfs::is_regular_file(s); } - inline bool operator()(const path& p, std::error_code& ec) const { - return stdfs::is_symlink(symlink_status(p, ec)); + }; + struct is_directory_t { + inline bool operator()(file_status s) const { + return stdfs::is_directory(s); } }; } constexpr detail::symlink_status_t symlink_status{}; constexpr detail::is_symlink_t is_symlink{}; - - inline bool is_regular_file(file_status s) { return stdfs::is_regular_file(s); } - inline bool is_directory(file_status s) { return stdfs::is_directory(s); } + constexpr detail::is_regular_file_t is_regular_file{}; + constexpr detail::is_directory_t is_directory{}; } /* @@ -57,9 +59,14 @@ namespace fs they might get the ADL version, which is broken. Therefore, put `symlink_status` in the global namespace, so that they get our symlink_status. + + We also want to poison the ADL on is_regular_file and is_directory, because + we don't want people calling these functions on paths */ using fs::symlink_status; using fs::is_symlink; +using fs::is_regular_file; +using fs::is_directory; namespace vcpkg::Files { @@ -85,7 +92,9 @@ namespace vcpkg::Files std::error_code& ec) = 0; bool remove(const fs::path& path, LineInfo linfo); virtual bool remove(const fs::path& path, std::error_code& ec) = 0; - virtual std::uintmax_t remove_all(const fs::path& path, std::error_code& ec) = 0; + + virtual std::uintmax_t remove_all(const fs::path& path, std::error_code& ec, fs::path& failure_point) = 0; + std::uintmax_t remove_all(const fs::path& path, LineInfo li); virtual bool exists(const fs::path& path) const = 0; virtual bool is_directory(const fs::path& path) const = 0; virtual bool is_regular_file(const fs::path& path) const = 0; diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h index 25cd302b0..625c0240f 100644 --- a/toolsrc/include/vcpkg/base/strings.h +++ b/toolsrc/include/vcpkg/base/strings.h @@ -188,36 +188,13 @@ namespace vcpkg::Strings // base 64 encoding with URL and filesafe alphabet (base64url) // based on IETF RFC 4648 // ignores padding, since one implicitly knows the length from the size of x - template - std::string b64url_encode(Integral x) { - static_assert(std::is_integral::value, "b64url_encode must take an integer type"); - using Unsigned = std::make_unsigned_t; - auto value = static_cast(x); - - // 64 values, plus the implicit \0 - constexpr static char map[0x41] = - /* 0123456789ABCDEF */ - /*0*/ "ABCDEFGHIJKLMNOP" - /*1*/ "QRSTUVWXYZabcdef" - /*2*/ "ghijklmnopqrstuv" - /*3*/ "wxyz0123456789-_" - ; - - constexpr static int shift = 5; - constexpr static auto mask = (static_cast(1) << shift) - 1; - - std::string result; - // reserve ceiling(number of bits / 3) - result.resize((sizeof(value) * 8 + 2) / 3, map[0]); - - for (char& c: result) { - if (value == 0) { - break; - } - c = map[value & mask]; - value >>= shift; - } + namespace detail { + + struct b64url_encode_t { + std::string operator()(std::uint64_t x) const noexcept; + }; - return result; } + + constexpr detail::b64url_encode_t b64url_encode{}; } diff --git a/toolsrc/include/vcpkg/base/work_queue.h b/toolsrc/include/vcpkg/base/work_queue.h index b6f070cd8..1836404ca 100644 --- a/toolsrc/include/vcpkg/base/work_queue.h +++ b/toolsrc/include/vcpkg/base/work_queue.h @@ -29,18 +29,19 @@ namespace vcpkg { { std::move(action)(tld); } + + struct immediately_run_t {}; } + constexpr detail::immediately_run_t immediately_run{}; + + template struct WorkQueue { template - explicit WorkQueue(const F& tld_init) noexcept { - m_state = State::Running; - - std::size_t num_threads = std::thread::hardware_concurrency(); - if (num_threads == 0) { - num_threads = 4; - } + WorkQueue(std::size_t num_threads, LineInfo li, const F& tld_init) noexcept { + m_line_info = li; + m_state = State::BeforeRun; m_threads.reserve(num_threads); for (std::size_t i = 0; i < num_threads; ++i) { @@ -48,22 +49,52 @@ namespace vcpkg { } } + template + WorkQueue( + detail::immediately_run_t, + std::size_t num_threads, + LineInfo li, + const F& tld_init + ) noexcept : WorkQueue(num_threads, li, tld_init) { + m_state = State::Running; + } + WorkQueue(WorkQueue const&) = delete; WorkQueue(WorkQueue&&) = delete; - ~WorkQueue() = default; + ~WorkQueue() { + auto lck = std::unique_lock(m_mutex); + if (m_state == State::Running) { + Checks::exit_with_message(m_line_info, "Failed to call join() on a WorkQueue that was destroyed"); + } + } + + // should only be called once; anything else is an error + void run(LineInfo li) { + // this should _not_ be locked before `run()` is called; however, we + // want to terminate if someone screws up, rather than cause UB + auto lck = std::unique_lock(m_mutex); + + if (m_state != State::BeforeRun) { + Checks::exit_with_message(li, "Attempted to run() twice"); + } + + m_state = State::Running; + } // runs all remaining tasks, and blocks on their finishing // if this is called in an existing task, _will block forever_ // DO NOT DO THAT // thread-unsafe - void join() { + void join(LineInfo li) { { auto lck = std::unique_lock(m_mutex); - if (m_state == State::Running) { - m_state = State::Joining; - } else if (m_state == State::Joining) { - Checks::exit_with_message(VCPKG_LINE_INFO, "Attempted to join more than once"); + if (is_joined(m_state)) { + Checks::exit_with_message(li, "Attempted to call join() more than once"); + } else if (m_state == State::Terminated) { + m_state = State::TerminatedJoined; + } else { + m_state = State::Joined; } } for (auto& thrd : m_threads) { @@ -77,7 +108,11 @@ namespace vcpkg { void terminate() const { { auto lck = std::unique_lock(m_mutex); - m_state = State::Terminated; + if (is_joined(m_state)) { + m_state = State::TerminatedJoined; + } else { + m_state = State::Terminated; + } } m_cv.notify_all(); } @@ -86,6 +121,8 @@ namespace vcpkg { { auto lck = std::unique_lock(m_mutex); m_actions.push_back(std::move(a)); + + if (m_state == State::BeforeRun) return; } m_cv.notify_one(); } @@ -104,6 +141,8 @@ namespace vcpkg { m_actions.reserve(m_actions.size() + (last - first)); std::move(first, last, std::back_inserter(rng)); + + if (m_state == State::BeforeRun) return; } m_cv.notify_all(); @@ -123,6 +162,8 @@ namespace vcpkg { m_actions.reserve(m_actions.size() + (last - first)); std::copy(first, last, std::back_inserter(rng)); + + if (m_state == State::BeforeRun) return; } m_cv.notify_all(); @@ -134,24 +175,30 @@ namespace vcpkg { ThreadLocalData tld; void operator()() { - // unlocked when waiting, or when in the `call_moved_action` - // block + // unlocked when waiting, or when in the action // locked otherwise auto lck = std::unique_lock(work_queue->m_mutex); + + work_queue->m_cv.wait(lck, [&] { + return work_queue->m_state != State::BeforeRun; + }); + for (;;) { const auto state = work_queue->m_state; - if (state == State::Terminated) { + if (is_terminated(state)) { return; } if (work_queue->m_actions.empty()) { if (state == State::Running || work_queue->running_workers > 0) { + --work_queue->running_workers; work_queue->m_cv.wait(lck); + ++work_queue->running_workers; continue; } - // state == State::Joining and we are the only worker + // the queue isn't running, and we are the only worker // no more work! return; } @@ -159,21 +206,31 @@ namespace vcpkg { Action action = std::move(work_queue->m_actions.back()); work_queue->m_actions.pop_back(); - ++work_queue->running_workers; lck.unlock(); detail::call_moved_action(action, *work_queue, tld); lck.lock(); - --work_queue->running_workers; } } }; - enum class State : std::uint16_t { + enum class State : std::int16_t { + // can only exist upon construction + BeforeRun = -1, + Running, - Joining, + Joined, Terminated, + TerminatedJoined, }; + static bool is_terminated(State st) { + return st == State::Terminated || st == State::TerminatedJoined; + } + + static bool is_joined(State st) { + return st != State::Joined || st == State::TerminatedJoined; + } + mutable std::mutex m_mutex; // these four are under m_mutex mutable State m_state; @@ -182,5 +239,6 @@ namespace vcpkg { mutable std::condition_variable m_cv; std::vector m_threads; + LineInfo m_line_info; }; } -- cgit v1.2.3 From a0fe40ea5842006c0da901a99ae07d7a25531175 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Thu, 11 Jul 2019 18:16:10 -0700 Subject: add tests! Also, fix all the bugs I found when I wrote the tests! --- toolsrc/include/vcpkg/base/files.h | 35 +++--- toolsrc/include/vcpkg/base/strings.h | 10 +- toolsrc/include/vcpkg/base/work_queue.h | 182 ++++++++++++++++++-------------- 3 files changed, 120 insertions(+), 107 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h index 6cad3d461..a5e04db25 100644 --- a/toolsrc/include/vcpkg/base/files.h +++ b/toolsrc/include/vcpkg/base/files.h @@ -12,8 +12,8 @@ namespace fs using stdfs::copy_options; using stdfs::file_status; using stdfs::file_type; - using stdfs::perms; using stdfs::path; + using stdfs::perms; using stdfs::u8path; /* @@ -26,25 +26,24 @@ namespace fs // we want to poison ADL with these niebloids - namespace detail { - struct symlink_status_t { + namespace detail + { + struct symlink_status_t + { file_status operator()(const path& p, std::error_code& ec) const noexcept; file_status operator()(const path& p, vcpkg::LineInfo li) const noexcept; }; - struct is_symlink_t { - inline bool operator()(file_status s) const { - return stdfs::is_symlink(s); - } + struct is_symlink_t + { + inline bool operator()(file_status s) const { return stdfs::is_symlink(s); } }; - struct is_regular_file_t { - inline bool operator()(file_status s) const { - return stdfs::is_regular_file(s); - } + struct is_regular_file_t + { + inline bool operator()(file_status s) const { return stdfs::is_regular_file(s); } }; - struct is_directory_t { - inline bool operator()(file_status s) const { - return stdfs::is_directory(s); - } + struct is_directory_t + { + inline bool operator()(file_status s) const { return stdfs::is_directory(s); } }; } @@ -63,10 +62,10 @@ namespace fs We also want to poison the ADL on is_regular_file and is_directory, because we don't want people calling these functions on paths */ -using fs::symlink_status; -using fs::is_symlink; -using fs::is_regular_file; using fs::is_directory; +using fs::is_regular_file; +using fs::is_symlink; +using fs::symlink_status; namespace vcpkg::Files { diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h index 625c0240f..a1906790f 100644 --- a/toolsrc/include/vcpkg/base/strings.h +++ b/toolsrc/include/vcpkg/base/strings.h @@ -188,13 +188,5 @@ namespace vcpkg::Strings // base 64 encoding with URL and filesafe alphabet (base64url) // based on IETF RFC 4648 // ignores padding, since one implicitly knows the length from the size of x - namespace detail { - - struct b64url_encode_t { - std::string operator()(std::uint64_t x) const noexcept; - }; - - } - - constexpr detail::b64url_encode_t b64url_encode{}; + std::string b64url_encode(std::uint64_t x) noexcept; } diff --git a/toolsrc/include/vcpkg/base/work_queue.h b/toolsrc/include/vcpkg/base/work_queue.h index 1836404ca..d6666770b 100644 --- a/toolsrc/include/vcpkg/base/work_queue.h +++ b/toolsrc/include/vcpkg/base/work_queue.h @@ -4,78 +4,67 @@ #include #include -namespace vcpkg { - template +namespace vcpkg +{ + template struct WorkQueue; - namespace detail { + namespace detail + { // for SFINAE purposes, keep out of the class - template - auto call_moved_action( - Action& action, - const WorkQueue& work_queue, - ThreadLocalData& tld - ) -> decltype(static_cast(std::move(action)(tld, work_queue))) + template + auto call_moved_action(Action& action, + const WorkQueue& work_queue, + ThreadLocalData& tld) -> decltype(static_cast(std::move(action)(tld, work_queue))) { std::move(action)(tld, work_queue); } - template - auto call_moved_action( - Action& action, - const WorkQueue&, - ThreadLocalData& tld - ) -> decltype(static_cast(std::move(action)(tld))) + template + auto call_moved_action(Action& action, const WorkQueue&, ThreadLocalData& tld) + -> decltype(static_cast(std::move(action)(tld))) { std::move(action)(tld); } - - struct immediately_run_t {}; } - constexpr detail::immediately_run_t immediately_run{}; - - - template - struct WorkQueue { - template - WorkQueue(std::size_t num_threads, LineInfo li, const F& tld_init) noexcept { + template + struct WorkQueue + { + template + WorkQueue(std::uint16_t num_threads, LineInfo li, const F& tld_init) noexcept + { m_line_info = li; - m_state = State::BeforeRun; + m_unjoined_workers = num_threads; m_threads.reserve(num_threads); - for (std::size_t i = 0; i < num_threads; ++i) { + for (std::size_t i = 0; i < num_threads; ++i) + { m_threads.push_back(std::thread(Worker{this, tld_init()})); } } - template - WorkQueue( - detail::immediately_run_t, - std::size_t num_threads, - LineInfo li, - const F& tld_init - ) noexcept : WorkQueue(num_threads, li, tld_init) { - m_state = State::Running; - } - WorkQueue(WorkQueue const&) = delete; WorkQueue(WorkQueue&&) = delete; - ~WorkQueue() { + ~WorkQueue() + { auto lck = std::unique_lock(m_mutex); - if (m_state == State::Running) { + if (!is_joined(m_state)) + { Checks::exit_with_message(m_line_info, "Failed to call join() on a WorkQueue that was destroyed"); } } // should only be called once; anything else is an error - void run(LineInfo li) { + void run(LineInfo li) + { // this should _not_ be locked before `run()` is called; however, we // want to terminate if someone screws up, rather than cause UB auto lck = std::unique_lock(m_mutex); - if (m_state != State::BeforeRun) { + if (m_state != State::BeforeRun) + { Checks::exit_with_message(li, "Attempted to run() twice"); } @@ -86,18 +75,40 @@ namespace vcpkg { // if this is called in an existing task, _will block forever_ // DO NOT DO THAT // thread-unsafe - void join(LineInfo li) { + void join(LineInfo li) + { { auto lck = std::unique_lock(m_mutex); - if (is_joined(m_state)) { + if (is_joined(m_state)) + { Checks::exit_with_message(li, "Attempted to call join() more than once"); - } else if (m_state == State::Terminated) { + } + else if (m_state == State::Terminated) + { m_state = State::TerminatedJoined; - } else { + } + else + { m_state = State::Joined; } } - for (auto& thrd : m_threads) { + + for (;;) + { + auto lck = std::unique_lock(m_mutex); + if (!m_unjoined_workers) + break; + + else if (!m_running_workers) + { + lck.unlock(); + m_cv.notify_all(); + } + } + + // all threads have returned -- now, it's time to join them + for (auto& thrd : m_threads) + { thrd.join(); } } @@ -105,19 +116,24 @@ namespace vcpkg { // useful in the case of errors // doesn't stop any existing running tasks // returns immediately, so that one can call this in a task - void terminate() const { + void terminate() const + { { auto lck = std::unique_lock(m_mutex); - if (is_joined(m_state)) { + if (is_joined(m_state)) + { m_state = State::TerminatedJoined; - } else { + } + else + { m_state = State::Terminated; } } m_cv.notify_all(); } - void enqueue_action(Action a) const { + void enqueue_action(Action a) const + { { auto lck = std::unique_lock(m_mutex); m_actions.push_back(std::move(a)); @@ -127,8 +143,9 @@ namespace vcpkg { m_cv.notify_one(); } - template - void enqueue_all_actions_by_move(Rng&& rng) const { + template + void enqueue_all_actions_by_move(Rng&& rng) const + { { using std::begin; using std::end; @@ -148,8 +165,9 @@ namespace vcpkg { m_cv.notify_all(); } - template - void enqueue_all_actions(Rng&& rng) const { + template + void enqueue_all_actions(Rng&& rng) const + { { using std::begin; using std::end; @@ -170,37 +188,41 @@ namespace vcpkg { } private: - struct Worker { + struct Worker + { const WorkQueue* work_queue; ThreadLocalData tld; - void operator()() { + void operator()() + { // unlocked when waiting, or when in the action // locked otherwise auto lck = std::unique_lock(work_queue->m_mutex); - work_queue->m_cv.wait(lck, [&] { - return work_queue->m_state != State::BeforeRun; - }); + work_queue->m_cv.wait(lck, [&] { return work_queue->m_state != State::BeforeRun; }); - for (;;) { + for (;;) + { const auto state = work_queue->m_state; - if (is_terminated(state)) { - return; + if (is_terminated(state)) + { + break; } - if (work_queue->m_actions.empty()) { - if (state == State::Running || work_queue->running_workers > 0) { - --work_queue->running_workers; + if (work_queue->m_actions.empty()) + { + if (state == State::Running || work_queue->m_running_workers > 1) + { + --work_queue->m_running_workers; work_queue->m_cv.wait(lck); - ++work_queue->running_workers; + ++work_queue->m_running_workers; continue; } // the queue isn't running, and we are the only worker // no more work! - return; + break; } Action action = std::move(work_queue->m_actions.back()); @@ -210,10 +232,13 @@ namespace vcpkg { detail::call_moved_action(action, *work_queue, tld); lck.lock(); } + + --work_queue->m_unjoined_workers; } }; - enum class State : std::int16_t { + enum class State : std::int16_t + { // can only exist upon construction BeforeRun = -1, @@ -223,22 +248,19 @@ namespace vcpkg { TerminatedJoined, }; - static bool is_terminated(State st) { - return st == State::Terminated || st == State::TerminatedJoined; - } + static bool is_terminated(State st) { return st == State::Terminated || st == State::TerminatedJoined; } - static bool is_joined(State st) { - return st != State::Joined || st == State::TerminatedJoined; - } + static bool is_joined(State st) { return st == State::Joined || st == State::TerminatedJoined; } - mutable std::mutex m_mutex; - // these four are under m_mutex - mutable State m_state; - mutable std::uint16_t running_workers; - mutable std::vector m_actions; - mutable std::condition_variable m_cv; + mutable std::mutex m_mutex{}; + // these are all under m_mutex + mutable State m_state = State::BeforeRun; + mutable std::uint16_t m_running_workers = 0; + mutable std::uint16_t m_unjoined_workers = 0; // num_threads + mutable std::vector m_actions{}; + mutable std::condition_variable m_cv{}; - std::vector m_threads; + std::vector m_threads{}; LineInfo m_line_info; }; } -- cgit v1.2.3 From 65d34c5e55ef30a6572dfb3b79d212196fbadc0d Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Mon, 15 Jul 2019 18:51:03 -0700 Subject: wheeeee more fixes --- toolsrc/include/vcpkg/base/strings.h | 8 +-- toolsrc/include/vcpkg/base/work_queue.h | 89 ++++++++++----------------------- 2 files changed, 31 insertions(+), 66 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h index a1906790f..aa4c4d690 100644 --- a/toolsrc/include/vcpkg/base/strings.h +++ b/toolsrc/include/vcpkg/base/strings.h @@ -185,8 +185,8 @@ namespace vcpkg::Strings bool contains(StringView haystack, StringView needle); - // base 64 encoding with URL and filesafe alphabet (base64url) - // based on IETF RFC 4648 - // ignores padding, since one implicitly knows the length from the size of x - std::string b64url_encode(std::uint64_t x) noexcept; + // base 32 encoding, since base64 encoding requires lowercase letters, + // which are not distinct from uppercase letters on macOS or Windows filesystems. + // follows RFC 4648 + std::string b32_encode(std::uint64_t x) noexcept; } diff --git a/toolsrc/include/vcpkg/base/work_queue.h b/toolsrc/include/vcpkg/base/work_queue.h index d6666770b..69ca387f3 100644 --- a/toolsrc/include/vcpkg/base/work_queue.h +++ b/toolsrc/include/vcpkg/base/work_queue.h @@ -36,7 +36,7 @@ namespace vcpkg { m_line_info = li; - m_unjoined_workers = num_threads; + set_unjoined_workers(num_threads); m_threads.reserve(num_threads); for (std::size_t i = 0; i < num_threads; ++i) { @@ -93,20 +93,16 @@ namespace vcpkg } } - for (;;) + while (unjoined_workers()) { - auto lck = std::unique_lock(m_mutex); - if (!m_unjoined_workers) - break; - - else if (!m_running_workers) + if (!running_workers()) { - lck.unlock(); - m_cv.notify_all(); - } + m_cv.notify_one(); + + } } - // all threads have returned -- now, it's time to join them + // wait for all threads to join for (auto& thrd : m_threads) { thrd.join(); @@ -143,50 +139,6 @@ namespace vcpkg m_cv.notify_one(); } - template - void enqueue_all_actions_by_move(Rng&& rng) const - { - { - using std::begin; - using std::end; - - auto lck = std::unique_lock(m_mutex); - - const auto first = begin(rng); - const auto last = end(rng); - - m_actions.reserve(m_actions.size() + (last - first)); - - std::move(first, last, std::back_inserter(rng)); - - if (m_state == State::BeforeRun) return; - } - - m_cv.notify_all(); - } - - template - void enqueue_all_actions(Rng&& rng) const - { - { - using std::begin; - using std::end; - - auto lck = std::unique_lock(m_mutex); - - const auto first = begin(rng); - const auto last = end(rng); - - m_actions.reserve(m_actions.size() + (last - first)); - - std::copy(first, last, std::back_inserter(rng)); - - if (m_state == State::BeforeRun) return; - } - - m_cv.notify_all(); - } - private: struct Worker { @@ -201,6 +153,7 @@ namespace vcpkg work_queue->m_cv.wait(lck, [&] { return work_queue->m_state != State::BeforeRun; }); + work_queue->increment_running_workers(); for (;;) { const auto state = work_queue->m_state; @@ -212,15 +165,15 @@ namespace vcpkg if (work_queue->m_actions.empty()) { - if (state == State::Running || work_queue->m_running_workers > 1) + if (state == State::Running || work_queue->running_workers() > 1) { - --work_queue->m_running_workers; + work_queue->decrement_running_workers(); work_queue->m_cv.wait(lck); - ++work_queue->m_running_workers; + work_queue->increment_running_workers(); continue; } - // the queue isn't running, and we are the only worker + // the queue is joining, and we are the only worker running // no more work! break; } @@ -229,11 +182,13 @@ namespace vcpkg work_queue->m_actions.pop_back(); lck.unlock(); + work_queue->m_cv.notify_one(); detail::call_moved_action(action, *work_queue, tld); lck.lock(); } - --work_queue->m_unjoined_workers; + work_queue->decrement_running_workers(); + work_queue->decrement_unjoined_workers(); } }; @@ -255,11 +210,21 @@ namespace vcpkg mutable std::mutex m_mutex{}; // these are all under m_mutex mutable State m_state = State::BeforeRun; - mutable std::uint16_t m_running_workers = 0; - mutable std::uint16_t m_unjoined_workers = 0; // num_threads mutable std::vector m_actions{}; mutable std::condition_variable m_cv{}; + mutable std::atomic m_workers; + // = unjoined_workers << 16 | running_workers + + void set_unjoined_workers(std::uint16_t threads) { m_workers = std::uint32_t(threads) << 16; } + void decrement_unjoined_workers() const { m_workers -= 1 << 16; } + + std::uint16_t unjoined_workers() const { return std::uint16_t(m_workers >> 16); } + + void increment_running_workers() const { ++m_workers; } + void decrement_running_workers() const { --m_workers; } + std::uint16_t running_workers() const { return std::uint16_t(m_workers); } + std::vector m_threads{}; LineInfo m_line_info; }; -- cgit v1.2.3 From 684989a1e48b6b7f0ac1c340a702236974762f05 Mon Sep 17 00:00:00 2001 From: "Curtis.Bezault" Date: Tue, 16 Jul 2019 14:02:13 -0700 Subject: use additional env param --- toolsrc/include/vcpkg/build.h | 24 ++++++++++++++++++++++++ toolsrc/include/vcpkg/sourceparagraph.h | 2 ++ 2 files changed, 26 insertions(+) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index 04cd7cf87..e26597376 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -117,6 +117,29 @@ namespace vcpkg::Build std::string create_error_message(const BuildResult build_result, const PackageSpec& spec); std::string create_user_troubleshooting_message(const PackageSpec& spec); + enum class VcpkgTripletVar + { + TARGET_ARCHITECTURE = 0, + CMAKE_SYSTEM_NAME, + CMAKE_SYSTEM_VERSION, + PLATFORM_TOOLSET, + VISUAL_STUDIO_PATH, + CHAINLOAD_TOOLCHAIN_FILE, + BUILD_TYPE, + ENV_PASSTHROUGH, + }; + + const std::unordered_map VCPKG_OPTIONS = { + {"VCPKG_TARGET_ARCHITECTURE", VcpkgTripletVar::TARGET_ARCHITECTURE}, + {"VCPKG_CMAKE_SYSTEM_NAME", VcpkgTripletVar::CMAKE_SYSTEM_NAME}, + {"VCPKG_CMAKE_SYSTEM_VERSION", VcpkgTripletVar::CMAKE_SYSTEM_VERSION}, + {"VCPKG_PLATFORM_TOOLSET", VcpkgTripletVar::PLATFORM_TOOLSET}, + {"VCPKG_VISUAL_STUDIO_PATH", VcpkgTripletVar::VISUAL_STUDIO_PATH}, + {"VCPKG_CHAINLOAD_TOOLCHAIN_FILE", VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE}, + {"VCPKG_BUILD_TYPE", VcpkgTripletVar::BUILD_TYPE}, + {"VCPKG_ENV_PASSTHROUGH", VcpkgTripletVar::ENV_PASSTHROUGH}, + }; + /// /// Settings from the triplet file which impact the build environment and post-build checks /// @@ -135,6 +158,7 @@ namespace vcpkg::Build Optional visual_studio_path; Optional external_toolchain_file; Optional build_type; + std::vector passthrough_env_vars; }; std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset); diff --git a/toolsrc/include/vcpkg/sourceparagraph.h b/toolsrc/include/vcpkg/sourceparagraph.h index 6232a3fd2..9fbd83475 100644 --- a/toolsrc/include/vcpkg/sourceparagraph.h +++ b/toolsrc/include/vcpkg/sourceparagraph.h @@ -23,6 +23,8 @@ namespace vcpkg std::vector filter_dependencies(const std::vector& deps, const Triplet& t); std::vector filter_dependencies_to_specs(const std::vector& deps, const Triplet& t); + std::vector filter_dependencies_to_features(const std::vector& deps, + const Triplet& t); // zlib[uwp] becomes Dependency{"zlib", "uwp"} std::vector expand_qualified_dependencies(const std::vector& depends); -- cgit v1.2.3 From 44dcc3d4f3d2bc56cc9f6d0371a141ad0145d537 Mon Sep 17 00:00:00 2001 From: "Curtis.Bezault" Date: Tue, 16 Jul 2019 15:34:13 -0700 Subject: First pass at port settings --- toolsrc/include/vcpkg/build.h | 48 ++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 23 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index e26597376..0d10d12a4 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -140,29 +140,6 @@ namespace vcpkg::Build {"VCPKG_ENV_PASSTHROUGH", VcpkgTripletVar::ENV_PASSTHROUGH}, }; - /// - /// Settings from the triplet file which impact the build environment and post-build checks - /// - struct PreBuildInfo - { - /// - /// Runs the triplet file in a "capture" mode to create a PreBuildInfo - /// - static PreBuildInfo from_triplet_file(const VcpkgPaths& paths, const Triplet& triplet); - - std::string triplet_abi_tag; - std::string target_architecture; - std::string cmake_system_name; - std::string cmake_system_version; - Optional platform_toolset; - Optional visual_studio_path; - Optional external_toolchain_file; - Optional build_type; - std::vector passthrough_env_vars; - }; - - std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset); - struct ExtendedBuildResult { ExtendedBuildResult(BuildResult code); @@ -200,6 +177,31 @@ namespace vcpkg::Build const BuildPackageConfig& config, const StatusParagraphs& status_db); + /// + /// Settings from the triplet file which impact the build environment and post-build checks + /// + struct PreBuildInfo + { + /// + /// Runs the triplet file in a "capture" mode to create a PreBuildInfo + /// + static PreBuildInfo from_triplet_file(const VcpkgPaths& paths, + const Triplet& triplet, + Optional port = nullopt); + + std::string triplet_abi_tag; + std::string target_architecture; + std::string cmake_system_name; + std::string cmake_system_version; + Optional platform_toolset; + Optional visual_studio_path; + Optional external_toolchain_file; + Optional build_type; + std::vector passthrough_env_vars; + }; + + std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset); + enum class BuildPolicy { EMPTY_PACKAGE, -- cgit v1.2.3 From 7d9d457f589d82d6675c511636808a0fbee7a4e5 Mon Sep 17 00:00:00 2001 From: "Curtis.Bezault" Date: Tue, 16 Jul 2019 16:09:30 -0700 Subject: revert unecessary reordering --- toolsrc/include/vcpkg/build.h | 94 +++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 47 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index 0d10d12a4..a0ad64ffd 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -117,28 +117,53 @@ namespace vcpkg::Build std::string create_error_message(const BuildResult build_result, const PackageSpec& spec); std::string create_user_troubleshooting_message(const PackageSpec& spec); - enum class VcpkgTripletVar - { - TARGET_ARCHITECTURE = 0, - CMAKE_SYSTEM_NAME, - CMAKE_SYSTEM_VERSION, - PLATFORM_TOOLSET, - VISUAL_STUDIO_PATH, - CHAINLOAD_TOOLCHAIN_FILE, - BUILD_TYPE, - ENV_PASSTHROUGH, - }; - - const std::unordered_map VCPKG_OPTIONS = { - {"VCPKG_TARGET_ARCHITECTURE", VcpkgTripletVar::TARGET_ARCHITECTURE}, - {"VCPKG_CMAKE_SYSTEM_NAME", VcpkgTripletVar::CMAKE_SYSTEM_NAME}, - {"VCPKG_CMAKE_SYSTEM_VERSION", VcpkgTripletVar::CMAKE_SYSTEM_VERSION}, - {"VCPKG_PLATFORM_TOOLSET", VcpkgTripletVar::PLATFORM_TOOLSET}, - {"VCPKG_VISUAL_STUDIO_PATH", VcpkgTripletVar::VISUAL_STUDIO_PATH}, - {"VCPKG_CHAINLOAD_TOOLCHAIN_FILE", VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE}, - {"VCPKG_BUILD_TYPE", VcpkgTripletVar::BUILD_TYPE}, - {"VCPKG_ENV_PASSTHROUGH", VcpkgTripletVar::ENV_PASSTHROUGH}, - }; + /// + /// Settings from the triplet file which impact the build environment and post-build checks + /// + struct PreBuildInfo + { + /// + /// Runs the triplet file in a "capture" mode to create a PreBuildInfo + /// + static PreBuildInfo from_triplet_file(const VcpkgPaths& paths, + const Triplet& triplet, + Optional port = nullopt); + + std::string triplet_abi_tag; + std::string target_architecture; + std::string cmake_system_name; + std::string cmake_system_version; + Optional platform_toolset; + Optional visual_studio_path; + Optional external_toolchain_file; + Optional build_type; + std::vector passthrough_env_vars; + }; + + std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset); + + enum class VcpkgTripletVar + { + TARGET_ARCHITECTURE = 0, + CMAKE_SYSTEM_NAME, + CMAKE_SYSTEM_VERSION, + PLATFORM_TOOLSET, + VISUAL_STUDIO_PATH, + CHAINLOAD_TOOLCHAIN_FILE, + BUILD_TYPE, + ENV_PASSTHROUGH, + }; + + const std::unordered_map VCPKG_OPTIONS = { + {"VCPKG_TARGET_ARCHITECTURE", VcpkgTripletVar::TARGET_ARCHITECTURE}, + {"VCPKG_CMAKE_SYSTEM_NAME", VcpkgTripletVar::CMAKE_SYSTEM_NAME}, + {"VCPKG_CMAKE_SYSTEM_VERSION", VcpkgTripletVar::CMAKE_SYSTEM_VERSION}, + {"VCPKG_PLATFORM_TOOLSET", VcpkgTripletVar::PLATFORM_TOOLSET}, + {"VCPKG_VISUAL_STUDIO_PATH", VcpkgTripletVar::VISUAL_STUDIO_PATH}, + {"VCPKG_CHAINLOAD_TOOLCHAIN_FILE", VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE}, + {"VCPKG_BUILD_TYPE", VcpkgTripletVar::BUILD_TYPE}, + {"VCPKG_ENV_PASSTHROUGH", VcpkgTripletVar::ENV_PASSTHROUGH}, + }; struct ExtendedBuildResult { @@ -177,31 +202,6 @@ namespace vcpkg::Build const BuildPackageConfig& config, const StatusParagraphs& status_db); - /// - /// Settings from the triplet file which impact the build environment and post-build checks - /// - struct PreBuildInfo - { - /// - /// Runs the triplet file in a "capture" mode to create a PreBuildInfo - /// - static PreBuildInfo from_triplet_file(const VcpkgPaths& paths, - const Triplet& triplet, - Optional port = nullopt); - - std::string triplet_abi_tag; - std::string target_architecture; - std::string cmake_system_name; - std::string cmake_system_version; - Optional platform_toolset; - Optional visual_studio_path; - Optional external_toolchain_file; - Optional build_type; - std::vector passthrough_env_vars; - }; - - std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset); - enum class BuildPolicy { EMPTY_PACKAGE, -- cgit v1.2.3 From d4ab567609495a5c239f537d7c1e200f7b8a19c0 Mon Sep 17 00:00:00 2001 From: "Curtis.Bezault" Date: Wed, 17 Jul 2019 10:10:36 -0700 Subject: first pass at abi additional files --- toolsrc/include/vcpkg/build.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index a0ad64ffd..85d6ebed9 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -138,6 +138,7 @@ namespace vcpkg::Build Optional external_toolchain_file; Optional build_type; std::vector passthrough_env_vars; + std::vector additional_files; }; std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset); @@ -152,6 +153,7 @@ namespace vcpkg::Build CHAINLOAD_TOOLCHAIN_FILE, BUILD_TYPE, ENV_PASSTHROUGH, + ABI_ADDITIONAL_FILES, }; const std::unordered_map VCPKG_OPTIONS = { @@ -163,6 +165,7 @@ namespace vcpkg::Build {"VCPKG_CHAINLOAD_TOOLCHAIN_FILE", VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE}, {"VCPKG_BUILD_TYPE", VcpkgTripletVar::BUILD_TYPE}, {"VCPKG_ENV_PASSTHROUGH", VcpkgTripletVar::ENV_PASSTHROUGH}, + {"VCPKG_ABI_ADDITIONAL_FILES", VcpkgTripletVar::ABI_ADDITIONAL_FILES}, }; struct ExtendedBuildResult -- cgit v1.2.3 From 58958eb0ea47c6c423fe78f2cd6fd1e31cbcb082 Mon Sep 17 00:00:00 2001 From: "Curtis.Bezault" Date: Wed, 17 Jul 2019 14:27:18 -0700 Subject: sourceparagraph changes --- toolsrc/include/vcpkg/sourceparagraph.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/sourceparagraph.h b/toolsrc/include/vcpkg/sourceparagraph.h index 9fbd83475..9a1c2c843 100644 --- a/toolsrc/include/vcpkg/sourceparagraph.h +++ b/toolsrc/include/vcpkg/sourceparagraph.h @@ -46,6 +46,12 @@ namespace vcpkg /// struct SourceParagraph { + enum TYPE : unsigned + { + PORT = 0, + SYS_TOOL, + }; + std::string name; std::string version; std::string description; @@ -54,6 +60,10 @@ namespace vcpkg std::vector supports; std::vector depends; std::vector default_features; + TYPE type; + + static TYPE type_from_string(const std::string& in); + static std::string string_from_type(const TYPE& in); }; /// -- cgit v1.2.3 From f18ffe996877a058da9e0208f92331c83517f6a0 Mon Sep 17 00:00:00 2001 From: "Curtis.Bezault" Date: Wed, 17 Jul 2019 16:04:05 -0700 Subject: Add type field --- toolsrc/include/vcpkg/binaryparagraph.h | 1 + 1 file changed, 1 insertion(+) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/binaryparagraph.h b/toolsrc/include/vcpkg/binaryparagraph.h index 3315151c6..fa49edaba 100644 --- a/toolsrc/include/vcpkg/binaryparagraph.h +++ b/toolsrc/include/vcpkg/binaryparagraph.h @@ -31,6 +31,7 @@ namespace vcpkg std::vector default_features; std::vector depends; std::string abi; + SourceParagraph::TYPE type; }; struct BinaryControlFile -- cgit v1.2.3 From bb3a9ddb6ec917f549e991f6bd344ce77054bb67 Mon Sep 17 00:00:00 2001 From: Curtis J Bezault Date: Thu, 18 Jul 2019 09:02:21 -0700 Subject: [vcpkg] Environment Variable Passthrough (#7290) * use additional env param * remove partials * remove change to linux triplet * Fix some issues that vicroms pointed out * whitespace change --- toolsrc/include/vcpkg/build.h | 24 ++++++++++++++++++++++++ toolsrc/include/vcpkg/sourceparagraph.h | 2 ++ 2 files changed, 26 insertions(+) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index 04cd7cf87..e26597376 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -117,6 +117,29 @@ namespace vcpkg::Build std::string create_error_message(const BuildResult build_result, const PackageSpec& spec); std::string create_user_troubleshooting_message(const PackageSpec& spec); + enum class VcpkgTripletVar + { + TARGET_ARCHITECTURE = 0, + CMAKE_SYSTEM_NAME, + CMAKE_SYSTEM_VERSION, + PLATFORM_TOOLSET, + VISUAL_STUDIO_PATH, + CHAINLOAD_TOOLCHAIN_FILE, + BUILD_TYPE, + ENV_PASSTHROUGH, + }; + + const std::unordered_map VCPKG_OPTIONS = { + {"VCPKG_TARGET_ARCHITECTURE", VcpkgTripletVar::TARGET_ARCHITECTURE}, + {"VCPKG_CMAKE_SYSTEM_NAME", VcpkgTripletVar::CMAKE_SYSTEM_NAME}, + {"VCPKG_CMAKE_SYSTEM_VERSION", VcpkgTripletVar::CMAKE_SYSTEM_VERSION}, + {"VCPKG_PLATFORM_TOOLSET", VcpkgTripletVar::PLATFORM_TOOLSET}, + {"VCPKG_VISUAL_STUDIO_PATH", VcpkgTripletVar::VISUAL_STUDIO_PATH}, + {"VCPKG_CHAINLOAD_TOOLCHAIN_FILE", VcpkgTripletVar::CHAINLOAD_TOOLCHAIN_FILE}, + {"VCPKG_BUILD_TYPE", VcpkgTripletVar::BUILD_TYPE}, + {"VCPKG_ENV_PASSTHROUGH", VcpkgTripletVar::ENV_PASSTHROUGH}, + }; + /// /// Settings from the triplet file which impact the build environment and post-build checks /// @@ -135,6 +158,7 @@ namespace vcpkg::Build Optional visual_studio_path; Optional external_toolchain_file; Optional build_type; + std::vector passthrough_env_vars; }; std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset); diff --git a/toolsrc/include/vcpkg/sourceparagraph.h b/toolsrc/include/vcpkg/sourceparagraph.h index 6232a3fd2..9fbd83475 100644 --- a/toolsrc/include/vcpkg/sourceparagraph.h +++ b/toolsrc/include/vcpkg/sourceparagraph.h @@ -23,6 +23,8 @@ namespace vcpkg std::vector filter_dependencies(const std::vector& deps, const Triplet& t); std::vector filter_dependencies_to_specs(const std::vector& deps, const Triplet& t); + std::vector filter_dependencies_to_features(const std::vector& deps, + const Triplet& t); // zlib[uwp] becomes Dependency{"zlib", "uwp"} std::vector expand_qualified_dependencies(const std::vector& depends); -- cgit v1.2.3 From d39bd70d533c64e929d4399cb9a1bdbfe0efaecd Mon Sep 17 00:00:00 2001 From: "Curtis.Bezault" Date: Thu, 18 Jul 2019 13:24:31 -0700 Subject: add needs_rebuild, should probably be moved to somewhere else --- toolsrc/include/vcpkg/statusparagraphs.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/statusparagraphs.h b/toolsrc/include/vcpkg/statusparagraphs.h index fa064de7e..3ebad67de 100644 --- a/toolsrc/include/vcpkg/statusparagraphs.h +++ b/toolsrc/include/vcpkg/statusparagraphs.h @@ -62,6 +62,8 @@ namespace vcpkg /// `true` if installed, `false` if not or not found. bool is_installed(const FeatureSpec& spec) const; + bool needs_rebuild(const PackageSpec& spec); + iterator insert(std::unique_ptr); friend void serialize(const StatusParagraphs& pgh, std::string& out_str); -- cgit v1.2.3 From fddebb75da034752fb267ba121497ba58157bb79 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Thu, 18 Jul 2019 16:40:52 -0700 Subject: clang-format all the things --- toolsrc/include/vcpkg/base/strings.h | 4 ++-- toolsrc/include/vcpkg/base/work_queue.h | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'toolsrc/include') diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h index aa4c4d690..d7de9b0b2 100644 --- a/toolsrc/include/vcpkg/base/strings.h +++ b/toolsrc/include/vcpkg/base/strings.h @@ -186,7 +186,7 @@ namespace vcpkg::Strings bool contains(StringView haystack, StringView needle); // base 32 encoding, since base64 encoding requires lowercase letters, - // which are not distinct from uppercase letters on macOS or Windows filesystems. - // follows RFC 4648 + // which are not distinct from uppercase letters on macOS or Windows filesystems. + // follows RFC 4648 std::string b32_encode(std::uint64_t x) noexcept; } diff --git a/toolsrc/include/vcpkg/base/work_queue.h b/toolsrc/include/vcpkg/base/work_queue.h index 69ca387f3..70142e110 100644 --- a/toolsrc/include/vcpkg/base/work_queue.h +++ b/toolsrc/include/vcpkg/base/work_queue.h @@ -98,8 +98,7 @@ namespace vcpkg if (!running_workers()) { m_cv.notify_one(); - - } + } } // wait for all threads to join -- cgit v1.2.3 From 825055378998ae6bc24e8cb0bce2e1fbf9a425da Mon Sep 17 00:00:00 2001 From: nicole mazzuca Date: Thu, 18 Jul 2019 19:07:00 -0700 Subject: Rewrite the tests! now they're cross-platform! (#7315) * begin exploratory rewriting of tests * continue working on tests * more test work! holy butts vcpkg-tests/plan.cpp was a bunch of work * finish writing new tests - [x] write catch2 tests - [ ] rewrite/at least delete the VS project files - [ ] document running tests * Fix tests to work on WSL, rewrite test vcxproj still need to test on macOS also, delete tests.pch.h * Condense add_test calls --- toolsrc/include/tests.pch.h | 19 - toolsrc/include/tests.utils.h | 76 - toolsrc/include/vcpkg-tests/catch.h | 16865 ++++++++++++++++++++++++++++++++++ toolsrc/include/vcpkg-tests/util.h | 33 + 4 files changed, 16898 insertions(+), 95 deletions(-) delete mode 100644 toolsrc/include/tests.pch.h delete mode 100644 toolsrc/include/tests.utils.h create mode 100644 toolsrc/include/vcpkg-tests/catch.h create mode 100644 toolsrc/include/vcpkg-tests/util.h (limited to 'toolsrc/include') diff --git a/toolsrc/include/tests.pch.h b/toolsrc/include/tests.pch.h deleted file mode 100644 index 5c00fca4a..000000000 --- a/toolsrc/include/tests.pch.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/toolsrc/include/tests.utils.h b/toolsrc/include/tests.utils.h deleted file mode 100644 index 3e8514e67..000000000 --- a/toolsrc/include/tests.utils.h +++ /dev/null @@ -1,76 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include - -#include - -namespace Microsoft::VisualStudio::CppUnitTestFramework -{ - template<> - inline std::wstring ToString(const vcpkg::Dependencies::InstallPlanType& t) - { - switch (t) - { - case vcpkg::Dependencies::InstallPlanType::ALREADY_INSTALLED: return L"ALREADY_INSTALLED"; - case vcpkg::Dependencies::InstallPlanType::BUILD_AND_INSTALL: return L"BUILD_AND_INSTALL"; - case vcpkg::Dependencies::InstallPlanType::EXCLUDED: return L"EXCLUDED"; - case vcpkg::Dependencies::InstallPlanType::UNKNOWN: return L"UNKNOWN"; - default: return ToString(static_cast(t)); - } - } - - template<> - inline std::wstring ToString(const vcpkg::Dependencies::RequestType& t) - { - switch (t) - { - case vcpkg::Dependencies::RequestType::AUTO_SELECTED: return L"AUTO_SELECTED"; - case vcpkg::Dependencies::RequestType::USER_REQUESTED: return L"USER_REQUESTED"; - case vcpkg::Dependencies::RequestType::UNKNOWN: return L"UNKNOWN"; - default: return ToString(static_cast(t)); - } - } - - template<> - inline std::wstring ToString(const vcpkg::PackageSpecParseResult& t) - { - return ToString(static_cast(t)); - } - - template<> - inline std::wstring ToString(const vcpkg::PackageSpec& t) - { - return ToString(t.to_string()); - } -} - -std::unique_ptr make_status_pgh(const char* name, - const char* depends = "", - const char* default_features = "", - const char* triplet = "x86-windows"); -std::unique_ptr make_status_feature_pgh(const char* name, - const char* feature, - const char* depends = "", - const char* triplet = "x86-windows"); - -template -T&& unwrap(vcpkg::ExpectedT&& p) -{ - Assert::IsTrue(p.has_value()); - return std::move(*p.get()); -} - -template -T&& unwrap(vcpkg::Optional&& opt) -{ - Assert::IsTrue(opt.has_value()); - return std::move(*opt.get()); -} - -vcpkg::PackageSpec unsafe_pspec(std::string name, vcpkg::Triplet t = vcpkg::Triplet::X86_WINDOWS); diff --git a/toolsrc/include/vcpkg-tests/catch.h b/toolsrc/include/vcpkg-tests/catch.h new file mode 100644 index 000000000..303f664ff --- /dev/null +++ b/toolsrc/include/vcpkg-tests/catch.h @@ -0,0 +1,16865 @@ +/* + * Catch v2.9.1 + * Generated: 2019-06-17 11:59:24.363643 + * ---------------------------------------------------------- + * This file has been merged from multiple headers. Please don't edit it directly + * Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved. + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ +#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED +// start catch.hpp + + +#define CATCH_VERSION_MAJOR 2 +#define CATCH_VERSION_MINOR 9 +#define CATCH_VERSION_PATCH 1 + +#ifdef __clang__ +# pragma clang system_header +#elif defined __GNUC__ +# pragma GCC system_header +#endif + +// start catch_suppress_warnings.h + +#ifdef __clang__ +# ifdef __ICC // icpc defines the __clang__ macro +# pragma warning(push) +# pragma warning(disable: 161 1682) +# else // __ICC +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wpadded" +# pragma clang diagnostic ignored "-Wswitch-enum" +# pragma clang diagnostic ignored "-Wcovered-switch-default" +# endif +#elif defined __GNUC__ + // Because REQUIREs trigger GCC's -Wparentheses, and because still + // supported version of g++ have only buggy support for _Pragmas, + // Wparentheses have to be suppressed globally. +# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details + +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-variable" +# pragma GCC diagnostic ignored "-Wpadded" +#endif +// end catch_suppress_warnings.h +#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) +# define CATCH_IMPL +# define CATCH_CONFIG_ALL_PARTS +#endif + +// In the impl file, we want to have access to all parts of the headers +// Can also be used to sanely support PCHs +#if defined(CATCH_CONFIG_ALL_PARTS) +# define CATCH_CONFIG_EXTERNAL_INTERFACES +# if defined(CATCH_CONFIG_DISABLE_MATCHERS) +# undef CATCH_CONFIG_DISABLE_MATCHERS +# endif +# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) +# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER +# endif +#endif + +#if !defined(CATCH_CONFIG_IMPL_ONLY) +// start catch_platform.h + +#ifdef __APPLE__ +# include +# if TARGET_OS_OSX == 1 +# define CATCH_PLATFORM_MAC +# elif TARGET_OS_IPHONE == 1 +# define CATCH_PLATFORM_IPHONE +# endif + +#elif defined(linux) || defined(__linux) || defined(__linux__) +# define CATCH_PLATFORM_LINUX + +#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) +# define CATCH_PLATFORM_WINDOWS +#endif + +// end catch_platform.h + +#ifdef CATCH_IMPL +# ifndef CLARA_CONFIG_MAIN +# define CLARA_CONFIG_MAIN_NOT_DEFINED +# define CLARA_CONFIG_MAIN +# endif +#endif + +// start catch_user_interfaces.h + +namespace Catch { + unsigned int rngSeed(); +} + +// end catch_user_interfaces.h +// start catch_tag_alias_autoregistrar.h + +// start catch_common.h + +// start catch_compiler_capabilities.h + +// Detect a number of compiler features - by compiler +// The following features are defined: +// +// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? +// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? +// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? +// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? +// **************** +// Note to maintainers: if new toggles are added please document them +// in configuration.md, too +// **************** + +// In general each macro has a _NO_ form +// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. +// Many features, at point of detection, define an _INTERNAL_ macro, so they +// can be combined, en-mass, with the _NO_ forms later. + +#ifdef __cplusplus + +# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +# define CATCH_CPP14_OR_GREATER +# endif + +# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# define CATCH_CPP17_OR_GREATER +# endif + +#endif + +#if defined(CATCH_CPP17_OR_GREATER) +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#ifdef __clang__ + +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic push" ) \ + _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ + _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS \ + _Pragma( "clang diagnostic pop" ) + +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic push" ) \ + _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) +# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ + _Pragma( "clang diagnostic pop" ) + +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic push" ) \ + _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) +# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS \ + _Pragma( "clang diagnostic pop" ) + +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic push" ) \ + _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) +# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS \ + _Pragma( "clang diagnostic pop" ) + +#endif // __clang__ + +//////////////////////////////////////////////////////////////////////////////// +// Assume that non-Windows platforms support posix signals by default +#if !defined(CATCH_PLATFORM_WINDOWS) + #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS +#endif + +//////////////////////////////////////////////////////////////////////////////// +// We know some environments not to support full POSIX signals +#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) + #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +#endif + +#ifdef __OS400__ +# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS +# define CATCH_CONFIG_COLOUR_NONE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Android somehow still does not support std::to_string +#if defined(__ANDROID__) +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Not all Windows environments support SEH properly +#if defined(__MINGW32__) +# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH +#endif + +//////////////////////////////////////////////////////////////////////////////// +// PS4 +#if defined(__ORBIS__) +# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Cygwin +#ifdef __CYGWIN__ + +// Required for some versions of Cygwin to declare gettimeofday +// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin +# define _BSD_SOURCE +// some versions of cygwin (most) do not support std::to_string. Use the libstd check. +// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 +# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ + && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) + +# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING + +# endif +#endif // __CYGWIN__ + +//////////////////////////////////////////////////////////////////////////////// +// Visual C++ +#ifdef _MSC_VER + +# if _MSC_VER >= 1900 // Visual Studio 2015 or newer +# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +# endif + +// Universal Windows platform does not support SEH +// Or console colours (or console at all...) +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) +# define CATCH_CONFIG_COLOUR_NONE +# else +# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH +# endif + +// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ +// _MSVC_TRADITIONAL == 0 means new conformant preprocessor +// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor +# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) +# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +# endif +#endif // _MSC_VER + +#if defined(_REENTRANT) || defined(_MSC_VER) +// Enable async processing, as -pthread is specified or no additional linking is required +# define CATCH_INTERNAL_CONFIG_USE_ASYNC +#endif // _MSC_VER + +//////////////////////////////////////////////////////////////////////////////// +// Check if we are compiled with -fno-exceptions or equivalent +#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) +# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED +#endif + +//////////////////////////////////////////////////////////////////////////////// +// DJGPP +#ifdef __DJGPP__ +# define CATCH_INTERNAL_CONFIG_NO_WCHAR +#endif // __DJGPP__ + +//////////////////////////////////////////////////////////////////////////////// +// Embarcadero C++Build +#if defined(__BORLANDC__) + #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN +#endif + +//////////////////////////////////////////////////////////////////////////////// + +// Use of __COUNTER__ is suppressed during code analysis in +// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly +// handled by it. +// Otherwise all supported compilers support COUNTER macro, +// but user still might want to turn it off +#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) + #define CATCH_INTERNAL_CONFIG_COUNTER +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Check if string_view is available and usable +// The check is split apart to work around v140 (VS2015) preprocessor issue... +#if defined(__has_include) +#if __has_include() && defined(CATCH_CPP17_OR_GREATER) +# define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW +#endif +#endif + +//////////////////////////////////////////////////////////////////////////////// +// Check if optional is available and usable +#if defined(__has_include) +# if __has_include() && defined(CATCH_CPP17_OR_GREATER) +# define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL +# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // __has_include + +//////////////////////////////////////////////////////////////////////////////// +// Check if variant is available and usable +#if defined(__has_include) +# if __has_include() && defined(CATCH_CPP17_OR_GREATER) +# if defined(__clang__) && (__clang_major__ < 8) + // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 + // fix should be in clang 8, workaround in libstdc++ 8.2 +# include +# if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) +# define CATCH_CONFIG_NO_CPP17_VARIANT +# else +# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT +# endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) +# else +# define CATCH_INTERNAL_CONFIG_CPP17_VARIANT +# endif // defined(__clang__) && (__clang_major__ < 8) +# endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) +#endif // __has_include + +#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) +# define CATCH_CONFIG_COUNTER +#endif +#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) +# define CATCH_CONFIG_WINDOWS_SEH +#endif +// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. +#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) +# define CATCH_CONFIG_POSIX_SIGNALS +#endif +// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. +#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) +# define CATCH_CONFIG_WCHAR +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) +# define CATCH_CONFIG_CPP11_TO_STRING +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) +# define CATCH_CONFIG_CPP17_OPTIONAL +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) +# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) +# define CATCH_CONFIG_CPP17_STRING_VIEW +#endif + +#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) +# define CATCH_CONFIG_CPP17_VARIANT +#endif + +#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) +# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE +#endif + +#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) +# define CATCH_CONFIG_NEW_CAPTURE +#endif + +#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +# define CATCH_CONFIG_DISABLE_EXCEPTIONS +#endif + +#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) +# define CATCH_CONFIG_POLYFILL_ISNAN +#endif + +#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) +# define CATCH_CONFIG_USE_ASYNC +#endif + +#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_UNUSED_WARNINGS +#endif +#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) +# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS +# define CATCH_INTERNAL_UNSUPPRESS_ZERO_VARIADIC_WARNINGS +#endif + +#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) +#define CATCH_TRY if ((true)) +#define CATCH_CATCH_ALL if ((false)) +#define CATCH_CATCH_ANON(type) if ((false)) +#else +#define CATCH_TRY try +#define CATCH_CATCH_ALL catch (...) +#define CATCH_CATCH_ANON(type) catch (type) +#endif + +#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) +#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#endif + +// end catch_compiler_capabilities.h +#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line +#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) +#ifdef CATCH_CONFIG_COUNTER +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) +#else +# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) +#endif + +#include +#include +#include + +// We need a dummy global operator<< so we can bring it into Catch namespace later +struct Catch_global_namespace_dummy {}; +std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); + +namespace Catch { + + struct CaseSensitive { enum Choice { + Yes, + No + }; }; + + class NonCopyable { + NonCopyable( NonCopyable const& ) = delete; + NonCopyable( NonCopyable && ) = delete; + NonCopyable& operator = ( NonCopyable const& ) = delete; + NonCopyable& operator = ( NonCopyable && ) = delete; + + protected: + NonCopyable(); + virtual ~NonCopyable(); + }; + + struct SourceLineInfo { + + SourceLineInfo() = delete; + SourceLineInfo( char const* _file, std::size_t _line ) noexcept + : file( _file ), + line( _line ) + {} + + SourceLineInfo( SourceLineInfo const& other ) = default; + SourceLineInfo& operator = ( SourceLineInfo const& ) = default; + SourceLineInfo( SourceLineInfo&& ) noexcept = default; + SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; + + bool empty() const noexcept; + bool operator == ( SourceLineInfo const& other ) const noexcept; + bool operator < ( SourceLineInfo const& other ) const noexcept; + + char const* file; + std::size_t line; + }; + + std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); + + // Bring in operator<< from global namespace into Catch namespace + // This is necessary because the overload of operator<< above makes + // lookup stop at namespace Catch + using ::operator<<; + + // Use this in variadic streaming macros to allow + // >> +StreamEndStop + // as well as + // >> stuff +StreamEndStop + struct StreamEndStop { + std::string operator+() const; + }; + template + T const& operator + ( T const& value, StreamEndStop ) { + return value; + } +} + +#define CATCH_INTERNAL_LINEINFO \ + ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) + +// end catch_common.h +namespace Catch { + + struct RegistrarForTagAliases { + RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); + }; + +} // end namespace Catch + +#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ + CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ + namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ + CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS + +// end catch_tag_alias_autoregistrar.h +// start catch_test_registry.h + +// start catch_interfaces_testcase.h + +#include + +namespace Catch { + + class TestSpec; + + struct ITestInvoker { + virtual void invoke () const = 0; + virtual ~ITestInvoker(); + }; + + class TestCase; + struct IConfig; + + struct ITestCaseRegistry { + virtual ~ITestCaseRegistry(); + virtual std::vector const& getAllTests() const = 0; + virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; + }; + + bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); + std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); + std::vector const& getAllTestCasesSorted( IConfig const& config ); + +} + +// end catch_interfaces_testcase.h +// start catch_stringref.h + +#include +#include +#include + +namespace Catch { + + /// A non-owning string class (similar to the forthcoming std::string_view) + /// Note that, because a StringRef may be a substring of another string, + /// it may not be null terminated. c_str() must return a null terminated + /// string, however, and so the StringRef will internally take ownership + /// (taking a copy), if necessary. In theory this ownership is not externally + /// visible - but it does mean (substring) StringRefs should not be shared between + /// threads. + class StringRef { + public: + using size_type = std::size_t; + + private: + friend struct StringRefTestAccess; + + char const* m_start; + size_type m_size; + + char* m_data = nullptr; + + void takeOwnership(); + + static constexpr char const* const s_empty = ""; + + public: // construction/ assignment + StringRef() noexcept + : StringRef( s_empty, 0 ) + {} + + StringRef( StringRef const& other ) noexcept + : m_start( other.m_start ), + m_size( other.m_size ) + {} + + StringRef( StringRef&& other ) noexcept + : m_start( other.m_start ), + m_size( other.m_size ), + m_data( other.m_data ) + { + other.m_data = nullptr; + } + + StringRef( char const* rawChars ) noexcept; + + StringRef( char const* rawChars, size_type size ) noexcept + : m_start( rawChars ), + m_size( size ) + {} + + StringRef( std::string const& stdString ) noexcept + : m_start( stdString.c_str() ), + m_size( stdString.size() ) + {} + + ~StringRef() noexcept { + delete[] m_data; + } + + auto operator = ( StringRef const &other ) noexcept -> StringRef& { + delete[] m_data; + m_data = nullptr; + m_start = other.m_start; + m_size = other.m_size; + return *this; + } + + operator std::string() const; + + void swap( StringRef& other ) noexcept; + + public: // operators + auto operator == ( StringRef const& other ) const noexcept -> bool; + auto operator != ( StringRef const& other ) const noexcept -> bool; + + auto operator[] ( size_type index ) const noexcept -> char; + + public: // named queries + auto empty() const noexcept -> bool { + return m_size == 0; + } + auto size() const noexcept -> size_type { + return m_size; + } + + auto numberOfCharacters() const noexcept -> size_type; + auto c_str() const -> char const*; + + public: // substrings and searches + auto substr( size_type start, size_type size ) const noexcept -> StringRef; + + // Returns the current start pointer. + // Note that the pointer can change when if the StringRef is a substring + auto currentData() const noexcept -> char const*; + + private: // ownership queries - may not be consistent between calls + auto isOwned() const noexcept -> bool; + auto isSubstring() const noexcept -> bool; + }; + + auto operator + ( StringRef const& lhs, StringRef const& rhs ) -> std::string; + auto operator + ( StringRef const& lhs, char const* rhs ) -> std::string; + auto operator + ( char const* lhs, StringRef const& rhs ) -> std::string; + + auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; + auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; + + inline auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { + return StringRef( rawChars, size ); + } + +} // namespace Catch + +inline auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { + return Catch::StringRef( rawChars, size ); +} + +// end catch_stringref.h +// start catch_type_traits.hpp + + +#include + +namespace Catch{ + +#ifdef CATCH_CPP17_OR_GREATER + template + inline constexpr auto is_unique = std::true_type{}; + + template + inline constexpr auto is_unique = std::bool_constant< + (!std::is_same_v && ...) && is_unique + >{}; +#else + +template +struct is_unique : std::true_type{}; + +template +struct is_unique : std::integral_constant +::value + && is_unique::value + && is_unique::value +>{}; + +#endif +} + +// end catch_type_traits.hpp +// start catch_preprocessor.hpp + + +#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ +#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) +#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) + +#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ +// MSVC needs more evaluations +#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) +#else +#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) +#endif + +#define CATCH_REC_END(...) +#define CATCH_REC_OUT + +#define CATCH_EMPTY() +#define CATCH_DEFER(id) id CATCH_EMPTY() + +#define CATCH_REC_GET_END2() 0, CATCH_REC_END +#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 +#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 +#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT +#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) +#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) + +#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) + +#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) +#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) + +// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, +// and passes userdata as the first parameter to each invocation, +// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) +#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) + +#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) +#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ +#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ +#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) +#else +// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF +#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) +#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ +#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) +#endif + +#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ +#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) + +#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) + +#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) +#else +#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) +#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) +#endif + +#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ + CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) + +#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) +#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) +#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) +#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) +#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) +#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) +#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _4, _5, _6) +#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) +#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) +#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) +#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) + +#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N + +#define INTERNAL_CATCH_TYPE_GEN\ + template struct TypeList {};\ + template\ + constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ + \ + template class L1, typename...E1, template class L2, typename...E2> \ + constexpr auto append(L1, L2) noexcept -> L1 { return {}; }\ + template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ + constexpr auto append(L1, L2, Rest...) noexcept -> decltype(append(L1{}, Rest{}...)) { return {}; }\ + template< template class L1, typename...E1, typename...Rest>\ + constexpr auto append(L1, TypeList, Rest...) noexcept -> L1 { return {}; }\ + \ + template< template class Container, template class List, typename...elems>\ + constexpr auto rewrap(List) noexcept -> TypeList> { return {}; }\ + template< template class Container, template class List, class...Elems, typename...Elements>\ + constexpr auto rewrap(List,Elements...) noexcept -> decltype(append(TypeList>{}, rewrap(Elements{}...))) { return {}; }\ + \ + template