Help us understand the problem. What is going on with this article?

Windows+VisualStudioCode+CMake+Ninja+clang/clang++でC/C++のプログラム組んでデバッグする話しながらD言語の布教をする

はじめに

まず、D言語はすばらしい。いいね?

注意: 本記事は冒頭からこの出だしであるように、まじめに会社とかで読む記事としては向いていない。冗談を冗談として理解できる環境と精神状態で読んでいただきたい。

非常に遺憾ながらC++でプログラムを組む必要があったので、せめてもという思いで普段D言語で簡単快適なプログラミングをしている環境である、VisualStudioCodeにて環境構築をすることにした。D言語のdubという快適なビルド環境につかり切った今、makeに疲弊するのはもう嫌なのでCMake+Ninjaでビルドすることにして、モダンなコンパイラということでclang(clang++)を選択した。ものすごく疲れたのでみんなは黙ってD言語をインストールすると良い。ちなみに、我々D言語を使用する者の間では、D言語をインストールするという行為を「人生最良の行動(It's a best practice for our life)」と呼称している。

clangのインストール

もはやWindowsだとこの時点で挫折しそうになる。
みんなはD言語を使うことでこの苦難を容易に回避することができるので参考にしてほしい。
clangを使用する場合、ランタイムとして、MSVCのランタイムを使うかMinGWのランタイムを使うかの選択を迫られる。
MinGWの場合はmsys2からインストールするのが楽だろう。

MSYS2
$ pacman -S mingw-w64-x86_64-clang

公式からバイナリを直接ダウンロードすると、MSVCをランタイムとして選択することになる。私はインストールが面倒なので、7zipで無理やりこじ開けて、適当な場所(本記事ではC:\app\llvmとしておきます)に配置した。あとは配置先のclang++.exeとか、VisualStudioのlink.exeとかにちゃんとパスが通っていれば(ムズい)、うまくコンパイルすることができるはずである。
以前はD言語のdmdの64bitコンパイルなどもVisualStudioに依存していたが、最近はVisualStudioのインストールすら必要なくなったらしい。さらに、DMDだけでなく、LDCもそれに追従している。素晴らしい。

VisualStudioのインストール

MSVCをランタイムとして選択する場合は、適切なライセンスのVisualStudioをインストールする必要がある。本記事では以降MSVCをランタイムとして選択した場合について取り扱う。
通常VisualStudioにはVisualStudioComunityという無償バージョンがあるのだが、OSS以外の用途にそこそこ大きな企業で使用する場合にはライセンス上使用することができない。その場合には、いざ、VisuaStudioのHPという名の大海原へ要件にうまく合致するパッケージを探す旅に出よう。4つのロードポーネグリフをすべて解読し、指し示す最果ての地ラフテルを目指すのだ。

光の道を示すがごとくたいていの場合にライセンス条件が合致する「Build Tools for Visual Studio 2019」をインストールする道筋を示したいところだが、Microsoftのホームページは数十秒ごとにたどり方とURLが変化する不思議のダンジョンと化しており、さらにその時その時で最新の環境がころころ変わってすぐに情報が陳腐化してしまうため、残念ながらそのダウンロード方法を教えることは難しい。
とはいえ、現時点ではこの記事に記載されている以下のアドレスが生きているかもしれない。参考にしてほしい。願わくば、あなたがこの記事を読むその時まで、リンク先があらんことを。
https://aka.ms/vs/16/release/vs_buildtools.exe

何度目かになるが、このあたりでライフが底をつきかけるので、そんなときにはD言語を使用することで心の平穏を取り戻すことをお勧めする。
D言語はいいぞぉ!
念のため、D言語のインストールはこちらから

CMakeのインストール

中途半端に流行ったが結局覇権をとるには至らずMesonとかいう後続まで許している体たらくだが、今回はCMakeを使用する。MesonがPythonを要求しているのが耐えがたい苦痛を与えてきたからだ。
CMakeの公式はここだ。
D言語を使えば今はdubという神がかったパッケージ管理&ビルドツールがあるので、何も考える必要がないのをここに言い添えておく。そういえば一昔前にdub最強説D言語のフォーラムに上がっていた。実のところ最近はdubのつらみが高まっているとのうわさもあるが、ここでは割愛する。この記事はD言語を賛美する記事だからである。

しかしながら流石中途半端には人気のあるCMake、インストール方法はいくらでも記事が上がっている基本的な使い方も

ただし、記事が上がっているからと言って使いやすいツールでないことだけは確かである。逆に言うと使うのに多大な苦痛を伴うため、勇あるものが立ち上がった結果、この記事のように記事が増えるのである。D言語のように情報が少ないのは一概に悪いことではなく、苦痛を伴わず使うことのできる優秀な言語であることが主な要因となっていることについても口添えておこう。

さて、CMakeの設定であるがこまごまとした設定ができるように見えて、ちょっとでも設定を変えようとすると、これもうmake直接書いたほうが速くない?みたいなレベルの細かさが要求される。そして、その設定を書き上げるのは至難の業である。あーあ。dubなら(ry

私は公式サイトからインストールが面倒なので.zipを拾ってきて解凍し、適当なところに配置した。うちの会社では管理者権限がもらえず、申請なしに勝手にインストールすることができないのだ。働き方改革の名のもとにこのへんもう少し何とかしていただきたい。

Ninjaのインストール

ちなみにNinjaっていうのはあれだ。makeのすごいやつだ。Ninjaなのでビルドの速度は音速を超える。今までmakeでビルドしている途中にはランチしてシエスタしてコーヒーを1杯くらい飲むことができるところだが、残念ながらその優雅な時間は無くなると思ってほしい。ちなみにD言語のビルドはもっと速い。その速度は光速を超え、飲んだはずのコーヒーがカップに戻っているレベルだ。

Ninjaで問題なのはそのググラビリティである。はっきり言ってD言語なんかよりよほどググり難い名前をしている。当たり前だ、Ninjaといったら国際的に人気な日本の超人集団のことである。俺は詳しいんだってばよ。ちなみに、D言語で検索するときは"D言語"とダブルクォーテーションで囲ったり、dlangのキーワードにしたりすると検索しやすい。

さて、仰々しくインストールなどという項を作ってしまったが、実のところNinjaはインストールを必要としない。公式サイトリリースページで落としたZIPから解凍して、適当なフォルダに置いておくだけだ。PATHを通す必要もあまりない。
ちなみに、CMakeが勝手にルール作成してくれるので、使い方を覚える必要もあまりない。

CMakeを使ったビルド

CMakeを使うには、CMakeLists.txtというテキストファイルを作成する必要がある。拡張子が.txtなので、テスト中に発生するログなどと一緒に幾度もゴミ箱の彼方に葬り去られそうな名前なので、注意して運用しなければならない。

path_to_project/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)

# コンパイラの設定
if(CMAKE_CXX_COMPILER MATCHES "clang\\+\\+")
    # フラグ設定
    set(CMAKE_CXX_FLAGS "-Wall --std=c++17 -Wno-register -Wno-unknown-pragmas")
    set(CMAKE_CXX_FLAGS_RELEASE "-O3 -s -DNDEBUG")
    set(CMAKE_CXX_FLAGS_DEBUG   "-O0 -g3 -gcodeview")
endif()
if(CMAKE_C_COMPILER MATCHES "clang")
    # フラグ設定
    set(CMAKE_C_FLAGS "-Wall --std=c89 -Wno-unknown-pragmas")
    set(CMAKE_C_FLAGS_RELEASE "-O3 -s -DNDEBUG")
    set(CMAKE_C_FLAGS_DEBUG   "-O0 -g3 -gcodeview")
endif()

# インクルードパスの登録
include_directories("include/")

# ファイルを登録
file(GLOB_RECURSE SOURCES src/*.c ${SOURCES})
file(GLOB_RECURSE SOURCES src/*.cpp ${SOURCES})

# 実行ファイル作成
add_executable(test.exe ${SOURCES})

余談だが私はC++は最新仕様(C++17)、C言語は古い仕様(C89)でのビルドを前提にして組むことが多い。C++11以降の仕様は、auto/decltype/constexprなどD言語に触発されて追従したような多数の新機能が追加されており恩恵が大きい。さらにどうせC++のコンパイラなんてg++かclang++、cl(MSVC++)くらいしか使われないのでいろんなコンパイラを想定したプログラムを組む必要性が薄い。しかしC言語だとそうはいかない。数えきれないほどのコンパイラ・ターゲットアーキテクチャが存在し、その最大公約数的な仕様がC89程度だからだ。C99の_Complexみたいな仕様本当に必要だったか?ちなみにD言語では非推奨機能の対象になった。

話を戻そう。次に作ったのはClang用の設定ファイル。原理はよくわかっていない。cmakeの-Cというオプションで渡すと変数?の初期化?に使用される?ようだ。以下のように実行ファイルのパスを指定することで、clang.exeにパスが通ってなくても使えるようになるらしい。以下の例はC:\app\llvmというフォルダにclangをインストールした場合の記述となっている。適宜自分の環境に読み替えていただきたい。

path_to_project/build/clang_settings.cmake
set(CMAKE_C_COMPILER      "C:/app/llvm/bin/clang.exe"   CACHE STRING "clang compiler" FORCE)
set(CMAKE_C_COMPILER_ID   "Clang"                       CACHE STRING "clang compiler" FORCE)
set(CMAKE_CXX_COMPILER    "C:/app/llvm/bin/clang++.exe" CACHE STRING "clang++ compiler" FORCE)
set(CMAKE_CXX_COMPILER_ID "Clang"                       CACHE STRING "clang++ compiler" FORCE)
set(CMAKE_SYSTEM_NAME     "Generic"                     CACHE STRING "Generic target system" FORCE)

ちなみに、D言語のdubでは、--compiler=ldc2--compiler=C:\app\ldc\bin\ldc2.exeなどとすることで、コンパイラを切り替えることが可能である。

CMakeではout-of-sourceビルドなどというものが使えるらしいが、たいていの解説サイトにはそんなものを使わずにbuildフォルダを作ってその中でビルドをしているので、本記事においてもその慣例を踏襲することとする。

また、ビルドにはバッチファイルを使用するのが楽だ。
もちろんバッチを使わなくともビルドすることは可能だが、殺人的な長蛇のコマンド列に確実に腱鞘炎になること請け合いだ。以下の例ではclang_settings.cmakeに設定をまとめたためかなりマシになったが、そうでなければcmakeのコマンドラインへの追加が必要になる。

path_to_project/build/build-debug.bat
@set CMAKE_EXE=C:\app\cmake\bin\cmake.exe
@set NINJA_BIN=C:\app\ninja
@set NINJA_EXE=C:\app\ninja\ninja.exe
@set MY_CMAKE_ARGS=
@set MY_CMAKE_ARGS=%MY_CMAKE_ARGS%      -G Ninja
@set MY_CMAKE_ARGS=%MY_CMAKE_ARGS%      -C clang_settings.cmake
@set MY_CMAKE_ARGS=%MY_CMAKE_ARGS%      -DCMAKE_BUILD_TYPE=Debug
@set MY_CMAKE_ARGS=%MY_CMAKE_ARGS%      ..

if "%~1" == "clean" goto L_CLEAN
if "%~1" == "force" goto L_BUILD_FORCE
goto L_BUILD

:L_BUILD
%CMAKE_EXE% %MY_CMAKE_ARGS%
if errorlevel 1 goto L_ERROR
%NINJA_EXE% -v
if errorlevel 1 goto L_ERROR
goto L_EXIT

:L_BUILD_FORCE
%CMAKE_EXE% %MY_CMAKE_ARGS%
if errorlevel 1 goto L_ERROR
%NINJA_EXE% clean
if errorlevel 1 goto L_ERROR
%NINJA_EXE%
if errorlevel 1 goto L_ERROR
goto L_EXIT

:L_NINJA_CLEAN
%CMAKE_EXE% %MY_CMAKE_ARGS%
if errorlevel 1 goto L_ERROR
%NINJA_EXE% clean
if errorlevel 1 goto L_ERROR
goto L_EXIT

:L_ERROR
exit /b %ERRORLEVEL%

:L_EXIT
exit /b 0

そして以下のようにしてビルドする。

cd build
.\build-debug.bat

一応デバッグ用の設定として書いてみたつもりだが、うまく機能しているかはよくわからない。一応、CMakeLists.txtに記載のCMAKE_C_FLAGS_DEBUGの内容がキモになっているはずだ。
しかし、曲がりなりにもプログラマを10年以上してきた私でも、ちょっと触ってみるのにこの程度の理解しかできていないのである。プログラマ初心者にとってはまず理解できる代物ではあるまい。会社で新人に任せると間違いを量産すると思われるので、手厚いサポートは必須だろう。
D言語のdubはその点 -b=debug をコマンドラインに付け足すだけでデバッグ用に、 -b=release を付けるだけでリリース用にビルドできる。D言語を選べば間違いない。

VisualStudioCodeのインストール

すでにVisualStudioはインストールしているが、VisualStudioCodeはVisualStudioの皮をかぶった別製品なので別途インストールが必要である。
公式ページから、User Installerというのをダウンロードすると管理者権限不要でインストールが可能だ。管理者権限は不要だが、公式で「インストール」と書いている以上、会社にはインストール申請を出さなければならない。ルールは大切だ。User Installerの何がいいかっていうと、アップデートに管理者権限が必要ない点だ。一度インストールしてしまえば、管理者権限不要で、容易に最新の状態に追従することができる。

同僚はVisualStudioCodeがJSONで設定するってところがつらすぎるって言ってEclipse使ってるけど、はっきり言ってEclipseのほうが1万倍くらい設定が難しいと思う。あとJava使ってるあたりに虫唾が走る(個人の感想です)。サードパーティーコンパイラのIDEはEclipseベースをやめてVisualStudioCodeベースにするべきだと思う。あと最近はGUIによる設定画面が使えるようになった。とはいえtasks.jsonとかlaunch.jsonとかは手書きする必要があるので、やっぱりまだとっつきにくいと思う。

さて、インストールしたらVSCodeを起動するわけだが、ここで一工夫。
ここまで何箇所か環境が汚れるのを嫌って正規のインストールを避け、clang++やVisualStudioといったきちんとしたパスを通していない箇所がある。この場合、VSCodeの起動にはこれらのパスを通した状態で起動するように、起動用のバッチを仕込んでおくのがいい。

vscode.bat
where ml64.exe >nul 2>&1
if errorlevel 1 call "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64
PATH=%LOCALAPPDATA%\Programs\Microsoft VS Code;C:\app\llvm\bin;C:\app\cmake\bin;%PATH%
cd %LOCALAPPDATA%\Programs\Microsoft VS Code
start Code.exe

このバッチからVSCodeを起動することで、各種ツールへの適切なPATHを通すことができるようになる。

入れておいた方がいいVSCode拡張機能

とりあえずコーディング・ビルド・デバッグするだけならばこれで十分だ。
日本語化?軟弱なもんインストールしてんじゃねぇ!なんて言わないので、その辺はお好みでインストールするといいだろう。

なお、D言語のために入れるべき拡張機能は以下の2つのうち、好みでどちらか片方を選べるようになっている。

code-dのほうは、公式で募金を募って開発した実績がある。
さらに、Native Debugを導入することでD言語でビルドしたバイナリをデバッグできるようになる。

VSCodeでビルド

VisualStudioCodeでビルドするためには、tasks.jsonを記述する必要がある。とはいえ、すでにバッチを作ってビルドできるようにしてあるので、それを呼び出すだけでよい。

path_to_project/.vscode/tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build-debug",
            "command": "cmd.exe",
            "args": ["/C", ".\\build-debug.bat"],
            "type": "process",
            "options": {"cwd": "${workspaceRoot}/build"},
            "problemMatcher": {
                "base": "$gcc",
                "fileLocation": ["relative", "${workspaceRoot}/build"]
            }
        }
    ]
}

VSCodeでデバッグ

VSCodeでデバッグするには、launch.jsonを記載する必要がある。preLaunchTaskとして、先のtasks.json記載のbuild-debugを指定してやれば、デバッグ前にビルドが走る。

path_to_project/.vscode/launch.json
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "build-debug",
            "type": "cppvsdbg",
            "preLaunchTask": "build-debug",
            "request": "launch",
            "program": "${workspaceRoot}\\build\\test.exe",
            "cwd": "${workspaceRoot}"
        }
    ]
}

あとは、F5を押すなり、デバッグ開始ボタンを押すなりすればビルド~デバッグが開始される。

動画

動画

まとめ

ここまで読んだあなた何をすればいいかもうわかっていることだろう。
そう、今すぐD言語をインストールするんだ。

理解度チェック

紙とペンを用意し、次の設問Q1~10に回答せよ。

  • Q1. D言語のインストールのことを「〇〇〇〇の行動」という
    1. 人類進化
    2. 文明開化
    3. 人生最良
    4. 天地開闢
  • Q2. D言語のコンパイルにはVisualStudioのインストールが必要
    1. ×
  • Q3. VisualStudioのインストールにくじけそうになっても、D言語を使用することで心の平穏を取り戻すことができる
    1. ×
  • Q4. D言語のビルドツールは
    1. dab
    2. dib
    3. dub
    4. deb
    5. dob
  • Q5. D言語の情報が少ないのは
    1. 言語自体が優秀であり、追加で記事にする必要性が薄いためである
    2. ただユーザーが少ないから、に尽きる
    3. あまりに危険な情報であるため、政府に検閲を受けているからである
    4. G〇の対抗馬として危険視され、G〇〇gleに抹消されているからである
  • Q6. D言語で検索するときのコツで間違っているものは?
    1. "D言語"とダブルクォーテーションで囲う
    2. dlangのキーワードで検索する
    3. 「d」で検索すれば当たり前のように出る
  • Q7. D言語の複素数型は公式的に非推奨とされている
    1. ×
  • Q8. D言語のビルドツールで、コンパイラを切り替える際に指定するべき引数は
    1. -c=ldc2
    2. -compiler=ldc2
    3. --compiler=ldc2
  • Q9. D言語のビルドツールで、デバッグ用のビルド設定を行いたい時に指定するべき引数は
    1. -a=debug
    2. -b=debug
    3. -c=debug
  • Q10. D言語のVSCode拡張機能で、募金を募って開発されたのは
    1. DSL
    2. code-d
    3. D Language
    4. Native Debug

答え
  • Q1. D言語のインストールのことを「〇〇〇〇の行動」という

A: 3. 人生最良

  • Q2. D言語のコンパイルにはVisualStudioのインストールが必要

A: 2. ×

  • Q3. VisualStudioのインストールにくじけそうになっても、D言語を使用することで心の平穏を取り戻すことができる

A: 1. 〇

  • Q4. D言語のビルドツールは

A: 3. dub

  • Q5. D言語の情報が少ないのは

A: 1. 言語自体が優秀であり、追加で記事にする必要性が薄いためである

  • Q6. D言語で検索するときのコツで間違っているものは?

A: 3. 「d」で検索すれば当たり前のように出る

  • Q7. D言語の複素数型は公式的に非推奨とされている

A: 1. 〇

  • Q8. D言語のビルドツールで、コンパイラを切り替える際に指定するべき引数は

A: 3. --compiler=ldc2

  • Q9. D言語のビルドツールで、デバッグ用のビルド設定を行いたい時に指定するべき引数は

A 2. -b=debug

  • Q10. D言語のVSCode拡張機能で、募金を募って開発されたのは

A: 2. code-d

全問正解できましたか?
※本回答は記事中の記載(個人の感想です)をもとに作成されており、事実を確実に保証するものではありません。

最後に

まあ、なんというか、真面目な記事を期待してこのページを開いてしまった人には、、正直、その、すまんかった。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした