summaryrefslogtreecommitdiff
blob: 9bba372740e837e66d7cfd8c2851bde771726063 (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
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
<!DOCTYPE html>

<html lang="en" data-content_root="./">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />

    <title>distutils-r1 — standard Python build systems &#8212; Gentoo Python Guide  documentation</title>
    <link rel="stylesheet" type="text/css" href="_static/pygments.css?v=d1102ebc" />
    <link rel="stylesheet" type="text/css" href="_static/basic.css?v=686e5160" />
    <link rel="stylesheet" type="text/css" href="_static/alabaster.css?v=27fed22d" />
    <script src="_static/documentation_options.js?v=5929fcd5"></script>
    <script src="_static/doctools.js?v=9bcbadda"></script>
    <script src="_static/sphinx_highlight.js?v=dc90522c"></script>
    <link rel="index" title="Index" href="genindex.html" />
    <link rel="search" title="Search" href="search.html" />
    <link rel="next" title="Tests in Python packages" href="test.html" />
    <link rel="prev" title="python-r1 — multi-impl packages" href="multi.html" />
   
  <link rel="stylesheet" href="_static/custom.css" type="text/css" />
  

  
  

  </head><body>
  

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

          <div class="body" role="main">
            
  <section id="distutils-r1-standard-python-build-systems">
<h1>distutils-r1 — standard Python build systems<a class="headerlink" href="#distutils-r1-standard-python-build-systems" title="Link to this heading"></a></h1>
<p>The <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> eclass is used to facilitate build systems using
<code class="docutils literal notranslate"><span class="pre">setup.py</span></code> (distutils and its derivatives, notably setuptools)
or <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> (flit, poetry).  It is built on top
of <code class="docutils literal notranslate"><span class="pre">python-r1</span></code> and <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code>, and therefore supports
efficiently building multi-impl and single-impl packages.</p>
<p>Eclass reference: <a class="reference external" href="https://devmanual.gentoo.org/eclass-reference/distutils-r1.eclass/index.html">distutils-r1.eclass(5)</a></p>
<section id="the-pep-517-and-legacy-modes">
<h2>The PEP 517 and legacy modes<a class="headerlink" href="#the-pep-517-and-legacy-modes" title="Link to this heading"></a></h2>
<p>The <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> eclass has currently two modes of operation:
the PEP 517 mode and the legacy mode.  The former mode should be
preferred for new ebuilds; the latter is provided for backwards
compatibility and packages that are incompatible with the other mode.</p>
<p>The PEP 517 mode uses backends as defined by <a class="reference external" href="https://www.python.org/dev/peps/pep-0517/">PEP 517</a> to build
packages.  It supports a greater number of Python build systems
at the cost of flexibility and performance.  In the eclass
implementation, the PEP 517 backend is used to build a wheel (i.e. a zip
archive) with the package and then an installer tool is used to install
the wheel into a staging directory.  The complete process is done
in compile phase, and the install phase merely moves the files into
the image directory.</p>
<p>The PEP 517 mode also features a ‘no build system’ mode for packages
that do not or cannot use a PEP 517-compliant build backend.</p>
<p>The legacy mode invokes the <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> script directly.  The build
command is invoked to populate the build directory in the compile phase,
then the install command is used in the install phase.  Normally, this
mode works only for packages using backwards-compatible distutils
derivatives.  Additionally, it supports flit and poetry through
pyproject2setuppy hack.  This mode relies on deprecated features.</p>
<p>The PEP 517 mode is enabled via declaring the <code class="docutils literal notranslate"><span class="pre">DISTUTILS_USE_PEP517</span></code>
variable.  The legal values can be found in the <a class="reference internal" href="#pep-517-build-systems">PEP 517 build
systems</a> section.  If unset, the legacy mode is used.</p>
</section>
<section id="basic-use-pep-517-mode">
<h2>Basic use (PEP 517 mode)<a class="headerlink" href="#basic-use-pep-517-mode" title="Link to this heading"></a></h2>
<p>By default, <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> sets appropriate metadata variables
and exports a full set of phase functions necessary to install packages
using Python build systems.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">DISTUTILS_USE_PEP517</span></code> variable is used to enable the modern
PEP 517 mode and declare the build system used.  The eclass
automatically generates a build-time dependency on the packages needed
for the build system.</p>
<p>The simplest case of ebuild is:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2022 Gentoo Authors</span>
<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>

<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">8</span>

<span class="hll"><span class="w"> </span><span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>setuptools
</span><span class="hll"><span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python3_<span class="o">{</span><span class="m">8</span>..10<span class="o">}</span><span class="w"> </span>pypy3<span class="w"> </span><span class="o">)</span>
</span><span class="hll"><span class="w"> </span>inherit<span class="w"> </span>distutils-r1
</span>
<span class="w"> </span><span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&quot;Makes working with XML feel like you are working with JSON&quot;</span>
<span class="w"> </span><span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">&quot;https://github.com/martinblech/xmltodict/ https://pypi.org/project/xmltodict/&quot;</span>
<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz&quot;</span>

<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;MIT&quot;</span>
<span class="w"> </span><span class="nv">SLOT</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
<span class="w"> </span><span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">&quot;~amd64 ~arm ~arm64 ~x86&quot;</span>
</pre></div>
</div>
</section>
<section id="source-archives">
<span id="id1"></span><h2>Source archives<a class="headerlink" href="#source-archives" title="Link to this heading"></a></h2>
<p>The vast majority of Python packages can be found in the <a class="reference external" href="https://pypi.org/">Python Package
Index (PyPI)</a>.  Often this includes both source (sdist) and binary
(wheel) packages.  In addition to that, many packages have public VCS
repositories with an automatic archive generation mechanism
(e.g. GitHub).</p>
<p>The current recommendation is to prefer source distributions from PyPI
<em>if and only if</em> they include all files needed for the package,
especially tests.  If the PyPI distribution is missing some files,
VCS generated archives should be used instead.  In some extreme cases,
it may be necessary to use both and combine the files contained in them
(e.g. to combine files pregenerated using NodeJS from sdist with tests
from GitHub archive).</p>
<p>When fetching archives from PyPI, <code class="docutils literal notranslate"><span class="pre">pypi.eclass</span></code> should be used.
It is documented in its own chapter: <a class="reference internal" href="pypi.html"><span class="doc">pypi — helper eclass for PyPI archives</span></a>.</p>
<p>When using generated archives, it is recommended to append a unique
suffix (in case of GitHub, using a <code class="docutils literal notranslate"><span class="pre">.gh.tar.gz</span></code> suffix is requested)
to the distfile name, in order to make the archive clearly
distinguishable from the upstream provided tarball and to use a filename
that matches the top directory inside the archive, e.g.:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">    https://github.com/Textualize/rich/archive/v</span><span class="si">${</span><span class="nv">PV</span><span class="si">}</span><span class="s2">.tar.gz</span>
<span class="s2">        -&gt; </span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.gh.tar.gz</span>
<span class="s2">&quot;</span>
</pre></div>
</div>
<p>Note that unlike sdist archives, snapshots are often missing generated
files.  This has some implications, notably:</p>
<ol class="arabic simple">
<li><p>If the package uses setuptools_scm or a similar package, the version
string may need to be provided explicitly,
cf. <a class="reference internal" href="#setuptools-scm-flit-scm-hatch-vcs-pdm-backend-and-snapshots">setuptools_scm (flit_scm, hatch-vcs, pdm-backend)
and snapshots</a>.</p></li>
<li><p>If the package uses Cython, the C files need to be generated
and an explicit <code class="docutils literal notranslate"><span class="pre">BDEPEND</span></code> on <code class="docutils literal notranslate"><span class="pre">dev-python/cython</span></code> needs to
be added.  However, regenerating them is recommended anyway,
cf. <a class="reference internal" href="#packages-using-cython">packages using Cython</a>.</p></li>
</ol>
</section>
<section id="dependencies">
<h2>Dependencies<a class="headerlink" href="#dependencies" title="Link to this heading"></a></h2>
<p>Dependencies on Python packages are declared using the same method
as the underlying eclass — that is, <code class="docutils literal notranslate"><span class="pre">python-r1</span></code>
or <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code>.</p>
<p>In packages using <code class="docutils literal notranslate"><span class="pre">dev-python/setuptools</span></code>, dependencies are often
specified in <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> or <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code> file.
The <code class="docutils literal notranslate"><span class="pre">install_requires</span></code> key specifies runtime dependencies,
<code class="docutils literal notranslate"><span class="pre">setup_requires</span></code> pure build-time dependencies, <code class="docutils literal notranslate"><span class="pre">extras_require</span></code>
optional dependencies.  Test dependencies are sometimes specified
as one of the ‘extras’, and sometimes as <code class="docutils literal notranslate"><span class="pre">tests_require</span></code>.</p>
<p>Setuptools strictly enforces <code class="docutils literal notranslate"><span class="pre">setup_requires</span></code> at build time,
and <code class="docutils literal notranslate"><span class="pre">tests_require</span></code> when running <code class="docutils literal notranslate"><span class="pre">setup.py</span> <span class="pre">test</span></code>.  Runtime
dependencies are enforced only when starting installed programs
via entry points.</p>
<p>In other cases, dependencies are listed in additional files named
e.g. <code class="docutils literal notranslate"><span class="pre">requirements.txt</span></code>.  They could be also found in test runner
setup (<code class="docutils literal notranslate"><span class="pre">tox.ini</span></code>) or CI setup files (<code class="docutils literal notranslate"><span class="pre">.travis.yml</span></code>).  Finally, you
can grep source code for <code class="docutils literal notranslate"><span class="pre">import</span></code> statements.</p>
<p>In general, you should take special care when listing dependencies
of Python packages.  Upstreams sometimes specify indirect dependencies,
often list packages that are not strictly relevant to Gentoo runs
but used on CI/CD setup, unnecessarily restrict version requirements.</p>
<p>Most of the time, runtime dependencies do not need to be present
at build time.  However, they do need to be copied there if the Python
modules needing them are imported at build time.  Often this is the case
when running tests, hence the following logic is common in Python
ebuilds:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">&quot;...&quot;</span>
<span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">&quot;test? ( </span><span class="si">${</span><span class="nv">RDEPEND</span><span class="si">}</span><span class="s2"> )&quot;</span>
</pre></div>
</div>
<p>There are two different approaches used for optional runtime
dependencies.  Some packages are installing them conditionally to USE
flags (this is generally acceptable as long as package builds quickly),
others list them in <code class="docutils literal notranslate"><span class="pre">pkg_postinst()</span></code> messages.  It is recommended
that optional test dependencies are used unconditionally (to ensure
the widest test coverage, and avoid unpredictable test failures on users
who have more dependencies installed).</p>
</section>
<section id="python-single-r1-variant">
<span id="index-0"></span><h2>python-single-r1 variant<a class="headerlink" href="#python-single-r1-variant" title="Link to this heading"></a></h2>
<p>Normally, <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> uses <code class="docutils literal notranslate"><span class="pre">python-r1</span></code> to build multi-impl
packages, and this is the recommended mode.  However, in some cases
you will need to use <code class="docutils literal notranslate"><span class="pre">python-single-r1</span></code> instead, especially if you
need to depend on other packages using that eclass.</p>
<p>The single-impl mode can be enabled by setting <code class="docutils literal notranslate"><span class="pre">DISTUTILS_SINGLE_IMPL</span></code>
variable before inheriting the eclass.  The eclass aims to provide
maximum compatibility between these two modes, so most of the existing
code will work with either.  However, the functions specific to
the underlying eclass are not compatible — e.g. the dependencies need
to be rewritten.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2022 Gentoo Authors</span>
<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>

