Browse Source

Merge branch 'master' into feature/ir-user

pull/86/head
AzureMarker 1 year ago
parent
commit
44a061abc2
  1. 6
      .github/workflows/ci.yml
  2. 62
      .github/workflows/docs.yml
  3. 10
      README.md
  4. 2
      _config.yml
  5. 15
      assets/css/style.scss
  6. 3
      ctru-rs/Cargo.toml
  7. 2
      ctru-rs/README.md
  8. 8
      ctru-rs/src/error.rs
  9. 1
      ctru-rs/src/lib.rs
  10. 8
      ctru-sys/Cargo.toml
  11. 32
      ctru-sys/README.md
  12. 132
      ctru-sys/build.rs
  13. 17
      ctru-sys/src/lib.rs

6
.github/workflows/ci.yml

@ -75,17 +75,17 @@ jobs:
# unless cargo-3ds actually runs them as separate commands. See # unless cargo-3ds actually runs them as separate commands. See
# https://github.com/rust3ds/cargo-3ds/issues/44 for more details # https://github.com/rust3ds/cargo-3ds/issues/44 for more details
- name: Build lib and integration tests - name: Build lib and integration tests
run: cargo 3ds test --no-run --tests --package ctru-rs run: cargo 3ds test --no-run --tests
- name: Run lib and integration tests - name: Run lib and integration tests
uses: rust3ds/test-runner/run-tests@v1 uses: rust3ds/test-runner/run-tests@v1
with: with:
args: --tests --package ctru-rs args: --tests
- name: Build and run doc tests - name: Build and run doc tests
uses: rust3ds/test-runner/run-tests@v1 uses: rust3ds/test-runner/run-tests@v1
with: with:
args: --doc --package ctru-rs args: --doc
- name: Upload citra logs and capture videos - name: Upload citra logs and capture videos
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v3

62
.github/workflows/docs.yml

@ -0,0 +1,62 @@
name: GitHub Pages
on:
push:
branches:
- master
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
container: devkitpro/devkitarm
steps:
- name: Checkout branch
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Build with Jekyll
uses: actions/jekyll-build-pages@v1
- uses: rust3ds/test-runner/setup@v1
with:
toolchain: nightly
- name: Build workspace docs
run: cargo 3ds --verbose doc --verbose --no-deps --workspace
env:
RUSTDOCFLAGS: --enable-index-page
# https://github.com/actions/upload-pages-artifact#file-permissions
- name: Fix file permissions
run: |
chmod -c -R +rX "target/armv6k-nintendo-3ds/doc" | while read line; do
echo "::warning title=Invalid file permissions automatically fixed::$line"
done
- name: Copy generated docs to _site
# Note: this won't include proc-macro crate, but macros are re-exported
# by the crate docs so there will still be some documentation.
run: cp -R ./target/armv6k-nintendo-3ds/doc ./_site/crates
- name: Upload docs
uses: actions/upload-pages-artifact@v2
deploy:
runs-on: ubuntu-latest
needs: build
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2

10
README.md

