-
Notifications
You must be signed in to change notification settings - Fork 16
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
Dependency graph will always be computed completely, including build-requires #20
Dependency graph will always be computed completely, including build-requires #20
Conversation
I'm OK with that as long as there is still a possibility for some packages that are build-only dependency to not affect the For example, package Also, I would argue that packages like the mentioned |
Yes, what we had in mind is a similar model to the existing one for
So changes in the minor version of I hadn't thought about this case, but I guess defining it based on the package name, could make sense. In that case we could support something like:
Just a rough UI idea. Note: for in-recipe definition in the |
Being able to specify the modes on a per-build-requirement basis resolved all of my concerns. Being able to have that level of control helps serve multiple needs. |
Overall I think this proposal makes sense and is a good idea. However I have one or two questions.
|
@Daniel-Roberts-Bose , I think the only difference between Or did I also miss something? |
everything that provides a solution for conan-io/conan#7876 is welcome ! |
If you only mean that it must pick a recipe (and not that a package_id), that could maybe be OK. Or maybe that there's a But we have a number of libraries that have complicated cross-compile setups (e.g. build_requires are almost wholly disjoint from their own package_id). Most are COM libraries, that may not even be written in the same language as their consumer, and potentially aren't even built on the same OS. The profile:build in effect for to build the consumer of this library may not be even remotely related to the profile:build needed to build the library, and such recipes are going to fail if you actually try to resolve them the consumer won't have have any of the needed settings. I feel like I don't understand the motivation here, though, so maybe I'm missing something. Given the android-ndk API level be a part of the package_id via settings.compiler or settings.os? We don't capture the exact compiler binary for anything else... Or looking at it more philosphically, what is a build_requires, except something that you only need to think about to build, not to consume? We already have Of course, given all these other knobs exist anyway, maybe it would make sense to just have a single kind of |
They are not going to be identical:
When you don't want def package_id(self):
self.info.requires["mydep"].unrelated_mode() Is this what you mean? |
what @puetzk is commenting here like We probably don't need to get into this level of detail now, we think it is possible to agree on the fact that having incomplete graphs based on the type of requirements is confusing, and having a full dependency graph containing all different types of requirements could help to reduce complexity and be more deterministic and understandable by users, irrespective of the different details of different types of requirements. |
@memsharded I have a question about this one. I can think of three ways to provide a custom toolchain to build:
I think you're saying that this proposal makes case 1 affect the This concerns me because the choice between these 3 cases is often stylistic/subjective or situation-dependent. There are been times within our organization that we've chosen one path or another. I would expect that whether I specify a |
We demand rigidly defined areas of doubt and uncertainty!. I guess I just still reject this premise - there are a lot of package with carefully limited API/ABI that I want to build, in a very specific way, and then consume, in a very-much-less-specific way. The implementation conceals a great deal of complexity that I do not want consumer recipes to even have to think about, because it doesn't affect them one bit if it changes, and they wouldn't reasonably be expected to even know vocabulary to describe it. They want the x86-windows runtime, they don't know or care that its built with msvc16.8 (or that it's built with mingw-gcc, C#, or that it's using liblzma internally, etc). There may be some transitive dependencies that come along with that, but not nearly as many as things that were statically linked inside, and for the latter there are no exported symbols that are affected and the client is free to not care, or even to use a different version of the same library for their own (unrelated) purposes. Of course, this is marginally supported even today (only Now, I would love to capture all of this in some full_package_id at I have some thoughts on how that might work better but this probably isn't the place for detailed speculation. I'm thinking some kind of a binary alias to complement the existing support for recipe aliases, that was an actual artifact to upload, download and cache, under its package_id, which could have a conaninfo.txt that provided the missing profile information needed to resolve the newly-revealed transitive dependencies. |
No, it will affect both cases, defining build_requires in recipes and in the profiles. The only thing that is not covered is environment variables, but that is not connected to this proposal. Environment variables are not connected to the build_requires, and they do not currently affect the |
I don't think the current proposal is opposed at all to having a better I totally understand there could be in the past some problems like conan-io/conan#4753, that deserves some attention into the new dependencies model for Conan 2.0. Maybe if we can come up with a good modeling for that situation, this proposal wouldn't necessarily be a problem for your use case, I'll follow up on that issue, try to understand it better and gather feedback. |
If you only intend to fetch the recipes listed in build_requires, but not apply settings/options to them, or use their configure()/package_id() as requirements do, then I guess I can can retract my downvote. The recipes are readily identifiable without getting into the messy question that scared me (that transitive build_requires may well belong to neither the current package's host profile, nor the consumer's build profile). So if they were to affect package_id, they could only do so as far as full_recipe_mode, not full_package_mode (or more). |
|
||
This approach would solve the above issues. It will have some other potential issues: | ||
|
||
- It might be slightly less efficient, as it might need to resolve some extra recipes as ``cmake/3.14`` that wouldn’t be strictly necessary otherwise. But only the recipes will be necessary, downloading and unzipping the potentially heavy binary packages can still be avoided, so the impact on the overall time might be negligible. In practice, it could suppose and average penalty of around 1-2% of the installation of a graph with existing binaries (much less if something is built from sources) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As we identified earlier the recipe resolution is a bottleneck :( (when there is no cache, as in some CI configurations).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recipe resolution of a large dependency graph can take some time. But in the context of the build_requires
, it is not like projects are having hundreds of different build requirements, but just a very few of them (cmake and similar tools), while we are aware of many users having dependency graphs with hundreds of dependencies. So fetching those build-requires should be relatively small compared with the resolution of the whole graph. Do you have tons of different build_requires in the same graph?
On the other hand, it is possible that a simplified dependency resolution could help in some tasks like parallelizing some tasks in it, and maybe speeding it up too.
The problem is transitive dependencies. Even if I remove (say) CMake from the hash it will leave its requirements (like OpenSSL and bzip). The second issue is that build requirements are affected by profiles which makes it hard to uncontrol. If on some particular machine you need some extra package to build (for example sysroot for other linux distro or so) which is in some local profile then all packages will need to be rebuilt (not nice when they are expected to be built by CI). I think proposal is fine as long as it's off by default and needs to be opted in in some convenient way. BTW, examples of Android NDK sound more like a wrong set of settings... This way all ABI settings like compiler etc can be removed by just depending on a compiler package... |
|
||
- It might be slightly less efficient, as it might need to resolve some extra recipes as ``cmake/3.14`` that wouldn’t be strictly necessary otherwise. But only the recipes will be necessary, downloading and unzipping the potentially heavy binary packages can still be avoided, so the impact on the overall time might be negligible. In practice, it could suppose and average penalty of around 1-2% of the installation of a graph with existing binaries (much less if something is built from sources) | ||
- It requires the ``build_require`` recipes to be accessible and available in different stages, for example, if recipes are copied from one server to another one, it is necessary to copy too those ``build_requires``, if later we plan to do a ``conan install``. Note that if the ``build_require`` is injected via the profile, it would be enough to not pass it in the profile, and it will not be necessary (but in this case the binaries ``package_id`` should be independent of the ``build_requires``). Also note that in many cases this is not necessarily a disadvantage, but desired behavior, as it allows full build reproducibility from the new server too. | ||
- It can resolve to invalid binaries in some configurations, but this can be a non-fatal condition. For example, when cross-building. Let's say that we have a cross-compiler "mygcc-arm/1.2" that works in Windows and can cross-compile for Linux arm architecture. If this is a ``build_require``, in Windows we could use a ``conan create . -pr:h=LinuxArm -pr:b=Windowsx86`` with the build and host profiles. Once the binaries are built, we could go to a Linux box and do ``conan install … -pr:h=LinuxArm``, but the binary for the cross-compiler “mygcc-arm/1.2” will not exist for that platform, again this is not necessarily an error. The binary can simply be marked as INVALID by the ``validate()`` method, and unless we tried to build, it would still be possible to install and use the desired binaries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but the binary for the cross-compiler “mygcc-arm/1.2” will not exist for that platform,
It's not that binary doesn't exist. It's that the build requirement is completely missing (didn't come with profile). So I assume hash will be different. Or do I miss something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the build_requirement
declaration is technically there. For most situations it is more than enough to know the version of it, in that example, lets say that you know that you want to rebuild binaries if your compiler bumps the major, to something like mygcc-arm/2.0
. Then you declare a major_mode
on that build-requirement.
If you are installing in Linux, you will not have a binary that can run in Linux, but you will still know the version, even down to the recipe revision of mygcc-arm/1.2
and you will know that you don't need new binaries, and don't need to fetch the whole mygcc-arm/1.2
package binaries because you don't need to build. But you know that the version is 1.2
, and everything fits, with just the declaration of that package without needing its full binaries.
Please let me know if this clarifies it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really.
When I build package with 2 profiles I have a bunch of build requirements coming from it.
When I consume a package I don't specify any build profile therefore I have no build requirements => different graph => different package id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is up to you. If you want that behavior, then you can have it, as by default build_requirements will not be automatically added to the package_id
. Basically do nothing, and you will not have a different package_id
when your build_requires are added by a profile or when they are not. If at some point you want to control it and decide that changing some of your build_requires and upgrading it to a newer version should automatically guarantee that packages using that build requires must be rebuilt, then you can add it to the package_id
policy. From that time, yes, you should declare your build_requires in your profiles even if you don't intend to build, because that declaration is necessary to define which binaries to install.
Yes, I also think it is necessary to have ways to model this
Not necessarily. Users will be able to define the logic they want, so if they don't want to rebuild packages, they will not have to do it. And they will be able to define under which conditions their packages need to be rebuilt when build-requires change.
Yes, the proposed default is off by default, and users will be able to opt-in if they want, with the |
Ok great. I didn't realize that seeing
Since a
I'm not familiar with this. Sounds like a new kind of profile, whose change to env vars would affect the
Perhaps you're right, but It all seems connected in my mind. We need a model of how build requirements affects the "identity" of the resulting package (i.e. |
It is a convention based on the version of the
Yes, at the moment the current model is It is kind of clear that adding env-vars to the It is possible that |
Yeah you're right. I think what you'd have to do is consider a profile an injectable You're also right that the I'll read up on |
Well, the idea is that this would be configurable, as it is already (in recipes for example) for normal requires. And users will be able to define which |
Sounds good. Upvoted! |
I think I got confused by package id mode: it was recommended by Conan developers (on trainings too) to use something like However I subconsciously missed 2 things:
Not sure if above realization helps anyone else, but it helped me 😊. |
@memsharded how will this proposal impact the following problem with packages "A" (shared lib), "B" (static lib), and "C" (executable) and different compiler runtimes
Scenario 1: functions from static libraries not exported further
Scenario 2: functions from static libraries are exported
Will this proposal help here and how? |
No, this proposal is not about library requirements to link other libraries or applications. This proposal is strictly about It is true that the relationship of static, shared and executables and static linking needs to be revisited, but that is intended to be represented by the Please let me know if this clarifies it. |
@memsharded it's clear now, thanks. |
It seems the feedback and voting is compelling enough. |
I realize, that you've merged this now, but I also wanted to add my two cents. What we see now, that parts of our organization start collaborating with other companies, using conan. However, only binary releases will be distributed (no source code), and I see that this might make collaboration more complicated. It seems that organization will need to repackage their binaries with different conanfiles, if they like to hide implementation detail. Which brings me of the point, that with conan, it's often not clear to me, which in formation is relevant for the build only, and which part is relevant for the consumer So maybe keep this collaboration usecase in mind, and let's see where this goes 😄 |
Yes, certainly this is one of the possible things that the new approach needs to handle somehow, and it is described in the proposal document as the "need to actually have at least the recipes" available when the graphs are resolved. It might be a possibility that for many cases it is good enough to promote just the recipes, but not the binaries, and consumers will be able to use them even if they cannot resolve those binaries, because they will be missing. Seems that it could make sense in many cases to have a complete definition of the things that are being pulled, even if not having access to binaries and couldn't reproduce the build. Of course, it this needs to be completely hidden, it could be that the re-packaging approach makes more sense, and the model could try to introduce something that makes the re-packaging a bit more explicit. Thanks very much for the feedback, it is useful, we will keep this case in mind. |
Whenever the Conan dependency graph is evaluated and computed, all the transitive dependencies will be computed, including
build_requires
and their transitive dependencies. This includes many commands such asconan create
,conan install
,conan info
, andconan lock
among others.One of the main advantages is that the
build_requires
will be able to affect the consumerspackage_ids
in a controlled way (with different modes, selectable by users, as with current requirespackage_id_modes
), and thus be part of Continuous Integration flows, forcing re-build of consumers when desired. On the other hand it will require thebuild_require
recipes to be available to construct the dependency graph, and might produce some (likely very small, like 1-2% on average) more time to build the graph, and even much less if we factor the binaries, as by default the binaries will not be necessary to be downloaded.Please note, as explained in the proposal, that it is not possible to have both. If we want the
build_requires
to be taken into account for thepackage_id
computation, they must be always in the graph. And if we wantbuild_requires
not to be in the graph if not necessary, then, they cannot be part of thepackage_id
.