<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>

<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python3_<span class="o">{</span><span class="m">8</span>..10<span class="o">}</span><span class="w"> </span><span class="o">)</span>
<span class="w"> </span><span class="nv">PYTHON_REQ_USE</span><span class="o">=</span><span class="s2">&quot;readline&quot;</span>
<span class="w"> </span><span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>setuptools
<span class="hll"><span class="w"> </span><span class="nv">DISTUTILS_SINGLE_IMPL</span><span class="o">=</span><span class="m">1</span>
</span>
<span class="w"> </span>inherit<span class="w"> </span>distutils-r1

<span class="w"> </span><span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&quot;Pythonic layer on top of the ROOT framework&#39;s PyROOT bindings&quot;</span>
<span class="w"> </span><span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">&quot;http://rootpy.org&quot;</span>
<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz&quot;</span>

<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;BSD&quot;</span>
<span class="w"> </span><span class="nv">SLOT</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
<span class="w"> </span><span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">&quot;~amd64 ~x86 ~amd64-linux ~x86-linux&quot;</span>

<span class="w"> </span><span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">     sci-physics/root:=[</span><span class="si">${</span><span class="nv">PYTHON_SINGLE_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2">     dev-python/root_numpy[</span><span class="si">${</span><span class="nv">PYTHON_SINGLE_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2">     </span><span class="k">$(</span>python_gen_cond_dep<span class="w"> </span><span class="s1">&#39;</span>
<span class="s1">         dev-python/matplotlib[${PYTHON_USEDEP}]</span>
<span class="s1">         dev-python/pytables[${PYTHON_USEDEP}]</span>
<span class="s1">         dev-python/termcolor[${PYTHON_USEDEP}]</span>
<span class="s1">     &#39;</span><span class="k">)</span><span class="s2">&quot;</span>

<span class="w"> </span><span class="nv">DEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">     sci-physics/root[</span><span class="si">${</span><span class="nv">PYTHON_SINGLE_USEDEP</span><span class="si">}</span><span class="s2">]&quot;</span>
</pre></div>
</div>
</section>
<section id="pep-517-build-systems">
<span id="index-1"></span><h2>PEP 517 build systems<a class="headerlink" href="#pep-517-build-systems" title="Link to this heading"></a></h2>
<p>The majority of examples in this guide assume using setuptools build
system.  However, PEP 517 mode provides support for other build systems.</p>
<p>In order to determine the correct build system used, read
the <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> file.  An example file could start with:</p>
<div class="highlight-toml notranslate"><div class="highlight"><pre><span></span><span class="k">[build-system]</span>
<span class="n">requires</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="s2">&quot;flit_core &gt;=3.6.0,&lt;4&quot;</span><span class="p">]</span>
<span class="n">build-backend</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">&quot;flit_core.buildapi&quot;</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">requires</span></code> key indicates the packages required in order to run
the build system, while <code class="docutils literal notranslate"><span class="pre">build-backend</span></code> indicates the module
(and optionally the class) providing the build system backend.
The eclass maintains a mapping of backend paths to the respective
<code class="docutils literal notranslate"><span class="pre">DISTUTILS_USE_PEP517</span></code> and automatically suggests the correct value.</p>
<p>The following table summarizes supported backends.</p>
<table class="docutils align-default">
<thead>
<tr class="row-odd"><th class="head"><p>USE_PEP517 value</p></th>
<th class="head"><p>Provider package</p></th>
<th class="head"><p>build-backend</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>flit</p></td>
<td><p>dev-python/flit_core</p></td>
<td><p>flit_core.buildapi</p></td>
</tr>
<tr class="row-odd"><td><p>flit_scm</p></td>
<td><p>dev-python/flit_scm</p></td>
<td><p>flit_scm:buildapi</p></td>
</tr>
<tr class="row-even"><td><p>hatchling</p></td>
<td><p>dev-python/hatchling</p></td>
<td><p>hatchling.build</p></td>
</tr>
<tr class="row-odd"><td><p>jupyter</p></td>
<td><p>dev-python/jupyter_packaging</p></td>
<td><p>jupyter_packaging.build_api</p></td>
</tr>
<tr class="row-even"><td><p>maturin</p></td>
<td><p>dev-util/maturin</p></td>
<td><p>maturin</p></td>
</tr>
<tr class="row-odd"><td><p>meson-python</p></td>
<td><p>dev-python/meson-python</p></td>
<td><p>mesonpy</p></td>
</tr>
<tr class="row-even"><td><p>no</p></td>
<td><p>(none)</p></td>
<td><p>(none, see below)</p></td>
</tr>
<tr class="row-odd"><td><p>pbr</p></td>
<td><p>dev-python/pbr</p></td>
<td><p>pbr.build</p></td>
</tr>
<tr class="row-even"><td><p>pdm</p></td>
<td><p>dev-python/pdm-pep517</p></td>
<td><p>pdm.pep517.api</p></td>
</tr>
<tr class="row-odd"><td><p>pdm-backend</p></td>
<td><p>dev-python/pdm-backend</p></td>
<td><p>pdm.backend</p></td>
</tr>
<tr class="row-even"><td><p>poetry</p></td>
<td><p>dev-python/poetry-core</p></td>
<td><p>poetry.core.masonry.api</p></td>
</tr>
<tr class="row-odd"><td><p>scikit-build-core</p></td>
<td><p>dev-python/scikit-build-core</p></td>
<td><p>scikit_build_core.build</p></td>
</tr>
<tr class="row-even"><td><p>setuptools</p></td>
<td><p>dev-python/setuptools</p></td>
<td><p>setuptools.build_meta
setuptools.__legacy__.build_meta</p></td>
</tr>
<tr class="row-odd"><td><p>sip</p></td>
<td><p>dev-python/sip</p></td>
<td><p>sipbuild.api</p></td>
</tr>
<tr class="row-even"><td><p>standalone</p></td>
<td><p>(none)</p></td>
<td><p>(various, see below)</p></td>
</tr>
</tbody>
</table>
<p>The eclass recognizes two special values: <code class="docutils literal notranslate"><span class="pre">no</span></code> and <code class="docutils literal notranslate"><span class="pre">standalone</span></code>.
<code class="docutils literal notranslate"><span class="pre">no</span></code> is used to enable ‘no build system’ mode as described
in <a class="reference internal" href="#installing-packages-without-a-pep-517-build-backend">installing packages without a PEP 517 build backend</a>.
<code class="docutils literal notranslate"><span class="pre">standalone</span></code> indicates that the package itself provides its own build
backend.</p>
<p>Legacy packages that provide <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> but no <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>
(or do not define a backend inside it) should be installed via
the <code class="docutils literal notranslate"><span class="pre">setuptools</span></code> backend (this applies to pure distutils packages
as well).  The eclass automatically uses the legacy setuptools backend
for them.</p>
</section>
<section id="setuptools-scm-flit-scm-hatch-vcs-pdm-backend-and-snapshots">
<span id="index-6"></span><span id="index-5"></span><span id="index-4"></span><span id="index-3"></span><span id="index-2"></span><h2>setuptools_scm (flit_scm, hatch-vcs, pdm-backend) and snapshots<a class="headerlink" href="#setuptools-scm-flit-scm-hatch-vcs-pdm-backend-and-snapshots" title="Link to this heading"></a></h2>
<p><a class="reference external" href="https://pypi.org/project/setuptools-scm/">setuptools_scm</a> is a package providing additional features for running
inside a VCS checkout, in particular the ability to determine version
from VCS tags.  However, this may not work when building from a GitHub
snapshot:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>Traceback<span class="w"> </span><span class="o">(</span>most<span class="w"> </span>recent<span class="w"> </span>call<span class="w"> </span>last<span class="o">)</span>:
<span class="w">  </span>File<span class="w"> </span><span class="s2">&quot;/tmp/executing-0.5.2/setup.py&quot;</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">4</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>&lt;module&gt;
<span class="w">    </span>setup<span class="o">()</span>
<span class="w">  </span>File<span class="w"> </span><span class="s2">&quot;/usr/lib/python3.9/site-packages/setuptools/__init__.py&quot;</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">143</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>setup
<span class="w">    </span>_install_setup_requires<span class="o">(</span>attrs<span class="o">)</span>
<span class="w">  </span>File<span class="w"> </span><span class="s2">&quot;/usr/lib/python3.9/site-packages/setuptools/__init__.py&quot;</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">131</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>_install_setup_requires
<span class="w">    </span><span class="nv">dist</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>distutils.core.Distribution<span class="o">(</span>dict<span class="o">(</span>
<span class="w">  </span>File<span class="w"> </span><span class="s2">&quot;/usr/lib/python3.9/site-packages/setuptools/dist.py&quot;</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">425</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>__init__
<span class="w">    </span>_Distribution.__init__<span class="o">(</span>self,<span class="w"> </span><span class="o">{</span>
<span class="w">  </span>File<span class="w"> </span><span class="s2">&quot;/usr/lib/python3.9/distutils/dist.py&quot;</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">292</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>__init__
<span class="w">    </span>self.finalize_options<span class="o">()</span>
<span class="w">  </span>File<span class="w"> </span><span class="s2">&quot;/usr/lib/python3.9/site-packages/setuptools/dist.py&quot;</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">717</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>finalize_options
<span class="w">    </span>ep<span class="o">(</span>self<span class="o">)</span>
<span class="w">  </span>File<span class="w"> </span><span class="s2">&quot;/usr/lib/python3.9/site-packages/setuptools_scm/integration.py&quot;</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">48</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>infer_version
<span class="w">    </span>dist.metadata.version<span class="w"> </span><span class="o">=</span><span class="w"> </span>_get_version<span class="o">(</span>config<span class="o">)</span>
<span class="w">  </span>File<span class="w"> </span><span class="s2">&quot;/usr/lib/python3.9/site-packages/setuptools_scm/__init__.py&quot;</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">148</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>_get_version
<span class="w">    </span><span class="nv">parsed_version</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>_do_parse<span class="o">(</span>config<span class="o">)</span>
<span class="w">  </span>File<span class="w"> </span><span class="s2">&quot;/usr/lib/python3.9/site-packages/setuptools_scm/__init__.py&quot;</span>,<span class="w"> </span>line<span class="w"> </span><span class="m">110</span>,<span class="w"> </span><span class="k">in</span><span class="w"> </span>_do_parse
<span class="w">    </span>raise<span class="w"> </span>LookupError<span class="o">(</span>
LookupError:<span class="w"> </span>setuptools-scm<span class="w"> </span>was<span class="w"> </span>unable<span class="w"> </span>to<span class="w"> </span>detect<span class="w"> </span>version<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="s1">&#39;/tmp/executing-0.5.2&#39;</span>.

Make<span class="w"> </span>sure<span class="w"> </span>you<span class="s1">&#39;re either building from a fully intact git repository or PyPI tarballs. Most other sources (such as GitHub&#39;</span>s<span class="w"> </span>tarballs,<span class="w"> </span>a<span class="w"> </span>git<span class="w"> </span>checkout<span class="w"> </span>without<span class="w"> </span>the<span class="w"> </span>.git<span class="w"> </span>folder<span class="o">)</span><span class="w"> </span>don<span class="s1">&#39;t contain the necessary metadata and will not work.</span>

<span class="s1">For example, if you&#39;</span>re<span class="w"> </span>using<span class="w"> </span>pip,<span class="w"> </span>instead<span class="w"> </span>of<span class="w"> </span>https://github.com/user/proj/archive/master.zip<span class="w"> </span>use<span class="w"> </span>git+https://github.com/user/proj.git#egg<span class="o">=</span>proj
</pre></div>
</div>
<p>This problem can be resolved by providing the correct version externally
via <code class="docutils literal notranslate"><span class="pre">SETUPTOOLS_SCM_PRETEND_VERSION</span></code>:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nb">export</span><span class="w"> </span><span class="nv">SETUPTOOLS_SCM_PRETEND_VERSION</span><span class="o">=</span><span class="si">${</span><span class="nv">PV</span><span class="si">}</span>
</pre></div>
</div>
<p>The <a class="reference external" href="https://pypi.org/project/flit_scm/">flit_scm</a> and <a class="reference external" href="https://pypi.org/project/hatch-vcs/">hatch-vcs</a> packages are both built on top
of setuptools_scm.  The same approach applies to both of them.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>While <code class="docutils literal notranslate"><span class="pre">SETUPTOOLS_SCM_PRETEND_VERSION</span></code> is sufficient to make
the package build, setuptools may install incomplete set of package
data files.  Please take special care to verify that all files are
installed.</p>
</div>
<p>The <a class="reference external" href="https://pypi.org/project/pdm-backend/">pdm-backend</a> package reinvents its own SCM version support,
and unlike setuptools_scm, it uses <code class="docutils literal notranslate"><span class="pre">0.0.0</span></code> rather than throwing
an error when the version cannot be determined.  The override for this
backend can be set using a similarly purposed environment variable:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nb">export</span><span class="w"> </span><span class="nv">PDM_BUILD_SCM_VERSION</span><span class="o">=</span><span class="si">${</span><span class="nv">PV</span><span class="si">}</span>
</pre></div>
</div>
</section>
<section id="packages-installing-extensions-c-rust">
<span id="index-7"></span><h2>Packages installing extensions (C, Rust…)<a class="headerlink" href="#packages-installing-extensions-c-rust" title="Link to this heading"></a></h2>
<p>Python extensions are compiled (C, Cython, Rust…) loadable modules.
They can generally be recognized by the presence of <code class="docutils literal notranslate"><span class="pre">.so</span></code> files
in site-packages directory.</p>
<p>The eclass provides a <code class="docutils literal notranslate"><span class="pre">DISTUTILS_EXT</span></code> control variable to enable
additional features related to extensions.  These are:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">DEPEND</span></code> class dependency on the Python implementation — needed
for cross-compilation (unless <code class="docutils literal notranslate"><span class="pre">DISTUTILS_OPTIONAL</span></code> is used,
then the <code class="docutils literal notranslate"><span class="pre">DEPEND</span></code> needs to be added manually).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">IUSE=debug</span></code> flag that is used to control whether the extensions
are compiled with assertions enabled (among others, used to verify
whether the Python API is used correctly).</p></li>
<li><p>calling <code class="docutils literal notranslate"><span class="pre">esetup.py</span> <span class="pre">build_ext</span></code> to compile C files using parallel
jobs.</p></li>
</ul>
<p>The variable needs to be set prior to inheriting the eclass, e.g.:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 2023 Gentoo Authors</span>
<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>

<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">8</span>

<span class="hll"><span class="w"> </span><span class="nv">DISTUTILS_EXT</span><span class="o">=</span><span class="m">1</span>
</span><span class="w"> </span><span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>setuptools
<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python3_<span class="o">{</span><span class="m">10</span>..11<span class="o">}</span><span class="w"> </span>pypy3<span class="w"> </span><span class="o">)</span>

<span class="w"> </span>inherit<span class="w"> </span>distutils-r1
</pre></div>
</div>
<p>Note that it should be enabled even if the extensions are only built
conditionally to USE flags.  Most of the additions need to be done
in global scope anyway, and making the <code class="docutils literal notranslate"><span class="pre">DEPEND</span></code> conditional isn’t
considered worth the added complexity.</p>
<p>In general, you don’t need to worry about adding the variable.
The eclass should automatically print a QA warning if <code class="docutils literal notranslate"><span class="pre">DISTUTILS_EXT</span></code>
is missing:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="go">* Python extension modules (*.so) found installed. Please set:</span>
<span class="go">*   DISTUTILS_EXT=1</span>
<span class="go">* in the ebuild.</span>
</pre></div>
</div>
</section>
<section id="packages-using-cython">
<span id="index-8"></span><h2>Packages using Cython<a class="headerlink" href="#packages-using-cython" title="Link to this heading"></a></h2>
<p><a class="reference external" href="https://cython.org/">Cython</a> is a static compiler that permits writing Python extensions
in a hybrid of C and Python.  Cython files are compiled into C code
that is compatible with multiple Python interpreters.  This makes it
possible for packages to include pregenerated C files and build
the respective extensions without exposing the Cython dependency.</p>
<p>In Gentoo, it is always recommended to depend on <code class="docutils literal notranslate"><span class="pre">dev-python/cython</span></code>
and regenerate the C files.  This guarantees that bug fixes found
in newer versions of Cython are taken advantage of.  Using shipped files
could e.g. cause compatibility issues with newer versions of Python.</p>
<p>Depending on the package in question, forcing regeneration could be
as simple as removing the pregenerated files:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">    dev-python/cython[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2">&quot;</span>

src_configure<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>rm<span class="w"> </span>src/frobnicate.c<span class="w"> </span><span class="o">||</span><span class="w"> </span>die
<span class="o">}</span>
</pre></div>
</div>
<p>However, in some cases packages utilize the generated C files directly
in <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>.  In these cases, sometimes a Makefile is provided
to run Cythonize.  It is also possible to call Cython directly:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">    dev-python/cython[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
<span class="s2">&quot;</span>

src_configure<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>cython<span class="w"> </span>-3<span class="w"> </span>jq.pyx<span class="w"> </span>-o<span class="w"> </span>jq.c<span class="w"> </span><span class="o">||</span><span class="w"> </span>die
<span class="o">}</span>
</pre></div>
</div>
<p>Note that Cython needs to be called only once, as the resulting code
is compatible with all Python versions.</p>
</section>
<section id="parallel-build-race-conditions">
<h2>Parallel build race conditions<a class="headerlink" href="#parallel-build-race-conditions" title="Link to this heading"></a></h2>
<p>The distutils build system has a major unresolved bug regarding race
conditions.  If the same source file is used to build multiple Python
extensions, the build can start multiple simultaneous compiler processes
using the same output file.  As a result, there is a race between
the compilers writing output file and link editors reading it.  This
generally does not cause immediate build failures but results in broken
extensions causing cryptic issues in reverse dependencies.</p>
<p>For example, a miscompilation of <code class="docutils literal notranslate"><span class="pre">dev-python/pandas</span></code> have recently
caused breakage in <code class="docutils literal notranslate"><span class="pre">dev-python/dask</span></code>:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>/usr/lib/python3.8/site-packages/pandas/__init__.py:29:<span class="w"> </span><span class="k">in</span><span class="w"> </span>&lt;module&gt;
<span class="w">    </span>from<span class="w"> </span>pandas._libs<span class="w"> </span>import<span class="w"> </span>hashtable<span class="w"> </span>as<span class="w"> </span>_hashtable,<span class="w"> </span>lib<span class="w"> </span>as<span class="w"> </span>_lib,<span class="w"> </span>tslib<span class="w"> </span>as<span class="w"> </span>_tslib
/usr/lib/python3.8/site-packages/pandas/_libs/__init__.py:13:<span class="w"> </span><span class="k">in</span><span class="w"> </span>&lt;module&gt;
<span class="w">    </span>from<span class="w"> </span>pandas._libs.interval<span class="w"> </span>import<span class="w"> </span>Interval
pandas/_libs/interval.pyx:1:<span class="w"> </span><span class="k">in</span><span class="w"> </span>init<span class="w"> </span>pandas._libs.interval
<span class="w">    </span>???
pandas/_libs/hashtable.pyx:1:<span class="w"> </span><span class="k">in</span><span class="w"> </span>init<span class="w"> </span>pandas._libs.hashtable
<span class="w">    </span>???
pandas/_libs/missing.pyx:1:<span class="w"> </span><span class="k">in</span><span class="w"> </span>init<span class="w"> </span>pandas._libs.missing
<span class="w">    </span>???
/usr/lib/python3.8/site-packages/pandas/_libs/tslibs/__init__.py:30:<span class="w"> </span><span class="k">in</span><span class="w"> </span>&lt;module&gt;
<span class="w">    </span>from<span class="w"> </span>.conversion<span class="w"> </span>import<span class="w"> </span>OutOfBoundsTimedelta,<span class="w"> </span>localize_pydatetime
E<span class="w">   </span>ImportError:<span class="w"> </span>/usr/lib/python3.8/site-packages/pandas/_libs/tslibs/conversion.cpython-38-x86_64-linux-gnu.so:<span class="w"> </span>undefined<span class="w"> </span>symbol:<span class="w"> </span>pandas_datetime_to_datetimestruct
</pre></div>
</div>
<p>The easiest way to workaround the problem in ebuild is to append <code class="docutils literal notranslate"><span class="pre">-j1</span></code>
in <a class="reference internal" href="#python-compile">python_compile</a> sub-phase.</p>
<p>The common way of working around the problem upstream is to create
additional .c files that <code class="docutils literal notranslate"><span class="pre">#include</span></code> the original file, and use unique
source files for every extension.</p>
</section>
<section id="sub-phase-functions">
<h2>Sub-phase functions<a class="headerlink" href="#sub-phase-functions" title="Link to this heading"></a></h2>
<p>Ebuilds define phase functions in order to conveniently override parts
of the build process.  <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> extends this concept
by introducing <em>sub-phases</em>.  All <code class="docutils literal notranslate"><span class="pre">src_*</span></code> phases in ebuild are split
into two sub-phases: <code class="docutils literal notranslate"><span class="pre">python_*</span></code> sub-phases that are run in a loop
for all enabled interpreters, and <code class="docutils literal notranslate"><span class="pre">python_*_all</span></code> sub-phases that
comprise the common code to be run only once.</p>
<p>Sub-phase functions behave similarly to phase functions.  They are run
if defined by the ebuild.  If they’re not, the default implementation
is run (if any).  The ebuild overrides can call the default
as <code class="docutils literal notranslate"><span class="pre">distutils-r1_&lt;sub-phase&gt;</span></code>, the same way it can call eclass’ phase
function defaults.</p>
<p>There are 10 sub-phases corresponding to 5 phase functions.  They are
run in the following order:</p>
<ol class="arabic simple">
<li><p><code class="docutils literal notranslate"><span class="pre">python_prepare_all</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_prepare</span></code>, has default)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_prepare</span></code> (for each impl.)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_configure</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_configure</span></code>, for each impl.)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_configure_all</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_compile</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_compile</span></code>, for each impl., has default)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_compile_all</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_test</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_test</span></code>, for each impl.)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_test_all</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_install</span></code> (for <code class="docutils literal notranslate"><span class="pre">src_install</span></code>, for each impl., has default)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">python_install_all</span></code> (has default)</p></li>
</ol>
<p>Note that normally all phases are run in the source directory, while
defining <code class="docutils literal notranslate"><span class="pre">${BUILD_DIR}</span></code> to a dedicated build directory for each
implementation.  However, if in-source builds are enabled, all phases
are run in these build directories.</p>
<section id="python-prepare">
<span id="index-10"></span><span id="index-9"></span><h3>python_prepare<a class="headerlink" href="#python-prepare" title="Link to this heading"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_prepare_all</span></code> is responsible for applying changes
to the package sources that are common to all Python implementations.
The default implementation performs the tasks of <code class="docutils literal notranslate"><span class="pre">default_src_prepare</span></code>
(applying patches), as well as eclass-specific tasks: removing
<code class="docutils literal notranslate"><span class="pre">ez_setup</span></code> (method of bootstrapping setuptools used in old packages)
and handling <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code>.  In the end, the function copies
sources to build dirs if in-source build is requested.</p>
<p>If additional changes need to be done to the package, either this
sub-phase or <code class="docutils literal notranslate"><span class="pre">src_prepare</span></code> in general can be replaced.  However,
you should always call the original implementation from your override.
For example, you could use it to strip extraneous dependencies or broken
tests:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_prepare_all<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span><span class="c1"># FIXME</span>
<span class="w">    </span>rm<span class="w"> </span>tests/test_pytest_plugin.py<span class="w"> </span><span class="o">||</span><span class="w"> </span>die
<span class="w">    </span>sed<span class="w"> </span>-i<span class="w"> </span>-e<span class="w"> </span><span class="s1">&#39;s:test_testcase_no_app:_&amp;:&#39;</span><span class="w"> </span>tests/test_test_utils.py<span class="w"> </span><span class="o">||</span><span class="w"> </span>die

