🧭
Goの競プロ環境構築【VSCode,devcontainer,acc,oj】
やりたいこと
- 競技プログラミング用の
Go
の環境をdevcontainer
で構築したい - atcoder-cliで問題とテストケースを取得したい
- online-judge-toolsを使ってテストをしたい
記事を書こうと思った理由
-
pip3 install online-judge-tools
がerror: externally-managed-environment
エラーでうまくいかなった - バインドマウントでdevcontainerのフォルダが上書きされて詰まった
- せっかくいろんなサイトで調べて解決できたので
go + devcontainer + acc + oj + venv
の環境構築を流れで残しておきたかった
環境構築
Dockerfileを作成
- 元となるイメージを指定
AtCoderのGo
のバージョンが1.20.6
なのでそれに合わせる
Dockerfile
FROM golang:1.20.6
- カレントディレクトリを変更
Dockerfile
WORKDIR /go/src
- パッケージをインストール
- nodejs
- npm
- python3
- python3-pip
- python3.11-venv
Dockerfile
RUN apt update && apt install -y nodejs npm python3 python3-pip python3.11-venv
- venvのセットアップ
Dockerfile
RUN python3 -m venv venv
- online-judge-toolsのインストール
Dockerfile
RUN . venv/bin/activate && pip3 install online-judge-tools
- venvのpythonを使用するようにパスを通す
Dockerfile
ENV PATH /go/src/venv/bin:$PATH
- atcoder-cliのインストール
Dockerfile
RUN npm install -g atcoder-cli
- toolsをインストール
Dockerfile
RUN go install -v golang.org/x/tools/gopls@latest
- atcoder-cliの設定変更
問題を全てダウンロードする設定
Dockerfile
RUN acc config default-task-choice all
docker-composeを作成
- バージョン指定
docker-compose.yaml
version: '3.9'
- コンテナ名設定
docker-compose.yaml
services:
atcoder:
container_name: atcoder-golang
- 使用するDockerfileを指定
docker-compose.yaml
services:
atcoder:
build:
dockerfile: ./Dockerfile
- コンテナ永続化
docker-compose.yaml
services:
atcoder:
tty: true
- ボリュームマウント
作成されたvenvフォルダがバインドマウントによって上書きされてしまうので、ボリュームマウントとして設定する
docker-compose.yaml
services:
atcoder:
volumes:
- type: volume
source: venv
target: /go/src/venv
volumes:
venv:
- バインドマウント
docker-compose.yaml
services:
atcoder:
volumes:
- type: bind
source: ./src
target: /go/src
devcontainerを起動
-
command + shift + p
でコマンドパレットを開いてDev Containers: ReOpen in Container
を実行
-
.devcontainer/devcontainer.json
が自動で作成されるはずなので書き換える- workspaceFolder: デフォルトで開くルートフォルダを指定
- vscode.settings: devcontainer側のsettings.jsonに追記したい内容
devcontainer.json
{
"name": "atcoder",
"dockerComposeFile": [
"../docker-compose.yaml",
"docker-compose.yml"
],
"service": "atcoder",
"workspaceFolder": "/go/src",
"customizations": {
"vscode": {
"settings": {
"[go]": {
"editor.defaultFormatter": "golang.go",
"editor.formatOnSave": true
}
}
}
}
}
Makefileを作成
- ログイン用コマンド作成
Makefile
acc_login:
acc login
oj_login:
oj login https://atcoder.jp/
login: acc_login oj_login
タスクを作成
-
command + shift + p
でコマンドパレットを開いてTasks: Configure Task
を実行
-
テンプレートから tasks.json を生成
を実行
-
Others
を実行
-
.vscode/tasks.json
が自動で作成されるはずなので編集する- download:
context
で指定したコンテストの問題を取得する
tasks.json{ "tasks": [ { "label": "download", "type": "shell", "command": "bash ${workspaceFolder}/cmd/download.sh" }, ] }
cmd/download.sh#! /bin/bash dir=$(cat ./contest) WORKING_DIR="/go/src" PROBLEM_DIR="${WORKING_DIR}/${dir}" TEMPLATE="${WORKING_DIR}/templates/main.go" cd $WORKING_DIR acc new $dir PROBLEMS="${PROBLEM_DIR}/*" for DIRPATH in $PROBLEMS; do if [ ! -d $DIRPATH ]; then continue fi cp -n $TEMPLATE "${DIRPATH}/main.go" done
- test: 開いている
main.go
をテストする
tasks.json{ "tasks": [ { "label": "test", "type": "shell", "command": "oj t -d ${fileDirname}/tests -c 'go run ${file}'" }, ] }
- submit: 開いている
main.go
をAtCoderに提出する
tasks.json{ "tasks": [ { "label": "submit", "type": "shell", "command": "cd ${fileDirname} && acc submit main.go" }, ] }
- download:
VSCodeの拡張
- アンインストールの横にある歯車から
devcontainer.json に追加
を選択すると.devcontainer/devcontainer.json
に追記されdevcontainer起動時に自動でインストールされる
devcontainer.json
{
...
"customizations": {
"vscode": {
"extensions": [
"golang.go",
"SanaAjani.taskrunnercode"
],
...
}
}
}
初期設定
テンプレートファイルを作成
templates/main.go
package main
func main() {
}
使い方
ログイン
make login
コンテストを指定
contest
abc001
問題とテストケースのダウンロード
- task runnerから
download
コマンドを実行
- ルート直下に問題とテストケースがダウンロードされ、テンプレートファイルがコピーされる
src/
├ abc001
├ a
├ main.go
└ tests
├ b
├ main.go
└ tests
└ c
├ main.go
└ tests
問題を解く
- main.goを編集
テストする
- task runnerから
test
コマンドを実行
提出する
- task runnerから
submit
コマンドを実行
おわりに
Dockerの本を読んで実際に作りたくなったので勉強もかねて環境構築しましたが結構詰まりました。
トライアンドエラーでやってたので不要な記述とかありそうですね。。。
一旦満足したのでちょこちょこコンテストにも参加してみたいなと思います。
Discussion