Cargo可以下载和构建依赖项而无需构建应用程序吗?

时间:2017-02-09 06:53:56

标签: rust rust-cargo

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

我认为cargo install会这样做,但它实际上也会一直构建我的应用程序。我想进入一个状态,其中cargo build会找到所有可以使用的依赖项,但不会触及/src目录。

我真正想要实现的目标:

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

构建时间(docker build .):

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

    1. 运行应用程序
    2. 我已经尝试了以下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
      

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

5 个答案:

答案 0 :(得分:6)

据我所知,在Cargo中只构建依赖项没有原生支持。有an open issue for it。如果你可以向Cargo提交一些东西来完成它,或者可能创建一个第三方Cargo插件,我不会感到惊讶。我也想要while True: i = random.randint(0, 8) j = random.randint(0, 9) if i != j and X_valid[0][i] > 0 and X_valid[0][j] > 0: break X_valid[0][i] = 0 X_valid[0][j] = 0 的这个功能,当我自己的代码太破碎而无法编译时; - )

但是,我维护的Rust playground确实可以实现您的最终目标。有base Docker container安装Rustup并在Cargo.toml中复制,并且所有的操作箱都可用于操场。 The build steps create a blank project (with a dummy src/lib.rs), then calls cargo build and cargo build --release to compile the crates

cargo doc

所有下载的包装箱都存储在Docker镜像的RUN cd / && \ cargo new playground WORKDIR /playground ADD Cargo.toml /playground/Cargo.toml RUN cargo build RUN cargo build --release RUN rm src/*.rs 目录中,所有构建的包装箱都存储在应用程序$HOME/.cargo目录中。

稍后,将真实的源文件复制到容器中,并使用现在编译的包装箱再次执行target/{debug,release} / cargo build

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

答案 1 :(得分:1)

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

COPY Cargo.toml .
RUN mkdir src \
    && echo "// dummy file" > src/lib.rs \
    && cargo build

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

答案 2 :(得分:0)

基于GitHub comment

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

答案 3 :(得分:0)

我只想在此处发布此内容,以便其他人看到它的发展。我刚刚开始使用一个名为docker-wharf(https://github.com/denzp/cargo-wharf/tree/master/cargo-wharf-frontend)的Docker实验工具。这是一个Docker BuildKit前端,可为您缓存已构建的货物依存关系。如果仅更改一个源文件,则在调用docker build时唯一要重建的内容。您可以通过注释Cargo.toml文件,然后将Docker定向到Cargo.toml而不是Dockerfile来使用它。去看看,这正是我想要的。 (我绝不隶属于该项目。)

答案 4 :(得分:0)

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