Visual Studio 2019でSDL2を静的リンクさせる覚書

# 概要
Visual C++とSDL2を静的リンクさせることができたので、手順を書き残しておきます。
個人的によくお世話になるSDL2+OpenGL2の環境でやってみます。


# 動作環境と前提条件
- Microsoft Visual Studio 2019
    - Visual C++の開発環境が必要です。
- SDL2(v2.0.10)
- 今回は32bitの実行ファイルを作成します。


# 前準備
## Visual Studio 2019のインストール
Visual Studio 2019 Communityをインストールします。手順は割愛。
既定ではVC++の開発環境は入らないので、インストール時にVisual C++コンポーネントを含めるようにします。

## CMakeのインストール
[ここ](https://cmake.org/download/)からWindows用のCMakeをダウンロードします。
私は**Windows win64-x64 ZIP**を選択しました。
ZIP版の場合は`(CMakeをインストールしたディレクトリ)\bin`を環境変数のPathに追記する必要があります。

## SDL2のインストール
[ここ](https://www.libsdl.org/download-2.0.php)から入手します。
今回はSDL2をソースコードからビルドするため、**SDL2-2.0.10.zip**をダウンロードします。
ファイルを展開して任意のディレクトリに保存してください。
今回は以下の場所に格納しました。
`C:\dev\SDL2-2.0.10`


# SDL2のビルド
上記のSDL2を配置したディレクトリ上でコマンドプロンプトを立ち上げます。
ここで、SDL2をVisual Studio 2019でビルドするソリューションを作成するため、CMakeコマンドを実行します。

```
md build
cd build
cmake -G "Visual Studio 16 2019" -A Win32 ..
```

`(SDL2をインストールしたディレクトリ)\build\`の中に作成された**SDL2.sln**をVisual Studioで開きます。
ソリューション構成の中にいくつかありますが、`Debug`と`Release`に対してそれぞれビルドします。
`(SDL2をインストールしたディレクトリ)\build\(DebugまたはRelease)`の中の以下のファイルを使用します。

- Debug
    - SDL2maind.lib
    - SDL2-staticd.lib
- Release
    - SDL2main.lib
    - SDL2-static.lib


# Visual C++プロジェクトの作成と設定
## プロジェクトの作成
Visual Studio 2019で新しいプロジェクトを作成します。
`Windows デスクトップ ウィザード`で作成します。
途中表示されるオプションで、
* アプリケーションの種類: デスクトップ アプリケーション (.exe)
* 追加のオプション: `空のプロジェクト`だけにチェック
として完了します。

## SDL2のファイルを配置
`(SDL2をインストールしたディレクトリ)/include`の中のファイルを`(プロジェクトのディレクトリ)/include/SDL2`にコピーします。
`(SDL2をインストールしたディレクトリ)/build/include`の中のファイルを`(プロジェクトのディレクトリ)/include/SDL2`に上書きコピーします。
`(プロジェクトのディレクトリ)/lib`の中にDebugとReleaseでディレクトリを切って、それぞれの中に対応するSDL2のlibファイルを配置します。

## プロジェクトの設定
### すべての構成
#### 全般
- 構成の種類: アプリケーション (.exe)
- 文字セット: マルチバイト文字セットを使用する
- 出力ディレクトリ: `$(SolutionDir)bin\$(Configuration)\`
- 中間ディレクトリ: `$(SolutionDir)obj\$(Configuration)\`

#### VC++ ディレクトリ
- インクルードディレクトリ:
  `$(ProjectDir)include`
  `$(ProjectDir)include\SDL2`
- ライブラリディレクトリ:
  `$(ProjectDir)lib\$(Configuration)`

#### リンカー
- システム
  - サブシステム: Windows (/SUBSYSTEM:WINDOWS)

### Debug
#### リンカー
- 入力
  - 追加の依存ファイル:
    `SDL2maind.lib`
    `SDL2-staticd.lib`
    `opengl32.lib`
    `version.lib`
    `winmm.lib`
    `imm32.lib`
    `setupapi.lib`

### Release
#### C/C++
- 全般
  - デバッグ情報の形式: なし

#### リンカー
- 入力
  - 追加の依存ファイル:
    `SDL2main.lib`
    `SDL2-static.lib`
    `opengl32.lib`
    `version.lib`
    `winmm.lib`
    `imm32.lib`
    `setupapi.lib`
- マニフェストファイル
  - マニフェストの生成: いいえ (/MANIFEST:NO)
- デバッグ
  - デバッグ情報の生成: いいえ
- 最適化
  - リンク時のコード生成: 既定


# ビルドしてみる
cppファイルを作成し、以下のコードを記述します。

```cpp:main.cpp
#include "SDL.h"
#include "SDL_opengl.h"

int main(int argc, char** argv) {
    SDL_Init(SDL_INIT_VIDEO);

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
    SDL_DisplayMode current;
    SDL_GetCurrentDisplayMode(0, &current);
    SDL_Window* window = SDL_CreateWindow("SDL2 static linking with VC++",
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        640, 480,
        SDL_WINDOW_OPENGL);
    SDL_GLContext glContext = SDL_GL_CreateContext(window);

    SDL_Event ev;
    bool running = true;
    while (running) {
        while (SDL_PollEvent(&ev)) {
            if (ev.type == SDL_QUIT)
                running = false;
        }

        glViewport(0, 0, 640, 480);
        glClearColor(0.0, 0.0, 0.0, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
        SDL_GL_SwapWindow(window);
    }

    SDL_GL_DeleteContext(glContext);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}
```
ビルドして実行すると、真っ黒な中身のウィンドウが立ち上がります。
また、`Debug`で実行した場合、ブレークポイントを設定して止めることもできます。

SDL2のアプリケーションをDLLなしで動かせるようになりました。