CeGCC

CeGCC は Windows CE デバイス向けのオープンソースの非公式開発環境で、UNIX 環境で動作します。Cygwin や WSL を使えば Windows 環境でも利用できます。**第5世代向けアプリはこの方法では作成不可能**です。

**GCC 9.3.0** をベースに移植されている版を用いて説明します。

## Windows

### Cygwin を使う

パッケージ **libmpc3** が必要です。32-bit 版の場合はこちらから .tar.gz ファイルを、64-bit 版の場合はこちらをダウンロード・展開して利用します。PATH を設定した場合は `arm-mingw32ce-g++ -v`、設定していない場合は `(配置場所)/bin/arm-mingw32ce-g++ -v` を実行します。PATH を設定した後、既存のターミナルは開き直さないと反映されないことに注意します。これによって以下のような出力が得られれば環境構築は終了です。コマンドが見つからない等のエラーが出た場合は、正しく環境構築できていません。

```
Using built-in specs.
COLLECT_GCC=arm-mingw32ce-g++
COLLECT_LTO_WRAPPER=/main/bin/../libexec/gcc/arm-mingw32ce/9.3.0/lto-wrapper.exe
Target: arm-mingw32ce
Configured with: /home/cygwin/cegcc-build/gcc/configure --prefix=/opt/cegcc --build=i686-pc-cygwin --with-gcc --with-gnu-ld --with-gnu-as --enable-threads=win32 --disable-nls --enable-langua
ges=c,c++ --disable-win32-registry --disable-multilib --disable-interwork --without-newlib --enable-checking --with-headers --disable-__cxa_atexit --with-libiconv-prefix=/usr/local --host=i6
86-pc-cygwin --target=arm-mingw32ce
Thread model: win32
gcc version 9.3.0 (GCC)

```

### WSL や Cygwin が使えない場合

Cygwin や WSL が使えない場合は、こちらをダウンロード・展開して使用します。ただし、**`arm-mingw32ce-windres` が動作しません**。使用にあたっては、付属の openTerminal.bat で起動したコマンドプロンプト上で使用するか、setting.bat の内容を参考に環境変数 PATH を設定するかのどちらかが必要です。

## UNIX

### 作者の APT リポジトリを利用する場合

最も簡単、確実、高速な方法です。ただし、APT をパッケージ管理に用いる Linux ディストリビューション (Debianやその派生など) が必要で、パッケージも AMD64 用しか提供されていません。

`[trusted=yes]` は Ubuntu では必須なため記載していますが、システムによっては不要な場合があるので適宜取り除きます。

```
sudo bash -c 'echo "deb [trusted=yes] https://max.kellermann.name/debian cegcc\_buster-default main" > /etc/apt/sources.list.d/gcc-arm-mingw32ce.list'
sudo apt update
sudo apt install gcc-arm-mingw32ce

```

終わったら `arm-mingw32ce-g++ -v` を実行し、以下のような出力が得られれば環境構築は完了です。コマンドが見つからない等のエラーが出た場合は、正しくインストールできていません。

```
Using built-in specs.
COLLECT_GCC=arm-mingw32ce-g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/arm-mingw32ce/9.3.0/lto-wrapper
Target: arm-mingw32ce
Configured with: ../../../configure --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=arm-mingw32ce --disable-dependency-tracking --prefix=/usr --sysconfdir=/etc --with-gcc --with-gnu-ld --with-gnu-as --enable-threads=win32 --disable-nls --enable-languages=c,c++ --disable-win32-registry --disable-multilib --disable-interwork --without-newlib --enable-checking --with-headers --disable-__cxa_atexit
Thread model: win32
gcc version 9.3.0 (GCC)

```

アンインストールは通常のパッケージと同様に行えます。必要に応じて、`sudo apt autoremove` による一掃や、`/etc/apt/sources.list.d/gcc-arm-mingw32ce.list` の削除も行います。

```
sudo apt remove gcc-arm-mingw32ce

```

### コンパイル済みバイナリを使用する場合

APT を採用しないシステムでコンパイル済みバイナリを使用する方法です。

Debian 10 Buster AMD64、Linux AMD64/Arm64、Intel Mac AMD64 から最も自身のシステムに近いものをダウンロードし、適当な場所に展開します。

