From 491b42b84d8ff3725927787f65cf16a754ec225b Mon Sep 17 00:00:00 2001 From: Salzian Date: Mon, 27 Nov 2023 01:26:57 +0100 Subject: [PATCH] WIP linking fails. file coying somewhat works. --- .idea/bevy_fmod.iml | 4 +- Cargo.toml | 9 ++- build.rs | 2 + dynamic_bundler/Cargo.toml | 5 ++ dynamic_bundler/src/lib.rs | 149 +++++++++++++++++++++++++++++++++++++ examples/spatial.rs | 4 +- vendor/README.md | 4 + 7 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 dynamic_bundler/Cargo.toml create mode 100644 dynamic_bundler/src/lib.rs create mode 100644 vendor/README.md diff --git a/.idea/bevy_fmod.iml b/.idea/bevy_fmod.iml index d05fa31..f0494e5 100644 --- a/.idea/bevy_fmod.iml +++ b/.idea/bevy_fmod.iml @@ -2,9 +2,11 @@ + + + - diff --git a/Cargo.toml b/Cargo.toml index 7b30e16..887d1ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "bevy_fmod" + authors = ["Fabian 'Salzian' Fritzsche "] description = "Idiomatic FMOD in Bevy" -authors = ["Fabian 'Salzian' Fritzsche "] edition = "2021" +license = "MIT OR Apache-2.0" +name = "bevy_fmod" repository = "https://github.com/salzian/bevy_fmod" version = "0.3.0" -license = "MIT OR Apache-2.0" [dependencies] anyhow = "1.0" @@ -17,6 +17,9 @@ libfmod = "~2.206.2" # The examples need the default features of bevy bevy = { version = "0.11", default-features = true } +[build-dependencies] +bevy_fmod_dynamic_bundler = { path = "dynamic_bundler" } + [features] default = [] live-update = [] diff --git a/build.rs b/build.rs index 1d62531..4e06edf 100644 --- a/build.rs +++ b/build.rs @@ -10,6 +10,8 @@ /// If you are running your executable directly (no IDE, no cargo) see https://www.hpc.dtu.dk/?page_id=1180 fn main() { + bevy_fmod_dynamic_bundler::bundle_libraries("./vendor"); + #[cfg(target_os = "linux")] { let mut target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap(); diff --git a/dynamic_bundler/Cargo.toml b/dynamic_bundler/Cargo.toml new file mode 100644 index 0000000..271a4be --- /dev/null +++ b/dynamic_bundler/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "bevy_fmod_dynamic_bundler" +description = "Bundles dynamic libraries into the build directory." +version = "0.0.0" +publish = false diff --git a/dynamic_bundler/src/lib.rs b/dynamic_bundler/src/lib.rs new file mode 100644 index 0000000..29fbafd --- /dev/null +++ b/dynamic_bundler/src/lib.rs @@ -0,0 +1,149 @@ +use std::env; +use std::fs::{self, canonicalize, metadata}; +use std::path::Path; + +#[cfg(target_os = "windows")] +use std::os::windows; + +#[cfg(target_os = "unix")] +use std::os::unix; +use std::time::SystemTime; + +/// Bundles dynamic libraries from a path into the build folder. +/// +/// # Example +/// +/// Vendor folder includes the FMOD libraries like this: +/// - vendor +/// - fmod.dll +/// - fmodstudio.dll +/// +/// ```rust +/// use bevy_fmod_dynamic_bundler::bundle_libraries; +/// +/// bundle_libraries("./vendor".into()); +/// ``` +pub fn bundle_libraries(path: &str) { + let profile = env::var("PROFILE").unwrap(); + let out_dir = env::var("OUT_DIR").unwrap(); + let vendor_dir = canonicalize(path) + .unwrap_or_else(|error| panic!("Failed to canonicalize path `{}`: {}", path, error)); + + for entry in fs::read_dir(vendor_dir) + .unwrap_or_else(|error| panic!("Failed to read directory `{}`: {}", path, error)) + { + let entry = entry.expect("Failed to read entry"); + let path = entry.path(); + + let metadata = metadata(&path).unwrap_or_else(|error| { + panic!( + "Failed to read metadata for {}: {}", + path.to_str().unwrap_or("unknown"), + error + ) + }); + + let file_type = metadata.file_type(); + + if !(file_type.is_file()) { + continue; + } + + #[cfg(target_os = "windows")] + { + let needed_files = vec!["dll", "lib"]; + if !needed_files.contains( + &path + .extension() + .unwrap_or_default() + .to_str() + .unwrap_or_default(), + ) { + continue; + } + } + + #[cfg(target_os = "macos")] + if !path.extension().unwrap_or_default().eq("dylib") { + continue; + } + + #[cfg(target_os = "linux")] + if !path.extension().unwrap_or_default().eq("so") { + continue; + } + + let destination_path = + Path::new(&out_dir).join(path.file_name().expect("Failed to get file name")); + + if profile == "debug" { + if destination_path.try_exists().unwrap_or_else(|error| { + panic!( + "Failed to check if {} exists: {}", + destination_path.to_str().unwrap_or("unknown"), + error + ) + }) { + continue; + } + + // Create symlink in debug mode + #[cfg(unix)] + unix::fs::symlink(&path, &destination_path).expect( + format!( + "Failed to create symlink for {}", + path.to_str().unwrap_or("unknown") + ) + .as_str(), + ); + + #[cfg(windows)] + windows::fs::symlink_file(&path, &destination_path).unwrap_or_else(|error| { + panic!( + "Failed to create symlink for {}: {}", + path.to_str().unwrap_or("unknown"), + error + ) + }); + } else { + if destination_path.exists() { + let destination_metadata = + fs::metadata(&destination_path).unwrap_or_else(|error| { + panic!( + "Failed to read metadata for {}: {}", + destination_path.to_str().unwrap_or("unknown"), + error + ) + }); + + // Compare if the destination file is older than the source file. + // In case any metadata retrieval fails, we assume the file is older and overwrite it. + if destination_metadata + .modified() + .unwrap_or(SystemTime::UNIX_EPOCH) + >= metadata.modified().unwrap_or(SystemTime::now()) + { + continue; + } else { + fs::remove_file(&destination_path).unwrap_or_else(|error| { + panic!( + "Failed to remove {}: {}", + destination_path.to_str().unwrap_or("unknown"), + error + ) + }); + } + } + + // Copy file in release mode + fs::copy(&path, &destination_path).unwrap_or_else(|error| { + panic!( + "Failed to copy {} to {}: {}", + path.to_str().unwrap_or("unknown"), + destination_path.to_str().unwrap_or("unknown"), + error + ) + }); + } + } +} diff --git a/examples/spatial.rs b/examples/spatial.rs index c4bc840..c4c9cbb 100644 --- a/examples/spatial.rs +++ b/examples/spatial.rs @@ -84,8 +84,8 @@ fn orbit_audio_source( mut audio_sources: Query<&mut Transform, With>, ) { for mut audio_source in audio_sources.iter_mut() { - audio_source.translation.x = time.elapsed_seconds().sin() * 2.0; - audio_source.translation.z = time.elapsed_seconds().cos() * 2.0; + audio_source.translation.x = time.elapsed_seconds().sin() * 10.0; + audio_source.translation.z = time.elapsed_seconds().cos() * 10.0; } } diff --git a/vendor/README.md b/vendor/README.md new file mode 100644 index 0000000..98afb35 --- /dev/null +++ b/vendor/README.md @@ -0,0 +1,4 @@ +# vendor + +Dynamic FMOD libraries used for CI. These files are not bundled in the crates.io crate. Not recommended to be used in production applications, as you should [download the +latest FMOD libraries from the FMOD website](../README.md#external-dependencies).