Windows 10 on ARM 用 Python3 を Windows 10 on ARM 上の Visual Studio 2019 (x86) でビルドする

## はじめに
前回投稿の「[Windows 10 on ARM 用 7-zip (19.00) を Windows 10 on ARM 上の Visual Studio 2019 (x86) でビルドする](https://qiita.com/Daru-IBN5100/items/690742e4b539d3ffb5b6)」に続きまして、今回は Python3 をビルドしてみました。

自分自身はあまり Python の経験はないのですが、OSS のビルド補助スクリプトとしてちょこちょこ使用されているのは見かけているので、ネイティブにしておくとそれなりに便利かなぁと思って調べていましたら [こちら](https://bugs.python.org/issue33125) の方で何やらいけそうな感じのやり取りを見かけましたのでチャレンジしてみた次第です。

## Python3 のビルド
とりあえず今回は現時点の Stable である 3.8 系でいきます。
少しばかし制約（後述）はありますが、以下のコマンド群でサクッとビルドできました。

```
git clone https://github.com/python/cpython -b 3.8
cd .\cpython\PCbuild
build.bat -p ARM64 -c Release
```

![python_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680157/5bbb592f-cd6b-5035-e3ad-cf280a2eaf84.png)

### 制約
Python ビルド時に NuGet で各種外部モジュールが `.\cpython\externals` 以下にインストールされるようですが、いくつかの外部モジュールは ARM64 用が未対応で入ってなく、ビルドがスキップされています。

そのなかでも Python 標準の GUI モジュールである tkinter (TclTk) が使用できないのは少し寂しいかなぁと思いまして TclTk のビルドにもチャレンジしてみました。

## tkinter (TclTk) のビルド
今回の Python ビルド時に NuGet でインストールされた TclTk はバージョン 8.6.9 でしたが、ビルドが少しでも通りやすくなっていると信じて [こちら](https://www.tcl.tk/software/tcltk/download.html) のサイトから tcl8610-src.zip および tk8610-src.zip をダウンロードして作業場所に展開します。

### ファイル内容修正
1. スクリプトが対応できていないようなので、今回は強引に ARM64 を指定しました。
`.\tcl8.6.10\win` の `rules.vc`
473行目の MACHINE パラメーターに ARM64 をセット
`MACHINE=$(ARCH)` → `MACHINE=ARM64`

2. また、cpuid関数はアセンブラっぽいので、今回は強引にオミットしました。
`.\tcl8.6.10\win` の `tclWin32Dll.c`
820行目をコメントアウト
`__cpuid(regsPtr, index);` → `/*__cpuid(regsPtr, index);*/`

※ Tk のビルド時にも Tcl 側の上記ファイルを参照するようで、Tk 側は修正しなくてもいいみたいです。

### TclTk のビルド
普通に展開したならば、それぞれ `.\tcl8.6.10\win` と `.\tk8.6.10\win` のフォルダ位置でコマンド ウィンドウを立ち上げます。

いつものように ARM64 用のツールセット環境を準備して

```
"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" x86_arm64
```

いざ、ビルド開始！

なのですが、何故か Windows 10 on ARM 上でビルドする場合は 「TCLSH_NATIVE が設定されていません」と怒られるので、とりあえず python のビルド時に NuGet でインストールされた TclTk の x86 版を指定しておきました。

```
nmake -f makefile.vc release OPTS=threads TCLSH_NATIVE="work\cpython\externals\tcltk-8.6.9.0\win32\bin\tclsh86t.exe"
```

基本的には上記のコマンドでビルドは通りましたが、Tcl 側ビルドの sqlite モジュールのコンパイル時に下記のようにリソースコンパイラ絡みのエラーでスキップがありました。

```
.\tcl8.6.10\pkgs\sqlite3.30.1.2\win\Release_ARM64_VC1926\sqlite_ThreadedDynamic\sqlite.rc(4) : error RC2167 : unrecognized VERSIONINFO field;  BEGIN or comma expected
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86\rc.EXE"' : リターン コード '0x2'
Stop.
```


多分 tkinter には影響ないであろうと思い今回はスルーしました。 ^^;
今後、気が向いた時にでも ARM64 用ビルド時のリソースコンパイラの扱いも調べてみようとは思います。

### TclTk のインストール
とりあえずバージョン番号の違いは気にせず、Python のビルド時に NuGet でインストールされた TclTk のところの arm64 フォルダに突っ込んでいます。 

```
nmake -f makefile.vc install INSTALLDIR="work\cpython\externals\tcltk-8.6.9.0\arm64" TCLSH_NATIVE="work\cpython\externals\tcltk-8.6.9.0\win32\bin\tclsh86t.exe"
```

### tkinter のビルド（Python のリビルド）
以上、TclTk の準備が整ったので tkinter のビルド（Python のリビルド）をするのですが、うまい具合にリコンフィグしてくれるのかよくわからなかったので今回は `.\cpython\PCbuild` 内にある `pcbuild.sln` から Visual Studio の IDE を立ち上げて、こちらの「ビルドの構成」で tkinter を追加してリビルドしました。

![python_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680157/3336a366-d94d-79c3-db12-884f523e818d.png)

詳細な動作検証まではしていませんが、とりあえず tkinter による GUI ウィンドウが立ち上がるところまでどうにか漕ぎ着けることができました。

![python_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680157/d7358079-2267-91e0-ae3b-98de437a33ca.png)

## おわりに
この、悪戦苦闘しつつも少しづつ環境が充実していく感じがマイナー機ならではの味わいですかね？
とはいえ、普及に弾みをつけるためにも、早く公式から ARM64 版が配布されるようになるよう願っています。