Is it possible to apply a patch to external code in Cargo.toml?
Asked Answered
T

2

5

I read the Cargo manual about the patch option but it is still unclear to me.

Is it possible to instruct Cargo:

  1. Get the code from this repository.
  2. Apply this patch file (my_cool_change.patch) to that code.

Is making my own fork of the project the only way to do it?

Tangerine answered 23/9, 2019 at 15:6 Comment(0)
S
5

It is not possible to instruct Cargo to do something like "take version 1.2.3 of crate foo-bar from crates.io and apply these arbitrary changes to the source code before compiling it".

The Cargo documentation is not lying to you: you will need to fork the project you wish to change, make the changes however you need, then replace the dependency with your forked version.

Scenic answered 23/9, 2019 at 15:10 Comment(0)
B
1

Internally yes, the correct way to do this is to download the original code, edit it, then point the Cargo dependencies to your changed local version. And you'd probably wanna do that by forking the original project's Git repository, especially if you plan to share your crate.

But if you really wanna do a quick-and-dirty patch with a tiny patch file, there's a tool for that now: cargo patch-crate automates much of this process for you. You just specify the base version of the crate like usual (let's say 0.1.2), and then add the following section to your Cargo.toml:

[package.metadata.patch]
crates=["crate-to-patch"]

From now on, running cargo patch-crate will fetch the crate's base version into a directory in target/patch, and apply patches in your project root's patches folder to it. If you don't have a patch file yet, the tool even helps with that: if you make file changes to that local version, then run cargo patch-crate crate-to-patch, all your changes will be collected into patches/crate-to-patch+0.1.2.patch and automatically applied in the future.

And to make your project actually use this patched version instead of the original, just use Cargo's official "patch" mechanism like this:

[patch.crates-io]
crate-to-patch = { path = './target/patch/crate-to-patch-0.1.2' }

Unfortunately this introduces another command into your clean-build process, because deleting the target directory now also deletes the version of the crate that your program depends on. This is easily fixed by running cargo patch-crate again, which re-fetches the base and re-applies the patches, but you can't forget to do that manually because there's no mechanism to tell Cargo to do it automatically before each build (AFAIK).

You could also look into a similar tool called cargo patch, which does essentially the same thing but uses slightly different configuration. In particular it allows you to specify by name the list of patches you want to apply, and since in your case you already have my_cool_change.patch that might be the better choice for you. But the principle is the same.

Becket answered 2/1, 2024 at 9:15 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.