@ -6,14 +6,20 @@ This repository is home of the `ctru-rs` project, which aims to bring full contr
This repository is organized as follows: This repository is organized as follows:
* [`ctru-rs`](./ctru-rs/) - Safe, idiomatic wrapper around [`ctru-sys`](./ctru-sys/). * [`ctru-rs`](./ctru-rs) - Safe, idiomatic wrapper around [`ctru-sys`](./ctru-sys).
* [`ctru-sys`](./ctru-sys/) - Low-level, unsafe bindings to [`libctru`](https://github.com/devkitPro/libctru). * [`ctru-sys`](./ctru-sys) - Low-level, unsafe bindings to [`libctru`](https://github.com/devkitPro/libctru).
## Getting Started ## Getting Started
Specific information about how to use the crates is present in the individual README for each package. Specific information about how to use the crates is present in the individual README for each package.
Have a look at `ctru-rs`' [README.md](./ctru-rs/README.md) for a broad overview. Have a look at `ctru-rs`' [README.md](./ctru-rs/README.md) for a broad overview.
## Documentation
Cargo-generated [documentation](https://rust3ds.github.io/ctru-rs/crates) is available
via GitHub Pages, because the <https://docs.rs> build environment does not have `libctru`
installed.
## Original version ## Original version
This project is based on the efforts of the original authors: This project is based on the efforts of the original authors:

2
_config.yml

@ -0,0 +1,2 @@
# Configuration for GitHub Pages (Jekyll)
theme: jekyll-theme-midnight

15
assets/css/style.scss

@ -0,0 +1,15 @@
---
---
// https://github.com/pages-themes/midnight#stylesheet
@import "{{ site.theme }}";
// Give code links a color that matches regular links
a code {
color: inherit;
}
// Remove weird extra padding and spaces from inline code blocks
code {
padding: 0;
}

3
ctru-rs/Cargo.toml

@ -4,6 +4,7 @@ version = "0.7.1"
authors = ["Rust3DS Org", "Ronald Kinard <furyhunter600@gmail.com>"] authors = ["Rust3DS Org", "Ronald Kinard <furyhunter600@gmail.com>"]
description = "A safe wrapper around libctru" description = "A safe wrapper around libctru"
repository = "https://github.com/rust3ds/ctru-rs" repository = "https://github.com/rust3ds/ctru-rs"
documentation = "https://rust3ds.github.io/ctru-rs/crates/ctru"
keywords = ["3ds", "libctru"] keywords = ["3ds", "libctru"]
categories = ["os", "api-bindings", "hardware-support"] categories = ["os", "api-bindings", "hardware-support"]
exclude = ["examples"] exclude = ["examples"]
@ -17,7 +18,7 @@ name = "ctru"
[dependencies] [dependencies]
cfg-if = "1.0" cfg-if = "1.0"
ctru-sys = { path = "../ctru-sys", version = "22.2" } ctru-sys = { path = "../ctru-sys", version = "0.5.0" }
const-zero = "0.1.0" const-zero = "0.1.0"
shim-3ds = { git = "https://github.com/rust3ds/shim-3ds.git" } shim-3ds = { git = "https://github.com/rust3ds/shim-3ds.git" }
pthread-3ds = { git = "https://github.com/rust3ds/pthread-3ds.git" } pthread-3ds = { git = "https://github.com/rust3ds/pthread-3ds.git" }

2
ctru-rs/README.md

@ -2,6 +2,8 @@
Safe and idiomatic Rust wrapper around [`libctru`](https://github.com/devkitPro/libctru). Safe and idiomatic Rust wrapper around [`libctru`](https://github.com/devkitPro/libctru).
Documentation for the `master` branch can be found [here](https://rust3ds.github.io/ctru-rs/crates/ctru).
## Getting Started ## Getting Started
Thoroughly read the [`ctru-rs` wiki](https://github.com/rust3ds/ctru-rs/wiki/Getting-Started) to meet the requirements Thoroughly read the [`ctru-rs` wiki](https://github.com/rust3ds/ctru-rs/wiki/Getting-Started) to meet the requirements

8
ctru-rs/src/error.rs

@ -263,7 +263,13 @@ fn result_code_description_str(result: ctru_sys::Result) -> Cow<'static, str> {
RD_NOT_AUTHORIZED => "not_authorized", RD_NOT_AUTHORIZED => "not_authorized",
RD_TOO_LARGE => "too_large", RD_TOO_LARGE => "too_large",
RD_INVALID_SELECTION => "invalid_selection", RD_INVALID_SELECTION => "invalid_selection",
code => return Cow::Owned(format!("(unknown description: {code:#x})")), code => {
let error = unsafe { CStr::from_ptr(ctru_sys::osStrError(result)) }.to_str();
match error {
Ok(err) => err,
Err(_) => return Cow::Owned(format!("(unknown description: {code:#x})")),
}
}
}) })
} }

1
ctru-rs/src/lib.rs

@ -28,6 +28,7 @@
#![doc( #![doc(
html_logo_url = "https://user-images.githubusercontent.com/11131775/225929072-2fa1741c-93ae-4b47-9bdf-af70f3d59910.png" html_logo_url = "https://user-images.githubusercontent.com/11131775/225929072-2fa1741c-93ae-4b47-9bdf-af70f3d59910.png"
)] )]
#![doc(html_root_url = "https://rust3ds.github.io/ctru-rs/crates")]
// Nothing is imported from these crates but their inclusion here assures correct linking of the missing implementations. // Nothing is imported from these crates but their inclusion here assures correct linking of the missing implementations.
extern crate pthread_3ds; extern crate pthread_3ds;

8
ctru-sys/Cargo.toml

