Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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 godot-bindings/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// It's the only purpose of this build.rs file. If a better solution is found, this file can be removed.

#[rustfmt::skip]
fn main() {
fn main() {
let mut count = 0;
if cfg!(feature = "api-custom") { count += 1; }
if cfg!(feature = "api-custom-json") { count += 1; }
Expand Down
64 changes: 62 additions & 2 deletions godot-bindings/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,66 @@ pub use gdextension_api::version_4_5 as prebuilt;
// ]]
// [version-sync] [[
// [include] current.minor
// [line] pub use gdextension_api::version_$snakeVersion as prebuilt;
pub use gdextension_api::version_4_5 as prebuilt;
// [line] pub use gdextension_api as prebuilt;
pub use gdextension_api as prebuilt;
// ]]

// Platform-specific header loading for cross-compilation support.
// The prebuilt module is compiled for HOST (not TARGET) when used as a build-dependency,
// so we determine the platform at runtime based on CARGO_CFG_TARGET_* environment variables.
#[cfg(not(any(feature = "api-custom", feature = "api-custom-json")))]
pub(crate) mod prebuilt_platform {
use std::borrow::Cow;
use std::path::PathBuf;

/// Load platform-specific prebuilt bindings based on the TARGET platform (not HOST).
///
/// Since godot-bindings is a build-dependency, it's compiled for HOST, but we need bindings for TARGET.
/// We detect the target platform using CARGO_CFG_TARGET_* environment variables available during
/// build script execution, then read the corresponding file from the gdextension-api dependency.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here, what "corresponding file"?

pub fn load_gdextension_header_rs_for_target() -> Cow<'static, str> {
// Determine TARGET platform from environment variables
let target_family = std::env::var("CARGO_CFG_TARGET_FAMILY").ok();
let target_os = std::env::var("CARGO_CFG_TARGET_OS").ok();

// Select platform suffix matching gdextension-api's file naming
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean? Which file naming?

let platform = match (target_family.as_deref(), target_os.as_deref()) {
(Some("windows"), _) => "windows",
(_, Some("macos" | "ios")) => "macos",
_ => "linux", // Linux, Android, and other Unix-like systems
};

// Get the Godot version string from prebuilt module
let version = super::prebuilt::GODOT_VERSION_STRING;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to comment trivial variable assignments.


// Read the file from gdextension-api dependency
load_platform_file(platform, version)
}

/// Load platform-specific bindings file from the gdextension-api dependency.
///
/// Uses the DEP_GDEXTENSION_API_ROOT environment variable exported by gdextension-api's build script
/// to locate the correct platform-specific bindings file.
fn load_platform_file(platform: &str, _version: &str) -> Cow<'static, str> {
// Get the gdextension-api root directory from the build script
let dep_root = std::env::var("DEP_GDEXTENSION_API_ROOT")
.expect("DEP_GDEXTENSION_API_ROOT not set. This should be exported by gdextension-api's build script.");

// The 4.x branches have files directly in res/, not versions/{version}/res/
let file_path = PathBuf::from(dep_root)
.join("res")
.join(format!("gdextension_interface_{}.rs", platform));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that comment is true, see https://github.com/godot-rust/godot4-prebuilt/tree/release-v0.3 directory structure.

What does the comment mean?


match std::fs::read_to_string(&file_path) {
Ok(contents) => Cow::Owned(contents),
Err(e) => panic!(
"Failed to load platform-specific bindings for platform '{}'.\n\
Tried to read: {}\n\
Error: {}\n\
\n\
This is likely a cross-compilation issue or the gdextension-api version doesn't support this platform.",
platform, file_path.display(), e
),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use inline string interpolation where possible (for platform + e)

}
}
}
6 changes: 5 additions & 1 deletion godot-bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,11 @@ mod depend_on_prebuilt {
.unwrap_or_else(|e| panic!("failed to write gdextension_interface.h: {e}"));
watch.record("write_header_h");

let rs_contents = prebuilt::load_gdextension_header_rs();
// CROSS-COMPILATION FIX:
// Since godot-bindings is a build-dependency, it and gdextension-api are compiled for the HOST platform.
// The #[cfg] attributes in gdextension-api::load_gdextension_header_rs() evaluate for HOST, not TARGET.
// We read CARGO_CFG_TARGET_* environment variables to select the correct bindings at runtime.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// CROSS-COMPILATION FIX:
// Since godot-bindings is a build-dependency, it and gdextension-api are compiled for the HOST platform.
// The #[cfg] attributes in gdextension-api::load_gdextension_header_rs() evaluate for HOST, not TARGET.
// We read CARGO_CFG_TARGET_* environment variables to select the correct bindings at runtime.
// Cross-compilation support:
// Since godot-bindings is a build-dependency, it and the gdextension-api crate are compiled for the HOST platform.
// The #[cfg] attributes in gdextension_api::load_gdextension_header_rs() evaluate for HOST, not TARGET.
// We read CARGO_CFG_TARGET_* environment variables to select the correct bindings at runtime.

let rs_contents = crate::import::prebuilt_platform::load_gdextension_header_rs_for_target();
std::fs::write(rs_path, rs_contents.as_ref())
.unwrap_or_else(|e| panic!("failed to write gdextension_interface.rs: {e}"));
watch.record("write_header_rs");
Expand Down