Browse Source

Merge pull request #133 from FenrirWolf/static-inline-fns

Support static inline functions in ctru-sys
pull/136/head
Meziu 1 year ago committed by GitHub
parent
commit
53154c5d1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Cargo.toml
  2. 5
      ctru-sys/Cargo.toml
  3. 8
      ctru-sys/bindgen-ctru-sys/Cargo.toml
  4. 62
      ctru-sys/bindgen-ctru-sys/src/main.rs
  5. 29
      ctru-sys/bindgen.sh
  6. 111
      ctru-sys/build.rs
  7. 18456
      ctru-sys/src/bindings.rs
  8. 6
      ctru-sys/src/lib.rs

2
Cargo.toml

@ -1,5 +1,5 @@
[workspace] [workspace]
members = ["ctru-rs", "ctru-sys", "ctru-sys/bindgen-ctru-sys"] members = ["ctru-rs", "ctru-sys"]
default-members = ["ctru-rs", "ctru-sys"] default-members = ["ctru-rs", "ctru-sys"]
resolver = "2" resolver = "2"

5
ctru-sys/Cargo.toml

@ -6,7 +6,7 @@ description = "Raw bindings to libctru"
repository = "https://github.com/rust3ds/ctru-rs" repository = "https://github.com/rust3ds/ctru-rs"
keywords = ["3ds", "libctru"] keywords = ["3ds", "libctru"]
categories = ["os", "external-ffi-bindings", "no-std", "hardware-support"] categories = ["os", "external-ffi-bindings", "no-std", "hardware-support"]
exclude = ["bindgen.sh", "src/.gitattributes"] exclude = ["src/.gitattributes"]
license = "Zlib" license = "Zlib"
links = "ctru" links = "ctru"
edition = "2021" edition = "2021"
@ -15,6 +15,9 @@ edition = "2021"
libc = { version = "0.2.121", default-features = false } libc = { version = "0.2.121", default-features = false }
[build-dependencies] [build-dependencies]
bindgen = { version = "0.65.1", features = ["experimental"] }
cc = "1.0"
doxygen-rs = "0.4.2"
which = "4.4.0" which = "4.4.0"
[package.metadata.docs.rs] [package.metadata.docs.rs]

8
ctru-sys/bindgen-ctru-sys/Cargo.toml

@ -1,8 +0,0 @@
[package]
name = "bindgen-ctru-sys"
version = "0.1.0"
edition = "2021"
[dependencies]
bindgen = "0.65.1"
doxygen-rs = "0.4.2"

62
ctru-sys/bindgen-ctru-sys/src/main.rs

@ -1,62 +0,0 @@
use bindgen::callbacks::ParseCallbacks;
use bindgen::{Builder, RustTarget};
use std::path::PathBuf;
#[derive(Debug)]
struct CustomCallbacks;
impl ParseCallbacks for CustomCallbacks {
fn process_comment(&self, comment: &str) -> Option<String> {
Some(doxygen_rs::transform(comment))
}
}
fn main() {
let devkitpro = std::env::var("DEVKITPRO").expect("DEVKITPRO not set in environment");
let devkitarm = std::env::var("DEVKITARM").expect("DEVKITARM not set in environment");
let include_path = PathBuf::from_iter([devkitpro.as_str(), "libctru", "include"]);
let ctru_header = include_path.join("3ds.h");
let sysroot = PathBuf::from(devkitarm).join("arm-none-eabi");
let system_include = sysroot.join("include");
let errno_header = system_include.join("errno.h");
let bindings = Builder::default()
.header(ctru_header.to_str().unwrap())
.header(errno_header.to_str().unwrap())
.rust_target(RustTarget::Nightly)
.use_core()
.trust_clang_mangling(false)
.must_use_type("Result")
.layout_tests(false)
.ctypes_prefix("::libc")
.prepend_enum_name(false)
.blocklist_type("u(8|16|32|64)")
.blocklist_type("__builtin_va_list")
.blocklist_type("__va_list")
.opaque_type("MiiData")
.derive_default(true)
.clang_args([
"--target=arm-none-eabi",
"--sysroot",
sysroot.to_str().unwrap(),
"-isystem",
system_include.to_str().unwrap(),
"-I",
include_path.to_str().unwrap(),
"-mfloat-abi=hard",
"-march=armv6k",
"-mtune=mpcore",
"-mfpu=vfp",
"-DARM11",
"-D__3DS__",
])
.parse_callbacks(Box::new(CustomCallbacks))
.generate()
.expect("unable to generate bindings");
bindings
.write(Box::new(std::io::stdout()))
.expect("failed to write bindings");
}

29
ctru-sys/bindgen.sh

@ -1,29 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
echo "Determining libctru version..."
pacman=dkp-pacman
if ! command -v $pacman &>/dev/null; then
pacman=pacman
if ! command -v $pacman &>/dev/null; then
echo >&2 "ERROR: Unable to automatically determine libctru version!"
exit 1
fi
fi
LIBCTRU_VERSION="$($pacman -Qi libctru | grep Version | cut -d: -f 2 | tr -d ' ')"
CTRU_SYS_VERSION="$(
printf '%s' "$LIBCTRU_VERSION" |
cut -d- -f1 |
sed -E 's/^([0-9]+)\.([0-9.]+)$/\1\2/'
)"
echo "Generating bindings.rs..."
cargo run --package bindgen-ctru-sys > src/bindings.rs
echo "Formatting generated files..."
cargo fmt --all
echo "Generated bindings for ctru-sys version \"${CTRU_SYS_VERSION}.x+${LIBCTRU_VERSION}\""

