Apple M1 macOS Monterey下Rust编译Diesel+PostgreSQL遇-lpq库缺失错误
在Apple M1 macOS上Diesel+PostgreSQL编译失败的解决建议
问题概述
在Apple M1芯片的macOS Monterey系统中,使用Rust Diesel框架连接PostgreSQL时,编译阶段出现链接错误,提示找不到libpq库。
报错信息
= note: ld: library not found for -lpq clang: error: linker command failed with exit code 1 (use -v to see invocation)
已尝试操作
- 执行
brew install libpq安装libpq - 设置环境变量
PQ_LIB_DIR="$(brew --prefix libpq)/lib" - 尝试过Stack Overflow上的相关解决方案,但问题未解决
相关代码文件
main.rs
use anyhow::Result; use diesel::query_dsl::RunQueryDsl; use diesel_orm::{ establish_connection, models::{Event, User}, schema::{events::dsl::events, users::dsl::users}, }; fn main() -> Result<()> { let connection = establish_connection(); let event_results = events.load::<Event>(&connection)?; let user_results = users.load::<User>(&connection)?; println!("Displaying {} events", event_results.len()); for event in event_results { println!("{}", event.name); } println!("Displaying {} users", user_results.len()); for user in user_results { println!("{}", user.user_name); } Ok(()) }
lib.rs
#![warn(clippy::pedantic)] #![allow(clippy::must_use_candidate)] #[macro_use] extern crate diesel; use crate::models::{Event, NewEvent, NewUser, User}; use crate::schema::{events::dsl::events, users::dsl::users}; use anyhow::Result; use diesel::pg::PgConnection; use diesel::prelude::*; use diesel::query_dsl::RunQueryDsl; use dotenv::dotenv; use std::env::var; pub mod models; pub mod schema; /// # Panics /// Function panics is the database connection fails pub fn establish_connection() -> PgConnection { dotenv().ok(); let database_url = var("DATABASE_URL").expect("DATABASE_URL must be set"); PgConnection::establish(&database_url) .unwrap_or_else(|_| panic!("Error connecting to {database_url}")) } pub fn create_event(conn: &PgConnection, name: &str) -> Event { use schema::events; let new_event = NewEvent { name, ..Default::default() }; diesel::insert_into(events::table) .values(&new_event) .get_result(conn) .expect("Error inserting new event") } pub fn create_user<'a>(conn: &PgConnection, user_name: &'a str, password: &'a str) -> User { use schema::users; let new_user = NewUser { user_name, password, liked_event_ids: &[], disliked_event_ids: &[], }; diesel::insert_into(users::table) .values(&new_user) .get_result(conn) .expect("Error inserting new user") } /// Gets all events in database /// /// # Errors /// /// Returns [`Err`] if it is unable to retrieve `Event`s pub fn get_events(conn: &PgConnection) -> Result<Vec<Event>> { Ok(events.load::<Event>(conn)?) } /// Gets all users in database /// /// # Errors /// /// Returns [`Err`] if it is unable to retrieve `User`s pub fn get_users(conn: &PgConnection) -> Result<Vec<User>> { Ok(users.load::<User>(conn)?) }
schema.rs
table! { events (id) { id -> Int4, name -> Text, uri -> Nullable<Text>, startdate -> Nullable<Text>, enddate -> Nullable<Text>, category -> Nullable<Text>, info -> Nullable<Text>, bookurl -> Nullable<Text>, price -> Nullable<Text>, location -> Nullable<Text>, source -> Nullable<Text>, } } table! { users (id) { id -> Int4, user_name -> Text, password -> Text, liked_event_ids -> Nullable<Array<Int4>>, disliked_event_ids -> Nullable<Array<Int4>>, } } allow_tables_to_appear_in_same_query!( events, users, );
models.rs
use super::schema::{events, users}; use diesel::Queryable; use serde::{Deserialize, Serialize}; #[derive(Debug, Queryable, Deserialize, Serialize)] pub struct User { pub id: i32, pub user_name: String, pub password: String, pub likes: Option<Vec<i32>>, pub dislikes: Option<Vec<i32>>, } #[derive(Debug, Queryable, Deserialize, Serialize)] pub struct Event { pub id: i32, pub name: String, pub uri: Option<String>, pub start_date: Option<String>, pub end_date: Option<String>, pub category: Option<String>, pub info: Option<String>, pub book_url: Option<String>, pub price: Option<String>, pub location: Option<String>, pub source: Option<String>, } #[derive(Insertable)] #[table_name = "users"] pub struct NewUser<'a> { pub user_name: &'a str, pub password: &'a str, pub liked_event_ids: &'a [i32], pub disliked_event_ids: &'a [i32], } #[derive(Default, Insertable)] #[table_name = "events"] pub struct NewEvent<'a> { pub name: &'a str, pub uri: Option<&'a str>, pub startdate: Option<&'a str>, pub enddate: Option<&'a str>, pub category: Option<&'a str>, pub info: Option<&'a str>, pub bookurl: Option<&'a str>, pub price: Option<&'a str>, pub location: Option<&'a str>, pub source: Option<&'a str>, }
Cargo.toml
[package] name = "diesel_orm" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diesel = { version = "1.4.4", features = ["postgres"] } dotenv = "0.15" serde = { version = "1.0", features = ["derive"] } anyhow = "1.0.13"
解决建议
1. 确保环境变量生效
在终端执行以下命令,临时加载libpq路径并重新编译:
export PQ_LIB_DIR=$(brew --prefix libpq)/lib export PATH="$(brew --prefix libpq)/bin:$PATH" cargo build
如果需要永久生效,将上述两行添加到shell配置文件:
- zsh用户:编辑
~/.zshrc,添加后执行source ~/.zshrc - bash用户:编辑
~/.bash_profile,添加后执行source ~/.bash_profile
2. 给Cargo指定libpq链接路径
在项目根目录创建.cargo/config.toml文件,写入以下内容(适配M1芯片的brew路径):
[target.aarch64-apple-darwin] rustflags = [ "-L", "/opt/homebrew/opt/libpq/lib", "-l", "pq", ]
保存后重新运行cargo build。
3. 升级Diesel版本
当前使用的Diesel 1.4.4版本较旧,对M1芯片的支持可能不完善,建议升级到最新稳定版:
修改Cargo.toml中的Diesel依赖:
diesel = { version = "2.1.0", features = ["postgres"] }
升级后需注意API变化,例如establish_connection的调用方式可能需要调整,同时重新生成数据库schema(若使用diesel-cli)。
4. 正确安装diesel-cli(若使用)
如果需要用diesel-cli管理数据库,安装时需指定libpq路径:
PQ_LIB_DIR=$(brew --prefix libpq)/lib cargo install diesel_cli --no-default-features --features postgres
5. 验证libpq安装路径
执行以下命令确认libpq的安装路径是否正确:
brew --prefix libpq
M1芯片上正常输出应为/opt/homebrew/opt/libpq,再检查该路径下是否存在libpq库文件:
ls $(brew --prefix libpq)/lib/libpq.dylib
若文件不存在,重新执行brew reinstall libpq修复安装。
内容的提问来源于stack exchange,提问作者trp
相关产品推荐
相关产品推荐

