Skip to content

Wasm registration fn names now based on crate name + index #1205

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
6 changes: 1 addition & 5 deletions godot-macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ homepage = "https://godot-rust.github.io"
api-custom = ["godot-bindings/api-custom"]
api-custom-json = ["godot-bindings/api-custom-json"]
codegen-full = ["godot/__codegen-full"]
experimental-wasm = ["dep:libc"]
experimental-wasm = []
register-docs = ["dep:markdown", "dep:litrs"]

[lib]
Expand All @@ -28,10 +28,6 @@ markdown = { workspace = true, optional = true }
litrs = { workspace = true, optional = true }
venial = { workspace = true }

# Cannot use [target.'cfg(target_family = "wasm")'.dependencies], as proc-macro crates are always compiled for host platform, not target.
# Thus solved via feature.
libc = { workspace = true, optional = true }

[build-dependencies]
godot-bindings = { path = "../godot-bindings", version = "=0.3.1" } # emit_godot_version_cfg

Expand Down
22 changes: 17 additions & 5 deletions godot-macros/src/ffi_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,34 @@ use crate::util::bail;
use crate::ParseResult;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use std::env;
use std::sync::atomic::{AtomicU32, Ordering};

// Note: global state in proc-macros may become problematic in the future, see:
// https://users.rust-lang.org/t/simple-state-in-procedural-macro/68204/2
static FUNCTION_COUNTER: AtomicU32 = AtomicU32::new(0);

pub(super) fn wasm_declare_init_fn(input: TokenStream) -> ParseResult<TokenStream> {
if !input.is_empty() {
return bail!(input, "macro expects no arguments");
}

// Create sufficiently unique identifier without entire `uuid` (let alone `rand`) crate dependency.
let a = unsafe { libc::rand() };
let b = unsafe { libc::rand() };
let crate_name = env::var("CARGO_CRATE_NAME")
.expect("CARGO_CRATE_NAME env var not found. This macro must be run by Cargo.");

let crate_version = env::var("CARGO_PKG_VERSION")
.expect("CARGO_PKG_VERSION env var not found. This macro must be run by Cargo.")
.replace(['.', '+', '-'], "_"); // version must follow semver, which allows digits, dots, hyphens, and plus signs, and alphanumeric characters.

let index = FUNCTION_COUNTER.fetch_add(1, Ordering::Relaxed);

// Rust presently requires that statics with a custom `#[link_section]` must be a simple
// list of bytes on the Wasm target (with no extra levels of indirection such as references).
//
// As such, instead we export a function with a random name of known prefix to be used by the embedder.
// As such, instead we export a function with a known prefix to be used by the embedder.
// This prefix is queried at load time, see godot-macros/src/gdextension.rs.
let function_name = format_ident!("__godot_rust_registrant_{a}_{b}");
let function_name =
format_ident!("__godot_rust_registrant__{crate_name}__v{crate_version}__i{index}");

let code = quote! {
#[cfg(target_family = "wasm")] // Strictly speaking not necessary, as this macro is only invoked for Wasm.
Expand Down
Loading