You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 10:05:56