summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2025-08-09 12:37:46 +0200
committerHampusM <hampus@hampusmat.com>2025-08-09 13:50:46 +0200
commitbb7c7d2f7d9bd9ad074c0186f5d503ee96b2f106 (patch)
treed58ed365764f320e3403c9ebd00f1b9d687217d5
parent2d1cf05abb72699d38a7c7db7e131922252e1fc1 (diff)
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.
-rw-r--r--Cargo.lock21
-rw-r--r--ecs/Cargo.toml1
-rw-r--r--ecs/examples/event_loop.rs12
-rw-r--r--ecs/examples/with_sole.rs6
-rw-r--r--ecs/src/entity.rs65
-rw-r--r--ecs/src/extension.rs7
-rw-r--r--ecs/src/lib.rs26
-rw-r--r--ecs/src/phase.rs16
-rw-r--r--ecs/src/private.rs2
9 files changed, 85 insertions, 71 deletions
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",
@@ -503,26 +502,6 @@ dependencies = [
]
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
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::<ChildOf>(*UPDATE_PHASE)));
+declare_entity!(SHEER_PHASE, (Phase, Pair::new::<ChildOf>(*UPDATE_PHASE)));
-static_entity!(FEED_PHASE, (Phase, Pair::new::<ChildOf>(*SHEER_PHASE)));
+declare_entity!(FEED_PHASE, (Phase, Pair::new::<ChildOf>(*SHEER_PHASE)));
-static_entity!(AGE_PHASE, (Phase, Pair::new::<ChildOf>(*FEED_PHASE)));
+declare_entity!(AGE_PHASE, (Phase, Pair::new::<ChildOf>(*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<AmmoCounter>)
assert_eq!(ammo_counter.counter, 19);
}
-static_entity!(
+declare_entity!(
PRINT_AMMO_COUNT_PHASE,
(Phase, Pair::new::<ChildOf>(*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<Uid>,
+ 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<Comps>(&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<Comps>(&mut self, components: Comps, entity_uid: Uid)
+ pub fn create_entity_with_uid<Comps>(&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::<ChildOf>(*PRE_UPDATE)));
-static_entity!(pub PRE_UPDATE, (Phase,));
-
-static_entity!(pub UPDATE, (Phase, Pair::new::<ChildOf>(*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};