<span class="w">    </span><span class="c1"># remove pointless dep on pytest-cov</span>
<span class="w">    </span>sed<span class="w"> </span>-i<span class="w"> </span>-e<span class="w"> </span><span class="s1">&#39;/addopts/s/--cov=aiohttp//&#39;</span><span class="w"> </span>pytest.ini<span class="w"> </span><span class="o">||</span><span class="w"> </span>die

<span class="w">    </span>distutils-r1_python_prepare_all
<span class="o">}</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">python_prepare</span></code> is responsible for applying changes specific to one
interpreter.  It has no default implementation.  When defined, in-source
builds are enabled implicitly as sources need to be duplicated to apply
implementation-specific changes.</p>
<p>In the following example, it is used to remove a CLI script whose
dependencies only support Python 3.8 and 3.9 at the moment.  Naturally,
since this modification needs to be done on a subset of all Python
interpreters, the eclass needs to keep a separate copy of the sources
for every one of them.  This is why <code class="docutils literal notranslate"><span class="pre">python_prepare</span></code> automatically
enables in-source builds.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_prepare<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span>!<span class="w"> </span>use<span class="w"> </span>cli<span class="w"> </span><span class="o">||</span><span class="w"> </span>!<span class="w"> </span>has<span class="w"> </span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">EPYTHON</span><span class="si">}</span><span class="s2">&quot;</span><span class="w"> </span>python3.<span class="o">{</span><span class="m">7</span>..9<span class="o">}</span><span class="p">;</span><span class="w"> </span><span class="k">then</span>
<span class="w">        </span>sed<span class="w"> </span>-i<span class="w"> </span>-e<span class="w"> </span><span class="s1">&#39;/console_scripts/d&#39;</span><span class="w"> </span>setup.py<span class="w"> </span><span class="o">||</span><span class="w"> </span>die
<span class="w">    </span><span class="k">fi</span>
<span class="o">}</span>
</pre></div>
</div>
</section>
<section id="python-configure">
<span id="index-12"></span><span id="index-11"></span><h3>python_configure<a class="headerlink" href="#python-configure" title="Link to this heading"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_configure</span></code> and <code class="docutils literal notranslate"><span class="pre">python_configure_all</span></code> have no default
functionality.  The former is convenient for running additional
configuration steps if needed by the package, the latter for defining
global environment variables.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_configure<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>esetup.py<span class="w"> </span>configure<span class="w"> </span><span class="k">$(</span>usex<span class="w"> </span>mpi<span class="w"> </span>--mpi<span class="w"> </span><span class="s1">&#39;&#39;</span><span class="k">)</span>
<span class="o">}</span>
</pre></div>
</div>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_configure_all<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span><span class="nv">DISTUTILS_ARGS</span><span class="o">=(</span>
<span class="w">        </span>--resourcepath<span class="o">=</span>/usr/share
<span class="w">        </span>--no-compress-manpages
<span class="w">    </span><span class="o">)</span>
<span class="o">}</span>
</pre></div>
</div>
</section>
<section id="python-compile">
<span id="index-14"></span><span id="index-13"></span><h3>python_compile<a class="headerlink" href="#python-compile" title="Link to this heading"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_compile</span></code> normally builds the package.  It is sometimes used
to pass additional arguments to the build step.  For example, it can
be used to disable parallel extension builds in packages that are broken
with it:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_compile<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>distutils-r1_python_compile<span class="w"> </span>-j1
<span class="o">}</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">python_compile_all</span></code>
has no default implementation.  It is convenient for performing
additional common build steps, in particular for building
the documentation (see <code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code>).</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_compile_all<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>use<span class="w"> </span>doc<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span>emake<span class="w"> </span>-C<span class="w"> </span>docs<span class="w"> </span>html
<span class="o">}</span>
</pre></div>
</div>
</section>
<section id="python-test">
<span id="index-16"></span><span id="index-15"></span><h3>python_test<a class="headerlink" href="#python-test" title="Link to this heading"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_test</span></code> is responsible for running tests.  It has no default
implementation but you are strongly encouraged to provide one (either
directly or via <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code>).  <code class="docutils literal notranslate"><span class="pre">python_test_all</span></code>
can be used to run additional testing code that is not specific
to Python.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">EPYTHON</span><span class="si">}</span><span class="s2">&quot;</span><span class="w"> </span>TestBitVector/Test.py<span class="w"> </span><span class="o">||</span><span class="w"> </span>die<span class="w"> </span><span class="s2">&quot;Tests fail with </span><span class="si">${</span><span class="nv">EPYTHON</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="o">}</span>
</pre></div>
</div>
</section>
<section id="python-install">
<span id="index-18"></span><span id="index-17"></span><h3>python_install<a class="headerlink" href="#python-install" title="Link to this heading"></a></h3>
<p><code class="docutils literal notranslate"><span class="pre">python_install</span></code> installs the package’s Python part.  It is usually
redefined in order to pass additional <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> arguments
or to install additional Python modules.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_install<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>distutils-r1_python_install

