diff options
| author | Wimok Nupphiboon <wimok.mok@gmail.com> | 2018-03-24 11:53:55 +0700 |
|---|---|---|
| committer | Wimok Nupphiboon <wimok.mok@gmail.com> | 2018-03-24 11:53:55 +0700 |
| commit | 663be4bbffd435cf5e5fc62a0774c784c10ddc68 (patch) | |
| tree | d214f24405fa75d4dad9dfb938a04846d2ca6102 /toolsrc | |
| parent | 1e380dde21317e73d1859dad1c64c06eb88cc502 (diff) | |
| parent | aa57df6d6ed6d17000522492b66fc93d3f32ab86 (diff) | |
| download | vcpkg-663be4bbffd435cf5e5fc62a0774c784c10ddc68.tar.gz vcpkg-663be4bbffd435cf5e5fc62a0774c784c10ddc68.zip | |
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'toolsrc')
36 files changed, 1036 insertions, 353 deletions
diff --git a/toolsrc/CMakeLists.txt b/toolsrc/CMakeLists.txt index 2a340bb8f..da0f41631 100644 --- a/toolsrc/CMakeLists.txt +++ b/toolsrc/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.3)
-project(vcpkg CXX)
+project(vcpkg C CXX)
if(CMAKE_COMPILER_IS_GNUXX OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
set(GCC 1)
@@ -19,10 +19,14 @@ file(GLOB_RECURSE VCPKGLIB_SOURCES src/vcpkg/*.cpp) add_executable(vcpkg src/vcpkg.cpp ${VCPKGLIB_SOURCES})
target_compile_definitions(vcpkg PRIVATE -DDISABLE_METRICS=0)
-target_include_directories(vcpkg PUBLIC include)
+target_include_directories(vcpkg PRIVATE include)
if(GCC)
- target_link_libraries(vcpkg PUBLIC stdc++fs)
+ target_link_libraries(vcpkg PRIVATE stdc++fs)
elseif(CLANG)
- target_link_libraries(vcpkg PUBLIC c++experimental)
+ target_link_libraries(vcpkg PRIVATE c++experimental)
endif()
+
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package(Threads REQUIRED)
+target_link_libraries(vcpkg PRIVATE Threads::Threads)
diff --git a/toolsrc/VERSION.txt b/toolsrc/VERSION.txt index 157d21b7b..1305e8f43 100644 --- a/toolsrc/VERSION.txt +++ b/toolsrc/VERSION.txt @@ -1 +1 @@ -"0.0.105"
\ No newline at end of file +"0.0.106"
\ No newline at end of file diff --git a/toolsrc/include/pch.h b/toolsrc/include/pch.h index 683bef171..9c9deeb3f 100644 --- a/toolsrc/include/pch.h +++ b/toolsrc/include/pch.h @@ -46,7 +46,11 @@ #include <set> #include <stdexcept> #include <string> +#if defined(_WIN32) #include <sys/timeb.h> +#else +#include <sys/time.h> +#endif #include <sys/types.h> #include <system_error> #include <thread> diff --git a/toolsrc/include/vcpkg/base/cache.h b/toolsrc/include/vcpkg/base/cache.h new file mode 100644 index 000000000..dfc7565b8 --- /dev/null +++ b/toolsrc/include/vcpkg/base/cache.h @@ -0,0 +1,21 @@ +#pragma once
+
+#include <map>
+
+namespace vcpkg
+{
+ template<class Key, class Value>
+ struct Cache
+ {
+ template<class F>
+ Value const& get_lazy(const Key& k, const F& f) const
+ {
+ auto it = m_cache.find(k);
+ if (it != m_cache.end()) return it->second;
+ return m_cache.emplace(k, f()).first->second;
+ }
+
+ private:
+ mutable std::map<Key, Value> m_cache;
+ };
+}
diff --git a/toolsrc/include/vcpkg/base/files.h b/toolsrc/include/vcpkg/base/files.h index 09393b9ee..ac1f192ae 100644 --- a/toolsrc/include/vcpkg/base/files.h +++ b/toolsrc/include/vcpkg/base/files.h @@ -36,6 +36,7 @@ namespace vcpkg::Files virtual void write_lines(const fs::path& file_path, const std::vector<std::string>& lines) = 0; virtual void write_contents(const fs::path& file_path, const std::string& data, std::error_code& ec) = 0; virtual void rename(const fs::path& oldpath, const fs::path& newpath) = 0; + virtual void rename(const fs::path& oldpath, const fs::path& newpath, std::error_code& ec) = 0; virtual bool remove(const fs::path& path) = 0; 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; diff --git a/toolsrc/include/vcpkg/base/strings.h b/toolsrc/include/vcpkg/base/strings.h index 6ef840fb3..c32e81ac2 100644 --- a/toolsrc/include/vcpkg/base/strings.h +++ b/toolsrc/include/vcpkg/base/strings.h @@ -46,7 +46,9 @@ namespace vcpkg::Strings bool case_insensitive_ascii_equals(const CStringView left, const CStringView right); - std::string ascii_to_lowercase(const std::string& input); + std::string ascii_to_lowercase(std::string s); + + std::string ascii_to_uppercase(std::string s); bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern); diff --git a/toolsrc/include/vcpkg/base/system.h b/toolsrc/include/vcpkg/base/system.h index 31034f6b4..0d089276f 100644 --- a/toolsrc/include/vcpkg/base/system.h +++ b/toolsrc/include/vcpkg/base/system.h @@ -1,5 +1,7 @@ #pragma once +#include <unordered_map> + #include <vcpkg/base/files.h> #include <vcpkg/base/optional.h> #include <vcpkg/base/strings.h> @@ -38,7 +40,8 @@ namespace vcpkg::System std::string output; }; - int cmd_execute_clean(const CStringView cmd_line); + int cmd_execute_clean(const CStringView cmd_line, + const std::unordered_map<std::string, std::string>& extra_env = {}); int cmd_execute(const CStringView cmd_line); @@ -107,9 +110,9 @@ namespace vcpkg::System std::vector<CPUArchitecture> get_supported_host_architectures(); - const fs::path& get_program_files_32_bit(); + const Optional<fs::path>& get_program_files_32_bit(); - const fs::path& get_program_files_platform_bitness(); + const Optional<fs::path>& get_program_files_platform_bitness(); } namespace vcpkg::Debug diff --git a/toolsrc/include/vcpkg/base/util.h b/toolsrc/include/vcpkg/base/util.h index 5e07b240a..c73345719 100644 --- a/toolsrc/include/vcpkg/base/util.h +++ b/toolsrc/include/vcpkg/base/util.h @@ -6,8 +6,6 @@ #include <utility> #include <vector> -#include <vcpkg/base/optional.h> - namespace vcpkg::Util { template<class Container> @@ -24,10 +22,10 @@ namespace vcpkg::Util namespace Sets { - template<class Container> - bool contains(const Container& container, const ElementT<Container>& item) + template<class Container, class Key> + bool contains(const Container& container, const Key& item) { - return container.find(item) != container.cend(); + return container.find(item) != container.end(); } } @@ -158,6 +156,8 @@ namespace vcpkg::Util MoveOnlyBase& operator=(const MoveOnlyBase&) = delete; MoveOnlyBase& operator=(MoveOnlyBase&&) = default; + + ~MoveOnlyBase() = default; }; struct ResourceBase @@ -168,6 +168,8 @@ namespace vcpkg::Util ResourceBase& operator=(const ResourceBase&) = delete; ResourceBase& operator=(ResourceBase&&) = delete; + + ~ResourceBase() = default; }; template<class T> @@ -214,4 +216,10 @@ namespace vcpkg::Util return e == E::YES; } } + + template<class T> + void unused(T&& param) + { + (void)param; + } } diff --git a/toolsrc/include/vcpkg/build.h b/toolsrc/include/vcpkg/build.h index ea81c4dbe..1c22d39d8 100644 --- a/toolsrc/include/vcpkg/build.h +++ b/toolsrc/include/vcpkg/build.h @@ -204,4 +204,26 @@ namespace vcpkg::Build }; BuildInfo read_build_info(const Files::Filesystem& fs, const fs::path& filepath); + + struct AbiEntry + { + std::string key; + std::string value; + + bool operator<(const AbiEntry& other) const + { + return key < other.key || (key == other.key && value < other.value); + } + }; + + struct AbiTagAndFile + { + std::string tag; + fs::path tag_file; + }; + + Optional<AbiTagAndFile> compute_abi_tag(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const PreBuildInfo& pre_build_info, + Span<const AbiEntry> dependency_abis); } diff --git a/toolsrc/include/vcpkg/commands.h b/toolsrc/include/vcpkg/commands.h index 4027e12f4..7369b8206 100644 --- a/toolsrc/include/vcpkg/commands.h +++ b/toolsrc/include/vcpkg/commands.h @@ -7,6 +7,8 @@ #include <vcpkg/vcpkgpaths.h> #include <array> +#include <map> +#include <vector> namespace vcpkg::Commands { @@ -23,7 +25,17 @@ namespace vcpkg::Commands namespace CI { + struct UnknownCIPortsResults + { + std::vector<PackageSpec> unknown; + std::map<PackageSpec, Build::BuildResult> known; + }; + extern const CommandStructure COMMAND_STRUCTURE; + UnknownCIPortsResults find_unknown_ports_for_ci(const VcpkgPaths& paths, + const std::set<std::string>& exclusions, + const Dependencies::PortFileProvider& provider, + const std::vector<FeatureSpec>& fspecs); void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet); } @@ -120,7 +132,7 @@ namespace vcpkg::Commands namespace Hash { void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths); - std::string get_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type); + std::string get_file_hash(const VcpkgPaths& paths, fs::path const& path, std::string const& hash_type); } template<class T> diff --git a/toolsrc/include/vcpkg/dependencies.h b/toolsrc/include/vcpkg/dependencies.h index fadb8cc7e..33af6c4f5 100644 --- a/toolsrc/include/vcpkg/dependencies.h +++ b/toolsrc/include/vcpkg/dependencies.h @@ -45,7 +45,8 @@ namespace vcpkg::Dependencies InstallPlanAction(const PackageSpec& spec, const SourceControlFile& scf, const std::set<std::string>& features, - const RequestType& request_type); + const RequestType& request_type, + std::vector<PackageSpec>&& dependencies); std::string displayname() const; @@ -58,6 +59,8 @@ namespace vcpkg::Dependencies RequestType request_type; Build::BuildPackageOptions build_options; std::set<std::string> feature_list; + + std::vector<PackageSpec> computed_dependencies; }; enum class RemovePlanType diff --git a/toolsrc/include/vcpkg/install.h b/toolsrc/include/vcpkg/install.h index 2e92764dc..b7acbf15f 100644 --- a/toolsrc/include/vcpkg/install.h +++ b/toolsrc/include/vcpkg/install.h @@ -37,6 +37,7 @@ namespace vcpkg::Install std::string total_elapsed_time; void print() const; + static std::string xunit_result(const PackageSpec& spec, Chrono::ElapsedTime time, Build::BuildResult code); std::string xunit_results() const; }; diff --git a/toolsrc/include/vcpkg/paragraphs.h b/toolsrc/include/vcpkg/paragraphs.h index e2c7f2d99..fa0265b75 100644 --- a/toolsrc/include/vcpkg/paragraphs.h +++ b/toolsrc/include/vcpkg/paragraphs.h @@ -20,7 +20,7 @@ namespace vcpkg::Paragraphs Parse::ParseExpected<SourceControlFile> try_load_port(const Files::Filesystem& fs, const fs::path& control_path); - Expected<BinaryControlFile> try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec); + Expected<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec); struct LoadResults { diff --git a/toolsrc/include/vcpkg/sourceparagraph.h b/toolsrc/include/vcpkg/sourceparagraph.h index ea8e27a94..ae5812ea7 100644 --- a/toolsrc/include/vcpkg/sourceparagraph.h +++ b/toolsrc/include/vcpkg/sourceparagraph.h @@ -63,6 +63,8 @@ namespace vcpkg std::unique_ptr<SourceParagraph> core_paragraph; std::vector<std::unique_ptr<FeatureParagraph>> feature_paragraphs; + + Optional<const FeatureParagraph&> find_feature(const std::string& featurename) const; }; void print_error_message(Span<const std::unique_ptr<Parse::ParseControlErrorInfo>> error_info_list); diff --git a/toolsrc/include/vcpkg/vcpkgpaths.h b/toolsrc/include/vcpkg/vcpkgpaths.h index 84e8110ec..71f1bbba9 100644 --- a/toolsrc/include/vcpkg/vcpkgpaths.h +++ b/toolsrc/include/vcpkg/vcpkgpaths.h @@ -33,7 +33,7 @@ namespace vcpkg struct VcpkgPaths { - static Expected<VcpkgPaths> create(const fs::path& vcpkg_root_dir); + static Expected<VcpkgPaths> 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; @@ -90,5 +90,7 @@ namespace vcpkg Lazy<fs::path> ifw_repogen_exe; Lazy<std::vector<Toolset>> toolsets; Lazy<std::vector<Toolset>> toolsets_vs2013; + + fs::path default_vs_path; }; } diff --git a/toolsrc/src/tests.plan.cpp b/toolsrc/src/tests.plan.cpp index 08d3c1dab..a99f1abb9 100644 --- a/toolsrc/src/tests.plan.cpp +++ b/toolsrc/src/tests.plan.cpp @@ -593,6 +593,87 @@ namespace UnitTest1 features_check(&install_plan[0], "a", {"core"}, Triplet::X64_WINDOWS); } + TEST_METHOD(install_plan_action_dependencies) + { + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_c = spec_map.emplace("c"); + auto spec_b = spec_map.emplace("b", "c"); + spec_map.emplace("a", "b"); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 3); + features_check(&install_plan[0], "c", {"core"}, Triplet::X64_WINDOWS); + + features_check(&install_plan[1], "b", {"core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[1].install_action.get()->computed_dependencies == + std::vector<PackageSpec>{spec_c}); + + features_check(&install_plan[2], "a", {"core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[2].install_action.get()->computed_dependencies == + std::vector<PackageSpec>{spec_b}); + } + + TEST_METHOD(install_plan_action_dependencies_2) + { + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + auto spec_c = spec_map.emplace("c"); + auto spec_b = spec_map.emplace("b", "c"); + spec_map.emplace("a", "c, b"); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 3); + features_check(&install_plan[0], "c", {"core"}, Triplet::X64_WINDOWS); + + features_check(&install_plan[1], "b", {"core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[1].install_action.get()->computed_dependencies == + std::vector<PackageSpec>{spec_c}); + + features_check(&install_plan[2], "a", {"core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[2].install_action.get()->computed_dependencies == + std::vector<PackageSpec>{spec_b, spec_c}); + } + + TEST_METHOD(install_plan_action_dependencies_3) + { + std::vector<std::unique_ptr<StatusParagraph>> status_paragraphs; + + // Add a port "a" which depends on the core of "b", which was already + // installed explicitly + PackageSpecMap spec_map(Triplet::X64_WINDOWS); + spec_map.emplace("a", "", {{"0", ""}, {"1", "a[0]"}}, {"1"}); + + // Install "a" (without explicit feature specification) + auto install_specs = FullPackageSpec::from_string("a", Triplet::X64_WINDOWS); + auto install_plan = Dependencies::create_feature_install_plan( + spec_map.map, + FullPackageSpec::to_feature_specs({install_specs.value_or_exit(VCPKG_LINE_INFO)}), + StatusParagraphs(std::move(status_paragraphs))); + + Assert::IsTrue(install_plan.size() == 1); + features_check(&install_plan[0], "a", {"1", "0", "core"}, Triplet::X64_WINDOWS); + Assert::IsTrue(install_plan[0].install_action.get()->computed_dependencies == std::vector<PackageSpec>{}); + } + TEST_METHOD(upgrade_with_default_features_1) { std::vector<std::unique_ptr<StatusParagraph>> pghs; @@ -619,7 +700,6 @@ namespace UnitTest1 Assert::IsTrue(plan[0].remove_action.has_value()); Assert::AreEqual("a", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); features_check(&plan[1], "a", {"core", "0"}, Triplet::X86_WINDOWS); } @@ -651,11 +731,9 @@ namespace UnitTest1 Assert::IsTrue(plan[0].remove_action.has_value()); Assert::AreEqual("b", plan[1].spec().name().c_str()); - Assert::IsTrue(plan[1].install_action.has_value()); features_check(&plan[1], "b", {"b0", "core"}, Triplet::X64_WINDOWS); Assert::AreEqual("a", plan[2].spec().name().c_str()); - Assert::IsTrue(plan[2].install_action.has_value()); features_check(&plan[2], "a", {"core"}, Triplet::X64_WINDOWS); } @@ -996,6 +1074,34 @@ namespace UnitTest1 features_check(&plan[1], "a", {"core", "a1"}); } + + TEST_METHOD(basic_upgrade_scheme_with_self_features) + { + std::vector<std::unique_ptr<StatusParagraph>> pghs; + pghs.push_back(make_status_pgh("a")); + pghs.push_back(make_status_feature_pgh("a", "a1", "")); + pghs.push_back(make_status_feature_pgh("a", "a2", "a[a1]")); + StatusParagraphs status_db(std::move(pghs)); + + PackageSpecMap spec_map(Triplet::X86_WINDOWS); + auto spec_a = spec_map.emplace("a", "", {{"a1", ""}, {"a2", "a[a1]"}}); + + Dependencies::MapPortFileProvider provider(spec_map.map); + Dependencies::PackageGraph graph(provider, status_db); + + graph.upgrade(spec_a); + + auto plan = graph.serialize(); + + Assert::AreEqual(size_t(2), plan.size()); + + Assert::AreEqual("a", plan[0].spec().name().c_str()); + Assert::IsTrue(plan[0].remove_action.has_value()); + + Assert::AreEqual("a", plan[1].spec().name().c_str()); + Assert::IsTrue(plan[1].install_action.has_value()); + Assert::IsTrue(plan[1].install_action.get()->feature_list == std::set<std::string>{"core", "a1", "a2"}); + } }; class ExportPlanTests : public TestClass<ExportPlanTests> @@ -1069,7 +1175,7 @@ namespace UnitTest1 Assert::IsTrue(plan[0].plan_type == Dependencies::ExportPlanType::NOT_BUILT); } - TEST_METHOD(basic_upgrade_scheme_with_features) + TEST_METHOD(basic_export_scheme_with_features) { std::vector<std::unique_ptr<StatusParagraph>> pghs; pghs.push_back(make_status_pgh("b")); diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index ef68e6f72..a65045aa8 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -94,7 +94,9 @@ static void inner(const VcpkgCmdArguments& args) Checks::check_exit(VCPKG_LINE_INFO, !vcpkg_root_dir.empty(), "Error: Could not detect vcpkg-root."); - const Expected<VcpkgPaths> expected_paths = VcpkgPaths::create(vcpkg_root_dir); + auto default_vs_path = System::get_environment_variable("VCPKG_DEFAULT_VS_PATH").value_or(""); + + const Expected<VcpkgPaths> expected_paths = VcpkgPaths::create(vcpkg_root_dir, default_vs_path); Checks::check_exit(VCPKG_LINE_INFO, !expected_paths.error(), "Error: Invalid vcpkg root directory %s: %s", @@ -155,7 +157,15 @@ static void inner(const VcpkgCmdArguments& args) } else { +#if defined(_WIN32) default_triplet = Triplet::X86_WINDOWS; +#elif defined(__APPLE__) + default_triplet = Triplet::from_canonical_name("x64-osx"); +#elif defined(__FreeBSD__) + default_triplet = Triplet::from_canonical_name("x64-freebsd"); +#else + default_triplet = Triplet::from_canonical_name("x64-linux"); +#endif } } diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp index b59104a59..4e61666b7 100644 --- a/toolsrc/src/vcpkg/base/files.cpp +++ b/toolsrc/src/vcpkg/base/files.cpp @@ -108,6 +108,10 @@ namespace vcpkg::Files output.close(); } + virtual void rename(const fs::path& oldpath, const fs::path& newpath, std::error_code& ec) override + { + fs::stdfs::rename(oldpath, newpath, ec); + } virtual void rename(const fs::path& oldpath, const fs::path& newpath) override { fs::stdfs::rename(oldpath, newpath); diff --git a/toolsrc/src/vcpkg/base/strings.cpp b/toolsrc/src/vcpkg/base/strings.cpp index d912734e3..5fedf3e1f 100644 --- a/toolsrc/src/vcpkg/base/strings.cpp +++ b/toolsrc/src/vcpkg/base/strings.cpp @@ -7,10 +7,11 @@ namespace vcpkg::Strings::details { // To disambiguate between two overloads - static const auto isspace = [](const char c) { return std::isspace(c); }; + static bool IS_SPACE(const char c) { return std::isspace(c) != 0; }; // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower() static char tolower_char(const char c) { return static_cast<char>(std::tolower(c)); } + static char toupper_char(const char c) { return static_cast<char>(std::toupper(c)); } #if defined(_WIN32) static _locale_t& c_locale() @@ -108,11 +109,16 @@ namespace vcpkg::Strings #endif } - std::string ascii_to_lowercase(const std::string& input) + std::string ascii_to_lowercase(std::string s) { - std::string output(input); - std::transform(output.begin(), output.end(), output.begin(), &details::tolower_char); - return output; + std::transform(s.begin(), s.end(), s.begin(), &details::tolower_char); + return s; + } + + std::string ascii_to_uppercase(std::string s) + { + std::transform(s.begin(), s.end(), s.begin(), &details::toupper_char); + return s; } bool case_insensitive_ascii_starts_with(const std::string& s, const std::string& pattern) @@ -137,8 +143,8 @@ namespace vcpkg::Strings std::string trim(std::string&& s) { - s.erase(std::find_if_not(s.rbegin(), s.rend(), details::isspace).base(), s.end()); - s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), details::isspace)); + s.erase(std::find_if_not(s.rbegin(), s.rend(), details::IS_SPACE).base(), s.end()); + s.erase(s.begin(), std::find_if_not(s.begin(), s.end(), details::IS_SPACE)); return std::move(s); } diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp index e55db9461..171dd2bbf 100644 --- a/toolsrc/src/vcpkg/base/system.cpp +++ b/toolsrc/src/vcpkg/base/system.cpp @@ -8,7 +8,11 @@ #include <time.h> #if defined(__APPLE__) -# include <mach-o/dyld.h> +#include <mach-o/dyld.h> +#endif + +#if defined(__FreeBSD__) +#include <sys/sysctl.h> #endif #pragma comment(lib, "Advapi32") @@ -35,14 +39,22 @@ namespace vcpkg::System const int bytes = GetModuleFileNameW(nullptr, buf, _MAX_PATH); if (bytes == 0) std::abort(); return fs::path(buf, buf + bytes); -#elif __APPLE__ +#elif defined(__APPLE__) uint32_t size = 1024 * 32; char buf[size] = {}; bool result = _NSGetExecutablePath(buf, &size); Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path."); - std::unique_ptr<char> canonicalPath (realpath(buf, NULL)); + std::unique_ptr<char> canonicalPath(realpath(buf, NULL)); Checks::check_exit(VCPKG_LINE_INFO, result != -1, "Could not determine current executable path."); return fs::path(std::string(canonicalPath.get())); +#elif defined(__FreeBSD__) + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; + char exePath[2048]; + size_t len = sizeof(exePath); + auto rcode = sysctl(mib, 4, exePath, &len, NULL, 0); + Checks::check_exit(VCPKG_LINE_INFO, rcode == 0, "Could not determine current executable path."); + Checks::check_exit(VCPKG_LINE_INFO, len > 0, "Could not determine current executable path."); + return fs::path(exePath, exePath + len - 1); #else /* LINUX */ std::array<char, 1024 * 4> buf; auto written = readlink("/proc/self/exe", buf.data(), buf.size()); @@ -141,12 +153,12 @@ namespace vcpkg::System R"(powershell -NoProfile -ExecutionPolicy Bypass -Command "& {& '%s' %s}")", script_path.u8string(), args); } - int cmd_execute_clean(const CStringView cmd_line) + int cmd_execute_clean(const CStringView cmd_line, const std::unordered_map<std::string, std::string>& extra_env) { #if defined(_WIN32) static const std::string SYSTEM_ROOT = get_environment_variable("SystemRoot").value_or_exit(VCPKG_LINE_INFO); static const std::string SYSTEM_32 = SYSTEM_ROOT + R"(\system32)"; - static const std::string NEW_PATH = Strings::format( + std::string NEW_PATH = Strings::format( R"(Path=%s;%s;%s\Wbem;%s\WindowsPowerShell\v1.0\)", SYSTEM_32, SYSTEM_ROOT, SYSTEM_32, SYSTEM_32); std::vector<std::wstring> env_wstrings = { @@ -212,11 +224,22 @@ namespace vcpkg::System env_cstr.push_back(L'\0'); } + if (extra_env.find("PATH") != extra_env.end()) + NEW_PATH += Strings::format(";%s", extra_env.find("PATH")->second); env_cstr.append(Strings::to_utf16(NEW_PATH)); env_cstr.push_back(L'\0'); env_cstr.append(L"VSLANG=1033"); env_cstr.push_back(L'\0'); + for (auto item : extra_env) + { + if (item.first == "PATH") continue; + env_cstr.append(Strings::to_utf16(item.first)); + env_cstr.push_back(L'='); + env_cstr.append(Strings::to_utf16(item.second)); + env_cstr.push_back(L'\0'); + } + STARTUPINFOW startup_info; memset(&startup_info, 0, sizeof(STARTUPINFOW)); startup_info.cb = sizeof(STARTUPINFOW); @@ -262,14 +285,14 @@ namespace vcpkg::System fflush(nullptr); // Basically we are wrapping it in quotes - const std::string& actual_cmd_line = Strings::format(R"###("%s")###", cmd_line); #if defined(_WIN32) + const std::string& actual_cmd_line = Strings::format(R"###("%s")###", cmd_line); Debug::println("_wsystem(%s)", actual_cmd_line); const int exit_code = _wsystem(Strings::to_utf16(actual_cmd_line).c_str()); Debug::println("_wsystem() returned %d", exit_code); #else - Debug::println("_system(%s)", actual_cmd_line); - const int exit_code = system(actual_cmd_line.c_str()); + Debug::println("_system(%s)", cmd_line); + const int exit_code = system(cmd_line.c_str()); Debug::println("_system() returned %d", exit_code); #endif return exit_code; @@ -291,6 +314,8 @@ namespace vcpkg::System // Flush stdout before launching external process fflush(stdout); + auto timer = Chrono::ElapsedTimer::create_started(); + #if defined(_WIN32) const auto actual_cmd_line = Strings::format(R"###("%s 2>&1")###", cmd_line); @@ -312,8 +337,10 @@ namespace vcpkg::System } const auto ec = _pclose(pipe); - Debug::println("_pclose() returned %d", ec); remove_byte_order_marks(&output); + + Debug::println("_pclose() returned %d after %8d us", ec, (int)timer.microseconds()); + return {ec, Strings::to_utf8(output)}; #else const auto actual_cmd_line = Strings::format(R"###(%s 2>&1)###", cmd_line); @@ -336,7 +363,9 @@ namespace vcpkg::System } const auto ec = pclose(pipe); - Debug::println("pclose() returned %d", ec); + + Debug::println("_pclose() returned %d after %8d us", ec, (int)timer.microseconds()); + return {ec, output}; #endif } @@ -502,32 +531,41 @@ namespace vcpkg::System } #endif - static const fs::path& get_program_files() + static const Optional<fs::path>& get_program_files() { - static const fs::path PATH = System::get_environment_variable("PROGRAMFILES").value_or_exit(VCPKG_LINE_INFO); + static const auto PATH = []() -> Optional<fs::path> { + auto value = System::get_environment_variable("PROGRAMFILES"); + if (auto v = value.get()) + { + return *v; + } + + return nullopt; + }(); + return PATH; } - const fs::path& get_program_files_32_bit() + const Optional<fs::path>& get_program_files_32_bit() { - static const fs::path PATH = []() -> fs::path { + static const auto PATH = []() -> Optional<fs::path> { auto value = System::get_environment_variable("ProgramFiles(x86)"); if (auto v = value.get()) { - return std::move(*v); + return *v; } return get_program_files(); }(); return PATH; } - const fs::path& get_program_files_platform_bitness() + const Optional<fs::path>& get_program_files_platform_bitness() { - static const fs::path PATH = []() -> fs::path { + static const auto PATH = []() -> Optional<fs::path> { auto value = System::get_environment_variable("ProgramW6432"); if (auto v = value.get()) { - return std::move(*v); + return *v; } return get_program_files(); }(); diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp index 5870bd187..953e77460 100644 --- a/toolsrc/src/vcpkg/build.cpp +++ b/toolsrc/src/vcpkg/build.cpp @@ -209,6 +209,7 @@ namespace vcpkg::Build std::string make_build_env_cmd(const PreBuildInfo& pre_build_info, const Toolset& toolset) { if (pre_build_info.external_toolchain_file.has_value()) return ""; + if (!pre_build_info.cmake_system_name.empty() && pre_build_info.cmake_system_name != "WindowsStore") return ""; const char* tonull = " >nul"; if (GlobalState::debugging) @@ -272,12 +273,10 @@ namespace vcpkg::Build return filter_dependencies(config.scf.core_paragraph->depends, triplet); } - auto it = - Util::find_if(config.scf.feature_paragraphs, - [&](std::unique_ptr<FeatureParagraph> const& fpgh) { return fpgh->name == feature; }); - Checks::check_exit(VCPKG_LINE_INFO, it != config.scf.feature_paragraphs.end()); + auto maybe_feature = config.scf.find_feature(feature); + Checks::check_exit(VCPKG_LINE_INFO, maybe_feature.has_value()); - return filter_dependencies(it->get()->depends, triplet); + return filter_dependencies(maybe_feature.get()->depends, triplet); }); auto dep_fspecs = FeatureSpec::from_strings_and_triplet(dep_strings, triplet); @@ -314,63 +313,134 @@ namespace vcpkg::Build } static ExtendedBuildResult do_build_package(const VcpkgPaths& paths, + const PreBuildInfo& pre_build_info, + const PackageSpec& spec, + const std::string& abi_tag, const BuildPackageConfig& config, const StatusParagraphs& status_db) { auto& fs = paths.get_filesystem(); - const Triplet& triplet = config.triplet; + const Triplet& triplet = spec.triplet(); + + const fs::path& cmake_exe_path = paths.get_cmake_exe(); + const fs::path& git_exe_path = paths.get_git_exe(); - struct AbiEntry + std::string all_features; + for (auto& feature : config.scf.feature_paragraphs) { - std::string key; - std::string value; - }; + all_features.append(feature->name + ";"); + } - std::vector<AbiEntry> abi_tag_entries; + const Toolset& toolset = paths.get_toolset(pre_build_info); + const std::string cmd_launch_cmake = System::make_cmake_cmd( + cmake_exe_path, + paths.ports_cmake, + { + {"CMD", "BUILD"}, + {"PORT", config.scf.core_paragraph->name}, + {"CURRENT_PORT_DIR", config.port_dir / "/."}, + {"TARGET_TRIPLET", spec.triplet().canonical_name()}, + {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, + {"VCPKG_USE_HEAD_VERSION", + Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, + {"_VCPKG_NO_DOWNLOADS", !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, + {"GIT", git_exe_path}, + {"FEATURES", Strings::join(";", config.feature_list)}, + {"ALL_FEATURES", all_features}, + }); - const PackageSpec spec = - PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, triplet).value_or_exit(VCPKG_LINE_INFO); + auto command = make_build_env_cmd(pre_build_info, toolset); + if (!command.empty()) command.append(" && "); + command.append(cmd_launch_cmake); - std::vector<FeatureSpec> required_fspecs = compute_required_feature_specs(config, status_db); + const auto timer = Chrono::ElapsedTimer::create_started(); - // extract out the actual package ids - auto dep_pspecs = Util::fmap(required_fspecs, [](FeatureSpec const& fspec) { return fspec.spec(); }); - Util::sort_unique_erase(dep_pspecs); - - // Find all features that aren't installed. This destroys required_fspecs. - Util::unstable_keep_if(required_fspecs, [&](FeatureSpec const& fspec) { - return !status_db.is_installed(fspec) && fspec.name() != spec.name(); - }); + const int return_code = System::cmd_execute_clean(command); + const auto buildtimeus = timer.microseconds(); + const auto spec_string = spec.to_string(); - if (!required_fspecs.empty()) { - return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; + auto locked_metrics = Metrics::g_metrics.lock(); + locked_metrics->track_buildtime(spec.to_string() + ":[" + Strings::join(",", config.feature_list) + "]", + buildtimeus); + if (return_code != 0) + { + locked_metrics->track_property("error", "build failed"); + locked_metrics->track_property("build_error", spec_string); + return BuildResult::BUILD_FAILED; + } } - // dep_pspecs was not destroyed - for (auto&& pspec : dep_pspecs) + const BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(spec)); + const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + + auto bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info, abi_tag); + + if (error_count != 0) { - if (pspec == spec) continue; - auto status_it = status_db.find_installed(pspec); - Checks::check_exit(VCPKG_LINE_INFO, status_it != status_db.end()); - abi_tag_entries.emplace_back( - AbiEntry{status_it->get()->package.spec.name(), status_it->get()->package.abi}); + return BuildResult::POST_BUILD_CHECKS_FAILED; + } + for (auto&& feature : config.feature_list) + { + for (auto&& f_pgh : config.scf.feature_paragraphs) + { + if (f_pgh->name == feature) + bcf->features.push_back( + create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); + } } - const fs::path& cmake_exe_path = paths.get_cmake_exe(); - const fs::path& git_exe_path = paths.get_git_exe(); + write_binary_control_file(paths, *bcf); + return {BuildResult::SUCCEEDED, std::move(bcf)}; + } - const fs::path ports_cmake_script_path = paths.ports_cmake; + static ExtendedBuildResult do_build_package_and_clean_buildtrees(const VcpkgPaths& paths, + const PreBuildInfo& pre_build_info, + const PackageSpec& spec, + const std::string& abi_tag, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) + { + auto result = do_build_package(paths, pre_build_info, spec, abi_tag, config, status_db); - if (GlobalState::g_binary_caching) + if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) { - abi_tag_entries.emplace_back(AbiEntry{ - "portfile", Commands::Hash::get_file_hash(cmake_exe_path, config.port_dir / "portfile.cmake", "SHA1")}); - abi_tag_entries.emplace_back(AbiEntry{ - "control", Commands::Hash::get_file_hash(cmake_exe_path, config.port_dir / "CONTROL", "SHA1")}); + auto& fs = paths.get_filesystem(); + const fs::path buildtrees_dir = paths.buildtrees / config.scf.core_paragraph->name; + auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); + for (auto&& file : buildtree_files) + { + if (fs.is_directory(file) && file.filename() != "src") + { + std::error_code ec; + fs.remove_all(file, ec); + } + } } - const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); + return result; + } + + Optional<AbiTagAndFile> compute_abi_tag(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const PreBuildInfo& pre_build_info, + Span<const AbiEntry> dependency_abis) + { + if (!GlobalState::g_binary_caching) return nullopt; + + auto& fs = paths.get_filesystem(); + const Triplet& triplet = config.triplet; + const std::string& name = config.scf.core_paragraph->name; + + std::vector<AbiEntry> abi_tag_entries; + + abi_tag_entries.insert(abi_tag_entries.end(), dependency_abis.begin(), dependency_abis.end()); + + abi_tag_entries.emplace_back( + AbiEntry{"portfile", Commands::Hash::get_file_hash(paths, config.port_dir / "portfile.cmake", "SHA1")}); + abi_tag_entries.emplace_back( + AbiEntry{"control", Commands::Hash::get_file_hash(paths, config.port_dir / "CONTROL", "SHA1")}); + abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag}); std::string features = Strings::join(";", config.feature_list); @@ -379,204 +449,198 @@ namespace vcpkg::Build if (config.build_package_options.use_head_version == UseHeadVersion::YES) abi_tag_entries.emplace_back(AbiEntry{"head", ""}); + Util::sort(abi_tag_entries); + std::string full_abi_info = Strings::join("", abi_tag_entries, [](const AbiEntry& p) { return p.key + " " + p.value + "\n"; }); - std::string abi_tag; - - if (GlobalState::g_binary_caching) + if (GlobalState::debugging) { - if (GlobalState::debugging) + System::println("[DEBUG] <abientries>"); + for (auto&& entry : abi_tag_entries) { - System::println("[DEBUG] <abientries>"); - for (auto&& entry : abi_tag_entries) - { - System::println("[DEBUG] %s|%s", entry.key, entry.value); - } - System::println("[DEBUG] </abientries>"); + System::println("[DEBUG] %s|%s", entry.key, entry.value); } + System::println("[DEBUG] </abientries>"); + } - auto abi_tag_entries_missing = abi_tag_entries; - Util::stable_keep_if(abi_tag_entries_missing, [](const AbiEntry& p) { return p.value.empty(); }); + auto abi_tag_entries_missing = abi_tag_entries; + Util::stable_keep_if(abi_tag_entries_missing, [](const AbiEntry& p) { return p.value.empty(); }); - if (abi_tag_entries_missing.empty()) - { - std::error_code ec; - fs.create_directories(paths.buildtrees / spec.name(), ec); - auto abi_file_path = paths.buildtrees / spec.name() / "vcpkg_abi_info"; - fs.write_contents(abi_file_path, full_abi_info); + if (abi_tag_entries_missing.empty()) + { + std::error_code ec; + fs.create_directories(paths.buildtrees / name, ec); + auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt"); + fs.write_contents(abi_file_path, full_abi_info); - abi_tag = Commands::Hash::get_file_hash(paths.get_cmake_exe(), abi_file_path, "SHA1"); - } - else - { - System::println("Warning: binary caching disabled because abi keys are missing values:\n%s", - Strings::join("", abi_tag_entries_missing, [](const AbiEntry& e) { - return " " + e.key + "\n"; - })); - } + return AbiTagAndFile{Commands::Hash::get_file_hash(paths, abi_file_path, "SHA1"), abi_file_path}; } - - std::unique_ptr<BinaryControlFile> bcf; - - auto archives_dir = paths.root / "archives"; - if (!abi_tag.empty()) + else { - archives_dir /= abi_tag.substr(0, 2); + System::println( + "Warning: binary caching disabled because abi keys are missing values:\n%s", + Strings::join("", abi_tag_entries_missing, [](const AbiEntry& e) { return " " + e.key + "\n"; })); + + return nullopt; } - auto archive_path = archives_dir / (abi_tag + ".zip"); + } - if (GlobalState::g_binary_caching && !abi_tag.empty() && fs.exists(archive_path)) - { - System::println("Using cached binary package: %s", archive_path.u8string()); + static void decompress_archive(const VcpkgPaths& paths, const PackageSpec& spec, const fs::path& archive_path) + { + auto& fs = paths.get_filesystem(); - auto pkg_path = paths.package_dir(spec); - std::error_code ec; - fs.remove_all(pkg_path, ec); - fs.create_directories(pkg_path, ec); - auto files = fs.get_files_non_recursive(pkg_path); - Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); + auto pkg_path = paths.package_dir(spec); + std::error_code ec; + fs.remove_all(pkg_path, ec); + fs.create_directories(pkg_path, ec); + auto files = fs.get_files_non_recursive(pkg_path); + Checks::check_exit(VCPKG_LINE_INFO, files.empty(), "unable to clear path: %s", pkg_path.u8string()); + +#if defined(_WIN32) + auto&& _7za = paths.get_7za_exe(); + + System::cmd_execute_clean(Strings::format( + R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); +#else + System::cmd_execute_clean(Strings::format( + R"(unzip -qq "%s" "-d%s")", archive_path.u8string(), pkg_path.u8string())); +#endif + } - auto&& _7za = paths.get_7za_exe(); + static void compress_archive(const VcpkgPaths& paths, const PackageSpec& spec, const fs::path& tmp_archive_path) + { + auto& fs = paths.get_filesystem(); + + std::error_code ec; + + fs.remove(tmp_archive_path, ec); + Checks::check_exit( + VCPKG_LINE_INFO, !fs.exists(tmp_archive_path), "Could not remove file: %s", tmp_archive_path.u8string()); +#if defined(_WIN32) + auto&& _7za = paths.get_7za_exe(); + + System::cmd_execute_clean(Strings::format( + R"("%s" a "%s" "%s\*" >nul)", + _7za.u8string(), + tmp_archive_path.u8string(), + paths.package_dir(spec).u8string())); +#else + System::cmd_execute_clean(Strings::format( + R"(cd '%s' && zip --quiet -r '%s' *)", paths.package_dir(spec).u8string(), tmp_archive_path.u8string())); +#endif + } + + ExtendedBuildResult build_package(const VcpkgPaths& paths, + const BuildPackageConfig& config, + const StatusParagraphs& status_db) + { + auto& fs = paths.get_filesystem(); + const Triplet& triplet = config.triplet; + const std::string& name = config.scf.core_paragraph->name; + + std::vector<FeatureSpec> required_fspecs = compute_required_feature_specs(config, status_db); - System::cmd_execute_clean(Strings::format( - R"("%s" x "%s" -o"%s" -y >nul)", _7za.u8string(), archive_path.u8string(), pkg_path.u8string())); + // extract out the actual package ids + auto dep_pspecs = Util::fmap(required_fspecs, [](FeatureSpec const& fspec) { return fspec.spec(); }); + Util::sort_unique_erase(dep_pspecs); - auto maybe_bcf = Paragraphs::try_load_cached_control_package(paths, spec); - bcf = std::make_unique<BinaryControlFile>(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO)); + // Find all features that aren't installed. This destroys required_fspecs. + Util::unstable_keep_if(required_fspecs, [&](FeatureSpec const& fspec) { + return !status_db.is_installed(fspec) && fspec.name() != name; + }); + + if (!required_fspecs.empty()) + { + return {BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES, std::move(required_fspecs)}; } - else + + const PackageSpec spec = + PackageSpec::from_name_and_triplet(config.scf.core_paragraph->name, triplet).value_or_exit(VCPKG_LINE_INFO); + + std::vector<AbiEntry> dependency_abis; + + // dep_pspecs was not destroyed + for (auto&& pspec : dep_pspecs) { - if (GlobalState::g_binary_caching && !abi_tag.empty()) - { - System::println("Could not locate cached archive: %s", archive_path.u8string()); - } + if (pspec == spec) continue; + auto status_it = status_db.find_installed(pspec); + Checks::check_exit(VCPKG_LINE_INFO, status_it != status_db.end()); + dependency_abis.emplace_back( + AbiEntry{status_it->get()->package.spec.name(), status_it->get()->package.abi}); + } - std::string all_features; - for (auto& feature : config.scf.feature_paragraphs) - { - all_features.append(feature->name + ";"); - } + const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); - const Toolset& toolset = paths.get_toolset(pre_build_info); - const std::string cmd_launch_cmake = System::make_cmake_cmd( - cmake_exe_path, - ports_cmake_script_path, - { - {"CMD", "BUILD"}, - {"PORT", config.scf.core_paragraph->name}, - {"CURRENT_PORT_DIR", config.port_dir / "/."}, - {"TARGET_TRIPLET", triplet.canonical_name()}, - {"VCPKG_PLATFORM_TOOLSET", toolset.version.c_str()}, - {"VCPKG_USE_HEAD_VERSION", - Util::Enum::to_bool(config.build_package_options.use_head_version) ? "1" : "0"}, - {"_VCPKG_NO_DOWNLOADS", - !Util::Enum::to_bool(config.build_package_options.allow_downloads) ? "1" : "0"}, - {"GIT", git_exe_path}, - {"FEATURES", features}, - {"ALL_FEATURES", all_features}, - }); - - auto command = make_build_env_cmd(pre_build_info, toolset); - if (!command.empty()) command.append(" && "); - command.append(cmd_launch_cmake); - - const auto timer = Chrono::ElapsedTimer::create_started(); - - const int return_code = System::cmd_execute_clean(command); - const auto buildtimeus = timer.microseconds(); - const auto spec_string = spec.to_string(); + auto maybe_abi_tag_and_file = compute_abi_tag(paths, config, pre_build_info, dependency_abis); - { - auto locked_metrics = Metrics::g_metrics.lock(); - locked_metrics->track_buildtime(spec.to_string() + ":[" + Strings::join(",", config.feature_list) + "]", - buildtimeus); - if (return_code != 0) - { - locked_metrics->track_property("error", "build failed"); - locked_metrics->track_property("build_error", spec_string); - return BuildResult::BUILD_FAILED; - } - } + std::unique_ptr<BinaryControlFile> bcf; - const BuildInfo build_info = read_build_info(fs, paths.build_info_file_path(spec)); - const size_t error_count = PostBuildLint::perform_all_checks(spec, paths, pre_build_info, build_info); + auto abi_tag_and_file = maybe_abi_tag_and_file.get(); - bcf = create_binary_control_file(*config.scf.core_paragraph, triplet, build_info, abi_tag); + if (GlobalState::g_binary_caching && abi_tag_and_file) + { + auto archives_root_dir = paths.root / "archives"; + auto archive_name = abi_tag_and_file->tag + ".zip"; + auto archive_subpath = fs::u8path(abi_tag_and_file->tag.substr(0, 2)) / archive_name; + auto archive_path = archives_root_dir / archive_subpath; + auto archive_tombstone_path = archives_root_dir / "fail" / archive_subpath; - if (error_count != 0) + if (fs.exists(archive_path)) { - return BuildResult::POST_BUILD_CHECKS_FAILED; + System::println("Using cached binary package: %s", archive_path.u8string()); + + decompress_archive(paths, spec, archive_path); + + auto maybe_bcf = Paragraphs::try_load_cached_package(paths, spec); + bcf = std::make_unique<BinaryControlFile>(std::move(maybe_bcf).value_or_exit(VCPKG_LINE_INFO)); + return {BuildResult::SUCCEEDED, std::move(bcf)}; } - for (auto&& feature : config.feature_list) + else if (fs.exists(archive_tombstone_path)) { - for (auto&& f_pgh : config.scf.feature_paragraphs) - { - if (f_pgh->name == feature) - bcf->features.push_back( - create_binary_feature_control_file(*config.scf.core_paragraph, *f_pgh, triplet)); - } + System::println("Found failure tombstone: %s", archive_tombstone_path.u8string()); + return BuildResult::BUILD_FAILED; } - if (GlobalState::g_binary_caching && !abi_tag.empty()) - { - std::error_code ec; - fs.write_contents( - paths.package_dir(spec) / "share" / spec.name() / "vcpkg_abi_info.txt", full_abi_info, ec); - } + System::println("Could not locate cached archive: %s", archive_path.u8string()); + + ExtendedBuildResult result = do_build_package_and_clean_buildtrees( + paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); - write_binary_control_file(paths, *bcf); + std::error_code ec; + fs.create_directories(paths.package_dir(spec) / "share" / spec.name(), ec); + auto abi_file_in_package = paths.package_dir(spec) / "share" / spec.name() / "vcpkg_abi_info.txt"; + fs.copy_file(abi_tag_and_file->tag_file, abi_file_in_package, fs::stdfs::copy_options::none, ec); + Checks::check_exit(VCPKG_LINE_INFO, !ec, "Could not copy into file: %s", abi_file_in_package.u8string()); - if (GlobalState::g_binary_caching && !abi_tag.empty()) + if (result.code == BuildResult::SUCCEEDED) { auto tmp_archive_path = paths.buildtrees / spec.name() / (spec.triplet().to_string() + ".zip"); - std::error_code ec; - fs.remove(tmp_archive_path, ec); - Checks::check_exit(VCPKG_LINE_INFO, - !fs.exists(tmp_archive_path), - "Could not remove file: %s", - tmp_archive_path.u8string()); - auto&& _7za = paths.get_7za_exe(); - - System::cmd_execute_clean(Strings::format( - R"("%s" a "%s" "%s\*" >nul)", - _7za.u8string(), - tmp_archive_path.u8string(), - paths.package_dir(spec).u8string())); - - fs.create_directories(archives_dir, ec); - - fs.rename(tmp_archive_path, archive_path); + compress_archive(paths, spec, tmp_archive_path); - System::println("Stored binary cache: %s", archive_path.u8string()); + fs.create_directories(archive_path.parent_path(), ec); + fs.rename(tmp_archive_path, archive_path, ec); + if (ec) + System::println( + System::Color::warning, "Failed to store binary cache: %s", archive_path.u8string()); + else + System::println("Stored binary cache: %s", archive_path.u8string()); } - } - return {BuildResult::SUCCEEDED, std::move(bcf)}; - } - - ExtendedBuildResult build_package(const VcpkgPaths& paths, - const BuildPackageConfig& config, - const StatusParagraphs& status_db) - { - ExtendedBuildResult result = do_build_package(paths, config, status_db); - - if (config.build_package_options.clean_buildtrees == CleanBuildtrees::YES) - { - auto& fs = paths.get_filesystem(); - const fs::path buildtrees_dir = paths.buildtrees / config.scf.core_paragraph->name; - auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir); - for (auto&& file : buildtree_files) + else if (result.code == BuildResult::BUILD_FAILED || result.code == BuildResult::POST_BUILD_CHECKS_FAILED) { - if (fs.is_directory(file) && file.filename() != "src") - { - std::error_code ec; - fs.remove_all(file, ec); - } + // Build failed, so store tombstone archive + fs.create_directories(archive_tombstone_path.parent_path(), ec); + fs.write_contents(archive_tombstone_path, "", ec); } - } - return result; + return result; + } + else + { + return do_build_package_and_clean_buildtrees( + paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config, status_db); + } } const std::string& to_string(const BuildResult build_result) @@ -700,7 +764,7 @@ namespace vcpkg::Build { return it_hash->second; } - auto hash = Commands::Hash::get_file_hash(paths.get_cmake_exe(), triplet_file_path, "SHA1"); + auto hash = Commands::Hash::get_file_hash(paths, triplet_file_path, "SHA1"); s_hash_cache.emplace(triplet_file_path, hash); return hash; } diff --git a/toolsrc/src/vcpkg/commands.ci.cpp b/toolsrc/src/vcpkg/commands.ci.cpp index c43f25b40..45eb1c83e 100644 --- a/toolsrc/src/vcpkg/commands.ci.cpp +++ b/toolsrc/src/vcpkg/commands.ci.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include <vcpkg/base/cache.h> #include <vcpkg/base/files.h> #include <vcpkg/base/stringliteral.h> #include <vcpkg/base/system.h> @@ -7,6 +8,7 @@ #include <vcpkg/build.h> #include <vcpkg/commands.h> #include <vcpkg/dependencies.h> +#include <vcpkg/globalstate.h> #include <vcpkg/help.h> #include <vcpkg/input.h> #include <vcpkg/install.h> @@ -24,6 +26,7 @@ namespace vcpkg::Commands::CI Install::InstallSummary summary; }; + static constexpr StringLiteral OPTION_DRY_RUN = "--dry-run"; static constexpr StringLiteral OPTION_EXCLUDE = "--exclude"; static constexpr StringLiteral OPTION_XUNIT = "--x-xunit"; @@ -32,16 +35,131 @@ namespace vcpkg::Commands::CI {OPTION_XUNIT, "File to output results in XUnit format (internal)"}, }}; + static constexpr std::array<CommandSwitch, 1> CI_SWITCHES = { + {{OPTION_DRY_RUN, "Print out plan without execution"}}}; + const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("ci x64-windows"), - 0, + 1, SIZE_MAX, - {{}, CI_SETTINGS}, + {CI_SWITCHES, CI_SETTINGS}, nullptr, }; + UnknownCIPortsResults find_unknown_ports_for_ci(const VcpkgPaths& paths, + const std::set<std::string>& exclusions, + const Dependencies::PortFileProvider& provider, + const std::vector<FeatureSpec>& fspecs) + { + UnknownCIPortsResults ret; + + auto& fs = paths.get_filesystem(); + + std::map<PackageSpec, std::string> abi_tag_map; + std::set<PackageSpec> will_fail; + + const Build::BuildPackageOptions install_plan_options = {Build::UseHeadVersion::NO, + Build::AllowDownloads::YES, + Build::CleanBuildtrees::YES, + Build::CleanPackages::YES}; + + vcpkg::Cache<Triplet, Build::PreBuildInfo> pre_build_info_cache; + + auto action_plan = Dependencies::create_feature_install_plan(provider, fspecs, StatusParagraphs{}); + + for (auto&& action : action_plan) + { + if (auto p = action.install_action.get()) + { + // determine abi tag + std::string abi; + if (auto scf = p->source_control_file.get()) + { + auto triplet = p->spec.triplet(); + + const Build::BuildPackageConfig build_config{p->source_control_file.value_or_exit(VCPKG_LINE_INFO), + triplet, + paths.port_dir(p->spec), + install_plan_options, + p->feature_list}; + + auto dependency_abis = + Util::fmap(p->computed_dependencies, [&](const PackageSpec& spec) -> Build::AbiEntry { + auto it = abi_tag_map.find(spec); + + if (it == abi_tag_map.end()) + return {spec.name(), ""}; + else + return {spec.name(), it->second}; + }); + const auto& pre_build_info = pre_build_info_cache.get_lazy( + triplet, [&]() { return Build::PreBuildInfo::from_triplet_file(paths, triplet); }); + + auto maybe_tag_and_file = + Build::compute_abi_tag(paths, build_config, pre_build_info, dependency_abis); + if (auto tag_and_file = maybe_tag_and_file.get()) + { + abi = tag_and_file->tag; + abi_tag_map.emplace(p->spec, abi); + } + } + else if (auto ipv = p->installed_package.get()) + { + abi = ipv->core->package.abi; + if (!abi.empty()) abi_tag_map.emplace(p->spec, abi); + } + + std::string state; + + auto archives_root_dir = paths.root / "archives"; + auto archive_name = abi + ".zip"; + auto archive_subpath = fs::u8path(abi.substr(0, 2)) / archive_name; + auto archive_path = archives_root_dir / archive_subpath; + auto archive_tombstone_path = archives_root_dir / "fail" / archive_subpath; + + bool b_will_build = false; + + if (Util::Sets::contains(exclusions, p->spec.name())) + { + ret.known.emplace(p->spec, BuildResult::EXCLUDED); + will_fail.emplace(p->spec); + } + else if (std::any_of(p->computed_dependencies.begin(), + p->computed_dependencies.end(), + [&](const PackageSpec& spec) { return Util::Sets::contains(will_fail, spec); })) + { + ret.known.emplace(p->spec, BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES); + will_fail.emplace(p->spec); + } + else if (fs.exists(archive_path)) + { + state += "pass"; + ret.known.emplace(p->spec, BuildResult::SUCCEEDED); + } + else if (fs.exists(archive_tombstone_path)) + { + state += "fail"; + ret.known.emplace(p->spec, BuildResult::BUILD_FAILED); + will_fail.emplace(p->spec); + } + else + { + ret.unknown.push_back(p->spec); + b_will_build = true; + } + + System::println("%40s: %1s %8s: %s", p->spec, (b_will_build ? "*" : " "), state, abi); + } + } + + return ret; + } + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) { + Checks::check_exit( + VCPKG_LINE_INFO, GlobalState::g_binary_caching, "The ci command requires binary caching to be enabled."); + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); std::set<std::string> exclusions_set; @@ -52,6 +170,8 @@ namespace vcpkg::Commands::CI exclusions_set.insert(exclusions.begin(), exclusions.end()); } + auto is_dry_run = Util::Sets::contains(options.switches, OPTION_DRY_RUN); + std::vector<Triplet> triplets; for (const std::string& triplet : args.command_arguments) { @@ -71,16 +191,21 @@ namespace vcpkg::Commands::CI Build::CleanBuildtrees::YES, Build::CleanPackages::YES}; - std::vector<std::string> ports = Install::get_all_port_names(paths); + std::vector<std::map<PackageSpec, BuildResult>> all_known_results; + + std::vector<std::string> all_ports = Install::get_all_port_names(paths); std::vector<TripletAndSummary> results; for (const Triplet& triplet : triplets) { Input::check_triplet(triplet, paths); - std::vector<PackageSpec> specs = PackageSpec::to_package_specs(ports, triplet); + + std::vector<PackageSpec> specs = PackageSpec::to_package_specs(all_ports, triplet); // Install the default features for every package - const auto featurespecs = Util::fmap(specs, [](auto& spec) { return FeatureSpec(spec, ""); }); + auto all_fspecs = Util::fmap(specs, [](auto& spec) { return FeatureSpec(spec, ""); }); + auto split_specs = find_unknown_ports_for_ci(paths, exclusions_set, paths_port_file, all_fspecs); + auto fspecs = Util::fmap(split_specs.unknown, [](auto& spec) { return FeatureSpec(spec, ""); }); - auto action_plan = Dependencies::create_feature_install_plan(paths_port_file, featurespecs, status_db); + auto action_plan = Dependencies::create_feature_install_plan(paths_port_file, fspecs, status_db); for (auto&& action : action_plan) { @@ -94,8 +219,18 @@ namespace vcpkg::Commands::CI } } - auto summary = Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); - results.push_back({triplet, std::move(summary)}); + if (is_dry_run) + { + Dependencies::print_plan(action_plan); + } + else + { + auto summary = Install::perform(action_plan, Install::KeepGoing::YES, paths, status_db); + for (auto&& result : summary.results) + split_specs.known.erase(result.spec); + results.push_back({triplet, std::move(summary)}); + all_known_results.emplace_back(std::move(split_specs.known)); + } } for (auto&& result : results) @@ -112,6 +247,14 @@ namespace vcpkg::Commands::CI for (auto&& result : results) xunit_doc += result.summary.xunit_results(); + for (auto&& known_result : all_known_results) + { + for (auto&& result : known_result) + { + xunit_doc += + Install::InstallSummary::xunit_result(result.first, Chrono::ElapsedTime{}, result.second); + } + } xunit_doc += "</collection></assembly></assemblies>\n"; paths.get_filesystem().write_contents(fs::u8path(it_xunit->second), xunit_doc); diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp index 41f261a53..ac34a6720 100644 --- a/toolsrc/src/vcpkg/commands.edit.cpp +++ b/toolsrc/src/vcpkg/commands.edit.cpp @@ -69,14 +69,24 @@ namespace vcpkg::Commands::Edit std::vector<fs::path> candidate_paths; auto maybe_editor_path = System::get_environment_variable("EDITOR"); - if (auto editor_path = maybe_editor_path.get()) + if (const std::string* editor_path = maybe_editor_path.get()) { candidate_paths.emplace_back(*editor_path); } - candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE_INSIDERS); - candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE_INSIDERS); - candidate_paths.push_back(System::get_program_files_platform_bitness() / VS_CODE); - candidate_paths.push_back(System::get_program_files_32_bit() / VS_CODE); + + const auto& program_files = System::get_program_files_platform_bitness(); + if (const fs::path* pf = program_files.get()) + { + candidate_paths.push_back(*pf / VS_CODE_INSIDERS); + candidate_paths.push_back(*pf / VS_CODE); + } + + const auto& program_files_32_bit = System::get_program_files_32_bit(); + if (const fs::path* pf = program_files_32_bit.get()) + { + candidate_paths.push_back(*pf / VS_CODE_INSIDERS); + candidate_paths.push_back(*pf / VS_CODE); + } const std::vector<fs::path> from_registry = find_from_registry(); candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend()); diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp index f3beef6cd..d078baedb 100644 --- a/toolsrc/src/vcpkg/commands.env.cpp +++ b/toolsrc/src/vcpkg/commands.env.cpp @@ -1,5 +1,6 @@ #include "pch.h" +#include <vcpkg/base/strings.h> #include <vcpkg/base/system.h> #include <vcpkg/build.h> #include <vcpkg/commands.h> @@ -7,25 +8,66 @@ namespace vcpkg::Commands::Env { + static constexpr StringLiteral OPTION_BIN = "--bin"; + static constexpr StringLiteral OPTION_INCLUDE = "--include"; + static constexpr StringLiteral OPTION_DEBUG_BIN = "--debug-bin"; + static constexpr StringLiteral OPTION_TOOLS = "--tools"; + static constexpr StringLiteral OPTION_PYTHON = "--python"; + + static constexpr std::array<CommandSwitch, 5> SWITCHES = {{ + {OPTION_BIN, "Add installed bin/ to PATH"}, + {OPTION_INCLUDE, "Add installed include/ to INCLUDE"}, + {OPTION_DEBUG_BIN, "Add installed debug/bin/ to PATH"}, + {OPTION_TOOLS, "Add installed tools/*/ to PATH"}, + {OPTION_PYTHON, "Add installed python/ to PYTHONPATH"}, + }}; + const CommandStructure COMMAND_STRUCTURE = { Help::create_example_string("env --triplet x64-windows"), 0, 0, - {}, + {SWITCHES, {}}, nullptr, }; - void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& default_triplet) + void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths, const Triplet& triplet) { - args.parse_arguments(COMMAND_STRUCTURE); + const auto& fs = paths.get_filesystem(); + + const ParsedArguments options = args.parse_arguments(COMMAND_STRUCTURE); - const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); + const auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, triplet); const Toolset& toolset = paths.get_toolset(pre_build_info); auto env_cmd = Build::make_build_env_cmd(pre_build_info, toolset); + + std::unordered_map<std::string, std::string> extra_env = {}; + const bool add_bin = Util::Sets::contains(options.switches, OPTION_BIN); + const bool add_include = Util::Sets::contains(options.switches, OPTION_INCLUDE); + const bool add_debug_bin = Util::Sets::contains(options.switches, OPTION_DEBUG_BIN); + const bool add_tools = Util::Sets::contains(options.switches, OPTION_TOOLS); + const bool add_python = Util::Sets::contains(options.switches, OPTION_PYTHON); + + std::vector<std::string> path_vars; + if (add_bin) path_vars.push_back((paths.installed / triplet.to_string() / "bin").u8string()); + if (add_debug_bin) path_vars.push_back((paths.installed / triplet.to_string() / "debug" / "bin").u8string()); + if (add_include) extra_env.emplace("INCLUDE", (paths.installed / triplet.to_string() / "include").u8string()); + if (add_tools) + { + auto tools_dir = paths.installed / triplet.to_string() / "tools"; + auto tool_files = fs.get_files_non_recursive(tools_dir); + path_vars.push_back(tools_dir.u8string()); + for (auto&& tool_dir : tool_files) + { + if (fs.is_directory(tool_dir)) path_vars.push_back(tool_dir.u8string()); + } + } + if (add_python) extra_env.emplace("PYTHONPATH", (paths.installed / triplet.to_string() / "python").u8string()); + if (path_vars.size() > 0) extra_env.emplace("PATH", Strings::join(";", path_vars)); + if (env_cmd.empty()) - System::cmd_execute_clean("cmd"); + System::cmd_execute_clean("cmd", extra_env); else - System::cmd_execute_clean(env_cmd + " && cmd"); + System::cmd_execute_clean(env_cmd + " && cmd", extra_env); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg/commands.hash.cpp b/toolsrc/src/vcpkg/commands.hash.cpp index bbbbed036..9e1b54390 100644 --- a/toolsrc/src/vcpkg/commands.hash.cpp +++ b/toolsrc/src/vcpkg/commands.hash.cpp @@ -1,17 +1,118 @@ #include "pch.h" +#include <vcpkg/base/checks.h> +#include <vcpkg/base/strings.h> #include <vcpkg/base/system.h> #include <vcpkg/base/util.h> #include <vcpkg/commands.h> #include <vcpkg/help.h> +#if defined(_WIN32) +#include <bcrypt.h> + +#ifndef NT_SUCCESS +#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) +#endif + namespace vcpkg::Commands::Hash { - std::string get_file_hash(fs::path const& cmake_exe_path, fs::path const& path, std::string const& hash_type) + namespace + { + static std::string to_hex(const unsigned char* string, const size_t bytes) + { + static constexpr char HEX_MAP[] = "0123456789abcdef"; + + std::string output; + output.resize(2 * bytes); + + size_t current_char = 0; + for (size_t i = 0; i < bytes; i++) + { + // high + output[current_char] = HEX_MAP[(string[i] & 0xF0) >> 4]; + ++current_char; + // low + output[current_char] = HEX_MAP[(string[i] & 0x0F)]; + ++current_char; + } + + return output; + } + + struct BCryptAlgorithmHandle : Util::ResourceBase + { + BCRYPT_ALG_HANDLE handle = nullptr; + + ~BCryptAlgorithmHandle() + { + if (handle) BCryptCloseAlgorithmProvider(handle, 0); + } + }; + + struct BCryptHashHandle : Util::ResourceBase + { + BCRYPT_HASH_HANDLE handle = nullptr; + + ~BCryptHashHandle() + { + if (handle) BCryptDestroyHash(handle); + } + }; + } + + std::string get_file_hash(const VcpkgPaths&, const fs::path& path, const std::string& hash_type) + { + BCryptAlgorithmHandle algorithm_handle; + + NTSTATUS error_code = BCryptOpenAlgorithmProvider( + &algorithm_handle.handle, Strings::to_utf16(Strings::ascii_to_uppercase(hash_type)).c_str(), nullptr, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to open the algorithm provider"); + + DWORD hash_buffer_bytes; + DWORD cb_data; + error_code = BCryptGetProperty(algorithm_handle.handle, + BCRYPT_HASH_LENGTH, + reinterpret_cast<PUCHAR>(&hash_buffer_bytes), + sizeof(DWORD), + &cb_data, + 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to get hash length"); + const ULONG length_in_bytes = hash_buffer_bytes; + + BCryptHashHandle hash_handle; + + error_code = BCryptCreateHash(algorithm_handle.handle, &hash_handle.handle, nullptr, 0, nullptr, 0, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to initialize the hasher"); + + FILE* file = nullptr; + const auto ec = _wfopen_s(&file, path.c_str(), L"rb"); + Checks::check_exit(VCPKG_LINE_INFO, ec == 0, "Failed to open file: %s", path.u8string()); + unsigned char buffer[4096]; + while (const auto actual_size = fread(buffer, 1, sizeof(buffer), file)) + { + error_code = BCryptHashData(hash_handle.handle, buffer, static_cast<ULONG>(actual_size), 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to hash data"); + } + + fclose(file); + + std::unique_ptr<unsigned char[]> hash_buffer = std::make_unique<UCHAR[]>(length_in_bytes); + + error_code = BCryptFinishHash(hash_handle.handle, hash_buffer.get(), length_in_bytes, 0); + Checks::check_exit(VCPKG_LINE_INFO, NT_SUCCESS(error_code), "Failed to finalize the hash"); + + return to_hex(hash_buffer.get(), length_in_bytes); + } +} + +#else +namespace vcpkg::Commands::Hash +{ + std::string get_file_hash(const VcpkgPaths& paths, const fs::path& path, const std::string& hash_type) { const std::string cmd_line = Strings::format( R"("%s" -E %ssum "%s")", - cmake_exe_path.u8string(), + paths.get_cmake_exe().u8string(), Strings::ascii_to_lowercase(hash_type), path.u8string()); @@ -32,7 +133,11 @@ namespace vcpkg::Commands::Hash Util::erase_remove_if(hash, isspace); return hash; } +} +#endif +namespace vcpkg::Commands::Hash +{ const CommandStructure COMMAND_STRUCTURE = { Strings::format("The argument should be a file path\n%s", Help::create_example_string("hash boost_1_62_0.tar.bz2")), @@ -44,19 +149,12 @@ namespace vcpkg::Commands::Hash void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths) { - args.parse_arguments(COMMAND_STRUCTURE); - - if (args.command_arguments.size() == 1) - { - auto hash = get_file_hash(paths.get_cmake_exe(), args.command_arguments[0], "SHA512"); - System::println(hash); - } - if (args.command_arguments.size() == 2) - { - auto hash = get_file_hash(paths.get_cmake_exe(), args.command_arguments[0], args.command_arguments[1]); - System::println(hash); - } + Util::unused(args.parse_arguments(COMMAND_STRUCTURE)); + const fs::path file_to_hash = args.command_arguments[0]; + const std::string algorithm = args.command_arguments.size() == 2 ? args.command_arguments[1] : "SHA512"; + const std::string hash = get_file_hash(paths, file_to_hash, algorithm); + System::println(hash); Checks::exit_success(VCPKG_LINE_INFO); } } diff --git a/toolsrc/src/vcpkg/commands.integrate.cpp b/toolsrc/src/vcpkg/commands.integrate.cpp index 460e99b88..36e4e56e7 100644 --- a/toolsrc/src/vcpkg/commands.integrate.cpp +++ b/toolsrc/src/vcpkg/commands.integrate.cpp @@ -148,12 +148,12 @@ namespace vcpkg::Commands::Integrate static void integrate_install(const VcpkgPaths& paths) { static const std::array<fs::path, 2> OLD_SYSTEM_TARGET_FILES = { - System::get_program_files_32_bit() / + System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", - System::get_program_files_32_bit() / + System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets"}; static const fs::path SYSTEM_WIDE_TARGETS_FILE = - System::get_program_files_32_bit() / + System::get_program_files_32_bit().value_or_exit(VCPKG_LINE_INFO) / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; auto& fs = paths.get_filesystem(); diff --git a/toolsrc/src/vcpkg/dependencies.cpp b/toolsrc/src/vcpkg/dependencies.cpp index 1f853014b..f6d81c973 100644 --- a/toolsrc/src/vcpkg/dependencies.cpp +++ b/toolsrc/src/vcpkg/dependencies.cpp @@ -144,12 +144,14 @@ namespace vcpkg::Dependencies InstallPlanAction::InstallPlanAction(const PackageSpec& spec, const SourceControlFile& scf, const std::set<std::string>& features, - const RequestType& request_type) + const RequestType& request_type, + std::vector<PackageSpec>&& dependencies) : spec(spec) , source_control_file(scf) , plan_type(InstallPlanType::BUILD_AND_INSTALL) , request_type(request_type) , feature_list(features) + , computed_dependencies(std::move(dependencies)) { } @@ -162,6 +164,7 @@ namespace vcpkg::Dependencies , plan_type(InstallPlanType::ALREADY_INSTALLED) , request_type(request_type) , feature_list(features) + , computed_dependencies(installed_package.get()->dependencies()) { } @@ -530,7 +533,7 @@ namespace vcpkg::Dependencies for (auto&& depend : remove_edges_edges) { auto& depend_cluster = graph.get(depend.spec()); - graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); + if (&depend_cluster != &cluster) graph_plan.remove_graph.add_edge({&cluster}, {&depend_cluster}); mark_minus(depend_cluster, graph, graph_plan); } } @@ -683,11 +686,17 @@ namespace vcpkg::Dependencies // If it will be transiently uninstalled, we need to issue a full installation command auto pscf = p_cluster->source_control_file.value_or_exit(VCPKG_LINE_INFO); Checks::check_exit(VCPKG_LINE_INFO, pscf != nullptr); + + auto dep_specs = Util::fmap(m_graph_plan->install_graph.adjacency_list(p_cluster), + [](ClusterPtr const& p) { return p->spec; }); + Util::sort_unique_erase(dep_specs); + plan.emplace_back(InstallPlanAction{ p_cluster->spec, *pscf, p_cluster->to_install_features, p_cluster->request_type, + std::move(dep_specs), }); } else diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp index b7d355742..743619937 100644 --- a/toolsrc/src/vcpkg/help.cpp +++ b/toolsrc/src/vcpkg/help.cpp @@ -98,14 +98,10 @@ namespace vcpkg::Help " vcpkg create <pkg> <url>\n" " [archivename] Create a new package\n" " vcpkg owns <pat> Search for files in installed packages\n" - " vcpkg cache List cached compiled packages\n" + " vcpkg env Creates a clean shell environment for development or compiling.\n" " vcpkg version Display version information\n" " vcpkg contact Display contact information to send feedback\n" "\n" - //"internal commands:\n" - //" --check-build-deps <controlfile>\n" - //" --create-binary-control <controlfile>\n" - //"\n" "Options:\n" " --triplet <t> Specify the target architecture triplet.\n" " (default: %%VCPKG_DEFAULT_TRIPLET%%, see 'vcpkg help triplet')\n" diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp index 46c7c53b8..e30a34c18 100644 --- a/toolsrc/src/vcpkg/install.cpp +++ b/toolsrc/src/vcpkg/install.cpp @@ -306,7 +306,7 @@ namespace vcpkg::Install System::println("Building package %s... done", display_name_with_features); auto bcf = std::make_unique<BinaryControlFile>( - Paragraphs::try_load_cached_control_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO)); + Paragraphs::try_load_cached_package(paths, action.spec).value_or_exit(VCPKG_LINE_INFO)); auto code = aux_install(display_name_with_features, *bcf); if (action.build_options.clean_packages == Build::CleanPackages::YES) @@ -668,39 +668,42 @@ namespace vcpkg::Install return nullptr; } + std::string InstallSummary::xunit_result(const PackageSpec& spec, Chrono::ElapsedTime time, BuildResult code) + { + std::string inner_block; + const char* result_string = ""; + switch (code) + { + case BuildResult::POST_BUILD_CHECKS_FAILED: + case BuildResult::FILE_CONFLICTS: + case BuildResult::BUILD_FAILED: + result_string = "Fail"; + inner_block = Strings::format("<failure><message><![CDATA[%s]]></message></failure>", to_string(code)); + break; + case BuildResult::EXCLUDED: + case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: + result_string = "Skip"; + inner_block = Strings::format("<reason><![CDATA[%s]]></reason>", to_string(code)); + break; + case BuildResult::SUCCEEDED: result_string = "Pass"; break; + default: Checks::exit_fail(VCPKG_LINE_INFO); + } + + return Strings::format(R"(<test name="%s" method="%s" time="%lld" result="%s">%s</test>)" + "\n", + spec, + spec, + time.as<std::chrono::seconds>().count(), + result_string, + inner_block); + } + std::string InstallSummary::xunit_results() const { std::string xunit_doc; for (auto&& result : results) { - std::string inner_block; - const char* result_string = ""; - switch (result.build_result.code) - { - case BuildResult::POST_BUILD_CHECKS_FAILED: - case BuildResult::FILE_CONFLICTS: - case BuildResult::BUILD_FAILED: - result_string = "Fail"; - inner_block = Strings::format("<failure><message><![CDATA[%s]]></message></failure>", - to_string(result.build_result.code)); - break; - case BuildResult::EXCLUDED: - case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: - result_string = "Skip"; - inner_block = - Strings::format("<reason><![CDATA[%s]]></reason>", to_string(result.build_result.code)); - break; - case BuildResult::SUCCEEDED: result_string = "Pass"; break; - default: Checks::exit_fail(VCPKG_LINE_INFO); - } - - xunit_doc += Strings::format(R"(<test name="%s" method="%s" time="%lld" result="%s">%s</test>)" - "\n", - result.spec, - result.spec, - result.timing.as<std::chrono::seconds>().count(), - result_string, - inner_block); + xunit_doc += xunit_result(result.spec, result.timing, result.build_result.code); } return xunit_doc; } diff --git a/toolsrc/src/vcpkg/metrics.cpp b/toolsrc/src/vcpkg/metrics.cpp index d49cadbe2..9e17b237d 100644 --- a/toolsrc/src/vcpkg/metrics.cpp +++ b/toolsrc/src/vcpkg/metrics.cpp @@ -92,7 +92,7 @@ namespace vcpkg::Metrics { encoded.append("\\\""); } - else if (ch < 0x20 || ch >= 0x80) + else if (ch < 0x20 || static_cast<unsigned char>(ch) >= 0x80) { // Note: this treats incoming Strings as Latin-1 static constexpr const char HEX[16] = { diff --git a/toolsrc/src/vcpkg/paragraphs.cpp b/toolsrc/src/vcpkg/paragraphs.cpp index b66d53994..d0b0c0abf 100644 --- a/toolsrc/src/vcpkg/paragraphs.cpp +++ b/toolsrc/src/vcpkg/paragraphs.cpp @@ -228,7 +228,7 @@ namespace vcpkg::Paragraphs return error_info; } - Expected<BinaryControlFile> try_load_cached_control_package(const VcpkgPaths& paths, const PackageSpec& spec) + Expected<BinaryControlFile> try_load_cached_package(const VcpkgPaths& paths, const PackageSpec& spec) { Expected<std::vector<std::unordered_map<std::string, std::string>>> pghs = get_paragraphs(paths.get_filesystem(), paths.package_dir(spec) / "CONTROL"); diff --git a/toolsrc/src/vcpkg/sourceparagraph.cpp b/toolsrc/src/vcpkg/sourceparagraph.cpp index 0b4baf189..ed61cb42a 100644 --- a/toolsrc/src/vcpkg/sourceparagraph.cpp +++ b/toolsrc/src/vcpkg/sourceparagraph.cpp @@ -158,6 +158,16 @@ namespace vcpkg return std::move(control_file); } + Optional<const FeatureParagraph&> SourceControlFile::find_feature(const std::string& featurename) const + { + auto it = Util::find_if(feature_paragraphs, + [&](const std::unique_ptr<FeatureParagraph>& p) { return p->name == featurename; }); + if (it != feature_paragraphs.end()) + return **it; + else + return nullopt; + } + Dependency Dependency::parse_dependency(std::string name, std::string qualifier) { Dependency dep; diff --git a/toolsrc/src/vcpkg/vcpkgpaths.cpp b/toolsrc/src/vcpkg/vcpkgpaths.cpp index e62ef8662..c36def15d 100644 --- a/toolsrc/src/vcpkg/vcpkgpaths.cpp +++ b/toolsrc/src/vcpkg/vcpkgpaths.cpp @@ -19,6 +19,8 @@ namespace vcpkg { std::array<int, 3> required_version; fs::path downloaded_exe_path; + std::string url; + fs::path downloaded_path; }; static Optional<std::array<int, 3>> parse_version_string(const std::string& version_as_string) @@ -41,8 +43,24 @@ namespace vcpkg static ToolData parse_tool_data_from_xml(const VcpkgPaths& paths, const std::string& tool) { +#if defined(_WIN32) + static constexpr StringLiteral OS_STRING = ""; +#elif defined(__APPLE__) + static constexpr StringLiteral OS_STRING = " os=\"osx\""; +#else // assume linux + static constexpr StringLiteral OS_STRING = " os=\"linux\""; +#endif + static const fs::path XML_PATH = paths.scripts / "vcpkgTools.xml"; + const auto maybe_get_string_inside_tags = [](const std::string& input, + const std::regex& regex) -> Optional<std::string> { + std::smatch match; + const bool has_match = std::regex_search(input.cbegin(), input.cend(), match, regex); + if (!has_match) return nullopt; + return match[1]; + }; + const auto get_string_inside_tags = [](const std::string& input, const std::regex& regex, const std::string& tag_name) -> std::string { std::smatch match; @@ -57,7 +75,10 @@ namespace vcpkg static const std::regex VERSION_REGEX{ Strings::format(R"###(<requiredVersion>([\s\S]*?)</requiredVersion>)###", tool)}; static const std::regex EXE_RELATIVE_PATH_REGEX{ - Strings::format(R"###(<exeRelativePath>([\s\S]*?)</exeRelativePath>)###", tool)}; + Strings::format(R"###(<exeRelativePath%s>([\s\S]*?)</exeRelativePath>)###", OS_STRING)}; + static const std::regex ARCHIVE_RELATIVE_PATH_REGEX{ + Strings::format(R"###(<archiveRelativePath%s>([\s\S]*?)</archiveRelativePath>)###", OS_STRING)}; + static const std::regex URL_REGEX{Strings::format(R"###(<url%s>([\s\S]*?)</url>)###", OS_STRING)}; const std::regex tool_regex{Strings::format(R"###(<tool[\s]+name="%s">([\s\S]*?)</tool>)###", tool)}; @@ -74,9 +95,13 @@ namespace vcpkg const std::string required_version_as_string = get_string_inside_tags(tool_data_as_string, VERSION_REGEX, "requiredVersion"); + const std::string url = get_string_inside_tags(tool_data_as_string, URL_REGEX, "url"); + const std::string exe_relative_path = get_string_inside_tags(tool_data_as_string, EXE_RELATIVE_PATH_REGEX, "exeRelativePath"); + auto archive_relative_path = maybe_get_string_inside_tags(tool_data_as_string, ARCHIVE_RELATIVE_PATH_REGEX); + const Optional<std::array<int, 3>> required_version = parse_version_string(required_version_as_string); Checks::check_exit(VCPKG_LINE_INFO, required_version.has_value(), @@ -85,7 +110,10 @@ namespace vcpkg required_version_as_string); const fs::path exe_path = paths.downloads / exe_relative_path; - return ToolData{*required_version.get(), exe_path}; + return ToolData{*required_version.get(), + exe_path, + url, + paths.downloads / archive_relative_path.value_or(exe_relative_path)}; } static bool exists_and_has_equal_or_greater_version(const std::string& version_cmd, @@ -144,8 +172,10 @@ namespace vcpkg return data_lines; } - static fs::path fetch_tool(const fs::path& scripts_folder, const std::string& tool_name, const ToolData& tool_data) + static fs::path fetch_tool(const VcpkgPaths& paths, const std::string& tool_name, const ToolData& tool_data) { + const auto& fs = paths.get_filesystem(); + const fs::path& scripts_folder = paths.scripts; const std::array<int, 3>& version = tool_data.required_version; const std::string version_as_string = Strings::format("%d.%d.%d", version[0], version[1], version[2]); @@ -154,6 +184,7 @@ namespace vcpkg version_as_string, tool_name, version_as_string); +#if defined(_WIN32) const fs::path script = scripts_folder / "fetchtool.ps1"; const std::string title = Strings::format( "Fetching %s version %s (No sufficient installed version was found)", tool_name, version_as_string); @@ -173,27 +204,44 @@ namespace vcpkg expected_downloaded_path.u8string(), actual_downloaded_path.u8string()); return actual_downloaded_path; +#else + if (!fs.exists(tool_data.downloaded_path)) + { + auto code = System::cmd_execute( + Strings::format(R"(curl '%s' --create-dirs --output '%s')", tool_data.url, tool_data.downloaded_path)); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "curl failed while downloading %s", tool_data.url); + } + auto code = System::cmd_execute( + Strings::format(R"(cd '%s' && tar xzf '%s')", paths.downloads, tool_data.downloaded_path)); + Checks::check_exit(VCPKG_LINE_INFO, code == 0, "tar failed while extracting %s", tool_data.downloaded_path); + + Checks::check_exit(VCPKG_LINE_INFO, + fs.exists(tool_data.downloaded_exe_path), + "Expected %s to exist after extracting", + tool_data.downloaded_exe_path); + + return tool_data.downloaded_exe_path; +#endif } static fs::path get_cmake_path(const VcpkgPaths& paths) { -#if defined(_WIN32) + std::vector<fs::path> candidate_paths; +#if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "cmake"); + candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); #else static const ToolData TOOL_DATA = ToolData{{3, 5, 1}, ""}; #endif static const std::string VERSION_CHECK_ARGUMENTS = "--version"; - std::vector<fs::path> candidate_paths; -#if defined(_WIN32) - candidate_paths.push_back(TOOL_DATA.downloaded_exe_path); -#endif const std::vector<fs::path> from_path = Files::find_from_PATH("cmake"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); -#if defined(_WIN32) - candidate_paths.push_back(System::get_program_files_platform_bitness() / "CMake" / "bin" / "cmake.exe"); - candidate_paths.push_back(System::get_program_files_32_bit() / "CMake" / "bin"); -#endif + + const auto& program_files = System::get_program_files_platform_bitness(); + if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); + const auto& program_files_32_bit = System::get_program_files_32_bit(); + if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "CMake" / "bin" / "cmake.exe"); const Optional<fs::path> path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); @@ -202,7 +250,7 @@ namespace vcpkg return *p; } - return fetch_tool(paths.scripts, "cmake", TOOL_DATA); + return fetch_tool(paths, "cmake", TOOL_DATA); } static fs::path get_7za_path(const VcpkgPaths& paths) @@ -211,7 +259,7 @@ namespace vcpkg static const ToolData TOOL_DATA = parse_tool_data_from_xml(paths, "7zip"); if (!paths.get_filesystem().exists(TOOL_DATA.downloaded_exe_path)) { - return fetch_tool(paths.scripts, "7zip", TOOL_DATA); + return fetch_tool(paths, "7zip", TOOL_DATA); } return TOOL_DATA.downloaded_exe_path; #else @@ -234,7 +282,7 @@ namespace vcpkg return *p; } - return fetch_tool(paths.scripts, "nuget", TOOL_DATA); + return fetch_tool(paths, "nuget", TOOL_DATA); } static fs::path get_git_path(const VcpkgPaths& paths) @@ -252,10 +300,11 @@ namespace vcpkg #endif const std::vector<fs::path> from_path = Files::find_from_PATH("git"); candidate_paths.insert(candidate_paths.end(), from_path.cbegin(), from_path.cend()); -#if defined(_WIN32) - candidate_paths.push_back(System::get_program_files_platform_bitness() / "git" / "cmd" / "git.exe"); - candidate_paths.push_back(System::get_program_files_32_bit() / "git" / "cmd" / "git.exe"); -#endif + + const auto& program_files = System::get_program_files_platform_bitness(); + if (const auto pf = program_files.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); + const auto& program_files_32_bit = System::get_program_files_32_bit(); + if (const auto pf = program_files_32_bit.get()) candidate_paths.push_back(*pf / "git" / "cmd" / "git.exe"); const Optional<fs::path> path = find_if_has_equal_or_greater_version(candidate_paths, VERSION_CHECK_ARGUMENTS, TOOL_DATA.required_version); @@ -264,7 +313,7 @@ namespace vcpkg return *p; } - return fetch_tool(paths.scripts, "git", TOOL_DATA); + return fetch_tool(paths, "git", TOOL_DATA); } static fs::path get_ifw_installerbase_path(const VcpkgPaths& paths) @@ -290,10 +339,10 @@ namespace vcpkg return *p; } - return fetch_tool(paths.scripts, "installerbase", TOOL_DATA); + return fetch_tool(paths, "installerbase", TOOL_DATA); } - Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir) + Expected<VcpkgPaths> VcpkgPaths::create(const fs::path& vcpkg_root_dir, const std::string& default_vs_path) { std::error_code ec; const fs::path canonical_vcpkg_root_dir = fs::stdfs::canonical(vcpkg_root_dir, ec); @@ -304,6 +353,7 @@ namespace vcpkg VcpkgPaths paths; paths.root = canonical_vcpkg_root_dir; + paths.default_vs_path = default_vs_path; if (paths.root.empty()) { @@ -621,7 +671,8 @@ namespace vcpkg const Toolset& VcpkgPaths::get_toolset(const Build::PreBuildInfo& prebuildinfo) const { - if (prebuildinfo.external_toolchain_file) + if (prebuildinfo.external_toolchain_file || + (!prebuildinfo.cmake_system_name.empty() && prebuildinfo.cmake_system_name != "WindowsStore")) { static Toolset external_toolset = []() -> Toolset { Toolset ret; @@ -643,7 +694,11 @@ namespace vcpkg std::vector<const Toolset*> candidates = Util::element_pointers(vs_toolsets); const auto tsv = prebuildinfo.platform_toolset.get(); - const auto vsp = prebuildinfo.visual_studio_path.get(); + auto vsp = prebuildinfo.visual_studio_path.get(); + if (!vsp && !default_vs_path.empty()) + { + vsp = &default_vs_path; + } if (tsv && vsp) { diff --git a/toolsrc/vcpkg/vcpkg.vcxproj b/toolsrc/vcpkg/vcpkg.vcxproj index 4def6a74b..2ab94eb0a 100644 --- a/toolsrc/vcpkg/vcpkg.vcxproj +++ b/toolsrc/vcpkg/vcpkg.vcxproj @@ -77,7 +77,7 @@ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
- <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -91,7 +91,7 @@ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
- <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -109,7 +109,7 @@ <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -127,7 +127,7 @@ <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/toolsrc/vcpkgmetricsuploader/vcpkgmetricsuploader.vcxproj b/toolsrc/vcpkgmetricsuploader/vcpkgmetricsuploader.vcxproj index d78e48e13..a2ceef9ce 100644 --- a/toolsrc/vcpkgmetricsuploader/vcpkgmetricsuploader.vcxproj +++ b/toolsrc/vcpkgmetricsuploader/vcpkgmetricsuploader.vcxproj @@ -77,7 +77,7 @@ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
- <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -91,7 +91,7 @@ <MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
- <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -109,7 +109,7 @@ <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -127,7 +127,7 @@ <Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
- <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>winhttp.lib;version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
diff --git a/toolsrc/vcpkgtest/vcpkgtest.vcxproj b/toolsrc/vcpkgtest/vcpkgtest.vcxproj index d61b15a71..a0d44918d 100644 --- a/toolsrc/vcpkgtest/vcpkgtest.vcxproj +++ b/toolsrc/vcpkgtest/vcpkgtest.vcxproj @@ -120,6 +120,7 @@ <Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;$(VsInstallRoot)\VC\Auxiliary\VS\UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -138,6 +139,7 @@ <Link>
<SubSystem>Windows</SubSystem>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;$(VsInstallRoot)\VC\Auxiliary\VS\UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -159,6 +161,7 @@ <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;$(VsInstallRoot)\VC\Auxiliary\VS\UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -180,6 +183,7 @@ <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;$(VsInstallRoot)\VC\Auxiliary\VS\UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
