From 585329541c7915418e80df14851199696e6f140e Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 16 Apr 2022 20:12:58 +0200 Subject: [PATCH] [yabridgectl] Update to use chainloader libraries --- CHANGELOG.md | 8 ++++ tools/yabridgectl/src/actions.rs | 49 ++++++++++++----------- tools/yabridgectl/src/config.rs | 68 ++++++++++++++++---------------- tools/yabridgectl/src/files.rs | 16 ++++---- tools/yabridgectl/src/main.rs | 6 +-- tools/yabridgectl/src/utils.rs | 2 +- 6 files changed, 79 insertions(+), 70 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18fcae6d..09d50125 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,14 @@ Versioning](https://semver.org/spec/v2.0.0.html). - Some of yabridge's socket file names contained extremely aesthetically unpleasing trailing underscores. Begone pesky underscores! +### yabridgectl + +- As mentioned above, yabridgectl will now use the new chainloading libraries + when setting up plugins. This means that once you've ran `yabridgectl sync` + once after updating to yabridge 4.0, yabridge can now be updated without + needing to rerun `yabridgectl sync`. This is particularly useful when using a + distro packaged version of yabridge. + ### Packaging notes - Completely removed the dependency on all Boost libraries. diff --git a/tools/yabridgectl/src/actions.rs b/tools/yabridgectl/src/actions.rs index 73f57301..6f04e83a 100644 --- a/tools/yabridgectl/src/actions.rs +++ b/tools/yabridgectl/src/actions.rs @@ -101,14 +101,15 @@ pub fn show_status(config: &Config) -> Result<()> { let files = config.files(); match &files { Ok(files) => { + // TOOD: Also include the architecture here to avoid confusion println!( - "libyabridge-vst2.so: '{}'", - files.libyabridge_vst2.display() + "libyabridge-chainloader-vst2.so: '{}'", + files.vst2_chainloader.display() ); println!( - "libyabridge-vst3.so: {}\n", + "libyabridge-chainloader-vst3.so: {}\n", files - .libyabridge_vst3 + .vst3_chainloader .as_ref() .map(|(path, arch)| format!("'{}' ({})", path.display(), arch)) .unwrap_or_else(|| "".red().to_string()) @@ -230,8 +231,8 @@ pub struct SyncOptions { /// `.so` files if the prune option is set. pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> { let files: YabridgeFiles = config.files()?; - let libyabridge_vst2_hash = utils::hash_file(&files.libyabridge_vst2)?; - let libyabridge_vst3_hash = match &files.libyabridge_vst3 { + let vst2_chainloader_hash = utils::hash_file(&files.vst2_chainloader)?; + let vst3_chainloader_hash = match &files.vst3_chainloader { Some((path, _)) => Some(utils::hash_file(path)?), None => None, }; @@ -250,13 +251,13 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> { ); } - if let Some((libyabridge_vst3_path, _)) = &files.libyabridge_vst3 { + if let Some((vst3_chainloader_path, _)) = &files.vst3_chainloader { println!("Setting up VST2 and VST3 plugins using:"); - println!("- {}", files.libyabridge_vst2.display()); - println!("- {}\n", libyabridge_vst3_path.display()); + println!("- {}", files.vst2_chainloader.display()); + println!("- {}\n", vst3_chainloader_path.display()); } else { println!("Setting up VST2 plugins using:"); - println!("- {}\n", files.libyabridge_vst2.display()); + println!("- {}\n", files.vst2_chainloader.display()); } let results = config @@ -273,14 +274,14 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> { // `utils::normalize_path()` so that the reported numbers are still correct when encountering // overlapping symlinked paths. let mut managed_plugins: HashSet = HashSet::new(); - // The plugins we created a new copy of `libyabridge-{vst2,vst3}.so` for. We don't touch these - // files if they're already up to date to prevent hosts from unnecessarily rescanning the - // plugins. + // The plugins we created a new copy of `libyabridge-chainloader-{vst2,vst3}.so` for. We don't + // touch these files if they're already up to date to prevent hosts from unnecessarily + // rescanning the plugins. let mut new_plugins: HashSet = HashSet::new(); // The files we skipped during the scan because they turned out to not be plugins let mut skipped_dll_files: Vec = Vec::new(); // `.so` files and unused VST3 modules we found during scanning that didn't have a corresponding - // copy or symlink of `libyabridge-vst2.so` + // copy or symlink of `libyabridge-chainloader-vst2.so` let mut orphan_files: Vec = Vec::new(); // Since VST3 bundles contain multiple files from multiple sources (native library files from // yabridge, and symlinks to Windows VST3 modules or bundles), cleaning up orphan VST3 files is @@ -319,8 +320,8 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> { if install_file( options.force, config.method, - &files.libyabridge_vst2, - Some(libyabridge_vst2_hash), + &files.vst2_chainloader, + Some(vst2_chainloader_hash), &target_path, )? { new_plugins.insert(normalized_target_path.clone()); @@ -333,7 +334,7 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> { // https://developer.steinberg.help/display/VST/Plug-in+Format+Structure#PluginFormatStructure-MergedBundle Plugin::Vst3(module) => { // Only set up VST3 plugins when yabridge has been compiled with VST3 support - if libyabridge_vst3_hash.is_none() { + if vst3_chainloader_hash.is_none() { continue; } @@ -372,15 +373,15 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> { } // We're building a merged VST3 bundle containing both a copy or symlink to - // `libyabridge-vst3.so` and the Windows VST3 plugin. The path to this native - // module will depend on whether `libyabridge-vst3.so` is a 32-bit or a 64-bit - // library file. + // `libyabridge-chainloader-vst3.so` and the Windows VST3 plugin. The path to + // this native module will depend on whether `libyabridge-chainloader-vst3.so` + // is a 32-bit or a 64-bit library file. utils::create_dir_all(target_native_module_path.parent().unwrap())?; if install_file( options.force, config.method, - &files.libyabridge_vst3.as_ref().unwrap().0, - libyabridge_vst3_hash, + &files.vst3_chainloader.as_ref().unwrap().0, + vst3_chainloader_hash, &target_native_module_path, )? { // We're counting the native `.so` files and not the Windows VST3 plugins @@ -557,8 +558,8 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> { return Ok(()); } - // The path setup is to make sure that the `libyabridge-{vst2,vst3}.so` copies can find - // `yabridge-host.exe` + // The path setup is to make sure that the `libyabridge-chainloader-{vst2,vst3}.so` copies can + // find `yabridge-host.exe` if config.method == InstallationMethod::Copy { verify_path_setup(config)?; } diff --git a/tools/yabridgectl/src/config.rs b/tools/yabridgectl/src/config.rs index 3e3b495d..deaff44a 100644 --- a/tools/yabridgectl/src/config.rs +++ b/tools/yabridgectl/src/config.rs @@ -36,10 +36,10 @@ pub const CONFIG_FILE_NAME: &str = "config.toml"; /// `$XDG_DATA_HOME`. const YABRIDGECTL_PREFIX: &str = "yabridgectl"; -/// The name of yabridge's VST2 library. -pub const LIBYABRIDGE_VST2_NAME: &str = "libyabridge-vst2.so"; -/// The name of yabridge's VST3 library. -pub const LIBYABRIDGE_VST3_NAME: &str = "libyabridge-vst3.so"; +/// The name of yabridge's VST2 chainloading library yabridgectl will create copies of. +pub const VST2_CHAINLOADER_NAME: &str = "libyabridge-chainloader-vst2.so"; +/// The name of yabridge's VST3 chainloading library yabridgectl will create copies of. +pub const VST3_CHAINLOADER_NAME: &str = "libyabridge-chainloader-vst3.so"; /// The name of the script we're going to run to verify that everything's working correctly. pub const YABRIDGE_HOST_EXE_NAME: &str = "yabridge-host.exe"; /// The 32-bit verison of `YABRIDGE_HOST_EXE_NAME`. If `~/.wine` was somehow created with @@ -63,9 +63,9 @@ pub struct Config { /// The installation method to use. We will default to creating copies since that works /// everywhere. pub method: InstallationMethod, - /// The path to the directory containing `libyabridge-{vst2,vst3}.so`. If not set, then - /// yabridgectl will look in `/usr/lib` and `$XDG_DATA_HOME/yabridge` since those are the - /// expected locations for yabridge to be installed in. + /// The path to the directory containing `libyabridge-{chainloader,}-{vst2,vst3}.so`. If not + /// set, then yabridgectl will look in `/usr/lib` and `$XDG_DATA_HOME/yabridge` since those are + /// the expected locations for yabridge to be installed in. pub yabridge_home: Option, /// Directories to search for Windows VST plugins. These directories can contain both VST2 /// plugin `.dll` files and VST3 modules (which should be located in `/drive_c/Program @@ -90,12 +90,12 @@ pub struct Config { #[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone, Copy)] #[serde(rename_all = "snake_case")] pub enum InstallationMethod { - /// Create a copy of `libyabridge-{vst2,vst3}.so` for every Windows VST2 plugin `.dll` file or - /// VST3 module found. After updating yabridge, the user will have to rerun `yabridgectl sync` - /// to copy over the new version. + /// Create a copy of `libyabridge-chainloader-{vst2,vst3}.so` for every Windows VST2 plugin + /// `.dll` file or VST3 module found. After updating yabridge, the user will have to rerun + /// `yabridgectl sync` to copy over the new version. Copy, - /// This will create a symlink to `libyabridge-{vst2,vst3}.so` for every VST2 plugin `.dll` file - /// or VST3 module in the plugin directories. Now that yabridge also searches in + /// This will create a symlink to `libyabridge-chainloader-{vst2,vst3}.so` for every VST2 plugin + /// `.dll` file or VST3 module in the plugin directories. Now that yabridge also searches in /// `~/.local/share/yabridge` since yabridge 2.1 this option is not really needed anymore. /// /// TODO: This feature has been deprecated, remove it in yabridge 4.0 @@ -147,12 +147,12 @@ pub struct KnownConfig { /// `Config::files`. #[derive(Debug)] pub struct YabridgeFiles { - /// The path to `libyabridge-vst2.so` we should use. - pub libyabridge_vst2: PathBuf, - /// The path to `libyabridge-vst3.so` we should use, if yabridge has been compiled with VST3 - /// support. We need to know if it's a 32-bit or a 64-bit library so we can properly set up the - /// merged VST3 bundles. - pub libyabridge_vst3: Option<(PathBuf, LibArchitecture)>, + /// The path to `libyabridge-chainloader-vst2.so` we should use. + pub vst2_chainloader: PathBuf, + /// The path to `libyabridge-chainloader-vst3.so` we should use, if yabridge has been compiled + /// with VST3 support. We need to know if it's a 32-bit or a 64-bit library so we can properly + /// set up the merged VST3 bundles. + pub vst3_chainloader: Option<(PathBuf, LibArchitecture)>, /// The path to `yabridge-host.exe`. This is the path yabridge will actually use, and it does /// not have to be relative to `yabridge_home`. pub yabridge_host_exe: Option, @@ -220,16 +220,16 @@ impl Config { pub fn files(&self) -> Result { let xdg_dirs = yabridge_directories()?; - // First find `libyabridge-vst2.so` - let libyabridge_vst2: PathBuf = match &self.yabridge_home { + // First find `libyabridge-chainloader-vst2.so` + let vst2_chainloader: PathBuf = match &self.yabridge_home { Some(directory) => { - let candidate = directory.join(LIBYABRIDGE_VST2_NAME); + let candidate = directory.join(VST2_CHAINLOADER_NAME); if candidate.exists() { candidate } else { return Err(anyhow!( "Could not find '{}' in '{}'", - LIBYABRIDGE_VST2_NAME, + VST2_CHAINLOADER_NAME, directory.display() )); } @@ -238,7 +238,7 @@ impl Config { // Search in the system library locations and in `~/.local/share/yabridge` if no // path was set explicitely. We'll also search through `/usr/local/lib` just in case // but since we advocate against installing yabridge there we won't list this path - // in the error message when `libyabridge-vst2.so` can't be found. + // in the error message when `libyabridge-chainloader-vst2.so` can't be found. let system_path = Path::new("/usr/lib"); let user_path = xdg_dirs.get_data_home(); let lib_directories = [ @@ -254,14 +254,14 @@ impl Config { ]; let mut candidates = lib_directories .iter() - .map(|directory| directory.join(LIBYABRIDGE_VST2_NAME)); + .map(|directory| directory.join(VST2_CHAINLOADER_NAME)); match candidates.find(|directory| directory.exists()) { Some(candidate) => candidate, _ => { return Err(anyhow!( "Could not find '{}' in either '{}' or '{}'. You can override the \ default search path using 'yabridgectl set --path='.", - LIBYABRIDGE_VST2_NAME, + VST2_CHAINLOADER_NAME, system_path.display(), user_path.display() )); @@ -270,12 +270,12 @@ impl Config { } }; - // Based on that we can check if `libyabridge-vst3.so` exists, since yabridge can be - // compiled without VST3 support - let libyabridge_vst3 = match libyabridge_vst2.with_file_name(LIBYABRIDGE_VST3_NAME) { + // Based on that we can check if `libyabridge-chainloader-vst3.so` exists, since yabridge + // can be compiled without VST3 support + let vst3_chainloader = match vst2_chainloader.with_file_name(VST3_CHAINLOADER_NAME) { path if path.exists() => { - // We need to know `libyabridge-vst3.so`'s architecture to be able to set up the - // bundle properly + // We need to know `libyabridge-chainloader-vst3.so`'s architecture to be able to + // set up the bundle properly. 32-bit builds of yabridge are technically supported. let arch = utils::get_elf_architecture(&path).with_context(|| { format!( "Could not determine ELF architecture for '{}'", @@ -300,8 +300,8 @@ impl Config { .map(|path| path.with_extension("exe.so")); Ok(YabridgeFiles { - libyabridge_vst2, - libyabridge_vst3, + vst2_chainloader, + vst3_chainloader, yabridge_host_exe, yabridge_host_exe_so, yabridge_host_32_exe, @@ -326,8 +326,8 @@ impl Config { } /// Fetch the XDG base directories for yabridge's own files, converting any error messages if this -/// somehow fails into a printable string to reduce boiler plate. This is only used when searching -/// for `libyabridge-{vst2,vst3}.so` when no explicit search path has been set. +/// somehow fails into a printable string to reduce boiler plate. This is used when searching for +/// `libyabridge-chainloader-{vst2,vst3}.so` when no explicit search path has been set. pub fn yabridge_directories() -> Result { BaseDirectories::with_prefix(YABRIDGE_PREFIX).context("Error while parsing base directories") } diff --git a/tools/yabridgectl/src/files.rs b/tools/yabridgectl/src/files.rs index be130c52..d57448ce 100644 --- a/tools/yabridgectl/src/files.rs +++ b/tools/yabridgectl/src/files.rs @@ -188,10 +188,10 @@ impl Vst3Module { } } - /// Get the path to the `libyabridge.so` file in `~/.vst3` corresponding to the bridged version - /// of this module. The path here depends on whether we're using a 32-bit or 64-bit version of - /// yabridge. If the configuration is not given (for instance, becuase yabridge is not set up - /// properly) we'll assume the module should be 64-bit. + /// Get the path to the renamed `plugin.so` file in `~/.vst3` corresponding to the bridged + /// version of this module. The path here depends on whether we're using a 32-bit or 64-bit + /// version of yabridge. If the configuration is not given (for instance, becuase yabridge is + /// not set up properly) we'll assume the module should be 64-bit. pub fn target_native_module_path(&self, config: Option<&YabridgeFiles>) -> PathBuf { let native_module_name = match &self.module { Vst3ModuleType::Legacy(path) | Vst3ModuleType::Bundle(path) => path @@ -207,11 +207,11 @@ impl Vst3Module { path.push("Contents"); #[allow(clippy::wildcard_in_or_patterns)] - match config.and_then(|c| c.libyabridge_vst3.as_ref()) { + match config.and_then(|c| c.vst3_chainloader.as_ref()) { Some((_, LibArchitecture::Lib32)) => path.push("i386-linux"), - // NOTE: We'll always fall back to this if `libyabridge-vst3.so` is not found, just so - // we cannot get any errors during `yabridgectl status` even if yabridge is not - // set up correctly. + // NOTE: We'll always fall back to this if `libyabridge-chainloader-vst3.so` is not + // found, just so we cannot get any errors during `yabridgectl status` even if + // yabridge is not set up correctly. Some((_, LibArchitecture::Lib64)) | _ => path.push("x86_64-linux"), } diff --git a/tools/yabridgectl/src/main.rs b/tools/yabridgectl/src/main.rs index db949598..9da08d89 100644 --- a/tools/yabridgectl/src/main.rs +++ b/tools/yabridgectl/src/main.rs @@ -148,10 +148,10 @@ fn main() -> Result<()> { .arg( Arg::new("path") .long("path") - .help("Path to the directory containing 'libyabridge-{vst2,vst3}.so'") + .help("Path to the directory containing 'libyabridge-chainloader-{vst2,vst3}.so'") .long_help( - "Path to the directory containing 'libyabridge-{vst2,vst3}.so'. If this \ - is not set, then yabridgectl will look in both '/usr/lib' and \ + "Path to the directory containing 'libyabridge-chainloader-{vst2,vst3}.so'. \ + If this is not set, then yabridgectl will look in both '/usr/lib' and \ '~/.local/share/yabridge' by default.", ) .validator(validate_path) diff --git a/tools/yabridgectl/src/utils.rs b/tools/yabridgectl/src/utils.rs index 0888e47a..ab8d189e 100644 --- a/tools/yabridgectl/src/utils.rs +++ b/tools/yabridgectl/src/utils.rs @@ -295,7 +295,7 @@ pub fn verify_path_setup(config: &Config) -> Result { reboot your system to complete the setup.\n\ \n\ https://github.com/robbert-vdh/yabridge#troubleshooting-common-issues", - config.files()?.libyabridge_vst2.parent().unwrap().display(), + config.files()?.vst2_chainloader.parent().unwrap().display(), shell.bright_white(), "PATH".bright_white() ))