Gentoo Archives: gentoo-dev

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

Attachments

File name MIME type
signature.asc application/pgp-signature

Replies