Simutransをビルドしてみる

# はじめに
Simutransは割と有名な(?)公共交通シミュレーションゲームですが、よくある環境でも動くように公式のバイナリは32Bit版で、しかもマルチスレッドでの動作に対応していません。

そこでこの記事では自力でビルドすることによって、64Bit対応でしかもマルチスレッド処理分散までできてしまうSimutransを作ってみる手順を紹介します。

なおこの記事では、Arch Linux上でMinGWを使ったWindows用Simutransのクロスビルドと、Windows上でMSYS + MinGWを使った普通の(?)ビルドに挑戦します。

> この手順でビルドしたSimutransが完全に意図した動作になるかどうかは未検証です。急な不具合などが発生する可能性があります。

# 用意するもの
AURにMinGWクロスビルド用のライブラリが充実しているため、Arch Linux環境を利用します。AURを利用するため、yaourtなどのツールを導入しておきましょう。

Windows上の場合は、事前にMSYS2を導入しておいてください。

# ビルドの準備(Linuxのみ)
ビルドに必要なパッケージをインストールします。
MinGW関連のインストールは全てAURから行われるので、事前にbase-develをインストールしておきましょう。
あとで使うツールもついでに入れておきます。

```bash
$ yaourt -S base-devel git zip unzip
$ yaourt -S mingw-w64-zlib mingw-w64-bzip2 mingw-w64-libpng
```

# ビルドの準備(MSYSのみ)
こちらはpacmanから全て導入出来ます。

```bash
$ pacman -S make mingw-w64-x86_64-toolchain mingw-w64-x86_64-zlib mingw-w64-x86_64-bzip2 mingw-w64-x86_64-libpng
```

# 安定版ソースコードの取得
SourceForgeから落としてきます。執筆時の安定版なので、その都度最新版を確かめてダウンロードしてください。
なぜかビルドに必要なファイルがいくつかが欠落しているので、Githubからもらってきます。

```bash
$ wget https://jaist.dl.sourceforge.net/project/simutrans/simutrans/120-2-2/simutrans-src-120-2-2.zip
$ unzip simutrans-src-120-2-2.zip -d simutrans
$ cd simutrans
$ wget https://raw.githubusercontent.com/aburch/simutrans/master/Simutrans.manifest
$ wget https://raw.githubusercontent.com/aburch/simutrans/master/distribute.sh
```

# 開発版ソースコードの取得(共通)
Githubからクローンしてきます。cdして次の作業に備えましょう。

```bash
$ git clone https://github.com/aburch/simutrans.git
$ cd simutrans
```

# 設定ファイルの準備(共通)
デフォルトの設定ファイルをコピーして、ビルド用の設定ファイルを準備します。
適当なエディタで設定ファイルを開き、以下のように編集します。

蛇足ですが、`+3,13`は`3行目から13行分にわたって`という意味です。
編集箇所の目安にお使いください。

```bash
$ cp config.template config.default
$ vim config.default
```

```diff
@@ -3,8 +3,13 @@
 # copy this file to config.default and adjust the settings
 #
 
+CC=x86_64-w64-mingw32-gcc
+CXX=x86_64-w64-mingw32-g++
+CFLAGS=-fpermissive
+CXXFLAGS=$(CFLAGS)
+
 #BACKEND = allegro
-#BACKEND = gdi
+BACKEND = gdi
 #BACKEND = opengl
 #BACKEND = sdl
 #BACKEND = sdl2
@@ -12,7 +17,7 @@
 #BACKEND = posix
 
 #COLOUR_DEPTH = 0
-#COLOUR_DEPTH = 16
+COLOUR_DEPTH = 16
 
 #OSTYPE = amiga
 #OSTYPE = beos
@@ -20,23 +25,23 @@
 #OSTYPE = freebsd
 #OSTYPE = haiku
 #OSTYPE = linux
-#OSTYPE = mingw
+OSTYPE = mingw
 #OSTYPE = mac
 
 #DEBUG = 1    # Level 1-3, higher number means more debug-friendly but slower, see Makefile
 #MSG_LEVEL = 1 # Level 1-4, more runtime debug messages (without only warnings and errors)
-#OPTIMISE = 1 # Add umpteen optimisation flags
+OPTIMISE = 3 # Add umpteen optimisation flags
 #PROFILE = 1  # Enable profiling
 #PROFILE = 2  # Enable profiling with optimisation flags, can be used with `OPTIMISE = 1'
 
-#STATIC = 1   # Enable static linkage, currently mingw only
+STATIC = 1   # Enable static linkage, currently mingw only
 
 #WITH_REVISION = 1 # adds the revision from svn; required for networkgames
 # if you do not use SVN, add -DREVISION="1234" to the FLAGS below
 
 #WIN32_CONSOLE = 1 # adds a console for windows debugging
 
