From 8db894669852ba4942c2d36a807b69f17bd727f3 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Mon, 4 May 2020 08:02:43 -0400 Subject: [PATCH] bypass_file fixed bad nul handle for stdin, removed workaround for cmake revisited pyqt fixed async_pipe busting the stack --- src/process.cpp | 28 +++++++++++++++++----------- src/process.h | 2 +- src/tasks/pyqt.cpp | 39 ++++++++++++++++++++++++++++++--------- src/tasks/tasks.h | 5 +++++ src/tools/cmake.cpp | 8 -------- src/utility.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/utility.h | 15 +++++++++++++++ 7 files changed, 112 insertions(+), 29 deletions(-) diff --git a/src/process.cpp b/src/process.cpp index 923e40f..99c5ccf 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -8,10 +8,19 @@ namespace mob { +HANDLE bit_bucket() +{ + SECURITY_ATTRIBUTES sa { .nLength = sizeof(sa), .bInheritHandle = TRUE }; + return ::CreateFileA("NUL", GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0); +} + + async_pipe::async_pipe() : pending_(false) { - std::memset(buffer_, 0, sizeof(buffer_)); + buffer_ = std::make_unique(buffer_size); + std::memset(buffer_.get(), 0, buffer_size); + std::memset(&ov_, 0, sizeof(ov_)); } @@ -108,7 +117,7 @@ std::string_view async_pipe::try_read() { DWORD bytes_read = 0; - if (!::ReadFile(stdout_.get(), buffer_, buffer_size, &bytes_read, &ov_)) + if (!::ReadFile(stdout_.get(), buffer_.get(), buffer_size, &bytes_read, &ov_)) { const auto e = GetLastError(); @@ -136,7 +145,7 @@ std::string_view async_pipe::try_read() return {}; } - return {buffer_, bytes_read}; + return {buffer_.get(), bytes_read}; } std::string_view async_pipe::check_pending() @@ -185,7 +194,7 @@ std::string_view async_pipe::check_pending() ::ResetEvent(event_.get()); pending_ = false; - return {buffer_, bytes_read}; + return {buffer_.get(), bytes_read}; } @@ -366,15 +375,12 @@ void process::do_run(const std::string& what) STARTUPINFOA si = { .cb=sizeof(si) }; PROCESS_INFORMATION pi = {}; - auto process_stdout = impl_.stdout_pipe.create(); - si.hStdOutput = process_stdout.get(); - auto process_stderr = impl_.stderr_pipe.create(); + auto process_stdout = impl_.stdout_pipe.create(); + + si.hStdOutput = process_stdout.get(); si.hStdError = process_stderr.get(); - - si.hStdInput = ::CreateFileA( - "NUL", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, 0); - + si.hStdInput = bit_bucket(); si.dwFlags = STARTF_USESTDHANDLES; const std::string cmd = this_env::get("COMSPEC"); diff --git a/src/process.h b/src/process.h index 6a13648..89b5460 100644 --- a/src/process.h +++ b/src/process.h @@ -24,7 +24,7 @@ private: handle_ptr stdout_; handle_ptr event_; - char buffer_[buffer_size]; + std::unique_ptr buffer_; OVERLAPPED ov_; bool pending_; diff --git a/src/tasks/pyqt.cpp b/src/tasks/pyqt.cpp index 325cecb..3efa6d4 100644 --- a/src/tasks/pyqt.cpp +++ b/src/tasks/pyqt.cpp @@ -19,6 +19,11 @@ fs::path pyqt::build_path() return source_path() / "build"; } +void pyqt::do_clean_for_rebuild() +{ + op::delete_file(cx(), paths::cache() / sip_install_file(), op::optional); +} + void pyqt::do_fetch() { const auto file = run_tool(downloader(source_url())); @@ -50,6 +55,13 @@ void pyqt::do_build_and_install() .file("builder.py.manual_patch") .root(python::site_packages_path() / "pyqtbuild")); + sip_build(modules); + install_sip_file(); + copy_files(modules); +} + +void pyqt::sip_build(const std::vector& modules) +{ auto pyqt_env = env::vs_x64() .append_path({ paths::qt_bin(), @@ -60,9 +72,12 @@ void pyqt::do_build_and_install() .set("LIB", ";" + paths::install_libs().string(), env::append) .set("PYTHONHOME", python::source_path().string()); - if (fs::exists(source_path() / "_mob_built")) + + bypass_file built_bypass(cx(), source_path(), "built"); + + if (built_bypass.exists()) { - debug("pyqt already built"); + cx().trace(context::bypass, "pyqt already built"); } else { @@ -74,7 +89,7 @@ void pyqt::do_build_and_install() run_tool(process_runner(process() .binary(sip::sip_install_exe()) .arg("--confirm-license") - .arg("--verbose") + .arg("--verbose", process::log_trace) .arg("--pep484-pyi") .arg("--link-full-dll") .arg("--build-dir", build_path()) @@ -84,7 +99,7 @@ void pyqt::do_build_and_install() .cwd(source_path()) .env(pyqt_env))); - op::touch(cx(), source_path() / "_mob_built"); + built_bypass.create(); } run_tool(process_runner(process() @@ -93,20 +108,27 @@ void pyqt::do_build_and_install() .arg("PyQt5.sip") .cwd(paths::cache()) .env(pyqt_env))); +} - if (fs::exists(source_path() / "_mob_installed")) +void pyqt::install_sip_file() +{ + bypass_file installed_bypass(cx(), source_path(), "installed"); + + if (installed_bypass.exists()) { - debug("pyqt already installed"); + cx().trace(context::bypass, "pyqt already installed"); } else { run_tool(pip_install() .file(paths::cache() / sip_install_file())); - op::touch(cx(), source_path() / "_mob_installed"); + installed_bypass.create(); } +} - +void pyqt::copy_files(const std::vector& modules) +{ const fs::path site_packages_pyqt = python::site_packages_path() / "PyQt5"; const fs::path pyqt_plugin = paths::install_plugins() / "data" / "PyQt5"; @@ -133,7 +155,6 @@ void pyqt::do_build_and_install() op::copy_file_to_dir_if_better(cx(), sip::module_source_path() / "sip.pyi", pyqt_plugin); - } url pyqt::source_url() diff --git a/src/tasks/tasks.h b/src/tasks/tasks.h index 917bdda..b683911 100644 --- a/src/tasks/tasks.h +++ b/src/tasks/tasks.h @@ -224,6 +224,11 @@ public: protected: void do_fetch() override; void do_build_and_install() override; + void do_clean_for_rebuild() override; + + void sip_build(const std::vector& modules); + void install_sip_file(); + void copy_files(const std::vector& modules); static url source_url(); static fs::path sip_install_file(); diff --git a/src/tools/cmake.cpp b/src/tools/cmake.cpp index fe60cae..10cce25 100644 --- a/src/tools/cmake.cpp +++ b/src/tools/cmake.cpp @@ -66,14 +66,6 @@ void cmake::do_run() output_ = root_ / (g.output_dir(arch_)); process_ - .stderr_filter([&](process::filter& f) - { - // cmake doesn't like NUL as stdin - if (f.line.find("Failed to create ConsoleBuf") != std::string::npos) - f.ignore = true; - else if (f.line.find("setActiveInputCodepage") != std::string::npos) - f.ignore = true; - }) .arg("-G", "\"" + g.name + "\"") .arg("-DCMAKE_BUILD_TYPE=Release") .arg("-DCMAKE_INSTALL_MESSAGE=NEVER", process::log_quiet) diff --git a/src/utility.cpp b/src/utility.cpp index 016e459..424edb8 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -144,6 +144,50 @@ void interruption_file::remove() } +bypass_file::bypass_file(const context& cx, fs::path dir, std::string name) + : cx_(cx), file_(dir / ("_mob_" + name)) +{ +} + +bool bypass_file::exists() const +{ + if (fs::exists(file_)) + { + if (conf::rebuild()) + { + cx_.trace(context::bypass, + "bypass file " + file_.string() + " exists, deleting"); + + op::delete_file(cx_, file_, op::optional); + + return false; + } + else + { + cx_.trace(context::bypass, + "bypass file " + file_.string() + " exists"); + + return true; + } + } + else + { + cx_.trace(context::bypass, + "bypass file " + file_.string() + " not found"); + + return false; + } +} + +void bypass_file::create() +{ + cx_.trace(context::bypass, + "create bypass file " + file_.string()); + + op::touch(cx_, file_); +} + + enum class color_methods { none = 0, diff --git a/src/utility.h b/src/utility.h index b4d92d6..3fb7e42 100644 --- a/src/utility.h +++ b/src/utility.h @@ -127,6 +127,20 @@ private: }; +class bypass_file +{ +public: + bypass_file(const context& cx, fs::path dir, std::string name); + + bool exists() const; + void create(); + +private: + const context& cx_; + fs::path file_; +}; + + class console_color { public: @@ -156,6 +170,7 @@ std::string join(const std::vector& v, const std::string& sep); std::string pad_right(std::string s, std::size_t n, char c=' '); std::string pad_left(std::string s, std::size_t n, char c=' '); + template void for_each_line(std::string_view s, F&& f) {