<span class="w">    </span><span class="c1"># ensure data files for tests are getting installed too</span>
<span class="w">    </span>python_moduleinto<span class="w"> </span>collada/tests/
<span class="w">    </span>python_domodule<span class="w"> </span>collada/tests/data
<span class="o">}</span>
</pre></div>
</div>
<p><code class="docutils literal notranslate"><span class="pre">python_install_all</span></code> installs documentation via <code class="docutils literal notranslate"><span class="pre">einstalldocs</span></code>.
It is usually defined by ebuilds to install additional common files
such as bash completions or examples.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_install_all<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span>use<span class="w"> </span>examples<span class="p">;</span><span class="w"> </span><span class="k">then</span>
<span class="w">        </span>docinto<span class="w"> </span>examples
<span class="w">        </span>dodoc<span class="w"> </span>-r<span class="w"> </span>Sample_Code/.
<span class="w">        </span>docompress<span class="w"> </span>-x<span class="w"> </span>/usr/share/doc/<span class="si">${</span><span class="nv">PF</span><span class="si">}</span>/examples
<span class="w">    </span><span class="k">fi</span>
<span class="w">    </span>distutils-r1_python_install_all
<span class="o">}</span>
</pre></div>
</div>
</section>
</section>
<section id="passing-arguments-to-setup-py">
<span id="index-19"></span><h2>Passing arguments to setup.py<a class="headerlink" href="#passing-arguments-to-setup-py" title="Link to this heading"></a></h2>
<p>There are two main methods of accepting additional command-line options
in <code class="docutils literal notranslate"><span class="pre">setup.py</span></code> scripts: using global options and via command options.</p>
<p>Global options are usually implemented through manipulating <code class="docutils literal notranslate"><span class="pre">sys.path</span></code>
directly.  The recommended way to use them is to specify them
via <code class="docutils literal notranslate"><span class="pre">DISTUTILS_ARGS</span></code> array:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>src_configure<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span><span class="nv">DISTUTILS_ARGS</span><span class="o">=(</span><span class="w"> </span>--external<span class="w"> </span><span class="o">)</span>
<span class="o">}</span>
</pre></div>
</div>
<p>The options specified via <code class="docutils literal notranslate"><span class="pre">DISTUTILS_ARGS</span></code> are passed to all
<code class="docutils literal notranslate"><span class="pre">esetup.py</span></code> invocations, as well as to the setuptools PEP 517 backend
(using the <code class="docutils literal notranslate"><span class="pre">--global-option</span></code> setting).  For future compatibility,
it is recommended to avoid adding command names to <code class="docutils literal notranslate"><span class="pre">DISTUTILS_ARGS</span></code>.</p>
<p>The recommended way to pass command options is to use the <code class="docutils literal notranslate"><span class="pre">setup.cfg</span></code>
file.  For example, Pillow provides for configuring available backends
via additional <code class="docutils literal notranslate"><span class="pre">build_ext</span></code> command flags:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>setup.py<span class="w"> </span>build_ext<span class="w"> </span>--enable-tiff<span class="w"> </span>--disable-webp<span class="w"> </span>...
</pre></div>
</div>
<p>The respective options can be setup via the configuration file, where
sections represent the commands and individual keys — options.  Note
that dashes need to be replaced by underscores, and flag-style options
take boolean arguments.  In this case, the ebuild can use:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>src_configure<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>cat<span class="w"> </span>&gt;&gt;<span class="w"> </span>setup.cfg<span class="w"> </span><span class="s">&lt;&lt;-EOF</span>
<span class="s">        [build_ext]</span>
<span class="s">        disable_tiff = $(usex !tiff True False)</span>
<span class="s">        enable_tiff = $(usex tiff True False)</span>
<span class="s">        disable_webp = $(usex !webp True False)</span>
<span class="s">        enable_webp = $(usex webp True False)</span>
<span class="s">        #...</span>
<span class="s">    EOF</span>
<span class="o">}</span>
</pre></div>
</div>
</section>
<section id="calling-custom-setup-py-commands">
<span id="index-20"></span><h2>Calling custom setup.py commands<a class="headerlink" href="#calling-custom-setup-py-commands" title="Link to this heading"></a></h2>
<p>When working on packages using setuptools or modified distutils, you
sometimes need to manually invoke <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>.  The eclass provides
a <code class="docutils literal notranslate"><span class="pre">esetup.py</span></code> helper that wraps it with additional checks, error
handling and ensures that the override configuration file is created
beforehand (much like <code class="docutils literal notranslate"><span class="pre">econf</span></code> or <code class="docutils literal notranslate"><span class="pre">emake</span></code>).</p>
<p><code class="docutils literal notranslate"><span class="pre">esetup.py</span></code> passes all its paremeters to <code class="docutils literal notranslate"><span class="pre">./setup.py</span></code>.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>python_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>esetup.py<span class="w"> </span>check
<span class="o">}</span>
</pre></div>
</div>
</section>
<section id="enabling-tests">
<h2>Enabling tests<a class="headerlink" href="#enabling-tests" title="Link to this heading"></a></h2>
<p>The support for test suites is now covered in the <a class="reference internal" href="test.html"><span class="doc">Tests in Python packages</span></a> chapter.</p>
</section>
<section id="building-documentation-via-sphinx">
<span id="index-21"></span><h2>Building documentation via Sphinx<a class="headerlink" href="#building-documentation-via-sphinx" title="Link to this heading"></a></h2>
<p><code class="docutils literal notranslate"><span class="pre">dev-python/sphinx</span></code> is commonly used to document Python packages.
It comes with a number of plugins and themes that make it convenient
to write and combine large text documents (such as this Guide!),
as well as automatically document Python code.</p>
<p>Depending on the exact package, building documentation may range
from being trivial to very hard.  Packages that do not use autodoc
(documenting of Python code) do not need to USE-depend on Sphinx at all.
Packages that do that need to use a supported Python implementation
for Sphinx, and packages that use plugins need to guarantee the same
implementation across all plugins.  To cover all those use cases easily,
the <code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code> function is provided.</p>
<section id="basic-documentation-with-autodoc">
<h3>Basic documentation with autodoc<a class="headerlink" href="#basic-documentation-with-autodoc" title="Link to this heading"></a></h3>
<p>The most common case is a package that uses Sphinx along with autodoc.
It can be recognized by <code class="docutils literal notranslate"><span class="pre">conf.py</span></code> listing <code class="docutils literal notranslate"><span class="pre">sphinx.ext.autodoc</span></code>
in the extension list.  In order to support building documentation,
call <code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code> and pass the path to the directory
containing Sphinx documentation:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>

