MinGWからWSL上のubuntuのgccに乗り換えた

投稿者: | 2020年5月18日

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 (Preview) メモ

私が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と言うらしい。

Homebrew Documentation

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はあんまり好きじゃないので、なんか良いフォント無いかなあ。

VSCodeのターミナル部分のフォント設定

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(Ubuntu 18.04)でHomebrewを使う

WSL と VSCode と Windows Terminal でコマンドプロンプトにさようなら

Windows Terminal (Preview) メモ

[C++/Mac] C++をVisual Studio Codeで書きたい

Variables Reference

VSCodeのターミナル部分のフォント設定

Visual Studio Code での C++ の初期設定 (Windows x gcc(MinGW) 編)

【VScode+WSLで始める】競プロ用C++デバッグ環境構築

WSL (Windows Subsystem for Linux)の基本メモ

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください