我正在为Windows开发一个应用程序(目标是:i686-pc-windows-msvc),这个应用程序有特殊的要求:它使用一个build.rs文件来指定Windows list .

编译在Windows上运行得很好,但我不得不在这个项目中切换到Linux.

这个项目是这样的:

❯ 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"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[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);
    }
}

因此,我try 通过Dockerfile将编译过程包装起来,但没有成功.

以下是我的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正确编译并返回程序的两个版本(debugrelease)?

推荐答案

winres crate 不支持交叉编译(见https://github.com/mxre/winres/issues/42).

您的 Select 是:

  • 在非Windows平台上使用条件编译,跳过build.rs中调用winres的部分.如果您的应用程序在没有 list 的情况下将无法正常工作,这可能不是您的 Select .
  • 切换到使用winresource fork,如果安装了mingw-w64,它确实支持交叉编译.请注意,您将无法从Linux容器中定位i686-pc-windows-msvc,因为MSVC工具链仅在Windows上可用.你需要使用i686-pc-windows-gnu目标来代替.事实上,消息cargo:warning=unknown Windows target used for cross-compilation; invoking unprefixed windres来自winresource,当交叉编译时不支持i686-pc-windows-msvc.

Rust相关问答推荐

为什么幻影数据不能自动推断?

如何格式化传入Rust中mysql crate的Pool::new的字符串

更合理的方法来设计样条线函数器?

程序在频道RX上挂起

在铁 rust 中,如何一次只引用几件事中的一件?

装箱特性如何影响传递给它的参数的生命周期 ?(举一个非常具体的例子)

为什么BufReader实际上没有缓冲短寻道?

我应该如何表达具有生命周期参数的类型的总排序,同时允许与不同生命周期进行比较?

为什么 Rust 创建的 f32 小于 f32::MIN_POSITIVE?

为什么 js_sys Promise::new 需要 FnMut?

Rust Redis 中的 HSET 命令问题

简单 TCP 服务器的连接由对等重置错误,mio 负载较小

特征中定义的类型与一般定义的类型之间的区别

如何获取函数中borrow 的切片的第一部分?

返回引用字符串的future

如何在 Rust 中返回通用 struct

如何在 nom 中构建负前瞻解析器?

如何将 u8 切片复制到 u32 切片中?

C++ 中的 CRTP 是一种表达其他语言中特征和/或 ADT 的方法吗?

在传输不可复制的值时实现就地枚举修改