Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bundling logic for dynamic libs #67

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .idea/bevy_fmod.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[package]
name = "bevy_fmod"
authors = ["Fabian 'Salzian' Fritzsche <bevy_fmod@salzian.dev>"]
description = "Idiomatic FMOD in Bevy"
authors = ["Fabian 'Salzian' Fritzsche <bevy_fmod@salzian.dev>"]
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"
Expand All @@ -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 = []
Expand Down
2 changes: 2 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
5 changes: 5 additions & 0 deletions dynamic_bundler/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[package]
name = "bevy_fmod_dynamic_bundler"
description = "Bundles dynamic libraries into the build directory."
version = "0.0.0"
publish = false
149 changes: 149 additions & 0 deletions dynamic_bundler/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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
)
});
}
}
}
4 changes: 2 additions & 2 deletions examples/spatial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ fn orbit_audio_source(
mut audio_sources: Query<&mut Transform, With<AudioSource>>,
) {
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;
}
}

Expand Down
4 changes: 4 additions & 0 deletions vendor/README.md
Original file line number Diff line number Diff line change
@@ -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).