別記事で Windows に Clang++ を導入できたので, Sublime Text 3 から使えるといいなと思ったところ, PackageResourceViewer で開いたデフォルトの C++/C++ Single File.sublime-build
を参考にすることで, Clang++14 でビルドして PowerShell 上で実行するビルドシステムを Sublime Text 3 に追加できたよ,という話.
ついでに Terminality の設定をした話も.
別記事でなんとか Windows に Clang++ 3.9.1 を導入できたので,これを Sublime Text 3 から使った.
まず Sublime Text 3 には g++ を使ってビルドする設定がデフォルトで入っているので,それを参考にした. PackageResourceViewer を使うことで,パッケージ化されている C++.sublime-package
の中身を覗ける. Package Control を利用してインストールしたのち, Ctrl+Shift+P
で PackageResourceViewer: Open Resource
を実行して C++
の中の C++ Single File.sublime-build
を開くと
{
"shell_cmd": "g++ \"${file}\" -o \"${file_path}/${file_base_name}\"",
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"working_dir": "${file_path}",
"selector": "source.c, source.c++",
"variants":
[
{
"name": "Run",
"shell_cmd": "g++ \"${file}\" -o \"${file_path}/${file_base_name}\" && \"${file_path}/${file_base_name}\""
}
]
}
を得た.これをコピーした.
Tools > Build System > New Build System...
を開いて C++14.sublime-build
の名前で保存し,さっきのをペーストした. shell_cmd
の値をClang++を実行するように編集し,C++14を有効化する -std=c++14
と,最適化レベル2にする -O2
をつけた.
ちなみに clang-cl (Visual C++互換版)を使う場合にはエラーメッセージの形式が異なるっぽいので, file_regex
の値を(clangとclang-clのエラーメッセージを見比べながら)適切な正規表現に変えれば,該当ファイル上にエラー箇所を表示してくれる機能が壊れずに済みそう.キャプチャリング括弧の1つ目がファイルパス,2つ目が行数,3つ目が文字数,4つ目がエラーの概要に対応するものと思われる(未検証).clangならg++と同じ形式なのでそのままでよかった.
これであとは Tools > Build With...
で作ったやつを選べばうまくビルドされた.(なおSTを開きっぱでClangをインストールした場合は当然ながら環境変数の読み直しのためにSTの再起動が必要.頭が悪いのではまった.)
ただし,このままだとclangのエラーメッセージ色付けの恩恵を受けられないのと,実行時に標準入力を与えたい場合に困るのとがあったので,PowerShellを開く設定も足した. start powershell -Command "hogehoge"
(終了時に閉じない場合は start powershell /noexit -Command "hogehoge"
)とすればPowerShellを開いてhogehogeを実行できるから,hogehogeにclangのコマンドを入れればよい.
また, Windows PowerShell Tip: Press Any Key to Continue によれば,cmdにおける pause
に相当する挙動は Write-Host "Press any key to continue ..."; $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
とすれば得られるのでこれも使った.あとどの時点でBuildからRunに移って標準入力待ち受け状態に入るか分かりづらかったので,Buildが終わった段階でメッセージを出力するようにした.
できあがった C++14.sublime-build
は以下.
{
"shell_cmd": "clang++ -O2 -std=c++14 \"${file}\" -o \"${file_path}/${file_base_name}\" -I \"C:/Program Files (x86)/Windows Kits/10/Include/10.0.14393.0/ucrt\" -L \"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/ucrt/x64\" -L \"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/um/x64\"",
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"working_dir": "${file_path}",
"selector": "source.c, source.c++",
"variants":
[
{
"name": "Build with Terminal",
"shell_cmd": "start powershell -Command \"clang++ -O2 -std=c++14 \\\"${file}\\\" -o \\\"${file_path}/${file_base_name}\\\" -I \\\"C:/Program Files (x86)/Windows Kits/10/Include/10.0.14393.0/ucrt\\\" -L \\\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/ucrt/x64\\\" -L \\\"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/um/x64\\\"; Write-Host \\\"Press any key to continue ...\\\"; \\$x = \\$host.UI.RawUI.ReadKey(\\\"NoEcho,IncludeKeyDown\\\")\""
},
{
"name": "Run",
"shell_cmd": "clang++ -O2 -std=c++14 \"${file}\" -o \"${file_path}/${file_base_name}\" -I \"C:/Program Files (x86)/Windows Kits/10/Include/10.0.14393.0/ucrt\" -L \"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/ucrt/x64\" -L \"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/um/x64\" && \"${file_path}/${file_base_name}\"; pause"
},
{
"name": "Run with Terminal",
"shell_cmd": "clang++ -O2 -std=c++14 \"${file}\" -o \"${file_path}/${file_base_name}\" -I \"C:/Program Files (x86)/Windows Kits/10/Include/10.0.14393.0/ucrt\" -L \"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/ucrt/x64\" -L \"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/um/x64\" && start powershell -Command \"Write-Output \\\"Run\\\"; Write-Output \\\"---\\\"; ${file_path}/${file_base_name}; Write-Host \\\"Press any key to continue ...\\\"; \\$x = \\$host.UI.RawUI.ReadKey(\\\"NoEcho,IncludeKeyDown\\\")\""
}
]
}
PowerShellに与えるコマンドの中のクォートは2度のエスケープを耐え抜く必要があるのでエスケープシーケンス盛り盛りと化した.
おまけ:TerminalityでClang++14ビルド&ラン
Terminality を使うと Sublime Text のタブとしてターミナルっぽいものを用意してくれてとても手軽なのでこれもClang++14版をこしらえた.
Terminality もデフォルトでg++を使うものがついているので, PackageResourceViewer で Terminality > Collections > C++.terminality-collections
を開いた:
{
"execution_units": {
"source.c++": {
"run": {
"name": "Run $file_name",
"description": "Compile and Run $file_name with default C++ compiler",
"required": ["file"],
"command": "g++ $file -o $file_without_ext && $file_without_ext $arguments",
"macros": {
"file_without_ext": [
["$file", ".*(?=\\.)"]
]
}
}
}
}
}
これを C++14.terminality-collections
として SublimeText3\Data\Packages\User
以下に別名保存した.
この設定ファイルにはmacrosという概念があるせいかクォーテーションが正常に効かないので,空白を含むインクルードパスは文字列を返すだけのマクロとして外に出したり,末尾に空白が残るなどの細かい点は無視したり,BuildとRunの境目をわかりやすくするための echo
を足したり,ビルドしないで単に実行するコマンドも足したりして,以下の C++14.terminality-collections
を得た:
{
"execution_units": {
"source.c++": {
"run_c++14": {
"order": "0",
"name": "Run $file_name with Clang++14",
"description": "Compile and Run $file_name with Clang++14 compiler",
"required": ["file"],
"command": "clang++ -O2 -std=c++14 $file -o $file_without_ext -I $inc1 -L $inc2 -L $inc3 && echo $file_without_ext && $file_without_ext $arguments",
"macros": {
"file_without_ext": [
["$file", ".*(?=\\.)"]
],
"inc1": ["C:/Program Files (x86)/Windows Kits/10/Include/10.0.14393.0/ucrt"], // avoid space handling problem
"inc2": ["C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/ucrt/x64"],
"inc3": ["C:/Program Files (x86)/Windows Kits/10/Lib/10.0.14393.0/um/x64"]
}
},
"run_without_build": {
"order": "1",
"name": "Run $file_name (No build)",
"description": "Run $file_name without build",
"required": ["file"],
"command": "$file_without_ext $arguments",
"macros": {
"file_without_ext": [
["$file", ".*(?=\\.)"]
]
}
}
}
}
}
これで,C++ファイル上で Ctrl+Alt+R
すれば作ったものを選べてTerminal風タブを開けた.なお, order
をセットするとコマンド選択肢のソーティングのための読み仮名みたいなものになるっぽかったので雑に使って1番目と2番目になるようにした.快適さを感じる.
ちなみに $file_without_ext はコマンド選択肢表示時にはまだセットされないようだったので name や description 内に使うのを諦めた.