From 4f946e1bf23b988b1f7466321a056a8118fd6019 Mon Sep 17 00:00:00 2001 From: slowsage <84777606+slowsage@users.noreply.github.com> Date: Thu, 25 Jun 2026 06:37:49 -0400 Subject: [PATCH] refactor(sys): adopt system-deps, preserve source build via add_build_internal - replace pkg-config + cc build-deps with system-deps = "7" - declare libevdev >= 1.0 in package.metadata.system-deps; v1_10 override enforces >= 1.10 when that feature is active - source build fallback preserved: defaults to auto (probe first, build from source on failure); override with SYSTEM_DEPS_LIBEVDEV_BUILD_INTERNAL=always|never - reduce build.rs from 147 lines to 62 BREAKING: feature renamed from `libevdev-1-10` to `v1_10` Users must update: features = ["libevdev-1-10"] -> features = ["v1_10"] --- Cargo.toml | 2 +- README.md | 2 +- evdev-sys/Cargo.toml | 12 +++- evdev-sys/build.rs | 156 ++++++++++--------------------------------- evdev-sys/src/lib.rs | 2 +- src/device.rs | 4 +- tests/all.rs | 12 ++-- 7 files changed, 57 insertions(+), 133 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1551e532..8e95f2ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ a library interface to the callers, thus avoiding erroneous ioctls, etc. [features] default = [] # Use features from libevdev version 1.10 and greater (libevdev_property_disable) -libevdev-1-10 = ["evdev-sys/libevdev-1-10"] +v1_10 = ["evdev-sys/v1_10"] [dependencies] serde = { version = "1.0", default-features = false, features=["derive"], optional = true } diff --git a/README.md b/README.md index b8759def..838cd81a 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ to enable serialization support, enable the feature "serde" evdev-rs = { version = "0.6.3", features = ["serde"] } ``` -With a newer libevdev version (>= 1.10) enable the feature `libevdev-1-10` to +With a newer libevdev version (>= 1.10) enable the feature `v1_10` to allow disabling a property. It also extends the `Enable` trait to `InputProp`, enabling the use of `enable()`, `disable()` and `has()` for `InputProp` as well. diff --git a/evdev-sys/Cargo.toml b/evdev-sys/Cargo.toml index 3031dc33..808f9b1a 100644 --- a/evdev-sys/Cargo.toml +++ b/evdev-sys/Cargo.toml @@ -15,11 +15,17 @@ High level Rust bindings are available in the `evdev` crate """ [features] -libevdev-1-10 = [] +v1_10 = [] [dependencies] libc = "0.2.67" [build-dependencies] -pkg-config = "0.3.17" -cc = "1.0.50" +system-deps = "7" + +[package.metadata.system-deps.libevdev] +name = "libevdev" +version = "1" + +[package.metadata.system-deps.libevdev.v1_10] +version = "1.10" diff --git a/evdev-sys/build.rs b/evdev-sys/build.rs index c5ad282b..4f551573 100644 --- a/evdev-sys/build.rs +++ b/evdev-sys/build.rs @@ -1,146 +1,64 @@ -use std::env; -use std::ffi::OsString; -use std::fs; -use std::path::{Path, PathBuf}; -use std::process::Command; +use std::{env, fs, path::PathBuf, process::Command}; -#[cfg(feature = "libevdev-1-10")] -// ver_str is string of the form "major.minor.patch" -fn parse_version(ver_str: &str) -> Option<(u32, u32, u32)> { - let mut major_minor_patch = ver_str - .split(".") - .map(|str| str.parse::().unwrap()); - let major = major_minor_patch.next()?; - let minor = major_minor_patch.next()?; - let patch = major_minor_patch.next()?; - Some((major, minor, patch)) -} - -fn main() -> Result<(), Box> { - if env::var_os("TARGET") == env::var_os("HOST") { - let mut config = pkg_config::Config::new(); - config.print_system_libs(false); - - match config.probe("libevdev") { - Ok(lib) => { - // panic if feature 1.10 is enabled and the installed library - // is older than 1.10 - #[cfg(feature = "libevdev-1-10")] - { - let (major, minor, patch) = parse_version(&lib.version) - .expect("Could not parse version information"); - assert_eq!(major, 1, "evdev-rs works only with libevdev 1"); - assert!(minor >= 10, - "Feature libevdev-1-10 was enabled, when compiling \ - for a system with libevdev version {}.{}.{}", - major, - minor, - patch, - ); - } - for path in &lib.include_paths { - println!("cargo:include={}", path.display()); - } - return Ok(()); - } - Err(e) => eprintln!( - "Couldn't find libevdev from pkgconfig ({:?}), \ - compiling it from source...", - e - ), - }; +fn main() { + if env::var("SYSTEM_DEPS_LIBEVDEV_BUILD_INTERNAL").is_err() { + unsafe { env::set_var("SYSTEM_DEPS_LIBEVDEV_BUILD_INTERNAL", "auto") }; } + system_deps::Config::new() + .add_build_internal("libevdev", build_from_source) + .probe() + .unwrap(); +} - if !Path::new("libevdev/.git").exists() { - let mut download = Command::new("git"); - download.args(&["submodule", "update", "--init", "--depth", "1"]); - run_ignore_error(&mut download)?; +fn build_from_source( + lib: &str, + version: &str, +) -> Result { + if !std::path::Path::new("libevdev/.git").exists() { + let _ = Command::new("git") + .args(["submodule", "update", "--init", "--depth", "1"]) + .status(); } let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap()); - let src = env::current_dir()?; - let mut cp = Command::new("cp"); - cp.arg("-r") - .arg(&src.join("libevdev/")) - .arg(&dst) - .current_dir(&src); - run(&mut cp)?; - - println!("cargo:rustc-link-search={}/lib", dst.display()); - println!("cargo:root={}", dst.display()); - println!("cargo:include={}/include", dst.display()); - println!("cargo:rerun-if-changed=libevdev"); + let build_dir = dst.join("build"); + let src = env::current_dir().unwrap(); + let jobs = env::var("NUM_JOBS").unwrap_or_else(|_| "1".into()); - println!("cargo:rustc-link-lib=static=evdev"); - let cfg = cc::Build::new(); - let compiler = cfg.get_compiler(); + let mut cp = Command::new("cp"); + run(cp.arg("-r").arg(src.join("libevdev/")).arg(&dst))?; - if !&dst.join("build").exists() { - fs::create_dir(&dst.join("build"))?; + if !build_dir.exists() { + fs::create_dir(&build_dir) + .map_err(|e| system_deps::BuildInternalClosureError::failed(&e.to_string()))?; } let mut autogen = Command::new("sh"); - let mut cflags = OsString::new(); - for arg in compiler.args() { - cflags.push(arg); - cflags.push(" "); - } autogen - .env("CC", compiler.path()) - .env("CFLAGS", cflags) - .current_dir(&dst.join("build")) - .arg( - dst.join("libevdev/autogen.sh") - .to_str() - .unwrap() - .replace("C:\\", "/c/") - .replace("\\", "/"), - ); + .current_dir(&build_dir) + .arg(dst.join("libevdev/autogen.sh").to_str().unwrap()) + .arg(format!("--prefix={}", dst.display())); if let Ok(h) = env::var("HOST") { autogen.arg(format!("--host={}", h)); } if let Ok(t) = env::var("TARGET") { autogen.arg(format!("--target={}", t)); } - autogen.arg(format!("--prefix={}", sanitize_sh(&dst))); run(&mut autogen)?; let mut make = Command::new("make"); - make.arg(&format!("-j{}", env::var("NUM_JOBS").unwrap())) - .current_dir(&dst.join("build")); - run(&mut make)?; - + run(make.arg(format!("-j{jobs}")).current_dir(&build_dir))?; let mut install = Command::new("make"); - install.arg("install").current_dir(&dst.join("build")); - run(&mut install)?; - Ok(()) -} + run(install.arg("install").current_dir(&build_dir))?; -fn run(cmd: &mut Command) -> std::io::Result<()> { - println!("running: {:?}", cmd); - assert!(cmd.status()?.success()); - Ok(()) -} + println!("cargo:rerun-if-changed=libevdev"); -fn run_ignore_error(cmd: &mut Command) -> std::io::Result<()> { - println!("running: {:?}", cmd); - let _ = cmd.status(); - Ok(()) + system_deps::Library::from_internal_pkg_config(dst.join("lib/pkgconfig"), lib, version) } -fn sanitize_sh(path: &Path) -> String { - let path = path.to_str().unwrap().replace("\\", "/"); - return change_drive(&path).unwrap_or(path); - - fn change_drive(s: &str) -> Option { - let mut ch = s.chars(); - let drive = ch.next().unwrap_or('C'); - if ch.next() != Some(':') { - return None; - } - if ch.next() != Some('/') { - return None; - } - Some(format!("/{}/{}", drive, &s[drive.len_utf8() + 2..])) - } +fn run(cmd: &mut Command) -> Result<(), system_deps::BuildInternalClosureError> { + cmd.status() + .ok() + .and_then(|s| s.success().then_some(())) + .ok_or_else(|| system_deps::BuildInternalClosureError::failed(&format!("{cmd:?} failed"))) } diff --git a/evdev-sys/src/lib.rs b/evdev-sys/src/lib.rs index 2ede074f..4c738209 100644 --- a/evdev-sys/src/lib.rs +++ b/evdev-sys/src/lib.rs @@ -102,7 +102,7 @@ extern "C" { pub fn libevdev_get_driver_version(ctx: *const libevdev) -> c_int; pub fn libevdev_has_property(ctx: *const libevdev, prop: c_uint) -> c_int; pub fn libevdev_enable_property(ctx: *mut libevdev, prop: c_uint) -> c_int; - #[cfg(feature = "libevdev-1-10")] + #[cfg(feature = "v1_10")] pub fn libevdev_disable_property (ctx: *mut libevdev, prop: c_uint) -> c_int; pub fn libevdev_has_event_type(ctx: *const libevdev, type_: c_uint) -> c_int; pub fn libevdev_has_event_code( diff --git a/src/device.rs b/src/device.rs index 22ba3e55..e8f61122 100644 --- a/src/device.rs +++ b/src/device.rs @@ -34,7 +34,7 @@ pub trait Enable { fn has(&self, device: &D) -> bool; } -#[cfg(feature = "libevdev-1-10")] +#[cfg(feature = "v1_10")] impl Enable for InputProp { fn enable(&self, device: &D) -> io::Result<()> { device.enable_property(self) @@ -248,7 +248,7 @@ pub trait DeviceWrapper: Sized { } } - #[cfg(feature = "libevdev-1-10")] + #[cfg(feature = "v1_10")] fn disable_property(&self, prop: &InputProp) -> io::Result<()> { let result = unsafe { raw::libevdev_disable_property(self.raw(), (*prop) as c_uint) }; diff --git a/tests/all.rs b/tests/all.rs index 51ad3c06..7f9e44e5 100644 --- a/tests/all.rs +++ b/tests/all.rs @@ -127,28 +127,28 @@ fn device_has_property() { #[test] fn device_enable_disable() { - #[cfg(feature = "libevdev-1-10")] + #[cfg(feature = "v1_10")] let prop = InputProp::INPUT_PROP_POINTER; let ev_type = EventType::EV_KEY; let code = EventCode::EV_KEY(EV_KEY::KEY_LEFTSHIFT); let d = UninitDevice::new().unwrap(); - #[cfg(feature = "libevdev-1-10")] + #[cfg(feature = "v1_10")] assert!(!d.has(prop)); assert!(!d.has(ev_type)); assert!(!d.has(code)); - #[cfg(feature = "libevdev-1-10")] + #[cfg(feature = "v1_10")] d.enable(prop).unwrap(); d.enable(ev_type).unwrap(); d.enable(code).unwrap(); - #[cfg(feature = "libevdev-1-10")] + #[cfg(feature = "v1_10")] assert!(d.has(prop)); assert!(d.has(ev_type)); assert!(d.has(code)); - #[cfg(feature = "libevdev-1-10")] + #[cfg(feature = "v1_10")] d.disable(prop).unwrap(); d.disable(ev_type).unwrap(); d.disable(code).unwrap(); - #[cfg(feature = "libevdev-1-10")] + #[cfg(feature = "v1_10")] assert!(!d.has(prop)); assert!(!d.has(ev_type)); assert!(!d.has(code));