mirror of
https://github.com/robbert-vdh/yabridge.git
synced 2026-05-07 03:50:11 +02:00
[yabridgectl] Determine libyabridge-vst3.so arch
We're going to need this for supporting merged VST3 bundles with a 32-bit libyabridge-vst3.so.
This commit is contained in:
@@ -108,7 +108,7 @@ pub fn show_status(config: &Config) -> Result<()> {
|
||||
"libyabridge-vst3.so: {}\n",
|
||||
files
|
||||
.libyabridge_vst3
|
||||
.map(|path| format!("'{}'", path.display()))
|
||||
.map(|(path, arch)| format!("'{}' ({})", path.display(), arch))
|
||||
.unwrap_or_else(|| "<not found>".red().to_string())
|
||||
);
|
||||
}
|
||||
@@ -204,11 +204,11 @@ 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 {
|
||||
Some(path) => Some(utils::hash_file(path)?),
|
||||
Some((path, _)) => Some(utils::hash_file(path)?),
|
||||
None => None,
|
||||
};
|
||||
|
||||
if let Some(libyabridge_vst3_path) = &files.libyabridge_vst3 {
|
||||
if let Some((libyabridge_vst3_path, _)) = &files.libyabridge_vst3 {
|
||||
println!("Setting up VST2 and VST3 plugins using:");
|
||||
println!("- {}", files.libyabridge_vst2.display());
|
||||
println!("- {}\n", libyabridge_vst3_path.display());
|
||||
@@ -308,7 +308,7 @@ pub fn do_sync(config: &mut Config, options: &SyncOptions) -> Result<()> {
|
||||
if install_file(
|
||||
options.force,
|
||||
config.method,
|
||||
files.libyabridge_vst3.as_ref().unwrap(),
|
||||
&files.libyabridge_vst3.as_ref().unwrap().0,
|
||||
libyabridge_vst3_hash,
|
||||
&native_module_path,
|
||||
)? || *updated_libyabridge
|
||||
|
||||
@@ -27,7 +27,8 @@ use std::path::{Path, PathBuf};
|
||||
use which::which;
|
||||
use xdg::BaseDirectories;
|
||||
|
||||
use crate::files::{self, SearchResults};
|
||||
use crate::files::{self, LibArchitecture, SearchResults};
|
||||
use crate::utils;
|
||||
|
||||
/// The name of the config file, relative to `$XDG_CONFIG_HOME/YABRIDGECTL_PREFIX`.
|
||||
pub const CONFIG_FILE_NAME: &str = "config.toml";
|
||||
@@ -143,8 +144,9 @@ 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.
|
||||
pub libyabridge_vst3: Option<PathBuf>,
|
||||
/// 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 `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: PathBuf,
|
||||
@@ -260,7 +262,18 @@ 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) {
|
||||
path if path.exists() => Some(path),
|
||||
path if path.exists() => {
|
||||
// We need to know `libyabridge-vst3.so`'s architecture to be able to set up the
|
||||
// bundle properly
|
||||
let arch = utils::get_elf_architecture(&path).with_context(|| {
|
||||
format!(
|
||||
"Could not determine ELF architecture for '{}'",
|
||||
path.display()
|
||||
)
|
||||
})?;
|
||||
|
||||
Some((path, arch))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
|
||||
//! Small helper utilities.
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use colored::Colorize;
|
||||
use is_executable::IsExecutable;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::hash::Hasher;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::os::unix::fs as unix_fs;
|
||||
use std::os::unix::process::CommandExt;
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -30,7 +31,7 @@ use std::process::{Command, Stdio};
|
||||
use textwrap::Wrapper;
|
||||
|
||||
use crate::config::{self, Config, KnownConfig, YABRIDGE_HOST_EXE_NAME};
|
||||
use crate::files::NativeFile;
|
||||
use crate::files::{LibArchitecture, NativeFile};
|
||||
|
||||
/// (Part of) the expected output when running `yabridge-host.exe`. Used to verify that everything's
|
||||
/// working correctly. We'll only match this prefix so we can modify the exact output at a later
|
||||
@@ -86,6 +87,41 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> Result<()> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the architecture of the ELF file at `path`. This detection is a bit naive, but we'd rather
|
||||
/// not depend on `libmagic` or `libreadelf` just for this, since encountering a 32-bit yabridge
|
||||
/// library is going to be incredibly rare.
|
||||
///
|
||||
/// This is based on this file header specification:
|
||||
/// https://en.wikipedia.org/wiki/Executable_and_Linkable_Format#File_header
|
||||
pub fn get_elf_architecture(path: &Path) -> Result<LibArchitecture> {
|
||||
// We'll assume `path` points to an ELF file and immediately skip to the good stuff
|
||||
let mut file = fs::File::open(path)?;
|
||||
|
||||
// I doubt yabridge will ever run on a Big-Endian machine until audio production on Windows on
|
||||
// ARM also becomes big, but we still need to account for this
|
||||
let little_endian = {
|
||||
let mut endianness_bytes = [0u8; 1];
|
||||
file.seek(SeekFrom::Start(0x05))?; // e_ident[EI_DATA], 1 byte
|
||||
file.read_exact(&mut endianness_bytes)?;
|
||||
endianness_bytes[0] == 1
|
||||
};
|
||||
|
||||
let mut machine_arch_bytes = [0u8; 2];
|
||||
file.seek(SeekFrom::Start(0x12))?; // e_machine, 2 bytes
|
||||
file.read_exact(&mut machine_arch_bytes)?;
|
||||
|
||||
let machine_arch = if little_endian {
|
||||
u16::from_le_bytes(machine_arch_bytes)
|
||||
} else {
|
||||
u16::from_be_bytes(machine_arch_bytes)
|
||||
};
|
||||
match machine_arch {
|
||||
0x03 => Ok(LibArchitecture::Lib32), // x86
|
||||
0x3E => Ok(LibArchitecture::Lib64), // AMD x86-64
|
||||
_ => Err(anyhow!("'{}' is not a recognized ELF machine ISA")),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the type of a file, if it exists.
|
||||
pub fn get_file_type(path: PathBuf) -> Option<NativeFile> {
|
||||
match path.symlink_metadata() {
|
||||
|
||||
Reference in New Issue
Block a user