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

如何在Linux上容器化编译Rust开发的i686-pc-windows-msvc应用

问题

我正在开发一款目标平台为i686-pc-windows-msvc的Rust Windows应用,该应用通过build.rs文件指定Windows清单,在Windows系统上编译正常。切换到Linux环境后,尝试通过Dockerfile容器化编译流程但未成功。相关信息如下:

项目结构

❯ tree
.
├── build.rs
├── Cargo.lock
├── Cargo.toml
├── Dockerfile
├── src
│   ├── api.rs
│   ├── client.rs
│   ├── main.rs
│   ├── service.rs
│   └── system.rs
└── target

Cargo.toml配置

[package]
name = "wrapper"
version = "0.1.0"
edition = "2021"
build = "build.rs"

[build-dependencies]
winresource = "0.1"

[dependencies]
named-lock = "0.3.0"
rand = "0.8.5"
reqwest = "0.11.24"
tokio = { version = "1.36.0", features = ["rt", "rt-multi-thread"] }
winapi = { version = "0.3.9", features = ["processthreadsapi", "securitybaseapi", "winnt", "fileapi", "minwinbase", "iphlpapi", "winsock2", "ws2def"] }
windows-service = "0.6.0"

build.rs代码

extern crate winresource;

fn main() {
    let mut res = winresource::WindowsResource::new();
    res.set_manifest(
        r#"
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
            <requestedPrivileges>
                <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
            </requestedPrivileges>
        </security>
    </trustInfo>
</assembly>
"#,
    );
    res.set_ar_path("i686-w64-mingw32-gcc-ar");
    res.set_windres_path("i686-w64-mingw32-windres");
    if let Err(error) = res.compile() {
        eprint!("{error}");
        std::process::exit(1);
    }
}

当前Dockerfile内容

FROM archlinux:multilib-devel-20240101.0.204074

RUN pacman -Syu --noconfirm && \
    pacman -S --needed --noconfirm rustup mingw-w64

RUN rustup default stable && \
    rustup target install i686-pc-windows-msvc

WORKDIR /app

COPY Cargo.toml Cargo.lock build.rs ./
COPY src ./src

RUN cargo build --target i686-pc-windows-msvc
RUN cargo build --release --target i686-pc-windows-msvc

RUN mkdir -p /app/debug/ && \
    cp target/i686-pc-windows-msvc/debug/wrapper.exe /app/debug/

RUN mkdir -p /app/release/ && \
    cp target/i686-pc-windows-msvc/release/wrapper.exe /app/release/

编译报错信息

❯ docker build --tag 'wrapper' .
[...]Step 7/10 : RUN cargo build --target i686-pc-windows-msvc
[...]   Compiling wrapper v0.1.0 (/app)
The following warnings were emitted during compilation:

warning: wrapper@0.1.0: unknown Windows target used for cross-compilation; invoking unprefixed windres

error: failed to run custom build command for `wrapper v0.1.0 (/app)`

Caused by:
  process didn't exit successfully: `/app/target/debug/build/wrapper-6dacece8a0e1e7d8/build-script-build` (exit status: 1)
  --- stdout
  package.metadata does not exist
  cargo:warning=unknown Windows target used for cross-compilation; invoking unprefixed windres
  Selected RC path: '/bin\x64\rc.exe'

  --- stderr
  No such file or directory (os error 2)
warning: build failed, waiting for other jobs to finish...
The command '/bin/sh -c cargo build --target i686-pc-windows-msvc' returned a non-zero code: 101

请问如何修改Dockerfile,使其能正常编译并生成debug和release版本的程序?

解决方案

报错核心原因是:指定的目标平台i686-pc-windows-msvc是MSVC工具链目标,但Linux容器中使用的是MinGW工具链,两者不兼容,导致winresource库错误地尝试调用Windows原生的rc.exe(不存在于Linux环境)。调整为MinGW对应的目标平台即可解决问题,具体修改如下:

修改后的Dockerfile

FROM archlinux:multilib-devel-20240101.0.204074

RUN pacman -Syu --noconfirm && \
    pacman -S --needed --noconfirm rustup mingw-w64

RUN rustup default stable && \
    # 替换为MinGW对应的32位Windows目标平台
    rustup target install i686-pc-windows-gnu

WORKDIR /app

# 配置Cargo使用MinGW的链接器
ENV CARGO_TARGET_I686_PC_WINDOWS_GNU_LINKER=i686-w64-mingw32-gcc

COPY Cargo.toml Cargo.lock build.rs ./
COPY src ./src

# 使用MinGW目标平台编译debug版本
RUN cargo build --target i686-pc-windows-gnu
# 使用MinGW目标平台编译release版本
RUN cargo build --release --target i686-pc-windows-gnu

# 复制debug版本到指定目录
RUN mkdir -p /app/debug/ && \
    cp target/i686-pc-windows-gnu/debug/wrapper.exe /app/debug/

# 复制release版本到指定目录
RUN mkdir -p /app/release/ && \
    cp target/i686-pc-windows-gnu/release/wrapper.exe /app/release/

关键修改点说明

  • 切换目标平台:将i686-pc-windows-msvc替换为i686-pc-windows-gnu,这是MinGW工具链对应的Windows 32位目标,与容器中安装的mingw-w64工具链完全兼容。
  • 指定链接器:通过环境变量CARGO_TARGET_I686_PC_WINDOWS_GNU_LINKER明确指定MinGW的链接器i686-w64-mingw32-gcc,确保Cargo使用正确的工具链完成编译。
  • 调整路径:所有编译命令和文件复制路径都对应修改为新的目标平台目录,保证能正确找到生成的可执行文件。

补充说明

你的build.rs已经正确设置了MinGW的ar和windres路径,切换到gnu目标后,winresource库会自动识别交叉编译环境,使用指定的MinGW工具处理资源清单,不会再尝试调用Windows的rc.exe。

内容的提问来源于stack exchange,提问作者Nayrosk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 22:08:19