Windwos版 Emacs 27.1 / HEAD コンパイル手順メモ


# 概要

Windows 10 にて、スクラッチから、 Emacs HEAD (または27.1) を gitのレポジトリから取得してコンパイルして、デバッガ上で実行する手順を示します。（IMEパッチを適用する方法も書いています。）

実は、Emacsは特に何もなくても、デバッガ上での利用が推奨されています。（参考： [etc/DEBUG](https://git.savannah.gnu.org/cgit/emacs.git/tree/etc/DEBUG) : "It is good idea to run Emacs under GDB ****all the time****."）

また、Emacs の [gitレポジトリ](https://git.savannah.gnu.org/git/emacs.git)先端ブランチ (HEAD) を使うことで、最新の機能をいち早く試せます。ただし、Emacs HEAD は開発中のブランチのため、時期によってはしょっちゅう落ちることがあります。デバッガ上で動かせば、落ちた時にバックトレースを取得して emacs-bugs へ報告することができます。

Emacs HEAD は開発時期によっては、頻繁に落ちて使いもものにならない場合はあります。その場合は、Windows版Emacsの正式版を使いましょう。 （Emacs 27.1 のインストーラは、[公式サイト](http://ftp.gnu.org/gnu/emacs/windows/emacs-27/)からダウンロード可能です。）

なお、正式版のリリース後も [バグ](https://debbugs.gnu.org/cgi/pkgreport.cgi?package=emacs;max-bugs=100;base-order=1;bug-rev=1)が発見されることがあり、そのバグを回避するためにはソースコードにパッチをあててコンパイルしなければならない場合があります。

なお、以下はあくまでも参考ですので、[公式なWindows向けコンパイル用マニュアル](https://git.savannah.gnu.org/cgit/emacs.git/tree/nt/INSTALL.W64) および [FAQ](https://www.gnu.org/software/emacs/manual/html_mono/efaq-w32.html) も参照してください。

以下にセットアップの手順の概要を図で示します。（初期設定が終わると、枠線内で、最新ソースコードの取得とビルドがまわるようになります。）

![procedure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21783/4c75406c-29b8-cdf9-0bc3-06b4b8ae46a7.png)


# Powershell の初期設定

ネットからダウンロードしたソフトウェアをコマンドラインで実行するには、ポリシを変更する必要があります。`[Win+X]` → `[A]` を押して、Admin権限のPowershell を起動し、以下を実行します。

```powershell
## 外部のツールに実行権限を付与。
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```


# chocolatey・msys2・Windows Terminal ・git のインストール

[chocolatey](https://chocolatey.org/) は、 Linux のrpm/apt のようなパッケージ管理ツール ([インストール詳細](https://chocolatey.org/install))です。[
msys2](https://www.msys2.org/) は、Unixツールを活用した Windowsアプリ開発環境で、Emacsのコンパイルに使用します。[
Windows Terminal](https://github.com/microsoft/terminal) は、Unixの疑似端末に対応したMicrosoft社謹製のターミナルプログラム。Emacsをデバッガで動かすときに使用します。

`[Win+X]` → `[A]` を押して、Admin権限のPowershell を起動し、以下を実行します。

```powershell
## chocolatey のインストール
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
## msys2のインストール
choco install -y msys2
## Windows Terminal のインストール
choco install -y microsoft-windows-terminal
## git のインストール
choco install -y git.install
```

chocolateyによる msys2 のインストール先は `C:\tools\msys64` ディレクトリです。


# MSYS2の設定


## ホームディレクトリの設定

msys2のホームディレクトリと、Emacsのホームディレクトリは、Windowsのユーザディレクトリと異なります。

-   **msys2の標準ホームディレクトリ:** `C:\tools\msys2\home\<username>` 。 nsswitch.conf で変更可能。
-   **Emacsの標準ホームディレクトリ:** `C:\Users\<username>\AppData\Roaming\` 。 [環境変数HOME](https://www.gnu.org/software/emacs/manual/html_node/emacs/Windows-HOME.html)で変更可能。

両方のホームディレクトリをユーザディレクトリ (`C:\Users\<username>\`) と揃えておくと便利なため、以下の設定を行います。


### nsswitch.confの編集

`C:\tools\msys64\etc\nsswitch.conf` の `db_home` のエントリの先頭に、以下のように `windows` を追加します。

```sh
db_home: windows cygwin desc
```


### HOME環境変数の追加

`[Win+I]` キー →「設定画面」にて「環境変数」で検索→「ユーザー環境変数の設定」にて、環境変数 `HOME` を、 `C:\Users\<username>` として追加します。


## mintty 用の 設定ファイルのカスタマイズ

mintty は、msys2に付属する標準のターミナルです。

実は、msys2には、以下の2つの開発環境があります。

-   **MINGW64:** Windows用APIを用いたアプリケーションの開発環境。Emacsはこの環境でコンパイルします。
-   **MSYS:** Unix用APIを用いたアプリケーションの開発環境。​`fakecygpty`​（後述）はこの環境でコンパイルします。

また、msys2の環境変数には以下があります。

-   **MSYSTEM:** `MINGW64` または `MSYS` を設定して、bash/zshをログイン起動 (-lオプション) すると、 `/etc/proifle` にて開発環境が設定されます。
-   **MSYS2\_PATH\_TYPE:** `inherit` にすると、Windows OS の `PATH` 環境変数の値が、MSYS2環境でも引き継がれます。
-   **MSYS:** `winsymlinks:nativestrict` にすると、Admin権限のシェルにて、 `ln -s` 命令で NTFS のシンボリックリンクが作成できます。
-   **SHELL:** MSYSで起動するシェル環境を設定します。
-   **CHERE\_INVOKING:** 1にすると、シェル起動時のディレクトリをホームディレクトリにしません。

ターミナルを起動する際には、上記の環境変数を設定して、シェルを立ち上げます。すると、シェルが /etc/profiles を読み込み、上記の設定に基づいて、開発環境等をセットアップします。

ターミナルとして mintty を使う場合は、 `C:\tools\msys64\msys2.ini`, `C:\tools\msys64\mingw64.ini` にてオプション変数を設定します。

以下に `msys2.ini` の設定例を示します。

```sh
MSYS=winsymlinks:nativestrict
# CHERE_INVOKING=1
MSYS2_PATH_TYPE=inherit
MSYSTEM=MSYS
SHELL=/usr/bin/zsh
```


# MSYS2のツール・ライブラリのインストール

`C:\tools\msys64\msys2_shell.cmd` を起動し、以下をコピペ・実行することで、次のものがインストールされます。

-   zshやfishなどのシェル
-   Emacs のビルドに必要なコンパイラ・ツール類とライブラリ
-   msys2/mingw64のアイコンや、タスクバーにピン留め可能なアプリとして扱えるランチャ

```sh
pacman -Syu
pacman -Sy
pacman -S --needed base-devel msys2-devel msys2-runtime \
  libreadline libiconv libarchive libgpgme libcurl pacman \
  ncurses libintl tar wget pkg-config \
  autoconf autogen automake automake-wrapper diffutils \
  git libgc libltdl libunistring make zsh msys2-launcher \
  mingw-w64-x86_64-toolchain \
  mingw-w64-x86_64-lcms2 \
  mingw-w64-x86_64-jansson \
  mingw-w64-x86_64-binutils \
  mingw-w64-x86_64-bzip2 \
  mingw-w64-x86_64-cairo \
  mingw-w64-x86_64-crt-git \
  mingw-w64-x86_64-dbus \
  mingw-w64-x86_64-expat \
  mingw-w64-x86_64-fontconfig \
  mingw-w64-x86_64-freetype \
  mingw-w64-x86_64-gcc \
  mingw-w64-x86_64-gcc-libs \
  mingw-w64-x86_64-gdk-pixbuf2 \
  mingw-w64-x86_64-gettext \
  mingw-w64-x86_64-giflib \
  mingw-w64-x86_64-glib2 \
  mingw-w64-x86_64-gmp \
  mingw-w64-x86_64-gnutls \
  mingw-w64-x86_64-harfbuzz \
  mingw-w64-x86_64-headers-git \
  mingw-w64-x86_64-imagemagick \
  mingw-w64-x86_64-isl \
  mingw-w64-x86_64-jbigkit \
  mingw-w64-x86_64-libffi \
  mingw-w64-x86_64-libiconv \
  mingw-w64-x86_64-libjpeg-turbo \
  mingw-w64-x86_64-libpng \
  mingw-w64-x86_64-librsvg \
  mingw-w64-x86_64-libtiff \
  mingw-w64-x86_64-libwinpthread-git \
  mingw-w64-x86_64-libxml2 \
  mingw-w64-x86_64-mpc \
  mingw-w64-x86_64-mpfr \
  mingw-w64-x86_64-pango \
  mingw-w64-x86_64-pixman \
  mingw-w64-x86_64-winpthreads \
  mingw-w64-x86_64-xpm-nox \
  mingw-w64-x86_64-xz \
  mingw-w64-x86_64-zlib \
  msys/gnutls
```


# Windows Terminal でのMSYS2/MINGW64設定

Emacsの実行やコンパイルは、msys2に付属の mintty でも可能ですが、Microsoft社の Windows Terminal は、下記の利点があるため、mintty に加えて、Windows Terminal で msys2 が使えるように設定します。（Qiita参考記事 [Windows Terminalでもmsys2を使おう](https://qiita.com/yumetodo/items/4aa03d1eb3d887bca1a8)）

-   Windows Terminal は疑似端末 [conpty](https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-console-conpty/) を実装しており、Emacs をデバッガ上のシグナルを処理できます。
-   Windows Terminal はマルチタブでPowerShell や、WSL2 Ubuntu など様々なシェルを扱えます。
-   Windows Terminal は端末の透明化など、多くの機能を備えています。

以下の手順を実行します。

1.  Windows Terminal を起動します。
2.  PowerShellで、 `[guid]::newGuid()` を２回実行して、２つのGUIDを取得します。
3.  `C-,` キーを押して、 `settings.json` ファイルを開きます。
4.  以下の設定を、JSONファイルの `profiles` セクションに追記し、保存します。guid の部分は自分で書き換えます。また `commandline` の `set` の設定については、上記のMSYS2の環境変数の説明を参考に必要に応じて変更してください。
5.  Windows Terminal を再起動し、ウィンドウバー右端のタブから、MSYS2/MINGW64が選択可能なことを確認します。

```json
{
     "name" : "MSYS2",
     "icon": "C:/tools/msys64/msys2.ico",
     "guid" : "{00000000-0000-0000-0000-000000000000}",
     "commandline" : "cmd.exe /c \"set MSYSTEM=MSYS&& set MSYS=winsymlinks:nativestrict&& set MSYS2_PATH_TYPE=inherit&& C:/tools/msys64/usr/bin/zsh.exe --login\"",
     "closeOnExit" : true,
     "colorScheme" : "Campbell",
     "fontFace" : "HackGen",
     "fontSize" : 11,
     "guid" : "{00000000-0000-0000-0000-000000000000}",
     "historySize" : 9001,
     "padding" : "0, 0, 0, 0",
     "snapOnInput" : true,
 },
{
     "name" : "MINGW64",
     "icon": "C:/tools/msys64/mingw64.ico",
     "commandline" : "cmd.exe /c \"set MSYSTEM=MINGW64&& set MSYS=winsymlinks:nativestrict&& set MSYS2_PATH_TYPE=inherit&& C:/tools/msys64/usr/bin/zsh.exe --login\"",
     "guid" : "{00000000-0000-0000-0000-000000000000}",
     "closeOnExit" : true,
     "colorScheme" : "Campbell",
     "fontFace" : "HackGen",
     "fontSize" : 11,
     "historySize" : 9001,
     "padding" : "0, 0, 0, 0",
     "snapOnInput" : true,
 },
```


# scoop ・ ghq のインストール

[scoop](https://scoop.sh/) は、 chocolatey と同様のパッケージ管理ツールです。

chocolatey が Admin権限でアプリにインストールするのに対し、 scoop は 個別ユーザ向けに 非Admin権限で アプリをユーザディレクトリにインストールします。[ghq](https://github.com/x-motemen/ghq) は git レポジトリ管理ツールで、Windowsへのインストールは scoop で行うのが簡単です。

AdminモードのPowershellで 、以下を順に実行します。

```powershell
## scoop のインストール
iwr -useb get.scoop.sh | iex
## ghq のインストール
scoop install ghq
```

`ghq` のインストール後、ユーザ環境変数 `PATH` に、 `c:\Users\<username>\scoop\shims` を追加します。

1.  `[Win+I]` → 「設定画面」の「設定の検索」にて「環境変数」で検索 → 「ユーザー環境変数の設定」で `PATH` 環境変数を選択、「追加」で末尾に上記のパスを追加します。
2.  `[Win+X] → I` で、 PowerShell を起動し、 `get-command ghq` を実行して `ghq` コマンドへパスが通っていることを確認します。


# Emacs レポジトリの取得・更新

Emacs は、 `MINGW64` 環境でコンパイルします。そのため、Windows Terminal から、MINGW64環境のコンソール (MSYS2付属のMinttyを使う場合は `C:\tools\msys64\mingw64.exe`) を起動します。

```sh
## git レポジトリのpull
ghq get https://git.savannah.gnu.org/git/emacs.git # 更新する場合は -u オプションを付ける。
## ブランチをEmacs 27.1 へ切替
cd ~/ghq/git.savannah.gnu.org/git/emacs/
git fetch origin
```

なお、改行がWindows形式 (CR+LF) だと、 `autogen.sh` 実行時に​`m4`​がうまく動作しない場合があります。そのため、下記の設定で、Windows改行形式を抑止します。

```sh
git config core.autocrlf false
git config core.eol lf
```

【ヒント】 `git config --global core.autocrlf false` のように、 `--global` オプションを付けると、任意の場所で適用されます。


# IMEパッチの適用

Emacs 26.1 より、IMEのインライン変換機能が含まれたため、IMEパッチの必要性は少なくなってきています。また、最近は、ダイナミックモジュールを用いて [IMEパッチ相当の機能を組み込む試み](https://github.com/trueroad/tr-emacs-ime-module/) もあります。

それでも、IMEパッチを適用したい場合は、以下のように パッチをghqで取得して、レポジトリを emacs-27.1 タグに移動して、 `patch` を適用します。

```sh
ghq get https://github.com/K-Arakawa/emacs-ime-patch
git tag -l # emacs-27.1 タグがあることを確認
git checkout emacs-27.1
git branch # ブランチは master ではないことを確認。（HEADをコンパイルするならbranch）
## configure を生成
./autogen.sh
## IMEパッチの適用
patch -p1 < ~/ghq/github.com/K-Arakawa/emacs-ime-patch/emacs-27.1-ime.patch
```


# ソースの修正・更新

Emacsのバグを発見・報告すると、作者からバグ対処パッチが送付され、「試験して欲しい」と言われる場合があります。または、Emacsのソースを自分で改造したい場合もあるかもしれません。

なお、自分で当てたパッチなどのローカルな変更を無効化し、ブランチを​`origin/master`​に戻すには、以下を実行します。

```sh
git reset --hard origin/master
git checkout -B master origin/master
```


# Emacsのビルド


## configureの実行

Emacsをビルドする際は、最初に `configure` を以下のように実行します。各種オプションはデバッガを利用する場合のものです。

```sh
./configure --without-pop --enable-checking='yes,glyphs' --enable-check-lisp-object-type  CFLAGS='-O0 -g3'
```

以下の出力が出ればOKです。gif, png, jpeg, svg, tiff などの画像ファイルがサポートされていること、Harfbuzz, GMP, pdumper, jansson, gnutls などの Emacs27 の最新機能が有効になっていることを確認します。

```txt
Configured for 'x86_64-w64-mingw32'.

  Where should the build process find the source code?    .
  What compiler should emacs be built with?               gcc  -O0 -g3
  Should Emacs use the GNU version of malloc?             no
    (The GNU allocators don't work with this system configuration.)
  Should Emacs use a relocating allocator for buffers?    no
  Should Emacs use mmap(2) for buffer allocation?         yes
  What window system should Emacs use?                    w32
  What toolkit should Emacs use?                          none
  Where do we find X Windows header files?                NONE
  Where do we find X Windows libraries?                   NONE
  Does Emacs use -lXaw3d?                                 no
  Does Emacs use -lXpm?                                   yes
  Does Emacs use -ljpeg?                                  yes
  Does Emacs use -ltiff?                                  yes
  Does Emacs use a gif library?                           yes
  Does Emacs use a png library?                           yes
  Does Emacs use -lrsvg-2?                                yes
  Does Emacs use cairo?                                   no
  Does Emacs use -llcms2?                                 yes
  Does Emacs use imagemagick?                             no
  Does Emacs use native APIs for images?                  yes (w32)
  Does Emacs support sound?                               yes
  Does Emacs use -lgpm?                                   no
  Does Emacs use -ldbus?                                  yes
  Does Emacs use -lgconf?                                 no
  Does Emacs use GSettings?                               no
  Does Emacs use a file notification library?             yes (w32)
  Does Emacs use access control lists?                    yes
  Does Emacs use -lselinux?                               no
  Does Emacs use -lgnutls?                                yes
  Does Emacs use -lxml2?                                  yes
  Does Emacs use -lfreetype?                              no
  Does Emacs use HarfBuzz?                                yes
  Does Emacs use -lm17n-flt?                              no
  Does Emacs use -lotf?                                   no
  Does Emacs use -lxft?                                   no
  Does Emacs use -lsystemd?                               no
  Does Emacs use -ljansson?                               yes
  Does Emacs use the GMP library?                         yes
  Does Emacs directly use zlib?                           yes
  Does Emacs have dynamic modules support?                yes
  Does Emacs use toolkit scroll bars?                     yes
  Does Emacs support Xwidgets?                            no
  Does Emacs have threading support in lisp?              yes
  Does Emacs support the portable dumper?                 yes
  Does Emacs support legacy unexec dumping?               no
  Which dumping strategy does Emacs use?                  pdumper
```


## コンパイル・インストール

`configure`​後、​`make`​を実行し、成功したら​`/usr/local` (C:/tools/msys64/usr/local/) へインストールします。

```sh
make -j && make install prefix=/usr/local
```


# Emacsのデバッガ上での起動

最初に `~/.gdbinit` に以下を設定し、Emacs専用GDBツールを動かせるようにします。

```conf
add-auto-load-safe-path ~/ghq/git.savannah.gnu.org/git/emacs/src/.gdbinit
```

次に、「デバッガ上でのEmacsの起動」をスクリプト化します。たとえば、仮に `~/bin/emacs-gdb.sh` として、下記のシェルスクリプトを用意します。スクリプトの最後に exec 文を指定するのは、gdb起動時にbashを終了させて SIGINT シグナルがgdbに届くようにするためです。

```sh
#/bin/env sh
cd ~/ghq/git.savannah.gnu.org/git/emacs/src
exec gdb -ex "set new-console 1" -ex run ./emacs
```

シェルでこのスクリプトを実行すると、gdbが起動し、その上で Emacs が起動します。Control-C (SIGINT) を押すとデバッガに入ること、そこから `fg` と入力すると、Emacsに戻ることを確認してください。Emacs や Emacs Lisp のgdb上でのデバッグ方法は、ソースツリーの /etc/DEBUG に詳述されています。


## ワンクリックでデバッガ上のEmacsを起動させる方法

上述のように、Emacsをデバッガ上で動かすには、Windows Terminal を起動し、MINGW64シェルを起動し、そしてデバッガ起動スクリプトを起動します。

これらをまとめてワンクリックで実行するためには、Explorer から、ショートカットを新規作成し、項目欄に以下を記入します。

```powershell
wt new-tab cmd.exe /c set MSYSTEM=MINGW64&& set MSYS=winsymlinks:nativestrict&& set MSYS2_PATH_TYPE=inherit&& C:/tools/msys64/usr/bin/zsh.exe -l ~/bin/emacs-gdb.sh
```

ここで、 `&&` の前に空白を入れてはいけません。


# 【参考】依存ライブラリの確認とPATHの追加

configureの設定によっては（下記は `--with-libgmp` を指定した場合）、 `C:\Windows\SYSTEM32\` のライブラリ以外にEmacsが依存することがあります。その場合は、 `PATH` 環境変数に当該ライブラリがある場所（上記の場合は `C:\tools\msys2\mingw64\bin` ）を追加します。

```sh
cd /usr/local/bin
ldd emacs-27.1.exe
        ntdll.dll => /c/Windows/SYSTEM32/ntdll.dll (0x7ffbc0810000)
        KERNEL32.DLL => /c/Windows/System32/KERNEL32.DLL (0x7ffbc0530000)
        KERNELBASE.dll => /c/Windows/System32/KERNELBASE.dll (0x7ffbbe470000)
        ADVAPI32.dll => /c/Windows/System32/ADVAPI32.dll (0x7ffbc05f0000)
        msvcrt.dll => /c/Windows/System32/msvcrt.dll (0x7ffbbe930000)
        sechost.dll => /c/Windows/System32/sechost.dll (0x7ffbc0330000)
        RPCRT4.dll => /c/Windows/System32/RPCRT4.dll (0x7ffbc03d0000)
        libgmp-10.dll => /mingw64/bin/libgmp-10.dll (0x6acc0000)
        COMCTL32.dll => /c/Windows/WinSxS/amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.1_none_b555e41d4684ddec/COMCTL32.dll (0x7ffbb4c20000)
        comdlg32.dll => /c/Windows/System32/comdlg32.dll (0x7ffbc0050000)
        GDI32.dll => /c/Windows/System32/GDI32.dll (0x7ffbc0500000)
        combase.dll => /c/Windows/System32/combase.dll (0x7ffbbeb70000)
        win32u.dll => /c/Windows/System32/win32u.dll (0x7ffbbdf60000)
        ucrtbase.dll => /c/Windows/System32/ucrtbase.dll (0x7ffbbdf90000)
        gdi32full.dll => /c/Windows/System32/gdi32full.dll (0x7ffbbe0e0000)
        msvcp_win.dll => /c/Windows/System32/msvcp_win.dll (0x7ffbbe3d0000)
        USER32.dll => /c/Windows/System32/USER32.dll (0x7ffbc0190000)
        shcore.dll => /c/Windows/System32/shcore.dll (0x7ffbbe880000)
        SHLWAPI.dll => /c/Windows/System32/SHLWAPI.dll (0x7ffbc0130000)
        SHELL32.dll => /c/Windows/System32/SHELL32.dll (0x7ffbbf750000)
        ole32.dll => /c/Windows/System32/ole32.dll (0x7ffbbf460000)
        MPR.dll => /c/Windows/SYSTEM32/MPR.dll (0x7ffbb6400000)
        USP10.dll => /c/Windows/SYSTEM32/USP10.dll (0x7ffba99b0000)
        WINMM.dll => /c/Windows/SYSTEM32/WINMM.dll (0x7ffbacd50000)
        WINSPOOL.DRV => /c/Windows/SYSTEM32/WINSPOOL.DRV (0x7ffba2580000)
```


# fakecygpty のインストール

[fakecygpty](https://github.com/d5884/fakecygpty) は、Windows 版 Emacs にて、 `M-x shell` で、 `bash` や `zsh` などのUnixシェルをインタラクティブなサブシェルとして動かすための[疑似端末](https://ja.wikipedia.org/wiki/擬似端末)のアダプタです。fakecygpty は、Unixのツールであるため、 `MSYSTEM=MSYS` 環境でコンパイルします。Windows Terminal で、 MSYS2シェルを起動するか、mintty の `c:\tools\msys64\msys2.exe` を起動し、下記を実行します。

```sh
ghq get https://github.com/d5884/fakecygpty
cd ~/ghq/github.com/d5884/fakecygpty/
autoreconf -ivf && ./configure && make install
```

これで、 `/usr/bin` (`C:\tools\msys64\usr\bin`)  に、 `fakecygpty.exe` と、 `qkill.exe` がインストールされます。これをEmacsで使うには、 `site-lisp` （または適当な load-path が通っている所） に `fakecygpty.el` を追加し、 `~/.emacs.d/init.el` に、fakecygpty のページで示されている設定を追加します。