-#MULTI_THREAD = 1 # Enable multithreading
+MULTI_THREAD = 1 # Enable multithreading
 
 # Define these as empty strings, if you don't have the respective config program
 #ALLEGRO_CONFIG = allegro-config
@@ -76,7 +81,7 @@
 # DESTINATION_CITYCARS: Citycars can have a destination (not recommended)
 #
 # In order to use the flags, add a line like this: (-Dxxx)
-# FLAGS = -DUSE_C
+FLAGS = -DUSE_C
 
 # Output directories:
 #
```

# Makefileの修正(ほぼ共通)
今度はビルドが通るようにMakefileを編集します。念のためオリジナルは残しておきました。
これも以下のように編集してください。

なおMSYSの場合は`windres`の箇所は変更しないでそのままにしてください。

```bash
$ cp Makefile Makefile.orig
$ vim Makefile
```

```diff
@@ -32,7 +32,7 @@
       else
         ifeq ($(OSTYPE),mingw)
           CFLAGS  += -DPNG_STATIC -DZLIB_STATIC
-          LDFLAGS += -static-libgcc -static-libstdc++ -Wl,-Bstatic -lpthread -lbz2 -lz -Wl,-Bdynamic -Wl,--large-address-aware
+          LDFLAGS += -static-libgcc -static-libstdc++ -Wl,-Bstatic -lpthread -lbz2 -lz -Wl,-Bdynamic
           ifneq ($(STATIC),)
             ifeq ($(shell expr $(STATIC) \>= 1), 1)
               CFLAGS  += -static
@@ -613,7 +613,7 @@
 
 ifneq ($(findstring $(OSTYPE), cygwin mingw),)
   SOURCES += simres.rc
-  WINDRES ?= windres
+  WINDRES ?= x86_64-w64-mingw32-windres
 endif
 
 CCFLAGS  += $(CFLAGS)
```

# ソースコードの修正(Linuxのみ)
`Windows.h`が大文字で始まっているせいでコンパイルがこけてしまいます。
`utils/searchfolder.cc`の該当箇所を修正しましょう。

```bash
$ cp utils/searchfolder.cc utils/searchfolder.cc.orig
$ vim utils/searchfolder.cc
```

```diff
@@ -5,7 +5,7 @@
 #include <dirent.h>
 #else
 #define NOMINMAX
-#include <Windows.h>
+#include <windows.h>
 #include <io.h>
 #endif
```

# いざビルド(共通)
ここまでできればmakeするだけの簡単ビルドです。
並列コンパイルをする場合はCPUのコア数+1ぐらいの値を`-j`の後ろにつけましょう。

```bash
$ make -j9
```

# パッケージの作成(共通)
最後に、コンパイルしたバイナリの他に言語ファイルやテーマなど起動に必要なファイルをまとめてパッケージを作成します。以下のコマンドを叩いて、生成された`simuwin-.zip`をWindows側に転送すればOKです。

```bash
$ cp build/default/sim sim.exe
$ ./distributes
```

# いざプレイ
`simuwin-.zip`を展開して、事前にダウンロードしておいたお好みの基本pakを`simutrans.exe`と同じ階層に入れてから起動します。後はいつも通りのんびりプレイしていきましょう。

# おまけ - makeobjのビルド
アドオンの自作に必要なmakeobjもビルドしてみましょう。

まずはmakeobjディレクトリに移動して、Makefileを修正します。
なぜかpentium指定になっていて64Bitではビルド出来ないのでnativeに変更しておきます。

```bash
$ cd makeobj
$ cp Makefile Makefile.orig
$ vim Makefile
```

```diff
@@ -30,7 +30,7 @@
 endif

 ifeq ($(OSTYPE),mingw)
-  OS_OPT   ?= -DPNG_STATIC -DZLIB_STATIC -march=pentium
+  OS_OPT   ?= -DPNG_STATIC -DZLIB_STATIC -march=native
   LDFLAGS += -static-libgcc -static-libstdc++ -static
   # we need the libraries EXACTLY in this order to link
   STD_LIBS = -lmingw32 -lpng -lz
```

後はコンパイルするだけです。

```bash
$ make -j9
```

コンパイルが終わったら、ソースコードのルートディレクトリにある`build/default/makeobj`の中に`makeobj.exe`ができあがりますので、こちらをコピーしてご利用ください。

# おわりに
事前の準備にいろいろとやることが多いですが、そんなに難易度は高くない作業でビルドが可能です。
自前ビルドの快適Simutrans生活、あなたも始めてみては？