@ -1,9 +1,10 @@
[package] [package]
name = "ctru-sys" name = "ctru-sys"
version = "22.2.0+2.2.2-1" version = "0.5.0"
authors = ["Rust3DS Org", "Ronald Kinard <furyhunter600@gmail.com>"] authors = ["Rust3DS Org", "Ronald Kinard <furyhunter600@gmail.com>"]
description = "Raw bindings to libctru" description = "Raw bindings to libctru"
repository = "https://github.com/rust3ds/ctru-rs" repository = "https://github.com/rust3ds/ctru-rs"
documentation = "https://rust3ds.github.io/ctru-rs/crates/ctru_sys"
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 = ["src/.gitattributes"] exclude = ["src/.gitattributes"]
@ -18,8 +19,13 @@ libc = { version = "0.2.121", default-features = false }
bindgen = { version = "0.65.1", features = ["experimental"] } bindgen = { version = "0.65.1", features = ["experimental"] }
cc = "1.0" cc = "1.0"
doxygen-rs = "0.4.2" doxygen-rs = "0.4.2"
itertools = "0.11.0"
which = "4.4.0" which = "4.4.0"
[dev-dependencies]
shim-3ds = { git = "https://github.com/rust3ds/shim-3ds.git" }
test-runner = { git = "https://github.com/rust3ds/test-runner.git" }
[package.metadata.docs.rs] [package.metadata.docs.rs]
default-target = "armv6k-nintendo-3ds" default-target = "armv6k-nintendo-3ds"
targets = [] targets = []

32
ctru-sys/README.md

