aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/src
diff options
context:
space:
mode:
authorBob Kast <bob.kast@emc.com>2018-11-13 15:48:26 -0500
committerBob Kast <bob.kast@emc.com>2018-11-13 15:48:26 -0500
commitd9e39bb4056795a70028b228a746da4889ca7c15 (patch)
tree4853304e1e71e45becedfba5d83e3f5321e0b9c9 /toolsrc/src
parent1a9dadf855ab93ff0803fd1ce4ecceec5bf211f0 (diff)
parentffa114aaa43e8bcdf880d6e2c47ee0ed46125070 (diff)
downloadvcpkg-d9e39bb4056795a70028b228a746da4889ca7c15.tar.gz
vcpkg-d9e39bb4056795a70028b228a746da4889ca7c15.zip
Merge branch 'master' of https://github.com/EMCECS/vcpkg
# Conflicts: # ports/ecsutil/CONTROL # ports/ecsutil/portfile.cmake
Diffstat (limited to 'toolsrc/src')
-rw-r--r--toolsrc/src/vcpkg.cpp26
-rw-r--r--toolsrc/src/vcpkg/base/checks.cpp14
-rw-r--r--toolsrc/src/vcpkg/base/chrono.cpp96
-rw-r--r--toolsrc/src/vcpkg/base/files.cpp8
-rw-r--r--toolsrc/src/vcpkg/base/system.cpp46
-rw-r--r--toolsrc/src/vcpkg/build.cpp46
-rw-r--r--toolsrc/src/vcpkg/commands.cpp1
-rw-r--r--toolsrc/src/vcpkg/commands.edit.cpp22
-rw-r--r--toolsrc/src/vcpkg/commands.env.cpp13
-rw-r--r--toolsrc/src/vcpkg/commands.exportifw.cpp2
-rw-r--r--toolsrc/src/vcpkg/commands.xvsinstances.cpp33
-rw-r--r--toolsrc/src/vcpkg/export.cpp10
-rw-r--r--toolsrc/src/vcpkg/globalstate.cpp44
-rw-r--r--toolsrc/src/vcpkg/help.cpp13
-rw-r--r--toolsrc/src/vcpkg/install.cpp19
-rw-r--r--toolsrc/src/vcpkg/postbuildlint.cpp6
-rw-r--r--toolsrc/src/vcpkg/remove.cpp4
-rw-r--r--toolsrc/src/vcpkg/visualstudio.cpp51
18 files changed, 337 insertions, 117 deletions
diff --git a/toolsrc/src/vcpkg.cpp b/toolsrc/src/vcpkg.cpp
index 6f10c503d..3589881a7 100644
--- a/toolsrc/src/vcpkg.cpp
+++ b/toolsrc/src/vcpkg.cpp
@@ -33,6 +33,12 @@
using namespace vcpkg;
+// 24 hours/day * 30 days/month * 6 months
+static constexpr int SURVEY_INTERVAL_IN_HOURS = 24 * 30 * 6;
+
+// Initial survey appears after 10 days. Therefore, subtract 24 hours/day * 10 days
+static constexpr int SURVEY_INITIAL_OFFSET_IN_HOURS = SURVEY_INTERVAL_IN_HOURS - 24 * 10;
+
void invalid_command(const std::string& cmd)
{
System::println(System::Color::error, "invalid command: %s", cmd);
@@ -113,19 +119,19 @@ static void inner(const VcpkgCmdArguments& args)
#endif
Checks::check_exit(VCPKG_LINE_INFO, exit_code == 0, "Changing the working dir failed");
- if (args.command != "autocomplete")
+ if (args.command == "install" || args.command == "remove" || args.command == "export" || args.command == "update")
{
Commands::Version::warn_if_vcpkg_version_mismatch(paths);
std::string surveydate = *GlobalState::g_surveydate.lock();
auto maybe_surveydate = Chrono::CTime::parse(surveydate);
if (auto p_surveydate = maybe_surveydate.get())
{
- auto delta = std::chrono::system_clock::now() - p_surveydate->to_time_point();
- // 24 hours/day * 30 days/month
- if (std::chrono::duration_cast<std::chrono::hours>(delta).count() > 24 * 30)
+ const auto now = Chrono::CTime::get_current_date_time().value_or_exit(VCPKG_LINE_INFO);
+ const auto delta = now.to_time_point() - p_surveydate->to_time_point();
+ if (std::chrono::duration_cast<std::chrono::hours>(delta).count() > SURVEY_INTERVAL_IN_HOURS)
{
std::default_random_engine generator(
- static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count()));
+ static_cast<unsigned int>(now.to_time_point().time_since_epoch().count()));
std::uniform_int_distribution<int> distribution(1, 4);
if (distribution(generator) == 1)
@@ -214,7 +220,9 @@ static void load_config()
if (config.last_completed_survey.empty())
{
- config.last_completed_survey = config.user_time;
+ const auto now = Chrono::CTime::parse(config.user_time).value_or_exit(VCPKG_LINE_INFO);
+ const Chrono::CTime offset = now.add_hours(-SURVEY_INITIAL_OFFSET_IN_HOURS);
+ config.last_completed_survey = offset.to_string();
}
GlobalState::g_surveydate.lock()->assign(config.last_completed_survey);
@@ -261,6 +269,7 @@ int main(const int argc, const char* const* const argv)
#if defined(_WIN32)
GlobalState::g_init_console_cp = GetConsoleCP();
GlobalState::g_init_console_output_cp = GetConsoleOutputCP();
+ GlobalState::g_init_console_initialized = true;
SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);
@@ -275,6 +284,9 @@ int main(const int argc, const char* const* const argv)
locked_metrics->track_property("cmdline", trimmed_command_line);
#endif
}
+
+ Checks::register_console_ctrl_handler();
+
load_config();
const auto vcpkg_feature_flags_env = System::get_environment_variable("VCPKG_FEATURE_FLAGS");
@@ -293,8 +305,6 @@ int main(const int argc, const char* const* const argv)
if (const auto p = args.sendmetrics.get()) Metrics::g_metrics.lock()->set_send_metrics(*p);
if (const auto p = args.debug.get()) GlobalState::debugging = *p;
- Checks::register_console_ctrl_handler();
-
if (GlobalState::debugging)
{
inner(args);
diff --git a/toolsrc/src/vcpkg/base/checks.cpp b/toolsrc/src/vcpkg/base/checks.cpp
index 72176e58c..cc439adfe 100644
--- a/toolsrc/src/vcpkg/base/checks.cpp
+++ b/toolsrc/src/vcpkg/base/checks.cpp
@@ -24,8 +24,11 @@ namespace vcpkg::Checks
metrics->flush();
#if defined(_WIN32)
- SetConsoleCP(GlobalState::g_init_console_cp);
- SetConsoleOutputCP(GlobalState::g_init_console_output_cp);
+ if (GlobalState::g_init_console_initialized)
+ {
+ SetConsoleCP(GlobalState::g_init_console_cp);
+ SetConsoleOutputCP(GlobalState::g_init_console_output_cp);
+ }
#endif
auto elapsed_us = GlobalState::timer.lock()->microseconds();
@@ -46,12 +49,11 @@ namespace vcpkg::Checks
#if defined(_WIN32)
static BOOL ctrl_handler(DWORD fdw_ctrl_type)
{
+ switch (fdw_ctrl_type)
{
- auto locked_metrics = Metrics::g_metrics.lock();
- locked_metrics->track_property("CtrlHandler", std::to_string(fdw_ctrl_type));
- locked_metrics->track_property("error", "CtrlHandler was fired.");
+ case CTRL_C_EVENT: GlobalState::g_ctrl_c_state.transition_handle_ctrl_c(); return TRUE;
+ default: return FALSE;
}
- cleanup_and_exit(EXIT_FAILURE);
}
void register_console_ctrl_handler()
diff --git a/toolsrc/src/vcpkg/base/chrono.cpp b/toolsrc/src/vcpkg/base/chrono.cpp
index 2a76f5df0..405e76605 100644
--- a/toolsrc/src/vcpkg/base/chrono.cpp
+++ b/toolsrc/src/vcpkg/base/chrono.cpp
@@ -5,6 +5,61 @@
namespace vcpkg::Chrono
{
+ static std::time_t get_current_time_as_time_since_epoch()
+ {
+ using std::chrono::system_clock;
+ return system_clock::to_time_t(system_clock::now());
+ }
+
+ static std::time_t utc_mktime(tm* time_ptr)
+ {
+#if defined(_WIN32)
+ return _mkgmtime(time_ptr);
+#else
+ return timegm(time_ptr);
+#endif
+ }
+
+ static tm to_local_time(const std::time_t& t)
+ {
+ tm parts {};
+#if defined(_WIN32)
+ localtime_s(&parts, &t);
+#else
+ parts = *localtime(&t);
+#endif
+ return parts;
+ }
+
+ static Optional<tm> to_utc_time(const std::time_t& t)
+ {
+ tm parts {};
+#if defined(_WIN32)
+ const errno_t err = gmtime_s(&parts, &t);
+ if (err)
+ {
+ return nullopt;
+ }
+#else
+ auto null_if_failed = gmtime_r(&t, &parts);
+ if (null_if_failed == nullptr)
+ {
+ return nullopt;
+ }
+#endif
+ return parts;
+ }
+
+ static tm date_plus_hours(tm* date, const int hours)
+ {
+ using namespace std::chrono_literals;
+ static constexpr std::chrono::seconds SECONDS_IN_ONE_HOUR =
+ std::chrono::duration_cast<std::chrono::seconds>(1h);
+
+ const std::time_t date_in_seconds = utc_mktime(date) + (hours * SECONDS_IN_ONE_HOUR.count());
+ return to_utc_time(date_in_seconds).value_or_exit(VCPKG_LINE_INFO);
+ }
+
static std::string format_time_userfriendly(const std::chrono::nanoseconds& nanos)
{
using std::chrono::duration_cast;
@@ -63,30 +118,14 @@ namespace vcpkg::Chrono
Optional<CTime> CTime::get_current_date_time()
{
- CTime ret;
-
-#if defined(_WIN32)
- struct _timeb timebuffer;
-
- _ftime_s(&timebuffer);
-
- const errno_t err = gmtime_s(&ret.m_tm, &timebuffer.time);
-
- if (err)
+ const std::time_t ct = get_current_time_as_time_since_epoch();
+ const Optional<tm> opt = to_utc_time(ct);
+ if (auto p_tm = opt.get())
{
- return nullopt;
+ return CTime {*p_tm};
}
-#else
- time_t now = {0};
- time(&now);
- auto null_if_failed = gmtime_r(&now, &ret.m_tm);
- if (null_if_failed == nullptr)
- {
- return nullopt;
- }
-#endif
- return ret;
+ return nullopt;
}
Optional<CTime> CTime::parse(CStringView str)
@@ -111,19 +150,28 @@ namespace vcpkg::Chrono
ret.m_tm.tm_year -= 1900;
if (ret.m_tm.tm_mon < 1) return nullopt;
ret.m_tm.tm_mon -= 1;
- mktime(&ret.m_tm);
+ utc_mktime(&ret.m_tm);
+
return ret;
}
+ CTime CTime::add_hours(const int hours) const { return CTime {date_plus_hours(&this->m_tm, hours)}; }
+
std::string CTime::to_string() const
{
- std::array<char, 80> date{};
+ std::array<char, 80> date {};
strftime(&date[0], date.size(), "%Y-%m-%dT%H:%M:%S.0Z", &m_tm);
return &date[0];
}
std::chrono::system_clock::time_point CTime::to_time_point() const
{
- const time_t t = mktime(&m_tm);
+ const time_t t = utc_mktime(&m_tm);
return std::chrono::system_clock::from_time_t(t);
}
+
+ tm get_current_date_time_local()
+ {
+ const std::time_t now_time = get_current_time_as_time_since_epoch();
+ return Chrono::to_local_time(now_time);
+ }
}
diff --git a/toolsrc/src/vcpkg/base/files.cpp b/toolsrc/src/vcpkg/base/files.cpp
index 4ff0912d1..f9bce8631 100644
--- a/toolsrc/src/vcpkg/base/files.cpp
+++ b/toolsrc/src/vcpkg/base/files.cpp
@@ -216,11 +216,19 @@ namespace vcpkg::Files
{
return fs::stdfs::copy_file(oldpath, newpath, opts, ec);
}
+ virtual void copy_symlink(const fs::path& oldpath, const fs::path& newpath, std::error_code& ec)
+ {
+ return fs::stdfs::copy_symlink(oldpath, newpath, ec);
+ }
virtual fs::file_status status(const fs::path& path, std::error_code& ec) const override
{
return fs::stdfs::status(path, ec);
}
+ virtual fs::file_status symlink_status(const fs::path& path, std::error_code& ec) const override
+ {
+ return fs::stdfs::symlink_status(path, ec);
+ }
virtual void write_contents(const fs::path& file_path, const std::string& data, std::error_code& ec) override
{
ec.clear();
diff --git a/toolsrc/src/vcpkg/base/system.cpp b/toolsrc/src/vcpkg/base/system.cpp
index d968c6dac..d95752bba 100644
--- a/toolsrc/src/vcpkg/base/system.cpp
+++ b/toolsrc/src/vcpkg/base/system.cpp
@@ -19,19 +19,6 @@
namespace vcpkg::System
{
- tm get_current_date_time()
- {
- using std::chrono::system_clock;
- std::time_t now_time = system_clock::to_time_t(system_clock::now());
- tm parts{};
-#if defined(_WIN32)
- localtime_s(&parts, &now_time);
-#else
- parts = *localtime(&now_time);
-#endif
- return parts;
- }
-
fs::path get_exe_path_of_current_process()
{
#if defined(_WIN32)
@@ -133,7 +120,7 @@ namespace vcpkg::System
static void windows_create_clean_process(const CStringView cmd_line,
const std::unordered_map<std::string, std::string>& extra_env,
PROCESS_INFORMATION& process_info,
- DWORD dwCreationFlags)
+ DWORD dwCreationFlags) noexcept
{
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)";
@@ -223,7 +210,7 @@ namespace vcpkg::System
memset(&startup_info, 0, sizeof(STARTUPINFOW));
startup_info.cb = sizeof(STARTUPINFOW);
- // Basically we are wrapping it in quotes
+ // Wrapping the command in a single set of quotes causes cmd.exe to correctly execute
const std::string actual_cmd_line = Strings::format(R"###(cmd.exe /c "%s")###", cmd_line);
Debug::println("CreateProcessW(%s)", actual_cmd_line);
bool succeeded = TRUE == CreateProcessW(nullptr,
@@ -242,7 +229,7 @@ namespace vcpkg::System
#endif
#if defined(_WIN32)
- void cmd_execute_no_wait(const CStringView cmd_line)
+ void cmd_execute_no_wait(const CStringView cmd_line) noexcept
{
auto timer = Chrono::ElapsedTimer::create_started();
@@ -258,7 +245,8 @@ namespace vcpkg::System
}
#endif
- int cmd_execute_clean(const CStringView cmd_line, const std::unordered_map<std::string, std::string>& extra_env)
+ int cmd_execute_clean(const CStringView cmd_line,
+ const std::unordered_map<std::string, std::string>& extra_env) noexcept
{
auto timer = Chrono::ElapsedTimer::create_started();
#if defined(_WIN32)
@@ -266,11 +254,13 @@ namespace vcpkg::System
PROCESS_INFORMATION process_info;
memset(&process_info, 0, sizeof(PROCESS_INFORMATION));
+ GlobalState::g_ctrl_c_state.transition_to_spawn_process();
windows_create_clean_process(cmd_line, extra_env, process_info, NULL);
CloseHandle(process_info.hThread);
const DWORD result = WaitForSingleObject(process_info.hProcess, INFINITE);
+ GlobalState::g_ctrl_c_state.transition_from_spawn_process();
Checks::check_exit(VCPKG_LINE_INFO, result != WAIT_FAILED, "WaitForSingleObject failed");
DWORD exit_code = 0;
@@ -279,6 +269,7 @@ namespace vcpkg::System
CloseHandle(process_info.hProcess);
Debug::println("CreateProcessW() returned %lu after %d us", exit_code, static_cast<int>(timer.microseconds()));
+
return static_cast<int>(exit_code);
#else
Debug::println("system(%s)", cmd_line.c_str());
@@ -289,16 +280,18 @@ namespace vcpkg::System
#endif
}
- int cmd_execute(const CStringView cmd_line)
+ int cmd_execute(const CStringView cmd_line) noexcept
{
// Flush stdout before launching external process
fflush(nullptr);
- // Basically we are wrapping it in quotes
#if defined(_WIN32)
+ // We are wrap the command line in quotes to cause cmd.exe to correctly process it
const std::string& actual_cmd_line = Strings::format(R"###("%s")###", cmd_line);
Debug::println("_wsystem(%s)", actual_cmd_line);
+ GlobalState::g_ctrl_c_state.transition_to_spawn_process();
const int exit_code = _wsystem(Strings::to_utf16(actual_cmd_line).c_str());
+ GlobalState::g_ctrl_c_state.transition_from_spawn_process();
Debug::println("_wsystem() returned %d", exit_code);
#else
Debug::println("_system(%s)", cmd_line);
@@ -308,11 +301,8 @@ namespace vcpkg::System
return exit_code;
}
- ExitCodeAndOutput cmd_execute_and_capture_output(const CStringView cmd_line)
+ ExitCodeAndOutput cmd_execute_and_capture_output(const CStringView cmd_line) noexcept
{
- // Flush stdout before launching external process
- fflush(stdout);
-
auto timer = Chrono::ElapsedTimer::create_started();
#if defined(_WIN32)
@@ -321,9 +311,13 @@ namespace vcpkg::System
Debug::println("_wpopen(%s)", actual_cmd_line);
std::wstring output;
wchar_t buf[1024];
+ GlobalState::g_ctrl_c_state.transition_to_spawn_process();
+ // Flush stdout before launching external process
+ fflush(stdout);
const auto pipe = _wpopen(Strings::to_utf16(actual_cmd_line).c_str(), L"r");
if (pipe == nullptr)
{
+ GlobalState::g_ctrl_c_state.transition_from_spawn_process();
return {1, Strings::to_utf8(output.c_str())};
}
while (fgetws(buf, 1024, pipe))
@@ -332,10 +326,12 @@ namespace vcpkg::System
}
if (!feof(pipe))
{
+ GlobalState::g_ctrl_c_state.transition_from_spawn_process();
return {1, Strings::to_utf8(output.c_str())};
}
const auto ec = _pclose(pipe);
+ GlobalState::g_ctrl_c_state.transition_from_spawn_process();
// On Win7, output from powershell calls contain a utf-8 byte order mark in the utf-16 stream, so we strip it
// out if it is present. 0xEF,0xBB,0xBF is the UTF-8 byte-order mark
@@ -354,6 +350,8 @@ namespace vcpkg::System
Debug::println("popen(%s)", actual_cmd_line);
std::string output;
char buf[1024];
+ // Flush stdout before launching external process
+ fflush(stdout);
const auto pipe = popen(actual_cmd_line.c_str(), "r");
if (pipe == nullptr)
{
@@ -391,7 +389,7 @@ namespace vcpkg::System
#if defined(_WIN32)
const HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info{};
+ CONSOLE_SCREEN_BUFFER_INFO console_screen_buffer_info {};
GetConsoleScreenBufferInfo(console_handle, &console_screen_buffer_info);
const auto original_color = console_screen_buffer_info.wAttributes;
diff --git a/toolsrc/src/vcpkg/build.cpp b/toolsrc/src/vcpkg/build.cpp
index 8e87fe7fe..7569f340f 100644
--- a/toolsrc/src/vcpkg/build.cpp
+++ b/toolsrc/src/vcpkg/build.cpp
@@ -63,7 +63,7 @@ namespace vcpkg::Build::Command
spec.name());
const StatusParagraphs status_db = database_load_check(paths);
- const Build::BuildPackageOptions build_package_options{
+ const Build::BuildPackageOptions build_package_options {
Build::UseHeadVersion::NO,
Build::AllowDownloads::YES,
Build::CleanBuildtrees::NO,
@@ -76,8 +76,8 @@ namespace vcpkg::Build::Command
std::set<std::string> features_as_set(full_spec.features.begin(), full_spec.features.end());
features_as_set.emplace("core");
- const Build::BuildPackageConfig build_config{
- *scf, spec.triplet(), fs::path{port_dir}, build_package_options, features_as_set};
+ const Build::BuildPackageConfig build_config {
+ *scf, spec.triplet(), fs::path {port_dir}, build_package_options, features_as_set};
const auto build_timer = Chrono::ElapsedTimer::create_started();
const auto result = Build::build_package(paths, build_config, status_db);
@@ -245,7 +245,7 @@ namespace vcpkg::Build
const auto arch = to_vcvarsall_toolchain(pre_build_info.target_architecture, toolset);
const auto target = to_vcvarsall_target(pre_build_info.cmake_system_name);
- return Strings::format(R"("%s" %s %s %s %s 2>&1)",
+ return Strings::format(R"("%s" %s %s %s %s 2>&1 <NUL)",
toolset.vcvarsall.u8string(),
Strings::join(" ", toolset.vcvarsall_options),
arch,
@@ -381,9 +381,15 @@ namespace vcpkg::Build
});
auto command = make_build_env_cmd(pre_build_info, toolset);
- if (!command.empty()) command.append(" && ");
+ if (!command.empty())
+ {
+#ifdef _WIN32
+ command.append(" & ");
+#else
+ command.append(" && ");
+#endif
+ }
command.append(cmd_launch_cmake);
-
const auto timer = Chrono::ElapsedTimer::create_started();
const int return_code = System::cmd_execute_clean(command);
@@ -440,7 +446,7 @@ namespace vcpkg::Build
auto buildtree_files = fs.get_files_non_recursive(buildtrees_dir);
for (auto&& file : buildtree_files)
{
- if (fs.is_directory(file) && file.filename() != "src")
+ if (fs.is_directory(file)) // Will only keep the logs
{
std::error_code ec;
fs.remove_all(file, ec);
@@ -464,22 +470,22 @@ namespace vcpkg::Build
std::vector<AbiEntry> abi_tag_entries;
- abi_tag_entries.emplace_back(AbiEntry{"cmake", paths.get_tool_version(Tools::CMAKE)});
+ abi_tag_entries.emplace_back(AbiEntry {"cmake", paths.get_tool_version(Tools::CMAKE)});
abi_tag_entries.insert(abi_tag_entries.end(), dependency_abis.begin(), dependency_abis.end());
abi_tag_entries.emplace_back(
- AbiEntry{"portfile", vcpkg::Hash::get_file_hash(fs, config.port_dir / "portfile.cmake", "SHA1")});
+ AbiEntry {"portfile", vcpkg::Hash::get_file_hash(fs, config.port_dir / "portfile.cmake", "SHA1")});
abi_tag_entries.emplace_back(
- AbiEntry{"control", vcpkg::Hash::get_file_hash(fs, config.port_dir / "CONTROL", "SHA1")});
+ AbiEntry {"control", vcpkg::Hash::get_file_hash(fs, config.port_dir / "CONTROL", "SHA1")});
- abi_tag_entries.emplace_back(AbiEntry{"triplet", pre_build_info.triplet_abi_tag});
+ abi_tag_entries.emplace_back(AbiEntry {"triplet", pre_build_info.triplet_abi_tag});
const std::string features = Strings::join(";", config.feature_list);
- abi_tag_entries.emplace_back(AbiEntry{"features", features});
+ abi_tag_entries.emplace_back(AbiEntry {"features", features});
if (config.build_package_options.use_head_version == UseHeadVersion::YES)
- abi_tag_entries.emplace_back(AbiEntry{"head", ""});
+ abi_tag_entries.emplace_back(AbiEntry {"head", ""});
Util::sort(abi_tag_entries);
@@ -506,7 +512,7 @@ namespace vcpkg::Build
const auto abi_file_path = paths.buildtrees / name / (triplet.canonical_name() + ".vcpkg_abi_info.txt");
fs.write_contents(abi_file_path, full_abi_info);
- return AbiTagAndFile{Hash::get_file_hash(fs, abi_file_path, "SHA1"), abi_file_path};
+ return AbiTagAndFile {Hash::get_file_hash(fs, abi_file_path, "SHA1"), abi_file_path};
}
System::println(
@@ -596,7 +602,7 @@ namespace vcpkg::Build
const 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});
+ AbiEntry {status_it->get()->package.spec.name(), status_it->get()->package.abi});
}
const auto pre_build_info = PreBuildInfo::from_triplet_file(paths, triplet);
@@ -642,7 +648,7 @@ namespace vcpkg::Build
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);
+ paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile {}).tag, config);
std::error_code ec;
fs.create_directories(paths.package_dir(spec) / "share" / spec.name(), ec);
@@ -679,7 +685,7 @@ namespace vcpkg::Build
}
return do_build_package_and_clean_buildtrees(
- paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile{}).tag, config);
+ paths, pre_build_info, spec, maybe_abi_tag_and_file.value_or(AbiTagAndFile {}).tag, config);
}
const std::string& to_string(const BuildResult build_result)
@@ -844,21 +850,21 @@ namespace vcpkg::Build
if (variable_name == "VCPKG_PLATFORM_TOOLSET")
{
pre_build_info.platform_toolset =
- variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
+ variable_value.empty() ? nullopt : Optional<std::string> {variable_value};
continue;
}
if (variable_name == "VCPKG_VISUAL_STUDIO_PATH")
{
pre_build_info.visual_studio_path =
- variable_value.empty() ? nullopt : Optional<fs::path>{variable_value};
+ variable_value.empty() ? nullopt : Optional<fs::path> {variable_value};
continue;
}
if (variable_name == "VCPKG_CHAINLOAD_TOOLCHAIN_FILE")
{
pre_build_info.external_toolchain_file =
- variable_value.empty() ? nullopt : Optional<std::string>{variable_value};
+ variable_value.empty() ? nullopt : Optional<std::string> {variable_value};
continue;
}
diff --git a/toolsrc/src/vcpkg/commands.cpp b/toolsrc/src/vcpkg/commands.cpp
index 7204b6e78..db265514f 100644
--- a/toolsrc/src/vcpkg/commands.cpp
+++ b/toolsrc/src/vcpkg/commands.cpp
@@ -46,6 +46,7 @@ namespace vcpkg::Commands
{"autocomplete", &Autocomplete::perform_and_exit},
{"hash", &Hash::perform_and_exit},
{"fetch", &Fetch::perform_and_exit},
+ {"x-vsinstances", &X_VSInstances::perform_and_exit},
};
return t;
}
diff --git a/toolsrc/src/vcpkg/commands.edit.cpp b/toolsrc/src/vcpkg/commands.edit.cpp
index 2569c2cea..237feebdd 100644
--- a/toolsrc/src/vcpkg/commands.edit.cpp
+++ b/toolsrc/src/vcpkg/commands.edit.cpp
@@ -92,8 +92,8 @@ namespace vcpkg::Commands::Edit
void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
{
- static const fs::path VS_CODE_INSIDERS = fs::path{"Microsoft VS Code Insiders"} / "Code - Insiders.exe";
- static const fs::path VS_CODE = fs::path{"Microsoft VS Code"} / "Code.exe";
+ static const fs::path VS_CODE_INSIDERS = fs::path {"Microsoft VS Code Insiders"} / "Code - Insiders.exe";
+ static const fs::path VS_CODE = fs::path {"Microsoft VS Code"} / "Code.exe";
auto& fs = paths.get_filesystem();
@@ -128,6 +128,14 @@ namespace vcpkg::Commands::Edit
candidate_paths.push_back(*pf / VS_CODE);
}
+ const auto& app_data = System::get_environment_variable("APPDATA");
+ if (const auto* ad = app_data.get())
+ {
+ const fs::path default_base = fs::path {*ad}.parent_path() / "Local" / "Programs";
+ candidate_paths.push_back(default_base / VS_CODE_INSIDERS);
+ candidate_paths.push_back(default_base / VS_CODE);
+ }
+
const std::vector<fs::path> from_registry = find_from_registry();
candidate_paths.insert(candidate_paths.end(), from_registry.cbegin(), from_registry.cend());
@@ -147,6 +155,16 @@ namespace vcpkg::Commands::Edit
const std::vector<std::string> arguments = create_editor_arguments(paths, options, ports);
const auto args_as_string = Strings::join(" ", arguments);
const auto cmd_line = Strings::format(R"("%s" %s -n)", env_editor.u8string(), args_as_string);
+
+ auto editor_exe = env_editor.filename().u8string();
+
+#ifdef _WIN32
+ if (editor_exe == "Code.exe" || editor_exe == "Code - Insiders.exe")
+ {
+ System::cmd_execute_no_wait(cmd_line + " <NUL");
+ Checks::exit_success(VCPKG_LINE_INFO);
+ }
+#endif
Checks::exit_with_code(VCPKG_LINE_INFO, System::cmd_execute(cmd_line));
}
}
diff --git a/toolsrc/src/vcpkg/commands.env.cpp b/toolsrc/src/vcpkg/commands.env.cpp
index d078baedb..ea00617d4 100644
--- a/toolsrc/src/vcpkg/commands.env.cpp
+++ b/toolsrc/src/vcpkg/commands.env.cpp
@@ -23,9 +23,9 @@ namespace vcpkg::Commands::Env
}};
const CommandStructure COMMAND_STRUCTURE = {
- Help::create_example_string("env --triplet x64-windows"),
- 0,
+ Help::create_example_string("env <optional command> --triplet x64-windows"),
0,
+ 1,
{SWITCHES, {}},
nullptr,
};
@@ -64,11 +64,12 @@ namespace vcpkg::Commands::Env
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", extra_env);
- else
- System::cmd_execute_clean(env_cmd + " && cmd", extra_env);
+ std::string env_cmd_prefix = env_cmd.empty() ? "" : Strings::format("%s && ", env_cmd);
+ std::string env_cmd_suffix =
+ args.command_arguments.empty() ? "cmd" : Strings::format("cmd /c %s", args.command_arguments.at(0));
+ const std::string cmd = Strings::format("%s%s", env_cmd_prefix, env_cmd_suffix);
+ System::cmd_execute_clean(cmd, extra_env);
Checks::exit_success(VCPKG_LINE_INFO);
}
}
diff --git a/toolsrc/src/vcpkg/commands.exportifw.cpp b/toolsrc/src/vcpkg/commands.exportifw.cpp
index ae106196a..62725a90a 100644
--- a/toolsrc/src/vcpkg/commands.exportifw.cpp
+++ b/toolsrc/src/vcpkg/commands.exportifw.cpp
@@ -13,7 +13,7 @@ namespace vcpkg::Export::IFW
static std::string create_release_date()
{
- const tm date_time = System::get_current_date_time();
+ const tm date_time = Chrono::get_current_date_time_local();
// Format is: YYYY-mm-dd
// 10 characters + 1 null terminating character will be written for a total of 11 chars
diff --git a/toolsrc/src/vcpkg/commands.xvsinstances.cpp b/toolsrc/src/vcpkg/commands.xvsinstances.cpp
new file mode 100644
index 000000000..d748b6b2f
--- /dev/null
+++ b/toolsrc/src/vcpkg/commands.xvsinstances.cpp
@@ -0,0 +1,33 @@
+#include "pch.h"
+
+#include <vcpkg/commands.h>
+#include <vcpkg/help.h>
+#include <vcpkg/visualstudio.h>
+
+namespace vcpkg::Commands::X_VSInstances
+{
+ const CommandStructure COMMAND_STRUCTURE = {
+ Help::create_example_string("x-vsinstances"),
+ 0,
+ 0,
+ {{}, {}},
+ nullptr,
+ };
+
+ void perform_and_exit(const VcpkgCmdArguments& args, const VcpkgPaths& paths)
+ {
+#if defined(_WIN32)
+ const ParsedArguments parsed_args = args.parse_arguments(COMMAND_STRUCTURE);
+
+ const auto instances = vcpkg::VisualStudio::get_visual_studio_instances(paths);
+ for (const std::string& instance : instances)
+ {
+ System::println(instance);
+ }
+
+ Checks::exit_success(VCPKG_LINE_INFO);
+#else
+ Checks::exit_with_message(VCPKG_LINE_INFO, "This command is not supported on non-windows platforms.");
+#endif
+ }
+}
diff --git a/toolsrc/src/vcpkg/export.cpp b/toolsrc/src/vcpkg/export.cpp
index 8161c0a62..eec9a39f2 100644
--- a/toolsrc/src/vcpkg/export.cpp
+++ b/toolsrc/src/vcpkg/export.cpp
@@ -108,7 +108,7 @@ namespace vcpkg::Export
static std::string create_export_id()
{
- const tm date_time = System::get_current_date_time();
+ const tm date_time = Chrono::get_current_date_time_local();
// Format is: YYYYmmdd-HHMMSS
// 15 characters + 1 null terminating character will be written for a total of 16 chars
@@ -227,10 +227,10 @@ namespace vcpkg::Export
{
const std::vector<fs::path> integration_files_relative_to_root = {
{".vcpkg-root"},
- {fs::path{"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"},
- {fs::path{"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"},
- {fs::path{"scripts"} / "buildsystems" / "vcpkg.cmake"},
- {fs::path{"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"},
+ {fs::path {"scripts"} / "buildsystems" / "msbuild" / "applocal.ps1"},
+ {fs::path {"scripts"} / "buildsystems" / "msbuild" / "vcpkg.targets"},
+ {fs::path {"scripts"} / "buildsystems" / "vcpkg.cmake"},
+ {fs::path {"scripts"} / "cmake" / "vcpkg_get_windows_sdk.cmake"},
};
for (const fs::path& file : integration_files_relative_to_root)
diff --git a/toolsrc/src/vcpkg/globalstate.cpp b/toolsrc/src/vcpkg/globalstate.cpp
index a4100acf7..a54c596fb 100644
--- a/toolsrc/src/vcpkg/globalstate.cpp
+++ b/toolsrc/src/vcpkg/globalstate.cpp
@@ -13,4 +13,48 @@ namespace vcpkg
std::atomic<int> GlobalState::g_init_console_cp(0);
std::atomic<int> GlobalState::g_init_console_output_cp(0);
+ std::atomic<bool> GlobalState::g_init_console_initialized(false);
+
+ GlobalState::CtrlCStateMachine GlobalState::g_ctrl_c_state;
+
+ GlobalState::CtrlCStateMachine::CtrlCStateMachine() : m_state(CtrlCState::normal) {}
+
+ void GlobalState::CtrlCStateMachine::transition_to_spawn_process() noexcept
+ {
+ auto expected = CtrlCState::normal;
+ auto transitioned = m_state.compare_exchange_strong(expected, CtrlCState::blocked_on_child);
+ if (!transitioned)
+ {
+ // Ctrl-C was hit and is asynchronously executing on another thread
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ }
+ void GlobalState::CtrlCStateMachine::transition_from_spawn_process() noexcept
+ {
+ auto expected = CtrlCState::blocked_on_child;
+ auto transitioned = m_state.compare_exchange_strong(expected, CtrlCState::normal);
+ if (!transitioned)
+ {
+ // Ctrl-C was hit while blocked on the child process
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ }
+ void GlobalState::CtrlCStateMachine::transition_handle_ctrl_c() noexcept
+ {
+ auto prev_state = m_state.exchange(CtrlCState::exit_requested);
+
+ if (prev_state == CtrlCState::normal)
+ {
+ // Not currently blocked on a child process and Ctrl-C has not been hit.
+ Checks::exit_fail(VCPKG_LINE_INFO);
+ }
+ else if (prev_state == CtrlCState::exit_requested)
+ {
+ // Ctrl-C was hit previously
+ }
+ else
+ {
+ // This is the case where we are currently blocked on a child process
+ }
+ }
}
diff --git a/toolsrc/src/vcpkg/help.cpp b/toolsrc/src/vcpkg/help.cpp
index 743619937..2b409373d 100644
--- a/toolsrc/src/vcpkg/help.cpp
+++ b/toolsrc/src/vcpkg/help.cpp
@@ -7,6 +7,13 @@
#include <vcpkg/install.h>
#include <vcpkg/remove.h>
+// Write environment variable names as %VARIABLE% on Windows and $VARIABLE in *nix
+#ifdef _WIN32
+#define ENVVAR(VARNAME) "%%" #VARNAME "%%"
+#else
+#define ENVVAR(VARNAME) "$" #VARNAME
+#endif
+
namespace vcpkg::Help
{
struct Topic
@@ -93,7 +100,7 @@ namespace vcpkg::Help
"%s" // Integration help
"\n"
" vcpkg export <pkg>... [opt]... Exports a package\n"
- " vcpkg edit <pkg> Open up a port for editing (uses %%EDITOR%%, default 'code')\n"
+ " vcpkg edit <pkg> Open up a port for editing (uses " ENVVAR(EDITOR) ", default 'code')\n"
" vcpkg import <pkg> Import a pre-built library\n"
" vcpkg create <pkg> <url>\n"
" [archivename] Create a new package\n"
@@ -104,10 +111,10 @@ namespace vcpkg::Help
"\n"
"Options:\n"
" --triplet <t> Specify the target architecture triplet.\n"
- " (default: %%VCPKG_DEFAULT_TRIPLET%%, see 'vcpkg help triplet')\n"
+ " (default: " ENVVAR(VCPKG_DEFAULT_TRIPLET) ", see 'vcpkg help triplet')\n"
"\n"
" --vcpkg-root <path> Specify the vcpkg root directory\n"
- " (default: %%VCPKG_ROOT%%)\n"
+ " (default: " ENVVAR(VCPKG_ROOT) ")\n"
"\n"
"For more help (including examples) see the accompanying README.md.",
Commands::Integrate::INTEGRATE_COMMAND_HELPSTRING);
diff --git a/toolsrc/src/vcpkg/install.cpp b/toolsrc/src/vcpkg/install.cpp
index 4bb84831e..1cfa2bf71 100644
--- a/toolsrc/src/vcpkg/install.cpp
+++ b/toolsrc/src/vcpkg/install.cpp
@@ -62,7 +62,7 @@ namespace vcpkg::Install
auto files = fs.get_files_recursive(source_dir);
for (auto&& file : files)
{
- const auto status = fs.status(file, ec);
+ const auto status = fs.symlink_status(file, ec);
if (ec)
{
System::println(System::Color::error, "failed: %s: %s", file.u8string(), ec.message());
@@ -111,6 +111,23 @@ namespace vcpkg::Install
output.push_back(Strings::format(R"(%s/%s)", destination_subdirectory, suffix));
break;
}
+ case fs::file_type::symlink:
+ {
+ if (fs.exists(target))
+ {
+ System::println(System::Color::warning,
+ "File %s was already present and will be overwritten",
+ target.u8string(),
+ ec.message());
+ }
+ fs.copy_symlink(file, target, ec);
+ if (ec)
+ {
+ System::println(System::Color::error, "failed: %s: %s", target.u8string(), ec.message());
+ }
+ output.push_back(Strings::format(R"(%s/%s)", destination_subdirectory, suffix));
+ break;
+ }
default:
System::println(System::Color::error, "failed: %s: cannot handle file type", file.u8string());
break;
diff --git a/toolsrc/src/vcpkg/postbuildlint.cpp b/toolsrc/src/vcpkg/postbuildlint.cpp
index 6fe11951f..90dcb7d64 100644
--- a/toolsrc/src/vcpkg/postbuildlint.cpp
+++ b/toolsrc/src/vcpkg/postbuildlint.cpp
@@ -617,7 +617,11 @@ namespace vcpkg::PostBuildLint
const std::string cmd_line =
Strings::format(R"("%s" /directives "%s")", dumpbin_exe.u8string(), lib.u8string());
System::ExitCodeAndOutput ec_data = System::cmd_execute_and_capture_output(cmd_line);
- Checks::check_exit(VCPKG_LINE_INFO, ec_data.exit_code == 0, "Running command:\n %s\n failed", cmd_line);
+ Checks::check_exit(VCPKG_LINE_INFO,
+ ec_data.exit_code == 0,
+ "Running command:\n %s\n failed with message:\n%s",
+ cmd_line,
+ ec_data.output);
for (const BuildType& bad_build_type : bad_build_types)
{
diff --git a/toolsrc/src/vcpkg/remove.cpp b/toolsrc/src/vcpkg/remove.cpp
index 13cc9325e..921a04c23 100644
--- a/toolsrc/src/vcpkg/remove.cpp
+++ b/toolsrc/src/vcpkg/remove.cpp
@@ -55,7 +55,7 @@ namespace vcpkg::Remove
auto target = paths.installed / suffix;
- const auto status = fs.status(target, ec);
+ const auto status = fs.symlink_status(target, ec);
if (ec)
{
System::println(System::Color::error, "failed: status(%s): %s", target.u8string(), ec.message());
@@ -66,7 +66,7 @@ namespace vcpkg::Remove
{
dirs_touched.push_back(target);
}
- else if (fs::is_regular_file(status))
+ else if (fs::is_regular_file(status) || fs::is_symlink(status))
{
fs.remove(target, ec);
if (ec)
diff --git a/toolsrc/src/vcpkg/visualstudio.cpp b/toolsrc/src/vcpkg/visualstudio.cpp
index 9480a11bf..e3656a7d2 100644
--- a/toolsrc/src/vcpkg/visualstudio.cpp
+++ b/toolsrc/src/vcpkg/visualstudio.cpp
@@ -22,6 +22,17 @@ namespace vcpkg::VisualStudio
LEGACY
};
+ static std::string release_type_to_string(const ReleaseType& release_type)
+ {
+ switch (release_type)
+ {
+ case ReleaseType::STABLE: return "STABLE";
+ case ReleaseType::PRERELEASE: return "PRERELEASE";
+ case ReleaseType::LEGACY: return "LEGACY";
+ default: Checks::unreachable(VCPKG_LINE_INFO);
+ }
+ }
+
static bool preferred_first_comparator(const VisualStudioInstance& left, const VisualStudioInstance& right)
{
const auto get_preference_weight = [](const ReleaseType& type) -> int {
@@ -51,10 +62,15 @@ namespace vcpkg::VisualStudio
std::string version;
ReleaseType release_type;
+ std::string to_string() const
+ {
+ return Strings::format("%s, %s, %s", root_path.u8string(), version, release_type_to_string(release_type));
+ }
+
std::string major_version() const { return version.substr(0, 2); }
};
- static std::vector<VisualStudioInstance> get_visual_studio_instances(const VcpkgPaths& paths)
+ static std::vector<VisualStudioInstance> get_visual_studio_instances_internal(const VcpkgPaths& paths)
{
const auto& fs = paths.get_filesystem();
std::vector<VisualStudioInstance> instances;
@@ -66,7 +82,7 @@ namespace vcpkg::VisualStudio
if (fs.exists(vswhere_exe))
{
const auto code_and_output = System::cmd_execute_and_capture_output(
- Strings::format(R"("%s" -prerelease -legacy -products * -format xml)", vswhere_exe.u8string()));
+ Strings::format(R"("%s" -all -prerelease -legacy -products * -format xml)", vswhere_exe.u8string()));
Checks::check_exit(VCPKG_LINE_INFO,
code_and_output.exit_code == 0,
"Running vswhere.exe failed with message:\n%s",
@@ -114,9 +130,9 @@ namespace vcpkg::VisualStudio
{
// We want lexically_normal(), but it is not available
// Correct root path might be 2 or 3 levels up, depending on if the path has trailing backslash. Try both.
- auto common7_tools = fs::path{*path_as_string};
- append_if_has_cl(fs::path{*path_as_string}.parent_path().parent_path());
- append_if_has_cl(fs::path{*path_as_string}.parent_path().parent_path().parent_path());
+ auto common7_tools = fs::path {*path_as_string};
+ append_if_has_cl(fs::path {*path_as_string}.parent_path().parent_path());
+ append_if_has_cl(fs::path {*path_as_string}.parent_path().parent_path().parent_path());
}
// VS2015 instance from Program Files
@@ -125,6 +141,13 @@ namespace vcpkg::VisualStudio
return instances;
}
+ std::vector<std::string> get_visual_studio_instances(const VcpkgPaths& paths)
+ {
+ std::vector<VisualStudioInstance> sorted {get_visual_studio_instances_internal(paths)};
+ std::sort(sorted.begin(), sorted.end(), VisualStudioInstance::preferred_first_comparator);
+ return Util::fmap(sorted, [](const VisualStudioInstance& instance) { return instance.to_string(); });
+ }
+
std::vector<Toolset> find_toolset_instances_preferred_first(const VcpkgPaths& paths)
{
using CPU = System::CPUArchitecture;
@@ -137,8 +160,8 @@ namespace vcpkg::VisualStudio
std::vector<Toolset> found_toolsets;
std::vector<Toolset> excluded_toolsets;
- const SortedVector<VisualStudioInstance> sorted{get_visual_studio_instances(paths),
- VisualStudioInstance::preferred_first_comparator};
+ const SortedVector<VisualStudioInstance> sorted {get_visual_studio_instances_internal(paths),
+ VisualStudioInstance::preferred_first_comparator};
const bool v140_is_available = Util::find_if(sorted, [&](const VisualStudioInstance& vs_instance) {
return vs_instance.major_version() == "14";
@@ -194,7 +217,7 @@ namespace vcpkg::VisualStudio
paths_examined.push_back(dumpbin_path);
if (fs.exists(dumpbin_path))
{
- const Toolset v141_toolset{
+ const Toolset v141_toolset {
vs_instance.root_path, dumpbin_path, vcvarsall_bat, {}, V_141, supported_architectures};
const auto english_language_pack = dumpbin_path.parent_path() / "1033";
@@ -209,12 +232,12 @@ namespace vcpkg::VisualStudio
if (v140_is_available)
{
- const Toolset v140_toolset{vs_instance.root_path,
- dumpbin_path,
- vcvarsall_bat,
- {"-vcvars_ver=14.0"},
- V_140,
- supported_architectures};
+ const Toolset v140_toolset {vs_instance.root_path,
+ dumpbin_path,
+ vcvarsall_bat,
+ {"-vcvars_ver=14.0"},
+ V_140,
+ supported_architectures};
found_toolsets.push_back(v140_toolset);
}