<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>

<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span><span class="w"> </span><span class="o">)</span>
<span class="w"> </span><span class="nv">DISTUTILS_USE_SETUPTOOLS</span><span class="o">=</span>rdepend

<span class="w"> </span>inherit<span class="w"> </span>distutils-r1

<span class="w"> </span><span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&quot;Colored stream handler for the logging module&quot;</span>
<span class="w"> </span><span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">     https://pypi.org/project/coloredlogs/</span>
<span class="s2">     https://github.com/xolox/python-coloredlogs</span>
<span class="s2">     https://coloredlogs.readthedocs.io/en/latest/&quot;</span>
<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz&quot;</span>

<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;MIT&quot;</span>
<span class="w"> </span><span class="nv">SLOT</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
<span class="w"> </span><span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">&quot;~amd64 ~x86 ~amd64-linux ~x86-linux&quot;</span>

<span class="w"> </span><span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">&quot;dev-python/humanfriendly[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]&quot;</span>

<span class="hll"><span class="w"> </span>distutils_enable_sphinx<span class="w"> </span>docs
</span></pre></div>
</div>
<p>This call takes care of it all: it adds <code class="docutils literal notranslate"><span class="pre">doc</span></code> USE flag to control
building documentation, appropriate dependencies via the expert any-r1
API making it sufficient for Sphinx to be installed with only one
of the supported implementations, and appropriate <code class="docutils literal notranslate"><span class="pre">python_compile_all</span></code>
implementation to build and install HTML documentation.</p>
</section>
<section id="additional-sphinx-extensions">
<h3>Additional Sphinx extensions<a class="headerlink" href="#additional-sphinx-extensions" title="Link to this heading"></a></h3>
<p>It is not uncommon for packages to require additional third-party
extensions to Sphinx.  Those include themes.  In order to specify
dependencies on the additional packages, pass them as extra arguments
to <code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code>.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>