111
ctru-sys/build.rs

@ -1,14 +1,29 @@
use bindgen::callbacks::ParseCallbacks;
use bindgen::{Builder, RustTarget};
use std::env; use std::env;
use std::error::Error; use std::error::Error;
use std::path::{Path, PathBuf};
use std::process::{Command, Output, Stdio}; use std::process::{Command, Output, Stdio};
#[derive(Debug)]
struct CustomCallbacks;
impl ParseCallbacks for CustomCallbacks {
fn process_comment(&self, comment: &str) -> Option<String> {
Some(doxygen_rs::transform(comment))
}
}
fn main() { fn main() {
let dkp_path = env::var("DEVKITPRO").unwrap(); let devkitpro = env::var("DEVKITPRO").unwrap();
let devkitarm = env::var("DEVKITARM").unwrap();
let profile = env::var("PROFILE").unwrap(); let profile = env::var("PROFILE").unwrap();
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=DEVKITPRO"); 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!( println!(
"cargo:rustc-link-lib=static={}", "cargo:rustc-link-lib=static={}",
match profile.as_str() { match profile.as_str() {
@ -30,9 +45,97 @@ fn main() {
} }
Err(err) => println!("cargo:warning=failed to check libctru version: {err}"), Err(err) => println!("cargo:warning=failed to check libctru version: {err}"),
} }
let gcc_version = get_gcc_version(PathBuf::from(&devkitarm).join("bin/arm-none-eabi-gcc"));
let include_path = PathBuf::from_iter([devkitpro.as_str(), "libctru", "include"]);
let ctru_header = include_path.join("3ds.h");
let sysroot = Path::new(&devkitarm).join("arm-none-eabi");
let system_include = sysroot.join("include");
let gcc_include = PathBuf::from(format!(
"{devkitarm}/lib/gcc/arm-none-eabi/{gcc_version}/include"
));
let errno_header = system_include.join("errno.h");
// Build libctru bindings
let bindings = Builder::default()
.header(ctru_header.to_str().unwrap())
.header(errno_header.to_str().unwrap())
.rust_target(RustTarget::Nightly)
.use_core()
.trust_clang_mangling(false)
.must_use_type("Result")
.layout_tests(false)
.ctypes_prefix("::libc")
.prepend_enum_name(false)
.blocklist_type("u(8|16|32|64)")
.blocklist_type("__builtin_va_list")
.blocklist_type("__va_list")
.opaque_type("MiiData")
.derive_default(true)
.wrap_static_fns(true)
.wrap_static_fns_path(out_dir.join("libctru_statics_wrapper"))
.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__",
])
.parse_callbacks(Box::new(CustomCallbacks))
.generate()
.expect("unable to generate bindings");
bindings
.write_to_file(out_dir.join("bindings.rs"))
.expect("Couldn't 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("libctru_statics_wrapper.c"))
.flag("-march=armv6k")
.flag("-mtune=mpcore")
.flag("-mfloat-abi=hard")
.flag("-mfpu=vfp")
.flag("-mtp=soft")
.flag("-Wno-deprecated-declarations")
.compile("ctru_statics_wrapper");
}
fn get_gcc_version(path_to_gcc: PathBuf) -> String {
let Output { stdout, .. } = Command::new(path_to_gcc)
.arg("--version")
.stderr(Stdio::inherit())
.output()
.unwrap();
let stdout_str = String::from_utf8_lossy(&stdout);
stdout_str
.split(|c: char| c.is_whitespace())
.nth(4)
.unwrap()
.to_string()
} }
fn parse_version(version: &str) -> Result<(String, String, String), &str> { fn parse_libctru_version(version: &str) -> Result<(String, String, String), &str> {
let versions: Vec<_> = version let versions: Vec<_> = version
.split(|c| c == '.' || c == '-') .split(|c| c == '.' || c == '-')
.map(String::from) .map(String::from)
@ -84,6 +187,6 @@ fn check_libctru_version() -> Result<(String, String, String), Box<dyn Error>> {
println!("cargo:rerun-if-changed={file}"); println!("cargo:rerun-if-changed={file}");
} }
let (lib_major, lib_minor, lib_patch) = parse_version(lib_version)?; let (lib_major, lib_minor, lib_patch) = parse_libctru_version(lib_version)?;
Ok((lib_major, lib_minor, lib_patch)) Ok((lib_major, lib_minor, lib_patch))
} }

18456
ctru-sys/src/bindings.rs generated

File diff suppressed because it is too large Load Diff

6
ctru-sys/src/lib.rs

@ -5,12 +5,10 @@
#![allow(clippy::all)] #![allow(clippy::all)]
pub mod result; pub mod result;
mod bindings;
pub use bindings::*;
pub use result::*; pub use result::*;
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
/// In lieu of a proper errno function exposed by libc /// In lieu of a proper errno function exposed by libc
/// (<https://github.com/rust-lang/libc/issues/1995>). /// (<https://github.com/rust-lang/libc/issues/1995>).
pub unsafe fn errno() -> s32 { pub unsafe fn errno() -> s32 {

Loading…
Cancel
Save