Browse Source

Initial pass of version checking in ctru-sys

pull/101/head
Ian Chamberlain 2 years ago
parent
commit
eb7932a501
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 7
      ctru-sys/Cargo.toml
  2. 67
      ctru-sys/build.rs

7
ctru-sys/Cargo.toml

@ -1,10 +1,13 @@
[package] [package]
name = "ctru-sys" name = "ctru-sys"
version = "0.4.1" version = "21.2.0+2.1.2-1"
authors = ["Ronald Kinard <furyhunter600@gmail.com>"] authors = ["Ronald Kinard <furyhunter600@gmail.com>"]
license = "https://en.wikipedia.org/wiki/Zlib_License" license = "Zlib"
links = "ctru" links = "ctru"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
libc = { version = "0.2.121", default-features = false } libc = { version = "0.2.121", default-features = false }
[build-dependencies]
which = "4.4.0"

67
ctru-sys/build.rs

@ -1,4 +1,6 @@
use std::env; use std::env;
use std::error::Error;
use std::process::{Command, Output, Stdio};
fn main() { fn main() {
let dkp_path = env::var("DEVKITPRO").unwrap(); let dkp_path = env::var("DEVKITPRO").unwrap();
@ -14,4 +16,69 @@ fn main() {
_ => "ctru", _ => "ctru",
} }
); );
match check_libctru_version() {
Ok((maj, min, patch)) => {
eprintln!("using libctru version {maj}.{min}.{patch}");
// These are accessible by the crate during build with `env!()`.
// We might consider exporting some public constants or something.
println!("cargo:rustc-env=LIBCTRU_VERSION={maj}.{min}.{patch}");
println!("cargo:rustc-env=LIBCTRU_MAJOR={maj}");
println!("cargo:rustc-env=LIBCTRU_MINOR={min}");
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}"),
}
}
fn parse_version(version: &str) -> Result<(String, String, String), &str> {
let versions: Vec<_> = version
.split(|c| c == '.' || c == '-')
.map(String::from)
.collect();
match &versions[..] {
[major, minor, patch, _build] => Ok((major.clone(), minor.clone(), patch.clone())),
_ => Err("unexpected number of version segments"),
}
}
fn check_libctru_version() -> Result<(String, String, String), Box<dyn Error>> {
let pacman = which::which("dkp-pacman").or_else(|_| which::which("pacman"))?;
let Output { stdout, .. } = Command::new(pacman)
.args(["--query", "libctru"])
.stderr(Stdio::inherit())
.output()?;
let output_str = String::from_utf8_lossy(&stdout);
let (_pkg, lib_version) = output_str
.split_once(char::is_whitespace)
.ok_or("unexpected output format")?;
let cargo_pkg_version = env::var("CARGO_PKG_VERSION").unwrap();
let (_, crate_built_version) = cargo_pkg_version
.split_once('+')
.expect("crate version should have '+' delimeter");
let (lib_major, lib_minor, lib_patch) = parse_version(lib_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!(
"libctru version is {lib_major}.{lib_minor}.{lib_patch}, \
but this crate only supports {crate_supported_major}.{crate_supported_minor}.x"
))?;
}
Ok((lib_major, lib_minor, lib_patch))
} }

Loading…
Cancel
Save