<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>

<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>pypy3<span class="w"> </span>python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span><span class="w"> </span><span class="o">)</span>
<span class="w"> </span>inherit<span class="w"> </span>distutils-r1

<span class="w"> </span><span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&quot;Correctly inflect words and numbers&quot;</span>
<span class="w"> </span><span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">&quot;https://github.com/jazzband/inflect&quot;</span>
<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz&quot;</span>

<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;MIT&quot;</span>
<span class="w"> </span><span class="nv">SLOT</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
<span class="w"> </span><span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">&quot;~amd64 ~arm64 ~ia64 ~ppc ~ppc64 ~x86&quot;</span>

<span class="hll"><span class="w"> </span>distutils_enable_sphinx<span class="w"> </span>docs<span class="w"> </span><span class="se">\</span>
</span><span class="hll"><span class="w">     </span><span class="s1">&#39;&gt;=dev-python/jaraco-packaging-3.2&#39;</span><span class="w"> </span><span class="se">\</span>
</span><span class="hll"><span class="w">     </span><span class="s1">&#39;&gt;=dev-python/rst-linker-1.9&#39;</span><span class="w"> </span><span class="se">\</span>
</span><span class="hll"><span class="w">     </span>dev-python/alabaster
</span></pre></div>
</div>
<p>In this case, the function uses the any-r1 API to request one
of the supported implementations to be enabled on <em>all</em> of those
packages.  However, it does not have to be the one in <code class="docutils literal notranslate"><span class="pre">PYTHON_TARGETS</span></code>
for this package.</p>
</section>
<section id="sphinx-without-autodoc-or-extensions">
<h3>Sphinx without autodoc or extensions<a class="headerlink" href="#sphinx-without-autodoc-or-extensions" title="Link to this heading"></a></h3>
<p>Finally, there are packages that use Sphinx purely to build
documentation from text files, without inspecting Python code.
For those packages, the any-r1 API can be omitted entirely and plain
dependency on <code class="docutils literal notranslate"><span class="pre">dev-python/sphinx</span></code> is sufficient.  In this case,
the <code class="docutils literal notranslate"><span class="pre">--no-autodoc</span></code> option can be specified instead of additional
packages.</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>

<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>

<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python2_7<span class="w"> </span>python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span><span class="w"> </span><span class="o">)</span>
<span class="w"> </span>inherit<span class="w"> </span>distutils-r1

<span class="w"> </span><span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&quot;Python Serial Port extension&quot;</span>
<span class="w"> </span><span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">&quot;https://github.com/pyserial/pyserial https://pypi.org/project/pyserial/&quot;</span>
<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz&quot;</span>

<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;PSF-2&quot;</span>
<span class="w"> </span><span class="nv">SLOT</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
<span class="w"> </span><span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">&quot;~alpha amd64 ~arm arm64 ~hppa ~ia64 ~m68k ~mips ~ppc ~ppc64 ~s390 ~sh ~sparc ~x86&quot;</span>

<span class="hll"><span class="w"> </span>distutils_enable_sphinx<span class="w"> </span>documentation<span class="w"> </span>--no-autodoc
</span></pre></div>
</div>
<p>Note that this is valid only if no third-party extensions are used.
If additional packages need to be installed, the previous variant
must be used instead.</p>
<p>The eclass tries to automatically determine whether <code class="docutils literal notranslate"><span class="pre">--no-autodoc</span></code>
should be used, and issue a warning if it’s missing or incorrect.</p>
</section>
</section>
<section id="packages-with-optional-python-build-system-usage">
<span id="index-23"></span><span id="index-22"></span><h2>Packages with optional Python build system usage<a class="headerlink" href="#packages-with-optional-python-build-system-usage" title="Link to this heading"></a></h2>
<p>The eclass has been written with the assumption that the vast majority
of its consumers will be using the Python build systems unconditionally.
For this reason, it sets the ebuild metadata variables (dependencies,
<code class="docutils literal notranslate"><span class="pre">REQUIRED_USE</span></code>) and exports phase functions by default.  However, it
also provides support for <em>optional mode</em> that can be used when Python
is used conditionally to USE flags.</p>
<p>If <code class="docutils literal notranslate"><span class="pre">DISTUTILS_OPTIONAL</span></code> is set to a non-empty value, then the eclass
does not alter ebuild metadata or export phase functions by default.
The ebuild needs to declare appropriate dependencies
and <code class="docutils literal notranslate"><span class="pre">REQUIRED_USE</span></code> explicitly, and call the appropriate phase
functions.</p>
<p>The <code class="docutils literal notranslate"><span class="pre">PYTHON_DEPS</span></code> and <code class="docutils literal notranslate"><span class="pre">PYTHON_REQUIRED_USE</span></code> variables provided
by the underlying Python eclasses should be used, as if using these
eclasses directly.  Furthermore, in PEP 517 mode an additional
<code class="docutils literal notranslate"><span class="pre">DISTUTILS_DEPS</span></code> variable is exported that contains build-time
dependnecies specific to wheel build and install, and should be added
to <code class="docutils literal notranslate"><span class="pre">BDEPEND</span></code>.</p>
<p>At the very least, the phases having default <a class="reference internal" href="#sub-phase-functions">sub-phase functions</a> need
to be called, that is:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">distutils-r1_src_prepare</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">distutils-r1_src_compile</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">distutils-r1_src_install</span></code></p></li>
</ul>
<p>Additional phases need to be called if the ebuild declares sub-phase
functions for them.</p>
<p>Note that in optional mode, the default implementation
of <code class="docutils literal notranslate"><span class="pre">distutils-r1_python_prepare_all</span></code> does not apply patches (to avoid
collisions with other eclasses).</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>The <code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code> and <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> alter
the ebuild metadata variables and declare sub-phase functions
independently of the value of <code class="docutils literal notranslate"><span class="pre">DISTUTILS_OPTIONAL</span></code>.  However,
in order for the respective sub-phases to be executed the ebuild
needs to call appropriate eclass phase functions (i.e. additionally
call <code class="docutils literal notranslate"><span class="pre">distutils-r1_src_test</span></code> for the latter).</p>
<p>If unconditional test dependencies are undesirable, these functions
cannot be used, and appropriate dependencies and sub-phases need
to be declared explicitly.</p>
<p>In the legacy mode, the <code class="docutils literal notranslate"><span class="pre">DISTUTILS_USE_SETUPTOOLS</span></code> variable is
not used if the optional mode is enabled.  Instead, the dependency
on <code class="docutils literal notranslate"><span class="pre">dev-python/setuptools</span></code> needs to be declared explicitly.</p>
</div>
<p>An example ebuild for a package utilizing autotools as a primary build
system alongside a flit-based <code class="docutils literal notranslate"><span class="pre">pyproject.toml</span></code> in the top directory
follows:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2022 Gentoo Authors</span>
<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>

<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">8</span>

<span class="hll"><span class="w"> </span><span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>flit
</span><span class="hll"><span class="w"> </span><span class="nv">DISTUTILS_OPTIONAL</span><span class="o">=</span><span class="m">1</span>
</span><span class="hll"><span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python3_<span class="o">{</span><span class="m">8</span>..10<span class="o">}</span><span class="w"> </span>pypy3<span class="w"> </span><span class="o">)</span>
</span><span class="hll">
</span><span class="hll"><span class="w"> </span>inherit<span class="w"> </span>distutils-r1
</span>
<span class="w"> </span><span class="c1"># ...</span>
<span class="hll"><span class="w"> </span><span class="nv">IUSE</span><span class="o">=</span><span class="s2">&quot;python test&quot;</span>
</span><span class="hll"><span class="w"> </span><span class="nv">REQUIRED_USE</span><span class="o">=</span><span class="s2">&quot;</span>
</span><span class="hll"><span class="s2">     python? ( </span><span class="si">${</span><span class="nv">PYTHON_REQUIRED_USE</span><span class="si">}</span><span class="s2"> )&quot;</span>
</span>
<span class="w"> </span><span class="nv">DEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">     dev-libs/libfoo:=&quot;</span>
<span class="w"> </span><span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">     </span><span class="si">${</span><span class="nv">DEPEND</span><span class="si">}</span>
<span class="hll"><span class="s2">     python? (</span>
</span><span class="hll"><span class="s2">         </span><span class="si">${</span><span class="nv">PYTHON_DEPS</span><span class="si">}</span>
</span><span class="hll"><span class="s2">         dev-python/frobnicate[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
</span><span class="hll"><span class="s2">     )&quot;</span>
</span><span class="w"> </span><span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="hll"><span class="s2">     python? (</span>
</span><span class="hll"><span class="s2">         </span><span class="si">${</span><span class="nv">PYTHON_DEPS</span><span class="si">}</span>
</span><span class="hll"><span class="s2">         </span><span class="si">${</span><span class="nv">DISTUTILS_DEPS</span><span class="si">}</span>
</span><span class="hll"><span class="s2">         test? (</span>
</span><span class="hll"><span class="s2">             dev-python/frobnicate[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
</span><span class="hll"><span class="s2">             dev-python/pytest[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
</span><span class="hll"><span class="s2">         )</span>
</span><span class="hll"><span class="s2">     )&quot;</span>
</span>
<span class="w"> </span>src_prepare<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">     </span>default
<span class="hll"><span class="w">     </span>use<span class="w"> </span>python<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span>distutils-r1_src_prepare
</span><span class="w"> </span><span class="o">}</span>

<span class="w"> </span>src_compile<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">     </span>default
<span class="hll"><span class="w">     </span>use<span class="w"> </span>python<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span>distutils-r1_src_compile
</span><span class="w"> </span><span class="o">}</span>

<span class="hll"><span class="w"> </span>python_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
</span><span class="hll"><span class="w">     </span>epytest
</span><span class="hll"><span class="w"> </span><span class="o">}</span>
</span>
<span class="w"> </span>src_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">     </span>default
<span class="hll"><span class="w">     </span>use<span class="w"> </span>python<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span>distutils-r1_src_test
</span><span class="w"> </span><span class="o">}</span>

