-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from rust3ds/feature/build-script-bindgen
- Loading branch information
Showing
16 changed files
with
163 additions
and
2,055 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,16 @@ | ||
[package] | ||
name = "citro3d-sys" | ||
version = "0.1.0" | ||
authors = [ "Rust3DS Org", "panicbit <[email protected]>" ] | ||
authors = ["Rust3DS Org", "panicbit <[email protected]>"] | ||
edition = "2021" | ||
license = "Zlib" | ||
links = "citro3d" | ||
|
||
[dependencies] | ||
libc = "0.2.116" | ||
ctru-sys = { git = "https://github.com/rust3ds/ctru-rs.git" } | ||
|
||
[build-dependencies] | ||
bindgen = { version = "0.68.1", features = ["experimental"] } | ||
cc = "1.0.83" | ||
doxygen-rs = "0.4.2" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,157 @@ | ||
//! This build script generates bindings from `citro3d` on the fly at compilation | ||
//! time into `OUT_DIR`, from which they can be included into `lib.rs`. | ||
use std::env; | ||
use std::iter::FromIterator; | ||
use std::path::{Path, PathBuf}; | ||
|
||
use bindgen::callbacks::{DeriveTrait, ImplementsTrait, ParseCallbacks}; | ||
use bindgen::{Builder, RustTarget}; | ||
|
||
fn main() { | ||
let dkp_path = env::var("DEVKITPRO").unwrap(); | ||
let devkitpro = env::var("DEVKITPRO").expect("DEVKITPRO not set in environment"); | ||
println!("cargo:rerun-if-env-changed=DEVKITPRO"); | ||
|
||
let devkitarm = std::env::var("DEVKITARM").expect("DEVKITARM not set in environment"); | ||
println!("cargo:rerun-if-env-changed=DEVKITARM"); | ||
|
||
let debug_symbols = env::var("DEBUG").unwrap(); | ||
println!("cargo:rerun-if-env-changed=DEBUG"); | ||
|
||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); | ||
println!("cargo:rerun-if-env-changed=OUT_DIR"); | ||
|
||
println!("cargo:rerun-if-changed=build.rs"); | ||
println!("cargo:rerun-if-env-changed=DEVKITPRO"); | ||
println!("cargo:rustc-link-search=native={dkp_path}/libctru/lib"); | ||
println!("cargo:rustc-link-search=native={devkitpro}/libctru/lib"); | ||
println!( | ||
"cargo:rustc-link-lib=static={}", | ||
match debug_symbols.as_str() { | ||
// Based on valid values described in | ||
// https://doc.rust-lang.org/cargo/reference/profiles.html#debug | ||
"0" | "false" => "citro3d", | ||
"0" | "false" | "none" => "citro3d", | ||
_ => "citro3dd", | ||
} | ||
); | ||
|
||
let include_path = PathBuf::from_iter([devkitpro.as_str(), "libctru", "include"]); | ||
let tex3ds_h = include_path.join("tex3ds.h"); | ||
let citro3d_h = include_path.join("citro3d.h"); | ||
let three_ds_h = include_path.join("3ds.h"); | ||
|
||
let sysroot = Path::new(devkitarm.as_str()).join("arm-none-eabi"); | ||
let system_include = sysroot.join("include"); | ||
let static_fns_path = Path::new("citro3d_statics_wrapper"); | ||
|
||
let gcc_dir = PathBuf::from_iter([devkitarm.as_str(), "lib", "gcc", "arm-none-eabi"]); | ||
|
||
let gcc_include = gcc_dir | ||
.read_dir() | ||
.unwrap() | ||
// Assuming that there is only one gcc version of libs under the devkitARM dir | ||
.next() | ||
.unwrap() | ||
.unwrap() | ||
.path() | ||
.join("include"); | ||
|
||
let bindings = Builder::default() | ||
.header(three_ds_h.to_str().unwrap()) | ||
.header(citro3d_h.to_str().unwrap()) | ||
.header(tex3ds_h.to_str().unwrap()) | ||
.rust_target(RustTarget::Nightly) | ||
.use_core() | ||
.trust_clang_mangling(false) | ||
.layout_tests(false) | ||
.ctypes_prefix("::libc") | ||
.prepend_enum_name(false) | ||
.fit_macro_constants(true) | ||
.raw_line("use ctru_sys::*;") | ||
.must_use_type("Result") | ||
.blocklist_type("u(8|16|32|64)") | ||
.opaque_type("(GPU|GFX)_.*") | ||
.opaque_type("float24Uniform_s") | ||
.allowlist_file(".*/c3d/.*[.]h") | ||
.allowlist_file(".*/tex3ds[.]h") | ||
.blocklist_file(".*/3ds/.*[.]h") | ||
.blocklist_file(".*/sys/.*[.]h") | ||
.wrap_static_fns(true) | ||
.wrap_static_fns_path(out_dir.join(static_fns_path)) | ||
.clang_args([ | ||
"--target=arm-none-eabi", | ||
"--sysroot", | ||
sysroot.to_str().unwrap(), | ||
"-isystem", | ||
system_include.to_str().unwrap(), | ||
"-isystem", | ||
gcc_include.to_str().unwrap(), | ||
"-I", | ||
include_path.to_str().unwrap(), | ||
"-mfloat-abi=hard", | ||
"-march=armv6k", | ||
"-mtune=mpcore", | ||
"-mfpu=vfp", | ||
"-DARM11 ", | ||
"-D_3DS ", | ||
"-D__3DS__ ", | ||
]) | ||
.parse_callbacks(Box::new(CustomCallbacks)) | ||
.generate() | ||
.expect("Unable to generate bindings"); | ||
|
||
bindings | ||
.write_to_file(out_dir.join("bindings.rs")) | ||
.expect("failed to write bindings"); | ||
|
||
// Compile static inline fns wrapper | ||
let cc = Path::new(devkitarm.as_str()).join("bin/arm-none-eabi-gcc"); | ||
let ar = Path::new(devkitarm.as_str()).join("bin/arm-none-eabi-ar"); | ||
|
||
cc::Build::new() | ||
.compiler(cc) | ||
.archiver(ar) | ||
.include(&include_path) | ||
.file(out_dir.join(static_fns_path.with_extension("c"))) | ||
.flag("-march=armv6k") | ||
.flag("-mtune=mpcore") | ||
.flag("-mfloat-abi=hard") | ||
.flag("-mfpu=vfp") | ||
.flag("-mtp=soft") | ||
.flag("-Wno-deprecated-declarations") | ||
.compile("citro3d_statics_wrapper"); | ||
} | ||
|
||
/// Custom callback struct to allow us to mark some "known good types" as | ||
/// [`Copy`], which in turn allows using Rust `union` instead of bindgen union types. See | ||
/// <https://rust-lang.github.io/rust-bindgen/using-unions.html#which-union-type-will-bindgen-generate> | ||
/// for more info. | ||
/// | ||
/// We do the same for [`Debug`] just for the convenience of derived Debug impls | ||
/// on some `citro3d` types. | ||
/// | ||
/// Finally, we use [`doxygen_rs`] to transform the doc comments into something | ||
/// easier to read in the generated documentation / hover documentation. | ||
#[derive(Debug)] | ||
struct CustomCallbacks; | ||
|
||
impl ParseCallbacks for CustomCallbacks { | ||
fn process_comment(&self, comment: &str) -> Option<String> { | ||
Some(doxygen_rs::transform(comment)) | ||
} | ||
|
||
fn blocklisted_type_implements_trait( | ||
&self, | ||
name: &str, | ||
derive_trait: DeriveTrait, | ||
) -> Option<ImplementsTrait> { | ||
if let DeriveTrait::Copy | DeriveTrait::Debug = derive_trait { | ||
match name { | ||
"u64_" | "u32_" | "u16_" | "u8_" | "u64" | "u32" | "u16" | "u8" | "gfxScreen_t" | ||
| "gfx3dSide_t" => Some(ImplementsTrait::Yes), | ||
_ if name.starts_with("GPU_") => Some(ImplementsTrait::Yes), | ||
_ => None, | ||
} | ||
} else { | ||
None | ||
} | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.