Gentoo Archives: gentoo-dev

From: Alexis Ballier <aballier@g.o>
To: gentoo-dev@l.g.o
Subject: Re: [gentoo-dev] [RFC] Forced/automatic USE flag constraints (codename: ENFORCED_USE)
Date: Mon, 05 Jun 2017 17:24:49
Message-Id: 20170605192433.6238797b@gentoo.org
In Reply to: Re: [gentoo-dev] [RFC] Forced/automatic USE flag constraints (codename: ENFORCED_USE) by "Michał Górny"
1 On Mon, 05 Jun 2017 16:10:25 +0200
2 Michał Górny <mgorny@g.o> wrote:
3
4 > On pon, 2017-06-05 at 09:55 +0200, Alexis Ballier wrote:
5 > > On Sun, 4 Jun 2017 10:59:38 +0200
6 > > Alexis Ballier <aballier@g.o> wrote:
7 > >
8 > > > Here's a quick n dirty code to play with, based on yours:
9 > > > https://github.com/aballier/required-use
10 > >
11 > > I've run that on the whole tree (considering all ebuilds with non
12 > > empty REQUIRED_USE), some stats:
13 > >
14 > > $ time python3 classify.py requsel
15 > > Stats:
16 > > Parse error: 16
17 >
18 > Hmm, how did you get those numbers? I just tested parsing and found
19 > only 7 unique REQUIRED_USE entries that fail. However, my sample file
20 > is only around 1000 entries long, so either I failed to get all of
21 > them, or you didn't deduplicate your list ;-). More on it below.
22
23 I did not deduplicate anything. I took every single ebuild and
24 generated a list of req use out of it. Meaning if you had 10 ebuilds
25 for 1 package with the same req use that'd count as 10 above.
26
27 [...]
28 > > The cycle is mostly due to:
29 > > $ python3 nsolve.py 'llvm? ( gallium ) gallium? ( llvm )'
30 > > [...]
31 > > toposort.CircularDependencyError: Circular dependencies exist among
32 > > these items: {[gallium]? => [llvm]:{[llvm]? => [gallium]}, [llvm]?
33 > > => [gallium]:{[gallium]? => [llvm]}}
34 > >
35 > >
36 > > This is something I had overseen when replacing 'a q'_j is some p_i
37 > > and one of q_1 ... q_m might be false' by only 'a q'_j is some
38 > > p_i'; it can be replaced without changing anything in the way PM
39 > > would solve it by "a q'_j is some p_i and the set of {q_j} is not a
40 > > subset of q' union p'" (that is, {q_i} is not trivially true if the
41 > > 2nd clause is applied). Extending that, we get those stats:
42 >
43 > I'm not even trying to understand the things you say with indexes but
44 > I trust you know what you're doing.
45
46 With that kind of things it's good to have someone having a second
47 look. It's so easy to forget a case or to miss a simplification.
48
49 > For completeness, we need to
50 > consider three cross-dependent states:
51 >
52 > a. a? ( b ) b? ( a )
53
54
55 that's exactly the above :p
56
57 {q_j} is {b}, {q'} is {a}, {p'} is {b}; {b} is a subset of {a} union
58 {b}
59
60
61 [...]
62 > b. !a? ( !b ) !b? ( !a )
63
64 that's also the above with s/!b/b/ s/!a/a/ :=)
65
66 > c. a? ( b ) !a? ( !b )
67
68 that's already handled.
69
70 [...]
71 > > I'll let you play with it, but for me it seems this would work quite
72 > > nicely.
73 > >
74 >
75 > Well, I guess it's time to hit the next level. For a start, we have to
76 > handle all-of groups, i.e.:
77 >
78 > ( a b c )
79 >
80 > Stand-alone makes little sense (and little trouble) but as you could
81 > have seen it's used nested in other thingies:
82 >
83 > 1. || ( ( a b ) ( c d ) e )
84 >
85 > 2. ?? ( ( a b ) ( c d ) e )
86 >
87 > 3. ^^ ( ( a b ) ( c d ) e )
88
89 Yeah that's the nesting problem causing a parse error.
90 Those should be expanded to implications. What I'm relying onto is all
91 clauses to be of the form '[list of conditions]? [list of constraints]'
92
93
94 > For verifying constraints, they are not bad. We just follow the
95 > generic rule that the branch evaluates to true if all subexpressions
96 > are true. 
97 >
98 > For solving, it might be a little unclear on how to proceed with
99 > partially true branches but for the sake of simplicity I would just
100 > ignore them and behave as if they were false. That is, case (1) with
101 > USE='c' would result in 'a b' being enabled.
102 >
103 > The practical uses I've seen are:
104 >
105 > a. || ( deprecated ( gtk3 introspection ) )
106 >
107 > I guess this one would be equivalent to:
108 >
109 > !gtk3? ( !introspection? ( deprecated ) )
110
111 Unfortunately no. Favoring leftmost, you need to enable 'deprecated'
112 when either gtk3 or introspection is false.
113
114 That'd be:
115 !gtk3? ( deprecated )
116 !introspection? ( deprecated )
117
118
119 Fortunately we can distribute \/ and /\:
120 || ( deprecated ( gtk3 introspection ) )
121 is equivalent to:
122 || ( deprecated gtk3 )
123 || ( deprecated introspection )
124
125 giving the above implication translation.
126
127 This can be extended to
128 || ( ( a1 a2 a3 ... ) ( b1 b2 b3 ... ) ... ) to handle all cases.
129
130
131
132 > b. ^^ ( ( !32bit 64bit ) ( 32bit !64bit ) ( 32bit 64bit ) )
133 >
134 > This looks like a crazy way of saying:
135 >
136 > || ( 32bit 64bit )
137
138 Hmm yes
139
140
141 > c. ^^ ( ( !ruby !s7 ) ( ruby !s7 ) ( !ruby s7 ) )
142 >
143 > This looks like an insane version of:
144 >
145 > ?? ( ruby s7 )
146
147
148 yes too it seems
149
150
151
152 > except that per my solver it just disables both when both are set ;-).
153
154 That's kind of the point. And that's why it is important to have the
155 solving rules well defined. Depending on how REQUIRED_USE is written,
156 it will be solved differently even for equivalent logical formulas.
157
158
159 > Not sure if the extra complexity is worth for roughly one valid use
160 > case, and a lot of insanity.
161
162 I think this can be done without too much pain. As you noticed, replace
163 '^^ ( whatever )' by '|| ( whatever ) ?? ( whatever )' so we're left
164 with only || and ?? (and 'and' denoted by space and grouping in our
165 notation).
166
167 || ( clause1 clause2 ... ) is replaced by
168 [!clause1 !clause2 ...]?[clause1]
169
170 ?? ( clause1 clause2 ... ) is replaced by:
171 [clause1]?[!clause2 !clause3 ...]
172 [!clause1]?[ ?? ( clause2 clause3 ... ) ]
173
174 ! (|| ( clause1 clause2 ... ) ) is '!clause1 !clause2 ...' (de morgan)
175 ! ( clause1 clause2 ... ) is '|| ( !clause1 !clause2 ... )' (de morgan
176 too)
177 ! (?? ( clause1 clause2 ... ) ) could be written as 'clause1? ( ||
178 ( clause2 ... ) ) !clause1? ( ! ?? ( clause2 ... ) )'
179
180 and I think that's it to allow expanding everything to implications.
181
182
183 [ begin || ( clause1 clause2 ... ) end ]?[constraint]
184
185 is:
186 [ begin clause1 end]?[constraint]
187 [ begin clause2 end]?[constraint]
188 etc.
189
190
191 [ begin ([icond]?[iconstraint]) end]?[constraint]
192 is:
193 [ begin icond]?[iconstraint]
194 [ begin end]?[constraint]
195
196 I think
197
198 and
199
200 [ begin ( clause1 clause2 ... ) end]?[constraint]
201 is
202 [ begin clause1 clause2 ... end]?[constraint]
203
204
205 [...]
206 > Of course past that there's a deeper insanity: all those constructs
207 > can be nested without limits. Verification is possible, solving maybe
208 > -- but I'm not sure if we even want to try to think what the correct
209 > solution would be.
210
211 We're good as long as they're rewritten as implications internally.
212
213
214 > There's only one use of this:
215 >
216 > ?? ( gl3plus ( || ( gles2 gles3 ) ) )
217
218 That'd be:
219 gl3plus? ( ! || ( gles2 gles3 ) )
220
221 per the above reduced to:
222 gl3plus? ( !gles2 !gles3 )
223
224 >
225 > FWICS, it probably works like this;
226 >
227 >  g       g    
228 >  l       l    
229 >  3 g g   3 g g
230 >  p l l   p l l
231 >  l e e   l e e
232 >  u s s   u s s
233 >  s 2 3 | s 2 3
234 >  0 0 0 | 0 0 0 (==)
235 >  0 0 1 | 0 0 1 (==)
236 >  0 1 0 | 0 1 0 (==)
237 >  0 1 1 | 0 1 1 (==)
238 >  1 0 0 | 1 0 0 (==)
239 >  1 0 1 | 1 0 1 [unsolvable due to loop]
240 >  1 1 0 | 1 1 0 [unsolvable due to loop]
241 >  1 1 1 | 1 1 1 [unsolvable due to loop]
242 >
243 > i.e. it would be equivalent to:
244 >
245 > gl3plus? ( !gles2 !gles3 )
246 >
247 > unless the author meant something else and failed.
248
249
250 Exactly. I don't know why you see a loop.
251
252
253 > The question is whether we want to:
254 >
255 > a. actually try to solve this nesting insanity,
256 >
257 > b. declare it unsupported and throw REQUIRED_USE mismatch on user,
258 >
259 > c. ban it altogether.
260
261
262 I don't think it is *that* insane to support nesting :)
263
264
265 Alexis.

Replies