Skip to content

Commit

Permalink
Merge pull request #26 from rust3ds/feature/build-script-bindgen
Browse files Browse the repository at this point in the history
  • Loading branch information
ian-h-chamberlain authored Oct 5, 2023
2 parents 333860e + 97f4835 commit 96b2c18
Show file tree
Hide file tree
Showing 16 changed files with 163 additions and 2,055 deletions.
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
[workspace]
members = [
"bindgen-citro3d",
"citro3d-macros",
"citro3d-sys",
"citro3d",
"citro3d-sys",
"citro3d-macros",
]
default-members = [
"citro3d",
Expand All @@ -13,4 +12,6 @@ default-members = [
resolver = "2"

[patch."https://github.com/rust3ds/citro3d-rs.git"]
citro3d = { path = "citro3d" }
citro3d-sys = { path = "citro3d-sys" }
citro3d-macros = { path = "citro3d-macros" }
9 changes: 0 additions & 9 deletions bindgen-citro3d/Cargo.toml

This file was deleted.

92 changes: 0 additions & 92 deletions bindgen-citro3d/src/main.rs

This file was deleted.

8 changes: 7 additions & 1 deletion citro3d-sys/Cargo.toml
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"
146 changes: 142 additions & 4 deletions citro3d-sys/build.rs
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
}
}
}
9 changes: 0 additions & 9 deletions citro3d-sys/src/base.rs

This file was deleted.

Loading

0 comments on commit 96b2c18

Please sign in to comment.