Open BenLeadbetter opened 8 months ago
I think managing the generation of the output bundles is outside of the scope for Clack (which is only a safe wrapper around the CLAP APIs), and is something better suited to be implemented by higher-level plugin frameworks that already handle cross-API/cross-platform bundle generation.
That being said, I think it would be beneficial to use something like cargo-bundle
for the examples instead of integrating it into Clack directly. That way people would have an easier time to get the examples up and running in actual hosts.
However, I don't have a macOS machine available to test things, and to be fair I have absolutely no knowledge of how things are handled on macOS at all, so I'd definitely welcome help and contributions on that front. :slightly_smiling_face:
Here's some simple Rust code that wraps a single-entry .dylib as a working .clap bundle on macOS. I integrated/call this using the xtask pattern.
Make sure to update the CFBundleIdentifier as appropriate.
#[cfg(target_os = "macos")]
fn package_as_clap_macos(plugin_name: &str) -> Result<(), DynError> {
println!("Creating bundle for {}", plugin_name);
let bundle_name = format!("{}.clap", plugin_name);
let bundle_root = project_root().join("target").join(&bundle_name);
let contents_dir = bundle_root.join("Contents");
let macos_dir = contents_dir.join("MacOS");
// Create directory structure
fs::create_dir_all(&macos_dir)?;
// Define dylib name
let dylib_name = format!("lib{}.dylib", plugin_name);
// Copy dylib
let src_dylib = project_root()
.join("target")
.join("release")
.join(&dylib_name);
let dst_dylib = macos_dir.join(&dylib_name);
fs::copy(&src_dylib, &dst_dylib)?;
println!("Copied dylib from {:?} to {:?}", src_dylib, dst_dylib);
// Create Info.plist
let info_plist = format!(
r#"<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>{}</string>
<key>CFBundleExecutable</key>
<string>{}</string>
<key>CFBundleIdentifier</key>
<string>com.yourcompany.{}</string>
</dict>
</plist>"#,
plugin_name,
dylib_name,
plugin_name.to_lowercase()
);
let info_plist_path = contents_dir.join("Info.plist");
fs::write(&info_plist_path, info_plist)?;
println!("Created Info.plist at {:?}", info_plist_path);
println!("Bundle created at {:?}", bundle_root);
Ok(())
}
I noticed that on macOS the example plugins are just raw binary files. Most tooling expects a "bundle" for a clap plugins with a
Info.plist
, etc. I'm only able to load the examples in REAPER, or validate with the clap-validator after I manually wrap the dynamic libraries into a basic bundle.Should we consider integrating with tools like
cargo-bundle
to have this stuff happen automatically?