Skip to content

Commit 5b26d26

Browse files
committed
Add 'custom-godot' feature: generate api.json during build step
1 parent 5ebdbc8 commit 5b26d26

File tree

6 files changed

+67
-11
lines changed

6 files changed

+67
-11
lines changed

README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ The bindings cover most of the exposed API of Godot 3.4, and are being used on a
1818

1919
We are committed to keeping compatibility with the latest stable patch releases of all minor versions of the engine, starting from Godot 3.2:
2020
* Godot 3.4 (works out-of-the-box)
21-
* Godot 3.3 (needs api.json adjustment)
22-
* Godot 3.2 (needs api.json adjustment)
21+
* Godot 3.3 (needs feature `custom-godot`)
22+
* Godot 3.2 (needs feature `custom-godot`)
2323

2424
For versions 3.2 and 3.3, some extra steps are needed, see _Custom builds_ below.
2525

@@ -45,6 +45,7 @@ This means that `bindgen` was unable to find the C system headers for your platf
4545

4646
### Latest `master` version + Godot 3.4
4747

48+
This is the recommended way of using godot-rust, if you want to benefit from latest features.
4849
After `bindgen` dependencies are installed, add the `gdnative` crate as a dependency, and set the crate type to `cdylib`:
4950

5051
```toml
@@ -57,7 +58,7 @@ crate-type = ["cdylib"]
5758

5859
### Godot 3.2.3-stable
5960

60-
To access the last released version on crates.io, use the following. If you are starting, we recommend using the `master` version at this point, as there have been significant API changes since v0.9.3.
61+
To access the last released version on crates.io, use the following. Note that there have been significant API changes since v0.9.3 -- if you are starting to use godot-rust, we recommend using the `master` version instead.
6162

6263
```toml
6364
[dependencies]
@@ -69,9 +70,7 @@ crate-type = ["cdylib"]
6970

7071
### Custom builds
7172