<span class="w"> </span>src_install<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">     </span>default
<span class="hll"><span class="w">     </span>use<span class="w"> </span>python<span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span>distutils-r1_src_install
</span><span class="w"> </span><span class="o">}</span>
</pre></div>
</div>
</section>
<section id="packages-with-rust-extensions-using-cargo">
<span id="index-24"></span><h2>Packages with Rust extensions (using Cargo)<a class="headerlink" href="#packages-with-rust-extensions-using-cargo" title="Link to this heading"></a></h2>
<p>Some Python build systems include support for writing extensions
in the Rust programming language.  Two examples of these are setuptools
using <code class="docutils literal notranslate"><span class="pre">dev-python/setuptools_rust</span></code> plugin and Maturin.  Normally,
these build systems utilize the Cargo ecosystem to automatically
download the Rust dependencies over the Internet.  In Gentoo,
<code class="docutils literal notranslate"><span class="pre">cargo.eclass</span></code> is used to provide these dependencies to ebuilds.</p>
<p>When creating a new ebuild for a package using Rust extensions
or bumping one, you need to locate the <code class="docutils literal notranslate"><span class="pre">Cargo.lock</span></code> files within
the package’s sources.  Run <code class="docutils literal notranslate"><span class="pre">pycargoebuild</span></code> passing the list of
the containing directories to generate a template ebuild, e.g.:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>pycargoebuild<span class="w"> </span>/tmp/portage/dev-python/setuptools-rust-1.5.2/work/setuptools-rust-1.5.2/examples/*/
</pre></div>
</div>
<p>The actual ebuild inherits both <code class="docutils literal notranslate"><span class="pre">cargo</span></code> and <code class="docutils literal notranslate"><span class="pre">distutils-r1</span></code> eclasses.
Prior to inherit, <code class="docutils literal notranslate"><span class="pre">CARGO_OPTIONAL</span></code> should be used to avoid exporting
phase functions, and <code class="docutils literal notranslate"><span class="pre">CRATES</span></code> should be declared.  <code class="docutils literal notranslate"><span class="pre">SRC_URI</span></code> needs
to contain URLs generated using <code class="docutils literal notranslate"><span class="pre">cargo_crate_uris</span></code>, and <code class="docutils literal notranslate"><span class="pre">LICENSE</span></code>
the crate licenses in addition to the Python package’s license.
<code class="docutils literal notranslate"><span class="pre">QA_FLAGS_IGNORED</span></code> needs to match all Rust extensions in order
to prevent false positives on ignored <code class="docutils literal notranslate"><span class="pre">CFLAGS</span></code> and <code class="docutils literal notranslate"><span class="pre">LDFLAGS</span></code>
warnings.  Finally, the ebuild needs to call <code class="docutils literal notranslate"><span class="pre">cargo_src_unpack</span></code>.</p>
<p>Note that some Rust/Python packages use both Rust-level and Python-level
tests.  To check for this, it is a good idea to run <code class="docutils literal notranslate"><span class="pre">cargo</span> <span class="pre">test</span></code>
manually and see if any tests are run.  If they are, <code class="docutils literal notranslate"><span class="pre">cargo_src_test</span></code>
should be called in <code class="docutils literal notranslate"><span class="pre">python_test_all()</span></code> (or possibly <code class="docutils literal notranslate"><span class="pre">python_test()</span></code>
if they specifically use Python linkage).</p>
<p>An example ebuild follows:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 2022 Gentoo Authors</span>
<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>

<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">8</span>

<span class="hll"><span class="w"> </span><span class="nv">CARGO_OPTIONAL</span><span class="o">=</span><span class="m">1</span>
</span><span class="w"> </span><span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>setuptools
<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python3_<span class="o">{</span><span class="m">8</span>..10<span class="o">}</span><span class="w"> </span>pypy3<span class="w"> </span><span class="o">)</span>

<span class="hll"><span class="w"> </span><span class="nv">CRATES</span><span class="o">=</span><span class="s2">&quot;</span>
</span><span class="hll"><span class="s2">     Inflector-0.11.4</span>
</span><span class="hll"><span class="s2">     aliasable-0.1.3</span>
</span><span class="hll"><span class="s2">     asn1-0.8.7</span>
</span><span class="hll"><span class="s2">     asn1_derive-0.8.7</span>
</span><span class="hll"><span class="s2"> &quot;</span>
</span>
<span class="hll"><span class="w"> </span>inherit<span class="w"> </span>cargo<span class="w"> </span>distutils-r1
</span>
<span class="w"> </span><span class="c1"># ...</span>

<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">     mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz</span>
<span class="hll"><span class="s2">     </span><span class="k">$(</span>cargo_crate_uris<span class="w"> </span><span class="si">${</span><span class="nv">CRATES</span><span class="si">}</span><span class="k">)</span>
</span><span class="s2"> &quot;</span>

<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;|| ( BSD-2 Apache-2.0 )&quot;</span>
<span class="w"> </span><span class="c1"># Crate licenses</span>
<span class="hll"><span class="w"> </span><span class="nv">LICENSE</span><span class="o">+=</span><span class="s2">&quot; Apache-2.0 BSD BSD-2 MIT&quot;</span>
</span>
<span class="w"> </span><span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="hll"><span class="s2">     dev-python/setuptools-rust[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
</span><span class="s2"> &quot;</span>

<span class="w"> </span><span class="c1"># Rust does not respect CFLAGS/LDFLAGS</span>
<span class="hll"><span class="w"> </span><span class="nv">QA_FLAGS_IGNORED</span><span class="o">=</span><span class="s2">&quot;.*/_rust.*&quot;</span>
</span>
<span class="w"> </span>src_unpack<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="hll"><span class="w">     </span>cargo_src_unpack
</span><span class="w"> </span><span class="o">}</span>

<span class="w"> </span>python_test_all<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">     </span><span class="nb">cd</span><span class="w"> </span>src/rust<span class="w"> </span><span class="o">||</span><span class="w"> </span>die
<span class="hll"><span class="w">     </span>cargo_src_test
</span><span class="w"> </span><span class="o">}</span>
</pre></div>
</div>
</section>
<section id="installing-packages-without-a-pep-517-build-backend">
<h2>Installing packages without a PEP 517 build backend<a class="headerlink" href="#installing-packages-without-a-pep-517-build-backend" title="Link to this heading"></a></h2>
<p>The eclass features a special ‘no build system’ that is dedicated
to packages that could benefit from distutils-r1 features yet either
do not use a PEP 517-compliant build system, or cannot use one.  This
generally means that either:</p>
<ul class="simple">
<li><p>it uses a non-PEP 517 build system (autotools, CMake, plain Meson)</p></li>
<li><p>it does not feature a build system at all</p></li>
<li><p>its build system cannot be used as that would cause cyclic
dependencies during build backend bootstrap</p></li>
</ul>
<p>This mode is not supposed to be used for legacy use of distutils or
setuptools — these are handled via the setuptools backend.</p>
<p>The use cases for this mode partially overlap with the use of other
Python eclasses, particularly python-single-r1.  Using distutils-r1
is recommended if one of the eclass features benefits the particular
ebuild, e.g. if Python modules are installed or one of the supported
test runners are used.  For pure bundles of Python scripts,
python-single-r1 is preferable.</p>
<p>The ‘no build system’ mode is enabled via setting the following value:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>no
</pre></div>
</div>
<p>When this mode is used, the following applies:</p>
<ul class="simple">
<li><p>no dependencies on a build backend or PEP 517 machinery are declared
(<code class="docutils literal notranslate"><span class="pre">DISTUTILS_DEPS</span></code> are empty)</p></li>
<li><p>the default implementation, <code class="docutils literal notranslate"><span class="pre">distutils-r1_python_compile</span></code> is a no-op</p></li>
</ul>
<p>However, the following eclass features are still available:</p>
<ul class="simple">
<li><p>Python interpreter dependencies, <code class="docutils literal notranslate"><span class="pre">REQUIRED_USE</span></code> and distutils-r1
phase functions are used (unless disabled via <code class="docutils literal notranslate"><span class="pre">DISTUTILS_OPTIONAL</span></code>)</p></li>
<li><p>the temporary venv is created in <code class="docutils literal notranslate"><span class="pre">${BUILD_DIR}/install</span></code> for test
phase to use (but the ebuild needs to install files there explicitly)</p></li>
<li><p>the contents of <code class="docutils literal notranslate"><span class="pre">${BUILD_DIR}/install</span></code> are merged into <code class="docutils literal notranslate"><span class="pre">${D}</span></code>
by <code class="docutils literal notranslate"><span class="pre">distutils-r1_python_install</span></code> (if present; temporary venv files
are removed)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">distutils_enable_sphinx</span></code> and <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code>
are functional</p></li>
</ul>
<section id="installing-packages-manually-into-build-dir">
<h3>Installing packages manually into BUILD_DIR<a class="headerlink" href="#installing-packages-manually-into-build-dir" title="Link to this heading"></a></h3>
<p>The simplest approach towards installing packages manually is to use
<code class="docutils literal notranslate"><span class="pre">python_domodule</span></code> in <code class="docutils literal notranslate"><span class="pre">python_compile</span></code> sub-phase.  This causes
the modules to be installed into <code class="docutils literal notranslate"><span class="pre">${BUILD_DIR}/install</span></code> tree,
effectively enabling them to be picked up for the test phase
and merged in <code class="docutils literal notranslate"><span class="pre">distutils-r1_python_install</span></code>.</p>
<p>An example ebuild using a combination of GitHub archive (for tests)
and PyPI wheel (for generated .dist-info) follows:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>

