Skip to content

Commit 6b09018

Browse files
MarijnS95claude
andcommitted
Move bindgen generation from build.rs to api_gen binary
Replace the `generate-bindings` feature + build.rs approach with a dedicated `api_gen` workspace member binary, following the pattern used by fidelityfx-rs. Bindings are generated by running `cargo r -p api_gen` instead of `cargo b -Fgenerate-bindings`. This pins bindgen to =0.72.1 for reproducible output and removes the build-dependency from the published crate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fc4c14e commit 6b09018

File tree

5 files changed

+38
-18
lines changed

5 files changed

+38
-18
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ jobs:
5454
src/xess/vk.rs
5555
src/xess/xess.rs
5656
- name: Generate
57-
run: cargo b -Fgenerate-bindings
57+
run: cargo r -p api_gen
5858
- name: Upload crate source
5959
uses: actions/upload-artifact@v6
6060
with:
6161
name: crate-source
6262
path: src/
6363
- name: Diff generated Rust code
6464
shell: bash
65-
run: test -z "$(git status --porcelain)" || (echo "::error::Generated files are different, please regenerate with cargo b -Fgenerate-bindings!"; git status; false)
65+
run: test -z "$(git status --porcelain)" || (echo "::error::Generated files are different, please regenerate with 'cargo r -p api_gen'!"; git status; false)

Cargo.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
[workspace]
2+
members = ["api_gen"]
3+
14
[package]
25
name = "xess-sys"
36
version = "0.1.0"
@@ -12,7 +15,7 @@ categories = ["external-ffi-bindings", "graphics", "rendering"]
1215
keywords = ["Intel", "XeSS", "XeLL", "frame generation", "upscaling"]
1316
rust-version = "1.74"
1417

15-
# Headers contain a sequence of characters which are incorrectly interpreted as a doctest, these obviously fail
18+
# Headers contain a sequence of characters which are incorrectly interpreted as a doctest, these obviously fail
1619
[lib]
1720
doctest = false
1821

@@ -23,12 +26,8 @@ libloading = { version = "0.8", default-features = false }
2326
[target.'cfg(windows)'.dependencies]
2427
windows = { version = "0.62", default-features = false, optional = true }
2528

26-
[build-dependencies]
27-
bindgen = { version = "0.72", optional = true }
28-
2929
[features]
3030
default = ["vk", "dx12", "xess"]
31-
generate-bindings = ["dep:bindgen"]
3231
dx11 = []
3332
dx12 = []
3433
vk = ["dep:ash"]

api_gen/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "api_gen"
3+
edition = "2024"
4+
publish = false
5+
6+
[dependencies]
7+
# Pin version to have control over how everything is generated (there is a CI
8+
# check that validates that all files are generated as currently checked in):
9+
bindgen = "=0.72.1"

build.rs renamed to api_gen/src/main.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
#[cfg(feature = "generate-bindings")]
1+
use std::path::Path;
2+
23
fn vulkan_sdk_include_directory() -> Option<std::path::PathBuf> {
3-
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
4-
let is_windows = target_os.as_str() == "windows";
4+
let is_windows = cfg!(target_os = "windows");
55

66
// Mostly on Windows, the Vulkan headers don't exist in a common location but can be found based
77
// on VULKAN_SDK, set by the Vulkan SDK installer.
@@ -22,9 +22,8 @@ fn vulkan_sdk_include_directory() -> Option<std::path::PathBuf> {
2222
}
2323
}
2424

25-
#[cfg(feature = "generate-bindings")]
2625
fn generate_bindings() {
27-
let compile = |input_file, output_file, allowlist_function, allowlist_type| {
26+
let compile = |input_file: &str, output_file: &str, allowlist_function, allowlist_type| {
2827
let mut bindings = bindgen::Builder::default()
2928
.header(input_file)
3029
.allowlist_recursively(false)
@@ -33,12 +32,15 @@ fn generate_bindings() {
3332
.allowlist_var(".*xess.*")
3433
.bitfield_enum(".*(flags|bits).*")
3534
.newtype_enum(".*result_t.*")
35+
.newtype_enum(".*logging_level_t.*")
3636
.default_enum_style(bindgen::EnumVariation::Rust {
3737
non_exhaustive: false,
3838
})
3939
.parse_callbacks(Box::new(RenameCallback))
4040
.derive_default(true)
41-
.clang_args(["-x", "c++"])
41+
// XeSS headers are Windows-only (D3D12, DXGI, etc.), so clang must
42+
// always target MSVC even when api_gen itself runs on Linux.
43+
.clang_args(["-x", "c++", "--target=x86_64-pc-windows-msvc"])
4244
.prepend_enum_name(false)
4345
.layout_tests(false)
4446
.dynamic_link_require_all(true)
@@ -47,11 +49,20 @@ fn generate_bindings() {
4749
assert!(vulkan_sdk_include_dir.is_dir());
4850
bindings = bindings.clang_arg(format!("-I{}", vulkan_sdk_include_dir.display()))
4951
}
52+
53+
let output_path = Path::new(output_file);
54+
assert!(
55+
output_path.parent().unwrap().is_dir(),
56+
"Output directory does not exist for {output_file}"
57+
);
58+
5059
bindings
5160
.generate()
5261
.expect("Unable to generate bindings")
53-
.write_to_file(output_file)
62+
.write_to_file(output_path)
5463
.expect("Couldn't write bindings");
64+
65+
println!("Generated {output_file}");
5566
};
5667

5768
compile(
@@ -114,11 +125,9 @@ fn generate_bindings() {
114125
);
115126
}
116127

117-
#[cfg(feature = "generate-bindings")]
118128
#[derive(Debug)]
119129
struct RenameCallback;
120130

121-
#[cfg(feature = "generate-bindings")]
122131
impl bindgen::callbacks::ParseCallbacks for RenameCallback {
123132
fn enum_variant_name(
124133
&self,
@@ -168,6 +177,5 @@ impl bindgen::callbacks::ParseCallbacks for RenameCallback {
168177
}
169178

170179
fn main() {
171-
#[cfg(feature = "generate-bindings")]
172180
generate_bindings();
173181
}

src/xell/xell.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ where
4949
index % 8
5050
};
5151
let mask = 1 << bit_index;
52-
if val { byte | mask } else { byte & !mask }
52+
if val {
53+
byte | mask
54+
} else {
55+
byte & !mask
56+
}
5357
}
5458
#[inline]
5559
pub fn set_bit(&mut self, index: usize, val: bool) {

0 commit comments

Comments
 (0)