-
Notifications
You must be signed in to change notification settings - Fork 991
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to resolve conflicts between requires and build_requires graphs #4753
Comments
Hi @DoDoENT I think the main point is that build_requires are private, they cannot be overwritten by downstream consumer. You cannot tell one of your dependencies that they should use a certain build_requires. That can only be done from the profiles. Maybe it would be good to understand your use case if the The way to not propagate downstream 2 different versions of A is to use them privately, otherwise, as you realized, they are a conflict. Because the system will effectively try to find the headers and link of both of them, but only one of them will be found, because they will collide in the consumer |
Hi @memsharded! Thank for the quick response!
I understand that and example I've attached does not even try that. The whole purpose of DD to have AA, BB and CC as build_requires instead of requires is because those are only required to build DD. However, DD build_requires newer version of AA than BB does, so I would expect that I should be able to somehow override BB's dependency (which is requires, not build_requires) to newer version of AA (maybe not automatically, but with something like 'overrides' keyword that is also available for the requires graph).
Of course - I think this will also make things more clear why private dependencies do not work for me. Let's say that Also, let's say that After that, let def configure(self):
self.options['Protection'].all_keys = False This is to prevent accidentally leaking encryption keys into production binary. Here we come to the After that, there are several models packages that are presented to Conan as header-only packages, but they don't contain any headers nor libraries. They only contain built resources to be used with class AaaConan(ConanFile):
name = 'EuropeanOcrModels'
requires = (
'OcrEngine/1.0.0@user/testing'
)
def build_requirements(self):
model_builder = str(self.requires['OcrEngine']).replace('OcrEngine', 'OcrModelBuilder')
self.build_requires(model_builder) From the example above it looks like that Finally, there is a final product (an ios/android app or SDK) that uses one or more OCR models packages (let's say one app uses only european OCR models, another needs european and chineese, the third one only japaneese, etc.) so in its Here is a described sample that correctly works with conan v1.12.3, but does not work with conan v1.13.1. With conan v1.13.1, when creating
If I change This is the
and this one when using private requirements:
This problem is also reflected in This may or may not lead to compile errors, depending on whether the compiler compiling the source of the Here is the modified example which uses private dependencies for I hope I explained the issue a bit better now. Please let me know if I can help more. |
The problem also happens with conan v1.14.0. However, if in requires = (
('CoreUtils/1.2.0@user/testing', 'private'),
('OcrEngine/1.0.0@user/testing', 'private'),
('Protection/1.0.0@user/testing', 'private'),
) into def requirements(self):
self.requires('CoreUtils/1.2.0@user/testing', private=True, override=True)
self.requires('OcrEngine/1.0.0@user/testing', private=True, override=True)
self.requires('Protection/1.0.0@user/testing', private=True, override=True) then conan does not complain, but the generated So, I am currently stuck with conan v1.12.3 for reasons explained in my earlier messages. |
@memsharded , I think I might be hitting this same problem. I first noticed it when upgrading to 1.13.2 from 1.12.3. But I also see the same problem on 1.14.0. Expected Behavior ( I think )I expect MyApp's semver compatible requirements to override additional requirements coming from its build requirements. Current Behavior (1.13+)
# Create SharedCOMLib 1.0.1
$ conan create shared_com_lib.py 1.0.1@user/testing
# Create SharedCOMLib 1.0.2
$ conan create shared_com_lib.py 1.0.2@user/testing
# Create SharedGuiLib 0.1
$ conan create shared_gui_lib.py user/testing
# Resolve requirements for MyApp 0.1
$ conan info myapp.py
Old Behavior (1.12.3)
# Create SharedCOMLib 1.0.1
$ conan create shared_com_lib.py 1.0.1@user/testing
# Create SharedCOMLib 1.0.2
$ conan create shared_com_lib.py 1.0.2@user/testing
# Create SharedGuiLib 0.1
$ conan create shared_gui_lib.py user/testing
# Resolve requirements for MyApp 0.1
$ conan info myapp.py
ContextI have three Conan packages in play:
With the following package versions: SharedCOMLib
SharedGuiLib
MyApp
A build requirement of MyApp (i.e. "SharedCOMLib") has outdated requirements on another shared library (i.e. "SharedCOMLib"). MyApp also has a requirement on the same shared library (i.e. "SharedCOMLib"), albeit with a more up to date version. Up until Conan 1.13, that has been okay, because Conan overrode the older version of "SharedCOMLib" coming from my MyApp's build requirements with the newer version coming from MyApp's requirements. I can apply the fix outlined above in #4753 (comment), and do something like: - requires = ("SharedCOMLib/1.0.2@user/testing",)
+def requirements(self):
+ self.requires('SharedCOMLib/1.0.2@user/testing', override=True) But I'm not certain whether the above change is necessary in a 1.13+ world or whether my example illustrates a regression. As always, thanks to you and all the other maintainers for all your hard work and support maintaining Conan! Edit 3/29/2019 Edit 4/10/2019 |
@thorntonryan: I think you got one quirk wrong while simplifying the scenario from our real package for into your example: The versions of SharedCOMLib should be more like 1.0.1 and 1.0.2; i.e. they are semver compatible, and the package_id of SharedGuiLib (which uses that default mode) does not change due to this override, and the existing binary package can/should be used. By making your example 0.1 and 0.2, they would not be semver compatible and the package_id would have the full version in it. I guess this doesn't change the initial error, since conan raises "Requirement ... conflicts with already defined ..." without even considering that the previous behavior of 1.12.x (treating the consuming package's chosen version as an override), but if it had continued your example would hit an unrelated (and valid) error that there was no binary in the cache for with that package_id |
With the official release of Visual Studio 2019 this now begins to pose a serious problem. Conan 1.12.3 does not work correctly with cmake generator for VS 2019 (it sets generator to "Visual Studio UnknownVersion 16 Win64") and latest conan version (which handles VS 2019 correctly) does not support resolving conflicts between build requirements. We really need to get this fixed. |
Hi there! @DoDoENT @puetzk @thorntonryan I am processing this feedback now, but it is a lot to process and understand, in the meantime, it would be great if you could have a look or even try (from the source branch) the current proposal for a patch in Conan 1.14.2: #4937 It changes the way that build-requires of libraries already existing in the regular-requires graph is processed. They won't span a new node anymore, as that would be a conflict, but it reuses the upstream node. Still, if the build_requires uses a different version, it will conflict (you don't want to change the upstream library version because of a build-requires), but it can be overriden from profile build-requires. |
Ok, there is too much feedback, lets start with the case of @DoDoENT I have put the zip in a repo here: https://github.com/memsharded/tools_build_requires, with a Lets start with this part of the graph: Some pre-conditions:
The expansion of the graph IF OcrModelBuilder uses build_requires as currently defined would be something like: This graph had 2 important bugs in conan 1.12 and older versions:
With the new expansion model defined in Conan 1.13, those bugs have been fixed. Conflicts will be raised, and the final dependency graph when the conflicts are solved, will resemble the first figure, with diamonds. So far, this behavior is not a considered a regression and it won't be reverted, the conflicts totally make sense and are the evidence of something that in the past was failing silently. I am not saying that in some cases the final result couldn't be a good one, but that was mostly a lucky coincidence. Now the problem is that
That means, they are designed for tools like cmake or gtest. Not for libraries to be linked with. They shouldn't affect at all to your binary. It doesn't matter if you are using the CMake from your system, or from a Conan package, and it doesn't matter if you are building your tests linked with gtest or not, the final package (headers, library), should be the same. This is definitely not the case for an executable linking with libraries. They are really required, they affect the binary, they are not tools that will be installed in the system. Another view, would be what happens if now the libraries are shared instead of static. Then, a So, the first stopper, which is building OcrModelBuilder is solved if we use regular requires instead of build_requires in it. Now the problem is moved downstream when we want to use this OcrModelBuilder as a build_require for EuropeanOcrModels, which is trying to do: The different versions of CoreUtils and the different configurations of Protection (with and without all_keys) will conflict, because EuropeanOcrModels need to build, it will So, what could be a possible approach right now, with the current provided tools? I think you already realized that 2 levels of
The graph would be: This approach has some other nice properties:
Please check the repo at https://github.com/memsharded/tools_build_requires, it implements exactly this later graph So, in my opinion, the changes introduced in Conan 1.13 and maintained in Conan 1.14, (modulo the bug fix pending for Conan 1.14.2 in #4937) are valid, and actually protecting from very dangerous effects of abuse of build-requires, like linking the wrong dependency version, or what could be worse, to link with the wrong Now, it is true that a mechanism to be able to depend on tools with build_requires, when those tools also have transitive and incompatible dependencies with our main dependency graph is necessary. Looking forward your feedback, if necessary we could even do a call/chat in slack or zoom. Thanks very much for all your detailed feedback, your prepared code, etc., you rock! It is great to be able to work this way :) :) :) |
Wow!! That's really huge feedback! Thank you very very much! I will definitely try this approach with another level of indirection (i.e. the OcrModelBuilderTool package) and report back if I stumble upon new problems. However, since I am currently in the middle of another project, it will probably take me a few days to find time to try this, so stay tuned! Anyway, @memsharded, this comment of yours is so detailed and great that it could be reused as a case study of how Conan can be used in rather complex development environments (maybe a blog post? or special part of documentation with case studies?). Of course, I first need to check that it really works for my real use case. |
Yes, definitely. I wanted to make sure first that we are addressing this issue in a way that make sense for most parties, and when we are all ok, it will be then converted to documentation. So looking forward to your feedback when you manage to try it. We will keep working on it, also checking the specific use cases of @puetzk and @thorntonryan too, will report progress here. Cheers!! |
Okay, FWIW, I've uploaded my example here too: Problem still exists on 1.14. Haven't tried 1.14.2 yet. |
Hi, sorry for reporting back late, but I've tested this approach on our codebase and so far it works flawlessly. Thank you again! I think this issue can be closed now and your comment added to the documentation. |
Hi @DoDoENT Thanks very much for your feedback and for your efforts trying this approach! It would also be great if you could try the changes proposed for a patch Conan 1.14.4 here: #4987, they affect mostly privates, but it would be better if you could try everything is ok. I will keep this issue open at the moment, as @thorntonryan might still have issues. |
@memsharded , thanks for the update! @puetzk and I haven't had a chance to test out your fix yet, but it's definitely on our todo list. We'll report back once we have more information. |
No problem, take your time, thanks for following up @thorntonryan 😄 Looking forward your feedback when possible. Cheers! |
Hi @memsharded, I've tried your patch for v1.14.4 and it works for us. However, we were using privates only as described in my example and replaced them with build requirements, which triggered this issue. Since we are not using shared libraries in our codebase (at the moment), but only statics and executables, we are OK with using your workaround with an additional level of indirection and build requirements as you described above. Thank you for all the hard work and your continuous support! |
Ok, I'm still trying to parse what we should be doing based on how we've been apparently mis-using According to #4753 (comment) and the doc for Build Requirements, it looks like As as summarized above:
And so, it is correct usage for
However, we are doing exactly this, which appears to be our problem. In a variety of places, we have static libraries listed as
Excerpt from Build Requirements These pseudo "build_requirements" of ours are only needed when building our static library from source, and otherwise aren't part of our static libraries' public API. If the static library's package has already been built, then there's no need for a consumer to download these "build_requirements". If I'm following, is the suggestion to make "build_requirements" such as these into Private Requirements ?
Excerpt from Private Requirements And so requirements on libraries that are required to build a static library from source, but are not otherwise part of its public API (e.g. boost, etc.) should be marked as "private" |
@thorntonryan, let me ask you about this part:
So if I understood correctly, you need package A (static library) when building package B (also a static library), but when package C (executable or shared library that is a user of package B) uses B, it does not need to see the headers of package A, as public API of B hides public API of A. However, when linking C, it needs to also link to A (because B uses it internally). Is that the case? If no, can you then please explain further why is A even needed for B? If yes, then B must have a normal requirement on A (neither private nor build), as it must transfer its dependency downstream, so that C knows that it needs to link to it. However, this also transfers the visibility of A's public API to C, which is something I opened issue #4038 for (I don't know of any workarounds for that at the moment). |
Looks like we were misusing build_requirements See conan-io/conan#4753 (comment) and conan-io/conan#4753 (comment) Leaving the COM libraries as requires also makes some logical sense, because the DLLs are not header only or static, therefore they are not embedded inside the mock static SharedGuiLib, and consuming applications linking against SharedGuiLib should still need these DLL binaries in some way. Arguably, SharedGuiLib *could* have a "private" requires on these COM libraries. However, that's a bit of an academic argument due to the nature of our COM libraries, which maintain strict semver ABI guarantees and for many applications are installed system wide and not shipped alongside the consuming tool. In our case, these COM libraries are not part of the public API of SharedGuiLib, so "private" seems appropriate, but private overrides don't seem to work that way in Conan 1.14.4 So, committing our workaround, which we'll take in practice, and will submit further examples to illustrate our remaining issues.
I have this issue with the following Conan file:
This does not install because of the following conflict:
Adding My current workaround is to not use build requirements, but this is not a long-term solution. |
Hi @kad-beekw When you do install, make sure to use both This will be the mode of operation in Conan 2.0. |
This issue was reported in 2019 and it seems, it will be long time "known issue". https://docs.conan.io/en/latest/versioning/introduction.html |
Closing this ticket as solved in Conan 2, please create new issues against Conan 2 if necessary, thanks. |
Conan v1.13 introduced reporting conflicts between requires and build_requires graphs. This is very good, as it solves many problems, but sometimes you need to be able to resolve reported conflicts and this seems not being possible at the moment (using conan v1.13.1).
Here is a simple project that demonstrates the issue.
Basically, we have a package
Aaa
with three versions: v1.0.0, v1.1.0 and v1.2.0. PackageBbb
requiresAaa/1.0.0
, packageCcc
requires bothAaa/1.1.0
andBbb/1.1.0
(thus overridingBbb's
dependency onAaa
and packageDdd
build_requires bothAaa/1.2.0
,Bbb/1.0.0
andCcc/1.0.0
. However, instead of overriding bothBbb's
andCcc's
requirements onAaa
with version1.2.0
, conan reports a conflict:However, if I change
Ddd's
build_requires expression fromto
I get different conflict:
Also, other permutations of build_requires order also give different conflicts.
My questions are:
Bbb's
andCcc's
dependency toAaa/1.2.0
?override
keyword (a solution I would use ifDdd
requiredAaa
,Bbb
andCcc
instead of only build_required it).build_requires
withrequires
inDdd's
conanfile, then no conflict is reported, but I don't wantDdd
to carryAaa
,Bbb
andCcc
as dependencies to downstream and I don't want to them to affectDdd's
package_id. (Image thatDdd
is a package that contains only executable built againstAaa
,Bbb
andCcc
static libraries and consumers of theDdd
package do not need executable rebuilt if they themselves use different versions of those static libraries (you can think of them as utility libraries)).build_requires
matter? Why can't I simply sort all my dependencies alphabetically? (we noticed the similar problem also forrequires
clause, although in more complex examples).The text was updated successfully, but these errors were encountered: