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

Dynamically add dylib #19

Merged
merged 3 commits into from
Sep 25, 2023
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ In your `Cargo.toml` add the following:
[lib]
name = "lib_THE_NAME_OF_YOUR_GAME"
path = "src/lib.rs"
crate-type = ["rlib", "dylib"]
crate-type = ["rlib"]

[dependencies]
bevy = "0.11"
Expand Down
1 change: 1 addition & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## UPCOMING

- generate a temporary manifest with dylib - avoiding the need to set that up in advance
- make sure compilation errors are emmitted properly

## Version 0.0.10
Expand Down
1 change: 1 addition & 0 deletions dexterous_developer_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@ directories = "5"
semver = "1"
which = "4"
toml = "0.8"
cargo_metadata = { version = "0.18" }
37 changes: 32 additions & 5 deletions dexterous_developer_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ mod existing;
mod paths;
mod remote;
mod serve;
mod temporary_manifest;

use std::path::PathBuf;

Expand All @@ -18,6 +19,7 @@ use url::Url;
use crate::{
cross::{check_cross_requirements_installed, AppleSDKPath},
paths::CliPaths,
temporary_manifest::setup_temporary_manifest,
};

#[derive(Parser, Debug)]
Expand Down Expand Up @@ -124,14 +126,18 @@ impl Default for Commands {
#[tokio::main]
async fn main() {
if std::env::var("DEXTEROUS_BUILD_SETTINGS").is_ok() {
dexterous_developer_internal::run_reloadabe_app(Default::default());
let result = dexterous_developer_internal::run_reloadabe_app(Default::default());
if let Err(e) = result {
eprintln!("Run Failed with error - {e}");
std::process::exit(1);
}
std::process::exit(0);
}

let Args { command } = Args::parse();
let dir = std::env::current_dir().expect("No current directory - nothing to run");
println!("Current directory: {:?}", dir);

std::env::set_var("CARGO_MANIFEST_DIR", dir);
println!("Current directory: {:?}", &dir);
std::env::set_var("CARGO_MANIFEST_DIR", &dir);

match command {
Commands::Run {
Expand All @@ -141,13 +147,23 @@ async fn main() {
} => {
println!("Running {package:?} with {features:?}");

let temporary = setup_temporary_manifest(&dir, package.as_deref())
.expect("Couldn't set up temporary manifest");

let options = HotReloadOptions {
features,
package,
watch_folders: watch,
..Default::default()
};
dexterous_developer_internal::run_reloadabe_app(options);
let result = dexterous_developer_internal::run_reloadabe_app(options);
if let Some(manifest) = temporary {
println!("Resetting original manifest - {manifest}");
};
if let Err(e) = result {
eprintln!("Run Failed with error - {e}");
std::process::exit(1);
}
}
Commands::Serve {
package,
Expand All @@ -156,9 +172,15 @@ async fn main() {
port,
} => {
println!("Serving {package:?} on port {port}");

let temporary = setup_temporary_manifest(&dir, package.as_deref())
.expect("Couldn't set up temporary manifest");
run_server(port, package, features, watch)
.await
.expect("Couldn't run server");
if let Some(manifest) = temporary {
println!("Resetting original manifest - {manifest}");
};
}
Commands::Remote { remote, dir } => {
connect_to_remote(remote, dir)
Expand Down Expand Up @@ -187,6 +209,8 @@ async fn main() {
libs,
target,
} => {
let temporary = setup_temporary_manifest(&dir, package.as_deref())
.expect("Couldn't set up temporary manifest");
let CliPaths { cross_config, .. } = paths::get_paths().expect("Couldn't get cli paths");
if cross_config.exists() {
std::env::set_var("CROSS_CONFIG", &cross_config);
Expand All @@ -209,6 +233,9 @@ async fn main() {

compile_reloadable_libraries(options, &libs)
.expect("Couldn't compile reloadable library");
if let Some(manifest) = temporary {
println!("Resetting original manifest - {manifest}");
};
}
}
}
115 changes: 115 additions & 0 deletions dexterous_developer_cli/src/temporary_manifest.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use std::{
fmt::Display,
path::{Path, PathBuf},
};

use anyhow::{bail, Context};
use toml::{Table, Value};

pub fn setup_temporary_manifest(
dir: &Path,
package: Option<&str>,
) -> anyhow::Result<Option<TemporaryManifest>> {
let mut get_metadata = cargo_metadata::MetadataCommand::new();
get_metadata.no_deps();
get_metadata.current_dir(dir);

let metadata = get_metadata.exec()?;

let packages = metadata.packages.iter();

let libs = packages.filter_map(|pkg| {
if let Some(package) = package {
let pkg = pkg.name.as_str();
if pkg != package {
return None;
}
}
pkg.targets
.iter()
.find(|p| {
p.crate_types
.iter()
.map(|v| v.as_str())
.any(|v| v == "lib" || v == "rlib" || v == "dylib")
})
.map(|p| (pkg, p))
});

let libs: Vec<_> = libs.collect();

if libs.len() > 1 {
bail!("Workspace contains multiple libraries - please set the one you want with the --package option");
}

let Some((pkg, lib)) = libs.first() else {
bail!("Workspace contains no matching libraries");
};

if lib
.crate_types
.iter()
.map(|v| v.as_str())
.any(|v| v == "dylib")
{
return Ok(None);
}

let manifest_path = pkg.manifest_path.as_std_path();

let tmp_manifest_path = manifest_path.with_extension("toml.tmp");

std::fs::copy(manifest_path, &tmp_manifest_path)?;

let manifest = std::fs::read_to_string(manifest_path)?;

let mut table: Table = toml::from_str(&manifest)?;
{
let lib = table
.entry("lib")
.or_insert_with(|| Value::Table(Table::new()));

let crate_type = lib
.as_table_mut()
.context("lib is not a table")?
.entry("crate-type")
.or_insert_with(|| Value::Array(vec![]));

crate_type
.as_array_mut()
.context("crate type is not an array")?
.insert(0, Value::String("dylib".to_string()));
}

let manifest = toml::to_string(&table)?;

std::fs::write(manifest_path, manifest)?;

Ok(Some(TemporaryManifest {
original: tmp_manifest_path,
temporary: manifest_path.to_path_buf(),
}))
}

pub struct TemporaryManifest {
original: PathBuf,
temporary: PathBuf,
}

impl Drop for TemporaryManifest {
fn drop(&mut self) {
println!("Clearing Temporary Manifest");
if let Err(e) = std::fs::remove_file(&self.temporary) {
eprintln!("Couldn't remove temporary file - {e:?}");
}
if let Err(e) = std::fs::rename(&self.original, &self.temporary) {
eprintln!("Couldn't reset original manifest {e:?}");
}
}
}

impl Display for TemporaryManifest {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.original.to_string_lossy())
}
}
2 changes: 1 addition & 1 deletion dexterous_developer_example/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ edition = "2021"
[lib]
name = "lib_dexterous_developer_example"
path = "src/lib.rs"
crate-type = ["rlib", "dylib"]
crate-type = ["rlib"]

[dependencies]
bevy = { version = "0.11" }
Expand Down
2 changes: 1 addition & 1 deletion dexterous_developer_example/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ fn setup_cube(
let cube_color = Color::ORANGE;

#[cfg(not(feature = "orange"))]
let cube_color = Color::RED;
let cube_color = Color::PINK;

// cube
commands.spawn((
Expand Down
2 changes: 1 addition & 1 deletion dexterous_developer_internal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ libloading = { version = "0.8", optional = true }
uuid = { version = "1", features = ["v4"], optional = true }
serde = { version = "1", optional = true, features = ["derive"] }
rmp-serde = { version = "1", optional = true }
cargo_metadata = { version = "0.17", optional = true }
cargo_metadata = { version = "0.18", optional = true }
notify = { version = "6", optional = true }
debounce = { version = "0.2", optional = true }
which = { version = "4.4.0", optional = true }
Expand Down
11 changes: 4 additions & 7 deletions dexterous_developer_internal/src/hot/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,20 +96,17 @@ pub(crate) fn setup_build_settings(
let libs = packages.filter_map(|pkg| {
if let Some(package) = package.as_ref() {
let pkg = &pkg.name;
debug!("Checking package name: {package} - {pkg}");
if pkg != package.as_str() {
return None;
}
}
pkg.targets
.iter()
.find(|p| {
let result = p.crate_types.contains(&String::from("dylib"));
debug!(
"Checking {} @ {} - {:?} {result}",
p.name, pkg.name, p.crate_types
);
result
p.crate_types
.iter()
.map(|v| v.as_str())
.any(|v| v == "dylib")
})
.map(|p| (pkg, p))
});
Expand Down
Loading