There are currently two dependency models in Portage: 'static' dependencies and 'dynamic' dependencies.
Static dependency model is defined in the PMS and used by most other distributions. In this model, the dependencies listed in ebuild are used only when building the ebuild, and are stored in vardb after the package is installed or in the binary packages when it is built. In subsequent dependency resolutions the dependencies stored in vardb are re-used as long as the ebuild is not scheduled for rebuild.
Dynamic dependency model was added to Portage to make dependency propagation easier. In this model, Portage always tries to use the dependencies listed in ebuild for dependency resolution. If the package is installed and not scheduled for rebuild, Portage tries to match an ebuild file to it and use the dependencies from the ebuild file. Dependencies stored in vardb are used as fallback when no ebuild file is available or the dependencies stored in it can't be used.
Currently, Portage defaults to using the dynamic dependency model. The static model is used as fallback. Every other package manager uses the static model.
Each of the two dependency models relies on specific behavior from developers when updating dependencies in ebuild files. Having both models active implies that developers have to consider both, and therefore can't really take benefit of either model.
The table below describes when revision bumps need to be performed for a particular model of dependencies for users dependency trees not being broken.
|Issue||Static deps||Dynamic deps|
|Significant dependency change that needs to be propagated immediately (like missing runtime dep)||revbump + unnecessary rebuild||applied immediately (as long as dynamic-deps work)|
|Minor dependency change (unused dependency removed)||applied after rebuild||applied immediately (but can break hard when dynamic-deps stop working))|
|Minor linking change w/ dependency change (unnecessary linking removed)||applied after rebuild||revbump + mostly unnecessary rebuild|
|Removal of a USE flag along with the relevant dependencies||applied when disabling the flag||revbump + unnecessary rebuild|
As can be seen from the table, covering for both models implies that every dependency change — even unimportant — requires a revision bump. Additionally, the lack of guarantees in the dynamic model means that each dependency fix may not stop being applied in some cases, effectively causing visible regression.
Portage defaults to using the dynamic model. However, the static model is applied:
- when the ebuild in question uses the slot/subslot operator :=,
- when the ebuild in question is removed,
- if user disables dynamic dependencies (e.g. due to performance overhead),
- to users of other package managers.
To actually benefit from either of the models, it would have to be implemented and applied consistently.
Improve & spread dynamic-deps
In order to be able to properly rely on dynamic-deps, it would have to be supported by all package managers and in all common circumstances.
This specifically includes:
- documenting it in PMS and getting all package managers to implement it,
- handling the slot/subslot operator := — possibly by separating the matched slots/subslots from stored dependency atoms and forcing rebuild whenever new := dependency appears,
- updating vardb every time dependencies in ebuild change (possibly after installing the dependencies).
While this wouldn't solve all the issues, it would at least prevent the worst breakage possible (and regressions in applied dependencies).
The alternative is to disable dynamic-deps completely.
This specifically involves:
- disabling it and requesting users to upgrade portage :),
- patiently reminding developers that they must no longer rely on this behavior.
While this supposedly could result in more 'unnecessary' rebuilds and revbumps, it would allow the dependency tree to be more predictable. It will also speed up the dependency resolution in many cases.