{"id":1090,"date":"2020-02-10T08:39:03","date_gmt":"2020-02-10T07:39:03","guid":{"rendered":"http:\/\/blogs.gentoo.org\/mgorny\/?p=1090"},"modified":"2020-02-21T11:29:42","modified_gmt":"2020-02-21T10:29:42","slug":"no-more-python_targets-in-single-r1","status":"publish","type":"post","link":"https:\/\/blogs.gentoo.org\/mgorny\/2020\/02\/10\/no-more-python_targets-in-single-r1\/","title":{"rendered":"No more PYTHON_TARGETS in single-r1"},"content":{"rendered":"<p>Since its inception in&nbsp;2012, python-single-r1 has been haunting users with two sets of&nbsp;USE flags: <kbd>PYTHON_TARGETS<\/kbd> and&nbsp;<kbd>PYTHON_SINGLE_TARGET<\/kbd>.  While this initially seemed a&nbsp;necessary part of&nbsp;the&nbsp;grand design, today I know we could have done better.  Today this chymera is disappearing for real, and&nbsp;python-single-r1 are going to use <kbd>PYTHON_SINGLE_TARGET<\/kbd> flags only.<\/p>\n<p>I would like to take this opportunity to&nbsp;explain why the&nbsp;eclass has been designed this way in&nbsp;the&nbsp;first place, and&nbsp;what has been done to&nbsp;change that.<br \/>\n<!--more--><\/p>\n<h2>Why PYTHON_SINGLE_TARGET?<\/h2>\n<p>Why did we need a&nbsp;second variable in&nbsp;the&nbsp;first place?  After all, we could probably get away with using <kbd>PYTHON_TARGETS<\/kbd> everywhere, and&nbsp;adding an&nbsp;appropriate <kbd>REQUIRED_USE<\/kbd> constraint.<\/p>\n<p>Back in&nbsp;the&nbsp;day we have established that for users&#8217; convenience we need to default to&nbsp;enabling one version of&nbsp;Python&nbsp;2 and&nbsp;one version of&nbsp;Python&nbsp;3.  If we enabled only one of&nbsp;them, the&nbsp;users would end up having to&nbsp;enable the&nbsp;other for a&nbsp;lot of&nbsp;packages.  On&nbsp;the&nbsp;other had, if&nbsp;we combined both with using PT for&nbsp;single-r1 packages, the&nbsp;users would have to <em>disable<\/em> the&nbsp;extra implementation for a&nbsp;lot of&nbsp;them.  Neither option was good.<\/p>\n<p>The&nbsp;primary purpose of&nbsp;<kbd>PYTHON_SINGLE_TARGET<\/kbd> was to&nbsp;provide a&nbsp;parallel sensible setting for those packages.  It was not only to&nbsp;make the&nbsp;default work out of&nbsp;the&nbsp;box but also to&nbsp;let users change it in&nbsp;one step.<\/p>\n<p>Today, with the&nbsp;demise of&nbsp;Python&nbsp;2 and&nbsp;the&nbsp;effort to remove Python&nbsp;2 from default PT, it may seem less important to&nbsp;keep the&nbsp;distinction.  Nevertheless, a&nbsp;number of&nbsp;developers and&nbsp;at&nbsp;least some users keep multiple versions of&nbsp;Python in&nbsp;PT to&nbsp;test their packages.  Having PST is still helpful to&nbsp;them.<\/p>\n<h2>Why additional PYTHON_TARGETS then?<\/h2>\n<p>PST is only half of&nbsp;the&nbsp;story.  What I explained above does not justify having <kbd>PYTHON_TARGETS<\/kbd> on&nbsp;those packages as&nbsp;well, and&nbsp;a&nbsp;REQUIRED_USE constraint to&nbsp;make them superset of&nbsp;enabled PST.  Why did we need to have two flag sets then?<\/p>\n<p>The&nbsp;answer is: <kbd>PYTHON_USEDEP<\/kbd>.  The&nbsp;initial design goal was that both python-r1 eclasses would use the&nbsp;same approach to&nbsp;declaring USE dependencies between packages.  This also meant that this variable must work alike on&nbsp;dependencies that are multi-impl and&nbsp;single-r1 packages.  In&nbsp;the&nbsp;end, this meant a&nbsp;gross hack.<\/p>\n<p>Without getting into details, the&nbsp;currently available USE dependency syntax does not permit directly depending on&nbsp;PT flags based on&nbsp;PST-based conditions.  This needs to be done using the&nbsp;more verbose expanded syntax:<\/p>\n<pre><code>pst2_7? ( foo[pt2_7] )\r\npst3_7? ( foo[pt3_7] )<\/code><\/pre>\n<p>While this was doable back in&nbsp;the&nbsp;day, it was not possible with <kbd>PYTHON_USEDEP<\/kbd>-based approach.  Hence, all single-r1 packages gained additional set of&nbsp;flags merely to&nbsp;construct dependencies conveniently.<\/p>\n<h2>What is the&nbsp;problem with that?<\/h2>\n<p>I suppose some of&nbsp;you see the&nbsp;problem already.  Nevertheless, let&#8217;s list them explicitly.<\/p>\n<p>Firstly, enabling additional implementations is inconvenient.  Whenever you need to do that, you need to&nbsp;add <em>both<\/em> PST and&nbsp;PT flags.<\/p>\n<p>Secondly, the&nbsp;PT flags are entirely redundant and&nbsp;meaningless for&nbsp;the&nbsp;package in&nbsp;question.  Whenever your value of&nbsp;PT changes, all single-r1 packages trigger rebuilds even if their PST value stays the&nbsp;same.<\/p>\n<p>Thirdly, the&nbsp;PT flags <em>overspecify<\/em> dependencies.  If&nbsp;your PT flags specify multiple implementations (which is normally the&nbsp;case), all dependencies will also have to be&nbsp;built for those interpreters even though PST requires only one&nbsp;of&nbsp;them.<\/p>\n<h2>The&nbsp;solution<\/h2>\n<p>The&nbsp;user-visible part of&nbsp;the&nbsp;solution is that <kbd>PYTHON_TARGETS<\/kbd> are disappearing from&nbsp;single-r1 packages.  From now on, only <kbd>PYTHON_SINGLE_TARGET<\/kbd> will be necessary.  Furthermore, PT enforcement on&nbsp;dependencies (if&nbsp;necessary) will be&nbsp;limited to the&nbsp;single implementation selected by&nbsp;PST rather than all of&nbsp;PT.<\/p>\n<p>The&nbsp;developer-oriented part is that <kbd>PYTHON_USEDEP<\/kbd> is no&nbsp;longer valid in&nbsp;single-r1 packages.  Instead, <kbd>PYTHON_SINGLE_USEDEP<\/kbd> is provided for&nbsp;dependencies on&nbsp;other single-r1 packages, and&nbsp;<kbd>PYTHON_MULTI_USEDEP<\/kbd> placeholder is used for&nbsp;multi-impl packages.  The&nbsp;former is available as&nbsp;a&nbsp;global variable, the&nbsp;latter only as&nbsp;a&nbsp;placeholder in&nbsp;<kbd>python_gen_cond_dep<\/kbd> (the&nbsp;name is a&nbsp;bit of&nbsp;misnomer now but I&#8217;ve decided not to&nbsp;introduce additional function).<\/p>\n<p>All existing uses have been converted, and&nbsp;the&nbsp;eclasses will now fail if&nbsp;someone tries to use the&nbsp;old logic.  The&nbsp;conversion of&nbsp;existing ebuilds is rather simple:<\/p>\n<ol>\n<li>Replace all <kbd>${PYTHON_USEDEP}<\/kbd>s with <kbd>${PYTHON_SINGLE_USEDEP}<\/kbd> when the&nbsp;dep is single-r1, or&nbsp;with <kbd>${PYTHON_MULTI_USEDEP}<\/kbd> otherwise.<\/li>\n<li>Wrap all dependencies containing <kbd>${PYTHON_MULTI_USEDEP}<\/kbd> in&nbsp;a&nbsp;<kbd>python_gen_cond_dep<\/kbd>.  Remember that the&nbsp;variable must be a&nbsp;literal placeholder, i.e. use single quotes.<\/li>\n<\/ol>\n<p>An example of&nbsp;the&nbsp;new logic follows:<\/p>\n<pre><code>RDEPEND=\"\r\n  dev-libs\/libfoo[python,${PYTHON_SINGLE_USEDEP}]\r\n  $(python_gen_cond_dep '\r\n    dev-python\/foo[${PYTHON_MULTI_USEDEP}]\r\n    dev-python\/bar[${PYTHON_MULTI_USEDEP}]\r\n  ')\r\n\"<\/code><\/pre>\n<p>If you get the&nbsp;dependency type wrong, repoman\/pkgcheck will complain about bad dependency.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Since its inception in&nbsp;2012, python-single-r1 has been haunting users with two sets of&nbsp;USE flags: PYTHON_TARGETS and&nbsp;PYTHON_SINGLE_TARGET. While this initially seemed a&nbsp;necessary part of&nbsp;the&nbsp;grand design, today I know we could have done better. Today this chymera is disappearing for real, and&nbsp;python-single-r1 are going to use PYTHON_SINGLE_TARGET flags only. I would like to take this opportunity to&nbsp;explain &hellip; <a href=\"https:\/\/blogs.gentoo.org\/mgorny\/2020\/02\/10\/no-more-python_targets-in-single-r1\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;No more PYTHON_TARGETS in single-r1&#8221;<\/span><\/a><\/p>\n","protected":false},"author":137,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[11],"tags":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/1090"}],"collection":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/users\/137"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/comments?post=1090"}],"version-history":[{"count":5,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/1090\/revisions"}],"predecessor-version":[{"id":1101,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/posts\/1090\/revisions\/1101"}],"wp:attachment":[{"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/media?parent=1090"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/categories?post=1090"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.gentoo.org\/mgorny\/wp-json\/wp\/v2\/tags?post=1090"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}