Numpyのため趣味的にPython 3.10をmakeする（M1 Mac: arm64アークテクチャ）

# はじめに
 　M1 Mac (mac OS Monterey) を手に入れて、デフォルトで入るPython 3.8を使ってみたらNumpyが入らない。調べてみれば、下の記事にあるように、Python 3.9以上のバージョンならばpipからNumpyはインストールできるし、新しいバージョンのPython自体もcondaやHomebrewから簡単にインストールできるとの事[^h1]。

[^h1]: [macOS 64-bit universal2 installer](https://www.python.org/downloads/macos/)という物もあり...。

https://qiita.com/ketaro-m/items/ebae35c49d55aa86dfcf

　この時点で、素直に上記の方法に従えさえすれば問題 (Python3とNumpyのインストール) は解決できます。この記事ではあえてそれを傍に置き、condaもHomebrewも使わずにソースコードからPython 3.10をmakeして、M1 Macにをインストールする方法を記します。Python 3.9などバージョンが違っていてもインストール方法はほぼ変わりません。

　Python 3.10のインストールは以下の手順で行います:

1. OpenSSLとPythonソースコードのダウンロード
1. OpenSSLのmake
1. Pythonのmake
1. Pythonとpipの実行
1. Pathの設定

また、Mac/README.rstの邦訳を付録として付けました（本編より長いです）。一通り読むと、MacOSにPythonをインストールする際に必要となる条件の理由が理解できます、

# OpenSSLはなぜ必要？
　Pythonのインストールなのに、手順にOpenSSLが登場しています。なぜなら、OpenSSLはPython上でhttps通信等を行う為に必要となるからです。別にPythonでそんな処理なんてしないし...。と思って入れないと、次の最悪の事が起こります。

:::note alert
Pythonと一緒にインストールされるpipはhttpsプロトコルで通信を行う為、OpenSSL抜きでPythonをmakeした場合、通信が失敗してインターネット経由でモジュールを一つも追加できなくなります。
:::

https://www.python.jp/news/wnpython310/require-openssl11.html

上の記事曰く、OpenSSLはOSにプリインストールされている物でも大丈夫らしいのですが、実はMacに標準でインストールされているOpenSSLの正体はLibreSSLなので、OpenSSLを使うならインストールが必要となります。HomebrewからOpenSSLもインストールできるそうなのだけど、今回は使わないのでこちらもmakeでインストールします。



# OpenSSLとPythonソースコードのダウンロード
　以下からソースコードをダウンロードします。この記事を執筆した2023年3月時点より新しいバージョン (場合によっては致命的なバグのアップデートバージョン) がリリースされている可能性があるので、配布元のサイトを確認する様にしてください。

* Python 3.10 (https://www.python.org/downloads/source/)
  * 最新安定版 (2023年3月): 3.10.3 (https://www.python.org/ftp/python/3.10.3/Python-3.10.3.tgz)
* OpenSSL (https://www.openssl.org/source/)
  * 最新安定版 (2023年3月): 1.1.1n (https://www.openssl.org/source/openssl-1.1.1n.tar.gz)

ダウンロードしたたtarballは、`% tar zxvf　XXX.tar.gz`等で適当な所に解凍してください。

# OpenSSLのmake
　この手順では、OpenSSLをシステム下の/libや/optディレクトリを汚したくないため、自分のhomeディレクトリに作った`"local/"`ディレクトリ下にインストールしています。趣味の問題なので、特にこだわりがなければ`--prefix`と`--openssldir`は省略して、デフォルトの場所にインストールでも良いと思います。
　また、OpenSSLは`"./configure"`ではなく`"./config"`を実行することに注意してください。

```sh
$ cd openssl-1.1.1n
$ ./config --prefix=/Users/hoge/local/opt/openssl --openssldir=/Users/hoge/local/ssl
$ make
$ make test
$ make install
```

:::note warn
OpenSSLのバージョンは1.1.1kだとarm64に対応していないのか、makeに失敗します。1.1.1m以上ならmakeできたので、最新版を使う場合には特に問題なくmakeできるはずです。
:::

**使用したconfigの引数**
| 引数名 | 説明 | デフォルト値 |
|:-----------:|:------------:|:------------:|
| --prefix=DIR | OpenSSLの設定ファイルおよび、デフォルトの証明書やKey Storeの保存先ディレクトリ | /usr/local |
| --openssldir=DIR | インストールされるディレクトリ群に対する最上位のパス |  /usr/local/ssl |

# Pythonのmake
　Pythonのmakeにおいてデフォルトで用いられるコンパイラはGCC (Gnu Compiler Collection) のgccとg++ですが、Apple製コンパイラを使用したいので、ここではClangを指定してコンパイルを行います。
　PythonはUnix形式ではなく、フレームワーク形式でインストールを行います。フレームワーク形式の詳細は[付録](#macosでフレームワークベースのpythonをビルドして使用する)をご参照ください。理由を簡単に書けば、GUIを用いるコード (matplotlib等) を実行できる様にするためと、ディレクトリ管理の簡単化のためとなります。
　OpenSSLをデフォルト以外の場所にインストールした場合は、`"./configure"`の引数`"--with-openssl"`に、OpenSSLのmake時に`"--prefix"`で指定してたディレクトリを指定します。同時に、`"--with-openssl-rpath"`を`"auto"`にします。`"--with-openssl-rpath"`が`"no"`でrpath[^1]が指定されない場合、Python実行時に動的ライブラリがロードされる際に、システムが想定する一般的なディレクトリ (/usr/libや/usr/local/lib等) からしか目的のライブラリが探索されないため、この場合のように異なる場所にインストールしたライブラリが見つからずロードが失敗したり、場合によっては探索されたディレクトリ内に存在する異なるバージョンのライブラリがロードされて、おかしな挙動を引き起こす場合があります。

```sh
$ cd Python-3.10.3
$  ./configure 
 --prefix=/Users/hoga/local \
 --enable-framework=/Users/hoge/local/Library/Frameworks \
 --enable-universalsdk --with-universal-archs=universal2 \
 --with-openssl=/Users/hoge/local/opt/openssl --with-openssl-rpath=auto\
 --with-ensurepip=install \
 --enable-optimizations CC=clang CXX=clang 
$ make -j4
$ make -j4 test
$ make install
```

:::note warn
 "`./confiure`"実行時に表示されるログ名の中で、以下のopenssl関係の構成が解決されていることを確認してください。

* checking for openssl/ssl.h in /Users/hoge/local/opt/openssl... yes
* checking for --with-builtin-hashlib-hashes... md5,sha1,sha256,sha512,sha3,blake2

解決されていない場合でも`"./configure"`は成功するので、気づかないままmakeした場合、インターネットからモジュールがダウンロードできないpipが出来上がり、makeのやり直しとなります。
:::

:::note alert
make installに`"-j"`オプションを指定するとインストールに失敗します。
:::


**使用したconfigureの引数**
| 引数名 | 説明 | デフォルト値 |
|:-----------:|:------------:|:------------:|
| --prefix=PREFIX | アーキテクチャと独立したファイルを`"PREFIX"`にインストールする。このオプションが指定されない場合は、`"/usr/local"`にインストールされる。 | - |
| --enable-framework[=INSTALLDIR]　| 従来のUnix形式のインストールではなく、Python.frameworkを作成する。`"INSTALLDIR"`オプションで、Python.frameworkのインストール先を指定できる（`"INSTALLDIR"`を指定しない場合は`"/Library/Frameworks/"`にインストールされる）。詳細はMac/README.rstを見よ。       | no     |
| --enable-universalsdk[=SDKDIR] | ユニバーサルバイナリでコンパイルされたプログラムを作成する。`"SDKDIR"`はビルド時にどのmac OS SDKを用いるかを指定する（`"SDKDIR"`が指定されない場合は、現在動いているXcodeかCommand Line Toolsのdeveloperディレクトリにあるデフォルトmac OS SDKが使われる。そのため、現在のシステムで`"SDKDIR"`を指定する必要はまずない）。詳細はMac/README.rstを見よ。 | no |
| --with-universal-archs=ARCH | どのアーキテクチャにおけるmacOS ユニバーサルバイナリが作られるかを指定する。このオプションは`"--enable-universalsdk"`が指定されている時のみ有効である。`"ARCH"`に指定できる値は次となる: `"universal2"`, `"intel-64"`, `"intel-32"`, `"intel"`, `"32-bit"`, `"64-bit"`, `"3-way"`, or `"all"` | - |
| --with-openssl=DIR | OpenSSLディレクトリのルート | - |
| --with-openssl-rpath=[DIR\|auto\|no] | OpenSSLライブラリに対するランタイムライブラリのディレクトリ (rpath[^1]) を指定する。指定できる値は次となり、 `"no" (デフォルト)`: rpathを指定しない、`"auto"`: --with-opensslで指定されたライブラリとpkg-configから、自動的にrpathを設定する、`"DIR"`: 明示的にrpathを指定する。 | no |
|  --with-ensurepip[=install\|upgrade\|no] | 付属しているpipを用いて`"install"` か`"upgrade"`を行う。(defaultは`"upgrade"`) | - |
| --enable-optimizations | 高価かつ安定した最適化を行う（Profile-Guided Optimization等）| no |
| CC |  C compiler command | gcc |
| CXX | C++ compiler command | g++ |

使用したmakeの引数
| 引数名 | 説明 | デフォルト値 |
|:-----------:|:------------:|:------------:|
| -j [jobの数] | make時に同時に実行されるjobの数を指定する。jobの数を指定しない場合は数を制限しない。指定するジョブ数は[こちら](https://www.na3.jp/entry/20070927/p1)が詳しいが、どちらにせよ最大でも物理コア数程度にするのが良い。ジョブ数を指定しない場合はマシンに大きな負荷が掛かる場合があるので、jobの数は必ず指定する事。 | - | 

[^1]: プログラムが実行時に動的ライブラリを呼び出す際、検索対象として追加されるディレクトリ。プログラムのコンパイル時に、リンカーの`-rpath`フラグ等により指定される。

# Pythonとpipの実行
　インストールが成功しているかの確認に、ここまでの作業でインストールされたpipを使い、目的のNumpyをインストールしてみます。

```sh
$ /Users/hoge/local/bin/pip3.10 install numpy
```

以下の様に表示されれば成功です。PythonとOpenSSLの動的ライブラリとの連携も無事出来ています。

```sh
Collecting numpy
  Downloading numpy-1.22.3-cp310-cp310-macosx_11_0_arm64.whl (12.8 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 12.8/12.8 MB 55.4 MB/s eta 0:00:00
Installing collected packages: numpy
Successfully installed numpy-1.22.3
```

Pythonを実行してみます。

```sh
$ /Users/hoge/local/bin/python3.10
```

インストールに問題なければ、インタプリタが起動されます。Numpyをインポートしたり、挙動を確認したら`Ctrl-D`か`exit()`で終了します。特にエラーや警告がでなければ、無事、M1 Mac (mac OS Monterey) 上にNumpyが動くPython環境を構築できています。

# Pathの設定
　ここまでで目的は達成されましたが、Python実行時に毎回/Users/~/Python3.10と打つのも面倒なので、Path環境変数を設定してコマンド名だけで実行できる様にします。自身で使用しているシェルの設定ファイル (OSデフォルトなら.zshrc) に以下を書き加えます。

* Zshの場合（Bashも同じ）
```zsh
export PATH="/Users/hoge/local/bin:${PATH}"
```

設定ファイルをターミナルを再起動したり、sourceコマンドで反映させれば、以下の様にPythonが実行できる様になります。

```zsh
$ python3.10
```


# 付録. Mac/README.rstの邦訳
　原文はPython3.10.3ソースコード内に存在するmac/README.rstなので、本邦訳はPython Software Foundation (PSF) ライセンス下で公開されます[^a1]。この文書は、私がいちいち英語を読むのが面倒なため、私的利用を目的として訳した文書となります。内容については訳者の英語力が怪しいため、参考にする際は今一度原文をご確認ください（間違いがありましたらコメントください）。

[^a1]: Copyright © 2001-2022 Python Software Foundation; All Rights
   Reserved (参照: https://docs.python.org/ja/3/license.html#psf-license)

---
## Python on macOS README

著者:
Jack Jansen (2004-07)
Ronald Oussoren (2010-04)
Ned Deily (2012-06)

### configureのmacOS用引数

* --enable-framework[=DIR]

　この引数が指定された場合、コンパイルされるプログラムは、従来のUnixのインストール形式ではなく、Python.frameworkとして作成される。フレームワークのより詳細な情報については[macOSでフレームワークベースのPythonをビルドして使用する](#macosでフレームワークベースのpythonをビルドして使用する)セクションを見よ。

　オプションのディレクトリ引数を指定した場合、フレームワークはそのディレクトリ内にインストールされる。これにより、自身のホームディレクトリにpythonのフレームワークをインストールする事もできる:
```sh
$ ./configure --enable-framework=/Users/ronald/Library/Frameworks
$ make && make install
```
　上の場合だと、フレームワーク自体が`/Users/ronald/Library/Frameworks`にインストールされ、`Users/ronald/Applications`にアプリケーションが、`/Users/ronald/bin`にコマンドラインツールがインストールされる。

* --with-framework-name=NAME

　Pythonフレームワークに対する名前を指定する（デフォルトは`Python`) 。このオプションは`"--enable-framework"`が指定された時のみ有効である。

* --enable-universalsdk[=PATH]

　Pythonをユニバーサルバイナリのプログラムとして作成する。これは通常（訳注: Unix形式）およびフレームワーク形式の両方で使用できる。
　
　この任意の引数は、コンパイルされるプログラムが動くために、どのmacOS SDKを用いるべきかを指定する。現在のシステムでは、大抵の場合`PATH`を指定す必要はなく、`/`だけで良い。その場合、現在動いているXcodeかCommand Line ToolsのdeveloperディレクトリにあるデフォルトmacOS SDKが使われる。より詳しい情報は、`macOS xcrun man page`を見よ。現行バージョンのmacOSおよびXcodeは、システムヘッダーファイルをもはやそれらの慣習的な場所 (`/usr/include`および`/System/Library/Frameworks`) に置いておらず、MacOSX SDKの内部に見つけられる。Appleが提供するビルドツールはこの事を意識せずに処理するので、現行バージョンのPythonもこれで処理する様になっている。そのため、もはやこの任意の引数は必要ではなく、 macOS 10.14以降、`xcode-select`でシステムヘッダーを強制的にインストールすることもできない。

* --with-universal-archs=VALUE

　どの種類のユニバーサルバイナルでPythonを作成するべきか指定する。このオプションは`"--enable-universalsdk"`が指定された場合のみ有効である。SDKがPPC (訳注: Power PC) に対応していれば、デフォルトでは`32-bit`となり、そうでなければ`intel`がデフォルトとなる。`intel`は32-bitと64-bit両方のユニバーサルバイナリを意味し、想定している物と違う可能性があることに注意する事：例えば、macOS 10.15 Catalina現在だと、32-bitでのバイナリの実行は、もはやオペレーティングシステムでサポートされていない。したがって、`"--with-universal-archs"`に対して以下の様に明示的に値を指定するか、どちらも使用しない事が最適となる。

```sh
    --enable-universalsdk --with-universal-archs=intel-64
```

### macOSでユニバーサルバイナリのPythonをビルドして使用する

#### 1.ユニバーサルバイナリとは何か

　Pythonにおけるユニバーサルバイナリでコンパイルされたプログラムは、複数のCPUアーキテクチャに対応したオブジェクトコードを含む。ユニバーサルなmacOS実行可能ファイルやライブラリは、アーキテクチャ固有のコードを一つに纏めており、それにより、サポートする全てのアーキテクチャでネイティブな速さで実行できる。ユニバーサルバイナリは、当時存在するPower PC (PPC) マシンに、IntelベースのMacに対するサポートを追加するために、macOS 10.4で導入された。macOS 10.5において、64-bit Intelと64-bit PPCアーキテクチャに拡張された。この仕組みにより、使用されているmacOSのバージョンとビルドツールによって、様々なアーキテクチャの組み合わせでPythonをビルドする事を可能である。PPCのサポートはmacOS 10.7でなくなり、32-bit Intelのサポーターはmac OS 10.15でなくなった。そのため、現行のmacOS 10.15では、実行できるアーキテクチャとして64-bit Intel (x86_64) しかサポートされていない。

#### 2.ユニバーサルバイナリのビルド方法

　configureに`"--enable-universalsdk`フラグを指定する事でユニバーサルバイナリを有効にできる。

```sh
$ ./configure --enable-universalsdk
$ make
$ make install
```

このフラグはpythonをフレームワークとしてビルドする場合だけでなく、従来のunix形式のビルドでも使用できる。ユニバーサルバイナリはmacOS 10.4におけるXcode 2.1と10.4u SDKで最初にサポートされた。Xcode 3とmacOS 10.5から、より多くの設定が利用できる様になった。

　通常、ユニバーサルビルドは、AppleのXcode開発ツール含まれている、Appleから供給されるコンパイラや他のビルドツールが提供する特定の機能に依存する。現在動いているmacOSのリリースに適したXcodeかコマンドラインツールのコンポーネントのインストールが推奨される。より詳しい情報はPython Developer's Guide (https://devguide.python.org/setup/) を見よ。

##### 2.1 ユニバーサルバイナリのタイプ

　幾つかのタイプのユニバーサルバイナリをビルドすることができ、デフォルトではPPCがサポートされるビルド環境 (macOS 10.4とXcode 2, macOS 10.5および10.6とXcode 3) なら32-bitバイナリ (i386とppc) のみ、ppcをサポートしていないビルド環境 (macOS 10.6におけるXcode 4およびそれ以降のシステム) ならIntel-32/-64-bitバイナリ (i386 and X86_64) となる。そのタイプはconfigureの`"--with-universal-archs=VALUE"`オプションを使用して指定できる:

* `universal2`: arm64, x86_64
* `intel`: i386, x86_64
* `intel-32`: i386
* `intel-64`: x86_64
* `32-bit`: ppc, i386
* `3-way`: i386, x86_64, ppc
* `64-bit`: ppc64, x86_64
* `all`: ppc, ppc64, i386, x86_64

64-bitアーキテクチャ (ppc64、x86_64およびarm64) を含むユニバーサルバイナリをビルドするためには、macOS 10.5かそれ以降が動いてるシステムでビルドしなければならない。`all`および`64-bit (ppc64, x86_64)`タイプのビルドは10.5 SDKのみで可能であり、なぜならppc64のサポートがmocOS 10.5にしか含まれていない為である。macOS 10.6のXcode 3にはppcサポートが遺産として含まれていたにもかかわらず、macOS 10.6でリリースされたXcode 4では削除され、macOS 10.7ではppcがサポートされない事が標準となった。まとめると、以下のSDKとuniversal-archsのタイプの組み合わせが有効となる：

* 10.4u SDKおよびXcode 2は32-bitのみ
* 10.5 SDKおよびXcode 3.1.xは全タイプ
* 10.6 SDKおよびXcode 3.2.xはintel、intel-32、intel-64、3-wayおよび32-bit
* 10.6 SDKおよびXcode 4はintel、intel-32およびintel-64
* 10.7から10.14 SDKsはintel、intel-32およびintel-64
* 10.15およびそれ以降のSDKsはintel-64のみ
* 11.0およびそれ以降のSDKsはuniversal2

　フレームワーク形式でビルドする場合のmakefileは、ユニバーサルアーキテクチャが少なくとも１つの32-bitアーキテクチャを含む場合、python3.x-32もインストールする（すなわち、64-bitとintel-64以外の全タイプ）。また、AppleシリコンMacのRosetta 2 Intenエミュレータで簡単に実行できる様にするため、universal2ではpython3.x-intel64バイナリもインストールしている。

#### アーキテクチャを指定しての実行

`arch`コマンドを使用してアーキテクチャを指定してコードを実行できる: 

```sh
$ arch -i386 python
```

マシンのハードウェアに関係なく、明示的に32-bitモードとしても実行できる:

```sh
$ arch -i386 -ppc python
```

`arch`コマンドの使用は、そのarchコマンドで実行されたPythonから起動されるサブプロセス (プログラムやテスト) に、選択されたアーキテクチャを自動的に引き継がないため、アーキテクチャの指定を完全には解決しない。もしメインのインタプリタから起動されたサブプロセスも32-bitモードで確実に起動したい場合には、`python3.x-32`バイナリ上で、`subprocess Popen`[^a2]に対して`sys.executable`[^a3]を実行する引数として使用する。

　同じ様に、`universal2`バイナリの`x86_64`モードを強制的に実行するには、`python3.x-intel64`を使用する。

[^a2]:https://docs.python.org/ja/3/library/subprocess.html

[^a3]:https://docs.python.org/ja/3/library/sys.html

### macOSでフレームワークベースのPythonをビルドして使用する

#### 1.一体なぜ通常の静的版Pythonの代わりにフレームワーク版Pythonを使用するのか？

　この主な理由は、PythonでGUIプログラムを作れる様にする為である。X11/XDarwinベースのGUIを除いた全てのGUIプログラムは、macOSアプリケーションバンドル (".app")からの起動を必要とする。

　フレームワークを用いない.appを作成することは技術的には可能であるが、これを本当に必要とするならば、自身で作成すべきである。

　フレームワークを用いる第二の理由は、Pythonに関係するアイテムを、次の2つの場所にのみ配置するからである。その場所は`"/Library/Framework/Python.framework"`および　`"/Applications/Python <VERSION>"`となり、ここで、 `"<VERSION>"`は`"3.8"`や`"2.7"`となる。これにより、バイナリ配布版からPythonをインストールしたユーザが、再びそれを取り除きたい場合に、処理が簡単となる。さらに、フレームワークとして稼働する方法を選ぶことにより、管理者権限のないユーザが、自身のホームディレクトリにバイナリ配布版を再コンパイルせずにインストールできる。

#### 2.通常の静的版Pythonとフレームワーク版Pythonは何が違うのか?
　
　格納場所が異なるだけで、普段使用する範囲においては特に違いはない。`/Library/Frameworks/Python.framework`を見れば、たくさんの相対シンボリックリンクが確認できる（詳しくは、Appleのドキュメントを見よ）。通常のUnix形式におけるPythonのファイルレイアウトに慣れているなら、Versions/Currentに行けば、おなじみのbinとlibディレクトリが確認できる。

#### 3.追加パッケージは必要か？

　十中八九、必要である。Tkinterのサポートを望むなら、macOS AquaTkディストリビューションを手に入れることが必要となり、これはmacOS 10.4以降にはデフォルトでインストールされている。macOS 10.6から提供が開始されあたCocoaベースのAquaTkは不安定であることが証明されているので気をつけること。もし可能であれば、macOS 10.6以降でビルドする前に、最新バージョンのインストールを検討するべきで、例えばActiveTcl 8.6等である。[https://www.python.org/download/mac/tcltk/](https://www.python.org/download/mac/tcltk/)を見よ。SDKとビルドするなら、SDKの`Library/Frameworks`ディレクトリ内に最新版のTclおよびTkフレームワークが含めれているか確認すること。場合によっては、それらのインストールされた場所 (`/Library/Frameworks`) に手動でシンボリックリンクを貼る必要がある。wxPythonを使用する場合、それを行う必要がある。Cocoaを使用する場合は、PyObjCを得る必要がある。

#### 4.フレームワーク版Pythonのビルド方法

 このディレクトリ (Mac/) は、`"/Applications/Python <VERSION>"`に幾つかのPython関連のアプリケーション (つまり、完全なmacOS .appアプリケーション) を、Pythonフレームワーク内にPython.app隠しヘルパーアプリケーションを、`/usr/local/bin`内に`"python"`を含むunixツールを作成するMakefileを保有する。加えて、Macサブツリーの関連部分をPython.frameworkにインストールする`"installmacsubtree"`ターゲットも保有する。

　通常の呼び出しでは、最後のステップでメインのMakefileを間接的に呼び出す。

```sh
./configure --enable-framework
make
make install
```

この手順では、フレームワークは`/Library/Framework/Python.framework`、アプリケーションは`/Applications/Python <VERSION>`およびUnixツールは`/usr/local/bin`に配置される。

　他の場所にインストールする際、例えばマシンの管理者権限を持っていない場合に`$HOME/Library/Frameworks`を対象とするなら、インストール可能である。これは、`--enable-framework=$HOME/Library/Frameworks`をつけてconfigureすることで行うことができる。他の２つのディレクトリも、その場合は`$HOME/Applications/Python-<VERSION>`および`$HOME/bin`にインストールされる。
　
　全てではなく、一部だけインストールを行いたい場合は、メインのMakefileを見よ。frameworkinstallは、フレームワーク自身、Macサブツリー、アプリケーションおよびunixツールをインストールする幾つかのサブターゲットから成り立っている。
　
　通常のframeworkinstallに含まれない追加ターゲットであるframeworkinstallextrasがあり、Toolsディレクトリを`"/Applications/Python <VERSION>"`にインストールする。これは、バイナリの配布に役立つ。

### "/Applications/Python \<VERSION\>"下のプログラムは何をするのか？

 `"IDLE.app"`はPythonの統合開発環境 (エディタ、デバッガなど) である。

　`"Python Launcher.app"`は、.py、.pyc および.pywがダブルクリックされれた時に実行されるヘルパーアプリケーションである。最初の二つ（.pyおよび.pyc）はターミナルウインドウが起動され、通常のコマンドラインでPythonからスクリプトを実行する。後者 (.pyc ) に対しては、Python.appインタプリタ上でスクリプトを実行され、スクリプトがGUI関連を実行できるようにするためである。Optionキーを押したままドラックかダブルクリックすると、スクリプトに実行時オプションを設定できる。これらオプションはPython Launcherの設定ダイアログから永続的に設定することもできる。
　
　`pythonx.x`プログラムは、コマンドラインからpythonスクリプトとして実行する。以前は、macOS上のPythonの初期リリースでGUIプログラムを実行するために必要だったpythonwx.xを含む、さまざまな互換性を持つエイリアスもインストールされていた。3.4.0時点で、pythonwx.xエイリアスはもうインストールされていない。

### バイナリ配布版をどう作るか？

　公開されているソースを[https://www.python.org/download/](https://www.python.org/download/)からダウンロードして、展開する。`"Mac/BuildScript"`に移動する。そこに、全ての作業を行う`build-installer.py`スクリプトがある。これは、幾つかのサードパーティ製ライブラリをダウンロードしてビルドし、フレームワーク版Pythonの設定とビルドをしてインストールを行い、インストーラパッケージファイルを作り、それをDMGイメージとして固める。このスクリプトは加えて、このリリースに対する現在のPythonドキュメント一式のHTMLコピーを、フレームワークに含ませるためにビルドする。インストーラパッケージはIDLE、pydoc、ShellユーザおよびFinderユーザが使用するためのドキュメントへのリンクを作成する。

　スクリプトはユニバーサルバイナリをビルドするので、このスクリプト（build-installer.py）はmacOS 10.4以降およびXcode 2.1以降がインストールされた環境で実行しなければならない。しかしながら、Pythonのビルドプロセスは、macOS 10.4だと追加設定なしに利用できない幾つかの依存関係を持つため、Xcode 2で提供されている物以外にも、追加のソフトウェアが必要かもしれない。

　古いバージョンのSDKsやXcodeを組み合わせて、より新しいシステム上で古いシステムに互換性のあるインストーラをビルドする事は可能ではあるが、これは完全確実ではない。そのため、作成される実行バイナリ、共有ライブラリおよび.soバンドルに対して、動的リンクの依存性が適切か全てのサポートされるシステムで入念に調査およびテストする必要がある。最小限のmacOSバージョンがサポートされて稼働しているシステム上で、配布版をビルドするのが安全である。

これら全ては通常完全に` /tmp/_py`に切り離されて行われるため、通常のビルドディレクトリは使用されず、`/`にもインストールを行う事はない。
　
　このスクリプトはファイルを探すために、`BuildScript`ディレクトリ内で実行する必要がある。スクリプトは幾つかのコマンドライン引数を指定できるので、より詳細な情報は--helpを引数にスクリプトを実行して得よ。

### Configureの警告
 
　configureスクリプトは時々以下の様な警告を出す:
　
```sh
configure: WARNING: libintl.h: present but cannot be compiled
configure: WARNING: libintl.h:     check for missing prerequisite headers?
configure: WARNING: libintl.h: see the Autoconf documentation
configure: WARNING: libintl.h:     section "Present But Cannot Be Compiled"
configure: WARNING: libintl.h: proceeding with the preprocessor's result
configure: WARNING: libintl.h: in the future, the compiler will take precedence
configure: WARNING:     ## --------------------------------------- ##
configure: WARNING:     ## Report this to https://bugs.python.org/ ##
configure: WARNING:     ## --------------------------------------- ##
```

これは大抵の場合、ユニバーサルバイナリをビルドしようろする時に、`/usr/local`内に必要なアーキテクチャのライブラリを保有していない事を意味する。ビルドを完了させるため、一時的に`/usr/local`を傍に動かせ。

### フレームワーク版インストールをアンインストールする (バイナリインストーラー版インストールも含む)
　
　フレームワークのアンインストールは、インストールされた全てを手動で削除して行う。これは、ソースおよびバイナリインストーラを使用したインストールのどちらに当てはまる。mac OSはシステム自身によるアンインストーラを提供していない。

　フレームワーク版のインストールにおける主な部分は、フレームワークそれ自体であり、`/Library/Frameworks/Python.framework`にインストールされている。ここには複数バージョンのPythonが存在することがあり、一つのバージョンだけを削除したい場合は、そのバージョンに対応したサブディレクトリを削除する: `/Library/Frameworks/Python.framework/Versions/X.Y`。その場合、`/Library/Frameworks/Python.framework/Versions/Current `がインストールされたバージョンのPythonをさしているシンボリックリンクか確認すること。


　フレームワーク版のインストールは`/Applications/Python X.Y`に幾つかのアプリケーションもインストールしている。

　最後に、フレームワーク版インストールは`/usr/local/bin`にファイルをインストールし、`/Library/Frameworks/Python.framework/Versions/X.Y/bin`に`/usr/local/bin`内のファイル全てのシンボリックリンクを貼っている。

### Weak linkingのサポート[^a6]

　CpythonのソースはmacOS 10.9をデプロイの対象とする一方、最新のSDKでビルドする事に対応している。これは、macOS 10.10以降で導入されたシンボルのweak linkingと、実行時にそれらが有効か確認して実現している。
　
　これには、macOS 10.13以降のApple製コンパイラーのツールチェインが必要となる。

* `HAVE_<FUNCTION>` はconfigureスクリプトによって定義される（または未定義となる）マクロ。　 
  
* `HAVE_<FUNCTION>_RUNTIME`は関連するソースファイル上で定義されているマクロ。このマクロは、十分に新しいApple製コンパイラが使用される場には、`__builtin_available`が呼ばれる様に拡張し、そうでなければ`true`値を返す。

* `<function>`が呼び出される前に、`HAVE_<FUNCTION>_RUNTIME`を使用する。このマクロは、if文の中で単体の式として**使用されなければいけない**:

```c
   if (HAVE_<FUNCTION>_RUNTIME) {
     /* <function> is available */
   }
```

または、

```c
   if (HAVE_<FUNCTION>_RUNTIME) {} else {
     /* <function> is not available */
   }
```

他のパターン (例えば`!HAVE_<FUNCTION>_RUNTIME`) はApple製コンパイラではサポートされていない。

[^a6]: CPythonのコードを弄る場合に必要となる知識なので、今回の本題的には特に理解が必要な知識ではないです。

### 参考

* https://www.python.org/downloads/macos/

* https://www.python.org/community/sigs/current/pythonmac-sig/

* https://devguide.python.org/