Skip to content

Commit

Permalink
Migrate crate-local /gen directories to OUT_DIR
Browse files Browse the repository at this point in the history
  • Loading branch information
Bromeon committed May 6, 2024
1 parent 0ccb18c commit 6d6c15c
Show file tree
Hide file tree
Showing 13 changed files with 88 additions and 45 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ members = [
]

#[patch."https://github.com/godot-rust/godot4-prebuilt"]
#godot4-prebuilt = { git = "https://github.com//godot-rust/godot4-prebuilt", branch = "4.1"}
#godot4-prebuilt = { git = "https://github.com//godot-rust/godot4-prebuilt", branch = "4.1" }
4 changes: 2 additions & 2 deletions godot-bindings/src/godot_exe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ use std::process::{Command, Output};
// Note: CARGO_BUILD_TARGET_DIR and CARGO_TARGET_DIR are not set.
// OUT_DIR would be standing to reason, but it's an unspecified path that cannot be referenced by CI.
// const GODOT_VERSION_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/src/gen/godot_version.txt");
const JSON_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/src/gen/extension_api.json");

pub fn load_gdextension_json(watch: &mut StopWatch) -> String {
let json_path = Path::new(JSON_PATH);
let path = format!("{}/extension_api.json", std::env::var("OUT_DIR").unwrap());
let json_path = Path::new(&path);

// 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 -> ...
Expand Down
17 changes: 16 additions & 1 deletion godot-bindings/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ pub fn emit_godot_version_cfg() {

// Function for safely removal of build directory. Workaround for errors happening during CI builds:
// https://github.com/godot-rust/gdext/issues/616
pub fn remove_dir_all_reliable(path: &std::path::Path) {
pub fn remove_dir_all_reliable(path: &Path) {
let mut retry_count = 0;

while path.exists() {
Expand All @@ -183,3 +183,18 @@ pub fn remove_dir_all_reliable(path: &std::path::Path) {
}
}
}
//
// pub fn write_module_file(path: &Path) {
// let code = quote! {
// pub mod table_builtins;
// pub mod table_builtins_lifecycle;
// pub mod table_servers_classes;
// pub mod table_scene_classes;
// pub mod table_editor_classes;
// pub mod table_utilities;
//
// pub mod central;
// pub mod gdextension_interface;
// pub mod interface;
// };
// }
15 changes: 5 additions & 10 deletions godot-codegen/src/generator/extension_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@ pub fn generate_sys_interface_file(
let code = if is_godot_4_0 {
// Compat for 4.0.x
// Most polyfills are in godot_exe.rs, fn polyfill_legacy_header()
quote! {
#[path = "../compat/compat_4_0.rs"]
mod compat_4_0;

pub use compat_4_0::*;
}
// Module `compat_4_0` is directly imported in Rust code, behind #[cfg].
TokenStream::new()
} else {
generate_proc_address_funcs(h_path)
};
Expand Down Expand Up @@ -80,10 +76,8 @@ fn generate_proc_address_funcs(h_path: &Path) -> TokenStream {

// Do not derive Copy -- even though the struct is bitwise-copyable, this is rarely needed and may point to an error.
let code = quote! {
#[path = "../compat/compat_4_1plus.rs"]
mod compat_4_1plus;

pub use compat_4_1plus::InitCompat;
pub use crate::compat::InitCompat;
// pub use crate::compat::compat_4_1plus::InitCompat;

pub struct GDExtensionInterface {
#( #fptr_decls )*
Expand All @@ -101,6 +95,7 @@ fn generate_proc_address_funcs(h_path: &Path) -> TokenStream {
}
}
};

code
}

Expand Down
17 changes: 17 additions & 0 deletions godot-codegen/src/generator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,23 @@ pub mod virtual_traits;
// - utility_functions
// - native_structures

pub fn generate_sys_module_file(sys_gen_path: &Path, submit_fn: &mut SubmitFn) {
let code = quote! {
pub mod table_builtins;
pub mod table_builtins_lifecycle;
pub mod table_servers_classes;
pub mod table_scene_classes;
pub mod table_editor_classes;
pub mod table_utilities;

pub mod central;
pub mod gdextension_interface;
pub mod interface;
};

submit_fn(sys_gen_path.join("mod.rs"), code);
}

pub fn generate_sys_central_file(
api: &ExtensionApi,
ctx: &mut Context,
Expand Down
5 changes: 4 additions & 1 deletion godot-codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::generator::utility_functions::generate_utilities_file;
use crate::generator::{
generate_core_central_file, generate_core_mod_file, generate_sys_builtin_lifecycle_file,
generate_sys_builtin_methods_file, generate_sys_central_file, generate_sys_classes_file,
generate_sys_utilities_file,
generate_sys_module_file, generate_sys_utilities_file,
};
use crate::models::domain::{ApiView, ExtensionApi};
use crate::models::json::{load_extension_api, JsonExtensionApi};
Expand Down Expand Up @@ -90,6 +90,9 @@ pub fn generate_sys_files(
let is_godot_4_0 = api.godot_version.major == 4 && api.godot_version.minor == 0;
generate_sys_interface_file(h_path, sys_gen_path, is_godot_4_0, &mut submit_fn);
watch.record("generate_interface_file");

generate_sys_module_file(sys_gen_path, &mut submit_fn);
watch.record("generate_module_file");
}

pub fn generate_core_files(core_gen_path: &Path) {
Expand Down
5 changes: 2 additions & 3 deletions godot-core/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
use std::path::Path;

fn main() {
// It would be better to generate this in /.generated or /target/godot-gen, however IDEs currently
// struggle with static analysis when symbols are outside the crate directory (April 2023).
let gen_path = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/src/gen"));
let out_dir = std::env::var("OUT_DIR").unwrap();
let gen_path = Path::new(&out_dir);

godot_bindings::remove_dir_all_reliable(gen_path);

Expand Down
6 changes: 3 additions & 3 deletions godot-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ pub mod engine;
#[allow(clippy::wrong_self_convention)] // to_string() is const
#[allow(clippy::upper_case_acronyms)] // TODO remove this line once we transform names
#[allow(unreachable_code, clippy::unimplemented)] // TODO remove once #153 is implemented
mod gen;


mod gen {
include!(concat!(env!("OUT_DIR"), "/mod.rs"));
}

macro_rules! generate_gdextension_api_version {
(
Expand Down
5 changes: 2 additions & 3 deletions godot-ffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ use std::path::Path;
fn main() {
let mut watch = godot_bindings::StopWatch::start();

// It would be better to generate this in /.generated or /target/godot-gen, however IDEs currently
// struggle with static analysis when symbols are outside the crate directory (April 2023).
let gen_path = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/src/gen"));
let out_dir = std::env::var("OUT_DIR").unwrap();
let gen_path = Path::new(&out_dir);

// C header is not strictly required, however it is generated for debugging.
let h_path = gen_path.join("gdextension_interface.h");
Expand Down
10 changes: 10 additions & 0 deletions godot-ffi/src/compat/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@

use crate as sys;

#[cfg(since_api = "4.1")]
mod compat_4_1plus;
#[cfg(since_api = "4.1")]
pub use compat_4_1plus::*;

#[cfg(before_api = "4.1")]
mod compat_4_0;
#[cfg(before_api = "4.1")]
pub use compat_4_0::*;

/// Dispatch at runtime between Godot 4.0 legacy and 4.1+ APIs.
///
/// Provides a compatibility layer to be able to use 4.0.x extensions under Godot versions >= 4.1.
Expand Down
34 changes: 18 additions & 16 deletions godot-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,7 @@
clippy::redundant_static_lifetimes
)]
pub(crate) mod gen {
pub mod table_builtins;
pub mod table_builtins_lifecycle;
pub mod table_servers_classes;
pub mod table_scene_classes;
pub mod table_editor_classes;
pub mod table_utilities;

pub mod central;
pub mod gdextension_interface;
pub mod interface;
include!(concat!(env!("OUT_DIR"), "/mod.rs"));
}

mod compat;
Expand Down Expand Up @@ -74,14 +65,25 @@ pub use global::*;
pub use string_cache::StringCache;
pub use toolbox::*;

// SAFETY: In Godot 4.0.4 the extension interface stores a c_char pointer, this is safe to access from different threads as no
// mutation happens after initialization. This was changed in 4.1, so we don't need to manually implement `Sync` or `Send` after 4.0.
// So we instead rely on rust to infer that it is `Sync` and `Send`.
#[cfg(before_api = "4.1")]
unsafe impl Sync for GDExtensionInterface {}
// SAFETY: See `Sync` impl.
mod godot_4_0_imported {
// SAFETY: In Godot 4.0.4, the extension interface stores a c_char pointer. This is safe to access from different threads, as no
// mutation happens after initialization. This was changed in 4.1, so we don't need to manually implement `Sync` or `Send` after 4.0.
// Instead, we rely on Rust to infer that it is `Sync` and `Send`.
unsafe impl Sync for super::GDExtensionInterface {}

// SAFETY: See `Sync` impl.
unsafe impl Send for super::GDExtensionInterface {}

// Re-import polyfills so that code can use the symbols as if 4.0 would natively define them.
pub use super::compat::InitCompat;
pub(crate) use super::compat::{
GDExtensionInterfaceClassdbGetMethodBind, GDExtensionInterfaceVariantGetPtrBuiltinMethod,
};
}

#[cfg(before_api = "4.1")]
unsafe impl Send for GDExtensionInterface {}
pub use godot_4_0_imported::*;

// ----------------------------------------------------------------------------------------------------------------------------------------------
// API to access Godot via FFI
Expand Down
7 changes: 4 additions & 3 deletions itest/rust/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,6 @@ fn main() {
let extras = inputs.iter().map(|input| &input.extra);

let rust_tokens = quote::quote! {
#![allow(clippy::partialeq_to_none)]

use godot::builtin::*;
use godot::builtin::meta::*;
use godot::log::godot_error;
Expand Down Expand Up @@ -242,7 +240,10 @@ fn main() {
#(#extras)*
};

let rust_output_dir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/src/gen"));
// Godot currently still uses local /gen folder. If this changes one day (no good reason right now),
// IntegrationTest class could get a func get_out_dir() which returns env!("OUT_DIR") and is called from GDScript.
let out_dir = std::env::var("OUT_DIR").unwrap();
let rust_output_dir = Path::new(&out_dir);
let godot_input_dir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../godot/input"));
let godot_output_dir = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/../godot/gen"));

Expand Down
6 changes: 4 additions & 2 deletions itest/rust/src/register_tests/gdscript_ffi_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,7 @@
#![allow(dead_code)]

#[rustfmt::skip]
#[path = "../gen/gen_ffi.rs"]
pub mod gen_ffi;
#[allow(clippy::partialeq_to_none)]
pub mod gen_ffi {
include!(concat!(env!("OUT_DIR"), "/gen_ffi.rs"));
}

0 comments on commit 6d6c15c

Please sign in to comment.