Apple Silicon Mac ではこれは動作せず、代わりに GCC 4.4.0 ベースの CeGCC を Mac に移植した版の動作が確認されています。こちらを使用して Windows CE 用のプログラムをコンパイルする場合は、後述のコンパイルコマンドから `-std=gnu++2a -march=armv5tej` を取り除く必要があります。

必要に応じて PATH に追加します。以下はインストール先が `/opt/cegcc` であり、環境変数をシステムに設定する例です。なお、この場合設定の反映には `~/.profile` の読み込みまたはシステムの再起動が必要です。

```
echo 'export PATH="$PATH:/opt/cegcc/bin"' >> ~/.profile

```

PATH を設定した場合は `arm-mingw32ce-g++ -v`、設定していない場合は `(配置場所)/bin/arm-mingw32ce-g++ -v` を実行します。これによって以下のような出力が得られれば環境構築は完了です。コマンドが見つからない等のエラーが出た場合は、正しくインストールできていません。

```
Using built-in specs.
COLLECT_GCC=arm-mingw32ce-g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/arm-mingw32ce/9.3.0/lto-wrapper
Target: arm-mingw32ce
Configured with: ../../../configure --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=arm-mingw32ce --disable-dependency-tracking --prefix=/usr --sysconfdir=/etc --with-gcc --with-gnu-ld --with-gnu-as --enable-threads=win32 --disable-nls --enable-languages=c,c++ --disable-win32-registry --disable-multilib --disable-interwork --without-newlib --enable-checking --with-headers --disable-__cxa_atexit
Thread model: win32
gcc version 9.3.0 (GCC)

```

### ソースからビルドする

以上の方法が使えないシステムでは、ソースからビルドすることで自分のシステム用のコンパイラを生成することができます。ただし、Apple Silicon Mac ではコンパイルに失敗することが知られています。また、GCC は巨大なプログラムであるため、かなり時間が掛かります。性能によっては数時間かかる場合もあります。

必要なパッケージを取得します。APT を用いないシステムでは、等価なものを適切な方法で取得してください。

```
sudo apt install git build-essential bison flex m4 libgmp-dev libmpc-dev libmpfr-dev texinfo

```

CeGCC のソースコードを取得します。Submodule 機能が使用されているため、`--recursive` を忘れないでください。これには少し時間が掛かります。

```
cd /path/to/clone
git clone --recursive https://github.com/MaxKellermann/cegcc-build.git
cd cegcc-build

```

CeGCC をインストールするディレクトリを作成し、所有者を自身に設定して書き込めるようにします。以下のコマンドの `/path/to/install` をインストールしたい場所で置き換えてください。よく分からない場合は `/opt/cegcc` とします。自身のホームディレクトリ下に配置する場合は `sudo` 無しで `mkdir` すれば十分です。

```
sudo mkdir /path/to/install
sudo chown "$(whoami):$(whoami)" /path/to/install

```

CeGCC のコンパイル中に使用するディレクトリを作成し、そこに移動します。通常は以下のコマンドで問題ありません。

```
mkdir /tmp/cegcc-output
cd /tmp/cegcc-output

```

いよいよ CeGCC をコンパイルします。これにはかなりの時間が掛かります。`-j` の直後には並行処理数を指定し、`--prefix=` の直後には先ほど作成したインストール先ディレクトリを指定します。以下は、並行処理数を論理コア数、インストール先を `/opt/cegcc` とした例です。なお、このコマンドを実行する時点で、`$OLDPWD` がソースコードのディレクトリ (cegcc-build) を指している必要があります。以上の手順を順番に行っていればこれは満たされているはずですが、途中で異なる操作を行った場合は変化している可能性があるため、`$OLDPWD` の部分を cegcc-build のパスで置き換えます。システムによっては `--prefix=` に各種パッケージのパス等も指定する必要があります。

```
"$OLDPWD/build.sh" -j$(nproc) --prefix=/opt/cegcc

```

完了したら、以下の出力とともに終了します。取得したソースコード、パッケージ、一時ディレクトリは削除しても構いません。エラーメッセージの場合は、その内容を元に調整して再度やり直してください。やり直す場合は、一時ディレクトリとインストール先ディレクトリの中身を空に戻しておくことを推奨します。

```
DONE --------------------------

```

以降の流れは、前節のコンパイル済みバイナリを使用する場合と同じです。アンインストールはインストール先ディレクトリを削除することで可能です。必要に応じて PATH も戻します。

