9
9
use crate :: godot_version:: parse_godot_version;
10
10
use crate :: header_gen:: generate_rust_binding;
11
11
use crate :: watch:: StopWatch ;
12
+
13
+ use regex:: Regex ;
14
+ use std:: fs;
12
15
use std:: path:: { Path , PathBuf } ;
13
16
use std:: process:: { Command , Output } ;
14
17
@@ -26,7 +29,6 @@ const HEADER_PATH: &str = concat!(
26
29
env!( "CARGO_MANIFEST_DIR" ) ,
27
30
"/../target/godot-gen/gdextension_interface.h"
28
31
) ;
29
- const RES_PATH : & str = concat ! ( env!( "CARGO_MANIFEST_DIR" ) , "/res" ) ;
30
32
31
33
pub fn load_gdextension_json ( watch : & mut StopWatch ) -> String {
32
34
let json_path = Path :: new ( JSON_PATH ) ;
@@ -45,7 +47,7 @@ pub fn load_gdextension_json(watch: &mut StopWatch) -> String {
45
47
watch. record ( "dump_json" ) ;
46
48
// }
47
49
48
- let result = std :: fs:: read_to_string ( json_path)
50
+ let result = fs:: read_to_string ( json_path)
49
51
. unwrap_or_else ( |_| panic ! ( "failed to open file {}" , json_path. display( ) ) ) ;
50
52
51
53
watch. record ( "read_json_file" ) ;
@@ -81,8 +83,7 @@ pub fn load_gdextension_header_rs(
81
83
82
84
watch. record ( "dump_header_c" ) ;
83
85
84
- let tweak_path = Path :: new ( RES_PATH ) . join ( "tweak.patch" ) ;
85
- patch_c_header ( c_header_path, & tweak_path) ;
86
+ patch_c_header ( c_header_path) ;
86
87
generate_rust_binding ( c_header_path, rust_out_path) ;
87
88
88
89
watch. record ( "generate_header_rs" ) ;
@@ -92,7 +93,7 @@ pub fn load_gdextension_header_rs(
92
93
fn has_version_changed ( current_version : & str ) -> bool {
93
94
let version_path = Path :: new ( GODOT_VERSION_PATH ) ;
94
95
95
- match std :: fs:: read_to_string ( version_path) {
96
+ match fs:: read_to_string ( version_path) {
96
97
Ok ( last_version) => current_version != last_version,
97
98
Err ( _) => true ,
98
99
}
@@ -168,26 +169,30 @@ fn dump_header_file(godot_bin: &Path, out_file: &Path) {
168
169
println ! ( "Generated {}/extension_api.json." , cwd. display( ) ) ;
169
170
}
170
171
171
- fn patch_c_header ( c_header_path : & Path , tweak_path : & Path ) {
172
+ fn patch_c_header ( c_header_path : & Path ) {
172
173
// The C header path *must* be passed in by the invoking crate, as the path cannot be relative to this crate.
173
174
// Otherwise, it can be something like `/home/runner/.cargo/git/checkouts/gdext-76630c89719e160c/efd3b94/godot-bindings`.
174
- let cwd = c_header_path. parent ( ) . unwrap ( ) . parent ( ) . unwrap ( ) ;
175
- println ! ( "cwd: {}" , cwd. display( ) ) ;
176
175
177
- // Note: patch must have paths relative to Git root (aka top-level dir), so cwd is root
178
- rerun_on_changed ( tweak_path) ;
176
+ // Read the contents of the file into a string
177
+ let c = fs:: read_to_string ( c_header_path)
178
+ . unwrap_or_else ( |_| panic ! ( "failed to read C header file {}" , c_header_path. display( ) ) ) ;
179
179
180
- let git = locate_git_binary ( ) ;
181
- let mut cmd = Command :: new ( & git) ;
182
- cmd. current_dir ( cwd) . arg ( "apply" ) . arg ( "-v" ) . arg ( tweak_path) ;
180
+ // Use single regex with independent "const"/"Const", as there are definitions like this:
181
+ // typedef const void *GDExtensionMethodBindPtr;
182
+ let c = Regex :: new ( r"typedef (const )?void \*GDExtension(Const)?([a-zA-Z0-9]+?)Ptr;" ) //
183
+ . expect ( "regex for mut typedef" )
184
+ . replace_all ( & c, "typedef ${1}struct __Gdext$3 *GDExtension${2}${3}Ptr;" ) ;
183
185
184
- let output = execute ( cmd, "apply Git patch" ) ;
185
- let stderr = String :: from_utf8 ( output. stderr ) . expect ( "convert Git patch output to UTF-8" ) ;
186
+ println ! ( "Patched contents:\n \n {}\n \n " , c. as_ref( ) ) ;
186
187
187
- // `git patch` returns 0 even if it skips a patch because it's not applicable -- treat this as error
188
- assert ! ( !stderr. contains( "Skipped" ) , "Git patch was skipped" ) ;
188
+ // Write the modified contents back to the file
189
+ fs:: write ( c_header_path, c. as_ref ( ) ) . unwrap_or_else ( |_| {
190
+ panic ! (
191
+ "failed to write patched C header file {}" ,
192
+ c_header_path. display( )
193
+ )
194
+ } ) ;
189
195
}
190
-
191
196
fn locate_godot_binary ( ) -> PathBuf {
192
197
if let Ok ( string) = std:: env:: var ( "GODOT4_BIN" ) {
193
198
println ! ( "Found GODOT4_BIN with path to executable: '{string}'" ) ;
@@ -204,21 +209,6 @@ fn locate_godot_binary() -> PathBuf {
204
209
}
205
210
}
206
211
207
- fn locate_git_binary ( ) -> PathBuf {
208
- if let Ok ( string) = std:: env:: var ( "GIT_BIN" ) {
209
- println ! ( "Found GIT_BIN with path to executable: '{string}'" ) ;
210
- PathBuf :: from ( string)
211
- } else if let Ok ( path) = which:: which ( "git" ) {
212
- println ! ( "Found 'git' executable in PATH: {}" , path. display( ) ) ;
213
- path
214
- } else {
215
- panic ! (
216
- "gdext with `custom-godot` feature requires `git` executable or a GIT_BIN \
217
- environment variable (with the path to the executable)."
218
- )
219
- }
220
- }
221
-
222
212
fn execute ( mut cmd : Command , error_message : & str ) -> Output {
223
213
let output = cmd
224
214
. output ( )
0 commit comments