mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
Read the Wine version without Boost.Process
By spawning the process using posix_spawn and manually reading from a pipe.
This commit is contained in:
+65
-42
@@ -83,14 +83,35 @@ bp::environment PluginInfo::create_host_env() const {
|
||||
return env;
|
||||
}
|
||||
|
||||
ProcessEnvironment PluginInfo::create_host_env_2() const {
|
||||
ProcessEnvironment env(environ);
|
||||
|
||||
// Only set the prefix when could auto detect it and it's not being
|
||||
// overridden (this entire `std::visit` instead of `std::has_alternative` is
|
||||
// just for clarity's sake)
|
||||
std::visit(overload{
|
||||
[](const OverridenWinePrefix&) {},
|
||||
[&](const ghc::filesystem::path& prefix) {
|
||||
env.insert("WINEPREFIX", prefix.string());
|
||||
},
|
||||
[](const DefaultWinePrefix&) {},
|
||||
},
|
||||
wine_prefix_);
|
||||
|
||||
return env;
|
||||
}
|
||||
|
||||
ghc::filesystem::path PluginInfo::normalize_wine_prefix() const {
|
||||
return std::visit(
|
||||
overload{
|
||||
[](const OverridenWinePrefix& prefix) { return prefix.value; },
|
||||
[](const ghc::filesystem::path& prefix) { return prefix; },
|
||||
[](const DefaultWinePrefix&) {
|
||||
const bp::environment env = boost::this_process::environment();
|
||||
return fs::path(env.at("HOME").to_string()) / ".wine";
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
const char* home_dir = getenv("HOME");
|
||||
assert(home_dir);
|
||||
|
||||
return fs::path(home_dir) / ".wine";
|
||||
},
|
||||
},
|
||||
wine_prefix_);
|
||||
@@ -99,38 +120,40 @@ ghc::filesystem::path PluginInfo::normalize_wine_prefix() const {
|
||||
std::string PluginInfo::wine_version() const {
|
||||
// The '*.exe' scripts generated by winegcc allow you to override the binary
|
||||
// used to run Wine, so will will handle this in the same way for our Wine
|
||||
// version detection
|
||||
// FIXME: Replace Boost.Filesystem usage
|
||||
boost::filesystem::path wine_path;
|
||||
bp::environment env = create_host_env();
|
||||
if (const std::string wineloader_path = env["WINELOADER"].to_string();
|
||||
access(wineloader_path.c_str(), X_OK) == 0) {
|
||||
// version detection. We'll be using `execvpe`
|
||||
std::string wine_path = "wine";
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
if (const char* wineloader_path = getenv("WINELOADER");
|
||||
wineloader_path && access(wineloader_path, X_OK) == 0) {
|
||||
wine_path = wineloader_path;
|
||||
} else {
|
||||
wine_path = bp::search_path("wine").string();
|
||||
}
|
||||
|
||||
bp::ipstream output;
|
||||
try {
|
||||
bp::system(wine_path, "--version", bp::std_out = output, bp::env = env,
|
||||
bp::posix::use_vfork);
|
||||
} catch (const std::system_error&) {
|
||||
return "<NOT FOUND>";
|
||||
}
|
||||
Process process(wine_path);
|
||||
process.arg("--version");
|
||||
process.environment(create_host_env_2());
|
||||
|
||||
// `wine --version` might contain additional output in certain custom Wine
|
||||
// builds, so we only want to look at the first line
|
||||
std::string version_string;
|
||||
std::getline(output, version_string);
|
||||
auto result = process.spawn_get_stdout_line();
|
||||
return std::visit(
|
||||
overload{
|
||||
[](std::string version_string) -> std::string {
|
||||
// Strip the `wine-` prefix from the output, could potentially
|
||||
// be absent in custom Wine builds
|
||||
constexpr std::string_view version_prefix("wine-");
|
||||
if (version_string.starts_with(version_prefix)) {
|
||||
version_string =
|
||||
version_string.substr(version_prefix.size());
|
||||
}
|
||||
|
||||
// Strip the `wine-` prefix from the output, could potentially be absent in
|
||||
// custom Wine builds
|
||||
constexpr std::string_view version_prefix("wine-");
|
||||
if (version_string.starts_with(version_prefix)) {
|
||||
version_string = version_string.substr(version_prefix.size());
|
||||
}
|
||||
|
||||
return version_string;
|
||||
return version_string;
|
||||
},
|
||||
[](const Process::CommandNotFound&) -> std::string {
|
||||
return "<NOT FOUND>";
|
||||
},
|
||||
[](const std::error_code& err) -> std::string {
|
||||
return "<ERROR SPAWNING WINE: " + err.message() + " >";
|
||||
},
|
||||
},
|
||||
result);
|
||||
}
|
||||
|
||||
fs::path find_plugin_library(const fs::path& this_plugin_path,
|
||||
@@ -256,9 +279,9 @@ fs::path normalize_plugin_path(const fs::path& windows_library_path,
|
||||
|
||||
std::variant<OverridenWinePrefix, fs::path, DefaultWinePrefix> find_wine_prefix(
|
||||
fs::path windows_plugin_path) {
|
||||
const bp::environment env = boost::this_process::environment();
|
||||
if (const auto prefix = env.find("WINEPREFIX"); prefix != env.end()) {
|
||||
return OverridenWinePrefix{prefix->to_string()};
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
if (const auto prefix = getenv("WINEPREFIX")) {
|
||||
return OverridenWinePrefix{prefix};
|
||||
}
|
||||
|
||||
const std::optional<fs::path> dosdevices_dir = find_dominating_file(
|
||||
@@ -411,16 +434,14 @@ std::vector<boost::filesystem::path> get_augmented_search_path() {
|
||||
std::vector<boost::filesystem::path> search_path =
|
||||
boost::this_process::path();
|
||||
|
||||
const bp::environment environment = boost::this_process::environment();
|
||||
if (auto xdg_data_home = environment.find("XDG_DATA_HOME");
|
||||
xdg_data_home != environment.end()) {
|
||||
search_path.push_back(
|
||||
boost::filesystem::path(xdg_data_home->to_string()) / "yabridge");
|
||||
} else if (auto home_directory = environment.find("HOME");
|
||||
home_directory != environment.end()) {
|
||||
search_path.push_back(
|
||||
boost::filesystem::path(home_directory->to_string()) / ".local" /
|
||||
"share" / "yabridge");
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
if (const char* xdg_data_home = getenv("XDG_DATA_HOME")) {
|
||||
search_path.push_back(boost::filesystem::path(xdg_data_home) /
|
||||
"yabridge");
|
||||
// NOLINTNEXTLINE(concurrency-mt-unsafe)
|
||||
} else if (const char* home_directory = getenv("HOME")) {
|
||||
search_path.push_back(boost::filesystem::path(home_directory) /
|
||||
".local" / "share" / "yabridge");
|
||||
}
|
||||
|
||||
return search_path;
|
||||
@@ -472,6 +493,8 @@ bool send_notification(const std::string& title,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Also use a custom process here, and wrap the above code in a
|
||||
// class
|
||||
try {
|
||||
return bp::system(notify_send_path, "--urgency=normal",
|
||||
"--expire-time=15000", "--app-name=yabridge", title,
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "../common/configuration.h"
|
||||
#include "../common/plugins.h"
|
||||
#include "../common/process.h"
|
||||
#include "../common/utils.h"
|
||||
|
||||
/**
|
||||
@@ -76,6 +77,8 @@ struct PluginInfo {
|
||||
* unset if we could not detect a prefix.
|
||||
*/
|
||||
boost::process::environment create_host_env() const;
|
||||
// FIXME: Replace create_host_env with this one
|
||||
ProcessEnvironment create_host_env_2() const;
|
||||
|
||||
/**
|
||||
* Return the path to the actual Wine prefix in use, taking into account
|
||||
|
||||
Reference in New Issue
Block a user