diff --git a/toolsrc/include/VcpkgPaths.h b/toolsrc/include/VcpkgPaths.h index 25c1728b9a..95cd4bc28e 100644 --- a/toolsrc/include/VcpkgPaths.h +++ b/toolsrc/include/VcpkgPaths.h @@ -48,7 +48,12 @@ namespace vcpkg const fs::path& get_cmake_exe() const; const fs::path& get_git_exe() const; const fs::path& get_nuget_exe() const; - const Toolset& get_toolset() const; + + /// Retrieve a toolset matching a VS version + /// + /// Valid version strings are "v140", "v141", and "". Empty string gets the latest. + /// + const Toolset& get_toolset(const std::string& toolset_version) const; Files::Filesystem& get_filesystem() const; @@ -56,6 +61,6 @@ namespace vcpkg Lazy cmake_exe; Lazy git_exe; Lazy nuget_exe; - Lazy toolset; + Lazy> toolsets; }; } diff --git a/toolsrc/src/PostBuildLint.cpp b/toolsrc/src/PostBuildLint.cpp index bcad270325..363346ab6c 100644 --- a/toolsrc/src/PostBuildLint.cpp +++ b/toolsrc/src/PostBuildLint.cpp @@ -733,7 +733,7 @@ namespace vcpkg::PostBuildLint const auto& fs = paths.get_filesystem(); // for dumpbin - const Toolset& toolset = paths.get_toolset(); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); const fs::path package_dir = paths.package_dir(spec); size_t error_count = 0; diff --git a/toolsrc/src/VcpkgPaths.cpp b/toolsrc/src/VcpkgPaths.cpp index 3dd32de01a..9068e3903e 100644 --- a/toolsrc/src/VcpkgPaths.cpp +++ b/toolsrc/src/VcpkgPaths.cpp @@ -269,7 +269,7 @@ namespace vcpkg return nullopt; } - static Toolset find_toolset_instance(const VcpkgPaths& paths) + static std::vector find_toolset_instances(const VcpkgPaths& paths) { const auto& fs = paths.get_filesystem(); @@ -277,7 +277,28 @@ namespace vcpkg // Note: this will contain a mix of vcvarsall.bat locations and dumpbin.exe locations. std::vector paths_examined; + std::vector found_toolsets; + + // VS2015 + const Optional vs_2015_installation_instance = get_VS2015_installation_instance(); + if (auto v = vs_2015_installation_instance.get()) + { + const fs::path vs2015_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; + + paths_examined.push_back(vs2015_vcvarsall_bat); + if (fs.exists(vs2015_vcvarsall_bat)) + { + const fs::path vs2015_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; + paths_examined.push_back(vs2015_dumpbin_exe); + if (fs.exists(vs2015_dumpbin_exe)) + { + found_toolsets.push_back({vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140"}); + } + } + } + // VS2017 + Optional vs2017_toolset; for (const fs::path& instance : vs2017_installation_instances) { const fs::path vc_dir = instance / "VC"; @@ -303,41 +324,50 @@ namespace vcpkg paths_examined.push_back(dumpbin_path); if (fs.exists(dumpbin_path)) { - return {dumpbin_path, vcvarsall_bat, L"v141"}; + vs2017_toolset = Toolset{dumpbin_path, vcvarsall_bat, L"v141"}; + break; } } - } - - // VS2015 - const Optional vs_2015_installation_instance = get_VS2015_installation_instance(); - if (auto v = vs_2015_installation_instance.get()) - { - const fs::path vs2015_vcvarsall_bat = *v / "VC" / "vcvarsall.bat"; - - paths_examined.push_back(vs2015_vcvarsall_bat); - if (fs.exists(vs2015_vcvarsall_bat)) + if (auto value = vs2017_toolset.get()) { - const fs::path vs2015_dumpbin_exe = *v / "VC" / "bin" / "dumpbin.exe"; - paths_examined.push_back(vs2015_dumpbin_exe); - if (fs.exists(vs2015_dumpbin_exe)) - { - return {vs2015_dumpbin_exe, vs2015_vcvarsall_bat, L"v140"}; - } + found_toolsets.push_back(*value); + break; } } - System::println(System::Color::error, "Could not locate a complete toolset."); - System::println("The following paths were examined:"); - for (const fs::path& path : paths_examined) + if (found_toolsets.empty()) { - System::println(" %s", path.u8string()); + System::println(System::Color::error, "Could not locate a complete toolset."); + System::println("The following paths were examined:"); + for (const fs::path& path : paths_examined) + { + System::println(" %s", path.u8string()); + } + Checks::exit_fail(VCPKG_LINE_INFO); } - Checks::exit_fail(VCPKG_LINE_INFO); + + return found_toolsets; } - const Toolset& VcpkgPaths::get_toolset() const + const Toolset& VcpkgPaths::get_toolset(const std::string& toolset_version) const { - return this->toolset.get_lazy([this]() { return find_toolset_instance(*this); }); + // Invariant: toolsets are non-empty and sorted with newest at back() + const auto& vs_toolsets = this->toolsets.get_lazy([this]() { return find_toolset_instances(*this); }); + + if (toolset_version.empty()) + { + return vs_toolsets.back(); + } + else + { + const auto toolset = Util::find_if(vs_toolsets, [&](const Toolset& toolset) { + return toolset_version == Strings::to_utf8(toolset.version); + }); + Checks::check_exit( + VCPKG_LINE_INFO, toolset != vs_toolsets.end(), "Could not find toolset '%s'", toolset_version); + return *toolset; + } } + Files::Filesystem& VcpkgPaths::get_filesystem() const { return Files::get_real_filesystem(); } } diff --git a/toolsrc/src/commands_env.cpp b/toolsrc/src/commands_env.cpp index 5e1ecc5e7e..dd7172b891 100644 --- a/toolsrc/src/commands_env.cpp +++ b/toolsrc/src/commands_env.cpp @@ -13,7 +13,7 @@ namespace vcpkg::Commands::Env args.check_and_get_optional_command_arguments({}); auto pre_build_info = Build::PreBuildInfo::from_triplet_file(paths, default_triplet); - System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, paths.get_toolset()) + L" && cmd"); + System::cmd_execute_clean(Build::make_build_env_cmd(pre_build_info, paths.get_toolset(pre_build_info.platform_toolset)) + L" && cmd"); Checks::exit_success(VCPKG_LINE_INFO); } diff --git a/toolsrc/src/vcpkg_Build.cpp b/toolsrc/src/vcpkg_Build.cpp index d44a673fc1..817febe2f2 100644 --- a/toolsrc/src/vcpkg_Build.cpp +++ b/toolsrc/src/vcpkg_Build.cpp @@ -128,8 +128,8 @@ namespace vcpkg::Build const fs::path& git_exe_path = paths.get_git_exe(); const fs::path ports_cmake_script_path = paths.ports_cmake; - const Toolset& toolset = paths.get_toolset(); auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet); + const Toolset& toolset = paths.get_toolset(pre_build_info.platform_toolset); const auto cmd_set_environment = make_build_env_cmd(pre_build_info, toolset); const std::wstring cmd_launch_cmake =