From bb7c7d2f7d9bd9ad074c0186f5d503ee96b2f106 Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 9 Aug 2025 12:37:46 +0200 Subject: fix(ecs): remove use of linkme to make pc-windows-gnu builds work Linkme is broken on the x86_64-pc-windows-gnu target (see https://github.com/dtolnay/linkme/issues/25) so static entities are now called entity declarations and must be created manually. --- Cargo.lock | 21 --------------- ecs/Cargo.toml | 1 - ecs/examples/event_loop.rs | 12 ++++++--- ecs/examples/with_sole.rs | 6 +++-- ecs/src/entity.rs | 65 +++++++++++++++++++++++++++++----------------- ecs/src/extension.rs | 7 +++++ ecs/src/lib.rs | 26 ++++++++++--------- ecs/src/phase.rs | 16 ++++++++---- ecs/src/private.rs | 2 -- 9 files changed, 85 insertions(+), 71 deletions(-) delete mode 100644 ecs/src/private.rs diff --git a/Cargo.lock b/Cargo.lock index 625d625..4f48d3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -257,7 +257,6 @@ dependencies = [ "criterion", "ecs-macros", "hashbrown", - "linkme", "parking_lot", "paste", "seq-macro", @@ -502,26 +501,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "linkme" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22d227772b5999ddc0690e733f734f95ca05387e329c4084fe65678c51198ffe" -dependencies = [ - "linkme-impl", -] - -[[package]] -name = "linkme-impl" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71a98813fa0073a317ed6a8055dcd4722a49d9b862af828ee68449adb799b6be" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "lock_api" version = "0.4.12" diff --git a/ecs/Cargo.toml b/ecs/Cargo.toml index cf35a74..5ea9fc7 100644 --- a/ecs/Cargo.toml +++ b/ecs/Cargo.toml @@ -11,7 +11,6 @@ seq-macro = "0.3.5" paste = "1.0.14" thiserror = "1.0.49" tracing = "0.1.39" -linkme = "0.3.29" hashbrown = "0.15.2" parking_lot = "0.12.3" ecs-macros = { path = "../ecs-macros" } diff --git a/ecs/examples/event_loop.rs b/ecs/examples/event_loop.rs index 61d7ba4..cc2f7f4 100644 --- a/ecs/examples/event_loop.rs +++ b/ecs/examples/event_loop.rs @@ -1,7 +1,7 @@ use ecs::actions::Actions; use ecs::pair::{ChildOf, Pair}; use ecs::phase::{Phase, UPDATE as UPDATE_PHASE}; -use ecs::{static_entity, Component, Query, World}; +use ecs::{declare_entity, Component, Query, World}; #[derive(Component)] struct Wool @@ -65,16 +65,20 @@ fn age(query: Query<(&mut Health, &Name)>, mut actions: Actions) } } -static_entity!(SHEER_PHASE, (Phase, Pair::new::(*UPDATE_PHASE))); +declare_entity!(SHEER_PHASE, (Phase, Pair::new::(*UPDATE_PHASE))); -static_entity!(FEED_PHASE, (Phase, Pair::new::(*SHEER_PHASE))); +declare_entity!(FEED_PHASE, (Phase, Pair::new::(*SHEER_PHASE))); -static_entity!(AGE_PHASE, (Phase, Pair::new::(*FEED_PHASE))); +declare_entity!(AGE_PHASE, (Phase, Pair::new::(*FEED_PHASE))); fn main() { let mut world = World::new(); + world.create_declared_entity(&SHEER_PHASE); + world.create_declared_entity(&FEED_PHASE); + world.create_declared_entity(&AGE_PHASE); + world.register_system(*SHEER_PHASE, sheer); world.register_system(*FEED_PHASE, feed); world.register_system(*AGE_PHASE, age); diff --git a/ecs/examples/with_sole.rs b/ecs/examples/with_sole.rs index c3feaab..a292f06 100644 --- a/ecs/examples/with_sole.rs +++ b/ecs/examples/with_sole.rs @@ -1,7 +1,7 @@ use ecs::pair::{ChildOf, Pair}; use ecs::phase::{Phase, UPDATE as UPDATE_PHASE}; use ecs::sole::Single; -use ecs::{static_entity, Component, Query, Sole, World}; +use ecs::{declare_entity, Component, Query, Sole, World}; #[derive(Component)] struct Ammo @@ -31,7 +31,7 @@ fn print_total_ammo_count(ammo_counter: Single) assert_eq!(ammo_counter.counter, 19); } -static_entity!( +declare_entity!( PRINT_AMMO_COUNT_PHASE, (Phase, Pair::new::(*UPDATE_PHASE)) ); @@ -40,6 +40,8 @@ fn main() { let mut world = World::new(); + world.create_declared_entity(&PRINT_AMMO_COUNT_PHASE); + world.register_system(*UPDATE_PHASE, count_ammo); world.register_system(*PRINT_AMMO_COUNT_PHASE, print_total_ammo_count); diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs index 4496a2b..ef91d20 100644 --- a/ecs/src/entity.rs +++ b/ecs/src/entity.rs @@ -1,6 +1,6 @@ use std::any::type_name; - -use linkme::distributed_slice; +use std::ops::Deref; +use std::sync::LazyLock; use crate::component::storage::archetype::{ Archetype, @@ -124,31 +124,48 @@ impl<'a> Iterator for MatchingComponentIter<'a> } } +/// The data type of a declaration of a entity. +#[derive(Debug)] +pub struct Declaration +{ + uid: LazyLock, + create_func: fn(&mut World), +} + +impl Declaration +{ + pub(crate) fn create(&self, world: &mut World) + { + (self.create_func)(world); + } + + #[doc(hidden)] + pub const fn new(create_func: fn(&mut World)) -> Self + { + Self { + uid: LazyLock::new(|| Uid::new_unique(UidKind::Entity)), + create_func, + } + } +} + +impl Deref for Declaration +{ + type Target = Uid; + + fn deref(&self) -> &Self::Target + { + &self.uid + } +} + #[allow(clippy::module_name_repetitions)] #[macro_export] -macro_rules! static_entity { +macro_rules! declare_entity { ($visibility: vis $ident: ident, $components: expr) => { - $visibility static $ident: ::std::sync::LazyLock<$crate::uid::Uid> = - ::std::sync::LazyLock::new(|| { - $crate::uid::Uid::new_unique($crate::uid::Kind::Entity) + $visibility static $ident: $crate::entity::Declaration = + $crate::entity::Declaration::new(|world| { + world.create_entity_with_uid(*$ident, $components); }); - - $crate::private::paste::paste! { - mod [<__ecs_ $ident:lower _static_entity_priv>] { - use super::*; - - #[$crate::private::linkme::distributed_slice( - $crate::entity::CREATE_STATIC_ENTITIES - )] - #[linkme(crate=$crate::private::linkme)] - static CREATE_STATIC_ENTITY: fn(&mut $crate::World) = |world| { - world.create_entity_with_uid($components, *$ident); - }; - } - } } } - -#[distributed_slice] -#[doc(hidden)] -pub static CREATE_STATIC_ENTITIES: [fn(&mut World)]; diff --git a/ecs/src/extension.rs b/ecs/src/extension.rs index 42ebef9..e180ac7 100644 --- a/ecs/src/extension.rs +++ b/ecs/src/extension.rs @@ -1,4 +1,5 @@ use crate::component::Sequence as ComponentSequence; +use crate::entity::Declaration as EntityDeclaration; use crate::sole::Sole; use crate::system::System; use crate::uid::Uid; @@ -42,6 +43,12 @@ impl<'world> Collector<'world> self.world.create_entity(components); } + /// Adds a declared entity to the [`World`]. + pub fn add_declared_entity(&mut self, entity_decl: &EntityDeclaration) + { + self.world.create_declared_entity(entity_decl); + } + /// Adds a globally shared singleton value to the [`World`]. /// /// # Errors diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs index 53abc6b..979b517 100644 --- a/ecs/src/lib.rs +++ b/ecs/src/lib.rs @@ -18,7 +18,7 @@ use crate::component::{ Parts as ComponentParts, Sequence as ComponentSequence, }; -use crate::entity::CREATE_STATIC_ENTITIES; +use crate::entity::Declaration as EntityDeclaration; use crate::event::component::{ Added as ComponentAddedEvent, Removed as ComponentRemovedEvent, @@ -56,9 +56,6 @@ pub mod tuple; pub mod uid; pub mod util; -#[doc(hidden)] -pub mod private; - mod lock; pub use ecs_macros::{Component, Sole}; @@ -84,30 +81,30 @@ impl World is_first_tick: AtomicBool::new(false), }; - world.add_sole(Stats::default()).ok(); + crate::phase::spawn_entities(&mut world); - for create_static_entity in CREATE_STATIC_ENTITIES { - create_static_entity(&mut world); - } + world.add_sole(Stats::default()).ok(); world } - /// Creates a new entity with the given components. + /// Creates a entity with the given components. A new unique [`Uid`] will be generated + /// for this entity. pub fn create_entity(&mut self, components: Comps) -> Uid where Comps: ComponentSequence, { let entity_uid = Uid::new_unique(UidKind::Entity); - self.create_entity_with_uid(components, entity_uid); + self.create_entity_with_uid(entity_uid, components); entity_uid } + /// Creates a entity with the given components. The entity will have the specified + /// [`Uid`]. #[tracing::instrument(skip_all)] - #[doc(hidden)] - pub fn create_entity_with_uid(&mut self, components: Comps, entity_uid: Uid) + pub fn create_entity_with_uid(&mut self, entity_uid: Uid, components: Comps) where Comps: ComponentSequence, { @@ -129,6 +126,11 @@ impl World } } + pub fn create_declared_entity(&mut self, entity_decl: &EntityDeclaration) + { + entity_decl.create(self); + } + /// Adds a globally shared singleton value. /// /// # Errors diff --git a/ecs/src/phase.rs b/ecs/src/phase.rs index 9f47fb8..c13c432 100644 --- a/ecs/src/phase.rs +++ b/ecs/src/phase.rs @@ -1,13 +1,19 @@ use ecs_macros::Component; use crate::pair::{ChildOf, Pair}; -use crate::static_entity; +use crate::{declare_entity, World}; #[derive(Debug, Default, Clone, Copy, Component)] pub struct Phase; -static_entity!(pub START, (Phase,)); +declare_entity!(pub START, (Phase,)); +declare_entity!(pub PRE_UPDATE, (Phase,)); +declare_entity!(pub UPDATE, (Phase, Pair::new::(*PRE_UPDATE))); -static_entity!(pub PRE_UPDATE, (Phase,)); - -static_entity!(pub UPDATE, (Phase, Pair::new::(*PRE_UPDATE))); +#[doc(hidden)] +pub(crate) fn spawn_entities(world: &mut World) +{ + world.create_declared_entity(&START); + world.create_declared_entity(&PRE_UPDATE); + world.create_declared_entity(&UPDATE); +} diff --git a/ecs/src/private.rs b/ecs/src/private.rs deleted file mode 100644 index 56a6552..0000000 --- a/ecs/src/private.rs +++ /dev/null @@ -1,2 +0,0 @@ -#[doc(hidden)] -pub use {linkme, paste}; -- cgit v1.2.3-18-g5258