diff --git a/src/conf.cpp b/src/conf.cpp index 40d0c79..46beafd 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -399,10 +399,12 @@ fs::path find_third_party_directory() fs::path find_in_path(const std::string& exe) { - const std::size_t buffer_size = MAX_PATH; - char buffer[buffer_size + 1] = {}; + const std::wstring wexe = utf8_to_utf16(exe); - if (SearchPathA(nullptr, exe.c_str(), nullptr, buffer_size, buffer, nullptr)) + const std::size_t size = MAX_PATH; + wchar_t buffer[size + 1] = {}; + + if (SearchPathW(nullptr, wexe.c_str(), nullptr, size, buffer, nullptr)) return buffer; else return {}; @@ -950,7 +952,7 @@ void dump_options() string_map tools; for (auto&& [k, v] : g_tools) - tools[k] = v.string(); + tools[k] = path_to_utf8(v); table("tools", tools); string_map prebuilt; @@ -962,7 +964,7 @@ void dump_options() string_map paths; for (auto&& [k, v] : g_paths) - paths[k] = v.string(); + paths[k] = path_to_utf8(v); table("paths", paths); } diff --git a/src/context.cpp b/src/context.cpp index 1d3967e..9ef9cfa 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -197,8 +197,8 @@ void context::set_log_file(const fs::path& p) { if (!p.empty()) { - HANDLE h = CreateFileA( - p.string().c_str(), GENERIC_WRITE, FILE_SHARE_READ, + HANDLE h = CreateFileW( + p.native().c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (h == INVALID_HANDLE_VALUE) @@ -242,8 +242,8 @@ void context::emit_log(level lv, const std::string& utf8) const if (log_enabled(lv, conf::output_log_level())) { - u8cout << utf8 << "\n"; auto c = level_color(lv); + u8cout << utf8 << "\n"; } if (g_log_file && log_enabled(lv, conf::file_log_level())) diff --git a/src/env.cpp b/src/env.cpp index 8d156b5..22be407 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -33,15 +33,16 @@ env get_vcvars_env(arch a) // "vcvarsall.bat" amd64 && set > temp_file std::string cmd = - "\"" + tools::vs::vcvars().string() + "\" " + arch_s + - " && set > \"" + tmp.string() + "\""; + "\"" + path_to_utf8(tools::vs::vcvars()) + "\" " + arch_s + + " && set > \"" + path_to_utf8(tmp) + "\""; process::raw(gcx(), cmd) + .cmd_unicode(true) .run(); gcx().trace(context::generic, "reading from {}", tmp); - std::stringstream ss(op::read_text_file(gcx(), tmp)); + std::stringstream ss(op::read_text_file(gcx(), encodings::utf16, tmp)); op::delete_file(gcx(), tmp); env e; @@ -119,7 +120,7 @@ env& env::append_path(const std::vector& v) if (!path.empty()) path += ";"; - path += p.string(); + path += path_to_utf8(p); } set("PATH", path, replace); @@ -172,13 +173,15 @@ void env::set_from(const env& e) void env::create() const { + sys_.clear(); + for (auto&& v : vars_) { - string_ += v.first + "=" + v.second; - string_.append(1, '\0'); + sys_ += utf8_to_utf16(v.first + "=" + v.second); + sys_.append(1, L'\0'); } - string_.append(1, '\0'); + sys_.append(1, L'\0'); } env::map::const_iterator env::find(const std::string& name) const @@ -192,79 +195,102 @@ env::map::const_iterator env::find(const std::string& name) const return vars_.end(); } -void* env::get_pointers() const +void* env::get_unicode_pointers() const { if (vars_.empty()) return nullptr; - if (string_.empty()) + if (sys_.empty()) create(); - return (void*)string_.c_str(); + return (void*)sys_.c_str(); } void this_env::set(const std::string& k, const std::string& v, env::flags f) { + const std::wstring wk = utf8_to_utf16(k); + const std::wstring wv = utf8_to_utf16(v); + switch (f) { case env::replace: - ::SetEnvironmentVariableA(k.c_str(), v.c_str()); + { + ::SetEnvironmentVariableW(wk.c_str(), wv.c_str()); break; + } case env::append: - ::SetEnvironmentVariableA(k.c_str(), (get(k) + v).c_str()); + { + const std::wstring current = get_impl(k); + ::SetEnvironmentVariableW(wk.c_str(), (current + wv).c_str()); break; + } case env::prepend: - ::SetEnvironmentVariableA(k.c_str(), (v + get(k)).c_str()); + { + const std::wstring current = get_impl(k); + ::SetEnvironmentVariableW(wk.c_str(), (wv + current).c_str()); break; + } } } void this_env::prepend_to_path(const fs::path& p) { gcx().trace(context::generic, "prepending to PATH: {}", p); - set("PATH", p.string() + ";", env::prepend); + set("PATH", path_to_utf8(p) + ";", env::prepend); } std::string this_env::get(const std::string& name) { - const std::size_t buffer_size = GetEnvironmentVariableA( - name.c_str(), nullptr, 0); + return utf16_to_utf8(get_impl(name)); +} + +std::wstring this_env::get_impl(const std::string& k) +{ + const std::wstring wk = utf8_to_utf16(k); + + const std::size_t buffer_size = GetEnvironmentVariableW( + wk.c_str(), nullptr, 0); if (buffer_size == 0) - bail_out("environment variable {} doesn't exist", name); + bail_out("environment variable {} doesn't exist", k); - auto buffer = std::make_unique(buffer_size + 1); + auto buffer = std::make_unique(buffer_size + 1); std::fill(buffer.get(), buffer.get() + buffer_size + 1, 0); - GetEnvironmentVariableA( - name.c_str(), buffer.get(), static_cast(buffer_size)); + const std::size_t written = GetEnvironmentVariableW( + wk.c_str(), buffer.get(), static_cast(buffer_size)); - return buffer.get(); + if (written == 0) + bail_out("environment variable {} doesn't exist", k); + + MOB_ASSERT((written + 1) == buffer_size); + + return {buffer.get(), buffer.get() + written}; } env this_env::get() { env e; - auto free = [](char* p) { FreeEnvironmentStrings(p); }; + auto free = [](wchar_t* p) { FreeEnvironmentStringsW(p); }; - auto env_block = std::unique_ptr{ - GetEnvironmentStrings(), free}; + auto env_block = std::unique_ptr{ + GetEnvironmentStringsW(), free}; - for (const char* name = env_block.get(); *name != '\0'; ) + for (const wchar_t* name = env_block.get(); *name != L'\0'; ) { - const char* equal = std::strchr(name, '='); - std::string key(name, static_cast(equal - name)); + const wchar_t* equal = std::wcschr(name, '='); + std::wstring key(name, static_cast(equal - name)); - const char* pValue = equal + 1; - std::string value(pValue); + const wchar_t* pValue = equal + 1; + std::wstring value(pValue); if (!key.empty()) - e.set(key, value); + e.set(utf16_to_utf8(key), utf16_to_utf8(value)); name = pValue + value.length() + 1; } diff --git a/src/env.h b/src/env.h index 03556d7..12c6cc4 100644 --- a/src/env.h +++ b/src/env.h @@ -27,13 +27,13 @@ public: std::string get(const std::string& k) const; - void* get_pointers() const; + void* get_unicode_pointers() const; private: using map = std::map; map vars_; - mutable std::string string_; + mutable std::wstring sys_; void create() const; map::const_iterator find(const std::string& name) const; @@ -51,6 +51,9 @@ struct this_env static env get(); static std::string get(const std::string& k); + +private: + static std::wstring get_impl(const std::string& k); }; } // namespace diff --git a/src/main.cpp b/src/main.cpp index fa9da3c..5473974 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -320,11 +320,11 @@ int main(int argc, char** argv) if (r == 0) { - mob::gcx().debug(mob::context::generic, "mob done"); + mob::gcx().info(mob::context::generic, "mob done"); } else { - mob::gcx().debug(mob::context::generic, + mob::gcx().info(mob::context::generic, "mob finished with exit code {}", r); } diff --git a/src/net.cpp b/src/net.cpp index 0631481..128492e 100644 --- a/src/net.cpp +++ b/src/net.cpp @@ -225,8 +225,8 @@ void curl_downloader::on_write(char* ptr, std::size_t n) noexcept cx_.trace(context::net, "opening {}", path_); - HANDLE h = ::CreateFileA( - path_.string().c_str(), GENERIC_WRITE, FILE_SHARE_READ, + HANDLE h = ::CreateFileW( + path_.native().c_str(), GENERIC_WRITE, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (h == INVALID_HANDLE_VALUE) diff --git a/src/op.cpp b/src/op.cpp index 7f1fd69..087d5a5 100644 --- a/src/op.cpp +++ b/src/op.cpp @@ -221,7 +221,7 @@ void copy_file_to_dir_if_better( check(cx, dir); } - if (file.string().find("*") != std::string::npos) + if (file.u8string().find(u8"*") != std::string::npos) cx.bail_out(context::fs, "{} contains a glob", file); if (!conf::dry()) @@ -266,7 +266,7 @@ void copy_file_to_file_if_better( check(cx, dest); } - if (src.string().find("*") != std::string::npos) + if (src.u8string().find(u8"*") != std::string::npos) cx.bail_out(context::fs, "{} contains a glob", src); if (!conf::dry()) @@ -309,13 +309,13 @@ void copy_glob_to_dir_if_better( const fs::path& src_glob, const fs::path& dest_dir, flags f) { const auto file_parent = src_glob.parent_path(); - const auto wildcard = src_glob.filename().string(); + const auto wildcard = src_glob.filename().native(); for (auto&& e : fs::directory_iterator(file_parent)) { - const auto name = e.path().filename().string(); + const auto name = e.path().filename().native(); - if (!PathMatchSpecA(name.c_str(), wildcard.c_str())) + if (!PathMatchSpecW(name.c_str(), wildcard.c_str())) { cx.trace(context::fs, "{} did not match {}; skipping", name, wildcard); @@ -355,12 +355,12 @@ void copy_glob_to_dir_if_better( } } -std::string read_text_file(const context& cx, const fs::path& p, flags f) +std::string read_text_file_impl(const context& cx, const fs::path& p, flags f) { cx.trace(context::fs, "reading {}", p); std::string s; - std::ifstream in(p); + std::ifstream in(p, std::ios::binary); in.seekg(0, std::ios::end); s.resize(static_cast(in.tellg())); @@ -382,6 +382,42 @@ std::string read_text_file(const context& cx, const fs::path& p, flags f) return s; } +std::string read_text_file( + const context& cx, encodings e, const fs::path& p, flags f) +{ + cx.trace(context::fs, "reading {}", p); + + std::string bytes = read_text_file_impl(cx, p, f); + if (bytes.empty()) + return bytes; + + std::string utf8; + + switch (e) + { + case encodings::utf16: + { + const auto* wbuf = reinterpret_cast(bytes.data()); + const std::size_t n = bytes.size() / sizeof(wchar_t); + const std::wstring ws(wbuf, wbuf + n); + + utf8 = utf16_to_utf8(ws); + break; + } + + case encodings::utf8: + case encodings::dont_know: + default: + { + utf8 = std::move(bytes); + break; + } + } + + utf8 = replace_all(utf8, "\r\n", "\n"); + return utf8; +} + void write_text_file( const context& cx, const fs::path& p, std::string_view s, flags f) { @@ -531,8 +567,8 @@ void check(const context& cx, const fs::path& p) auto is_inside = [](auto&& p, auto&& dir) { - const std::string s = p.string(); - const std::string prefix = dir.string(); + const std::string s = path_to_utf8(p); + const std::string prefix = path_to_utf8(dir); if (s.size() < prefix.size()) return false; diff --git a/src/op.h b/src/op.h index 80e8ff7..1dfcd57 100644 --- a/src/op.h +++ b/src/op.h @@ -52,7 +52,7 @@ void copy_glob_to_dir_if_better( const fs::path& src_glob, const fs::path& dest_dir, flags f); std::string read_text_file( - const context& cx, const fs::path& p, flags f=noflags); + const context& cx, encodings e, const fs::path& p, flags f=noflags); void write_text_file( const context& cx, const fs::path& p, std::string_view s, flags f=noflags); diff --git a/src/process.cpp b/src/process.cpp index 20a697f..61916eb 100644 --- a/src/process.cpp +++ b/src/process.cpp @@ -15,12 +15,11 @@ const DWORD process_wait_timeout = 50; HANDLE get_bit_bucket() { SECURITY_ATTRIBUTES sa { .nLength = sizeof(sa), .bInheritHandle = TRUE }; - return ::CreateFileA("NUL", GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0); + return ::CreateFileW(L"NUL", GENERIC_WRITE, 0, &sa, OPEN_EXISTING, 0, 0); } - async_pipe::async_pipe() - : pending_(false) + : pending_(false), closed_(true) { buffer_ = std::make_unique(buffer_size); std::memset(buffer_.get(), 0, buffer_size); @@ -28,6 +27,11 @@ async_pipe::async_pipe() std::memset(&ov_, 0, sizeof(ov_)); } +bool async_pipe::closed() const +{ + return closed_; +} + handle_ptr async_pipe::create() { // creating pipe @@ -44,6 +48,7 @@ handle_ptr async_pipe::create() } event_.reset(ov_.hEvent); + closed_ = false; return out; } @@ -60,8 +65,8 @@ HANDLE async_pipe::create_pipe() { static std::atomic pipe_id(0); - const std::string pipe_name_prefix = "\\\\.\\pipe\\mob_pipe"; - const std::string pipe_name = pipe_name_prefix + std::to_string(++pipe_id); + const std::wstring pipe_name = + L"\\\\.\\pipe\\mob_pipe" + std::to_wstring(++pipe_id); SECURITY_ATTRIBUTES sa = {}; sa.nLength = sizeof(SECURITY_ATTRIBUTES); @@ -71,7 +76,7 @@ HANDLE async_pipe::create_pipe() // creating pipe { - HANDLE pipe_handle = ::CreateNamedPipeA( + HANDLE pipe_handle = ::CreateNamedPipeW( pipe_name.c_str(), PIPE_ACCESS_DUPLEX|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE|PIPE_READMODE_BYTE|PIPE_WAIT, 1, buffer_size, buffer_size, pipe_timeout, &sa); @@ -79,7 +84,7 @@ HANDLE async_pipe::create_pipe() if (pipe_handle == INVALID_HANDLE_VALUE) { const auto e = GetLastError(); - bail_out("CreateNamedPipe failed", error_message(e)); + bail_out("CreateNamedPipeW failed", error_message(e)); } pipe.reset(pipe_handle); @@ -104,7 +109,7 @@ HANDLE async_pipe::create_pipe() // creating handle to pipe which is passed to CreateProcess() - HANDLE output_write = ::CreateFileA( + HANDLE output_write = ::CreateFileW( pipe_name.c_str(), FILE_WRITE_DATA|SYNCHRONIZE, 0, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); @@ -135,7 +140,8 @@ std::string_view async_pipe::try_read() case ERROR_BROKEN_PIPE: { - // broken pipe probably means the process is finished + // broken pipe means the process is finished + closed_ = true; break; } @@ -183,7 +189,8 @@ std::string_view async_pipe::check_pending() case ERROR_BROKEN_PIPE: { - // broken pipe probably means lootcli is finished + // broken pipe means the process is finished + closed_ = true; break; } @@ -222,7 +229,7 @@ process::impl& process::impl::operator=(const impl& i) process::process() - : cx_(&gcx()), flags_(process::noflags), code_(0) + : cx_(&gcx()), unicode_(false), flags_(process::noflags), code_(0) { } @@ -260,7 +267,7 @@ process& process::name(const std::string& name) std::string process::name() const { if (name_.empty()) - return bin_.stem().string(); + return path_to_utf8(bin_.stem()); else return name_; } @@ -323,6 +330,12 @@ process& process::stderr_filter(filter_fun f) return *this; } +process& process::cmd_unicode(bool b) +{ + unicode_ = b; + return *this; +} + process& process::external_error_log(const fs::path& p) { error_log_file_ = p; @@ -359,7 +372,7 @@ std::string process::make_cmd() const if (!raw_.empty()) return raw_; - return "\"" + bin_.string() + "\"" + cmd_; + return "\"" + path_to_utf8(bin_) + "\"" + cmd_; } void process::pipe_into(const process& p) @@ -394,10 +407,10 @@ void process::do_run(const std::string& what) op::delete_file(*cx_, error_log_file_, op::optional); } - STARTUPINFOA si = { .cb=sizeof(si) }; + STARTUPINFOW si = { .cb=sizeof(si) }; PROCESS_INFORMATION pi = {}; - handle_ptr stdout_pipe, stderr_pipe; + handle_ptr stdout_pipe, stderr_pipe, stdin_pipe; switch (stdout_.flags) { @@ -445,28 +458,31 @@ void process::do_run(const std::string& what) } } - si.hStdInput = get_bit_bucket(); + stdin_pipe.reset(get_bit_bucket()); + si.hStdInput = stdin_pipe.get(); + si.dwFlags = STARTF_USESTDHANDLES; - const std::string cmd = this_env::get("COMSPEC"); - const std::string args = "/C \"" + what + "\""; + const std::wstring cmd = utf8_to_utf16(this_env::get("COMSPEC")); + std::wstring args = make_cmd_args(what); - const char* cwd_p = nullptr; - std::string cwd_s; + const wchar_t* cwd_p = nullptr; + std::wstring cwd_s; if (!cwd_.empty()) { op::create_directories(*cx_, cwd_); - cwd_s = cwd_.string(); + cwd_s = cwd_.native(); cwd_p = (cwd_s.empty() ? nullptr : cwd_s.c_str()); } cx_->trace(context::cmd, "creating process"); - const auto r = ::CreateProcessA( - cmd.c_str(), const_cast(args.c_str()), - nullptr, nullptr, TRUE, CREATE_NEW_PROCESS_GROUP, - env_.get_pointers(), cwd_p, &si, &pi); + const auto r = ::CreateProcessW( + cmd.c_str(), args.data(), + nullptr, nullptr, TRUE, + CREATE_NEW_PROCESS_GROUP|CREATE_UNICODE_ENVIRONMENT, + env_.get_unicode_pointers(), cwd_p, &si, &pi); if (!r) { @@ -481,6 +497,18 @@ void process::do_run(const std::string& what) impl_.handle.reset(pi.hProcess); } +std::wstring process::make_cmd_args(const std::string& what) const +{ + std::wstring s; + + if (unicode_) + s += L"/U "; + + s += L"/C \"" + utf8_to_utf16(what) + L"\""; + + return s; +} + void process::interrupt() { impl_.interrupt = true; @@ -523,30 +551,19 @@ void process::join() cx_->trace(context::cmd, "process interrupted and finished"); } -bool process::read_pipes() +void process::read_pipes() { - bool read_something = false; - - if (read_pipe(stdout_, impl_.stdout_pipe, context::std_out)) - read_something = true; - - if (read_pipe(stderr_, impl_.stderr_pipe, context::std_err)) - read_something = true; - - return read_something; + read_pipe(stdout_, impl_.stdout_pipe, context::std_out); + read_pipe(stderr_, impl_.stderr_pipe, context::std_err); } -bool process::read_pipe(stream& s, async_pipe& pipe, context::reason r) +void process::read_pipe(stream& s, async_pipe& pipe, context::reason r) { - bool read_something = false; - switch (s.flags) { case forward_to_log: { const std::string_view buffer = pipe.read(); - if (!buffer.empty()) - read_something = true; for_each_line(buffer, [&](auto&& line) { @@ -562,15 +579,14 @@ bool process::read_pipe(stream& s, async_pipe& pipe, context::reason r) cx_->log(f.r, f.lv, "{}", f.line); }); + s.string.append(buffer.begin(), buffer.end()); + break; } case keep_in_string: { const std::string_view buffer = pipe.read(); - if (!buffer.empty()) - read_something = true; - s.string.append(buffer.begin(), buffer.end()); break; } @@ -579,8 +595,6 @@ bool process::read_pipe(stream& s, async_pipe& pipe, context::reason r) case inherit: break; } - - return read_something; } void process::on_completed() @@ -588,7 +602,9 @@ void process::on_completed() // one last time for (;;) { - if (!read_pipes()) + read_pipes(); + + if (impl_.stdout_pipe.closed() && impl_.stderr_pipe.closed()) break; } @@ -620,6 +636,7 @@ void process::on_completed() else { dump_error_log_file(); + dump_stderr(); cx_->bail_out(context::cmd, "{} returned {}", make_name(), code_); } } @@ -669,7 +686,7 @@ void process::dump_error_log_file() noexcept if (fs::exists(error_log_file_)) { std::string log = op::read_text_file( - *cx_, error_log_file_, op::optional); + *cx_, encodings::dont_know, error_log_file_, op::optional); if (log.empty()) return; @@ -694,6 +711,32 @@ void process::dump_error_log_file() noexcept } } +void process::dump_stderr() noexcept +{ + try + { + if (!stderr_.string.empty()) + { + cx_->error(context::cmd, + "{} failed, content of stderr:", make_name()); + + for_each_line(stderr_.string, [&](auto&& line) + { + cx_->error(context::cmd, " {}", line); + }); + } + else + { + cx_->error(context::cmd, + "{} failed, stderr was empty", make_name()); + } + } + catch(...) + { + // eat it + } +} + int process::exit_code() const { return static_cast(code_); @@ -752,7 +795,7 @@ std::string process::arg_to_string(const std::string& s, bool force_quote) std::string process::arg_to_string(const fs::path& p, bool) { - return "\"" + p.string() + "\""; + return "\"" + path_to_utf8(p) + "\""; } std::string process::arg_to_string(const url& u, bool force_quote) diff --git a/src/process.h b/src/process.h index 745b87b..aa7d027 100644 --- a/src/process.h +++ b/src/process.h @@ -16,7 +16,8 @@ public: async_pipe(); handle_ptr create(); - std::string_view read(); + std::string_view read(); + bool closed() const; private: static const std::size_t buffer_size = 50'000; @@ -26,6 +27,7 @@ private: std::unique_ptr buffer_; OVERLAPPED ov_; bool pending_; + bool closed_; HANDLE create_pipe(); std::string_view try_read(); @@ -111,6 +113,8 @@ public: process& stderr_level(context::level lv); process& stderr_filter(filter_fun f); + process& cmd_unicode(bool b); + process& external_error_log(const fs::path& p); process& flags(flags_t f); @@ -182,6 +186,7 @@ private: std::string name_; fs::path bin_; fs::path cwd_; + bool unicode_; flags_t flags_; stream stdout_; stream stderr_; @@ -195,15 +200,17 @@ private: std::string make_name() const; std::string make_cmd() const; + std::wstring make_cmd_args(const std::string& what) const; void pipe_into(const process& p); void do_run(const std::string& what); - bool read_pipes(); - bool read_pipe(stream& s, async_pipe& pipe, context::reason r); + void read_pipes(); + void read_pipe(stream& s, async_pipe& pipe, context::reason r); void on_completed(); void on_timeout(bool& already_interrupted); void dump_error_log_file() noexcept; + void dump_stderr() noexcept; void add_arg(const std::string& k, const std::string& v, arg_flags f); diff --git a/src/tasks/pyqt.cpp b/src/tasks/pyqt.cpp index 1f6ab00..a21767a 100644 --- a/src/tasks/pyqt.cpp +++ b/src/tasks/pyqt.cpp @@ -111,8 +111,8 @@ void pyqt::sip_build() python::source_path(), python::scripts_path()}) .set("CL", " /MP") - .set("LIB", ";" + paths::install_libs().string(), env::append) - .set("PYTHONHOME", python::source_path().string()); + .set("LIB", ";" + path_to_utf8(paths::install_libs()), env::append) + .set("PYTHONHOME", path_to_utf8(python::source_path())); bypass_file built_bypass(cx(), source_path(), "built"); diff --git a/src/tasks/python.cpp b/src/tasks/python.cpp index 7a8c81c..71a7892 100644 --- a/src/tasks/python.cpp +++ b/src/tasks/python.cpp @@ -127,12 +127,12 @@ void python::build_and_install_from_source() "python", "pythonw", "python3dll", "select", "pyexpat", "unicodedata", "_queue", "_bz2", "_ssl"}) .parameters({ - "bz2Dir=" + bzip2::source_path().string(), - "zlibDir=" + zlib::source_path().string(), - "opensslIncludeDir=" + openssl::include_path().string(), - "opensslOutDir=" + openssl::source_path().string(), - "libffiIncludeDir=" + libffi::include_path().string(), - "libffiOutDir=" + libffi::lib_path().string()})); + "bz2Dir=" + path_to_utf8(bzip2::source_path()), + "zlibDir=" + path_to_utf8(zlib::source_path()), + "opensslIncludeDir=" + path_to_utf8(openssl::include_path()), + "opensslOutDir=" + path_to_utf8(openssl::source_path()), + "libffiIncludeDir=" + path_to_utf8(libffi::include_path()), + "libffiOutDir=" + path_to_utf8(libffi::lib_path())})); package(); install_pip(); diff --git a/src/tasks/zlib.cpp b/src/tasks/zlib.cpp index 7d7c985..69d8819 100644 --- a/src/tasks/zlib.cpp +++ b/src/tasks/zlib.cpp @@ -41,13 +41,12 @@ void zlib::do_fetch() void zlib::do_build_and_install() { const auto build_path = run_tool(cmake() - .generator(cmake::jom) + .generator(cmake::vs) .root(source_path()) .prefix(source_path())); - run_tool(jom() - .path(build_path) - .target("install")); + run_tool(msbuild() + .solution(source_path() / "vsbuild" / "INSTALL.vcxproj")); op::copy_file_to_dir_if_better(cx(), build_path / "zconf.h", diff --git a/src/tools/cmake.cpp b/src/tools/cmake.cpp index 49e6905..cb6c866 100644 --- a/src/tools/cmake.cpp +++ b/src/tools/cmake.cpp @@ -37,7 +37,7 @@ cmake& cmake::def(const std::string& name, const std::string& value) cmake& cmake::def(const std::string& name, const fs::path& p) { - def(name, p.string()); + def(name, path_to_utf8(p)); return *this; } diff --git a/src/tools/extractor.cpp b/src/tools/extractor.cpp index a874e0e..e7b6ef2 100644 --- a/src/tools/extractor.cpp +++ b/src/tools/extractor.cpp @@ -67,7 +67,7 @@ void extractor::do_run() // so the handling of a duplicate directory is done manually in // check_duplicate_directory() below - if (file_.string().ends_with(".tar.gz")) + if (file_.u8string().ends_with(u8".tar.gz")) { cx_->trace(context::generic, "this is a tar.gz, piping"); @@ -109,7 +109,7 @@ void extractor::do_run() void extractor::check_duplicate_directory(const fs::path& ifile) { - const auto dir_name = where_.filename().string(); + const auto dir_name = where_.filename(); // check for a folder with the same name if (!fs::exists(where_ / dir_name)) @@ -160,7 +160,7 @@ void extractor::check_duplicate_directory(const fs::path& ifile) // give it a temp name in case there's yet another directory with the // same name in it - const auto temp_dir = where_ / ("_mob_" + dir_name ); + const auto temp_dir = where_ / (u8"_mob_" + dir_name.u8string()); cx_->trace(context::generic, "renaming dir to {} to avoid clashes", temp_dir); diff --git a/src/tools/process_runner.cpp b/src/tools/process_runner.cpp index f981cf5..acd377b 100644 --- a/src/tools/process_runner.cpp +++ b/src/tools/process_runner.cpp @@ -25,6 +25,7 @@ int basic_process_runner::execute_and_join() process_.set_context(cx_); process_.run(); join(); + return process_.exit_code(); } diff --git a/src/utility.cpp b/src/utility.cpp index 1f9a4ba..2f31c9a 100644 --- a/src/utility.cpp +++ b/src/utility.cpp @@ -483,7 +483,7 @@ std::string cp_to_utf8(std::string_view s) return *s8; } -std::string path_to_utf8(const fs::path& p) +std::string path_to_utf8(fs::path p) { return utf16_to_utf8(p.native()); } diff --git a/src/utility.h b/src/utility.h index fcb63e0..23206a6 100644 --- a/src/utility.h +++ b/src/utility.h @@ -32,6 +32,14 @@ inline void mob_assert( } +enum class encodings +{ + dont_know = 0, + utf8, + utf16 +}; + + class context; class url; @@ -214,7 +222,11 @@ std::string trim_copy(const std::string& s, const std::string& what=" \t\r\n"); std::wstring utf8_to_utf16(std::string_view s); std::string utf16_to_utf8(std::wstring_view ws); -std::string path_to_utf8(const fs::path& p); + +template +std::string path_to_utf8(T&&) = delete; + +std::string path_to_utf8(fs::path p); class u8stream diff --git a/vs/mob.vcxproj b/vs/mob.vcxproj index 729d6b7..a953391 100644 --- a/vs/mob.vcxproj +++ b/vs/mob.vcxproj @@ -22,13 +22,13 @@ Application true v142 - MultiByte + Unicode Application false v142 - MultiByte + Unicode