Cargo: Allow patching dependencies with patch files

Created on 20 Oct 2017  Â·  7Comments  Â·  Source: rust-lang/cargo

Summary

This proposes to add an ability for Cargo to patch dependencies with patch files.

Problem description

The addition of the [patch] manifest section has made making localised changes to crates used by an individual project much easier. However, this still requires checking out the source code for the entire crate even if only a few lines of the source actually need to be modified.

This approach is fairly reasonable for individual Rust projects, however when embedded in a much larger build system that pulls hundreds of various projects together this can quickly become unwieldy (e.g. Buildroot, OpenWrt build system, etc). Rather than storing the entire source for any packages requiring modification, these build system instead store a set of patch files against a specific release version for the package in question.

Possible solution

This proposes adding an ability to let Cargo apply a set of patch files to a create after it is retrieved and extracted and before it is compiled. It would probably make sense to use the unified diff format given its popularity with tools like Git etc.

A previous proposal #3830 similar to this one, suggested the following syntax:

[dependencies.foobar]
version = "1.42"
patches = [
    "path/to/patch-1.patch",
    "path/to/patch-2/foobarize-a-bit-less.patch"
]

That syntax seems like a good starting point although someone with more Cargo experience might have a better idea.

Final remarks

One of the stated 2017 roadmap goals was for better integration with large build systems and I believe this would help further that goal.

C-feature-request

Most helpful comment

Hey folks,
I created a (very) dirty POC for a Cargo Patch sub command [1] which allows patching dependencies from crates.io. It is far away from being feature complete but it should be a nice base to get something started. I will work on it on the next days and weeks and help would be much appreciated.

[1] https://github.com/mettke/cargo-patch

All 7 comments

FWIW, I think applying patches is beyond Cargo's rational. Besides the intricacies of successfully applying patches (see the wilderness of git apply), at the end of the day Cargo itself is simply not a universal build system. For my money, it would be better turn this around and have the external build system fetch the source of the dependency, apply the patch and call cargo to build the desired crate, including the prepared, patched dependency.

@lukaslueg I see where you're coming from but that would eliminate the primary purpose of Cargo; that is dependency management. Having build systems re-implement the crates.io dependecy tree and try to keep it in sync with upstream would be so onerous I don't think anyone would bother.

There is however an alternative to this proposal. Keep the behaviour of Cargo as it is now but expose more of the internal behaviour to outside build systems so they can have more control over the process. For example, what I'm picturing might be something like the following:

  1. A command for Cargo to list all the crates and their specific versions which are needed to build the project; listed in the correct build order.
  2. A way to download an individual crate from the spec in the above list to a custom location.
  3. A way to extract the crates (the external build system could do this but letting Cargo do it might make the process more consistent?)
  4. A way to build the project with the manually extracted crates (after the external build system has patched those crates)

The above is probably just one approach and someone more familiar with Cargo's internals might have a better suggestion, however the core idea here is a way for external build systems to hook into any part of the Cargo build process to make it easier to integrate into their own build process.

+1

Hello,

Here i use Rocket for a project.
But there is a thing Rocket doesn't do well for my purpose : Chunked Transfer Encoding of few bytes.
I had to patch Rocket AND Hyper (Rocket uses an old version of Hyper → 0.10.13).

There is an issue for this on Rocket, but i can't open an issue for this on Hyper as latest versions of hyper already has the patch (but Rocket isn't compatible with latest Hyper).

So, as long as Rocket doesnt use latest Hyper, i am stuck at forking both projects, to add my patches to them, while @hetmankp's proposal would allow me to store only 2 diff files of around 10 lines each.

That's why i +1 this issue.
Sorry for my english if understanding me is hard.

Another case where it might be useful, is when you need to provide a mini test project that expose a bug.
You could provide a patch for the impacted library, and observe the bug by (de)commenting the patch from the Cargo.toml file.

I like the idea.
Now, it may not be doable.

Hey folks,
I created a (very) dirty POC for a Cargo Patch sub command [1] which allows patching dependencies from crates.io. It is far away from being feature complete but it should be a nice base to get something started. I will work on it on the next days and weeks and help would be much appreciated.

[1] https://github.com/mettke/cargo-patch

I've posted an implementation PR. Currently in draft.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sdroege picture sdroege  Â·  3Comments

JustAPerson picture JustAPerson  Â·  3Comments

rodoufu picture rodoufu  Â·  3Comments

briansmith picture briansmith  Â·  3Comments

japaric picture japaric  Â·  3Comments