You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
84 lines
3.1 KiB
84 lines
3.1 KiB
use std::env; |
|
use std::error::Error; |
|
use std::process::{Command, Output, Stdio}; |
|
|
|
fn main() { |
|
let dkp_path = env::var("DEVKITPRO").unwrap(); |
|
let profile = env::var("PROFILE").unwrap(); |
|
|
|
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-lib=static={}", |
|
match profile.as_str() { |
|
"debug" => "ctrud", |
|
_ => "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)) |
|
}
|
|
|