はじめに
やると快適になるけれど、何かと面倒な環境構築。
私は環境構築への苦手意識が強くあったのですが、3回くらいやって少しは慣れた気がするので今のうちにメモをしておきます。
もし記事内容に明らかな誤りがあれば、コメント等でご指摘いただけると幸いです。
当記事では以下の内容を扱います。
- C++201の導入
- AtCoder Libraryの導入
-
<bits/stdc++.h>
ヘッダのプリコンパイル - コンパイルと実行のコマンド(ShellScript)
Linuxについての知識が一切ない人でも大丈夫だと思います。
なお、想定環境としてはWindows11+WSL2でVSCodeを利用する形ですが、Windows10でも概ね同様だと思います。
LinuxユーザでもWSL関連以外の内容は共通しています。MacOSはわかりかねます…
最終的にはこのようなディレクトリ2構成になります。
ac-library
ディレクトリを作業ディレクトリ下に置くかはお好みで分かれると思いますが、今回の記事では外に置きます。
私の環境ではac-library
ディレクトリを作業ディレクトリ直下に置いていないと動作しないことを確認したので、作業ディレクトリ直下に置く方針へ記事を修正しました。[2024/07/01 追記]
また、main.cpp
以外のcppファイルも同様に使用できます。a.cpp
など。
competitive/
├ ac-library/
│ ├ atcoder/
│ └ expandar.py
├ .vscode/
│ ├ c_cpp_properties.json
│ └ settings.json
├ sh/
│ ├ build.sh
│ └ io.sh
├ a.out
├ in.txt
├ main.cpp
└ out.txt
目次
- VSCodeの導入
- WSLの導入 (Windowsユーザのみ)
- C++の導入、バージョン設定
- VSCode側の設定
- AtCoder Libraryの導入
- <bits/stdc++.h>ヘッダのプリコンパイル
- 実行用ShellScriptの作成
- おわり
VSCodeの導入
VSCodeを使用するので、まずはVSCodeをインストールしておきましょう。
こちらのリンク先ページに飛び、現在使用しているOSに合わせてダウンロードボタンを押下します。
想定読者となるWindowsユーザの方は「Windows」でよいです。
WSLの導入 (Windowsユーザのみ)
WSL (Windows Subsystem for Linux)を利用して、実行環境をLinux上に移します。
一見回りくどいようですが、Windows上でやるよりも色々と都合がよいためです。
なお、Windows以外のユーザはこの項を飛ばして構いません。
これらの記事を参考に進めればよいと思います(特に二つ目の記事)。
具体的には、以下の手順を行えばよいです。
Windows PowerShellかコマンドプロンプトを「管理者として実行」で開いて、以下のコマンドを実行します。
wsl --install
その後PCを再起動します。
Linux側のターミナル (既定ではUbuntu) を開き、こちらでLinux側のユーザー名とパスワードを設定します。
Linux側のユーザ名とパスワードは半角英数字のみを用いるほうがよいです。
入力中のパスワードは一切表示されない仕様なので、正確に入力してください。
パスワードは必ず忘れないでください。
ただし、バージョンが古いWindows10を利用している人は、こちらの記事に沿って進める必要があります(バージョン等の詳細は一つ目の記事を参照のこと)。
C++の導入、バージョン設定
ここからは、コマンドの実行はすべてLinux側のターミナルで行います。
既定のターミナルはUbuntuです。
こちらの記事の「C言語のコンパイラを導入する」の項に沿って進めればよいです。
具体的には以下の手順でコマンドを実行します。
sudo apt update
sudo apt upgrade
sudo apt install build-essential
これでC++自体は実行できるようになりましたが、バージョン関係の設定も必要です。
こちらの記事の手順に沿って、gcc及びg++の別バージョンをインストールし、update-alternatives
コマンドの設定もしておきましょう。
これによりC++20環境を利用できます。
具体的には以下の手順を実行します。
12の部分は適宜最新のバージョンの数値に置き換えてください(詳しくは後述)。
sudo apt install gcc-12
sudo apt install g++-12
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-12 12
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-12 12
AtCoderでは各コンテストページの下部に「ルール」と書かれたリンクが貼られており(例: ARC178 - ルール)、このページの「言語」の項から実行環境を確認することができます。
最新の実行環境に合わせて上記の設定をしてください。
VSCode側の設定
VSCode側の設定も進めていきます。
まずはWSLをVSCodeと接続します。
WSLとの接続
以下のコマンドを実行します。
実行後はLinuxのターミナルを一旦終了しておきましょう。
sudo apt-get update
sudo apt-get install wget ca-certificates
次に、VSCodeを起動して「WSL」拡張機能をインストールします。
一度VSCodeを終了します。
Linuxのターミナルを起動し、以下を実行して競プロ用のディレクトリを作成します。
mkdir competitive
code competitive
作業ディレクトリcompetitive
を作成し、VSCodeで開きました。
competitive
の部分は好きな名前でよいですが、以下ではcometitive
と仮定します。
VSCodeの左下にWSL: Ubuntu
などと表示されていたらWSLとの接続は完了です。
C++の設定
VSCode上でC++を快適に書くための設定をしていきます。
「C/C++」「C/C++ Extension Pack」拡張機能をインストールします。
インストールしたらVSCodeを再起動してください。
Ctrl+Shift+P
でコマンドパレットを開き、「C/C++: Edit Configurations (JSON)」を押下します。
.vscode
ディレクトリが作業ディレクトリ下に作成され、その中にc_cpp_properties.json
が作成されます。
c_cpp_properties.json
に以下の内容を記述します。
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"~/competitive/ac-library"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
"cppStandard": "gnu++20",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
初期状態とのDiff
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
+ "~/competitive/ac-library"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "c17",
- "cppStandard": "gnu++14",
+ "cppStandard": "gnu++20",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}
includePath
の"~/competitive/ac-library"
に赤波線が引かれていると思いますが、これは一旦無視して先に進みます。
ついでに、画面左上のFile
>Preferences
>Settings
でVSCode全般の設定ができることを知っておきましょう。
設定に関しては人それぞれなので、使いながら適宜設定していけばよいです。基本的にWorkspace
の設定をいじるほうが良いと思います3。
なお、今回の記事の構成に合わせる場合、Files: Auto Save
はonFocusChange
にしておくことを推奨します。
AtCoder Libraryの導入
AtCoder Libraryという便利なAtCoder公式ライブラリ集があります。
せっかく環境構築をするからにはこれも導入しておきましょう。
AtCoder Libraryを知らないという人は以下のリンク先の記事を参考にしてください。
ドキュメント: https://atcoder.github.io/ac-library/production/document_ja/
紹介いろいろ: https://atcoder.jp/posts/517
AtCoder Libraryの保存場所はLinux > Ubuntu > home > [ユーザ名] > [作業ディレクトリ] > [AtCoder Libraryを入れるディレクトリ]
です4。
以下では、[AtCoder Libraryを入れるディレクトリ]のディレクトリ名をac-library
にしたと仮定して話を進めます。
予めac-library
ディレクトリを作成しておきます。
cd ~/competitive
mkdir ac-library
さて、AtCoder Libraryをダウンロードします。
こちらのGitHubから、画面中央-右上あたりの「Code」>「Download ZIP」を押下します。
ダウンロードしたzipファイルを展開し、Linux側に移します。
WSLであれば、Windows標準の「エクスプローラー」からLinux環境のファイルにも干渉できるので、普通にコピペなりドラッグアンドドロップなりをするとよいです。
なお、展開したフォルダ(ac-library-master
)内にはそこそこの数のファイルとフォルダが入っていたと思いますが、ac-library
ディレクトリに移しておくべきなのはatcoder
とexpander.py
くらいだと思います。
あとはc_cpp_properties.json
のincludePath
にac-libraryのパスを渡して、IntelliSenseに認識させておきます(この工程は既にやっています)。
includePath
がこのようになっていればよいです。
"includePath": [
"${workspaceFolder}/**",
"~/competitive/ac-library"
]
これでAtCoder Libraryの導入は完了です。
<bits/stdc++.h>ヘッダのプリコンパイル
参考:5
記事執筆時点とは使用すべきg++等のバージョンが変わっている可能性もあります。
ここで紹介する手順は適宜最新のバージョンに読み替えながら行ってください。
ヘッダファイルのプリコンパイルをしておくと、コンパイルに要する時間を短縮することができます。
何回もコンパイルすることを考えると、一回あたりのコンパイル時間はできる限り短縮しておきたいところです。
ここでは<bits/stdc++.h>
ヘッダをプリコンパイルします6。
まずディレクトリを移行します。
cd /usr/include/x86_64-linux-gnu/c++/12/bits
そして普段使うコンパイルオプションに合わせて以下のコマンドを実行、プリコンパイルヘッダを生成します。
sudo g++ [オプション] stdc++.h
当記事では以下のコマンドを実行します。
sudo g++ -std=gnu++20 -O2 -Wall -Wextra stdc++.h
こうすることで.gch
ファイルが生成されているはずです。
ls
を実行してstdc++.gch
が表示されているか確認しましょう。
これでプリコンパイルは完了です。
.gch
生成時と同じコンパイルオプションでコンパイルした場合、プリコンパイルヘッダが使用されて速くコンパイルされます。
(<atcoder/all>
もプリコンパイルできたらいいんですが、たしかプリコンパイルヘッダは一つしか使えなかった…はずです。要出典。
まぁローカル環境ではヘッダファイルをまとめたものをプリコンパイルして使用、外部環境では個別に展開する…とか頑張ればいけると思うんですが、難しそうなので逃げています。
毎回ACLを使うことはないと思うので、ACL関連は適宜includeする形式をとっています。)
実行用ShellScriptの作成
ここまで進めた時点で、すでにC++環境は完成しています。
ですが、これから毎回コンパイルをするたびに
g++ -std=gnu++20 -O2 -Wall -Wextra main.cpp
とは打ちたくない気持ちになります。
ここで、ショートカットのようなものを定義して楽をします。
ShellScriptという形式の(.sh
)ファイルを作成していきます。
まず.sh
ファイルをまとめるsh
ディレクトリをcompetitive
下に作成します。(任意)
cd ~/competitive
mkdir sh
cd sh
コンパイルをするためのShellScript build.sh
を作成します。
code build.sh
build.sh
に以下の内容を記述します。
#!/bin/bash
cd ~/competitive/
# ソースファイルの決定
SOURCE_FILE="${1:-main.cpp}" # 引数が無い場合はmain.cppを使用
# "atcoder"の出現回数をカウント
ATCODER_COUNT=$(grep -o "atcoder" "$SOURCE_FILE" | wc -l)
# コンパイルオプションの決定
CXX_FLAGS="-std=gnu++20 -O2 -Wall -Wextra"
if [ "$ATCODER_COUNT" -ge 2 ]; then
CXX_FLAGS+=" -I./ac-library"
fi
# コンパイル実行
g++ $CXX_FLAGS "$SOURCE_FILE"
以下の機能を実現しています。
- 任意の
.cpp
ファイルをコンパイルする (初期値はmain.cpp
) - ソースファイル内に"atcoder"が2つ以上含まれているならAtCoder Libraryに対応したコンパイルオプションへ変更する
保存したら、
chmod +x ./build.sh
で実行権限を与えておきましょう。すると (カレントディレクトリが./competitiveとして)
./sh/build.sh
で実行でき、main.cpp
をコンパイルした実行ファイルa.out
を生成してくれるはずです。
./sh/build.sh # main.cppをコンパイル
./sh/build.sh a # a.cppをコンパイル
a.out
は
./a.out
で実行できますが、毎回これを打って入力を与えて、とするのはやや面倒です。
なので、io.sh
で楽にできるようにします。
code io.sh
chmod +x io.sh
io.sh
の中身は以下の通りにします。
#!/bin/bash
cd ~/competitive/
if [ $# -eq 0 ]; then
./a.out < in.txt > out.txt
elif [ "$1" == "term" ]; then
./a.out < in.txt
else
./a.out < in.txt > "$1.txt"
fi
io.sh
は、in.txt
の内容を標準入力として受け取ってa.out
を実行し、標準出力をout.txt
に書き込みます(ファイル入出力)。
また、引数としてファイル名を渡せば標準出力を[ファイル名].txtに書き込みます。
term
を引数にすると標準出力をターミナルに書き込みます(標準出力)。
./sh/io.sh # out.txtに書き込み
./sh/io.sh memo # memo.txtに書き込み
./sh/io.sh term # ターミナルに出力
in.txt
とout.txt
を作成します。
code in.txt
code out.txt
in.txt
とout.txt
は常に表示しているほうが便利なので、レイアウトを変えます。
View > Editor Layout > Two Rows Right
を押下し、in.txt
を右上のウィンドウに、out.txt
を右下のウィンドウで開きます。
これで定義完了…なのですが、./build.sh
とか毎回打つのは結局面倒ですね?短縮します。
code ~/.bashrc
~/.bashrc
の一番下に、次の内容を追記します。
alias bd='/home/[ユーザ名]/competitive/sh/build.sh'
alias io='/home/[ユーザ名]/competitive/sh/io.sh'
私の場合は/home/sora/competitive/sh/build.sh
などですね。
alias ooo='xxx'
でooo
をxxx
に置き換えます。
C++の#define
マクロを想像するとよいです。
ちなみに、bd
はbuild
、io
はin/out
からとっています7。
追記したら、以下を実行するかVSCodeを再起動して反映させます(再起動の方がよいかも?)。
source ~/.bashrc
ここまで正常に進んでいれば、
bd
io
でコンパイルと実行ができるはずです。楽ですね。
旧版のsh/
拙著のshファイルを一応残しておきます。
汚い見た目で、絶対これもっとうまく書けるんだろうとは思っていたんですが、ChatGPTに投げたら見事に綺麗になって帰ってきました。そんな…
#! /bin/bash
cd ~/competitive/
if [ $# != 1 ]; then
count_atcoder=$(grep -c "atcoder" main.cpp)
if [ ${count_atcoder} -gt 1 ]; then
g++ -std=gnu++20 -O2 -Wall -Wextra -I./ac-library/ main.cpp
else
g++ -std=gnu++20 -O2 -Wall -Wextra main.cpp
fi
exit 0
fi
FILE=$1
count_atcoder=$(grep -c "atcoder" ${FILE}.cpp)
if [ ${count_atcoder} -gt 1 ]; then
g++ -std=gnu++20 -O2 -Wall -Wextra -I./ac-library ${FILE}.cpp
else
g++ -std=gnu++20 -O2 -Wall -Wextra ${FILE}.cpp
fi
#! /bin/bash
cd ~/competitive/
if [ $# == 0 ]; then
./a.out < in.txt > out.txt
exit 0
fi
if [ $1 == "terminal" ]; then
./a.out < in.txt
exit 0
fi
./a.out < in.txt > $1.txt
おわり
これで当記事での環境構築は完了です。おつかれさまでした。
私はまだ導入していませんが、online-judge-tools
やatcoder-cli
など便利なコマンドラインツールもあるので、もっと利便性を高めたい人は調べてみると良いと思います。
昔wsl --install
が使えない環境で初めてやったときは本当に大変で二度と触りたくないと思った記憶があるんですが、今回は結構楽でした。
この記事で次回以降はもっと楽になるとうれしいです。
これはただの余談なのですが、なんか現時点「競プロ 環境構築」でGoogle検索すると一番上にこの記事が出てくるらしいですね。「atcoder 環境構築」でも3番目に出てきています。
多分私が一番驚いてる。これそんなに上げてもらっていいのか?(困惑)
私用のメモ程度に書いた記事のつもりでしたが、ご愛読いただきありがたい限りです。
-
当記事執筆時点での、AtCoderで使用できるC++の最新バージョン (C++23も選択できますが、AtCoderの環境だと実質20なので…) ↩
-
「ディレクトリ」はWindows等の「フォルダ」に相当する概念です ↩
-
というか優先度の都合などがあるのか、他の設定は反映されない? よくわかっていません… ↩
-
「はじめに」の項で触れたとおり、別に作業ディレクトリ直下に置いても構いません。どっちのほうがいいのかは私にはわかりかねます。作業ディレクトリ直下に置きましょう ↩ -
サムネかわいいですね ↩
-
<bits/stdc++.h>は元来プリコンパイルすることを前提に作られていたはずです ↩
-
b
とかi
とか、一文字にしたほうが早くなりますが、なんか一文字にまで踏み込む勇気は出ませんでした(?) ↩