UbuntuとVisual Studio CodeでF#の開発環境の構築 + デバッグ方法

LinuxでもF#で書いたアプリを動かせるみたいなので試しに開発環境を作ってみた。

今回作った環境で使ったソフトウェアは次の通り。

・Ubuntu 14.04.3 (32bit)
・Visual Studio Code 0.8 (32bit)
・Mono 4.0.4
・F# 4.0

これでVisual Studio CodeでF#のコードを書いて実行とデバッグができるようになった。

# F#のコードのコンパイルと実行ができる環境の構築
F#の公式サイトにLinuxでF#を動かすやり方を書いたドキュメントがある。

[Use F# on Linux](http://fsharp.org/use/linux/)

今回はOption 1の手順でやってみた。

まずはapt-getでXamarinのMonoパッケージをインストールできるようにリポジトリを追加する。

    $ sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
    $ echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list

次にMonoとF#の開発ツールをインストールする。

    $ sudo apt-get update
    $ sudo apt-get install mono-complete fsharp

インストールできたか確認するためにF#のコンパイラとMonoのバージョンを出力してみる。
次のようにバージョンが出力されたらOK。

    $ fsharpc --help
    F# Compiler for F# 4.0 (Open Source Edition)
    Freely distributed under the Apache 2.0 Open Source License
    ...
    $ mono -V
    Mono JIT compiler version 4.0.4 (Stable 4.0.4.1/5ab4c0d Tue Aug 25 23:10:38 UTC 2015)
    Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
    ...


# Visual Studio Codeのインストール
Visual Studio Codeは公式サイトでZIPファイルで配布されている。

[Visual Studio Code](https://code.visualstudio.com/)

Ubuntuが32bitなのでVisual Studio Codeもそれに合わせて32bitバージョンをダウンロードする。

ダウンロードが終わると"VSCode-linux-ia32.zip"というファイルがあるので、好きなところに展開する。今回は/opt/に展開した。

    $ sudo unzip -d /opt/ [VSCode-linux-ia32.zipのパス]
    $ sudo mv /opt/VSCode-linux-ia32/ /opt/VSCode

これでインストールは終わり。

この記事ではVisual Studio Codeの基本的な使い方の説明は省くので、分からない人は次のサイトを参考にしてください。

[特集：Visual Studio Code早分かりガイド：Visual Studio Codeの使い方、基本の「キ」 (1/4) - ＠IT](http://www.atmarkit.co.jp/ait/articles/1507/10/news028.html)
# Hello Worldを書く
ここまでできたらF#のコードを書いて実行ができるので、Visual Studio CodeでHello Worldを書いて実行してみる。

まずはコードを保存するディレクトリを作成する。

    $ mkdir -p ~/dev/fsharp-hello-world
    $ cd ~/dev/fsharp-hello-world

次にVisual Studio Codeを起動する。

    $ /opt/VSCode/Code

![first-screen.png](https://qiita-image-store.s3.amazonaws.com/0/39729/c7e02c61-07bd-9912-f15f-4b78f9b338d9.png)

Visual Studio Codeで"HelloWorld.fs"というファイルを作成してコードを書く。

```fsharp
module HelloWorld

[<EntryPoint>]
let main argv =
    printfn "Hello World"
    0
```

コンソールを開いてコンパイルして実行する。

    $ ls
    HelloWorld.fs
    $ fsharpc HelloWorld.fs
    F# Compiler for F# 4.0 (Open Source Edition)
    Freely distributed under the Apache 2.0 Open Source License
    $ ls
    HelloWorld.exe  HelloWorld.fs
    $ mono HelloWorld.exe
    Hello World

上のように表示されればOK。

# Visual Studio Codeでデバッグする
Visual Studio CodeはMonoを使ったデバッグに対応してるのでF#で書いたプログラムのデバッグもできる。
今回はさっきのHelloWorldのプログラムにブレークポイントを置いて実行を停止させてみる。

## プログラムをデバッグバージョンでコンパイルする
まずはコンソールで次のコマンドを実行して、HelloWorld.fsをデバッグバージョンでコンパイルする。

    $ fsharpc --debug:full HelloWorld.fs
    F# Compiler for F# 4.0 (Open Source Edition)
    Freely distributed under the Apache 2.0 Open Source License
    $ ls
    HelloWorld.exe HelloWorld.exe.mdb HelloWorld.fs

HelloWorld.exe.mdbファイルが生成されていればOK。

ちなみにfsharpcには"--debug"というオプションもあるけど、"--debug:{full | pdbonly}"とは別のオプションなので注意。
Visual Studio Codeでデバッグをするには*.mdbファイルが必要だけど、"--debug"オプションを指定しても生成されないのでブレークポイントなどが機能しない。

## launch.jsonの編集
launch.jsonを編集してVisual Studio Codeでデバッグできるようにする。

launch.jsonはVisual Studio Codeの「DEBUG」の右上の"Configure"ボタンをクリックすると開く。

![launch.json.png](https://qiita-image-store.s3.amazonaws.com/0/39729/fa371440-f2c3-8d3d-0f74-7369e2c33382.png)

launch.jsonの内容を次のように変更する。


```text
{
	"version": "0.1.0",
	"configurations": [
		{
			// "Configure"ボタンの左に表示される名前。
			"name": "Launch HelloWorld",
			// この設定の種類。今回はMonoを使うので"mono"を指定する。
			"type": "mono",
			// 起動するプログラム。
			"program": "HelloWorld.exe",
			"stopOnEntry": false,
			"args": [],
			"cwd": ".",
			"runtimeExecutable": null,
			// monoコマンドに渡す引数。
			"runtimeArgs": ["--debug"]
		},
		// 以降は既に起動しているプログラムにアタッチする時の設定で今回は使わないので省略する。
		...
	]
}
```

(ところでJSONってコメントはサポートしてなかったと思うんだけど、launch.jsonには普通にコメントが書いてあるのはVisual Studio Codeの独自拡張なんだろうか。)

## デバッグの開始
HelloWorld.fsの行番号5の左横をクリックしてブレークポイントを置く。

![breakpoint.png](https://qiita-image-store.s3.amazonaws.com/0/39729/16fd2a2d-752e-69d0-872f-da655c4e653f.png)

「DEBUG」のStartボタン(緑の三角形)をクリックしてデバッグを開始する。

![start-debug.png](https://qiita-image-store.s3.amazonaws.com/0/39729/3e4ca301-2e79-e3cb-b89d-4ce4681e560c.png)

ブレークポイントの位置で実行が停止すればOK。

![stop-at-breakpoint.png](https://qiita-image-store.s3.amazonaws.com/0/39729/ec5880c9-545f-09a0-264c-bd35b0e5e1e7.png)

あとはソースコードの上に実行制御系のボタン("Continue"、"Step Over"、"Step Into"、"Step Out"、"Stop")と、左側に"VARIABLES"、"WATCH"、"CALL STACK"、"BREAKPOINTS"のエリアがあるので、これらを使いつつデバッグする。

ただ、"VARIABLES"のローカル変数一覧にはlet構文で宣言した値は表示されない。mutableな値だと表示される。
Visual Studioだとlet構文で宣言した値もローカル変数一覧に表示されるので、少し不便に感じる。

# 最後に
UbuntuにVisual Studio CodeをインストールしてF#のコードを書くのにどの程度便利か確かめてみた。簡単に環境の構築ができたし、Visual Studio CodeでF#のシンタックスハイライトされてデバッグができたのは良かった。

特にVisual Studio CodeでF#のコードのデバッグができるのはすごく良い。Linuxで（C++などの）コードを書くときはVimを使っていたけど、ブレークポイントを置いたり変数の値を見るのがVimでできなかった[^1]（GDBでコマンドを打てばできるけど、Visual Studioに慣れてて不便に感じていた）ので、デバッグに対応してるのは自分にとってはポイントがすごく高い。

ただ、Visual Studio CodeにはIntelliSenseの機能があってC#（と他のいくつかの言語）には対応してるんだけど、自分が試した限りF#のコードでIntelliSenseは動かなかった。IntelliSense（もしくはコード補完）も自分にとっては重要な機能なので対応してないのが惜しい。

Visual Studio Codeはまだ0.8.0だし、IntelliSenseがF#に対応するのを期待して小さめのプログラムなら書いてみようかと思ってる。

[^1]: pyClewnとかを試してみたけど自分はうまく動かせる状態にできなかった。