Rust使用exif crate时PKG_CONFIG缺失libexif的问题求助
问题:使用exif crate v0.0.1解析图片元数据时编译失败,libexif系统库未找到
我正在编写Rust函数解析png、jpg、jpeg、heic等格式的图片元数据,使用exif crate v0.0.1时出现编译错误,核心是exif-sys构建失败,提示系统库libexif未找到,缺少libexif.pc文件且PKG_CONFIG_PATH配置异常。
已做的操作:
- 通过msys64安装了PKG-CONFIG
- 将包含
pkg-config.exe的C:\msys64\mingw64\bin添加到系统PATH - 将包含
.pc文件的C:\msys64\usr\share\pkgconfig添加到PKG_CONFIG_PATH
但问题仍未解决,以下是相关文件和错误日志:
错误日志
Running `cargo build --bin=rust_file_scrub --package=rust_file_scrub --message-format=json`... Blocking waiting for file lock on package cache Updating crates.io index Blocking waiting for file lock on package cache Blocking waiting for file lock on package cache Compiling exif-sys v0.1.0 Compiling tiff v0.6.1 error: failed to run custom build command for `exif-sys v0.1.0` Caused by: process didn't exit successfully: `e:\file_scrub\rust_file_scrub\target\debug\build\exif-sys-e9172f41e2a5fece\build-script-build` (exit code: 101) --- stdout cargo:rerun-if-env-changed=LIBEXIF_NO_PKG_CONFIG cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-pc-windows-msvc cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_pc_windows_msvc cargo:rerun-if-env-changed=HOST_PKG_CONFIG cargo:rerun-if-env-changed=PKG_CONFIG cargo:rerun-if-env-changed=LIBEXIF_STATIC cargo:rerun-if-env-changed=LIBEXIF_DYNAMIC cargo:rerun-if-env-changed=PKG_CONFIG_ALL_STATIC cargo:rerun-if-env-changed=PKG_CONFIG_ALL_DYNAMIC cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64-pc-windows-msvc cargo:rerun-if-env-changed=PKG_CONFIG_PATH_x86_64_pc_windows_msvc cargo:rerun-if-env-changed=HOST_PKG_CONFIG_PATH cargo:rerun-if-env-changed=PKG_CONFIG_PATH cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64-pc-windows-msvc cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR_x86_64_pc_windows_msvc cargo:rerun-if-env-changed=HOST_PKG_CONFIG_LIBDIR cargo:rerun-if-env-changed=PKG_CONFIG_LIBDIR cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-pc-windows-msvc cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_pc_windows_msvc cargo:rerun-if-env-changed=HOST_PKG_CONFIG_SYSROOT_DIR cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR --- stderr thread 'main' panicked at C:\Users\hchap\.cargo\registry\src\index.crates.io-6f17d22bba15001f\exif-sys-0.1.0\build.rs:4:41: called `Result::unwrap()` on an `Err` value: "\npkg-config exited with status code 1\n> PKG_CONFIG_PATH=C:\\msys64\\usr\\lib\\pkgconfig PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 pkg-config --libs --cflags libexif\n\nThe system library `libexif` required by crate `exif-sys` was not found.\nThe file `libexif.pc` needs to be installed and the PKG_CONFIG_PATH environment variable must contain its parent directory.\nPKG_CONFIG_PATH contains the following:\n - C\n - \\msys64\\usr\\lib\\pkgconfig\n\nHINT: you may need to install a package such as libexif, libexif-dev or libexif-devel.\n" note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace warning: build failed, waiting for other jobs to finish... Error: Cargo invocation failed. at t.Cargo.getCargoArtifacts (c:\Users\hchap\.vscode\extensions\vadimcn.vscode-lldb-1.10.0\extension.js:1:14943) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async Object.open (c:\Users\hchap\.vscode\extensions\vadimcn.vscode-lldb-1.10.0\extension.js:1:13253) Caused by: Error: exit code: 101. at ChildProcess.<anonymous> (c:\Users\hchap\.vscode\extensions\vadimcn.vscode-lldb-1.10.0\extension.js:1:16610) at ChildProcess.emit (node:events:517:28) at maybeClose (node:internal/child_process:1098:16) at ChildProcess._handle.onexit (node:internal/child_process:303:5) * The terminal process terminated with exit code: 1. * Terminal will be reused by tasks, press any key to close it.
模块代码(file_management.rs)
use chrono::{Date, DateTime}; use std::fs::{File, metadata}; use image::io::Reader; use exif::{DateTime, Exif}; pub enum FileError{ NoSuchFile, UnableToRead } pub fn path_exists(path: Str) -> bool { return fs::metadata(path).is_ok(); } pub fn get_file_date(filepath: &str) -> Result<(u32, u32, u32), FileError> { if filepath.contains(".png") || filepath.contains(".jpg") || filepath.contains(".heic"){ if let Ok(file) = File::open(filepath) { if let Ok(reader) = image::io::Reader::open(file) { if let Some(exif) = reader.into_exif() { if let Some(datetime) = exif.get_field(exif::Tag::DateTime, false) { if let Some(datetime) = datetime.value.get_decoded() { if let DateTime::DateTime(dt) = datetime { return Some((dt.day(), dt.month(), dt.year())); } } } } } } } if let Ok(metadata) = metadata(filepath) { if let Ok(created) = metadata.created() { if let Ok(time) = created.duration_since(std::time::UNIX_EPOCH) { let datetime = chrono::NaiveDateTime::from_timestamp(time.as_secs() as i64, 0); return Some((datetime.day(), datetime.month(), datetime.year())); } } } return FileError::NoSuchFile; }
main.rs
mod file_management; use file_management::get_file_creation_date; fn main() { let file_path: String = String::from("E:/test_directory/photos/download.jpg"); if let Ok((year, month, day)) = get_file_date(file_path){ println!("{file_path} was created on {day}/{month}/{year}") } }
Cargo.toml
[package] name = "rust_file_scrub" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] chrono = "0.4" exif = "0.0.1" image = "0.23"
解决方案
1. 修正PKG_CONFIG_PATH配置问题
从错误日志能看到PKG_CONFIG_PATH被拆成了C和\msys64\usr\lib\pkgconfig,说明路径格式或环境变量设置有误:
- 打开系统环境变量设置,将PKG_CONFIG_PATH设为
C:\msys64\usr\lib\pkgconfig;C:\msys64\mingw64\lib\pkgconfig(覆盖原有值) - 重启终端和VSCode,确保环境变量生效
2. 安装libexif开发包
打开msys64的mingw64终端,执行以下命令安装libexif的开发文件(包含libexif.pc):
pacman -S mingw-w64-x86_64-libexif
3. 升级exif crate版本(推荐)
exif v0.0.1是2017年的老旧版本,后续版本优化了依赖处理,甚至支持静态编译libexif,无需系统库。修改Cargo.toml中的依赖:
exif = "0.24" # 使用最新稳定版
4. 修正代码中的编译错误
你的代码存在几处语法和逻辑错误,修正后示例如下:
修正后的file_management.rs
use chrono::{Date, DateTime}; use std::fs::{self, File, metadata}; use image::io::Reader; use exif::{DateTime as ExifDateTime, Exif, Tag}; pub enum FileError{ NoSuchFile, UnableToRead } pub fn path_exists(path: &str) -> bool { fs::metadata(path).is_ok() } pub fn get_file_date(filepath: &str) -> Result<(u32, u32, u32), FileError> { if filepath.ends_with(".png") || filepath.ends_with(".jpg") || filepath.ends_with(".heic"){ let file = File::open(filepath).map_err(|_| FileError::UnableToRead)?; let reader = Reader::open(file).map_err(|_| FileError::UnableToRead)?; if let Some(exif) = reader.into_exif().ok() { if let Some(field) = exif.get_field(Tag::DateTime, false) { if let Some(exif_dt) = field.value.get_decoded() { if let ExifDateTime::DateTime(dt) = exif_dt { return Ok((dt.day(), dt.month(), dt.year())); } } } } } let metadata = metadata(filepath).map_err(|_| FileError::NoSuchFile)?; let created = metadata.created().map_err(|_| FileError::UnableToRead)?; let time = created.duration_since(std::time::UNIX_EPOCH).map_err(|_| FileError::UnableToRead)?; let datetime = chrono::NaiveDateTime::from_timestamp(time.as_secs() as i64, 0); Ok((datetime.day(), datetime.month(), datetime.year())) }
修正后的main.rs
mod file_management; use file_management::get_file_date; fn main() { let file_path = String::from("E:/test_directory/photos/download.jpg"); match get_file_date(&file_path) { Ok((day, month, year)) => println!("{file_path} was created on {day}/{month}/{year}"), Err(e) => match e { file_management::FileError::NoSuchFile => println!("File not found: {file_path}"), file_management::FileError::UnableToRead => println!("Failed to read file: {file_path}"), } } }
内容的提问来源于stack exchange,提问作者Hchap
相关产品推荐
相关产品推荐