72-
To use the bindings with a non-default Godot version or a custom build, see [Using custom builds of Godot](https://godot-rust.github.io/book/advanced-guides/custom-godot.html) in the user guide.
73-
74-
In short, you will need to generate `api.json` manually, using `godot --gdnative-generate-json-api api.json` to replace the file in the `gdnative-bindings` directory.
73+
To use the bindings with a different Godot version or a custom build of the engine, see [Custom Godot builds](https://godot-rust.github.io/book/advanced-guides/custom-godot.html) in the user guide.
7574

7675
### Async / `yield` support
7776

gdnative-bindings/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ edition = "2018"
1313
[features]
1414
formatted = []
1515
one_class_one_file = []
16+
custom-godot = ["which"]
1617

1718
[dependencies]
1819
gdnative-sys = { path = "../gdnative-sys", version = "0.9.3" }
@@ -23,3 +24,4 @@ bitflags = "1.3.2"
2324
[build-dependencies]
2425
heck = "0.4.0"
2526
gdnative_bindings_generator = { path = "../bindings_generator", version = "=0.9.3" }
27+
which = { optional = true, version = "4.2.2" }

gdnative-bindings/build.rs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use std::path::{Path, PathBuf};
77
use std::process::Command;
88

99
fn main() {
10+
let just_generated_api = generate_api_if_needed();
11+
1012
let api_data = std::fs::read_to_string("api.json").expect("Unable to read api.json");
1113

1214
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
@@ -39,8 +41,12 @@ fn main() {
3941
// Ignoring all but build.rs will keep from needless rebuilds.
4042
// Manually rebuilding the crate will ignore this.
4143
println!("cargo:rerun-if-changed=docs/");
42-
println!("cargo:rerun-if-changed=api.json");
4344
println!("cargo:rerun-if-changed=build.rs");
45+
46+
// Avoid endless recompiling, if this script generates api.json
47+
if !just_generated_api {
48+
println!("cargo:rerun-if-changed=api.json");
49+
}
4450
}
4551

4652
/// Output all the class bindings into the `generated.rs` file.
@@ -147,3 +153,43 @@ fn format_file(output_rs: &Path) {
147153
}
148154
}
149155
}
156+
157+
#[cfg(feature = "custom-godot")]
158+
fn generate_api_if_needed() -> bool {
159+
let source: String;
160+
let godot_bin: PathBuf;
161+
162+
if let Ok(string) = env::var("GODOT_BIN") {
163+
source = format!("GODOT_BIN executable '{}'", string);
164+
godot_bin = PathBuf::from(string);
165+
} else if let Ok(path) = which::which("godot") {
166+
source = "executable 'godot'".to_string();
167+
godot_bin = path;
168+
} else {
169+
panic!(
170+
"Feature 'custom-godot' requires an accessible 'godot' executable or \
171+
a GODOT_BIN environment variable (with the path to the executable)."
172+
);
173+
};
174+
175+
// TODO call 'godot --version' and ensure >= 3.2 && < 4.0
176+
177+
let status = Command::new(godot_bin)
178+
.arg("--gdnative-generate-json-api")
179+
.arg("api.json")
180+
.status()
181+
.unwrap_or_else(|err| panic!("Failed to invoke {}; error {}", source, err));
182+
183+
assert!(
184+
status.success(),
185+
"Custom Godot command exited with status {}",
186+
status.code().map_or("?".to_string(), |f| f.to_string())
187+
);
188+
189+
true
190+
}
191+
192+
#[cfg(not(feature = "custom-godot"))]
193+
fn generate_api_if_needed() -> bool {
194+
false
195+
}

gdnative/Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,17 @@ readme = "../README.md"
1212
edition = "2018"
1313

1414
[features]
15+
# Public
16+
async = ["gdnative-async", "bindings"]
17+
bindings = ["gdnative-bindings"]
18+
custom-godot = ["gdnative-bindings/custom-godot"]
1519
default = ["bindings"]
1620
formatted = ["gdnative-bindings/formatted", "gdnative-bindings/one_class_one_file"]
1721
serde = ["gdnative-core/serde"]
1822

23+
# Internal
1924
gd_test = ["gdnative-core/gd_test"]
2025
type_tag_fallback = ["gdnative-core/type_tag_fallback"]
21-
bindings = ["gdnative-bindings"]
22-
async = ["gdnative-async", "bindings"]
2326

2427
[dependencies]
2528
gdnative-derive = { path = "../gdnative-derive", version = "=0.9.3" }

gdnative/src/lib.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,16 @@
4040
//! on `Ref`.
4141
//!
4242
//! ## Feature flags
43+
//! Functionality toggles:
44+
//! * `async` -- *disabled* by default. Enables asyn functionality, see [`tasks`] module for details.
45+
//! * `serde` -- *disabled* by default. Enable for `serde` support. See also
46+
//! [`Variant`](core_types::Variant).
4347
//!
48+
//! Affecting bindings generation:
4449
//! * `bindings` -- *enabled* by default. Includes the crates.io version of the bindings in the
4550
//! `api` module. Disable if you want to use a custom Godot version.
46-
//! * `serde` -- *disabled* by default. Enable for `serde` support. See also
47-
//! [`Variant`](core_types::Variant).
51+
//! * `custom-godot` -- *disabled* by default. When active, looks for a `GODOT_BIN` environment
52+
//! variable pointing to the Godot executable, or a `godot` executable in the path.
4853
//! * `formatted` -- *disabled* by default. Enable if the generated binding source code should
4954
//! be human-readable.
5055
//!

test/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ crate-type = ["cdylib"]
1111
[features]
1212
default = []
1313
type_tag_fallback = ["gdnative/type_tag_fallback"]
14+
custom-godot = ["gdnative/custom-godot"]
1415

1516
[dependencies]
1617
gdnative = { path = "../gdnative", features = ["gd_test", "serde", "async"] }

0 commit comments

Comments
 (0)