Browse Source

Add all `libctru` files to rerun-if-changed

Also simplify version checking logic a bit. It's just a warning, so we
can check for exact version just to be safe and skip the major/minor
comparisons for semver.

Also update the README a bit to explain the versioning scheme.
pull/101/head
Ian Chamberlain 2 years ago
parent
commit
322d99e4ae
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 21
      README.md
  2. 34
      ctru-sys/build.rs

21
README.md

@ -5,8 +5,24 @@ A Rust wrapper library for smealum's [ctrulib](https://github.com/smealum/ctruli
## Structure ## Structure
This repository is organized as follows: This repository is organized as follows:
* `ctru-rs`: Safe, idiomatic wrapper around `ctru-sys`.
* `ctru-sys`: Low-level, unsafe bindings to ctrulib * `ctru-rs`: Safe, idiomatic wrapper around `ctru-sys`
* `ctru-sys`: Low-level, unsafe bindings to ctrulib.
This crate's version changes according to the version of `libctru`
used to generate the bindings, with the following convention:
* `libctru` version `X.Y.Z-W`
* `ctru-sys` version `XY.Z.P+X.Y.Z-W`
where `P` is usually 0 but may be incremented for fixes in e.g.
binding generation, `libc` dependency bump, etc.
It may be possible to build this crate against a different version of `libctru`,
but you may encounter linker errors or ABI issues. A build-time Cargo warning
(displayed when built with `-vv`) will be issued if the build script detects
a mismatch or is unable to check the installed `libctru` version.
## License ## License
@ -37,3 +53,4 @@ applies to every file in the tree, unless otherwise noted.
Rust is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses. Rust is primarily distributed under the terms of both the MIT license and the Apache License (Version 2.0), with portions covered by various BSD-like licenses.
See [LICENSE-APACHE](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE), [LICENSE-MIT](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT), and [COPYRIGHT](https://github.com/rust-lang/rust/blob/master/COPYRIGHT) for details. See [LICENSE-APACHE](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE), [LICENSE-MIT](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT), and [COPYRIGHT](https://github.com/rust-lang/rust/blob/master/COPYRIGHT) for details.

34
ctru-sys/build.rs

@ -27,9 +27,6 @@ fn main() {
println!("cargo:rustc-env=LIBCTRU_MAJOR={maj}"); println!("cargo:rustc-env=LIBCTRU_MAJOR={maj}");
println!("cargo:rustc-env=LIBCTRU_MINOR={min}"); println!("cargo:rustc-env=LIBCTRU_MINOR={min}");
println!("cargo:rustc-env=LIBCTRU_PATCH={patch}"); println!("cargo:rustc-env=LIBCTRU_PATCH={patch}");
// It would be nice if we could rerun-if-changed on libctru itself,
// maybe we can write a file to OUT_DIR and check that file?
} }
Err(err) => println!("cargo:warning=failed to check libctru version: {err}"), Err(err) => println!("cargo:warning=failed to check libctru version: {err}"),
} }
@ -50,7 +47,7 @@ fn parse_version(version: &str) -> Result<(String, String, String), &str> {
fn check_libctru_version() -> Result<(String, String, String), Box<dyn Error>> { fn check_libctru_version() -> Result<(String, String, String), Box<dyn Error>> {
let pacman = which::which("dkp-pacman").or_else(|_| which::which("pacman"))?; 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()?;
@ -59,26 +56,33 @@ 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 output format")?; .ok_or("unexpected pacman output format")?;
let lib_version = lib_version.trim();
let cargo_pkg_version = env::var("CARGO_PKG_VERSION").unwrap(); let cargo_pkg_version = env::var("CARGO_PKG_VERSION").unwrap();
let (_, crate_built_version) = cargo_pkg_version let (_, crate_built_version) = cargo_pkg_version
.split_once('+') .split_once('+')
.expect("crate version should have '+' delimeter"); .expect("crate version should have '+' delimeter");
let (lib_major, lib_minor, lib_patch) = parse_version(lib_version)?; if lib_version != crate_built_version {
let (crate_supported_major, crate_supported_minor, _crate_supported_patch) =
parse_version(crate_built_version)?;
// TODO: does == comparison make sense, or should we use >= or something?
if crate_supported_major != lib_major || crate_supported_minor != lib_minor {
// TODO: should this be a panic (i.e. induce build failure)? Maybe only for major version?
return Err(format!( return Err(format!(
"libctru version is {lib_major}.{lib_minor}.{lib_patch}, \ "libctru version is {lib_version} but this crate was built for {crate_built_version}"
but this crate only supports {crate_supported_major}.{crate_supported_minor}.x"
))?; ))?;
} }
let Output { stdout, .. } = Command::new(pacman)
.args(["--query", "--list", "libctru"])
.stderr(Stdio::inherit())
.output()?;
for line in String::from_utf8_lossy(&stdout).split('\n') {
let Some((_pkg, file)) = line.split_once(char::is_whitespace)
else { continue };
println!("cargo:rerun-if-changed={file}");
}
let (lib_major, lib_minor, lib_patch) = parse_version(lib_version)?;
Ok((lib_major, lib_minor, lib_patch)) Ok((lib_major, lib_minor, lib_patch))
} }

Loading…
Cancel
Save