プラットフォームの互換性タグ¶
プラットフォーム相互互換性タグは、特定のプラットフォームと互換であるとビルドツールが配布物にマークを付けることができるようにし、インストーラが自身が動作しているシステムと互換であるのはどの配布物であるかを理解できるようにします。
概要¶
タグの書式は、 {python tag}-{abi tag}-{platform tag}
です。
- python タグ
'py27' ・ 'cp33'
- abi タグ
'cp33dmu' ・ 'none'
- プラットフォームタグ
'linux_x86_64' ・ 'any'
例えば、py27-none-any
というタグは、abi に対する要求なしに任意のプラットフォームで Python 2.7 (任意の Python 2.7 実装) との互換性を持つことを意味します。
wheel
ビルド済みパッケージのフォーマットは、ファイル名の中にこのようなタグを {distribution}-{version}(-{build tag})?-{python tag}-{abitag}-{platform tag}.whl
の形で包含しています。他のパッケージフォーマットにはそれぞれ独自の慣習があるかもしれません。
どのようなタグであれ、その中に潜在的に含まれる空白文字は _
で置換されるべきです。
Python タグ¶
Python タグは、配布物が必要とする実装やバージョンを示します。主要な実装には短縮系のコードがあって、当初は:
py: 一般的な Python (実装に特有な機能を要求しません)
cp: CPython
ip: IronPython
pp: PyPy
jy: Jython
他の Python 実装には sys.implementation.name
を用いるべきです。
バージョンは py_version_nodot
です。 CPython は no dot にせずに済ませますが、必要な場合には代わりにアンダースコア文字 _
が使用されます。 PyPy は、おそらく、ここに pp18
や pp19
といったそれ自身のバージョンを使います。
多くの純 Python 配布物では、バージョンは 2
や 3
や py2
・ py3
といったメジャーバージョンだけにしておくことができます。
重要なことは、 py2
や py3
のような major-version-only タグは py20
や py30
の短縮形であるわけではないということです。そうではなくて、これらのタグは、パッケージ作成者がいくつものバージョンに互換性を持つ配布物を意図的にリリースしたのです。
単一ソースで Python 2/3 に互換性を持つ配布物は、合成タグ py2.py3
を用いることができます。 後述の タグの圧縮された組み合わせ を参照してください。
ABI タグ¶
ABI タグは、いずれかの拡張モジュールによってどのような Python ABI が要求されているのかを示します。実装依存の ABI 群については、実装 (の名前) は、たとえば cp33d
がデバッグオプション付きの CPython 3.3 ABI のことを指すように、 Python タグと同様のやり方で短縮したものを使います。
CPython の安定版 ABI のことは、共有ライブラリの拡張子と同様に abi3
と書きます。
非常に不安定な ABI を持つ実装は、そのソースコードのリビジョンやコンパイラフラグその他の SHA-256 ハッシュ値の最初の6バイトを (BASE64にエンコードされた8文字として) 用いても構いませんが、おそらくはバイナリ配布物を配布することには大きな需要はないでしょう。それぞれの実装のコミュニティで ABI タグをどのように用いるのが最適かを決定すればよいでしょう。
プラットフォームタグ¶
基本的なプラットフォームタグ¶
最も単純な形式では、プラットフォームタグは、 sysconfig.get_platform()
(の出力) のすべてのハイフン -
と ピリオド .
をアンダースコア _
で置き換えたものです。 Python 3.12 における distutils の削除があるまでは、これは distutils.util.get_platform()
でした。例えば:
win32
linux_i386
linux_x86_64
manylinux
¶
上記のような単純なスキームでは、Linux プラットフォーム向けに公開するための wheel ファイルの配布物用としては不十分で、それは、 Linux プラットフォーム群が巨大なエコシステムであって、プラットフォーム間に微妙な際が見られるためです。
代わりに、そのようなプラットフォーム向けには、 manylinux
という標準が Linux プラットフォームの共通のサブセットを体現していて、 manylinux
プラットフォームタグを付けて wheel をビルドすることで一般的な Linux のディストリビューションのほとんどで使えるようにすることができます。
The current standard is the future-proof manylinux_x_y
standard. It defines
tags of the form manylinux_x_y_arch
, where x
and y
are glibc major
and minor versions supported (e.g. manylinux_2_24_xxx
should work on any
distro using glibc 2.24+), and arch
is the architecture, matching the value
of sysconfig.get_platform()
on the system as in the "simple" form above.
この後に述べる古めのタグ群は、後方互換性のために今もサポートされています:
manylinux1
は、x86_64
とi686
のアーキテクチャで libc 2.5 をサポートしています。manylinux2010
は、x86_64
とi686
上で libc 2.12 をサポートしています。manylinux2014
は、x86_64
・i686
・aarch64
・armv7l
・ppc64
・ppc64le
・s390x
上で glibc 2.17 をサポートしています。
一般に、古めのバージョンの仕様向けにビルドされた配布物には前方互換性があります (というのは、 manylinux1
の配布物はより新しいシステムでも同様に動作するはずだということです) が、後方互換性はありません (manylinux2010
の配布物が 2010 年よりも前に存在していたプラットフォームで動作するとは想定されていないということです) 。
manylinux1
と manylinux2010
は既に end-of-life に達していて、提供されているビルド環境にはもはやセキュリティアップデートが提供されることはないであろうという警告されていることもあって、パッケージ保守者は最も互換性のある仕様をターゲットにするように努力するべきです。
適切なプロジェクトがサポートするさまざまな manylinux
標準の最低限のバージョンを次に掲げる表に示します:
ツール |
|
|
|
|
---|---|---|---|---|
pip |
|
|
|
|
auditwheel |
|
|
|
|
musllinux
¶
The musllinux
family of tags is similar to manylinux
, but for Linux
platforms that use the musl libc rather than glibc (a prime example being Alpine
Linux). The schema is musllinux_x_y_arch
, supporting musl x.y
and higher
on the architecture arch
.
musl のバージョンの値は、 Python インタープリタが現在その上で走行している musl libc 共有ライブラリを実行し、その出力を字句解析することで得られます:
import re
import subprocess
def get_musl_major_minor(so: str) -> tuple[int, int] | None:
"""Detect musl runtime version.
Returns a two-tuple ``(major, minor)`` that indicates musl
library's version, or ``None`` if the given libc .so does not
output expected information.
The libc library should output something like this to stderr::
musl libc (x86_64)
Version 1.2.2
Dynamic Program Loader
"""
proc = subprocess.run([so], stderr=subprocess.PIPE, text=True)
lines = (line.strip() for line in proc.stderr.splitlines())
lines = [line for line in lines if line]
if len(lines) < 2 or lines[0][:4] != "musl":
return None
match = re.match(r"Version (\d+)\.(\d+)", lines[1])
if match:
return (int(match.group(1)), int(match.group(2)))
return None
Python インタープリタがその上で走行している musl ライブラリの場所を見つけるためには、現在、二つの可能なやり方があり、ひとつはシステムの ldd コマンドによるもの、もうひとつは 実行ファイルの ELF ヘッダから PT_INTERP
セクションの値をパースする方法です。
macOS¶
macOS uses the macosx
family of tags (the x
suffix is a historical
artefact of Apple's official macOS naming scheme). The schema for compatibility
tags is macosx_x_y_arch
, indicating that the wheel is compatible
with macOS x.y
or later on the architecture arch
.
The values of x
and y
correspond to the major and minor version number of
the macOS release, respectively. They must both be positive integers, with the
x
value being >= 10
. The version number always includes a major and
minor version, even if Apple's official version numbering only refers to
the major value. For example, macosx_11_0_arm64
indicates compatibility
with macOS 11 or later.
macOS binaries can be compiled for a single architecture, or can include support
for multiple architectures in the same binary (sometimes called "fat" binaries).
To indicate support for a single architecture, the value of arch
must match
the value of platform.machine()
on the system. To indicate
support multiple architectures, the arch
tag should be an identifier from
the following list that describes the set of supported architectures:
|
Architectures supported |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
The minimum supported macOS version may also be constrained by architecture. For example, macOS 11 (Big Sur) was the first release to support arm64. These additional constraints are enforced transparently by the macOS compilation toolchain when building binaries that support multiple architectures.
Android¶
Android uses the schema android_apilevel_abi
, indicating
compatibility with the given Android API level or later, on the given ABI. For
example, android_27_arm64_v8a
indicates support for API level 27 or later,
on arm64_v8a
devices. Android makes no distinction between physical devices
and emulated devices.
The API level should be a positive integer. This is not the same thing as the user-facing Android version. For example, the release known as Android 12 (code named "Snow Cone") uses API level 31 or 32, depending on the specific Android version in use. Android's release documentation contains the full list of Android versions and their corresponding API levels.
There are 4 supported ABIs. Normalized according to the rules above, they are:
armeabi_v7a
arm64_v8a
x86
x86_64
Virtually all current physical devices use one of the ARM architectures. x86
and x86_64
are supported for use in the emulator. x86
has not been
supported as a development platform since 2020, and no new emulator images have
been released since then.
iOS¶
iOS uses the schema ios_x_y_arch_sdk
, indicating compatibility with
iOS x.y
or later, on the arch
architecture, using the sdk
SDK.
The value of x
and y
correspond to the major and minor version number of
the iOS release, respectively. They must both be positive integers. The version
number always includes a major and minor version, even if Apple's official
version numbering only refers to the major value. For example, a
ios_13_0_arm64_iphonesimulator
indicates compatibility with iOS 13 or later.
The value of arch
must match the value of platform.machine()
on
the system.
The value of sdk
must be either iphoneos
(for physical devices), or
iphonesimulator
(for device simulators). These SDKs have the same API
surface, but are incompatible at the binary level, even if they are running on
the same CPU architecture. Code compiled for an arm64 simulator will not run on
an arm64 device.
The combination of arch_sdk
is referred to as the "multiarch". There
are three possible values for multiarch:
arm64_iphoneos
, for physical iPhone/iPad devices. This includes every iOS device manufactured since ~2015;arm64_iphonesimulator
, for simulators running on Apple Silicon macOS hardware; andx86_64_iphonesimulator
, for simulators running on x86_64 hardware.
使い方¶
タグ類は、 (もしダウンロードが必要なら) 選択可能なビルド済配布物のリストの中からどれをダウンロードするのかをインストーラが決定するために使われます。インストーラは、自身がサポートする (pyver, abi, arch) タプルのリストを維持管理しています。ビルド済配布物のタグがリストに含まれて (in
) いれば、それをインストールすることができます。
古い Python リリース向けに発行された純 Python のバージョンにフォールバックするよりも前に、利用できる中で最も機能を網羅したビルド済配布物 (インストールする先の環境に最も適したもの) をインストーラがデフォルトで選択することが推奨されています。インストーラは、また、受け入れ可能な互換性タグのリストを設定変更したり順序を入れ替えたりする方法を持つことが推奨されています; 例えば、ユーザは、純 Python であると広報しているビルド済みパッケージだけをダウンロードするために、 *-none-any
タグだけを受容しても構いません。
互換性はあるがもはや古くなってしまったビルド済みのものを使う選択肢よりもより好ましいという点で、インストーラに望まれるもうひとつの機能は "可能ならソースコードから再コンパイルする" でしょう。
この事例集は、インストーラを linux_x86_64 システム上の CPython 3.3 のもとで走らせるためのものです。最も好ましいもの (最新版の Python 向けにビルドされたコンパイル済みの拡張モジュールが付属している配布物) から、最も好ましくはないもの (古いバージョンの Python でビルドされた純 Python の配布物) へ、という順序で並んでいます:
cp33-cp33m-linux_x86_64
cp33-abi3-linux_x86_64
cp3-abi3-linux_x86_64
cp33-none-linux_x86_64*
cp3-none-linux_x86_64*
py33-none-linux_x86_64*
py3-none-linux_x86_64*
cp33-none-any
cp3-none-any
py33-none-any
py3-none-any
py32-none-any
py31-none-any
py30-none-any
ビルド済み配布物は、サブプロセスとして起動されるネーティブの実行可能ファイルを含んでいるなどのようなC 言語拡張以外の理由によって、特定のプラットフォーム向けであっても構いません。
時々、あるパッケージの特定のバージョンとして複数のビルド済み配布物が存在することがあるでしょう。例えば、パッケージ製作者が、 cp33-abi3-linux_x86_64
というタグを付けて追加的な C 言語拡張を含むパッケージをリリースし、そのようなものを含まない同じ配布物に py3-none-any
というタグを付けてリリースするような場合です。(このような場合でも) サポートされるタグのリストで先に出現する方を優先するという理由によって C 言語拡張付きのパッケージがそうでないパッケージよりも選好されてインストールされるという形で、インデックスによってどちらかに決めることができます。
圧縮されたタグのセット¶
bdists のコンパクトなファイル名で、互換性のあるタグトリプルが複数ある場合にもきちんと動作するものを許容するためには、代わりにファイル名の中のそれぞれのタグが '.' で分割可能でありソート可能であるような一連のタグになっていることが可能です。例えば、 pip は純 Python のパッケージで、同一のソースコードで Python 2 でも 3 でも動作するように書かれていますが、これは py2.py3-none-any
というタグを付けた bdist として配布することができるでしょう。単純なタグの完全なリストは:
for x in pytag.split('.'):
for y in abitag.split('.'):
for z in platformtag.split('.'):
yield '-'.join((x, y, z))
このスキームを実装する bdist フォーマットは、拡張されたタグ群を bdist に特有のメタデータの中に含んでいるべきです。この圧縮スキームは、サポートされていないタグや例えば "cp33-cp31u-win64" のようにいかなる Python 実装においてもサポートされていない "不可能な" タグを大量に生成すると思われるので、控えめに使うようにしてください。
FAQ¶
- デフォルトではどんなタグが使われますか?
ツール類は、
cp33-cp33m-win32
のようなアーキテクチャへの依存を示すタグやpy33-none-any
のような純 Python タグの中で最も好ましいものをデフォルトで採用するべきです。パッケージ製作者がデフォルトをオーバーライドしていたとすれば、それは彼らが異なる Python 間での互換性を提供しようという意図があったことを示しています。- 自分の配布物が最新版の Python と相容れない機能を使っているとしたら、どんなタグを使いますか?
互換性タグは、インストーラがある配布物の 単一のバージョン の 最も互換性がある ビルドを選択する際に助けとなります。例えば、 (Python 3.4 に特有の機能を使っている)
beaglevote-1.2.0``には Python 3.3 と互換性を持つビルドがひとつもないという場合でも、 ``py34-none-any
タグの代わりにpy3-none-any
タグを使っても構いません。 Python 3.3 のユーザが互換性のあるビルドを得るためには、新しい機能を使う前のリリースであるbeaglevote-1.1.0
用の要求 (requirement) などを他の指定子を組み合わせなければなりません。- Python のバージョン番号に
.
がないのはなぜですか? CPython は、数字3個のメジャーリリースなしで 20 年以上にわたって存続してきました。これはしばらくの間は続くに違いありません。 - や . が周辺のファイル名を区切る役割を果たしているので、他の実装では _ を区切り子として使っても構いません。
- ハイフンやその他の英数字以外の文字をアンダースコアに正規化するのはなぜですか?
ファイル名の部分部分を区分けする
.
文字や-
文字との干渉を避けるために、かつ、 (クォートすることなく URL パス内で使用可能であることを含む) 数多あるファイルシステムのファイル名に対する制限事項との間のより良い互換性のために。- 何故、
.
や-
の代わりに特殊な文字 <X> を使わないのですか? それは、その文字が不便であるかコンテクストによっては潜在的に混乱を招きやすい (例えば
+
は URL 内ではクォートしなければなりませんし、~
は POSIX でユーザのホームディレクトリを示すために使われます) から、あるいは、 PEP 427 で定義された wheel フォーマットを参照して作成された既存の参照実装を変更すること (例えば、圧縮タグで部分部分を分割するのに.
ではなく,
を使うようにすること) を正当化するに足りるだけのアドバンテージがないから、のいずれかです。- 誰が実装に関する短縮形のレジストリの維持管理をしているのですか?
python-dev メーリングリストで要求することで、新しい2文字省略形の割り当てを受けることができるでしょう。経験上は、その時点で最も卓越した4個の実装のために省略形が予約されています。
- 互換性タグは METADATA に含まれるのか、あるいは PKG-INFO か?
否。互換性タグはビルド済み配布物のメタデータの一部です。METADATA / PKG-INFO は、その配布物の単一のビルドではなく配布物の全体にとって正当なものであるべきです。
- どうして私のお気に入りの Python 実装について言及しなかったの?
省略形タグは、コンパイル済みの Python コードを公開のインデックスでシェアすることを促進します。あなたの Python 実装においてもこの仕様を使うことができますが、しかしもっと長いタグになってしまうことでしょう。すべての "純 Python" なビルド済み配布物が単に
py
を使うだけであることを思い出してください。- どうして参照実装における ABI タグ (第2のタグ) は時々 "none" なのですか?
Python 2 では SOABI (より新しい版の Python 3 から来た概念) を作成する簡単な方法がないので、本稿執筆時点の参照実装は "none" なのです。理想的には、それはもっと新しい版の Python に相似の "py27(d|m|u)" を検出するようになるでしょうが、それまでの間は "知られていない" ことを示すのに "none" とすることが必要十分な方法なのです。
歴史¶
2013年2月: PEP 425 を通じてこの仕様の元々のバージョンが承認されました。
2016年1月: PEP 513 を通じて
manylinux1
タグが承認されました。2018年4月: PEP 571 を通じて
manylinux2010
タグが承認されました。2019年7月: PEP 599 を通じて
manylinux2014
タグが承認されました。2019年11月: PEP 600 を通じて多年性の
manylinux_x_y
タグが承認されました。2021年4月: PEP 656 を通じて
musllinux_x_y
タグが承認されました。December 2023: The tags for iOS were approved through PEP 730.
March 2024: The tags for Android were approved through PEP 738.