<span class="hll"><span class="w"> </span><span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>no
</span><span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python3_<span class="o">{</span><span class="m">8</span>..11<span class="o">}</span><span class="w"> </span>pypy3<span class="w"> </span><span class="o">)</span>

<span class="w"> </span>inherit<span class="w"> </span>distutils-r1

<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">     https://github.com/hukkin/tomli/archive/</span><span class="si">${</span><span class="nv">PV</span><span class="si">}</span><span class="s2">.tar.gz</span>
<span class="s2">         -&gt; </span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.gh.tar.gz</span>
<span class="s2">     https://files.pythonhosted.org/packages/py3/</span><span class="si">${</span><span class="nv">PN</span><span class="p">::</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">-py3-none-any.whl</span>
<span class="s2">         -&gt; </span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">-py3-none-any.whl.zip</span>
<span class="s2"> &quot;</span>

<span class="w"> </span><span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
<span class="s2">     app-arch/unzip</span>
<span class="s2"> &quot;</span>

<span class="hll"><span class="w"> </span>distutils_enable_tests<span class="w"> </span>unittest
</span>
<span class="w"> </span>python_compile<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="hll"><span class="w">     </span>python_domodule<span class="w"> </span>src/tomli<span class="w"> </span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">WORKDIR</span><span class="si">}</span><span class="s2">&quot;</span>/*.dist-info
</span><span class="w"> </span><span class="o">}</span>
</pre></div>
</div>
<p>Note that the wheel suffix is deliberately changed in order to enable
automatic unpacking by the default <code class="docutils literal notranslate"><span class="pre">src_unpack</span></code>.</p>
</section>
<section id="installing-packages-manually-into-d">
<h3>Installing packages manually into D<a class="headerlink" href="#installing-packages-manually-into-d" title="Link to this heading"></a></h3>
<p>The alternative approach is to install files in <code class="docutils literal notranslate"><span class="pre">python_install</span></code>
phase.  This provides a greater number of helpers.  However,
the installed modules will not be provided in the venv for the test
phase.</p>
<p>An example ebuild follows:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>

<span class="hll"><span class="w"> </span><span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>no
</span><span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>pypy3<span class="w"> </span>python3_<span class="o">{</span><span class="m">8</span>..11<span class="o">}</span><span class="w"> </span><span class="o">)</span>

<span class="w"> </span>inherit<span class="w"> </span>distutils-r1

<span class="hll"><span class="w"> </span>distutils_enable_tests<span class="w"> </span>pytest
</span>
<span class="w"> </span>python_install<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="hll"><span class="w">     </span>python_domodule<span class="w"> </span>gpep517
</span><span class="hll"><span class="w">     </span>python_newscript<span class="w"> </span>-<span class="w"> </span>gpep517<span class="w"> </span><span class="s">&lt;&lt;-EOF</span>
</span><span class="hll"><span class="s">         #!${EPREFIX}/usr/bin/python</span>
</span><span class="hll"><span class="s">         import sys</span>
</span><span class="hll"><span class="s">         from gpep517.__main__ import main</span>
</span><span class="hll"><span class="s">         sys.exit(main())</span>
</span><span class="hll"><span class="s">     EOF</span>
</span><span class="w"> </span><span class="o">}</span>
</pre></div>
</div>
<p>It is also valid to combine both approaches, e.g. install Python modules
in <code class="docutils literal notranslate"><span class="pre">python_compile</span></code>, and scripts in <code class="docutils literal notranslate"><span class="pre">python_install</span></code>.  In this case,
<code class="docutils literal notranslate"><span class="pre">distutils-r1_python_install</span></code> needs to be called explicitly.</p>
</section>
<section id="integrating-with-a-non-pep-517-build-system">
<h3>Integrating with a non-PEP 517 build system<a class="headerlink" href="#integrating-with-a-non-pep-517-build-system" title="Link to this heading"></a></h3>
<p>The ‘no build system’ mode can also be used to use distutils-r1
sub-phases to integrate with a build system conveniently.  The following
ebuild fragment demonstrates using it with Meson:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="nv">EAPI</span><span class="o">=</span><span class="m">8</span>

<span class="nv">DISTUTILS_USE_PEP517</span><span class="o">=</span>no
<span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python3_<span class="o">{</span><span class="m">8</span>..10<span class="o">}</span><span class="w"> </span><span class="o">)</span>

inherit<span class="w"> </span>meson<span class="w"> </span>distutils-r1

python_configure<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span><span class="nb">local</span><span class="w"> </span><span class="nv">emesonargs</span><span class="o">=(</span>
<span class="w">        </span>-Dlint<span class="o">=</span><span class="nb">false</span>
<span class="w">    </span><span class="o">)</span>

<span class="w">    </span>meson_src_configure
<span class="o">}</span>

python_compile<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>meson_src_compile
<span class="o">}</span>

python_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>meson_src_test
<span class="o">}</span>

python_install<span class="o">()</span><span class="w"> </span><span class="o">{</span>
<span class="w">    </span>meson_src_install
<span class="o">}</span>
</pre></div>
</div>
</section>
</section>
</section>


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









<search id="searchbox" style="display: none" role="search">
    <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" placeholder="Search"/>
      <input type="submit" value="Go" />
    </form>
    </div>
</search>
<script>document.getElementById('searchbox').style.display = "block"</script><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"><a class="reference internal" href="eclass.html">Choosing between Python eclasses</a></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 current"><a class="current reference internal" href="#">distutils-r1 — standard Python build systems</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#the-pep-517-and-legacy-modes">The PEP 517 and legacy modes</a></li>
<li class="toctree-l2"><a class="reference internal" href="#basic-use-pep-517-mode">Basic use (PEP 517 mode)</a></li>
<li class="toctree-l2"><a class="reference internal" href="#source-archives">Source archives</a></li>
<li class="toctree-l2"><a class="reference internal" href="#dependencies">Dependencies</a></li>
<li class="toctree-l2"><a class="reference internal" href="#python-single-r1-variant">python-single-r1 variant</a></li>
<li class="toctree-l2"><a class="reference internal" href="#pep-517-build-systems">PEP 517 build systems</a></li>
<li class="toctree-l2"><a class="reference internal" href="#setuptools-scm-flit-scm-hatch-vcs-pdm-backend-and-snapshots">setuptools_scm (flit_scm, hatch-vcs, pdm-backend) and snapshots</a></li>
<li class="toctree-l2"><a class="reference internal" href="#packages-installing-extensions-c-rust">Packages installing extensions (C, Rust…)</a></li>
<li class="toctree-l2"><a class="reference internal" href="#packages-using-cython">Packages using Cython</a></li>
<li class="toctree-l2"><a class="reference internal" href="#parallel-build-race-conditions">Parallel build race conditions</a></li>
<li class="toctree-l2"><a class="reference internal" href="#sub-phase-functions">Sub-phase functions</a></li>
<li class="toctree-l2"><a class="reference internal" href="#passing-arguments-to-setup-py">Passing arguments to setup.py</a></li>
<li class="toctree-l2"><a class="reference internal" href="#calling-custom-setup-py-commands">Calling custom setup.py commands</a></li>
<li class="toctree-l2"><a class="reference internal" href="#enabling-tests">Enabling tests</a></li>
<li class="toctree-l2"><a class="reference internal" href="#building-documentation-via-sphinx">Building documentation via Sphinx</a></li>
<li class="toctree-l2"><a class="reference internal" href="#packages-with-optional-python-build-system-usage">Packages with optional Python build system usage</a></li>
<li class="toctree-l2"><a class="reference internal" href="#packages-with-rust-extensions-using-cargo">Packages with Rust extensions (using Cargo)</a></li>
<li class="toctree-l2"><a class="reference internal" href="#installing-packages-without-a-pep-517-build-backend">Installing packages without a PEP 517 build backend</a></li>
</ul>
</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="multi.html" title="previous chapter">python-r1 — multi-impl packages</a></li>
      <li>Next: <a href="test.html" title="next chapter">Tests in Python packages</a></li>
  </ul></li>
</ul>
</div>








        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="footer">
      &#169;2020, Michał Górny, license: CC BY 4.0.
      
      |
      Powered by <a href="https://www.sphinx-doc.org/">Sphinx 8.1.3</a>
      &amp; <a href="https://alabaster.readthedocs.io">Alabaster 1.0.0</a>
      
      |
      <a href="_sources/distutils.rst.txt"
          rel="nofollow">Page source</a>
    </div>

    

    
  </body>
</html>