## OS 非依存：Docker

Brain Hackers が CeGCC をセットアップ済みの Docker イメージを公開しています。このイメージを使うことで、ホストマシンの OS に関わらず、手軽に CeGCC 環境を入手できます。

Docker あるいは Docker Desktop の環境構築を行い、`docker pull brainhackers/gen1_builder` でイメージを入手できます。詳しい使い方については、インターネット等でたくさん見つかる Docker の解説記事を参照してください。

## コンパイル

ソースコードがあるディレクトリで

```
arm-mingw32ce-g++ -Wall -Wextra -O3 -std=gnu++2a -march=armv5tej -mcpu=arm926ej-s -static -s -lcommctrl -lcommdlg -lmmtimer -o AppMain.exe (コンパイルするファイル).cpp

```

を実行すると `AppMain.exe` が生成されるので、これをアプリの起動方法に従って起動します。C 言語を用いる場合は `g++`、`gnu++2a` の部分をそれぞれ `gcc`、`gnu2x` に置き換えます。ソースコードの拡張子はもちろん `.c` になります。

補足
--

一般的な GCC の使い方はここでは説明しきれないので、別で調べてください。また、外部ライブラリを使う場合やリンカエラーが出た場合は、必要なライブラリファイルを **`-l(ライブラリ名)`** の形でコンパイルオプションに追加します。Windows API 関数がどのライブラリで提供されるかは、「関数名 Windows CE」で出てくる MS の記事の一番下に書いてあります。上記のコンパイルオプションでは頻繁に使用される `commctrl`, `commdlg`, `mmtimer` を既に追加してあります。

リソースの埋め込みは通常通り `arm-mingw32ce-windres` を使えば可能です。参考までに、コマンドライン引数として C/C++ ソースファイル名を受け取り、`resource.rc` があればそれもコンパイルしてバイナリを生成するスクリプトを掲載しておきます: C / C++

文字コードは **UTF-8** を使用できます。また **GCC 9.3.0 ベース**なので **C++17 に対応し、C++20 にも部分的に対応**します。上のコンパイルオプションでは C++20 を有効化させています。

注意
--

ヘッダファイルは Windows PC のものを流用しているらしく、CE のものと定数が異なり変な挙動をすることがあります。例えば、最小化ボタンを表示させたはずが最大化ボタンが出たり、起動時に最大化するようにしたのに変化しなかったりします。Microsoft eMbedded Visual C++ 4.0、Pocket GCC 等の他のコンパイラに付属のヘッダファイルを参考に直接書き換えたり、ソースコード中で定義し直したり、直接数値で指定したりして対応します。

なお、ソースコード中での再定義は windows.h をインクルードした直後に以下のように記述することで行えます。以下は一部を修正するのみですが、他の定数も同様にして修正できます。

```
#ifdef UNDER\_CE
#if SW\_MAXIMIZE != 12
#undef SW\_MAXIMIZE
#define SW\_MAXIMIZE 12
#endif
#if SW\_MINIMIZE != 6
#undef SW\_MINIMIZE
#define SW\_MINIMIZE 6
#endif
#if WS\_MINIMIZEBOX != 0x00010000L
#undef WS\_MINIMIZEBOX
#define WS\_MINIMIZEBOX 0x00010000L
#endif
#if WS\_MAXIMIZEBOX != 0x00020000L
#undef WS\_MAXIMIZEBOX
#define WS\_MAXIMIZEBOX 0x00020000L
#endif
#endif

```

## オリジナルの CeGCC (非推奨)

デフォルトでは Windows CE 3.0 でも動くものが生成されます。Linux 環境にインストールするのが無難です。

まず、32-bit 版の `libgmp` と `libmpfr` をインストールします。64-bit 版 Linux でも 32-bit 版が必要です。次に、ARM 用の CeGCC を `/opt` 以下に展開し、各種環境変数を設定します。その後、`ln -s` を用いて `libgmp.so.3` と `libmpfr.so.1` のシンボリックリンクを作成します。

1. ↑ `--recursive` 無しで実行した場合は submodule 部分が未取得の状態になります。これを修正するには、取得したディレクトリに入って `git submodule update --init --recursive` を実行します。
2. ↑ これが最も無難な設定ですが、メモリ容量がコア数に対して小さい環境では並行処理数を減らした方が効率が良いなど、環境によって最適な設定は異なります。