如何在Windows x64机器上用64位rustc链接x86 .lib库?
问题
我在x64架构的Windows机器上构建Rust应用,需要链接一个暴露C接口的x86架构C++静态库ClientAuth.lib。已通过64位rustup-init.exe安装Rust,执行cargo build时出现以下链接错误:
= note: sanitized_auth_test_1.qvct9jv5vjn41op.rcgu.o : error LNK2019: unresolved external symbol encryptLogonAuth referenced in function _ZN21sanitized_auth_test_14main17hf80bd6c03de31c54E sanitized_auth_test_1.qvct9jv5vjn41op.rcgu.o : error LNK2019: unresolved external symbol initEncryption referenced in function _ZN21sanitized_auth_test_14main17hf80bd6c03de31c54E lib\\ClientAuth.lib : warning LNK4272: library machine type 'x86' conflicts with target machine type 'x64' C:\Users\XXX\development\sanitized_auth_test_1\target\debug\deps\sanitized_auth_test_1.exe : fatal error LNK1120: 2 unresolved externals
已尝试在VS 2022的x64原生工具命令提示符、x86_64交叉工具命令提示符以及x86原生工具命令提示符中执行编译,但错误一致。
环境信息
- Rust版本:
rustc 1.70.0-nightly (700938c07 2023-04-04) binary: rustc commit-hash: 700938c0781c9f135244bb1ec846fe1a5e03ae7d commit-date: 2023-04-04 host: x86_64-pc-windows-msvc release: 1.70.0-nightly LLVM version: 16.0.0
- Cargo版本:
cargo 1.70.0-nightly (0e474cfd7 2023-03-31) release: 1.70.0-nightly commit-hash: 0e474cfd7b16b018cf46e95da3f6a5b2f1f6a9e7 commit-date: 2023-03-31 host: x86_64-pc-windows-msvc libgit2: 1.5.0 (sys:0.16.0 vendored) libcurl: 8.0.1-DEV (sys:0.4.61+curl-8.0.1 vendored ssl:Schannel) os: Windows 10.0.22000 (Windows 10 Pro) [64-bit]
项目结构
Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 4/6/2023 8:00 AM include d----- 4/6/2023 8:00 AM lib d----- 4/6/2023 7:56 AM src d----- 4/6/2023 8:01 AM target -a---- 4/5/2023 12:09 PM 9 .gitignore -a---- 4/6/2023 7:58 AM 228 build.rs -a---- 4/6/2023 7:58 AM 165 Cargo.lock -a---- 4/6/2023 7:58 AM 178 Cargo.toml
关键文件内容
include/ClientAuth.h:
#pragma once #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ void initEncryption(void); int encryptLogonAuth( unsigned int sessionID, unsigned int vendorID, unsigned int productID, unsigned int bigEndian, char* outBuff); #ifdef __cplusplus } #endif /* __cplusplus */
src/main.rs:
use std::os::raw::c_char; #[link(name = "ClientAuth", kind = "static")] extern "C" { fn initEncryption(); fn encryptLogonAuth( session_id: u32, vendor_id: u32, product_id: u32, big_endian: u32, out_buff: *mut c_char, ) -> i32; } fn main() { let session_id: u32 = 0; let vendor_id: u32 = 0; let big_endian: u32 = 0; let product_id: u32 = 0; let mut out_buff: [c_char; 16] = Default::default(); unsafe { let _ = encryptLogonAuth( session_id, vendor_id, product_id, big_endian, out_buff.as_mut_ptr(), ); initEncryption(); } }
build.rs:
fn main() { println!("cargo:rustc-link-search=lib/"); println!("cargo:rustc-link-lib=ClientAuth"); println!("cargo:rerun-if-changed=src/main.rs"); println!("cargo:rerun-if-changed=include/ClientAuth.h"); }
Cargo.toml:
[package] name = "sanitized_auth_test_1" version = "0.1.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
由于无法获取库的源码重新编译,请问是否有办法在x64机器上使用64位cargo/rustc链接x86架构的ClientAuth.lib库?
解答
核心结论
无法直接用64位Rust工具链链接x86架构的静态库,x64与x86属于不同指令集架构,链接器无法匹配跨架构的符号,这是底层架构限制,没有绕过的办法。
可行解决方案:切换Rust到x86目标编译
既然无法重新编译库,只能将Rust程序编译为32位(x86),与库的架构匹配。步骤如下:
- 安装x86目标的Rust工具链
打开命令提示符执行:
rustup target add i686-pc-windows-msvc
- 指定x86目标编译程序
在VS 2022的x86原生工具命令提示符中执行:
cargo build --target i686-pc-windows-msvc
- 验证编译结果
编译完成后,32位程序会生成在target/i686-pc-windows-msvc/debug目录下,可直接在x64 Windows系统上通过WoW64兼容层运行。
为什么之前尝试x86命令提示符无效?
之前的操作未指定--target i686-pc-windows-msvc参数,Rust默认使用x64目标编译,即使在x86工具环境中,依然会生成64位程序,导致架构不匹配的错误。
内容的提问来源于stack exchange,提问作者Matthew Pittenger
相关产品推荐
相关产品推荐

