diff --git a/build.rs b/build.rs index 907f80e..1a45be8 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,20 @@ use std::process::Command; use std::env; +use std::fs; +use std::path::Path; fn main() { + // 检测当前是否在树莓派或其他支持GPIO的Linux平台上 + let supports_gpio = detect_gpio_support(); + + // 自动启用GPIO功能(如果支持) + if supports_gpio { + println!("cargo:rustc-cfg=feature=\"gpio\""); + println!("cargo:warning=GPIO support detected, enabling gpio feature"); + } else { + println!("cargo:warning=No GPIO support detected, gpio feature NOT enabled"); + } + // 通过包含的 OpenCV 库检测版本 let opencv_version = detect_opencv_version(); @@ -21,6 +34,83 @@ fn main() { } } +fn detect_gpio_support() -> bool { + // 方法1: 检查是否是Linux系统 + let is_linux = env::consts::OS == "linux"; + if !is_linux { + return false; + } + + // 方法2: 检查/proc/cpuinfo是否包含Raspberry Pi的特征 + if let Ok(cpuinfo) = fs::read_to_string("/proc/cpuinfo") { + if cpuinfo.contains("Raspberry Pi") || + cpuinfo.contains("BCM2708") || + cpuinfo.contains("BCM2709") || + cpuinfo.contains("BCM2710") || + cpuinfo.contains("BCM2711") || + cpuinfo.contains("BCM2835") || + cpuinfo.contains("BCM2836") || + cpuinfo.contains("BCM2837") || + cpuinfo.contains("BCM2838") { + return true; + } + } + + // 方法3: 检查是否存在/dev/gpiochip*设备 + if Path::new("/dev/gpiochip0").exists() || + fs::read_dir("/dev").ok() + .map(|entries| entries.filter_map(Result::ok) + .any(|entry| entry.file_name() + .to_string_lossy() + .starts_with("gpiochip"))) + .unwrap_or(false) { + return true; + } + + // 方法4: 检查是否存在/sys/class/gpio目录 + if Path::new("/sys/class/gpio").exists() { + return true; + } + + // 方法5: 检查是否安装了librpgpio库(树莓派特有) + let lib_check = Command::new("ldconfig") + .args(["-p"]) + .output() + .ok() + .and_then(|output| { + if output.status.success() { + let libraries = String::from_utf8_lossy(&output.stdout); + if libraries.contains("librpgpio") { + Some(true) + } else { + None + } + } else { + None + } + }); + + if lib_check.is_some() { + return true; + } + + // 回退到检查核心文件路径查找 + if let Ok(model) = fs::read_to_string("/sys/firmware/devicetree/base/model") { + if model.contains("Raspberry Pi") { + return true; + } + } + + // 如果还没确定,检查是否在CARGO_FEATURE_GPIO环境变量中强制启用 + // 这允许用户手动启用GPIO功能(覆盖自动检测) + if env::var("CARGO_FEATURE_GPIO").is_ok() { + return true; + } + + // 否则默认为false + false +} + fn detect_opencv_version() -> String { // 方法 1: 尝试使用 pkg-config if let Some(version) = try_pkg_config() { diff --git a/examples/camera_demo.rs b/examples/camera_demo.rs index 480d169..7f5b8c1 100644 --- a/examples/camera_demo.rs +++ b/examples/camera_demo.rs @@ -119,9 +119,18 @@ async fn main() -> Result<()> { /// 创建用于演示的配置 fn create_demo_config() -> Config { + // 根据操作系统自动选择合适的设备路径 + let device = match std::env::consts::OS { + "linux" => "/dev/video0".to_string(), + "macos" => "0".to_string(), + // Windows和其他操作系统通常使用索引 + _ => "0".to_string(), + }; + + info!("自动选择相机设备: {}", device); + let camera_settings = CameraSettings { - // 在Linux上通常是"/dev/video0",在macOS上通常是"0" - device: "0".to_string(), + device, // 使用根据操作系统确定的设备路径 resolution: Resolution::HD720p, fps: 30, exposure: ExposureMode::Auto, diff --git a/src/lib.rs b/src/lib.rs index 13d9f40..c81427f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,10 @@ -// Platform detection -#[cfg(target_os = "linux")] +// 这里的常量将在编译时由build.rs设置 +// 通过rustc-cfg设置的cfg特性可以在代码中使用 +// 将PLATFORM_SUPPORTS_GPIO基于实际检测到的GPIO支持来设置 +#[cfg(feature = "gpio")] pub const PLATFORM_SUPPORTS_GPIO: bool = true; -#[cfg(not(target_os = "linux"))] +#[cfg(not(feature = "gpio"))] pub const PLATFORM_SUPPORTS_GPIO: bool = false; // 将所有模块重新导出,使它们对例子可见