@ -2,6 +2,10 @@
Raw Rust bindings over the [`libctru`](https://github.com/devkitPro/libctru) C library. Raw Rust bindings over the [`libctru`](https://github.com/devkitPro/libctru) C library.
Documentation for the latest devkitPro release
[on Docker Hub](https://hub.docker.com/r/devkitpro/devkitarm/)
can be found [here](https://rust3ds.github.io/ctru-rs/crates/ctru_sys).
## Requirements ## Requirements
To use the bindings provided by this crate you will need to link against the [`libctru`](https://github.com/devkitPro/libctru) library. To use the bindings provided by this crate you will need to link against the [`libctru`](https://github.com/devkitPro/libctru) library.
@ -10,23 +14,17 @@ to use this library.
## Version ## Version
This crate's version changes according to the version of `libctru` Crate bindings are generated at build time, so the available APIs will depend on the
used to generate the bindings, with the following convention: installed version of `libctru` when the crate is built. If you want to check
what version of `libctru` is being built, you can examine these environment
* [`libctru`](https://github.com/devkitPro/libctru) version `X.Y.Z-W` variables from your crate's build script via to its
* `ctru-sys` version `XY.Z.P+X.Y.Z-W` [`links` variables](https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key):
where `P` is usually 0 but may be incremented for fixes in e.g. * `DEP_CTRU_VERSION`: full version string (e.g. `"2.3.1-4"`)
binding generation, `libc` dependency bump, etc. * `DEP_CTRU_MAJOR_VERSION`: major version (e.g. `"2"` for version `2.3.1-4`)
* `DEP_CTRU_MINOR_VERSION`: minor version (e.g. `"3"` for version `2.3.1-4`)
It may be possible to build this crate against a different version of [`libctru`](https://github.com/devkitPro/libctru), * `DEP_CTRU_PATCH_VERSION`: patch version (e.g. `"1"` for version `2.3.1-4`)
but you may encounter linker errors or ABI issues. A build-time Cargo warning * `DEP_CTRU_RELEASE`: release version (e.g. `"4"` for version `2.3.1-4`)
(displayed when built with `-vv`) will be issued if the build script detects
a mismatch or is unable to check the installed [`libctru`](https://github.com/devkitPro/libctru) version.
## Generating bindings
Bindings of new versions of [`libctru`](https://github.com/devkitPro/libctru) can be built using the integrated [`bindgen.sh`](./bindgen.sh) script.
## License ## License

132
ctru-sys/build.rs

@ -1,5 +1,6 @@
use bindgen::callbacks::ParseCallbacks; use bindgen::callbacks::ParseCallbacks;
use bindgen::{Builder, RustTarget}; use bindgen::{Builder, RustTarget};
use itertools::Itertools;
use std::env; use std::env;
use std::error::Error; use std::error::Error;
@ -18,33 +19,39 @@ impl ParseCallbacks for CustomCallbacks {
fn main() { fn main() {
let devkitpro = env::var("DEVKITPRO").unwrap(); let devkitpro = env::var("DEVKITPRO").unwrap();
let devkitarm = env::var("DEVKITARM").unwrap(); let devkitarm = env::var("DEVKITARM").unwrap();
let profile = env::var("PROFILE").unwrap();
let out_dir = PathBuf::from(env::var("OUT_DIR").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={devkitpro}/libctru/lib"); println!("cargo:rustc-link-search=native={devkitpro}/libctru/lib");
println!(
"cargo:rustc-link-lib=static={}", // https://github.com/rust3ds/cargo-3ds/issues/14#issuecomment-1783991872
match profile.as_str() { // To link properly, this must be the same as the library linked by cargo-3ds when building
"debug" => "ctrud", // the standard library, so if `-lctru[d]` is found in RUSTFLAGS we always defer to that
_ => "ctru", // https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
} let cargo_rustflags = env::var("CARGO_ENCODED_RUSTFLAGS").unwrap();
); let rustflags_libctru = cargo_rustflags
.split('\x1F')
match check_libctru_version() { // Technically this could also be `-l ctru`, or `-lstatic=ctru` etc.
Ok((maj, min, patch)) => { // but for now we'll just rely on cargo-3ds implementation to pass it like this
eprintln!("using libctru version {maj}.{min}.{patch}"); .find(|flag| flag.starts_with("-lctru"))
.and_then(|flag| flag.strip_prefix("-l"));
// These are accessible by the crate during build with `env!()`.
// We might consider exporting some public constants or something. let linked_libctru = rustflags_libctru.unwrap_or_else(|| {
println!("cargo:rustc-env=LIBCTRU_VERSION={maj}.{min}.{patch}"); let debuginfo = env::var("DEBUG").unwrap();
println!("cargo:rustc-env=LIBCTRU_MAJOR={maj}"); match debuginfo.as_str() {
println!("cargo:rustc-env=LIBCTRU_MINOR={min}"); // Normally this should just be "true" or "false", but just in case,
println!("cargo:rustc-env=LIBCTRU_PATCH={patch}"); // we don't support all the different options documented in
// https://doc.rust-lang.org/cargo/reference/profiles.html#debug
// so just default to linking with debuginfo if it wasn't disabled
"0" | "false" | "none" => "ctru",
_ => "ctrud",
} }
Err(err) => println!("cargo:warning=failed to check libctru version: {err}"), });
}
println!("cargo:rustc-link-lib=static={linked_libctru}");
detect_and_track_libctru();
let gcc_version = get_gcc_version(PathBuf::from(&devkitarm).join("bin/arm-none-eabi-gcc")); let gcc_version = get_gcc_version(PathBuf::from(&devkitarm).join("bin/arm-none-eabi-gcc"));
@ -135,22 +142,40 @@ fn get_gcc_version(path_to_gcc: PathBuf) -> String {
.to_string() .to_string()
} }
fn parse_libctru_version(version: &str) -> Result<(String, String, String), &str> { fn detect_and_track_libctru() {
let versions: Vec<_> = version let pacman = match which::which("dkp-pacman")
.split(|c| c == '.' || c == '-') .or_else(|err1| which::which("pacman").map_err(|err2| format!("{err1}; {err2}")))
.map(String::from) {
.collect(); Ok(pacman) => pacman,
Err(err) => {
println!("cargo:warning=unable to find `pacman` or `dkp-pacman`: {err}");
return;
}
};
match get_libctru_version(&pacman) {
Ok((maj, min, patch, rel)) => {
let version = format!("{maj}.{min}.{patch}-{rel}");
eprintln!("using libctru version {version}");
// These are exported as build script output variables, accessible
// via `env::var("DEP_CTRU_<key>")` in other crates' build scripts.
// https://doc.rust-lang.org/cargo/reference/build-scripts.html#the-links-manifest-key
println!("cargo:VERSION={version}");
println!("cargo:MAJOR_VERSION={maj}");
println!("cargo:MINOR_VERSION={min}");
println!("cargo:PATCH_VERSION={patch}");
println!("cargo:RELEASE={rel}");
}
Err(err) => println!("cargo:warning=unknown libctru version: {err}"),
}
match &versions[..] { if let Err(err) = track_libctru_files(&pacman) {
[major, minor, patch, _build] => Ok((major.clone(), minor.clone(), patch.clone())), println!("cargo:warning=unable to track `libctru` files for changes: {err}");
_ => Err("unexpected number of version segments"),
} }
} }
fn check_libctru_version() -> Result<(String, String, String), Box<dyn Error>> { fn get_libctru_version(pacman: &Path) -> Result<(String, String, String, String), Box<dyn Error>> {
let pacman = which::which("dkp-pacman").or_else(|_| which::which("pacman"))?; let Output { stdout, .. } = Command::new(pacman)
let Output { stdout, .. } = Command::new(&pacman)
.args(["--query", "libctru"]) .args(["--query", "libctru"])
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.output()?; .output()?;
@ -159,35 +184,44 @@ fn check_libctru_version() -> Result<(String, String, String), Box<dyn Error>> {
let (_pkg, lib_version) = output_str let (_pkg, lib_version) = output_str
.split_once(char::is_whitespace) .split_once(char::is_whitespace)
.ok_or("unexpected pacman output format")?; .ok_or_else(|| format!("unexpected pacman output format: {output_str:?}"))?;
let lib_version = lib_version.trim(); let lib_version = lib_version.trim();
let cargo_pkg_version = env::var("CARGO_PKG_VERSION").unwrap(); parse_libctru_version(lib_version).map_err(Into::into)
let (_, crate_built_version) = cargo_pkg_version }
.split_once('+')
.expect("crate version should have '+' delimeter");
if lib_version != crate_built_version { fn parse_libctru_version(version: &str) -> Result<(String, String, String, String), String> {
return Err(format!( version
"libctru version is {lib_version} but this crate was built for {crate_built_version}" .split(|c| c == '.' || c == '-')
) .map(String::from)
.into()); .collect_tuple()
} .ok_or_else(|| format!("unexpected number of version segments: {version:?}"))
}
let Output { stdout, .. } = Command::new(pacman) fn track_libctru_files(pacman: &Path) -> Result<(), String> {
let stdout = match Command::new(pacman)
.args(["--query", "--list", "libctru"]) .args(["--query", "--list", "libctru"])
.stderr(Stdio::inherit()) .stderr(Stdio::inherit())
.output()?; .output()
{
Ok(Output { stdout, status, .. }) if status.success() => stdout,
Ok(Output { status, .. }) => {
return Err(format!("pacman query failed with status {status}"));
}
Err(err) => {
return Err(format!("pacman query failed: {err}"));
}
};
for line in String::from_utf8_lossy(&stdout).split('\n') { for line in String::from_utf8_lossy(&stdout).trim().split('\n') {
let Some((_pkg, file)) = line.split_once(char::is_whitespace) else { let Some((_pkg, file)) = line.split_once(char::is_whitespace) else {
println!("cargo:warning=unexpected line from pacman query: {line:?}");
continue; continue;
}; };
println!("cargo:rerun-if-changed={file}"); println!("cargo:rerun-if-changed={file}");
} }
let (lib_major, lib_minor, lib_patch) = parse_libctru_version(lib_version)?; Ok(())
Ok((lib_major, lib_minor, lib_patch))
} }

17
ctru-sys/src/lib.rs

@ -3,6 +3,15 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![allow(non_snake_case)] #![allow(non_snake_case)]
#![allow(clippy::all)] #![allow(clippy::all)]
#![cfg_attr(test, feature(custom_test_frameworks))]
#![cfg_attr(test, test_runner(test_runner::run_gdb))]
#![doc(
html_favicon_url = "https://user-images.githubusercontent.com/11131775/225929072-2fa1741c-93ae-4b47-9bdf-af70f3d59910.png"
)]
#![doc(
html_logo_url = "https://user-images.githubusercontent.com/11131775/225929072-2fa1741c-93ae-4b47-9bdf-af70f3d59910.png"
)]
#![doc(html_root_url = "https://rust3ds.github.io/ctru-rs/crates")]
pub mod result; pub mod result;
pub use result::*; pub use result::*;
@ -15,10 +24,6 @@ pub unsafe fn errno() -> s32 {
*__errno() *__errno()
} }
// TODO: not sure if there's a better way to do this, but I have gotten myself // Prevent linking errors from the standard `test` library when running `cargo 3ds test --lib`.
// with this a couple times so having the hint seems nice to have.
#[cfg(test)] #[cfg(test)]
compile_error!(concat!( extern crate shim_3ds;
"ctru-sys doesn't have tests and its lib test will fail to build at link time. ",
"Try specifying `--package ctru-rs` to build those tests.",
));

Loading…
Cancel
Save