summaryrefslogtreecommitdiff
blob: a08ec17fcd3ff930307557cce5412948643e7783 (plain)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />

    <title>Choosing between Python eclasses &#8212; Gentoo Python Guide  documentation</title>
    <link rel="stylesheet" type="text/css" href="_static/pygments.css" />
    <link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
    <script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
    <script src="_static/doctools.js"></script>
    <script src="_static/sphinx_highlight.js"></script>
    <link rel="index" title="Index" href="genindex.html" />
    <link rel="search" title="Search" href="search.html" />
    <link rel="next" title="Common basics" href="basic.html" />
    <link rel="prev" title="Python interpreters" href="interpreter.html" />
   
  <link rel="stylesheet" href="_static/custom.css" type="text/css" />
  
  
  <meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />

  </head><body>
  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          

          <div class="body" role="main">
            
  <section id="choosing-between-python-eclasses">
<h1>Choosing between Python eclasses<a class="headerlink" href="#choosing-between-python-eclasses" title="Permalink to this heading"></a></h1>
<section id="overview">
<h2>Overview<a class="headerlink" href="#overview" title="Permalink to this heading"></a></h2>
<p>The python-r1 eclass suite features 5 eclasses in total:</p>
<ol class="arabic simple">
<li><p><code class="docutils literal notranslate"><span class="pre">python-utils-r1.eclass</span></code> that provides utility functions common
to all eclasses.  This eclass is rarely inherited directly.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python-any-r1.eclass</span></code> that is suitable for packages using Python
purely at build time.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python-single-r1.eclass</span></code> that provides a base for simpler packages
installing Python scripts and alike.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python-r1.eclass</span></code> that provides a base for more complex packages,
particularly these installing Python modules.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">distutils-r1.eclass</span></code> that provides convenient phase functions
and helpers for packages that primarily involve installing Python
files.</p></li>
</ol>
<figure class="align-default" id="id1">
<img alt="_images/eclass.svg" src="_images/eclass.svg" /><figcaption>
<p><span class="caption-text">Inheritance graph of python-r1 suite eclasses.</span><a class="headerlink" href="#id1" title="Permalink to this image"></a></p>
</figcaption>
</figure>
<p>As a rule of thumb, the best eclass to use is the one that makes
the ebuild the simplest while meeting its requirements.  A more detailed
process involves:</p>
<ol class="arabic simple">
<li><p>Determining whether Python is used purely at build time,
or at runtime as well.  In the former case, <code class="docutils literal notranslate"><span class="pre">python-any-r1</span></code>
is the right choice.</p></li>
<li><p>Determining whether single-impl or multi-impl approach is more
appropriate.  For the former, <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code> is the correct
base eclass.  For the latter, <code class="docutils literal notranslate"><span class="pre">python-r1</span></code>.</p></li>
<li><p>Determining whether the ebuild benefits from using <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code>.
If it does, this eclass should be use instead (potentially along
with <code class="docutils literal notranslate"><span class="pre">DISTUTILS_SINGLE_IMPL</span></code> to switch the underlying eclass).</p></li>
</ol>
</section>
<section id="build-time-vs-runtime-use">
<h2>Build time vs runtime use<a class="headerlink" href="#build-time-vs-runtime-use" title="Permalink to this heading"></a></h2>
<p>The first basis for choosing Python eclass is whether Python is used
merely at build time or at runtime as well.</p>
<p>A runtime use occurs if the package explicitly needs Python to be
installed along with it, in order for it to function correctly.  This
generally happens if the package installs Python modules, extensions,
scripts, or executables calling the Python interpreter or linking
to libpython.  This also applies to bash scripts or other executables
that call python inline.</p>
<p>A build time use occurs if the package calls the Python interpreter
or any kind of aforementioned executables during package’s build
(or install) phases.</p>
<p>If the package uses Python purely at build time, the <code class="docutils literal notranslate"><span class="pre">python-any-r1</span></code>
eclass is appropriate.  Otherwise, <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code>, <code class="docutils literal notranslate"><span class="pre">python-r1</span></code>
or <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> are to be used.</p>
<p>A specific exception to that rule is when the package is only calling
external Python scripts directly (i.e. not via <code class="docutils literal notranslate"><span class="pre">python</span> <span class="pre">/usr/bin/foo</span></code>).
If the called executables can be considered fully contained
dependency-wise, there is no need to use an eclass.</p>
<p>For example, when using <code class="docutils literal notranslate"><span class="pre">dev-util/meson</span></code> to build a package, there is
no need to use a Python eclass since Meson abstracts away its Pythonic
implementation details and works as a regular executable for your
packages.  However, <code class="docutils literal notranslate"><span class="pre">dev-util/scons</span></code> requires Python eclass since it
loads Python code from the package and a compatible Python version must
be enforced.</p>
</section>
<section id="single-impl-vs-multi-impl">
<h2>Single-impl vs multi-impl<a class="headerlink" href="#single-impl-vs-multi-impl" title="Permalink to this heading"></a></h2>
<p>The second important basis for packages using Python at runtime is
whether the package in question should support multi-implementation
install or not.</p>
<p>A <em>single-impl</em> package is a package requiring the user to choose
exactly one Python implementation to be built against.  This means
that the scripts installed by that package will be run via specified
Python interpreter, and that the modules and extensions will be
importable from it only.  The package’s Python reverse dependencies will
also have to use the same implementation.  Since the package can’t
support having more than one implementation enabled, its reverse
dependencies have to be simple-impl as well.</p>
<p>Single-impl packages use <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code> eclass.  Writing ebuilds
for them is easier since it is generally sufficient to call setup
function early on, and the upstream build system generally takes care
of using selected Python version correctly.  Making packages single-impl
is recommended when dealing with packages that are not purely written
for Python or have single-impl dependencies.</p>
<p>A <em>multi-impl</em> package allows user to enable multiple (preferably
any number of) implementations.  The modules, extensions and scripts
installed by the package are installed separately for each enabled
implementation, and can therefore be used from any of them.  The package
can have reverse dependencies enabling only a subset of its
implementations.</p>
<p>Multi-impl packages use <code class="docutils literal notranslate"><span class="pre">python-r1</span></code> eclass.  Ebuilds are more complex
since they need to explicitly repeat build and install steps for each
enabled implementation.  Using this model is recommended for packages
providing Python modules or extensions only, or having multi-impl
reverse dependencies.  In some cases supporting multi-impl build
requires applying hacks, e.g. <code class="docutils literal notranslate"><span class="pre">dev-libs/boost[python]</span></code> uses
non-standard names to install <code class="docutils literal notranslate"><span class="pre">libboost_python</span></code> for multiple Python
versions.</p>
<p>The implementation for single-impl packages is selected
via <code class="docutils literal notranslate"><span class="pre">PYTHON_SINGLE_TARGET</span></code>, while multi-impl uses <code class="docutils literal notranslate"><span class="pre">PYTHON_TARGETS</span></code>.
These USE flag sets can be set independently to provide greater
flexibility for developers and end users.</p>
<p>Both single-impl and multi-impl installs are supported
by the <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> eclass.</p>
</section>
<section id="python-first-packages-distutils-r1-eclass">
<h2>Python-first packages (distutils-r1 eclass)<a class="headerlink" href="#python-first-packages-distutils-r1-eclass" title="Permalink to this heading"></a></h2>
<p>The third step in choosing the eclass for runtime use of Python
is determining whether the ebuild would benefit from <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code>.
This eclass is especially useful for packages that primarily focus
on providing Python content.  Its advantages include:</p>
<ul class="simple">
<li><p>adding appropriate dependencies and <code class="docutils literal notranslate"><span class="pre">REQUIRED_USE</span></code> by default</p></li>
<li><p>a sub-phase function mechanism that makes installing Python modules
in multi-impl mode easier</p></li>
<li><p>convenient support for building documentation using Sphinx
and running tests using common Python test runners</p></li>
</ul>
<p>In general, <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> should be preferred over the other eclasses
if:</p>
<ul class="simple">
<li><p>the package uses a PEP 517-compliant build system (i.e. has
a <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file with a <code class="docutils literal notranslate"><span class="pre">build-system</span></code> section)</p></li>
<li><p>the package uses a legacy distutils or setuptools build system
(i.e. has a <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> file)</p></li>
<li><p>the package primarily installs Python modules</p></li>
</ul>
<p>In general, for multi-impl packages <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> is preferred
over <code class="docutils literal notranslate"><span class="pre">python-r1</span></code> as it usually makes the ebuilds simpler.
For single-impl packages, <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code> can sometimes be simpler.</p>
</section>
</section>


          </div>
          
        </div>
      </div>
      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
        <div class="sphinxsidebarwrapper">
