Hi, TLDR: Guillem is right, I'm wrong. Please leave everything as it is. :)
I came to the conclusion that the meaning/semantics of the new syntax can best be summarized as: - by default no build profile is set - multiple build profiles can be activated at the same time - the restriction syntax is an ordered list of statements that govern whether or not a build dependency is kept - an exclamation mark in front means: "drop build dependency if the profile indicated by the following statement is set" - no exclamation mark in front means: "keep build dependency if the profile indicated by the following statement is set" - processing is done from left to right - the first statement for which a profile is set, applies the rule and stops further evaluation of other items in the list - if the list has been processed and for no statement a profile was set, keep the build dependency if at least one statement in the list has an exclamation mark in front, otherwise drop the build dependency The following should only be consumed with enough time at hand and might not make any sense at all. It does to me so I'm posting it in the hope it might be found useful by someone. Otherwise the above actually says it all. The below gives some reason of why this makes sense by linking the meaning of the syntax to how it is done in Gentoo with USE flags. Quoting Guillem Jover (2014-02-08 02:02:21) > > In your test cases I see that for "dep3 <!profile.stage1 profile.notest>" > > with profiles stage1 and notest both activated, dep3 does not get picked. > > Right (although I rearranged it so that it gets picked now, and I guess > that could be considered cheating :), I should probably add another case > demonstrating it being dropped. Yes, I think that would make things clearer. With your solution, order of the qualifiers matters. With DEB_BUILD_PROFILE="stage1 notest": this would be dropped: dep3 <!profile.stage1 profile.notest> but this would get picked: dep3 <profile.notest !profile.stage1> I find it very hard to visualize the logical reason for that in my head. Let me express in words what both of the above mean. The first: drop dep3 if we build with stage1. If we dont build with stage1, then also check if we build with notest. If we dont build with notest then drop dep3, otherwise keep it. The second: keep dep3 if we build with notest. If we dont build with notest, then also check if we build with stage1. If we do build with stage1 then drop dep3, otherwise keep it. > Sure. The issue with the disjunction is that adding a new negated restriction > is not safe anymore, in the common case of building with just one profile, > and no mixed positive/negative restrictions. What tripped me, was the dep1 in > the 2/4 and 3/4 cases. > > Say, you don't want a specific dependency on profile.stage1, you have: > > dep1 <!profile.stage1> > > it gets reduced fine if only profile.stage1 is specified, but then if > you decide you don't want it either on profile.other, then: > > dep1 <!profile.stage1 !profile.other> > > will make dep1 suddenly start appearing on profile.stage1. > > This means, that adding negations to an existing negated restriction is > not safe any longer, because it has side effects, and to get the old > behaviour you need to know what other restrictions are in place for > each dependency where profile.stage1 appears so that they can be > specified as part of the build. This seems highly undesirable to me. > > If this analysis is wrong, I'd like to hear, or if you have a solution > to that specific problem, I'd gladly revert to a nicer implementation > that could support also positive/negative restrictions nicely. I see what you mean. So lets do it the other way round and lets make a table on what we can probably agree upon would intuitively be the right meaning: "" "stage1" "notest" "stage1 notest" foo <!profile.stage1> keep drop keep drop foo <profile.stage1> drop keep drop keep Is the above meaning okay with everybody? Here the more difficult ones: "" "stage1" "notest" "stage1 notest" foo <!profile.stage1 !profile.notest> keep drop drop drop foo <profile.stage1 profile.notest> drop keep keep keep If I didnt miss anything, then the above tables match exactly the current implementation in dpkg by Guillem. It should probably stay that way. It must be noted that my implementation did not result in the above tables and thus introduces confusion. And here the tricky one: dep3 <!profile.stage1 profile.notest> When reading that out loud, what does it say: drop if we build with stage1 and keep if we build with notest. I'm at a loss what this should mean even for the most simple setup of "no profile specified at all". When no profile is specified then surely "notest" is not specified so we should drop it. But with no profile "stage1" is also not specified so we should not not drop it (i.e keep it). While pondering about this I remembered Gentoo and its USE flags. Surely it would help to see how they solve this. In gentoo it's the other way round (in both: meaning and ordering). First they do write which condition to check for and then the dependency to install like this: jpeg? ( media-libs/jpeg ) Meaning: if we build with the USE flag jpeg set to true, then depend on media-libs/jpeg. This can also be be negated: !nophysfs? ( dev-games/physfs ) Meaning: if we build with the USE flag nophysfs set to false, then depend on dev-games/physfs. It can also be (infinitely) nested: jpeg? ( !nophysfs? ( dev-games/physfs ) ) So first the USE flag jpeg is checked and if it's true, then nophysfs is checked and upon that result, depend on dev-games/physfs or not. If jpeg was set to false, then no further check would be done and no dependency on dev-games/physfs would be added. Lets translate the last example to build profiles: physfs <!profile.nojpeg profile.physfs> Notice the translation of jpeg->nojpeg and nophysfs->physfs. This is because build profiles work in the opposite direction compared to USE flags. So if the build profile "nojpeg" was given, then the dependency on physfs would be dropped and no further check would be done. If "nojpeg" was not listed, then a check for "physfs" would be done. If physfs was set, then the dependency would be added and if not, it would be dropped. I hope you can see how this allows to interpret the list of mixed positive and negative build profiles as it is done by Gentoo USE flags? Just the other way round because an enabled USE flag means the addition of a dependency and an enabled build profile means its removal. The '!' works the other way round in build profiles compared to USE flags. For build profiles, an exclamation mark means "drop if this is set". For USE flags an exclamation mark means "drop if this is not set". Lets see if this rule still fulfills above tables. I translate stage1->full and notest->test. Debian: dep3 <!profile.stage1> Gentoo: full? ( dep3 ) If a full build is done, depend on dep3. Both agree on that. Debian: dep3 <profile.stage1> Gentoo: !full? ( dep3 ) If no full build is done, depend on dep3. Correct. Now it becomes hairy: Debian: dep3 <!profile.stage1 !profile.notest> Gentoo: full? ( test? ( dep3 ) ) In the table above we agreed that dep3 should be dropped once either stage1 or notest or both are activated. The Gentoo statement means that dep3 should only be included if *both* full and test USE flags are set. If either or both of them are false, the dependency on dep3 is dropped. I hope you can see how this makes those statements equivalent? Debian: dep3 <profile.stage1 profile.notest> Gentoo: !full? ( !test? ( dep3 ) ) In the table above we agreed that dep3 should be kept only once either stage1 or notest or both are activated. The Gentoo statement means that dep3 should only be included if *both* full and test use flags are *not* set. If either or both of them are true, then the dependency is dropped. I hope this makes sense? And now to the tricky mixed ones: Debian: dep3 <!profile.stage1 profile.notest> Gentoo: full? ( !test? ( dep3 ) ) Lets recall how I described the Debian statement initially: Drop dep3 if we build with stage1. If we dont build with stage1, then also check if we build with notest. If we dont build with notest then drop dep3, otherwise keep it. Lets do the same for the Gentoo statement: Drop dep3 if we dont do a full build (no need to check test). If we dont do a full build, then also check if we build with test. If we dont build with test then add dep3, otherwise drop it. I hope this still all makes sense. The last part can equivalently be applied to the reverse situation. So at least for me, the build profile syntax is now abundantly clear. Order matters and it is important that it does. Maybe this was actually helpful for somebody to understand why it makes sense to treat things as they are now treated and I hope I didnt waste anybodies time. cheers, josch -- To UNSUBSCRIBE, email to debian-dpkg-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/20140209001639.3663.87935@hoothoot