Cargo可以在不构建应用程序的情况下下载和构建依赖项吗?

Tom*_*han 18 rust rust-cargo

有没有办法告诉Cargo安装和构建我的所有依赖项,但是没有尝试构建我的应用程序?

我想cargo install会这样做,但它实际上也一直在构建我的应用程序.我想进入一个状态,在那里cargo build可以找到所有依赖项,但无需触及/src目录.


我真正想要实现的目标:

我正在尝试为Rust应用程序构建Docker镜像,我想在其中执行以下步骤:

建立时间(docker build .):

  1. 导入已安装防锈工具的docker镜像
  2. 添加我的Cargo.toml和Cargo.lock文件
  3. 下载并构建所有依赖项
  4. 将我的源目录添加到图像
  5. 构建我的源代码

运行时间(docker run ...):

  1. 运行应用程序

我已经尝试了以下内容Dockerfile,但是指示的步骤也构建了我的应用程序(由于源目录尚未存在,当然会失败):

FROM jimmycuadra/rust

ADD Cargo.toml /source
ADD Cargo.lock /source

RUN cargo install # <-- failure here

ADD src /source/src
RUN cargo build

ENTRYPOINT cargo run
Run Code Online (Sandbox Code Playgroud)

我想将安装依赖项步骤与实际构建我的应用程序分开的原因是,如果我不更改依赖项,我希望Docker能够使用已安装和构建所有依赖项的缓存映像.因此,我不能ADD /src /source/src,直到安装依赖条件,因为当我改变我自己的代码,将无效缓存图像.

She*_*ter 8

据我所知,在Cargo中只构建依赖项没有原生支持.有一个未解决的问题.如果您可以向Cargo提交一些东西来完成它,或者可能创建第三方Cargo插件,我不会感到惊讶.我也想要这个功能cargo doc,当我自己的代码太破碎而无法编译时;-)

但是,我维护的Rust游乐场确实实现了您的最终目标.有一个基础Docker容器可以安装Rustup并复制到一个Cargo.toml包含所有可用于操场的板条箱.构建步骤创建一个空白项目(带有一个虚拟src/lib.rs),然后调用cargo buildcargo build --release编译包:

RUN cd / && \
    cargo new playground
WORKDIR /playground

ADD Cargo.toml /playground/Cargo.toml
RUN cargo build
RUN cargo build --release
RUN rm src/*.rs
Run Code Online (Sandbox Code Playgroud)

所有下载的包装箱都存储在Docker镜像$HOME/.cargo目录中,所有构建的包装箱都存储在应用程序target/{debug,release}目录中.

稍后,使用现在编译的包装箱将真实的源文件复制到容器中并且cargo build/ cargo run可以再次执行.

如果您正在构建可执行项目,那么您也希望复制Cargo.lock.

  • @UselesssCat [playground](https://play.rust-lang.org/) 允许您在调试和发布模式下编译代码,因此我们需要在两种模式下预编译所有依赖项。 (2认同)

Zac*_*hal 6

如果您添加一个虚拟的 main 或 lib 文件,您可以使用cargo build来拉下依赖项。我目前正在将此解决方案用于我的基于 Docker 的项目:

COPY Cargo.toml .
RUN mkdir src \
    && echo "// dummy file" > src/lib.rs \
    && cargo build
Run Code Online (Sandbox Code Playgroud)

我正在使用--volumes,所以我在这一点上完成了。主机卷进来并吹走虚拟文件,当我稍后构建源代码时,cargo 使用缓存的依赖项。如果您想稍后添加COPY(或ADD)并使用缓存的依赖项,则此解决方案也能正常工作。


Дми*_*ьев 5

基于GitHub 评论

FROM rust:1.37

WORKDIR /usr/src

# Create blank project
RUN USER=root cargo new PROJ

# We want dependencies cached, so copy those first.
COPY Cargo.toml /usr/src/PROJ/
COPY Cargo.lock /usr/src/PROJ/

WORKDIR /usr/src/PROJ

# This is a dummy build to get the dependencies cached.
RUN cargo build --release

# Now copy in the rest of the sources
COPY MyPROJECT/src /usr/src/PROJ/src/

# This is the actual build.
RUN cargo build --release \
    && mv target/release/appname /bin \
    && rm -rf /usr/src/PROJ

WORKDIR /

EXPOSE 8888

CMD ["/bin/appname"]
Run Code Online (Sandbox Code Playgroud)


Nie*_*kob 5

Cargo-Chef工具就是为了解决这个问题而设计的。以下是 README 中的示例,说明如何在 Dockerfile 中使用它:

FROM lukemathwalker/cargo-chef as planner
WORKDIR app
COPY . .
RUN cargo chef prepare  --recipe-path recipe.json

FROM lukemathwalker/cargo-chef as cacher
WORKDIR app
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

FROM rust as builder
WORKDIR app
COPY . .
# Copy over the cached dependencies
COPY --from=cacher /app/target target
COPY --from=cacher $CARGO_HOME $CARGO_HOME
RUN cargo build --release --bin app

FROM rust as runtime
WORKDIR app
COPY --from=builder /app/target/release/app /usr/local/bin
ENTRYPOINT ["/usr/local/bin/app"]
Run Code Online (Sandbox Code Playgroud)