Skip to content

Commit

Permalink
Remove dead binding code regarding Godot 4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Bromeon committed Jan 17, 2025
1 parent 6a5d19d commit d90507e
Showing 1 changed file with 21 additions and 68 deletions.
89 changes: 21 additions & 68 deletions godot-bindings/src/godot_exe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,24 @@ pub fn write_gdextension_headers(
watch: &mut StopWatch,
) {
// None=(unknown, no engine), Some=(version of Godot). Later verified by header itself.
let is_engine_4_0;
if is_h_provided {
is_engine_4_0 = None;
} else {
// Even though we don't support 4.0 anymore, we still detect it, for better error messages.
if !is_h_provided {
// No external C header file: Godot binary is present, we use it to dump C header
let godot_bin = locate_godot_binary();
rerun_on_changed(&godot_bin);
watch.record("locate_godot");

// Regenerate API JSON if first time or Godot version is different
let version = read_godot_version(&godot_bin);
is_engine_4_0 = Some(version.major == 4 && version.minor == 0);
assert_eq!(
version.major, 4,
"Godot version {} is not supported by godot-rust",
version.full_string
);
assert_ne!(
version.minor, 0,
"Godot 4.0 is no longer supported by godot-rust"
);

// if !c_header_path.exists() || has_version_changed(&version) {
dump_header_file(&godot_bin, inout_h_path);
Expand All @@ -79,7 +85,7 @@ pub fn write_gdextension_headers(
// Listening to changes on files that are generated by this build step cause an infinite loop with cargo watch of
// build -> detect change -> rebuild -> detect change -> ...
// rerun_on_changed(inout_h_path);
patch_c_header(inout_h_path, is_engine_4_0);
patch_c_header(inout_h_path);
watch.record("patch_header_h");

generate_rust_binding(inout_h_path, out_rs_path);
Expand Down Expand Up @@ -158,35 +164,23 @@ fn dump_header_file(godot_bin: &Path, out_file: &Path) {
println!("Generated {}/gdextension_interface.h.", cwd.display());
}

fn patch_c_header(inout_h_path: &Path, is_engine_4_0: Option<bool>) {
fn patch_c_header(inout_h_path: &Path) {
// The C header path *must* be passed in by the invoking crate, as the path cannot be relative to this crate.
// Otherwise, it can be something like `/home/runner/.cargo/git/checkouts/gdext-76630c89719e160c/efd3b94/godot-bindings`.

println!(
"Patch C header '{}' (is_engine_4_0={is_engine_4_0:?})...",
inout_h_path.display()
);
println!("Patch C header '{}'...", inout_h_path.display());

let mut c = fs::read_to_string(inout_h_path)
.unwrap_or_else(|_| panic!("failed to read C header file {}", inout_h_path.display()));

// Detect whether header is legacy (4.0) or modern (4.1+) format.
let is_header_4_0 = !c.contains("GDExtensionInterfaceGetProcAddress");
println!("is_header_4_0={is_header_4_0}");

// Sanity check
if let Some(is_engine_4_0) = is_engine_4_0 {
assert_eq!(
is_header_4_0, is_engine_4_0,
"Mismatch between engine/header versions"
);
}

if is_header_4_0 {
polyfill_legacy_header(&mut c);
}
// Detect whether header is legacy (4.0) format. This should generally already be checked outside.
assert!(
c.contains("GDExtensionInterfaceGetProcAddress"),
"C header file '{}' seems to be GDExtension version 4.0, which is no longer support by godot-rust.",
inout_h_path.display()
);

// Patch for variant converters and type constructors
// Patch for variant converters and type constructors.
c = c.replace(
"typedef void (*GDExtensionVariantFromTypeConstructorFunc)(GDExtensionVariantPtr, GDExtensionTypePtr);",
"typedef void (*GDExtensionVariantFromTypeConstructorFunc)(GDExtensionUninitializedVariantPtr, GDExtensionTypePtr);"
Expand Down Expand Up @@ -217,47 +211,6 @@ fn patch_c_header(inout_h_path: &Path, is_engine_4_0: Option<bool>) {
});
}

/// Backport Godot 4.1+ changes to the old GDExtension API, so gdext can use both uniformly.
fn polyfill_legacy_header(c: &mut String) {
// Newer Uninitialized* types -- use same types as initialized ones, because old functions are not written with Uninitialized* in mind
let pos = c
.find("typedef int64_t GDExtensionInt;")
.expect("Unexpected gdextension_interface.h format (int)");

c.insert_str(
pos,
"\
// gdext polyfill\n\
typedef struct __GdextVariant *GDExtensionUninitializedVariantPtr;\n\
typedef struct __GdextStringName *GDExtensionUninitializedStringNamePtr;\n\
typedef struct __GdextString *GDExtensionUninitializedStringPtr;\n\
typedef struct __GdextObject *GDExtensionUninitializedObjectPtr;\n\
typedef struct __GdextType *GDExtensionUninitializedTypePtr;\n\
\n",
);

// Typedef GDExtensionInterfaceGetProcAddress (simply resolving to GDExtensionInterface, as it's the same parameter)
let pos = c
.find("/* INITIALIZATION */")
.expect("Unexpected gdextension_interface.h format (struct)");

c.insert_str(
pos,
"\
// gdext polyfill\n\
typedef struct {\n\
uint32_t major;\n\
uint32_t minor;\n\
uint32_t patch;\n\
const char *string;\n\
} GDExtensionGodotVersion;\n\
typedef void (*GDExtensionInterfaceFunctionPtr)();\n\
typedef void (*GDExtensionInterfaceGetGodotVersion)(GDExtensionGodotVersion *r_godot_version);\n\
typedef GDExtensionInterfaceFunctionPtr (*GDExtensionInterfaceGetProcAddress)(const char *p_function_name);\n\
\n",
);
}

pub(crate) fn locate_godot_binary() -> PathBuf {
if let Ok(string) = std::env::var("GODOT4_BIN") {
println!("Found GODOT4_BIN with path to executable: '{string}'");
Expand Down

0 comments on commit d90507e

Please sign in to comment.