Description
Summary
AtCoder Library が内部での include にも #include <...>
を使ってることの影響で、oj-bundle
で AtCoder Library のヘッダを展開しようとしても中途半端な展開で止まってしまう。
Description
次のような C++ のファイルを考える。
#include <cstdio>
#include "atcoder/all"
int main() {
printf("Hello, world!");
return 0;
}
これを現在の master
branch (473ef7c) (v5.2.1 + 修正) の oj-bundle
コマンドで処理すると、以下のように #include "atcoder/all"
が一段階しか展開されない。
$ oj-bundle -I path/to/ac-library foo.cpp > foo.bundled.cpp
INFO:onlinejudge_verify.config:no config file
DEBUG:onlinejudge_verify.languages.cplusplus_bundle:foo.cpp: line 1: #include <cstdio>
DEBUG:onlinejudge_verify.languages.cplusplus_bundle:foo.cpp: line 2: #include "atcoder/all"
g++: warning: /home/user/GitHub/ac-library/atcoder/all: linker input file unused because linking not done
$ cat foo.bundled.cpp
#line 1 "foo.cpp"
#include <cstdio>
#line 1 "/home/user/GitHub/ac-library/atcoder/all"
#include <atcoder/convolution>
#include <atcoder/dsu>
#include <atcoder/fenwicktree>
#include <atcoder/lazysegtree>
#include <atcoder/math>
#include <atcoder/maxflow>
#include <atcoder/mincostflow>
#include <atcoder/modint>
#include <atcoder/scc>
#include <atcoder/segtree>
#include <atcoder/string>
#include <atcoder/twosat>
#line 3 "foo.cpp"
int main() {
printf("Hello, world!");
return 0;
}
これは
仕様としては正しいが、#include <atcoder/convolution>
などが出力結果に残っているのでは「コードを展開してオンラインジャッジに提出可能な状態にする」という機能を果せていない。
Possible implementations and the analysis (optional)
選択肢一覧
oj-bundle
側を修正する- ユーザにオプションを指定してもらう
1.--bundle-atcoder-library
のようなオプションを作る (Feature/#342 #344)
1.--force-bundle
のようなオプションを作って、#include <...>
でも常に展開してほしいファイルを指定できるようにする - デフォルトの挙動を変更する
1.#include "atcoder/..."
の処理中で遭遇した#include <atcoder/...>
は展開するようにする
1. 一般に#include "foo/bar"
の処理中で遭遇した#include <foo/baz>
は展開するようにする
- ユーザにオプションを指定してもらう
- AtCoder Library 側を修正する
#include "..."
を使ってもらう
(1.1.1.) オプションを増やす + AtCoder Library に特殊化する
--bundle-atcoder-library
のようなオプションを作る (#344)
- 利点: 特になし
- 欠点: (1.1.2.) と (1.2.1.) の欠点を合わせ持つ
(1.1.2.) オプションを増やす + AtCoder Library に特殊化しない
--force-bundle
のようなオプションを作って、#include <...>
でも常に展開してほしいファイルを指定できるようにする
- 利点: AtCoder Library 以外にも対応できる。これさえしておけばこれ以降同様の問題は起きない
- 欠点: ユーザが自分でオプションを指定する必要がある。「何も知らないユーザが AtCoder Library を展開しようとしたらうまく動かなくて困る」という問題は解決しない
(1.2.1.) デフォルトの挙動を変更する + AtCoder Library に特殊化する
#include "atcoder/..."
の処理中で遭遇した #include <atcoder/...>
は展開するようにする
- 利点: 何も知らないユーザでも快適に使える
- 欠点: 特になし
(1.2.2.) デフォルトの挙動を変更する + AtCoder Library に特殊化しない
一般に #include "foo/bar"
の処理中で遭遇した #include <foo/baz>
(同じディレクトリ内にあるヘッダ) は展開するようにする
- 利点: 何も知らないユーザでも快適に使える。これさえしておけばこれ以降同様の問題は起きない
- 欠点: 「
#include "foo1"
の中で#include <foo2>
する」と「#include "dir/foo1"
の中で#include <dir/foo2>
する」とで挙動が変化するのは混乱を招く
(2.1.) AtCoder Library 側を修正する
#include "..."
を使ってもらう
- 利点: 技術的に正しいのはこれ
- 欠点: 対応してもらえるかは AtCoder Library 側次第である + 今回対応してもらえたとしても今後同様のライブラリが出現したときに対応してもらえるとは限らない
#include <...>
は "in the standard system directories" なヘッダ (つまり、コンパイラや OS に付属して配布されるようなヘッダ) に対して用いるものである (詳しくは GCC のドキュメントなどを参照: https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html)。
一方で AtCoder Library のヘッダはそのような「システムの標準のディレクトリにあるようなヘッダ」ではない。
インストール方法 (https://atcoder.github.io/ac-library/production/document_ja/appendix.html) を見ても「CPLUS_INCLUDE_PATH
を設定しろ」などとあり、標準のディレクトリにインストールされることは想定されていなさそうである。
あるライブラリ内のヘッダから、同じライブラリ内の別のヘッダを include するときは、#include "..."
を使うのが通常である (例1, 例2, 例3)。
そうしない場合には、複数バージョンを複数の場所にインストールしたときに問題が起こることがある。たとえば /usr/include/atcoder/segtree.hpp
と /home/user/kimiyuki/GitHub/ac-library/atcoder/segtree.hpp
と /home/user/kimiyuki/GitHub/ac-library/atcoder/all
があるとしよう。このときに #include "atcoder/all"
と書いて /home/user/kimiyuki/GitHub/ac-library/atcoder/all
を include したとしても、この atcoder/all
は /home/user/kimiyuki/GitHub/ac-library/atcoder/segtree.hpp
を無視して /usr/include/atcoder/segtree.hpp
を include してしまう。
どれを選ぶか
とりあえずは「(2.1.) AtCoder Library 側を修正する」が可能か @yosupo06 に相談したい。
だめそうなら「(1.2.1.) デフォルトの挙動を変更する + AtCoder Library に特殊化する」を書く。
Other notes
- Will you try to create a pull request?
- yes. 「どのような仕様が適切であるか」などの判断が必要なので、私が積極的にコードを書きます
- cc @kjnh10
- cc @yosupo06
- AtCoder Library の owner として
@yosupo06 とりあえず oj-bundle
側の事情を抜きにして言える一般論「#include <...>
は一般によくない」だけを書いた issue (atcoder/ac-library#71) を atcoder/ac-library に作りました。対応お願いします。なお、一般論だけを主張したのは、AtCoder Library 側では oj-bundle
の都合をあまり気にするべきではないはずだからです