ABC168の解説動画見ていると、E問題でgcd()を使う問題が出てきました。C++17から追加された機能なので、コンパイル時に-std=c++17を付けないといけません。しかし、MinGW環境のgccではこのオプションが使えません。-std=c++14までしか対応してないっぽいからです。
MinGWでC++17に対応させる方法はあるんでしょうが、検索しても出てこないのと、MinGW環境なんて使わなくてもいいような状況になってきたので、WSL(Windows Subsystem for Linux)とWindows Terminalで環境を作り直そうと思いました。
それに付随して、AtomのLinter-gccがうまく動かなくなったので、エディターもVScodeに乗り換えました。
要するに今回は、
- MinGW→WSL
- cmd→Windows Terminal
- Atom→VScode
をやろうというものです。
目次
1.MinGWをアンイストール
もうお払い箱になったMinGWをアンイストールします。5年間ありがとう。
さてMinGWですが、コントロールパネルからアンイストールできません。まじかよって感じです。そのため、MinGWのフォルダを削除して、pathを消し、スタートからショートカットを消します。レジストリはわからんので放置。
さらば、MinGW。
2.WSLとubuntuをインストール
ようこそ、WSL。気合い入れてインストールしていきましょう。
めんどくさい手順はなく、コントロールパネル→プログラム→Windowsの機能の有効化と無効化→Windows Subsystem for Linuxにチェックを入れてOK。再起動が必要なので再起動。
再起動し終わったら、Microsoft Storeの検索窓に"Ubuntu"と入れて、良さそうなものを入手します。私がこの記事を書いているときは、Ubuntu,Ubuntu18.04LTS,Ubuntu 20.04LTSがでてきました。
どれでも良いと思いますが、私がUbuntu18.04LTSをいれました。
3.ubuntuをセットアップ
初回にWSLを起動すると、ユーザー名とパスワードが求められます。入力して終わり。
ついでに、
$ sudo apt update
$ sudo apt upgrade
しときましょう。
4.Windows Terminalをインストール
こちらもMicrosoft Storeから入手します。検索窓に"windows terminal"と打ち込むと出てくるので入手。
インストールされたら終わり。一度実行してみる。
5.Windows Terminal起動時にUbuntuがデフォルトで開かれるようにする
最初起動時はデフォルトでpowershellが起動します。今回は、ubuntu上のgccを使うことが目的なので、デフォルトでubuntuが開かれると便利です。
Windows Terminalのタブの一番右にある∨でプルダウンメニューを開いて、設定をクリックする、またはCtrl+,を押すとsetting.jsonがメモ帳で開かれます。
デフォルトで開かれるようにするには、defaultProfileを弄る必要があります。
横のハッシュみたいな文字列を弄るわけですが、その部分にguidと呼ばれるIDみたいなものを入れればOKです。
setting.jsonの中にporfilesという項目があるので、その中かから"name":"Ubuntu"となっているところのguidをコピーして、先程のdefaultProfileのguidに上書きします。
一度Windows Terminalを終了させて再び立ち上げた時に、Ubuntuが起動していれば設定完了です。
Windows Terminalですが、このsetting jsonに書き込むと色々とできるみたいです。
WSL と VSCode と Windows Terminal でコマンドプロンプトにさようなら
私がWindows Terminalを入れたときは、デフォルトでショートカットキーにCtrl+C,Ctrl+Vが登録されていました。
cmdで使えなかったCtrl+C,Ctrl+Vが使える、そういうことに幸せを感じるんだ・・・。
6.gccをインストールする
6-1.Linuxbrewのインストール
基本的にコードはMacOS上で書いていて、gccはHomebrewから入れたものを使っています。最新版が簡単に手に入りますし、必要なら昔のバージョンも持ってこれます。
なので、ubuntu上でもHomebrewが使いたい!と思って調べた、Homebrew for Linuxとして公式にサポートされているみたいです。名前はLinuxbrewと言うらしい。
Linuxbrewを入れる前に、ubuntuに必要なものを入れておきます。
$ sudo apt-get install build-essential curl file git
Homebrew本体をインストール。
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
PATHに追加。
$ test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
$ test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
起動時にPATHが自動的に読み込まれるようにする。
$ echo "eval $($(brew --prefix)/bin/brew shellenv)" >>~/.profile
テストとして、helloだったりslだったりinstallしてみて、動いたらインストール完了。
6-2.gccをインストール
$ brew install gcc
何故か勝手にpathが通っているので、gccのバージョン確認。(MacだとPATHに追加して、シンボリックリンク貼らないとダメだったんだけど・・・)
$ gcc -v
そうしたら私がやったときは次のように表示されました。
Reading specs from /home/linuxbrew/.linuxbrew/Cellar/gcc/5.5.0_7/lib/gcc/x86_64-unknown-linux-gnu/5.5.0/specs
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/home/linuxbrew/.linuxbrew/Cellar/gcc/5.5.0_7/libexec/gcc/x86_64-unknown-linux-gnu/5.5.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ../configure --prefix=/home/linuxbrew/.linuxbrew/Cellar/gcc/5.5.0_7 --disable-nls --enable-checking=release --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-5 --with-gmp=/home/linuxbrew/.linuxbrew/opt/gmp --with-mpfr=/home/linuxbrew/.linuxbrew/opt/mpfr --with-mpc=/home/linuxbrew/.linuxbrew/opt/libmpc --with-pkgversion='Homebrew GCC 5.5.0_7' --with-isl=/home/linuxbrew/.linuxbrew/opt/isl@0.18 --with-bugurl=https://github.com/Homebrew/linuxbrew-core/issues --with-boot-ldflags='-static-libstdc++ -static-libgcc ' --disable-multilib
Thread model: posix
gcc version 5.5.0 (Homebrew GCC 5.5.0_7)
ここで「あれ?」と思ったのは、gcc versionが古い。Macの方ではgcc versionは9.2.0。HomebrewとLinuxbrewはfomulaが違うのかなと思いましたが、同じっぽい。変だなと思って、gcc.rbの中身を見たら、次のようになっていました。
linuxbrew-core/Formula/gcc.rd/gcc
if OS.mac?
url "https://ftp.gnu.org/gnu/gcc/gcc-9.3.0/gcc-9.3.0.tar.xz"
mirror "https://ftpmirror.gnu.org/gcc/gcc-9.3.0/gcc-9.3.0.tar.xz"
sha256 "71e197867611f6054aa1119b13a0c0abac12834765fe2d81f35ac57f84f742d1"
head "https://gcc.gnu.org/git/gcc.git"
else
url "https://ftp.gnu.org/gnu/gcc/gcc-5.5.0/gcc-5.5.0.tar.xz"
mirror "https://ftpmirror.gnu.org/gcc/gcc-5.5.0/gcc-5.5.0.tar.xz"
sha256 "530cea139d82fe542b358961130c69cfde8b3d14556370b65823d2f91f0ced87"
end
MacOSだとgcc-9.3.0を、それ以外はgcc-5.5.0を取ってくるようになっています。そして、gcc-5.5.0の最終更新日は2017年10月。入れて-std-c++17オプション付けてコンパイルしましたが、色々吐き出して終わりました。
また、gcc versionの新しいものを指定してもgcc@5しか入りません。
今回の目的は-std=c++17オプションを付けてコンパイルすることなので、これではダメです。アンイストール。
$ brew uninstall gcc
ちなみにMacOSに入ってるgccは普通に-std~c++17オプション付けてコンパイルが通ります。
6-3.(解決策)ubuntuのg++を使う
Linuxbrewで入れたgccを削除すれば、必要なツールを入れた時に入ったgccだけが残ります。
しかし、私の環境ではg++ -vは動くのに、gcc -vはそんなディレクトリは存在しないと怒られます。
ただ、私はC++しか書かないので無視することにしました。
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/7/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none
OFFLOAD_TARGET_DEFAULT=1
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 7.5.0-3ubuntu1~18.04' --with-bugurl=file:///usr/share/doc/gcc-7/README.Bugs --enable-languages=c,ada,c++,go,brig,d,fortran,objc,obj-c++ --prefix=/usr --with-gcc-major-version-only --program-suffix=-7 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --enable-bootstrap --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --with-target-system-zlib --enable-objc-gc=auto --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-offload-targets=nvptx-none --without-cuda-driver --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
これでコンパイラの準備は完了です。
7.VScodeの環境を整える(Atomから引っ越し)
最近Atomをいじってましたが、情報量と情報の新しさはVScodeのほうが多く、いいなあと思ってましたが、linter-gccがうまいこと動かなくなったので乗り換えることにしました。
基本的に【VScode+WSLで始める】競プロ用C++デバッグ環境構築に則って進めています。
7-1.VScodeをインストール
Visual Studio Codeからexeファイルをダウンロードして、インストール。
7-2.ワークスペースの追加
Atomで追加していたプロジェクトフォルダをVScodeのワークスペースに追加。
7-3.WSL上のubuntuにgdbをインストール
先に設定したWindows Terminalからインストールします。
$ sudo apt install gdb
7-4.拡張機能をインストール
VScodeに拡張機能をインストールします。必要なのは、C/C++とC++ Intellisense。
7-5統合ターミナルをWSLに設定
Ctrl+Shift+Pでコマンドパレットを表示、Terminal:Select Default Shellと打つと、選べるshellが出てくるので、WSL Bashを選択。
一度、Ctrl+@などでターミナルを開いて、WSLが起動していればOK。
ここで、ターミナルの文字が変になっている場合があります。その時は、設定→検索窓に"Font Family"と打ち込み、
Terminal > Integrated: Font Familyのフォントを"monospace"にするとまともになります。
エディター、ターミナルどちらもMyricaにしていたのですが、ターミナルだとMyricaはダメっぽそうでした。ただ、monospaceはあんまり好きじゃないので、なんか良いフォント無いかなあ。
7-6.IntelliSenseの設定
コマンドパレットを開いて、c/c++と打つとc/c++構成の編集と出てくるので、それを選択。するとc_cpp_properties.jsonが開きます。それを次のように書き換えます。
{
{
"configurations": [
{
"name": "WSL",
"intelliSenseMode": "gcc-x64",
"compilerPath": "/usr/bin/gcc",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"cStandard": "c11",
"cppStandard": "c++17"
},
"version": 4
}
cppStandardは目的達成のためにc++17を指定。他は特に弄らなくてよい。
7-7.tasks.jsonの設定
コマンドパレットを開いて、Tasksと打つと、"Tasks: Configure Task"とあるので、それを選択。そうすると、tasks.jsonが開きます。
それを次のように上書きします。
{
{
"version": "2.0.0",
"tasks": [
{
"label": "build on windows",
"type": "shell",
"options": {
"shell": {
"executable": "C:\\Windows\\System32\\wsl.exe",
}
},
"command": "g++",
"args": [
"-std=c++17",
"-g",
"-O0",
"-I/opt/boost/gcc/include",
"-L/opt/boost/gcc/lib",
"-o",
"`wslpath",
"'${workspaceFolder}\\problem.exe'`",
"`wslpath",
"'${file}'`",
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
13行目からは、g++につけるオプションなどを一個一個書いています。gcdとかは今後も使うと思うので、-std=c++17にしています。
これで実行環境ができました。
実行手順は、ソースファイルを開いて、Ctrl+Shift+Bでコンパイル、ターミナル上で./problem.exeを実行。
ただ、統合ターミナルをWSLにした時点で、ディレクトリ移動→g++でコンパイル→./a.outを実行でも実行できます。
7-8.(デバッグ環境構築)launch.jsonの設定
先にWSL workspaceFolderをインストールします。pathの変換する時に必要になります。
そして、コマンドパレットでlaunch.jsonと売ってlaunch.jsonを開きます。
その中身を次のように上書きします。
{
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Bash on Windows Launch",
"type": "cppdbg",
"request": "launch",
"program": "${command:extension.vscode-wsl-workspaceFolder}/problem.exe",
"args": [
"${command:extension.vscode-wsl-workspaceFolder}/problem.in"
],
"stopAtEntry": false,
"cwd": "${command:extension.vscode-wsl-workspaceFolder}",
"environment": [],
"externalConsole": true,
"pipeTransport": {
"debuggerPath": "/usr/bin/gdb",
"pipeProgram": "${env:windir}\\system32\\bash.exe",
"pipeArgs": [
"-c"
],
"pipeCwd": "/"
},
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"sourceFileMap": {
"${command:extension.vscode-wsl-workspaceFolder}": "${workspaceFolder}"
},
}
]
}
これでデバッグ環境構築は終わりです。
ルートディレクトリにproblem.inを作って、そこに入力例を入れます。
problem.inという名前が嫌な場合は、launch.jsonの9行目のargsのproblem.inを好きな名前に変えれば、なんでも良いと思います。(試してない)
後はF5を押すとデバッグされます。ブレークポイントを入れていれば、変数の値なども見ることができます。
これ本当にテキストエディタ?IDEじゃなくて?
8.おわり
デバッグ機能使ったときは、なんだこれはとなりました。最近デバッグのために変数をcoutさせてた部分を消し忘れてWA出すことが何度もあったので、これは便利。
全部の環境でVScodeを導入しようと思いましたが、問題発生。
まず、VScodeのワークスペースはOnedriveで共有しています。そうなると、全てのjsonファイルも共有されるので、Mac固有のディレクトリとかの設定が書けない。環境ごとに書けそうなんで、調べながらやっていきます。
もう一つ問題なのは、Macとgdbの相性が悪いらしいこと。デバッグ機能が使えなくなります。こんな便利なのを使えないのは困る。codeLLDBならいいらしいけど。
Macでもやってみて、ダメならwindowsはVScode、MacはAtomでいこうかな。
9.参考文献
Windows10でWSLとVSCodeを使ってC++環境を整える
【Windows10/WSL Ubuntu】gcc, make などの開発ツールをインストールして使う
WSL と VSCode と Windows Terminal でコマンドプロンプトにさようなら
[C++/Mac] C++をVisual Studio Codeで書きたい
Visual Studio Code での C++ の初期設定 (Windows x gcc(MinGW) 編)