<h1 class="logo"><a href="index.html">Gentoo Python Guide</a></h1>








<h3>Navigation</h3>
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="preface.html">Preface</a></li>
<li class="toctree-l1"><a class="reference internal" href="interpreter.html">Python interpreters</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Choosing between Python eclasses</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#overview">Overview</a></li>
<li class="toctree-l2"><a class="reference internal" href="#build-time-vs-runtime-use">Build time vs runtime use</a></li>
<li class="toctree-l2"><a class="reference internal" href="#single-impl-vs-multi-impl">Single-impl vs multi-impl</a></li>
<li class="toctree-l2"><a class="reference internal" href="#python-first-packages-distutils-r1-eclass">Python-first packages (distutils-r1 eclass)</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="basic.html">Common basics</a></li>
<li class="toctree-l1"><a class="reference internal" href="any.html">python-any-r1 — build-time dependency</a></li>
<li class="toctree-l1"><a class="reference internal" href="single.html">python-single-r1 — single-impl packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="multi.html">python-r1 — multi-impl packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="distutils.html">distutils-r1 — standard Python build systems</a></li>
<li class="toctree-l1"><a class="reference internal" href="test.html">Tests in Python packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="distutils-legacy.html">distutils-r1 legacy concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="pypi.html">pypi — helper eclass for PyPI archives</a></li>
<li class="toctree-l1"><a class="reference internal" href="helper.html">Common helper functions</a></li>
<li class="toctree-l1"><a class="reference internal" href="depend.html">Advanced dependencies</a></li>
<li class="toctree-l1"><a class="reference internal" href="pytest.html">pytest recipes</a></li>
<li class="toctree-l1"><a class="reference internal" href="concept.html">Advanced concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="expert-multi.html">Expert python-r1 usage</a></li>
<li class="toctree-l1"><a class="reference internal" href="buildsys.html">Integration with build systems written in Python</a></li>
<li class="toctree-l1"><a class="reference internal" href="porting.html">Porting tips</a></li>
<li class="toctree-l1"><a class="reference internal" href="migration.html">Migration guides</a></li>
<li class="toctree-l1"><a class="reference internal" href="qawarn.html">QA checks and warnings</a></li>
<li class="toctree-l1"><a class="reference internal" href="package-maintenance.html">Python package maintenance</a></li>
<li class="toctree-l1"><a class="reference internal" href="interpreter-maintenance.html">Maintenance of Python implementations</a></li>
</ul>

<div class="relations">
<h3>Related Topics</h3>
<ul>
  <li><a href="index.html">Documentation overview</a><ul>
      <li>Previous: <a href="interpreter.html" title="previous chapter">Python interpreters</a></li>
      <li>Next: <a href="basic.html" title="next chapter">Common basics</a></li>
  </ul></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
  <h3 id="searchlabel">Quick search</h3>
    <div class="searchformwrapper">
    <form class="search" action="search.html" method="get">
      <input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
      <input type="submit" value="Go" />
    </form>
    </div>
</div>
<script>document.getElementById('searchbox').style.display = "block"</script>








        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="footer">
      &copy;2020, Michał Górny, license: CC BY 4.0.
      
      |
      Powered by <a href="http://sphinx-doc.org/">Sphinx 6.1.3</a>
      &amp; <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.13</a>
      
      |
      <a href="_sources/eclass.rst.txt"
          rel="nofollow">Page source</a>
    </div>

    

    
  </body>
</html>