-
Notifications
You must be signed in to change notification settings - Fork 349
/
depexts-plugins
115 lines (91 loc) · 5.39 KB
/
depexts-plugins
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
Proposal for a plugin architecture for supporting checking and resolving
of external dependencies (depexts) in OPAM > 1.2
========================================================================
Rationale
---------
The opam package metadata now contains a specific field for declaring
dependencies on external packages handled through external package managers
(typically, distribution and OS dependent, but may in general be any other
package manager).
There are two main functionalities that are needed:
- checking whether external dependencies are satisified at a given moment; this
is an operation that can be implemented in linear time (we are just checking
whether a boolean formula is true or false); since external packages are
managed outside opam, this check needs to be performed at the beginning of
each opam run, to discover packages that are no longer functional, and report
the issue to the user.
With proper, OS specific integration, this operation can be made blazingly fast;
a simple hack, calling an external command each time, may be functionally equivalent,
but quite slow.
- finding a way of satisfying external dependencies required by a set of opam
packages; this is potentially much more expensive, it involves not only a
dependency solving phase, but also the fetch and installation phase, and
requires proper interfacing with the existing OS specific package manager.
This should be done only when modifying or fixing an opam configuration and
after asking user confirmation.
Making things work smoothly and efficiently requires OS specific knowledge that
is best found among experienced users of each OS, which may be different people,
with different knowledge of Opam internals: a well designed plugin
infrastructure can separate concerns and facilitate contributions.
Proposal
--------
It is proposed to create a plugin architecture for OS specific external
dependencies, extending the following module signature for the modules
implementing a plugin
module type OSDependencyLayer =
sig
type depexts (* external dependencies, a CNF involvin OS-specific stuff *)
type actions (* an abstract token corresponding to actions, and a textual
representation of them to present to the user *)
type explanations (* in case the depexts cannot be satisfied, explain why *)
type result = Can of actions | Cannot of explanations
type outcome (* result of the execution of the OS-specific actions *)
val satisfied : depexts -> bool (* are the depexts already satisfied ? *)
val cansatisfydepexts : depexts -> result
val perform : actions -> outcome
end
Notice that there are two distinct sets of functions for the very different
cases outlined above:
- satisfied performs just a check to see whether depexts are already satisfied
- cansatisfydepexts tries to solve the external dependencies, and returns a proposed action,
or an explanation for the failure, while perform executes the actions (typically
after user confirmation)
The proposed module interface is intentionally incomplete, as it makes no assumption
on the way in which plugins are identified, and registered, which is an orthogonal
issue.
Note on OCaml detection
-----------------------
The OCaml compiler itself is an external dependency when using "system"
switches. It's currently handled by a specific, dynamically generated compiler
definition, with some ad-hoc code to treat it specifically, or check that it
didn't change at startup time.
With the current trend to move compiler handling to packages, the above won't
work anymore, because "system" would now need to be a specific, dynamic package.
While re-implementing the system switch hacks in this context would certainly be
possible, having the depexts mechanism flexible enough to handle all this
consistently would certainly be more consistent and easier to maintain.
Here is a possibility: having an 'ocaml-system' package (that would "provide"
ocaml) with depext on the system ocaml.
* the package needs to be able to export some environment variables that are
currently exported by the switch (`CAML_LD_LIBRARY_PATH`).
* a change of this package should be detected at OPAM startup -- like for any
depexts
* "system" compilers currently don't have to be managed by the OS, they are just
looked for in the PATH. Keeping this would probably require a specific (lower
level) "depext" plugin, that wouldn't have the functionalities to install the
depext.
* this raises a new, but valid, concern: the above handles a binary state for
depexts, while for this, we'd need to detect changes also. Creating one
'ocaml-system' package version for each possible compiler version may be an
answer: on system compiler change, the installed 'ocaml-system' becomes
invalid, and you'll need to replace it by the fitting version (recompiling all
dependent packages as you go).
* However, it sounds quite difficult to hold a middle ground between
- "resolve with all OPAM packages installable, then check and handle their
depexts", and
- "check depexts, and then resolve with OPAM packages that can be installed
with what's currently on the system;" (don't install them, except on
conflict (how exactly?))
and the above won't play well with first option here, second option raising
many more questions.
Maybe this doesn't fit well with depexts, but it's worth considering