diff options
| author | Robert Schumacher <roschuma@microsoft.com> | 2017-02-21 13:39:36 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-02-21 13:39:36 -0800 |
| commit | 7d4df89c1dfff0b2bad0165ac4579f6352935a94 (patch) | |
| tree | 8b87d29fb74fb24984d5aff9b021f14d95afb5ab /toolsrc/src | |
| parent | d9462fdf490d3396cac58b1a935b1b8a982b3a72 (diff) | |
| parent | b921dce5fc17bd4c1c206b79eb0a7b8758dcf5bf (diff) | |
| download | vcpkg-7d4df89c1dfff0b2bad0165ac4579f6352935a94.tar.gz vcpkg-7d4df89c1dfff0b2bad0165ac4579f6352935a94.zip | |
Merge branch 'master' into master
Diffstat (limited to 'toolsrc/src')
42 files changed, 661 insertions, 388 deletions
diff --git a/toolsrc/src/BinaryParagraph.cpp b/toolsrc/src/BinaryParagraph.cpp index f949677a3..8605cd276 100644 --- a/toolsrc/src/BinaryParagraph.cpp +++ b/toolsrc/src/BinaryParagraph.cpp @@ -23,22 +23,6 @@ namespace vcpkg static const std::string DEPENDS = "Depends"; } - static const std::vector<std::string>& get_list_of_valid_fields() - { - static const std::vector<std::string> valid_fields = - { - BinaryParagraphRequiredField::PACKAGE, - BinaryParagraphRequiredField::VERSION, - BinaryParagraphRequiredField::ARCHITECTURE, - - BinaryParagraphOptionalField::DESCRIPTION, - BinaryParagraphOptionalField::MAINTAINER, - BinaryParagraphOptionalField::DEPENDS - }; - - return valid_fields; - } - BinaryParagraph::BinaryParagraph() = default; BinaryParagraph::BinaryParagraph(std::unordered_map<std::string, std::string> fields) diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index 90bd55843..c4ddbc62e 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -22,7 +22,8 @@ namespace vcpkg::PostBuildLint std::regex regex; OutdatedDynamicCrt(const std::string& name, const std::string& regex_as_string) - : name(name), regex(std::regex(regex_as_string, std::regex_constants::icase)) {} + : name(name), + regex(std::regex(regex_as_string, std::regex_constants::icase)) {} }; const std::vector<OutdatedDynamicCrt>& get_outdated_dynamic_crts() @@ -424,24 +425,6 @@ namespace vcpkg::PostBuildLint return lint_status::SUCCESS; } - static lint_status check_no_subdirectories(const fs::path& dir) - { - const std::vector<fs::path> subdirectories = Files::recursive_find_matching_paths_in_dir(dir, [&](const fs::path& current) - { - return fs::is_directory(current); - }); - - if (!subdirectories.empty()) - { - System::println(System::color::warning, "Directory %s should have no subdirectories", dir.generic_string()); - System::println("The following subdirectories were found: "); - Files::print_paths(subdirectories); - return lint_status::ERROR_DETECTED; - } - - return lint_status::SUCCESS; - } - static lint_status check_bin_folders_are_not_present_in_static_build(const fs::path& package_dir) { const fs::path bin = package_dir / "bin"; @@ -486,7 +469,7 @@ namespace vcpkg::PostBuildLint System::println("The following empty directories were found: "); Files::print_paths(empty_directories); System::println(System::color::warning, "If a directory should be populated but is not, this might indicate an error in the portfile.\n" - "If the directories are not needed and their creation cannot be disabled, use something like this in the portfile to remove them)\n" + "If the directories are not needed and their creation cannot be disabled, use something like this in the portfile to remove them:\n" "\n" R"###( file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/a/dir ${CURRENT_PACKAGES_DIR}/some/other/dir))###""\n" "\n"); @@ -499,12 +482,12 @@ namespace vcpkg::PostBuildLint struct BuildType_and_file { fs::path file; - BuildType build_type; + BuildType::type build_type; }; - static lint_status check_crt_linkage_of_libs(const BuildType& expected_build_type, const std::vector<fs::path>& libs, const fs::path dumpbin_exe) + static lint_status check_crt_linkage_of_libs(const BuildType::type& expected_build_type, const std::vector<fs::path>& libs, const fs::path dumpbin_exe) { - std::vector<BuildType> bad_build_types = BuildType::values(); + std::vector<BuildType::type> bad_build_types(BuildType::values.cbegin(), BuildType::values.cend()); bad_build_types.erase(std::remove(bad_build_types.begin(), bad_build_types.end(), expected_build_type), bad_build_types.end()); std::vector<BuildType_and_file> libs_with_invalid_crt; @@ -515,7 +498,7 @@ namespace vcpkg::PostBuildLint System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(cmd_line); Checks::check_exit(ec_data.exit_code == 0, "Running command:\n %s\n failed", Strings::utf16_to_utf8(cmd_line)); - for (const BuildType& bad_build_type : bad_build_types) + for (const BuildType::type& bad_build_type : bad_build_types) { if (std::regex_search(ec_data.output.cbegin(), ec_data.output.cend(), bad_build_type.crt_regex())) { @@ -546,6 +529,8 @@ namespace vcpkg::PostBuildLint { fs::path file; OutdatedDynamicCrt outdated_crt; + + OutdatedDynamicCrt_and_file() = delete; }; static lint_status check_outdated_crt_linkage_of_dlls(const std::vector<fs::path>& dlls, const fs::path dumpbin_exe) @@ -616,6 +601,7 @@ namespace vcpkg::PostBuildLint left += static_cast<size_t>(right); } + static size_t perform_all_checks_and_return_error_count(const package_spec& spec, const vcpkg_paths& paths) { const fs::path dumpbin_exe = Environment::get_dumpbin_exe(paths); @@ -657,9 +643,9 @@ namespace vcpkg::PostBuildLint error_count += check_lib_architecture(spec.target_triplet().architecture(), libs); - switch (linkage_type_value_of(build_info.library_linkage)) + switch (build_info.library_linkage) { - case LinkageType::DYNAMIC: + case LinkageType::backing_enum_t::DYNAMIC: { const std::vector<fs::path> debug_dlls = Files::recursive_find_files_with_extension_in_dir(debug_bin_dir, ".dll"); const std::vector<fs::path> release_dlls = Files::recursive_find_files_with_extension_in_dir(release_bin_dir, ".dll"); @@ -680,7 +666,7 @@ namespace vcpkg::PostBuildLint error_count += check_outdated_crt_linkage_of_dlls(dlls, dumpbin_exe); break; } - case LinkageType::STATIC: + case LinkageType::backing_enum_t::STATIC: { std::vector<fs::path> dlls; Files::recursive_find_files_with_extension_in_dir(package_dir, ".dll", &dlls); @@ -688,23 +674,14 @@ namespace vcpkg::PostBuildLint error_count += check_bin_folders_are_not_present_in_static_build(package_dir); - error_count += check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::DEBUG, linkage_type_value_of(build_info.crt_linkage)), debug_libs, dumpbin_exe); - error_count += check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::RELEASE, linkage_type_value_of(build_info.crt_linkage)), release_libs, dumpbin_exe); - break; - } - case LinkageType::UNKNOWN: - { - error_count += 1; - System::println(System::color::warning, "Unknown library_linkage architecture: [ %s ]", build_info.library_linkage); + error_count += check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::DEBUG, build_info.crt_linkage), debug_libs, dumpbin_exe); + error_count += check_crt_linkage_of_libs(BuildType::value_of(ConfigurationType::RELEASE, build_info.crt_linkage), release_libs, dumpbin_exe); break; } + case LinkageType::backing_enum_t::NULLVALUE: default: Checks::unreachable(); } -#if 0 - error_count += check_no_subdirectories(package_dir / "lib"); - error_count += check_no_subdirectories(package_dir / "debug" / "lib"); -#endif error_count += check_no_empty_folders(package_dir); error_count += check_no_files_in_package_dir_and_debug_dir(package_dir); @@ -712,19 +689,18 @@ namespace vcpkg::PostBuildLint return error_count; } - void perform_all_checks(const package_spec& spec, const vcpkg_paths& paths) + size_t perform_all_checks(const package_spec& spec, const vcpkg_paths& paths) { System::println("-- Performing post-build validation"); - const size_t error_count = perform_all_checks_and_return_error_count(spec, paths); + System::println("-- Performing post-build validation done"); if (error_count != 0) { const fs::path portfile = paths.ports / spec.name() / "portfile.cmake"; System::println(System::color::error, "Found %u error(s). Please correct the portfile:\n %s", error_count, portfile.string()); - exit(EXIT_FAILURE); } - System::println("-- Performing post-build validation done"); + return error_count; } } diff --git a/toolsrc/src/PostBuildLint_BuildInfo.cpp b/toolsrc/src/PostBuildLint_BuildInfo.cpp index 63107acd1..7308c9bac 100644 --- a/toolsrc/src/PostBuildLint_BuildInfo.cpp +++ b/toolsrc/src/PostBuildLint_BuildInfo.cpp @@ -16,14 +16,19 @@ namespace vcpkg::PostBuildLint BuildInfo BuildInfo::create(std::unordered_map<std::string, std::string> pgh) { BuildInfo build_info; - build_info.crt_linkage = details::remove_required_field(&pgh, BuildInfoRequiredField::CRT_LINKAGE); - build_info.library_linkage = details::remove_required_field(&pgh, BuildInfoRequiredField::LIBRARY_LINKAGE); + const std::string crt_linkage_as_string = details::remove_required_field(&pgh, BuildInfoRequiredField::CRT_LINKAGE); + build_info.crt_linkage = LinkageType::value_of(crt_linkage_as_string); + Checks::check_exit(build_info.crt_linkage != LinkageType::NULLVALUE, "Invalid crt linkage type: [%s]", crt_linkage_as_string); + + const std::string library_linkage_as_string = details::remove_required_field(&pgh, BuildInfoRequiredField::LIBRARY_LINKAGE); + build_info.library_linkage = LinkageType::value_of(library_linkage_as_string); + Checks::check_exit(build_info.library_linkage != LinkageType::NULLVALUE, "Invalid library linkage type: [%s]", library_linkage_as_string); // The remaining entries are policies for (const std::unordered_map<std::string, std::string>::value_type& p : pgh) { const BuildPolicies::type policy = BuildPolicies::parse(p.first); - Checks::check_exit(policy != BuildPolicies::UNKNOWN, "Unknown policy found: %s", p.first); + Checks::check_exit(policy != BuildPolicies::NULLVALUE, "Unknown policy found: %s", p.first); const opt_bool_t status = opt_bool::parse(p.second); build_info.policies.emplace(policy, status); } diff --git a/toolsrc/src/PostBuildLint_BuildPolicies.cpp b/toolsrc/src/PostBuildLint_BuildPolicies.cpp index 4e5ac3cea..53dfcf95a 100644 --- a/toolsrc/src/PostBuildLint_BuildPolicies.cpp +++ b/toolsrc/src/PostBuildLint_BuildPolicies.cpp @@ -1,10 +1,11 @@ #include "pch.h" #include "PostBuildLint_BuildPolicies.h" -#include "vcpkg_Checks.h" +#include "vcpkg_Enums.h" namespace vcpkg::PostBuildLint::BuildPolicies { - static const std::string NAME_UNKNOWN = "PolicyUnknown"; + static const std::string NULLVALUE_STRING = Enums::nullvalue_toString(ENUM_NAME); + static const std::string NAME_EMPTY_PACKAGE = "PolicyEmptyPackage"; static const std::string NAME_DLLS_WITHOUT_LIBS = "PolicyDLLsWithoutLIBs"; @@ -16,10 +17,10 @@ namespace vcpkg::PostBuildLint::BuildPolicies return NAME_EMPTY_PACKAGE; case DLLS_WITHOUT_LIBS: return NAME_DLLS_WITHOUT_LIBS; - case UNKNOWN: - return NAME_UNKNOWN; + case NULLVALUE: + return NULLVALUE_STRING; default: - Checks::unreachable(); + Enums::unreachable(ENUM_NAME); } } @@ -34,21 +35,13 @@ namespace vcpkg::PostBuildLint::BuildPolicies return CMAKE_VARIABLE_EMPTY_PACKAGE; case DLLS_WITHOUT_LIBS: return CMAKE_VARIABLE_DLLS_WITHOUT_LIBS; - case UNKNOWN: - Checks::exit_with_message("No CMake command corresponds to UNKNOWN"); + case NULLVALUE: + Enums::nullvalue_used(ENUM_NAME); default: - Checks::unreachable(); + Enums::unreachable(ENUM_NAME); } } - type::type(): backing_enum(backing_enum_t::UNKNOWN) {} - - const std::vector<type>& values() - { - static const std::vector<type>& v = {UNKNOWN, EMPTY_PACKAGE, DLLS_WITHOUT_LIBS}; - return v; - } - type parse(const std::string& s) { if (s == NAME_EMPTY_PACKAGE) @@ -61,6 +54,6 @@ namespace vcpkg::PostBuildLint::BuildPolicies return BuildPolicies::DLLS_WITHOUT_LIBS; } - return BuildPolicies::UNKNOWN; + return BuildPolicies::NULLVALUE; } } diff --git a/toolsrc/src/PostBuildLint_BuildType.cpp b/toolsrc/src/PostBuildLint_BuildType.cpp index b4e199aee..f2fb292d7 100644 --- a/toolsrc/src/PostBuildLint_BuildType.cpp +++ b/toolsrc/src/PostBuildLint_BuildType.cpp @@ -1,15 +1,10 @@ #include "pch.h" #include "PostBuildLint_BuildType.h" -#include "vcpkg_Checks.h" +#include "vcpkg_Enums.h" -namespace vcpkg::PostBuildLint +namespace vcpkg::PostBuildLint::BuildType { - const BuildType BuildType::DEBUG_STATIC = BuildType(ConfigurationType::DEBUG, LinkageType::STATIC, R"(/DEFAULTLIB:LIBCMTD)"); - const BuildType BuildType::DEBUG_DYNAMIC = BuildType(ConfigurationType::DEBUG, LinkageType::DYNAMIC, R"(/DEFAULTLIB:MSVCRTD)"); - const BuildType BuildType::RELEASE_STATIC = BuildType(ConfigurationType::RELEASE, LinkageType::STATIC, R"(/DEFAULTLIB:LIBCMT[^D])"); - const BuildType BuildType::RELEASE_DYNAMIC = BuildType(ConfigurationType::RELEASE, LinkageType::DYNAMIC, R"(/DEFAULTLIB:MSVCRT[^D])"); - - BuildType BuildType::value_of(const ConfigurationType& config, const LinkageType& linkage) + type value_of(const ConfigurationType::type& config, const LinkageType::type& linkage) { if (config == ConfigurationType::DEBUG && linkage == LinkageType::STATIC) { @@ -31,38 +26,60 @@ namespace vcpkg::PostBuildLint return RELEASE_DYNAMIC; } - Checks::unreachable(); + Enums::unreachable(ENUM_NAME); } - const ConfigurationType& BuildType::config() const + const ConfigurationType::type& type::config() const { return this->m_config; } - const LinkageType& BuildType::linkage() const + const LinkageType::type& type::linkage() const { return this->m_linkage; } - std::regex BuildType::crt_regex() const + const std::regex& type::crt_regex() const { - const std::regex r(this->m_crt_regex_as_string, std::regex_constants::icase); - return r; - } + static const std::regex REGEX_DEBUG_STATIC(R"(/DEFAULTLIB:LIBCMTD)", std::regex_constants::icase); + static const std::regex REGEX_DEBUG_DYNAMIC(R"(/DEFAULTLIB:MSVCRTD)", std::regex_constants::icase); + static const std::regex REGEX_RELEASE_STATIC(R"(/DEFAULTLIB:LIBCMT[^D])", std::regex_constants::icase); + static const std::regex REGEX_RELEASE_DYNAMIC(R"(/DEFAULTLIB:MSVCRT[^D])", std::regex_constants::icase); - std::string BuildType::toString() const - { - const std::string s = Strings::format("[%s,%s]", to_string(this->m_config), to_string(this->m_linkage)); - return s; + switch (backing_enum) + { + case BuildType::DEBUG_STATIC: + return REGEX_DEBUG_STATIC; + case BuildType::DEBUG_DYNAMIC: + return REGEX_DEBUG_DYNAMIC; + case BuildType::RELEASE_STATIC: + return REGEX_RELEASE_STATIC; + case BuildType::RELEASE_DYNAMIC: + return REGEX_RELEASE_DYNAMIC; + default: + Enums::unreachable(ENUM_NAME); + } } - bool operator==(const BuildType& lhs, const BuildType& rhs) + const std::string& type::toString() const { - return lhs.config() == rhs.config() && lhs.linkage() == rhs.linkage(); - } + static const std::string NAME_DEBUG_STATIC("Debug,Static"); + static const std::string NAME_DEBUG_DYNAMIC("Debug,Dynamic"); + static const std::string NAME_RELEASE_STATIC("Release,Static"); + static const std::string NAME_RELEASE_DYNAMIC("Release,Dynamic"); - bool operator!=(const BuildType& lhs, const BuildType& rhs) - { - return !(lhs == rhs); + switch (backing_enum) + { + case BuildType::DEBUG_STATIC: + return NAME_DEBUG_STATIC; + case BuildType::DEBUG_DYNAMIC: + return NAME_DEBUG_DYNAMIC; + case BuildType::RELEASE_STATIC: + return NAME_RELEASE_STATIC; + case BuildType::RELEASE_DYNAMIC: + return NAME_RELEASE_DYNAMIC; + default: + Enums::unreachable(ENUM_NAME); + } } } diff --git a/toolsrc/src/PostBuildLint_ConfigurationType.cpp b/toolsrc/src/PostBuildLint_ConfigurationType.cpp index 9c3499cac..990b10a37 100644 --- a/toolsrc/src/PostBuildLint_ConfigurationType.cpp +++ b/toolsrc/src/PostBuildLint_ConfigurationType.cpp @@ -1,19 +1,26 @@ #include "pch.h" #include "PostBuildLint_ConfigurationType.h" -#include "vcpkg_Checks.h" +#include "vcpkg_Enums.h" -namespace vcpkg::PostBuildLint +namespace vcpkg::PostBuildLint::ConfigurationType { - std::string to_string(const ConfigurationType& conf) + static const std::string NULLVALUE_STRING = Enums::nullvalue_toString(ENUM_NAME); + + static const std::string NAME_DEBUG = "Debug"; + static const std::string NAME_RELEASE = "Release"; + + const std::string& type::toString() const { - switch (conf) + switch (this->backing_enum) { - case ConfigurationType::DEBUG: - return "Debug"; - case ConfigurationType::RELEASE: - return "Release"; - default: - Checks::unreachable(); + case ConfigurationType::DEBUG: + return NAME_DEBUG; + case ConfigurationType::RELEASE: + return NAME_RELEASE; + case ConfigurationType::NULLVALUE: + return NULLVALUE_STRING; + default: + Enums::unreachable(ENUM_NAME); } } } diff --git a/toolsrc/src/PostBuildLint_LinkageType.cpp b/toolsrc/src/PostBuildLint_LinkageType.cpp index 8a3f35be8..6d2c2c935 100644 --- a/toolsrc/src/PostBuildLint_LinkageType.cpp +++ b/toolsrc/src/PostBuildLint_LinkageType.cpp @@ -1,34 +1,41 @@ #include "pch.h" #include "PostBuildLint_LinkageType.h" -#include "vcpkg_Checks.h" +#include "vcpkg_Enums.h" -namespace vcpkg::PostBuildLint +namespace vcpkg::PostBuildLint::LinkageType { - LinkageType linkage_type_value_of(const std::string& as_string) + static const std::string NULLVALUE_STRING = Enums::nullvalue_toString(ENUM_NAME); + + static const std::string NAME_DYNAMIC = "dynamic"; + static const std::string NAME_STATIC = "static"; + + const std::string& type::toString() const { - if (as_string == "dynamic") + switch (this->backing_enum) { - return LinkageType::DYNAMIC; + case LinkageType::DYNAMIC: + return NAME_DYNAMIC; + case LinkageType::STATIC: + return NAME_STATIC; + case LinkageType::NULLVALUE: + return NULLVALUE_STRING; + default: + Enums::unreachable(ENUM_NAME); } + } - if (as_string == "static") + type value_of(const std::string& as_string) + { + if (as_string == NAME_DYNAMIC) { - return LinkageType::STATIC; + return LinkageType::DYNAMIC; } - return LinkageType::UNKNOWN; - } - - std::string to_string(const LinkageType& build_info) - { - switch (build_info) + if (as_string == NAME_STATIC) { - case LinkageType::STATIC: - return "static"; - case LinkageType::DYNAMIC: - return "dynamic"; - default: - Checks::unreachable(); + return LinkageType::STATIC; } + + return LinkageType::NULLVALUE; } } diff --git a/toolsrc/src/StatusParagraphs.cpp b/toolsrc/src/StatusParagraphs.cpp index c2398d2b8..48bc0b062 100644 --- a/toolsrc/src/StatusParagraphs.cpp +++ b/toolsrc/src/StatusParagraphs.cpp @@ -29,9 +29,9 @@ namespace vcpkg }); } - StatusParagraphs::iterator StatusParagraphs::find_installed(const std::string& name, const triplet& target_triplet) + StatusParagraphs::const_iterator StatusParagraphs::find_installed(const std::string& name, const triplet& target_triplet) const { - auto it = find(name, target_triplet); + const const_iterator it = find(name, target_triplet); if (it != end() && (*it)->want == want_t::install) { return it; diff --git a/toolsrc/src/commands_available_commands.cpp b/toolsrc/src/commands_available_commands.cpp index 56056218b..4c7e0df2c 100644 --- a/toolsrc/src/commands_available_commands.cpp +++ b/toolsrc/src/commands_available_commands.cpp @@ -7,6 +7,7 @@ namespace vcpkg::Commands { static std::vector<package_name_and_function<command_type_a>> t = { {"install", &Install::perform_and_exit}, + { "ci", &CI::perform_and_exit }, {"remove", &Remove::perform_and_exit}, {"build", &Build::perform_and_exit}, {"build_external", &BuildExternal::perform_and_exit} diff --git a/toolsrc/src/commands_build.cpp b/toolsrc/src/commands_build.cpp index 743be216a..ec4124922 100644 --- a/toolsrc/src/commands_build.cpp +++ b/toolsrc/src/commands_build.cpp @@ -8,7 +8,7 @@ #include "vcpkg_System.h" #include "vcpkg_Environment.h" #include "metrics.h" -#include "vcpkg_info.h" +#include "vcpkg_Enums.h" namespace vcpkg::Commands::Build { @@ -24,10 +24,18 @@ namespace vcpkg::Commands::Build std::ofstream(binary_control_file) << bpgh; } - void build_package(const SourceParagraph& source_paragraph, const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir) + BuildResult build_package(const SourceParagraph& source_paragraph, const package_spec& spec, const vcpkg_paths& paths, const fs::path& port_dir, const StatusParagraphs& status_db) { - Checks::check_exit(spec.name() == source_paragraph.name, "inconsistent arguments to build_internal()"); + Checks::check_exit(spec.name() == source_paragraph.name, "inconsistent arguments to build_package()"); + const triplet& target_triplet = spec.target_triplet(); + for (auto&& dep : source_paragraph.depends) + { + if (status_db.find_installed(dep.name, target_triplet) == status_db.end()) + { + return BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES; + } + } const fs::path ports_cmake_script_path = paths.ports_cmake; const Environment::vcvarsall_and_platform_toolset vcvarsall_bat = Environment::get_vcvarsall_bat(paths); @@ -48,71 +56,91 @@ namespace vcpkg::Commands::Build if (return_code != 0) { - System::println(System::color::error, "Error: building package %s failed", spec.toString()); - System::println("Please ensure sure you're using the latest portfiles with `.\\vcpkg update`, then\n" - "submit an issue at https://github.com/Microsoft/vcpkg/issues including:\n" - " Package: %s\n" - " Vcpkg version: %s\n" - "\n" - "Additionally, attach any relevant sections from the log files above." - , spec.toString(), Info::version()); TrackProperty("error", "build failed"); TrackProperty("build_error", spec.toString()); - exit(EXIT_FAILURE); + return BuildResult::BUILD_FAILED; } - PostBuildLint::perform_all_checks(spec, paths); + const size_t error_count = PostBuildLint::perform_all_checks(spec, paths); + + if (error_count != 0) + { + return BuildResult::POST_BUILD_CHECKS_FAILED; + } create_binary_control_file(paths, source_paragraph, target_triplet); // const fs::path port_buildtrees_dir = paths.buildtrees / spec.name; // delete_directory(port_buildtrees_dir); + + return BuildResult::SUCCEEDED; } - void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet) + const std::string& to_string(const BuildResult build_result) { - static const std::string example = Commands::Help::create_example_string("build zlib:x64-windows"); + static const std::string NULLVALUE_STRING = Enums::nullvalue_toString("vcpkg::Commands::Build::BuildResult"); + static const std::string SUCCEEDED_STRING = "SUCCEEDED"; + static const std::string BUILD_FAILED_STRING = "BUILD_FAILED"; + static const std::string POST_BUILD_CHECKS_FAILED_STRING = "POST_BUILD_CHECKS_FAILED"; + static const std::string CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING = "CASCADED_DUE_TO_MISSING_DEPENDENCIES"; - // Installing multiple packages leads to unintuitive behavior if one of them depends on another. - // Allowing only 1 package for now. - - args.check_exact_arg_count(1, example); + switch (build_result) + { + case BuildResult::NULLVALUE: return NULLVALUE_STRING; + case BuildResult::SUCCEEDED: return SUCCEEDED_STRING; + case BuildResult::BUILD_FAILED: return BUILD_FAILED_STRING; + case BuildResult::POST_BUILD_CHECKS_FAILED: return POST_BUILD_CHECKS_FAILED_STRING; + case BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES: return CASCADED_DUE_TO_MISSING_DEPENDENCIES_STRING; + default: Checks::unreachable(); + } + } - StatusParagraphs status_db = database_load_check(paths); + std::string create_error_message(const BuildResult build_result, const package_spec& spec) + { + return Strings::format("Error: Building package %s failed with: %s", spec.toString(), Build::to_string(build_result)); + } - const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example); - Input::check_triplet(spec.target_triplet(), paths); + std::string create_user_troubleshooting_message(const package_spec& spec) + { + return Strings::format("Please ensure sure you're using the latest portfiles with `.\\vcpkg update`, then\n" + "submit an issue at https://github.com/Microsoft/vcpkg/issues including:\n" + " Package: %s\n" + " Vcpkg version: %s\n" + "\n" + "Additionally, attach any relevant sections from the log files above." + , spec.toString(), Version::version()); + } - const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_CHECKS_ONLY}); + void perform_and_exit(const package_spec& spec, const fs::path& port_dir, const std::unordered_set<std::string>& options, const vcpkg_paths& paths) + { if (options.find(OPTION_CHECKS_ONLY) != options.end()) { - PostBuildLint::perform_all_checks(spec, paths); + const size_t error_count = PostBuildLint::perform_all_checks(spec, paths); + if (error_count > 0) + { + exit(EXIT_FAILURE); + } exit(EXIT_SUCCESS); } - // Explicitly load and use the portfile's build dependencies when resolving the build command (instead of a cached package's dependencies). - const expected<SourceParagraph> maybe_spgh = try_load_port(paths, spec.name()); + const expected<SourceParagraph> maybe_spgh = try_load_port(port_dir); Checks::check_exit(!maybe_spgh.error_code(), "Could not find package named %s: %s", spec, maybe_spgh.error_code().message()); const SourceParagraph& spgh = *maybe_spgh.get(); - const std::vector<std::string> first_level_deps = filter_dependencies(spgh.depends, spec.target_triplet()); - - std::vector<package_spec> first_level_deps_specs; - for (const std::string& dep : first_level_deps) - { - first_level_deps_specs.push_back(package_spec::from_name_and_triplet(dep, spec.target_triplet()).get_or_throw()); - } - - std::vector<package_spec_with_install_plan> unmet_dependencies = Dependencies::create_install_plan(paths, first_level_deps_specs, status_db); - unmet_dependencies.erase( - std::remove_if(unmet_dependencies.begin(), unmet_dependencies.end(), [](const package_spec_with_install_plan& p) - { - return p.plan.plan_type == install_plan_type::ALREADY_INSTALLED; - }), - unmet_dependencies.end()); - - if (!unmet_dependencies.empty()) + Environment::ensure_utilities_on_path(paths); + StatusParagraphs status_db = database_load_check(paths); + const BuildResult result = build_package(spgh, spec, paths, paths.port_dir(spec), status_db); + if (result == BuildResult::CASCADED_DUE_TO_MISSING_DEPENDENCIES) { + std::vector<package_spec_with_install_plan> unmet_dependencies = Dependencies::create_install_plan(paths, { spec }, status_db); + unmet_dependencies.erase( + std::remove_if(unmet_dependencies.begin(), unmet_dependencies.end(), [&spec](const package_spec_with_install_plan& p) + { + return (p.spec == spec) || (p.plan.plan_type == install_plan_type::ALREADY_INSTALLED); + }), + unmet_dependencies.end()); + + Checks::check_exit(!unmet_dependencies.empty()); System::println(System::color::error, "The build command requires all dependencies to be already installed."); System::println("The following dependencies are missing:"); System::println(""); @@ -124,8 +152,23 @@ namespace vcpkg::Commands::Build exit(EXIT_FAILURE); } - Environment::ensure_utilities_on_path(paths); - build_package(spgh, spec, paths, paths.port_dir(spec)); + if (result != BuildResult::SUCCEEDED) + { + System::println(System::color::error, Build::create_error_message(result, spec)); + System::println(Build::create_user_troubleshooting_message(spec)); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); } + + void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet) + { + static const std::string example = Commands::Help::create_example_string("build zlib:x64-windows"); + args.check_exact_arg_count(1, example); // Build only takes a single package and all dependencies must already be installed + const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example); + Input::check_triplet(spec.target_triplet(), paths); + const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({ OPTION_CHECKS_ONLY }); + perform_and_exit(spec, paths.port_dir(spec), options, paths); + } } diff --git a/toolsrc/src/commands_build_external.cpp b/toolsrc/src/commands_build_external.cpp index 5c3fa9857..06bd1374c 100644 --- a/toolsrc/src/commands_build_external.cpp +++ b/toolsrc/src/commands_build_external.cpp @@ -3,7 +3,6 @@ #include "vcpkg_System.h" #include "vcpkg_Environment.h" #include "vcpkg_Input.h" -#include "vcpkglib.h" namespace vcpkg::Commands::BuildExternal { @@ -11,23 +10,11 @@ namespace vcpkg::Commands::BuildExternal { static const std::string example = Commands::Help::create_example_string(R"(build_external zlib2 C:\path\to\dir\with\controlfile\)"); args.check_exact_arg_count(2, example); + const package_spec spec = Input::check_and_get_package_spec(args.command_arguments.at(0), default_target_triplet, example); + Input::check_triplet(spec.target_triplet(), paths); + const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({}); - expected<package_spec> maybe_current_spec = package_spec::from_string(args.command_arguments[0], default_target_triplet); - if (auto spec = maybe_current_spec.get()) - { - Input::check_triplet(spec->target_triplet(), paths); - Environment::ensure_utilities_on_path(paths); - const fs::path port_dir = args.command_arguments.at(1); - const expected<SourceParagraph> maybe_spgh = try_load_port(port_dir); - if (auto spgh = maybe_spgh.get()) - { - Commands::Build::build_package(*spgh, *spec, paths, port_dir); - exit(EXIT_SUCCESS); - } - } - - System::println(System::color::error, "Error: %s: %s", maybe_current_spec.error_code().message(), args.command_arguments[0]); - Commands::Help::print_example(Strings::format("%s zlib:x64-windows", args.command)); - exit(EXIT_FAILURE); + const fs::path port_dir = args.command_arguments.at(1); + Build::perform_and_exit(spec, port_dir, options, paths); } } diff --git a/toolsrc/src/commands_cache.cpp b/toolsrc/src/commands_cache.cpp index fa49a647f..e255b5dff 100644 --- a/toolsrc/src/commands_cache.cpp +++ b/toolsrc/src/commands_cache.cpp @@ -40,6 +40,7 @@ namespace vcpkg::Commands::Cache static const std::string example = Strings::format( "The argument should be a substring to search for, or no argument to display all cached libraries.\n%s", Commands::Help::create_example_string("cache png")); args.check_max_arg_count(1, example); + args.check_and_get_optional_command_arguments({}); const std::vector<BinaryParagraph> binary_paragraphs = read_all_binary_paragraphs(paths); if (binary_paragraphs.empty()) diff --git a/toolsrc/src/commands_ci.cpp b/toolsrc/src/commands_ci.cpp new file mode 100644 index 000000000..db37db123 --- /dev/null +++ b/toolsrc/src/commands_ci.cpp @@ -0,0 +1,124 @@ +#include "pch.h" +#include "vcpkg_Commands.h" +#include "vcpkglib.h" +#include "vcpkg_Environment.h" +#include "vcpkg_Files.h" +#include "vcpkg_System.h" +#include "vcpkg_Dependencies.h" +#include "vcpkg_Input.h" +#include "vcpkg_Chrono.h" + +namespace vcpkg::Commands::CI +{ + using Dependencies::package_spec_with_install_plan; + using Dependencies::install_plan_type; + using Build::BuildResult; + + static std::vector<package_spec> load_all_package_specs(const fs::path& directory, const triplet& target_triplet) + { + std::vector<fs::path> port_folders; + Files::non_recursive_find_matching_paths_in_dir(directory, [](const fs::path& current) + { + return fs::is_directory(current); + }, &port_folders); + + std::vector<package_spec> specs; + for (const fs::path& p : port_folders) + { + specs.push_back(package_spec::from_name_and_triplet(p.filename().generic_string(), target_triplet).get_or_throw()); + } + + return specs; + } + + void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths, const triplet& default_target_triplet) + { + static const std::string example = Commands::Help::create_example_string("ci x64-windows"); + args.check_max_arg_count(1, example); + const triplet target_triplet = args.command_arguments.size() == 1 ? triplet::from_canonical_name(args.command_arguments.at(0)) : default_target_triplet; + Input::check_triplet(target_triplet, paths); + args.check_and_get_optional_command_arguments({}); + const std::vector<package_spec> specs = load_all_package_specs(paths.ports, target_triplet); + + StatusParagraphs status_db = database_load_check(paths); + const std::vector<package_spec_with_install_plan> install_plan = Dependencies::create_install_plan(paths, specs, status_db); + Checks::check_exit(!install_plan.empty(), "Install plan cannot be empty"); + + Environment::ensure_utilities_on_path(paths); + + std::vector<BuildResult> results; + const ElapsedTime timer = ElapsedTime::createStarted(); + size_t counter = 0; + const size_t package_count = install_plan.size(); + for (const package_spec_with_install_plan& action : install_plan) + { + counter++; + System::println("Starting package %d/%d: %s. Time Elapsed: %s", counter, package_count, action.spec.toString(), timer.toString()); + try + { + if (action.plan.plan_type == install_plan_type::ALREADY_INSTALLED) + { + results.push_back(BuildResult::SUCCEEDED); + System::println(System::color::success, "Package %s is already installed", action.spec); + } + else if (action.plan.plan_type == install_plan_type::BUILD_AND_INSTALL) + { + const BuildResult result = Commands::Build::build_package(*action.plan.source_pgh, action.spec, paths, paths.port_dir(action.spec), status_db); + results.push_back(result); + if (result != BuildResult::SUCCEEDED) + { + System::println(System::color::error, Build::create_error_message(result, action.spec)); + continue; + } + const BinaryParagraph bpgh = try_load_cached_package(paths, action.spec).get_or_throw(); + Install::install_package(paths, bpgh, &status_db); + System::println(System::color::success, "Package %s is installed", action.spec); + } + else if (action.plan.plan_type == install_plan_type::INSTALL) + { + results.push_back(BuildResult::SUCCEEDED); + Install::install_package(paths, *action.plan.binary_pgh, &status_db); + System::println(System::color::success, "Package %s is installed", action.spec); + } + else + Checks::unreachable(); + } + catch (const std::exception& e) + { + System::println(System::color::error, "Error: Could not install package %s: %s", action.spec, e.what()); + exit(EXIT_FAILURE); + } + } + + System::println(timer.toString()); + + for (size_t i = 0; i < results.size(); i++) + { + if (results[i] == BuildResult::SUCCEEDED) + { + continue; + } + + System::println("%s: %s", install_plan[i].spec.toString(), Build::to_string(results[i])); + } + + std::map<BuildResult, int> summary; + for (const BuildResult& v : Build::BuildResult_values) + { + summary[v] = 0; + } + + for (const BuildResult& r : results) + { + summary[r]++; + } + + System::println("\n\nSUMMARY"); + for (const std::pair<const BuildResult, int>& entry : summary) + { + System::println(" %s: %d", Build::to_string(entry.first), entry.second); + } + + exit(EXIT_SUCCESS); + } +} diff --git a/toolsrc/src/commands_contact.cpp b/toolsrc/src/commands_contact.cpp index 2be468fb8..29f0d4d27 100644 --- a/toolsrc/src/commands_contact.cpp +++ b/toolsrc/src/commands_contact.cpp @@ -1,14 +1,21 @@ #include "pch.h" #include "vcpkg_Commands.h" #include "vcpkg_System.h" -#include "vcpkg_info.h" namespace vcpkg::Commands::Contact { - void perform_and_exit(const vcpkg_cmd_arguments& args) + const std::string& email() + { + static const std::string s_email = R"(vcpkg@microsoft.com)"; + return s_email; + } + + void perform_and_exit(const vcpkg_cmd_arguments& args) { args.check_exact_arg_count(0); - System::println("Send an email to %s with any feedback.", Info::email()); + args.check_and_get_optional_command_arguments({}); + + System::println("Send an email to %s with any feedback.", email()); exit(EXIT_SUCCESS); } } diff --git a/toolsrc/src/commands_create.cpp b/toolsrc/src/commands_create.cpp index 5042ab97b..494c2aa08 100644 --- a/toolsrc/src/commands_create.cpp +++ b/toolsrc/src/commands_create.cpp @@ -12,8 +12,9 @@ namespace vcpkg::Commands::Create static const std::string example = Commands::Help::create_example_string(R"###(create zlib2 http://zlib.net/zlib128.zip "zlib128-2.zip")###"); args.check_max_arg_count(3, example); args.check_min_arg_count(2, example); - + args.check_and_get_optional_command_arguments({}); const std::string port_name = args.command_arguments.at(0); + Environment::ensure_utilities_on_path(paths); // Space OR define the FILENAME with proper spacing diff --git a/toolsrc/src/commands_edit.cpp b/toolsrc/src/commands_edit.cpp index dff30f7ad..5a2433e5a 100644 --- a/toolsrc/src/commands_edit.cpp +++ b/toolsrc/src/commands_edit.cpp @@ -2,6 +2,7 @@ #include "vcpkg_Commands.h" #include "vcpkg_System.h" #include "vcpkg_Input.h" +#include "vcpkg_Environment.h" namespace vcpkg::Commands::Edit { @@ -9,16 +10,23 @@ namespace vcpkg::Commands::Edit { static const std::string example = Commands::Help::create_example_string("edit zlib"); args.check_exact_arg_count(1, example); + args.check_and_get_optional_command_arguments({}); const std::string port_name = args.command_arguments.at(0); const fs::path portpath = paths.ports / port_name; Checks::check_exit(fs::is_directory(portpath), R"(Could not find port named "%s")", port_name); // Find editor - std::wstring env_EDITOR = System::wdupenv_str(L"EDITOR"); - if (env_EDITOR.empty()) + const optional<std::wstring> env_EDITOR_optional = System::get_environmental_variable(L"EDITOR"); + std::wstring env_EDITOR; + + if (env_EDITOR_optional) + { + env_EDITOR = *env_EDITOR_optional; + } + else { - static const std::wstring CODE_EXE_PATH = LR"(C:\Program Files (x86)\Microsoft VS Code\Code.exe)"; + static const fs::path CODE_EXE_PATH = Environment::get_ProgramFiles_32_bit() / "Microsoft VS Code/Code.exe"; if (fs::exists(CODE_EXE_PATH)) { env_EDITOR = CODE_EXE_PATH; diff --git a/toolsrc/src/commands_hash.cpp b/toolsrc/src/commands_hash.cpp index 4c0028f53..805da4153 100644 --- a/toolsrc/src/commands_hash.cpp +++ b/toolsrc/src/commands_hash.cpp @@ -30,6 +30,7 @@ namespace vcpkg::Commands::Hash "The argument should be a file path\n%s", Commands::Help::create_example_string("hash boost_1_62_0.tar.bz2")); args.check_min_arg_count(1, example); args.check_max_arg_count(2, example); + args.check_and_get_optional_command_arguments({}); if (args.command_arguments.size() == 1) { diff --git a/toolsrc/src/commands_help.cpp b/toolsrc/src/commands_help.cpp index 6068c22fb..49b5697c3 100644 --- a/toolsrc/src/commands_help.cpp +++ b/toolsrc/src/commands_help.cpp @@ -67,6 +67,8 @@ namespace vcpkg::Commands::Help void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths) { args.check_max_arg_count(1); + args.check_and_get_optional_command_arguments({}); + if (args.command_arguments.empty()) { print_usage(); diff --git a/toolsrc/src/commands_import.cpp b/toolsrc/src/commands_import.cpp index 7af2c7185..4b71fc290 100644 --- a/toolsrc/src/commands_import.cpp +++ b/toolsrc/src/commands_import.cpp @@ -79,6 +79,7 @@ namespace vcpkg::Commands::Import { static const std::string example = Commands::Help::create_example_string(R"(import C:\path\to\CONTROLfile C:\path\to\includedir C:\path\to\projectdir)"); args.check_exact_arg_count(3, example); + args.check_and_get_optional_command_arguments({}); const fs::path control_file_path(args.command_arguments[0]); const fs::path include_directory(args.command_arguments[1]); diff --git a/toolsrc/src/commands_install.cpp b/toolsrc/src/commands_install.cpp index 1f5a2234d..4ae311f83 100644 --- a/toolsrc/src/commands_install.cpp +++ b/toolsrc/src/commands_install.cpp @@ -24,7 +24,7 @@ namespace vcpkg::Commands::Install const std::string& target_triplet_as_string = target_triplet.canonical_name(); std::error_code ec; fs::create_directory(paths.installed / target_triplet_as_string, ec); - output.push_back(Strings::format(R"(%s)", target_triplet_as_string)); + output.push_back(Strings::format(R"(%s/)", target_triplet_as_string)); for (auto it = fs::recursive_directory_iterator(package_prefix_path); it != fs::recursive_directory_iterator(); ++it) { @@ -54,7 +54,7 @@ namespace vcpkg::Commands::Install } // Trailing backslash for directories - output.push_back(Strings::format(R"(%s/%s)", target_triplet_as_string, suffix)); + output.push_back(Strings::format(R"(%s/%s/)", target_triplet_as_string, suffix)); continue; } @@ -82,6 +82,8 @@ namespace vcpkg::Commands::Install System::println(System::color::error, "failed: %s: cannot handle file type", it->path().u8string()); } + std::sort(output.begin(), output.end()); + Files::write_all_lines(paths.listfile_path(bpgh), output); } @@ -185,10 +187,11 @@ namespace vcpkg::Commands::Install { static const std::string example = Commands::Help::create_example_string("install zlib zlib:x64-windows curl boost"); args.check_min_arg_count(1, example); - StatusParagraphs status_db = database_load_check(paths); - std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example); Input::check_triplets(specs, paths); + args.check_and_get_optional_command_arguments({}); + + StatusParagraphs status_db = database_load_check(paths); std::vector<package_spec_with_install_plan> install_plan = Dependencies::create_install_plan(paths, specs, status_db); Checks::check_exit(!install_plan.empty(), "Install plan cannot be empty"); @@ -214,7 +217,13 @@ namespace vcpkg::Commands::Install } else if (action.plan.plan_type == install_plan_type::BUILD_AND_INSTALL) { - Commands::Build::build_package(*action.plan.source_pgh, action.spec, paths, paths.port_dir(action.spec)); + const Build::BuildResult result = Commands::Build::build_package(*action.plan.source_pgh, action.spec, paths, paths.port_dir(action.spec), status_db); + if (result != Build::BuildResult::SUCCEEDED) + { + System::println(System::color::error, Build::create_error_message(result, action.spec)); + System::println(Build::create_user_troubleshooting_message(action.spec)); + exit(EXIT_FAILURE); + } const BinaryParagraph bpgh = try_load_cached_package(paths, action.spec).get_or_throw(); install_package(paths, bpgh, &status_db); System::println(System::color::success, "Package %s is installed", action.spec); diff --git a/toolsrc/src/commands_integrate.cpp b/toolsrc/src/commands_integrate.cpp index 03c51b5a7..94af19e96 100644 --- a/toolsrc/src/commands_integrate.cpp +++ b/toolsrc/src/commands_integrate.cpp @@ -8,10 +8,10 @@ namespace vcpkg::Commands::Integrate { static const std::array<fs::path, 2> old_system_target_files = { - "C:/Program Files (x86)/MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", - "C:/Program Files (x86)/MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets" + Environment::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.nuget.targets", + Environment::get_ProgramFiles_32_bit() / "MSBuild/14.0/Microsoft.Common.Targets/ImportBefore/vcpkg.system.targets" }; - static const fs::path system_wide_targets_file = "C:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; + static const fs::path system_wide_targets_file = Environment::get_ProgramFiles_32_bit() / "MSBuild/Microsoft.Cpp/v4.0/V140/ImportBefore/Default/vcpkg.system.props"; static std::string create_appdata_targets_shortcut(const std::string& target_path) noexcept { @@ -109,7 +109,7 @@ namespace vcpkg::Commands::Integrate static elevation_prompt_user_choice elevated_cmd_execute(const std::string& param) { - SHELLEXECUTEINFO shExInfo = {0}; + SHELLEXECUTEINFO shExInfo = { 0 }; shExInfo.cbSize = sizeof(shExInfo); shExInfo.fMask = SEE_MASK_NOCLOSEPROCESS; shExInfo.hwnd = nullptr; @@ -136,7 +136,7 @@ namespace vcpkg::Commands::Integrate static fs::path get_appdata_targets_path() { - return fs::path(System::wdupenv_str(L"LOCALAPPDATA")) / "vcpkg" / "vcpkg.user.targets"; + return fs::path(*System::get_environmental_variable(L"LOCALAPPDATA")) / "vcpkg" / "vcpkg.user.targets"; } static void integrate_install(const vcpkg_paths& paths) @@ -214,10 +214,13 @@ namespace vcpkg::Commands::Integrate exit(EXIT_FAILURE); } System::println(System::color::success, "Applied user-wide integration for this vcpkg root."); + const fs::path cmake_toolchain = paths.buildsystems / "vcpkg.cmake"; System::println("\n" - "All C++ projects can now #include any installed libraries.\n" + "All MSBuild C++ projects can now #include any installed libraries.\n" "Linking will be handled automatically.\n" - "Installing new libraries will make them instantly available."); + "Installing new libraries will make them instantly available.\n" + "\n" + "CMake projects should use -DCMAKE_TOOLCHAIN_FILE=%s", cmake_toolchain.generic_string()); exit(EXIT_SUCCESS); } @@ -293,6 +296,7 @@ With a project open, go to Tools->NuGet Package Manager->Package Manager Console static const std::string example = Strings::format("Commands:\n" "%s", INTEGRATE_COMMAND_HELPSTRING); args.check_exact_arg_count(1, example); + args.check_and_get_optional_command_arguments({}); if (args.command_arguments[0] == "install") { diff --git a/toolsrc/src/commands_list.cpp b/toolsrc/src/commands_list.cpp index 34a9c2fc8..7bfc11f1b 100644 --- a/toolsrc/src/commands_list.cpp +++ b/toolsrc/src/commands_list.cpp @@ -19,6 +19,7 @@ namespace vcpkg::Commands::List static const std::string example = Strings::format( "The argument should be a substring to search for, or no argument to display all installed libraries.\n%s", Commands::Help::create_example_string("list png")); args.check_max_arg_count(1, example); + args.check_and_get_optional_command_arguments({}); const StatusParagraphs status_paragraphs = database_load_check(paths); std::vector<StatusParagraph> installed_packages; diff --git a/toolsrc/src/commands_owns.cpp b/toolsrc/src/commands_owns.cpp index 6c4c20c44..16bb986e2 100644 --- a/toolsrc/src/commands_owns.cpp +++ b/toolsrc/src/commands_owns.cpp @@ -26,6 +26,7 @@ namespace vcpkg::Commands::Owns { static const std::string example = Strings::format("The argument should be a pattern to search for. %s", Commands::Help::create_example_string("owns zlib.dll")); args.check_exact_arg_count(1, example); + args.check_and_get_optional_command_arguments({}); StatusParagraphs status_db = database_load_check(paths); search_file(paths, args.command_arguments[0], status_db); diff --git a/toolsrc/src/commands_portsdiff.cpp b/toolsrc/src/commands_portsdiff.cpp index e75633b3c..119997485 100644 --- a/toolsrc/src/commands_portsdiff.cpp +++ b/toolsrc/src/commands_portsdiff.cpp @@ -98,6 +98,7 @@ namespace vcpkg::Commands::PortsDiff static const std::string example = Strings::format("The argument should be a branch/tag/hash to checkout.\n%s", Commands::Help::create_example_string("portsdiff mybranchname")); args.check_min_arg_count(1, example); args.check_max_arg_count(2, example); + args.check_and_get_optional_command_arguments({}); Environment::ensure_git_on_path(paths); const std::wstring git_commit_id_for_previous_snapshot = Strings::utf8_to_utf16(args.command_arguments.at(0)); diff --git a/toolsrc/src/commands_remove.cpp b/toolsrc/src/commands_remove.cpp index f49104d1e..1daacb944 100644 --- a/toolsrc/src/commands_remove.cpp +++ b/toolsrc/src/commands_remove.cpp @@ -167,16 +167,14 @@ namespace vcpkg::Commands::Remove { static const std::string example = Commands::Help::create_example_string("remove zlib zlib:x64-windows curl boost"); args.check_min_arg_count(1, example); - - const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({OPTION_PURGE, OPTION_RECURSE}); - auto status_db = database_load_check(paths); - std::vector<package_spec> specs = Input::check_and_get_package_specs(args.command_arguments, default_target_triplet, example); Input::check_triplets(specs, paths); + const std::unordered_set<std::string> options = args.check_and_get_optional_command_arguments({ OPTION_PURGE, OPTION_RECURSE }); const bool alsoRemoveFolderFromPackages = options.find(OPTION_PURGE) != options.end(); const bool isRecursive = options.find(OPTION_RECURSE) != options.end(); - const std::vector<package_spec_with_remove_plan> remove_plan = Dependencies::create_remove_plan(paths, specs, status_db); + auto status_db = database_load_check(paths); + const std::vector<package_spec_with_remove_plan> remove_plan = Dependencies::create_remove_plan(specs, status_db); Checks::check_exit(!remove_plan.empty(), "Remove plan cannot be empty"); print_plan(remove_plan); diff --git a/toolsrc/src/commands_search.cpp b/toolsrc/src/commands_search.cpp index 3a3226e4b..5dba71149 100644 --- a/toolsrc/src/commands_search.cpp +++ b/toolsrc/src/commands_search.cpp @@ -46,6 +46,7 @@ namespace vcpkg::Commands::Search static const std::string example = Strings::format("The argument should be a substring to search for, or no argument to display all libraries.\n%s", Commands::Help::create_example_string("search png")); args.check_max_arg_count(1, example); + args.check_and_get_optional_command_arguments({}); const std::vector<SourceParagraph> source_paragraphs = read_all_source_paragraphs(paths); diff --git a/toolsrc/src/commands_update.cpp b/toolsrc/src/commands_update.cpp index a42ae5341..d4519ca14 100644 --- a/toolsrc/src/commands_update.cpp +++ b/toolsrc/src/commands_update.cpp @@ -4,13 +4,13 @@ #include "vcpkg_System.h" #include "vcpkg_Files.h" #include "Paragraphs.h" -#include "vcpkg_info.h" namespace vcpkg::Commands::Update { void perform_and_exit(const vcpkg_cmd_arguments& args, const vcpkg_paths& paths) { args.check_exact_arg_count(0); + args.check_and_get_optional_command_arguments({}); System::println("Using local portfile versions. To update the local portfiles, use `git pull`."); auto status_db = database_load_check(paths); @@ -79,7 +79,7 @@ namespace vcpkg::Commands::Update auto num1 = sscanf_s(version_contents->c_str(), "\"%d.%d.%d\"", &maj1, &min1, &rev1); int maj2, min2, rev2; - auto num2 = sscanf_s(Info::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); + auto num2 = sscanf_s(Version::version().c_str(), "%d.%d.%d-", &maj2, &min2, &rev2); if (num1 == 3 && num2 == 3) { diff --git a/toolsrc/src/commands_version.cpp b/toolsrc/src/commands_version.cpp index a521b2567..4789e2409 100644 --- a/toolsrc/src/commands_version.cpp +++ b/toolsrc/src/commands_version.cpp @@ -1,16 +1,36 @@ #include "pch.h" #include "vcpkg_Commands.h" #include "vcpkg_System.h" -#include "vcpkg_info.h" +#include "metrics.h" + +#define STRINGIFY(...) #__VA_ARGS__ +#define MACRO_TO_STRING(X) STRINGIFY(X) + +#define VCPKG_VERSION_AS_STRING MACRO_TO_STRING(VCPKG_VERSION) namespace vcpkg::Commands::Version { + const std::string& version() + { + static const std::string s_version = +#include "../VERSION.txt" + + + std::string(VCPKG_VERSION_AS_STRING) +#ifndef NDEBUG + + std::string("-debug") +#endif + + std::string(GetCompiledMetricsEnabled() ? "" : "-external"); + return s_version; + } + void perform_and_exit(const vcpkg_cmd_arguments& args) { args.check_exact_arg_count(0); + args.check_and_get_optional_command_arguments({}); + System::println("Vcpkg package management program version %s\n" "\n" - "See LICENSE.txt for license information.", Info::version() + "See LICENSE.txt for license information.", version() ); exit(EXIT_SUCCESS); } diff --git a/toolsrc/src/metrics.cpp b/toolsrc/src/metrics.cpp index 263d6eb74..4ac43c5c6 100644 --- a/toolsrc/src/metrics.cpp +++ b/toolsrc/src/metrics.cpp @@ -32,7 +32,7 @@ namespace vcpkg static std::string GenerateRandomUUID() { - int partSizes[] = {8, 4, 4, 4, 12}; + int partSizes[] = { 8, 4, 4, 4, 12 }; char uuid[37]; memset(uuid, 0, sizeof(uuid)); int num; @@ -101,7 +101,7 @@ namespace vcpkg // Note: this treats incoming Strings as Latin-1 static constexpr const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; encoded.append("\\u00"); encoded.push_back(hex[ch / 16]); encoded.push_back(hex[ch % 16]); @@ -229,8 +229,10 @@ true { LONG err; - struct RAII_HKEY { + struct RAII_HKEY + { HKEY hkey = nullptr; + ~RAII_HKEY() { if (hkey != nullptr) @@ -244,7 +246,7 @@ true return L"{}"; } - std::array<wchar_t,128> buffer; + std::array<wchar_t, 128> buffer; DWORD lType = 0; DWORD dwBufferSize = static_cast<DWORD>(buffer.size() * sizeof(wchar_t)); err = RegQueryValueExW(HKCU_SQMClient.hkey, L"UserId", nullptr, &lType, reinterpret_cast<LPBYTE>(buffer.data()), &dwBufferSize); @@ -356,8 +358,7 @@ true if (bResults) { DWORD availableData = 0, readData = 0, totalData = 0; - - while ((bResults = WinHttpQueryDataAvailable(hRequest, &availableData)) && availableData > 0) + while ((bResults = WinHttpQueryDataAvailable(hRequest, &availableData)) == TRUE && availableData > 0) { responseBuffer.resize(responseBuffer.size() + availableData); diff --git a/toolsrc/src/triplet.cpp b/toolsrc/src/triplet.cpp index e1302d9ed..d91e0e68f 100644 --- a/toolsrc/src/triplet.cpp +++ b/toolsrc/src/triplet.cpp @@ -1,6 +1,7 @@ #include "pch.h" #include "triplet.h" #include "vcpkg_Checks.h" +#include "vcpkg_Strings.h" namespace vcpkg { @@ -37,9 +38,7 @@ namespace vcpkg triplet triplet::from_canonical_name(const std::string& triplet_as_string) { - std::string s(triplet_as_string); - std::transform(s.begin(), s.end(), s.begin(), ::tolower); - + const std::string s(Strings::ascii_to_lowercase(triplet_as_string)); auto it = std::find(s.cbegin(), s.cend(), '-'); Checks::check_exit(it != s.cend(), "Invalid triplet: %s", triplet_as_string); diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp index 3e313c702..f40126ecf 100644 --- a/toolsrc/src/vcpkg.cpp +++ b/toolsrc/src/vcpkg.cpp @@ -12,7 +12,6 @@ #include "vcpkg_System.h" #include "vcpkg_Input.h" #include "Paragraphs.h" -#include "vcpkg_info.h" #include "vcpkg_Strings.h" using namespace vcpkg; @@ -47,11 +46,10 @@ static void inner(const vcpkg_cmd_arguments& args) } else { - auto vcpkg_root_dir_env = System::wdupenv_str(L"VCPKG_ROOT"); - - if (!vcpkg_root_dir_env.empty()) + const optional<std::wstring> vcpkg_root_dir_env = System::get_environmental_variable(L"VCPKG_ROOT"); + if (vcpkg_root_dir_env) { - vcpkg_root_dir = fs::absolute(vcpkg_root_dir_env); + vcpkg_root_dir = fs::absolute(*vcpkg_root_dir_env); } else { @@ -79,10 +77,10 @@ static void inner(const vcpkg_cmd_arguments& args) } else { - const auto vcpkg_default_triplet_env = System::wdupenv_str(L"VCPKG_DEFAULT_TRIPLET"); - if (!vcpkg_default_triplet_env.empty()) + const optional<std::wstring> vcpkg_default_triplet_env = System::get_environmental_variable(L"VCPKG_DEFAULT_TRIPLET"); + if (vcpkg_default_triplet_env) { - default_target_triplet = triplet::from_canonical_name(Strings::utf16_to_utf8(vcpkg_default_triplet_env)); + default_target_triplet = triplet::from_canonical_name(Strings::utf16_to_utf8(*vcpkg_default_triplet_env)); } else { @@ -193,7 +191,7 @@ int wmain(const int argc, const wchar_t* const* const argv) Flush(); }); - TrackProperty("version", Info::version()); + TrackProperty("version", Commands::Version::version()); const std::string trimmed_command_line = trim_path_from_command_line(Strings::utf16_to_utf8(GetCommandLineW())); TrackProperty("cmdline", trimmed_command_line); @@ -236,10 +234,10 @@ int wmain(const int argc, const wchar_t* const* const argv) std::cerr << "vcpkg.exe has crashed.\n" << "Please send an email to:\n" - << " " << Info::email() << "\n" + << " " << Commands::Contact::email() << "\n" << "containing a brief summary of what you were trying to do and the following data blob:\n" << "\n" - << "Version=" << Info::version() << "\n" + << "Version=" << Commands::Version::version() << "\n" << "EXCEPTION='" << exc_msg << "'\n" << "CMD=\n"; for (int x = 0; x < argc; ++x) diff --git a/toolsrc/src/vcpkg_Checks.cpp b/toolsrc/src/vcpkg_Checks.cpp index 5c3fef27a..f02addc08 100644 --- a/toolsrc/src/vcpkg_Checks.cpp +++ b/toolsrc/src/vcpkg_Checks.cpp @@ -33,6 +33,14 @@ namespace vcpkg::Checks } } + void check_exit(bool expression) + { + if (!expression) + { + exit(EXIT_FAILURE); + } + } + void check_exit(bool expression, const char* errorMessage) { if (!expression) diff --git a/toolsrc/src/Stopwatch.cpp b/toolsrc/src/vcpkg_Chrono.cpp index ec7af60b6..1bcb439be 100644 --- a/toolsrc/src/Stopwatch.cpp +++ b/toolsrc/src/vcpkg_Chrono.cpp @@ -1,49 +1,10 @@ #include "pch.h" -#include "Stopwatch.h" +#include "vcpkg_Chrono.h" #include "vcpkg_Checks.h" namespace vcpkg { - Stopwatch Stopwatch::createUnstarted() - { - return Stopwatch(); - } - - Stopwatch Stopwatch::createStarted() - { - return Stopwatch().start(); - } - - bool Stopwatch::isRunning() const - { - return this->m_isRunning; - } - - const Stopwatch& Stopwatch::start() - { - Checks::check_exit(!this->m_isRunning, "This stopwatch is already running."); - this->m_isRunning = true; - this->m_startTick = std::chrono::high_resolution_clock::now(); - return *this; - } - - const Stopwatch& Stopwatch::stop() - { - auto tick = std::chrono::high_resolution_clock::now(); - Checks::check_exit(this->m_isRunning, "This stopwatch is already stopped."); - this->m_isRunning = false; - this->m_elapsedNanos += tick - this->m_startTick; - return *this; - } - - Stopwatch& Stopwatch::reset() - { - this->m_elapsedNanos = std::chrono::nanoseconds(); - this->m_isRunning = false; - return *this; - } - - std::string Stopwatch::toString() const + static std::string format_time_userfriendly(const std::chrono::nanoseconds& nanos) { using std::chrono::hours; using std::chrono::minutes; @@ -53,8 +14,7 @@ namespace vcpkg using std::chrono::nanoseconds; using std::chrono::duration_cast; - auto nanos = elapsedNanos(); - auto nanos_as_double = static_cast<double>(nanos.count()); + const double nanos_as_double = static_cast<double>(nanos.count()); if (duration_cast<hours>(nanos) > hours()) { @@ -89,10 +49,64 @@ namespace vcpkg return Strings::format("%.4g ns", nanos_as_double); } - Stopwatch::Stopwatch() : m_isRunning(false), m_elapsedNanos(0), m_startTick() + ElapsedTime ElapsedTime::createStarted() { + ElapsedTime t; + t.m_startTick = std::chrono::high_resolution_clock::now(); + return t; } + std::string ElapsedTime::toString() const + { + return format_time_userfriendly(elapsed<std::chrono::nanoseconds>()); + } + + Stopwatch Stopwatch::createUnstarted() + { + return Stopwatch(); + } + + Stopwatch Stopwatch::createStarted() + { + return Stopwatch().start(); + } + + bool Stopwatch::isRunning() const + { + return this->m_isRunning; + } + + const Stopwatch& Stopwatch::start() + { + Checks::check_exit(!this->m_isRunning, "This stopwatch is already running."); + this->m_isRunning = true; + this->m_startTick = std::chrono::high_resolution_clock::now(); + return *this; + } + + const Stopwatch& Stopwatch::stop() + { + auto tick = std::chrono::high_resolution_clock::now(); + Checks::check_exit(this->m_isRunning, "This stopwatch is already stopped."); + this->m_isRunning = false; + this->m_elapsedNanos += tick - this->m_startTick; + return *this; + } + + Stopwatch& Stopwatch::reset() + { + this->m_elapsedNanos = std::chrono::nanoseconds(); + this->m_isRunning = false; + return *this; + } + + std::string Stopwatch::toString() const + { + return format_time_userfriendly(this->elapsedNanos()); + } + + Stopwatch::Stopwatch() : m_isRunning(false), m_elapsedNanos(0), m_startTick() { } + std::chrono::nanoseconds Stopwatch::elapsedNanos() const { if (this->m_isRunning) diff --git a/toolsrc/src/vcpkg_Dependencies.cpp b/toolsrc/src/vcpkg_Dependencies.cpp index 5bd6c3eb9..b255cc77b 100644 --- a/toolsrc/src/vcpkg_Dependencies.cpp +++ b/toolsrc/src/vcpkg_Dependencies.cpp @@ -80,7 +80,7 @@ namespace vcpkg::Dependencies continue; } - expected<SourceParagraph> maybe_spgh = try_load_port(paths, spec.name()); + expected<SourceParagraph> maybe_spgh = try_load_port(paths.port_dir(spec)); SourceParagraph* spgh = maybe_spgh.get(); Checks::check_exit(spgh != nullptr, "Cannot find package %s", spec.name()); process_dependencies(filter_dependencies(spgh->depends, spec.target_triplet())); @@ -97,7 +97,7 @@ namespace vcpkg::Dependencies return ret; } - std::vector<package_spec_with_remove_plan> create_remove_plan(const vcpkg_paths& paths, const std::vector<package_spec>& specs, const StatusParagraphs& status_db) + std::vector<package_spec_with_remove_plan> create_remove_plan(const std::vector<package_spec>& specs, const StatusParagraphs& status_db) { std::unordered_set<package_spec> specs_as_set(specs.cbegin(), specs.cend()); diff --git a/toolsrc/src/vcpkg_Enums.cpp b/toolsrc/src/vcpkg_Enums.cpp new file mode 100644 index 000000000..5e698659d --- /dev/null +++ b/toolsrc/src/vcpkg_Enums.cpp @@ -0,0 +1,21 @@ +#include "pch.h" +#include "vcpkg_Enums.h" +#include "vcpkg_Checks.h" + +namespace vcpkg::Enums +{ + std::string nullvalue_toString(const std::string& enum_name) + { + return Strings::format("%s_NULLVALUE", enum_name); + } + + void nullvalue_used(const std::string& enum_name) + { + Checks::exit_with_message("NULLVALUE of enum %s was used", enum_name); + } + + void unreachable(const std::string& enum_name) + { + Checks::exit_with_message("Unreachable code for enum, %s", enum_name); + } +} diff --git a/toolsrc/src/vcpkg_Environment.cpp b/toolsrc/src/vcpkg_Environment.cpp index 1babdc547..527d8de89 100644 --- a/toolsrc/src/vcpkg_Environment.cpp +++ b/toolsrc/src/vcpkg_Environment.cpp @@ -8,11 +8,6 @@ namespace vcpkg::Environment { - static const fs::path default_cmake_installation_dir = "C:/Program Files/CMake/bin"; - static const fs::path default_cmake_installation_dir_x86 = "C:/Program Files (x86)/CMake/bin"; - static const fs::path default_git_installation_dir = "C:/Program Files/git/cmd"; - static const fs::path default_git_installation_dir_x86 = "C:/Program Files (x86)/git/cmd"; - static void ensure_on_path(const std::array<int, 3>& version, const std::wstring& version_check_cmd, const std::wstring& install_cmd) { System::exit_code_and_output ec_data = System::cmd_execute_and_capture_output(version_check_cmd); @@ -54,15 +49,21 @@ namespace vcpkg::Environment void ensure_git_on_path(const vcpkg_paths& paths) { - const fs::path downloaded_git = paths.downloads / "PortableGit" / "cmd"; - const std::wstring path_buf = Strings::wformat(L"%s;%s;%s;%s", - downloaded_git.native(), - System::wdupenv_str(L"PATH"), + static const fs::path default_git_installation_dir = Environment::get_ProgramFiles_platform_bitness() / "git/cmd"; + static const fs::path default_git_installation_dir_32 = Environment::get_ProgramFiles_32_bit() / "git/cmd"; + + const fs::path portable_git = paths.downloads / "PortableGit" / "cmd"; // TODO: Remove next time we bump the version + const fs::path min_git = paths.downloads / "MinGit-2.11.1-32-bit" / "cmd"; + const std::wstring path_buf = Strings::wformat(L"%s;%s;%s;%s;%s", + min_git.native(), + portable_git.native(), + *System::get_environmental_variable(L"PATH"), default_git_installation_dir.native(), - default_git_installation_dir_x86.native()); - _wputenv_s(L"PATH", path_buf.c_str()); + default_git_installation_dir_32.native()); - static constexpr std::array<int, 3> git_version = {2,0,0}; + System::set_environmental_variable(L"PATH", path_buf.c_str()); + + static constexpr std::array<int, 3> git_version = { 2,0,0 }; static const std::wstring version_check_cmd = L"git --version 2>&1"; const std::wstring install_cmd = create_default_install_cmd(paths, L"git"); ensure_on_path(git_version, version_check_cmd, install_cmd); @@ -70,15 +71,18 @@ namespace vcpkg::Environment void ensure_cmake_on_path(const vcpkg_paths& paths) { - const fs::path downloaded_cmake = paths.downloads / "cmake-3.7.2-win32-x86" / "bin"; + static const fs::path default_cmake_installation_dir = Environment::get_ProgramFiles_platform_bitness() / "CMake/bin"; + static const fs::path default_cmake_installation_dir_32 = Environment::get_ProgramFiles_32_bit() / "CMake/bin"; + + const fs::path downloaded_cmake = paths.downloads / "cmake-3.8.0-rc1-win32-x86" / "bin"; const std::wstring path_buf = Strings::wformat(L"%s;%s;%s;%s", downloaded_cmake.native(), - System::wdupenv_str(L"PATH"), + *System::get_environmental_variable(L"PATH"), default_cmake_installation_dir.native(), - default_cmake_installation_dir_x86.native()); - _wputenv_s(L"PATH", path_buf.c_str()); + default_cmake_installation_dir_32.native()); + System::set_environmental_variable(L"PATH", path_buf.c_str()); - static constexpr std::array<int, 3> cmake_version = {3,7,2}; + static constexpr std::array<int, 3> cmake_version = { 3,8,0 }; static const std::wstring version_check_cmd = L"cmake --version 2>&1"; const std::wstring install_cmd = create_default_install_cmd(paths, L"cmake"); ensure_on_path(cmake_version, version_check_cmd, install_cmd); @@ -87,10 +91,10 @@ namespace vcpkg::Environment void ensure_nuget_on_path(const vcpkg_paths& paths) { const fs::path downloaded_nuget = paths.downloads / "nuget-3.5.0"; - const std::wstring path_buf = Strings::wformat(L"%s;%s", downloaded_nuget.native(), System::wdupenv_str(L"PATH")); - _wputenv_s(L"PATH", path_buf.c_str()); + const std::wstring path_buf = Strings::wformat(L"%s;%s", downloaded_nuget.native(), *System::get_environmental_variable(L"PATH")); + System::set_environmental_variable(L"PATH", path_buf.c_str()); - static constexpr std::array<int, 3> nuget_version = {3,3,0}; + static constexpr std::array<int, 3> nuget_version = { 3,3,0 }; static const std::wstring version_check_cmd = L"nuget 2>&1"; const std::wstring install_cmd = create_default_install_cmd(paths, L"nuget"); ensure_on_path(nuget_version, version_check_cmd, install_cmd); @@ -105,10 +109,22 @@ namespace vcpkg::Environment return Strings::split(ec_data.output, "\n"); } - static const fs::path& get_VS2015_installation_instance() + static optional<fs::path> find_vs2015_installation_instance() { - static const fs::path vs2015_cmntools = fs::path(System::wdupenv_str(L"VS140COMNTOOLS")).parent_path(); // The call to parent_path() is needed because the env variable has a trailing backslash + const optional<std::wstring> vs2015_cmntools_optional = System::get_environmental_variable(L"VS140COMNTOOLS"); + if (!vs2015_cmntools_optional) + { + return nullptr; + } + + static const fs::path vs2015_cmntools = fs::path(*vs2015_cmntools_optional).parent_path(); // The call to parent_path() is needed because the env variable has a trailing backslash static const fs::path vs2015_path = vs2015_cmntools.parent_path().parent_path(); + return std::make_unique<fs::path>(vs2015_path); + } + + static const optional<fs::path>& get_VS2015_installation_instance() + { + static const optional<fs::path> vs2015_path = find_vs2015_installation_instance(); return vs2015_path; } @@ -145,11 +161,15 @@ namespace vcpkg::Environment } // VS2015 - const fs::path vs2015_dumpbin_exe = get_VS2015_installation_instance() / "VC" / "bin" / "dumpbin.exe"; - paths_examined.push_back(vs2015_dumpbin_exe); - if (fs::exists(vs2015_dumpbin_exe)) + const optional<fs::path>& vs_2015_installation_instance = get_VS2015_installation_instance(); + if (vs_2015_installation_instance) { - return vs2015_dumpbin_exe; + const fs::path vs2015_dumpbin_exe = *vs_2015_installation_instance / "VC" / "bin" / "dumpbin.exe"; + paths_examined.push_back(vs2015_dumpbin_exe); + if (fs::exists(vs2015_dumpbin_exe)) + { + return vs2015_dumpbin_exe; + } } System::println(System::color::error, "Could not detect dumpbin.exe."); @@ -179,23 +199,28 @@ namespace vcpkg::Environment paths_examined.push_back(vcvarsall_bat); if (fs::exists(vcvarsall_bat)) { - return { vcvarsall_bat , L"v141"}; + return { vcvarsall_bat , L"v141" }; } } // VS2015 - const fs::path vs2015_vcvarsall_bat = get_VS2015_installation_instance() / "VC" / "vcvarsall.bat"; - paths_examined.push_back(vs2015_vcvarsall_bat); - if (fs::exists(vs2015_vcvarsall_bat)) + const optional<fs::path>& vs_2015_installation_instance = get_VS2015_installation_instance(); + if (vs_2015_installation_instance) { - return { vs2015_vcvarsall_bat, L"v140" }; + const fs::path vs2015_vcvarsall_bat = *vs_2015_installation_instance / "VC" / "vcvarsall.bat"; + + paths_examined.push_back(vs2015_vcvarsall_bat); + if (fs::exists(vs2015_vcvarsall_bat)) + { + return { vs2015_vcvarsall_bat, L"v140" }; + } } - System::println(System::color::error, "Could not detect vccarsall.bat."); + System::println(System::color::error, "Could not detect vcvarsall.bat."); System::println("The following paths were examined:"); for (const fs::path& path : paths_examined) { - System::println(" %s",path.generic_string()); + System::println(" %s", path.generic_string()); } exit(EXIT_FAILURE); } @@ -205,4 +230,38 @@ namespace vcpkg::Environment static const vcvarsall_and_platform_toolset vcvarsall_bat = find_vcvarsall_bat(paths); return vcvarsall_bat; } + + static fs::path find_ProgramFiles_32_bit() + { + const optional<std::wstring> program_files_X86 = System::get_environmental_variable(L"ProgramFiles(x86)"); + if (program_files_X86) + { + return *program_files_X86; + } + + return *System::get_environmental_variable(L"PROGRAMFILES"); + } + + const fs::path& get_ProgramFiles_32_bit() + { + static const fs::path p = find_ProgramFiles_32_bit(); + return p; + } + + static fs::path find_ProgramFiles_platform_bitness() + { + const optional<std::wstring> program_files_W6432 = System::get_environmental_variable(L"ProgramW6432"); + if (program_files_W6432) + { + return *program_files_W6432; + } + + return *System::get_environmental_variable(L"PROGRAMFILES"); + } + + const fs::path& get_ProgramFiles_platform_bitness() + { + static const fs::path p = find_ProgramFiles_platform_bitness(); + return p; + } } diff --git a/toolsrc/src/vcpkg_Files.cpp b/toolsrc/src/vcpkg_Files.cpp index 87700238d..57d4c665c 100644 --- a/toolsrc/src/vcpkg_Files.cpp +++ b/toolsrc/src/vcpkg_Files.cpp @@ -102,7 +102,7 @@ namespace vcpkg::Files void recursive_find_all_files_in_dir(const fs::path& dir, std::vector<fs::path>* output) { - recursive_find_matching_paths_in_dir(dir, [&](const fs::path& current) + recursive_find_matching_paths_in_dir(dir, [](const fs::path& current) { return !fs::is_directory(current); }, output); @@ -117,7 +117,7 @@ namespace vcpkg::Files void non_recursive_find_all_files_in_dir(const fs::path& dir, std::vector<fs::path>* output) { - non_recursive_find_matching_paths_in_dir(dir, [&](const fs::path& current) + non_recursive_find_matching_paths_in_dir(dir, [](const fs::path& current) { return !fs::is_directory(current); }, output); diff --git a/toolsrc/src/vcpkg_Strings.cpp b/toolsrc/src/vcpkg_Strings.cpp index 3b9d6a859..35ebcc90f 100644 --- a/toolsrc/src/vcpkg_Strings.cpp +++ b/toolsrc/src/vcpkg_Strings.cpp @@ -9,12 +9,18 @@ namespace vcpkg::Strings::details return std::isspace(c); }; + // Avoids C4244 warnings because of char<->int conversion that occur when using std::tolower() + static char tolower_char(const char c) + { + return static_cast<char>(std::tolower(c)); + } + std::string format_internal(const char* fmtstr, ...) { va_list lst; va_start(lst, fmtstr); - auto sz = _vscprintf(fmtstr, lst); + const int sz = _vscprintf(fmtstr, lst); std::string output(sz, '\0'); _vsnprintf_s(&output[0], output.size() + 1, output.size() + 1, fmtstr, lst); va_end(lst); @@ -27,7 +33,7 @@ namespace vcpkg::Strings::details va_list lst; va_start(lst, fmtstr); - auto sz = _vscwprintf(fmtstr, lst); + const int sz = _vscwprintf(fmtstr, lst); std::wstring output(sz, '\0'); _vsnwprintf_s(&output[0], output.size() + 1, output.size() + 1, fmtstr, lst); va_end(lst); @@ -52,18 +58,17 @@ namespace vcpkg::Strings std::string::const_iterator case_insensitive_ascii_find(const std::string& s, const std::string& pattern) { - std::string pattern_as_lower_case; - std::transform(pattern.begin(), pattern.end(), back_inserter(pattern_as_lower_case), tolower); + const std::string pattern_as_lower_case(ascii_to_lowercase(pattern)); return search(s.begin(), s.end(), pattern_as_lower_case.begin(), pattern_as_lower_case.end(), [](const char a, const char b) { - return tolower(a) == b; + return details::tolower_char(a) == b; }); } std::string ascii_to_lowercase(const std::string& input) { - std::string output = input; - std::transform(output.begin(), output.end(), output.begin(), ::tolower); + std::string output(input); + std::transform(output.begin(), output.end(), output.begin(), &details::tolower_char); return output; } diff --git a/toolsrc/src/vcpkg_System.cpp b/toolsrc/src/vcpkg_System.cpp index 754a26741..90ec9c99c 100644 --- a/toolsrc/src/vcpkg_System.cpp +++ b/toolsrc/src/vcpkg_System.cpp @@ -14,6 +14,9 @@ namespace vcpkg::System int cmd_execute(const wchar_t* cmd_line) { + // Flush cout before launching external process + std::cout << std::flush; + // Basically we are wrapping it in quotes const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); int exit_code = _wsystem(actual_cmd_line.c_str()); @@ -22,6 +25,9 @@ namespace vcpkg::System exit_code_and_output cmd_execute_and_capture_output(const wchar_t* cmd_line) { + // Flush cout before launching external process + std::cout << std::flush; + const std::wstring& actual_cmd_line = Strings::wformat(LR"###("%s")###", cmd_line); std::string output; @@ -29,7 +35,7 @@ namespace vcpkg::System auto pipe = _wpopen(actual_cmd_line.c_str(), L"r"); if (pipe == nullptr) { - return {1, output}; + return { 1, output }; } while (fgets(buf, 1024, pipe)) { @@ -37,10 +43,10 @@ namespace vcpkg::System } if (!feof(pipe)) { - return {1, output}; + return { 1, output }; } auto ec = _pclose(pipe); - return {ec, output}; + return { ec, output }; } void print(const char* message) @@ -62,7 +68,7 @@ namespace vcpkg::System GetConsoleScreenBufferInfo(hConsole, &consoleScreenBufferInfo); auto original_color = consoleScreenBufferInfo.wAttributes; - SetConsoleTextAttribute(hConsole, static_cast<int>(c) | (original_color & 0xF0)); + SetConsoleTextAttribute(hConsole, static_cast<WORD>(c) | (original_color & 0xF0)); std::cout << message; SetConsoleTextAttribute(hConsole, original_color); } @@ -73,17 +79,22 @@ namespace vcpkg::System std::cout << "\n"; } - std::wstring wdupenv_str(const wchar_t* varname) noexcept + optional<std::wstring> get_environmental_variable(const wchar_t* varname) noexcept { - std::wstring ret; wchar_t* buffer; _wdupenv_s(&buffer, nullptr, varname); - if (buffer != nullptr) + + if (buffer == nullptr) { - ret = buffer; - free(buffer); + return nullptr; } - return ret; + std::unique_ptr<wchar_t, void(__cdecl *)(void*)> bufptr(buffer, free); + return std::make_unique<std::wstring>(buffer); + } + + void set_environmental_variable(const wchar_t* varname, const wchar_t* varvalue) noexcept + { + _wputenv_s(varname, varvalue); } void Stopwatch2::start() diff --git a/toolsrc/src/vcpkg_info.cpp b/toolsrc/src/vcpkg_info.cpp deleted file mode 100644 index f8e214998..000000000 --- a/toolsrc/src/vcpkg_info.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "pch.h" -#include "vcpkg_info.h" -#include "metrics.h" - -#define STRINGIFY(X) #X -#define MACRO_TO_STRING(X) STRINGIFY(X) - -#define VCPKG_VERSION_AS_STRING MACRO_TO_STRING(VCPKG_VERSION)"" // Double quotes needed at the end to prevent blank token - -namespace vcpkg::Info -{ - const std::string& version() - { - static const std::string s_version = -#include "../VERSION.txt" - - -#pragma warning( push ) -#pragma warning( disable : 4003) - // VCPKG_VERSION can be defined but have no value, which yields C4003. - + std::string(VCPKG_VERSION_AS_STRING) -#pragma warning( pop ) -#ifndef NDEBUG - + std::string("-debug") -#endif - + std::string(GetCompiledMetricsEnabled() ? "" : "-external"); - return s_version; - } - - const std::string& email() - { - static const std::string s_email = R"(vcpkg@microsoft.com)"; - return s_email; - } -} diff --git a/toolsrc/src/vcpkg_metrics_uploader.cpp b/toolsrc/src/vcpkg_metrics_uploader.cpp index 14fc9ae48..82dcd4b03 100644 --- a/toolsrc/src/vcpkg_metrics_uploader.cpp +++ b/toolsrc/src/vcpkg_metrics_uploader.cpp @@ -5,13 +5,7 @@ using namespace vcpkg; -int WINAPI -WinMain( - _In_ HINSTANCE hInstance, - _In_opt_ HINSTANCE hPrevInstance, - _In_ LPSTR lpCmdLine, - _In_ int nShowCmd -) +int WINAPI WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int) { LPWSTR* szArgList; int argCount; diff --git a/toolsrc/src/vcpkglib.cpp b/toolsrc/src/vcpkglib.cpp index 06487684c..78918e62c 100644 --- a/toolsrc/src/vcpkglib.cpp +++ b/toolsrc/src/vcpkglib.cpp @@ -164,12 +164,10 @@ static void upgrade_to_slash_terminated_sorted_format(std::vector<std::string>* // The new format is lexicographically sorted std::sort(lines->begin(), lines->end()); -#if 0 // Replace the listfile on disk const fs::path updated_listfile_path = listfile_path.generic_string() + "_updated"; Files::write_all_lines(updated_listfile_path, *lines); fs::rename(updated_listfile_path, listfile_path); -#endif } std::vector<StatusParagraph_and_associated_files> vcpkg::get_installed_files(const vcpkg_paths& paths, const StatusParagraphs& status_db) |
