2026-01-02

ホストマシン依存の AtCoder 環境 を dev container に寄せた

細々とやっていた AtCoder ですが、去年とりあえずの目標にしていた入緑を果たして以降ほとんど Rated には参加していない状態です。

緑だ!

michimaniさんのAtCoder Beginner Contest 416での成績:2497位 パフォーマンス:1121相当 レーティング:767→808 (+41) :) Highestを更新し、6 級になりました! #AtCoder #ABC416

— michimani (@bsky.michimani.net) 2025年7月27日 7:03

今年もまた細々とやっていくために、タイトルの通り手元の環境を整備しました。

これまではローカルの macOS 環境に依存していた設定になっていたんですが、諸々 dev containers で完結する C++23 (Clang 21.1.0) 環境に移行したのでその記録です。とはいえ AtCoder の環境 (コンパイル・インタプリタ) を完全再現したわけではなく、ホストの設定は最小限にとどめてコンテナ内で実装から提出までをとりあえず完結させることを目指しました。

https://github.com/michimani/atcoder

どう作ったか

ベースイメージには mcr.microsoft.com/devcontainers/base:bookworm を選び、apt.llvm.org から Clang 21.1.0 と libc++、lld を導入しました。update-alternatives/usr/bin/clang(++) を 21 系に向け、online-judge-tools (oj)--break-system-packages 付きで pip インストールしています。これは、 Debian/Bookworm が PEP 668 で「システム管理の Python 環境」を強制しているため、そのまま pip install online-judge-tools を実行すると “externally-managed-environment” エラーで止まります。コンテナ内では専用の venv を作らずにすぐ使えるようにしたかったので、システム Python に直接入れるための回避策として —break-system-packages を付けてインストールしています。

ライブラリは Boost/Eigen/abseil/protobuf/re2/gmp など、手元でビルドが通る現実的な最小セットにとどめました。AtCoder 本番の全ライブラリを完全再現するのではなく、リンクエラーを避けつつ軽めのフラグで回る構成を優先しています。ツールとして GNU time も同梱し、oj の警告を抑制しています。

主な差分

dev container 構築

.devcontainer/Dockerfile の抜粋:

RUN set -e; \
    curl -fsSL https://apt.llvm.org/llvm-snapshot.gpg.key | gpg --dearmor -o /usr/share/keyrings/llvm-snapshot.gpg; \
    echo "deb [signed-by=/usr/share/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/bookworm/ llvm-toolchain-bookworm-21 main" > /etc/apt/sources.list.d/llvm-toolchain.list; \
    curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg; \
    echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" > /etc/apt/sources.list.d/github-cli.list

...

RUN apt-get install -y --no-install-recommends \
    clang-21 clang-format-21 clang-tidy-21 lld-21 lldb-21 libc++-21-dev libc++abi-21-dev \
    libboost-all-dev libabsl-dev libprotobuf-dev libre2-dev libgmp-dev libbz2-dev libglpk-dev \
    coinor-libcbc-dev coinor-libclp-dev coinor-libcgl-dev coinor-libcoinutils-dev coinor-libosi-dev \
    libeigen3-dev cmake ninja-build pkg-config gdb time python3 python3-pip gh \
    || true

VS Code 設定

.vscode/c_cpp_properties.json にコンテナ用設定を記述。

{
  "configurations": [
    {
      "name": "devcontainer-clang-21",
      "compilerPath": "/usr/bin/clang-21",
      "cppStandard": "c++23",
      "intelliSenseMode": "linux-clang-arm64"
    }
  ],
  "version": 4
}

タスクとビルドスクリプト

ビルドおよび実行は .vscode/tasks.json で管理しています。その中のtest_atcoder_sample はビルドおよび対象の問題に対して oj test を実行するもので、その実態は onlinejudge/cpp-test.sh です。

.vscode/tasks.json:

{
  "label": "test_atcoder_sample",
  "command": "${workspaceFolder}/onlinejudge/cpp-test.sh",
  "group": { "kind": "test", "isDefault": true }
}

onlinejudge/cpp-test.sh:

USER_BUILD_FLAGS=(
  "-DATCODER" "-DNOMINMAX" "-DONLINE_JUDGE"
  "-O2" "-Wall" "-Wextra"
  "-fconstexpr-depth=1024" "-fconstexpr-steps=524288"
  "-fexperimental-library" "-flto=auto" "-ftrivial-auto-var-init=zero"
  "-fuse-ld=lld" "-march=native" "-pthread"
  "-std=gnu++23" "-stdlib=libc++" "-Wl,--as-needed"
)

/usr/bin/clang++-21 "${code_path}" -I/usr/include/eigen3 -o ./a.out "${USER_BUILD_FLAGS[@]}"
oj test -c "./a.out " -d "${test_dir}"

onlinejudge/cpp-submit.sh では言語 ID を AtCoder の Clang 21.1.0 に合わせて 6116 に変更。

使い方

これまでと特に変わりはなく、 dev container に入って作業するだけです。

  1. VS Code でリポジトリを開く
  2. 「Dev Containers: Reopen in Container」を実行
  3. new.sh で回答用ファイル作成、実装
  4. コマンドパレットから test_atcoder_sample でサンプルテスト、submit_to_atcoder で提出を実行

参考文献