My C++ workspace for competitive programming
まず、uv 0.11.25 以上をインストールする(インストール済みの uv が古い場合はアップグレードする)。
libraries/ の中身が空であれば、
git submodule update --init --recursiveを実行しておく。
このリポジトリのルートディレクトリで、
git pullと
git submodule update --recursiveを実行する。
次に、もし bits/stdc++.h をプリコンパイルしていなければ
cd /usr/include/x86_64-linux-gnu/c++/11/bits (などの bits/stdc++.h が存在するディレクトリ)
sudo g++ -O3 -std=gnu++23 stdc++.h
cd (このリポジトリのルートディレクトリ)を実行する(適切にディレクトリ名は読み替えること)。
次に、libraries/precompile/precompile.hpp をプリコンパイルしていない場合と、このリポジトリが ac-library の更新を反映した場合(および、libraries/precompile/precompile.hpp 自体が変更された場合)は
cd libraries/precompile
sudo g++ -O3 -std=gnu++23 -I ../ac-library ./precompile.hpp
cd ../..を実行する。
そして、
./scripts/install-workspace.py (問題を解くワークスペースのルートディレクトリのパス)を実行する。 既に存在するディレクトリもまだ存在していないディレクトリも指定できる。
なお、問題を解くワークスペースとしてこのリポジトリやその他 Git リポジトリの内部は指定できないようになっていることに注意。
Note
必須ではないオプションとして --no-backup または --backup がある。
これは .python-version、prepare.config.toml、template が既に存在する場合にそれらをバックアップするかを指定するオプションである。
Note
インストーラは CPython 3.11 の仮想環境を uv のキャッシュ内に同期する。
環境本体は uv のキャッシュに保存され、.venv は通常、現在選択されている環境へのリンクになる。
同じ Python インタープリタ用の環境がキャッシュ内に既にある場合、そこへ手動で追加したパッケージは --inexact により保持される。
別実装や別バージョンの Python 環境は別々にキャッシュされるため、切り替え直したときに再利用できる。
ただし、centralized-project-envs を使わずに実ディレクトリとして作成された .venv から初めてキャッシュ内の環境へ移行する場合、その .venv に手動で追加していたパッケージは引き継がれない。
なお、インストール後に uv sync --no-dev --python pypy3.11 を実行することで、PyPy と相性の悪い Mypy などを避けて環境を作成し、キャッシュすることができる。
その後、問題を解くワークスペースのルートで oj-prepare またはそのラッパー ./scripts/ojp を実行できる。
Caution
.clang-format と libraries/precompile/.clang-format は clang-format 20 で追加されたオプションを使用している。
使用する clang-format のバージョンは 20 以上にすること。
同じパスに対して上の Installation を再度行えばよい。
problems/ 内のファイルが削除されることはない。
ただし、独自に編集していた設定ファイルがあればそれは上書きされることに注意。
通常ビルドとデバッグビルドは .vscode/bundle.py を通して oj-bundle を実行する。
手動で実行する場合は、ワークスペースのルートで以下のコマンドを使う。
uv run python .vscode/bundle.py problems/example/main.cpp
uv run python .vscode/bundle.py problems/example/main.cpp -o submission.cpp-o を省略すると、入力と同じディレクトリに main.bundle.cpp を生成する。
実際に展開したファイルの URL は、依存先も含めて、出力の先頭にコメントとして一度ずつ記載する。
展開に失敗した場合や出典を確認できない場合は、非ゼロで終了し、既存の出力を上書きしない。
対象は以下の 4 ライブラリに固定し、この順序で -I を渡す。
| 配置先 | URL の基点 |
|---|---|
libraries/ei1333 |
https://github.com/ei1333/library |
libraries/nyaan |
https://github.com/NotLeonian/Nyaan-Library |
libraries/suisen |
https://github.com/NotLeonian/cp-library-cpp |
libraries/niche-library |
https://github.com/NotLeonian/NicheLibrary |
URL は https://github.com/<owner>/<repo>/blob/<コミットSHA>/<ファイルのパス> とする。
oj-bundle と同じ展開処理を使い、各ファイルを読み込む際にパスを記録する。
同名のヘッダがある場合も、実際に読み込んだファイルのパスで区別する。
別のヘッダを読み込むだけのファイルも記録し、URL の添付と内容の照合を行う。
ACL、標準ライブラリ、precompile.hpp の #include は展開せずに残す。
4 ライブラリ以外のローカルヘッダは従来どおり展開するが、URL は自動で付けない。
元リポジトリでは各ライブラリの HEAD と、使用したファイルの内容を照合する。
インストーラは .git をコピーしないため、配布先の libraries/.bundle-sources.json に
各ライブラリのコミット SHA と、コミット中の各ファイルの SHA-256 を保存する。
配布先ではこの記録と照合し、変更されたファイルや、コミットに含まれていないファイルを使った場合はエラーにする。
再インストールで古いファイルが残っていても、現在の記録に含まれていなければ使用できない。
変更したライブラリを使う場合は、公開するコミットに変更を含め、ワークスペースを再インストールする。
AtCoder生成AI対策ルール(20261014版)に対応するため、 コードの作成に生成 AI を利用したかどうかにかかわらず、対象のライブラリには URL を付ける。 使用するコミットは、コンテスト開始前に上記の公開リポジトリで閲覧できるようにしておく。 スクリプトは通常の展開ではネットワークに接続せず、公開された時期は判定しない。
Luzhiled's Library と Nyaan's Library の geometry/ カテゴリ内の一部のファイルなど、そのライブラリのルートディレクトリから見た相対パスが衝突しているファイルがある。
たとえば Nyaan's Library の geometry/circle.hpp を使用したい場合、
#include "geometry/circle.hpp"とすると、このリポジトリのコンパイルオプションでは Luzhiled's Library が優先されてそちらの geometry/circle.hpp が include されてしまう。
このリポジトリの配置であれば、このような場合も絶対パスを使わずに
#include "../nyaan/geometry/circle.hpp"のように相対パスの先頭に ../(ei1333|nyaan|suisen) を追加すればよい。
Python ソースコードのフォーマットと静的検査には以下のコマンドを使用できる。
uv run ruff format . .vscode/bundle.py
uv run ruff check . .vscode/bundle.py
uv run pyright . .vscode/bundle.py
uv run mypy . .vscode/bundle.pyライブラリの展開と出典の照合をテストするには、以下のコマンドを実行する。 テストには Git と g++ が必要で、外部のライブラリをダウンロードする必要はない。
uv run python -m unittest discover -s tests -vonlinejudge_template と onlinejudge_verify は py.typed を提供していないため、テンプレートとライブラリの展開処理が使う API の型を typings/ に定義している。
その API の使い方や依存先のバージョンを変更した場合は、型スタブと依存先の実装が一致していることを確認する。
インストーラは typings/ もワークスペースにコピーする。