我正在尝试使用 Rust 中的 IOKit FFI 绑定来获取 macOS 上的硬件信息。我在一台运行 macOS 13.1、apple clang 14.0.0、xcode 14.2 和命令行工具 14.2 的苹果硅机器上。我已经多次重新安装了 xcode 和命令行工具。尝试通过货物构建时,我收到以下错误:
error: failed to run custom build command for `iokit_binding_test v0.1.0 (/Users/curlin/Desktop/master/school/school22-23/spring/cosc340/Watchtower/local/iokit_binding_test)`
Caused by:
process didn't exit successfully: `/Users/curlin/Desktop/master/school/school22-23/spring/cosc340/Watchtower/local/iokit_binding_test/target/debug/build/iokit_binding_test-c6ae1186e1f0394a/build-script-build` (exit status: 101)
--- stderr
wrapper.h:7:10: fatal error: 'IOKit/IOKitLib.h' file not found
wrapper.h:7:10: note: did not find header 'IOKitLib.h' in framework 'IOKit' (loaded from '/System/Library/Frameworks')
wrapper.h:7:10: fatal error: 'IOKit/IOKitLib.h' file not found, err: true
thread 'main' panicked at 'Unable to generate bindings: ()', build.rs:17:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
我的
cargo.toml
:
[package]
name = "iokit_binding_test"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libc = "0.2" # provides all definitions necessesary to easily interoperate with C code (or 'C-like' code) in rust
# includes type definitions (e.g. 'c_int'), constants, and function headers (e.g. 'malloc')
#[target.'cfg(macos)'.build-dependencies] -- target-specific build dependency header
[build-dependencies] # other cargo-based crate dependencies (can only be used in build.rs, which prepares external dependencies before build)
bindgen = "0.59
我的
wrapper.h
:
#include <IOKit/IOKitLib.h
我的
/System/Library/Frameworks/IOKit.framework/Versions/A
目录中没有标头。尝试通过 xcode 找到这些标头表明它们位于 xcode 的 /Applications/
目录中。
我试图在这里和Apple的开发板上找到解决方案,但是我发现的唯一信息包括特定于IOS开发的类似问题,建议我手动为每个标头创建一个符号链接;并建议我运行位于
/Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg
的 SDK pkg,但我的计算机上的该路径中没有包目录。
<IOKit/IOKitLib.h>
是已弃用的包含路径,还是我的配置有问题?
如果这个问题微不足道或有记录,我深表歉意,我已经彻底搜索了现有的解决方案,没有尽头。我对 Rust 或 macOS 开发几乎没有经验。
我通过在 build.rs 文件中显式指定 Frameworks 目录的位置解决了此问题,如下所示:
use bindgen::Builder;
use std::{env, path::PathBuf};
fn main()·
{
let bindings = Builder::default()·
.header("wrapper.h") // input header to generate bindings for
.clang_arg("-F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks")
.generate() // finish the build and generate the bindings
.expect("Unable to generate bindings"); // unwrap the result and panic on failure
// write the bindings to the $OUT_DIR/bindings.rs file
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
macOS 框架文件结构的更改似乎已弃用
'/系统/库/框架'
位置,而不是将框架标头存储在
'Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks'。