[question] What is the recommended best practice for merging multiple packages?
See original GitHub issueConsider this example: we have packages A and B, where B depends on A. Then, we have a package C, which depends on B (and transitively on A). Now, further downstream (let’s say a package Z) someone needed at some time needed some bugfix for A, so they overrode the version of A to a specific version that contained the bugfix. Conan correctly rebuilt the B and all other packages that directly depended on A and everyone lived happily ever after.
Then, several months later, a maintainer of A and B noticed that packages A and B are too much coupled together and that it was a poor design choice to actually package the code into two packages, i.e. that packages A and B should have always been a single package. So they decide to merge A and B into a single package called AB. After that, package C gets updated to depend on package AB, not on B anymore (which is no longer maintained) and this propagates downstream.
Eventually, we come to the package Z, which is not aware that A and B have been merged and still has an override for A in its recipe. However, since both A and AB provide the same symbols, it gets a duplicate symbol linker error (in the best scenario) or undefined behaviour due to ODR violation (in the worst scenario).
Now, what is the recommended way for AB to communicate downstream that it supersedes packages A and B, i.e. that if a package X has a direct dependency on either A or B (or dependency override on either of those packages) and obtains AB as a transitive dependency, via some dependency Y, is there a way to inform package X (via warning or, ideally, error) that A and B have been superseded by AB and that it should either remove dependencies on A/B or on whatever brought the transitive dependency to AB.
Basically, I would like to know how to “force a conflict” between package AB and packages A and B.
I believe that would also help with resolving of #6599.
For example, a hypothetical syntax could be something like this:
class PackageAB(ConanFile):
name = "AB"
...
conflicts = ('A/[<2.0.0]@company/stable', 'B/*@company/stable')
This would say that if package AB
is in graph, the graph must not contain package B
at all (any version from company/stable
) nor package A earlier than v2.0.0 (however, it’s OK to contain A v2.0.0 or newer).
So my questions are:
- are there any ways to achieve this with current features of conan?
- if not, are there plans to add such a feature to conan v2.0?
- would such a feature be breaking, i.e. would it be possible to implement it on top of conan v1.x graph model?
Issue Analytics
- State:
- Created 4 years ago
- Comments:5 (5 by maintainers)
That crossed my mind as soon as I read the conan v1.28 release notes. I think it could work, but I’ll have to test it.
In general, I think this issue can be closed now, as
provides
should most probably be an answer to the question. In case it does not work as planned, rest assured that I’ll open a new issue 😛 .Hi! Maybe the
provides
attribute in the recipe can help with this situation.AB
will declare that providesA
andB
and Conan will raise an error. https://docs.conan.io/en/latest/reference/conanfile/attributes.html?highlight=provides#provides